PageSourceSearch

https://www.fromsoftware.jp/jp/static/js/lib/threejs/three/build/three.module.js

js fromsoftware.jp collected 2026-09-24 17:16:05 UTC 1,187,498 bytes, 50,722 lines download raw bytes

1// Polyfills
2
3if ( Number.EPSILON === undefined ) {
4
5	Number.EPSILON = Math.pow( 2, - 52 );
6
7}
8
9if ( Number.isInteger === undefined ) {
10
11	// Missing in IE
12	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
13
14	Number.isInteger = function ( value ) {
15
16		return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;
17
18	};
19
20}
21
22//
23
24if ( Math.sign === undefined ) {
25
26	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
27
28	Math.sign = function ( x ) {
29
30		return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;
31
32	};
33
34}
35
36if ( 'name' in Function.prototype === false ) {
37
38	// Missing in IE
39	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
40
41	Object.defineProperty( Function.prototype, 'name', {
42
43		get: function () {
44
45			return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ];
46
47		}
48
49	} );
50
51}
52
53if ( Object.assign === undefined ) {
54
55	// Missing in IE
56	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
57
58	Object.assign = function ( target ) {
59
60		if ( target === undefined || target === null ) {
61
62			throw new TypeError( 'Cannot convert undefined or null to object' );
63
64		}
65
66		var output = Object( target );
67
68		for ( var index = 1; index < arguments.length; index ++ ) {
69
70			var source = arguments[ index ];
71
72			if ( source !== undefined && source !== null ) {
73
74				for ( var nextKey in source ) {
75
76					if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {
77
78						output[ nextKey ] = source[ nextKey ];
79
80					}
81
82				}
83
84			}
85
86		}
87
88		return output;
89
90	};
91
92}
93
94var REVISION = '116';
95var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
96var TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
97var CullFaceNone = 0;
98var CullFaceBack = 1;
99var CullFaceFront = 2;
100var CullFaceFrontBack = 3;
101var FrontFaceDirectionCW = 0;
102var FrontFaceDirectionCCW = 1;
103var BasicShadowMap = 0;
104var PCFShadowMap = 1;
105var PCFSoftShadowMap = 2;
106var VSMShadowMap = 3;
107var FrontSide = 0;
108var BackSide = 1;
109var DoubleSide = 2;
110var FlatShading = 1;
111var SmoothShading = 2;
112var NoBlending = 0;
113var NormalBlending = 1;
114var AdditiveBlending = 2;
115var SubtractiveBlending = 3;
116var MultiplyBlending = 4;
117var CustomBlending = 5;
118var AddEquation = 100;
119var SubtractEquation = 101;
120var ReverseSubtractEquation = 102;
121var MinEquation = 103;
122var MaxEquation = 104;
123var ZeroFactor = 200;
124var OneFactor = 201;
125var SrcColorFactor = 202;
126var OneMinusSrcColorFactor = 203;
127var SrcAlphaFactor = 204;
128var OneMinusSrcAlphaFactor = 205;
129var DstAlphaFactor = 206;
130var OneMinusDstAlphaFactor = 207;
131var DstColorFactor = 208;
132var OneMinusDstColorFactor = 209;
133var SrcAlphaSaturateFactor = 210;
134var NeverDepth = 0;
135var AlwaysDepth = 1;
136var LessDepth = 2;
137var LessEqualDepth = 3;
138var EqualDepth = 4;
139var GreaterEqualDepth = 5;
140var GreaterDepth = 6;
141var NotEqualDepth = 7;
142var MultiplyOperation = 0;
143var MixOperation = 1;
144var AddOperation = 2;
145var NoToneMapping = 0;
146var LinearToneMapping = 1;
147var ReinhardToneMapping = 2;
148var Uncharted2ToneMapping = 3;
149var CineonToneMapping = 4;
150var ACESFilmicToneMapping = 5;
151
152var UVMapping = 300;
153var CubeReflectionMapping = 301;
154var CubeRefractionMapping = 302;
155var EquirectangularReflectionMapping = 303;
156var EquirectangularRefractionMapping = 304;
157var SphericalReflectionMapping = 305;
158var CubeUVReflectionMapping = 306;
159var CubeUVRefractionMapping = 307;
160var RepeatWrapping = 1000;
161var ClampToEdgeWrapping = 1001;
162var MirroredRepeatWrapping = 1002;
163var NearestFilter = 1003;
164var NearestMipmapNearestFilter = 1004;
165var NearestMipMapNearestFilter = 1004;
166var NearestMipmapLinearFilter = 1005;
167var NearestMipMapLinearFilter = 1005;
168var LinearFilter = 1006;
169var LinearMipmapNearestFilter = 1007;
170var LinearMipMapNearestFilter = 1007;
171var LinearMipmapLinearFilter = 1008;
172var LinearMipMapLinearFilter = 1008;
173var UnsignedByteType = 1009;
174var ByteType = 1010;
175var ShortType = 1011;
176var UnsignedShortType = 1012;
177var IntType = 1013;
178var UnsignedIntType = 1014;
179var FloatType = 1015;
180var HalfFloatType = 1016;
181var UnsignedShort4444Type = 1017;
182var UnsignedShort5551Type = 1018;
183var UnsignedShort565Type = 1019;
184var UnsignedInt248Type = 1020;
185var AlphaFormat = 1021;
186var RGBFormat = 1022;
187var RGBAFormat = 1023;
188var LuminanceFormat = 1024;
189var LuminanceAlphaFormat = 1025;
190var RGBEFormat = RGBAFormat;
191var DepthFormat = 1026;
192var DepthStencilFormat = 1027;
193var RedFormat = 1028;
194var RedIntegerFormat = 1029;
195var RGFormat = 1030;
196var RGIntegerFormat = 1031;
197var RGBIntegerFormat = 1032;
198var RGBAIntegerFormat = 1033;
199
200var RGB_S3TC_DXT1_Format = 33776;
201var RGBA_S3TC_DXT1_Format = 33777;
202var RGBA_S3TC_DXT3_Format = 33778;
203var RGBA_S3TC_DXT5_Format = 33779;
204var RGB_PVRTC_4BPPV1_Format = 35840;
205var RGB_PVRTC_2BPPV1_Format = 35841;
206var RGBA_PVRTC_4BPPV1_Format = 35842;
207var RGBA_PVRTC_2BPPV1_Format = 35843;
208var RGB_ETC1_Format = 36196;
209var RGB_ETC2_Format = 37492;
210var RGBA_ETC2_EAC_Format = 37496;
211var RGBA_ASTC_4x4_Format = 37808;
212var RGBA_ASTC_5x4_Format = 37809;
213var RGBA_ASTC_5x5_Format = 37810;
214var RGBA_ASTC_6x5_Format = 37811;
215var RGBA_ASTC_6x6_Format = 37812;
216var RGBA_ASTC_8x5_Format = 37813;
217var RGBA_ASTC_8x6_Format = 37814;
218var RGBA_ASTC_8x8_Format = 37815;
219var RGBA_ASTC_10x5_Format = 37816;
220var RGBA_ASTC_10x6_Format = 37817;
221var RGBA_ASTC_10x8_Format = 37818;
222var RGBA_ASTC_10x10_Format = 37819;
223var RGBA_ASTC_12x10_Format = 37820;
224var RGBA_ASTC_12x12_Format = 37821;
225var RGBA_BPTC_Format = 36492;
226var SRGB8_ALPHA8_ASTC_4x4_Format = 37840;
227var SRGB8_ALPHA8_ASTC_5x4_Format = 37841;
228var SRGB8_ALPHA8_ASTC_5x5_Format = 37842;
229var SRGB8_ALPHA8_ASTC_6x5_Format = 37843;
230var SRGB8_ALPHA8_ASTC_6x6_Format = 37844;
231var SRGB8_ALPHA8_ASTC_8x5_Format = 37845;
232var SRGB8_ALPHA8_ASTC_8x6_Format = 37846;
233var SRGB8_ALPHA8_ASTC_8x8_Format = 37847;
234var SRGB8_ALPHA8_ASTC_10x5_Format = 37848;
235var SRGB8_ALPHA8_ASTC_10x6_Format = 37849;
236var SRGB8_ALPHA8_ASTC_10x8_Format = 37850;
237var SRGB8_ALPHA8_ASTC_10x10_Format = 37851;
238var SRGB8_ALPHA8_ASTC_12x10_Format = 37852;
239var SRGB8_ALPHA8_ASTC_12x12_Format = 37853;
240var LoopOnce = 2200;
241var LoopRepeat = 2201;
242var LoopPingPong = 2202;
243var InterpolateDiscrete = 2300;
244var InterpolateLinear = 2301;
245var InterpolateSmooth = 2302;
246var ZeroCurvatureEnding = 2400;
247var ZeroSlopeEnding = 2401;
248var WrapAroundEnding = 2402;
249var NormalAnimationBlendMode = 2500;
250var AdditiveAnimationBlendMode = 2501;
251var TrianglesDrawMode = 0;
252var TriangleStripDrawMode = 1;
253var TriangleFanDrawMode = 2;
254var LinearEncoding = 3000;
255var sRGBEncoding = 3001;
256var GammaEncoding = 3007;
257var RGBEEncoding = 3002;
258var LogLuvEncoding = 3003;
259var RGBM7Encoding = 3004;
260var RGBM16Encoding = 3005;
261var RGBDEncoding = 3006;
262var BasicDepthPacking = 3200;
263var RGBADepthPacking = 3201;
264var TangentSpaceNormalMap = 0;
265var ObjectSpaceNormalMap = 1;
266
267var ZeroStencilOp = 0;
268var KeepStencilOp = 7680;
269var ReplaceStencilOp = 7681;
270var IncrementStencilOp = 7682;
271var DecrementStencilOp = 7683;
272var IncrementWrapStencilOp = 34055;
273var DecrementWrapStencilOp = 34056;
274var InvertStencilOp = 5386;
275
276var NeverStencilFunc = 512;
277var LessStencilFunc = 513;
278var EqualStencilFunc = 514;
279var LessEqualStencilFunc = 515;
280var GreaterStencilFunc = 516;
281var NotEqualStencilFunc = 517;
282var GreaterEqualStencilFunc = 518;
283var AlwaysStencilFunc = 519;
284
285var StaticDrawUsage = 35044;
286var DynamicDrawUsage = 35048;
287var StreamDrawUsage = 35040;
288var StaticReadUsage = 35045;
289var DynamicReadUsage = 35049;
290var StreamReadUsage = 35041;
291var StaticCopyUsage = 35046;
292var DynamicCopyUsage = 35050;
293var StreamCopyUsage = 35042;
294
295/**
296 * https://github.com/mrdoob/eventdispatcher.js/
297 */
298
299function EventDispatcher() {}
300
301Object.assign( EventDispatcher.prototype, {
302
303	addEventListener: function ( type, listener ) {
304
305		if ( this._listeners === undefined ) this._listeners = {};
306
307		var listeners = this._listeners;
308
309		if ( listeners[ type ] === undefined ) {
310
311			listeners[ type ] = [];
312
313		}
314
315		if ( listeners[ type ].indexOf( listener ) === - 1 ) {
316
317			listeners[ type ].push( listener );
318
319		}
320
321	},
322
323	hasEventListener: function ( type, listener ) {
324
325		if ( this._listeners === undefined ) return false;
326
327		var listeners = this._listeners;
328
329		return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
330
331	},
332
333	removeEventListener: function ( type, listener ) {
334
335		if ( this._listeners === undefined ) return;
336
337		var listeners = this._listeners;
338		var listenerArray = listeners[ type ];
339
340		if ( listenerArray !== undefined ) {
341
342			var index = listenerArray.indexOf( listener );
343
344			if ( index !== - 1 ) {
345
346				listenerArray.splice( index, 1 );
347
348			}
349
350		}
351
352	},
353
354	dispatchEvent: function ( event ) {
355
356		if ( this._listeners === undefined ) return;
357
358		var listeners = this._listeners;
359		var listenerArray = listeners[ event.type ];
360
361		if ( listenerArray !== undefined ) {
362
363			event.target = this;
364
365			// Make a copy, in case listeners are removed while iterating.
366			var array = listenerArray.slice( 0 );
367
368			for ( var i = 0, l = array.length; i < l; i ++ ) {
369
370				array[ i ].call( this, event );
371
372			}
373
374		}
375
376	}
377
378} );
379
380/**
381 * @author alteredq / http://alteredqualia.com/
382 * @author mrdoob / http://mrdoob.com/
383 * @author WestLangley / http://github.com/WestLangley
384 * @author thezwap
385 */
386
387var _lut = [];
388
389for ( var i = 0; i < 256; i ++ ) {
390
391	_lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
392
393}
394
395var MathUtils = {
396
397	DEG2RAD: Math.PI / 180,
398	RAD2DEG: 180 / Math.PI,
399
400	generateUUID: function () {
401
402		// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
403
404		var d0 = Math.random() * 0xffffffff | 0;
405		var d1 = Math.random() * 0xffffffff | 0;
406		var d2 = Math.random() * 0xffffffff | 0;
407		var d3 = Math.random() * 0xffffffff | 0;
408		var uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
409			_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
410			_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
411			_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
412
413		// .toUpperCase() here flattens concatenated strings to save heap memory space.
414		return uuid.toUpperCase();
415
416	},
417
418	clamp: function ( value, min, max ) {
419
420		return Math.max( min, Math.min( max, value ) );
421
422	},
423
424	// compute euclidian modulo of m % n
425	// https://en.wikipedia.org/wiki/Modulo_operation
426
427	euclideanModulo: function ( n, m ) {
428
429		return ( ( n % m ) + m ) % m;
430
431	},
432
433	// Linear mapping from range <a1, a2> to range <b1, b2>
434
435	mapLinear: function ( x, a1, a2, b1, b2 ) {
436
437		return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
438
439	},
440
441	// https://en.wikipedia.org/wiki/Linear_interpolation
442
443	lerp: function ( x, y, t ) {
444
445		return ( 1 - t ) * x + t * y;
446
447	},
448
449	// http://en.wikipedia.org/wiki/Smoothstep
450
451	smoothstep: function ( x, min, max ) {
452
453		if ( x <= min ) return 0;
454		if ( x >= max ) return 1;
455
456		x = ( x - min ) / ( max - min );
457
458		return x * x * ( 3 - 2 * x );
459
460	},
461
462	smootherstep: function ( x, min, max ) {
463
464		if ( x <= min ) return 0;
465		if ( x >= max ) return 1;
466
467		x = ( x - min ) / ( max - min );
468
469		return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
470
471	},
472
473	// Random integer from <low, high> interval
474
475	randInt: function ( low, high ) {
476
477		return low + Math.floor( Math.random() * ( high - low + 1 ) );
478
479	},
480
481	// Random float from <low, high> interval
482
483	randFloat: function ( low, high ) {
484
485		return low + Math.random() * ( high - low );
486
487	},
488
489	// Random float from <-range/2, range/2> interval
490
491	randFloatSpread: function ( range ) {
492
493		return range * ( 0.5 - Math.random() );
494
495	},
496
497	degToRad: function ( degrees ) {
498
499		return degrees * MathUtils.DEG2RAD;
500
501	},
502
503	radToDeg: function ( radians ) {
504
505		return radians * MathUtils.RAD2DEG;
506
507	},
508
509	isPowerOfTwo: function ( value ) {
510
511		return ( value & ( value - 1 ) ) === 0 && value !== 0;
512
513	},
514
515	ceilPowerOfTwo: function ( value ) {
516
517		return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
518
519	},
520
521	floorPowerOfTwo: function ( value ) {
522
523		return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
524
525	},
526
527	setQuaternionFromProperEuler: function ( q, a, b, c, order ) {
528
529		// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
530
531		// rotations are applied to the axes in the order specified by 'order'
532		// rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
533		// angles are in radians
534
535		var cos = Math.cos;
536		var sin = Math.sin;
537
538		var c2 = cos( b / 2 );
539		var s2 = sin( b / 2 );
540
541		var c13 = cos( ( a + c ) / 2 );
542		var s13 = sin( ( a + c ) / 2 );
543
544		var c1_3 = cos( ( a - c ) / 2 );
545		var s1_3 = sin( ( a - c ) / 2 );
546
547		var c3_1 = cos( ( c - a ) / 2 );
548		var s3_1 = sin( ( c - a ) / 2 );
549
550		switch ( order ) {
551
552			case 'XYX':
553				q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
554				break;
555
556			case 'YZY':
557				q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
558				break;
559
560			case 'ZXZ':
561				q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
562				break;
563
564			case 'XZX':
565				q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
566				break;
567
568			case 'YXY':
569				q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
570				break;
571
572			case 'ZYZ':
573				q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
574				break;
575
576			default:
577				console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
578
579		}
580
581	}
582
583};
584
585/**
586 * @author mrdoob / http://mrdoob.com/
587 * @author philogb / http://blog.thejit.org/
588 * @author egraether / http://egraether.com/
589 * @author zz85 / http://www.lab4games.net/zz85/blog
590 */
591
592function Vector2( x, y ) {
593
594	this.x = x || 0;
595	this.y = y || 0;
596
597}
598
599Object.defineProperties( Vector2.prototype, {
600
601	"width": {
602
603		get: function () {
604
605			return this.x;
606
607		},
608
609		set: function ( value ) {
610
611			this.x = value;
612
613		}
614
615	},
616
617	"height": {
618
619		get: function () {
620
621			return this.y;
622
623		},
624
625		set: function ( value ) {
626
627			this.y = value;
628
629		}
630
631	}
632
633} );
634
635Object.assign( Vector2.prototype, {
636
637	isVector2: true,
638
639	set: function ( x, y ) {
640
641		this.x = x;
642		this.y = y;
643
644		return this;
645
646	},
647
648	setScalar: function ( scalar ) {
649
650		this.x = scalar;
651		this.y = scalar;
652
653		return this;
654
655	},
656
657	setX: function ( x ) {
658
659		this.x = x;
660
661		return this;
662
663	},
664
665	setY: function ( y ) {
666
667		this.y = y;
668
669		return this;
670
671	},
672
673	setComponent: function ( index, value ) {
674
675		switch ( index ) {
676
677			case 0: this.x = value; break;
678			case 1: this.y = value; break;
679			default: throw new Error( 'index is out of range: ' + index );
680
681		}
682
683		return this;
684
685	},
686
687	getComponent: function ( index ) {
688
689		switch ( index ) {
690
691			case 0: return this.x;
692			case 1: return this.y;
693			default: throw new Error( 'index is out of range: ' + index );
694
695		}
696
697	},
698
699	clone: function () {
700
701		return new this.constructor( this.x, this.y );
702
703	},
704
705	copy: function ( v ) {
706
707		this.x = v.x;
708		this.y = v.y;
709
710		return this;
711
712	},
713
714	add: function ( v, w ) {
715
716		if ( w !== undefined ) {
717
718			console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
719			return this.addVectors( v, w );
720
721		}
722
723		this.x += v.x;
724		this.y += v.y;
725
726		return this;
727
728	},
729
730	addScalar: function ( s ) {
731
732		this.x += s;
733		this.y += s;
734
735		return this;
736
737	},
738
739	addVectors: function ( a, b ) {
740
741		this.x = a.x + b.x;
742		this.y = a.y + b.y;
743
744		return this;
745
746	},
747
748	addScaledVector: function ( v, s ) {
749
750		this.x += v.x * s;
751		this.y += v.y * s;
752
753		return this;
754
755	},
756
757	sub: function ( v, w ) {
758
759		if ( w !== undefined ) {
760
761			console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
762			return this.subVectors( v, w );
763
764		}
765
766		this.x -= v.x;
767		this.y -= v.y;
768
769		return this;
770
771	},
772
773	subScalar: function ( s ) {
774
775		this.x -= s;
776		this.y -= s;
777
778		return this;
779
780	},
781
782	subVectors: function ( a, b ) {
783
784		this.x = a.x - b.x;
785		this.y = a.y - b.y;
786
787		return this;
788
789	},
790
791	multiply: function ( v ) {
792
793		this.x *= v.x;
794		this.y *= v.y;
795
796		return this;
797
798	},
799
800	multiplyScalar: function ( scalar ) {
801
802		this.x *= scalar;
803		this.y *= scalar;
804
805		return this;
806
807	},
808
809	divide: function ( v ) {
810
811		this.x /= v.x;
812		this.y /= v.y;
813
814		return this;
815
816	},
817
818	divideScalar: function ( scalar ) {
819
820		return this.multiplyScalar( 1 / scalar );
821
822	},
823
824	applyMatrix3: function ( m ) {
825
826		var x = this.x, y = this.y;
827		var e = m.elements;
828
829		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
830		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
831
832		return this;
833
834	},
835
836	min: function ( v ) {
837
838		this.x = Math.min( this.x, v.x );
839		this.y = Math.min( this.y, v.y );
840
841		return this;
842
843	},
844
845	max: function ( v ) {
846
847		this.x = Math.max( this.x, v.x );
848		this.y = Math.max( this.y, v.y );
849
850		return this;
851
852	},
853
854	clamp: function ( min, max ) {
855
856		// assumes min < max, componentwise
857
858		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
859		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
860
861		return this;
862
863	},
864
865	clampScalar: function ( minVal, maxVal ) {
866
867		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
868		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
869
870		return this;
871
872	},
873
874	clampLength: function ( min, max ) {
875
876		var length = this.length();
877
878		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
879
880	},
881
882	floor: function () {
883
884		this.x = Math.floor( this.x );
885		this.y = Math.floor( this.y );
886
887		return this;
888
889	},
890
891	ceil: function () {
892
893		this.x = Math.ceil( this.x );
894		this.y = Math.ceil( this.y );
895
896		return this;
897
898	},
899
900	round: function () {
901
902		this.x = Math.round( this.x );
903		this.y = Math.round( this.y );
904
905		return this;
906
907	},
908
909	roundToZero: function () {
910
911		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
912		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
913
914		return this;
915
916	},
917
918	negate: function () {
919
920		this.x = - this.x;
921		this.y = - this.y;
922
923		return this;
924
925	},
926
927	dot: function ( v ) {
928
929		return this.x * v.x + this.y * v.y;
930
931	},
932
933	cross: function ( v ) {
934
935		return this.x * v.y - this.y * v.x;
936
937	},
938
939	lengthSq: function () {
940
941		return this.x * this.x + this.y * this.y;
942
943	},
944
945	length: function () {
946
947		return Math.sqrt( this.x * this.x + this.y * this.y );
948
949	},
950
951	manhattanLength: function () {
952
953		return Math.abs( this.x ) + Math.abs( this.y );
954
955	},
956
957	normalize: function () {
958
959		return this.divideScalar( this.length() || 1 );
960
961	},
962
963	angle: function () {
964
965		// computes the angle in radians with respect to the positive x-axis
966
967		var angle = Math.atan2( - this.y, - this.x ) + Math.PI;
968
969		return angle;
970
971	},
972
973	distanceTo: function ( v ) {
974
975		return Math.sqrt( this.distanceToSquared( v ) );
976
977	},
978
979	distanceToSquared: function ( v ) {
980
981		var dx = this.x - v.x, dy = this.y - v.y;
982		return dx * dx + dy * dy;
983
984	},
985
986	manhattanDistanceTo: function ( v ) {
987
988		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
989
990	},
991
992	setLength: function ( length ) {
993
994		return this.normalize().multiplyScalar( length );
995
996	},
997
998	lerp: function ( v, alpha ) {
999
1000		this.x += ( v.x - this.x ) * alpha;
1001		this.y += ( v.y - this.y ) * alpha;
1002
1003		return this;
1004
1005	},
1006
1007	lerpVectors: function ( v1, v2, alpha ) {
1008
1009		return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
1010
1011	},
1012
1013	equals: function ( v ) {
1014
1015		return ( ( v.x === this.x ) && ( v.y === this.y ) );
1016
1017	},
1018
1019	fromArray: function ( array, offset ) {
1020
1021		if ( offset === undefined ) offset = 0;
1022
1023		this.x = array[ offset ];
1024		this.y = array[ offset + 1 ];
1025
1026		return this;
1027
1028	},
1029
1030	toArray: function ( array, offset ) {
1031
1032		if ( array === undefined ) array = [];
1033		if ( offset === undefined ) offset = 0;
1034
1035		array[ offset ] = this.x;
1036		array[ offset + 1 ] = this.y;
1037
1038		return array;
1039
1040	},
1041
1042	fromBufferAttribute: function ( attribute, index, offset ) {
1043
1044		if ( offset !== undefined ) {
1045
1046			console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );
1047
1048		}
1049
1050		this.x = attribute.getX( index );
1051		this.y = attribute.getY( index );
1052
1053		return this;
1054
1055	},
1056
1057	rotateAround: function ( center, angle ) {
1058
1059		var c = Math.cos( angle ), s = Math.sin( angle );
1060
1061		var x = this.x - center.x;
1062		var y = this.y - center.y;
1063
1064		this.x = x * c - y * s + center.x;
1065		this.y = x * s + y * c + center.y;
1066
1067		return this;
1068
1069	},
1070
1071	random: function () {
1072
1073		this.x = Math.random();
1074		this.y = Math.random();
1075
1076		return this;
1077
1078	}
1079
1080} );
1081
1082/**
1083 * @author alteredq / http://alteredqualia.com/
1084 * @author WestLangley / http://github.com/WestLangley
1085 * @author bhouston / http://clara.io
1086 * @author tschw
1087 */
1088
1089function Matrix3() {
1090
1091	this.elements = [
1092
1093		1, 0, 0,
1094		0, 1, 0,
1095		0, 0, 1
1096
1097	];
1098
1099	if ( arguments.length > 0 ) {
1100
1101		console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
1102
1103	}
1104
1105}
1106
1107Object.assign( Matrix3.prototype, {
1108
1109	isMatrix3: true,
1110
1111	set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1112
1113		var te = this.elements;
1114
1115		te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
1116		te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
1117		te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
1118
1119		return this;
1120
1121	},
1122
1123	identity: function () {
1124
1125		this.set(
1126
1127			1, 0, 0,
1128			0, 1, 0,
1129			0, 0, 1
1130
1131		);
1132
1133		return this;
1134
1135	},
1136
1137	clone: function () {
1138
1139		return new this.constructor().fromArray( this.elements );
1140
1141	},
1142
1143	copy: function ( m ) {
1144
1145		var te = this.elements;
1146		var me = m.elements;
1147
1148		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
1149		te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
1150		te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
1151
1152		return this;
1153
1154	},
1155
1156	extractBasis: function ( xAxis, yAxis, zAxis ) {
1157
1158		xAxis.setFromMatrix3Column( this, 0 );
1159		yAxis.setFromMatrix3Column( this, 1 );
1160		zAxis.setFromMatrix3Column( this, 2 );
1161
1162		return this;
1163
1164	},
1165
1166	setFromMatrix4: function ( m ) {
1167
1168		var me = m.elements;
1169
1170		this.set(
1171
1172			me[ 0 ], me[ 4 ], me[ 8 ],
1173			me[ 1 ], me[ 5 ], me[ 9 ],
1174			me[ 2 ], me[ 6 ], me[ 10 ]
1175
1176		);
1177
1178		return this;
1179
1180	},
1181
1182	multiply: function ( m ) {
1183
1184		return this.multiplyMatrices( this, m );
1185
1186	},
1187
1188	premultiply: function ( m ) {
1189
1190		return this.multiplyMatrices( m, this );
1191
1192	},
1193
1194	multiplyMatrices: function ( a, b ) {
1195
1196		var ae = a.elements;
1197		var be = b.elements;
1198		var te = this.elements;
1199
1200		var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
1201		var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
1202		var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
1203
1204		var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
1205		var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
1206		var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
1207
1208		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
1209		te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
1210		te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
1211
1212		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
1213		te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
1214		te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
1215
1216		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
1217		te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
1218		te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
1219
1220		return this;
1221
1222	},
1223
1224	multiplyScalar: function ( s ) {
1225
1226		var te = this.elements;
1227
1228		te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
1229		te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
1230		te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
1231
1232		return this;
1233
1234	},
1235
1236	determinant: function () {
1237
1238		var te = this.elements;
1239
1240		var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
1241			d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
1242			g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
1243
1244		return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
1245
1246	},
1247
1248	getInverse: function ( matrix, throwOnDegenerate ) {
1249
1250		if ( throwOnDegenerate !== undefined ) {
1251
1252			console.warn( "THREE.Matrix3: .getInverse() can no longer be configured to throw on degenerate." );
1253
1254		}
1255
1256		var me = matrix.elements,
1257			te = this.elements,
1258
1259			n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
1260			n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
1261			n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
1262
1263			t11 = n33 * n22 - n32 * n23,
1264			t12 = n32 * n13 - n33 * n12,
1265			t13 = n23 * n12 - n22 * n13,
1266
1267			det = n11 * t11 + n21 * t12 + n31 * t13;
1268
1269		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1270
1271		var detInv = 1 / det;
1272
1273		te[ 0 ] = t11 * detInv;
1274		te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
1275		te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
1276
1277		te[ 3 ] = t12 * detInv;
1278		te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
1279		te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
1280
1281		te[ 6 ] = t13 * detInv;
1282		te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
1283		te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
1284
1285		return this;
1286
1287	},
1288
1289	transpose: function () {
1290
1291		var tmp, m = this.elements;
1292
1293		tmp = m[ 1 ]; m[ 1 ] = m[ 3 ];
vendor: 8,738 bytes, lines 1293-1734
1293 m[ 3 ] = tmp;
1294		tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
1295		tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
1296
1297		return this;
1298
1299	},
1300
1301	getNormalMatrix: function ( matrix4 ) {
1302
1303		return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
1304
1305	},
1306
1307	transposeIntoArray: function ( r ) {
1308
1309		var m = this.elements;
1310
1311		r[ 0 ] = m[ 0 ];
1312		r[ 1 ] = m[ 3 ];
1313		r[ 2 ] = m[ 6 ];
1314		r[ 3 ] = m[ 1 ];
1315		r[ 4 ] = m[ 4 ];
1316		r[ 5 ] = m[ 7 ];
1317		r[ 6 ] = m[ 2 ];
1318		r[ 7 ] = m[ 5 ];
1319		r[ 8 ] = m[ 8 ];
1320
1321		return this;
1322
1323	},
1324
1325	setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {
1326
1327		var c = Math.cos( rotation );
1328		var s = Math.sin( rotation );
1329
1330		this.set(
1331			sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
1332			- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
1333			0, 0, 1
1334		);
1335
1336	},
1337
1338	scale: function ( sx, sy ) {
1339
1340		var te = this.elements;
1341
1342		te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;
1343		te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;
1344
1345		return this;
1346
1347	},
1348
1349	rotate: function ( theta ) {
1350
1351		var c = Math.cos( theta );
1352		var s = Math.sin( theta );
1353
1354		var te = this.elements;
1355
1356		var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];
1357		var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];
1358
1359		te[ 0 ] = c * a11 + s * a21;
1360		te[ 3 ] = c * a12 + s * a22;
1361		te[ 6 ] = c * a13 + s * a23;
1362
1363		te[ 1 ] = - s * a11 + c * a21;
1364		te[ 4 ] = - s * a12 + c * a22;
1365		te[ 7 ] = - s * a13 + c * a23;
1366
1367		return this;
1368
1369	},
1370
1371	translate: function ( tx, ty ) {
1372
1373		var te = this.elements;
1374
1375		te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];
1376		te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];
1377
1378		return this;
1379
1380	},
1381
1382	equals: function ( matrix ) {
1383
1384		var te = this.elements;
1385		var me = matrix.elements;
1386
1387		for ( var i = 0; i < 9; i ++ ) {
1388
1389			if ( te[ i ] !== me[ i ] ) return false;
1390
1391		}
1392
1393		return true;
1394
1395	},
1396
1397	fromArray: function ( array, offset ) {
1398
1399		if ( offset === undefined ) offset = 0;
1400
1401		for ( var i = 0; i < 9; i ++ ) {
1402
1403			this.elements[ i ] = array[ i + offset ];
1404
1405		}
1406
1407		return this;
1408
1409	},
1410
1411	toArray: function ( array, offset ) {
1412
1413		if ( array === undefined ) array = [];
1414		if ( offset === undefined ) offset = 0;
1415
1416		var te = this.elements;
1417
1418		array[ offset ] = te[ 0 ];
1419		array[ offset + 1 ] = te[ 1 ];
1420		array[ offset + 2 ] = te[ 2 ];
1421
1422		array[ offset + 3 ] = te[ 3 ];
1423		array[ offset + 4 ] = te[ 4 ];
1424		array[ offset + 5 ] = te[ 5 ];
1425
1426		array[ offset + 6 ] = te[ 6 ];
1427		array[ offset + 7 ] = te[ 7 ];
1428		array[ offset + 8 ] = te[ 8 ];
1429
1430		return array;
1431
1432	}
1433
1434} );
1435
1436/**
1437 * @author mrdoob / http://mrdoob.com/
1438 * @author alteredq / http://alteredqualia.com/
1439 * @author szimek / https://github.com/szimek/
1440 */
1441
1442var _canvas;
1443
1444var ImageUtils = {
1445
1446	getDataURL: function ( image ) {
1447
1448		var canvas;
1449
1450		if ( typeof HTMLCanvasElement == 'undefined' ) {
1451
1452			return image.src;
1453
1454		} else if ( image instanceof HTMLCanvasElement ) {
1455
1456			canvas = image;
1457
1458		} else {
1459
1460			if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
1461
1462			_canvas.width = image.width;
1463			_canvas.height = image.height;
1464
1465			var context = _canvas.getContext( '2d' );
1466
1467			if ( image instanceof ImageData ) {
1468
1469				context.putImageData( image, 0, 0 );
1470
1471			} else {
1472
1473				context.drawImage( image, 0, 0, image.width, image.height );
1474
1475			}
1476
1477			canvas = _canvas;
1478
1479		}
1480
1481		if ( canvas.width > 2048 || canvas.height > 2048 ) {
1482
1483			return canvas.toDataURL( 'image/jpeg', 0.6 );
1484
1485		} else {
1486
1487			return canvas.toDataURL( 'image/png' );
1488
1489		}
1490
1491	}
1492
1493};
1494
1495/**
1496 * @author mrdoob / http://mrdoob.com/
1497 * @author alteredq / http://alteredqualia.com/
1498 * @author szimek / https://github.com/szimek/
1499 */
1500
1501var textureId = 0;
1502
1503function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
1504
1505	Object.defineProperty( this, 'id', { value: textureId ++ } );
1506
1507	this.uuid = MathUtils.generateUUID();
1508
1509	this.name = '';
1510
1511	this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;
1512	this.mipmaps = [];
1513
1514	this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;
1515
1516	this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;
1517	this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;
1518
1519	this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
1520	this.minFilter = minFilter !== undefined ? minFilter : LinearMipmapLinearFilter;
1521
1522	this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
1523
1524	this.format = format !== undefined ? format : RGBAFormat;
1525	this.internalFormat = null;
1526	this.type = type !== undefined ? type : UnsignedByteType;
1527
1528	this.offset = new Vector2( 0, 0 );
1529	this.repeat = new Vector2( 1, 1 );
1530	this.center = new Vector2( 0, 0 );
1531	this.rotation = 0;
1532
1533	this.matrixAutoUpdate = true;
1534	this.matrix = new Matrix3();
1535
1536	this.generateMipmaps = true;
1537	this.premultiplyAlpha = false;
1538	this.flipY = true;
1539	this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
1540
1541	// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
1542	//
1543	// Also changing the encoding after already used by a Material will not automatically make the Material
1544	// update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
1545	this.encoding = encoding !== undefined ? encoding : LinearEncoding;
1546
1547	this.version = 0;
1548	this.onUpdate = null;
1549
1550}
1551
1552Texture.DEFAULT_IMAGE = undefined;
1553Texture.DEFAULT_MAPPING = UVMapping;
1554
1555Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
1556
1557	constructor: Texture,
1558
1559	isTexture: true,
1560
1561	updateMatrix: function () {
1562
1563		this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
1564
1565	},
1566
1567	clone: function () {
1568
1569		return new this.constructor().copy( this );
1570
1571	},
1572
1573	copy: function ( source ) {
1574
1575		this.name = source.name;
1576
1577		this.image = source.image;
1578		this.mipmaps = source.mipmaps.slice( 0 );
1579
1580		this.mapping = source.mapping;
1581
1582		this.wrapS = source.wrapS;
1583		this.wrapT = source.wrapT;
1584
1585		this.magFilter = source.magFilter;
1586		this.minFilter = source.minFilter;
1587
1588		this.anisotropy = source.anisotropy;
1589
1590		this.format = source.format;
1591		this.internalFormat = source.internalFormat;
1592		this.type = source.type;
1593
1594		this.offset.copy( source.offset );
1595		this.repeat.copy( source.repeat );
1596		this.center.copy( source.center );
1597		this.rotation = source.rotation;
1598
1599		this.matrixAutoUpdate = source.matrixAutoUpdate;
1600		this.matrix.copy( source.matrix );
1601
1602		this.generateMipmaps = source.generateMipmaps;
1603		this.premultiplyAlpha = source.premultiplyAlpha;
1604		this.flipY = source.flipY;
1605		this.unpackAlignment = source.unpackAlignment;
1606		this.encoding = source.encoding;
1607
1608		return this;
1609
1610	},
1611
1612	toJSON: function ( meta ) {
1613
1614		var isRootObject = ( meta === undefined || typeof meta === 'string' );
1615
1616		if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
1617
1618			return meta.textures[ this.uuid ];
1619
1620		}
1621
1622		var output = {
1623
1624			metadata: {
1625				version: 4.5,
1626				type: 'Texture',
1627				generator: 'Texture.toJSON'
1628			},
1629
1630			uuid: this.uuid,
1631			name: this.name,
1632
1633			mapping: this.mapping,
1634
1635			repeat: [ this.repeat.x, this.repeat.y ],
1636			offset: [ this.offset.x, this.offset.y ],
1637			center: [ this.center.x, this.center.y ],
1638			rotation: this.rotation,
1639
1640			wrap: [ this.wrapS, this.wrapT ],
1641
1642			format: this.format,
1643			type: this.type,
1644			encoding: this.encoding,
1645
1646			minFilter: this.minFilter,
1647			magFilter: this.magFilter,
1648			anisotropy: this.anisotropy,
1649
1650			flipY: this.flipY,
1651
1652			premultiplyAlpha: this.premultiplyAlpha,
1653			unpackAlignment: this.unpackAlignment
1654
1655		};
1656
1657		if ( this.image !== undefined ) {
1658
1659			// TODO: Move to THREE.Image
1660
1661			var image = this.image;
1662
1663			if ( image.uuid === undefined ) {
1664
1665				image.uuid = MathUtils.generateUUID(); // UGH
1666
1667			}
1668
1669			if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {
1670
1671				var url;
1672
1673				if ( Array.isArray( image ) ) {
1674
1675					// process array of images e.g. CubeTexture
1676
1677					url = [];
1678
1679					for ( var i = 0, l = image.length; i < l; i ++ ) {
1680
1681						url.push( ImageUtils.getDataURL( image[ i ] ) );
1682
1683					}
1684
1685				} else {
1686
1687					// process single image
1688
1689					url = ImageUtils.getDataURL( image );
1690
1691				}
1692
1693				meta.images[ image.uuid ] = {
1694					uuid: image.uuid,
1695					url: url
1696				};
1697
1698			}
1699
1700			output.image = image.uuid;
1701
1702		}
1703
1704		if ( ! isRootObject ) {
1705
1706			meta.textures[ this.uuid ] = output;
1707
1708		}
1709
1710		return output;
1711
1712	},
1713
1714	dispose: function () {
1715
1716		this.dispatchEvent( { type: 'dispose' } );
1717
1718	},
1719
1720	transformUv: function ( uv ) {
1721
1722		if ( this.mapping !== UVMapping ) return uv;
1723
1724		uv.applyMatrix3( this.matrix );
1725
1726		if ( uv.x < 0 || uv.x > 1 ) {
1727
1728			switch ( this.wrapS ) {
1729
1730				case RepeatWrapping:
1731
1732					uv.x = uv.x - Math.floor( uv.x );
1733					break;
1734
1735				case ClampToEdgeWrapping:
1736
1737					uv.x = uv.x < 0 ? 0 : 1;
1738					break;
1739
1740				case MirroredRepeatWrapping:
1741
1742					if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
1743
1744						uv.x = Math.ceil( uv.x ) - uv.x;
1745
1746					} else {
1747
1748						uv.x = uv.x - Math.floor( uv.x );
1749
1750					}
1751
1752					break;
1753
1754			}
1755
1756		}
1757
1758		if ( uv.y < 0 || uv.y > 1 ) {
1759
1760			switch ( this.wrapT ) {
1761
1762				case RepeatWrapping:
1763
1764					uv.y = uv.y - Math.floor( uv.y );
1765					break;
1766
1767				case ClampToEdgeWrapping:
1768
1769					uv.y = uv.y < 0 ? 0 : 1;
1770					break;
1771
1772				case MirroredRepeatWrapping:
1773
1774					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
1775
1776						uv.y = Math.ceil( uv.y ) - uv.y;
1777
1778					} else {
1779
1780						uv.y = uv.y - Math.floor( uv.y );
1781
1782					}
1783
1784					break;
1785
1786			}
1787
1788		}
1789
1790		if ( this.flipY ) {
1791
1792			uv.y = 1 - uv.y;
1793
1794		}
1795
1796		return uv;
1797
1798	}
1799
1800} );
1801
1802Object.defineProperty( Texture.prototype, "needsUpdate", {
1803
1804	set: function ( value ) {
1805
1806		if ( value === true ) this.version ++;
1807
1808	}
1809
1810} );
1811
1812/**
1813 * @author supereggbert / http://www.paulbrunt.co.uk/
1814 * @author philogb / http://blog.thejit.org/
1815 * @author mikael emtinger / http://gomo.se/
1816 * @author egraether / http://egraether.com/
1817 * @author WestLangley / http://github.com/WestLangley
1818 */
1819
1820function Vector4( x, y, z, w ) {
1821
1822	this.x = x || 0;
1823	this.y = y || 0;
1824	this.z = z || 0;
1825	this.w = ( w !== undefined ) ? w : 1;
1826
1827}
1828
1829Object.defineProperties( Vector4.prototype, {
1830
1831	"width": {
1832
1833		get: function () {
1834
1835			return this.z;
1836
1837		},
1838
1839		set: function ( value ) {
1840
1841			this.z = value;
1842
1843		}
1844
1845	},
1846
1847	"height": {
1848
1849		get: function () {
1850
1851			return this.w;
1852
1853		},
1854
1855		set: function ( value ) {
1856
1857			this.w = value;
1858
1859		}
1860
1861	}
1862
1863} );
1864
1865Object.assign( Vector4.prototype, {
1866
1867	isVector4: true,
1868
1869	set: function ( x, y, z, w ) {
1870
1871		this.x = x;
1872		this.y = y;
1873		this.z = z;
1874		this.w = w;
1875
1876		return this;
1877
1878	},
1879
1880	setScalar: function ( scalar ) {
1881
1882		this.x = scalar;
1883		this.y = scalar;
1884		this.z = scalar;
1885		this.w = scalar;
1886
1887		return this;
1888
1889	},
1890
1891	setX: function ( x ) {
1892
1893		this.x = x;
1894
1895		return this;
1896
1897	},
1898
1899	setY: function ( y ) {
1900
1901		this.y = y;
1902
1903		return this;
1904
1905	},
1906
1907	setZ: function ( z ) {
1908
1909		this.z = z;
1910
1911		return this;
1912
1913	},
1914
1915	setW: function ( w ) {
1916
1917		this.w = w;
1918
1919		return this;
1920
1921	},
1922
1923	setComponent: function ( index, value ) {
1924
1925		switch ( index ) {
1926
1927			case 0: this.x = value; break;
1928			case 1: this.y = value; break;
1929			case 2: this.z = value; break;
1930			case 3: this.w = value; break;
1931			default: throw new Error( 'index is out of range: ' + index );
1932
1933		}
1934
1935		return this;
1936
1937	},
1938
1939	getComponent: function ( index ) {
1940
1941		switch ( index ) {
1942
1943			case 0: return this.x;
1944			case 1: return this.y;
1945			case 2: return this.z;
1946			case 3: return this.w;
1947			default: throw new Error( 'index is out of range: ' + index );
1948
1949		}
1950
1951	},
1952
1953	clone: function () {
1954
1955		return new this.constructor( this.x, this.y, this.z, this.w );
1956
1957	},
1958
1959	copy: function ( v ) {
1960
1961		this.x = v.x;
1962		this.y = v.y;
1963		this.z = v.z;
1964		this.w = ( v.w !== undefined ) ? v.w : 1;
1965
1966		return this;
1967
1968	},
1969
1970	add: function ( v, w ) {
1971
1972		if ( w !== undefined ) {
1973
1974			console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
1975			return this.addVectors( v, w );
1976
1977		}
1978
1979		this.x += v.x;
1980		this.y += v.y;
1981		this.z += v.z;
1982		this.w += v.w;
1983
1984		return this;
1985
1986	},
1987
1988	addScalar: function ( s ) {
1989
1990		this.x += s;
1991		this.y += s;
1992		this.z += s;
1993		this.w += s;
1994
1995		return this;
1996
1997	},
1998
1999	addVectors: function ( a, b ) {
2000
2001		this.x = a.x + b.x;
2002		this.y = a.y + b.y;
2003		this.z = a.z + b.z;
2004		this.w = a.w + b.w;
2005
2006		return this;
2007
2008	},
2009
2010	addScaledVector: function ( v, s ) {
2011
2012		this.x += v.x * s;
2013		this.y += v.y * s;
2014		this.z += v.z * s;
2015		this.w += v.w * s;
2016
2017		return this;
2018
2019	},
2020
2021	sub: function ( v, w ) {
2022
2023		if ( w !== undefined ) {
2024
2025			console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
2026			return this.subVectors( v, w );
2027
2028		}
2029
2030		this.x -= v.x;
2031		this.y -= v.y;
2032		this.z -= v.z;
2033		this.w -= v.w;
2034
2035		return this;
2036
2037	},
2038
2039	subScalar: function ( s ) {
2040
2041		this.x -= s;
2042		this.y -= s;
2043		this.z -= s;
2044		this.w -= s;
2045
2046		return this;
2047
2048	},
2049
2050	subVectors: function ( a, b ) {
2051
2052		this.x = a.x - b.x;
2053		this.y = a.y - b.y;
2054		this.z = a.z - b.z;
2055		this.w = a.w - b.w;
2056
2057		return this;
2058
2059	},
2060
2061	multiplyScalar: function ( scalar ) {
2062
2063		this.x *= scalar;
2064		this.y *= scalar;
2065		this.z *= scalar;
2066		this.w *= scalar;
2067
2068		return this;
2069
2070	},
2071
2072	applyMatrix4: function ( m ) {
2073
2074		var x = this.x, y = this.y, z = this.z, w = this.w;
2075		var e = m.elements;
2076
2077		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
2078		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
2079		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
2080		this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
2081
2082		return this;
2083
2084	},
2085
2086	divideScalar: function ( scalar ) {
2087
2088		return this.multiplyScalar( 1 / scalar );
2089
2090	},
2091
2092	setAxisAngleFromQuaternion: function ( q ) {
2093
2094		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
2095
2096		// q is assumed to be normalized
2097
2098		this.w = 2 * Math.acos( q.w );
2099
2100		var s = Math.sqrt( 1 - q.w * q.w );
2101
2102		if ( s < 0.0001 ) {
2103
2104			this.x = 1;
2105			this.y = 0;
2106			this.z = 0;
2107
2108		} else {
2109
2110			this.x = q.x / s;
2111			this.y = q.y / s;
2112			this.z = q.z / s;
2113
2114		}
2115
2116		return this;
2117
2118	},
2119
2120	setAxisAngleFromRotationMatrix: function ( m ) {
2121
2122		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2123
2124		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2125
2126		var angle, x, y, z,		// variables for result
2127			epsilon = 0.01,		// margin to allow for rounding errors
2128			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
2129
2130			te = m.elements,
2131
2132			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2133			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2134			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
2135
2136		if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
2137		     ( Math.abs( m13 - m31 ) < epsilon ) &&
2138		     ( Math.abs( m23 - m32 ) < epsilon ) ) {
2139
2140			// singularity found
2141			// first check for identity matrix which must have +1 for all terms
2142			// in leading diagonal and zero in other terms
2143
2144			if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
2145			     ( Math.abs( m13 + m31 ) < epsilon2 ) &&
2146			     ( Math.abs( m23 + m32 ) < epsilon2 ) &&
2147			     ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
2148
2149				// this singularity is identity matrix so angle = 0
2150
2151				this.set( 1, 0, 0, 0 );
2152
2153				return this; // zero angle, arbitrary axis
2154
2155			}
2156
2157			// otherwise this singularity is angle = 180
2158
2159			angle = Math.PI;
2160
2161			var xx = ( m11 + 1 ) / 2;
2162			var yy = ( m22 + 1 ) / 2;
2163			var zz = ( m33 + 1 ) / 2;
2164			var xy = ( m12 + m21 ) / 4;
2165			var xz = ( m13 + m31 ) / 4;
2166			var yz = ( m23 + m32 ) / 4;
2167
2168			if ( ( xx > yy ) && ( xx > zz ) ) {
2169
2170				// m11 is the largest diagonal term
2171
2172				if ( xx < epsilon ) {
2173
2174					x = 0;
2175					y = 0.707106781;
2176					z = 0.707106781;
2177
2178				} else {
2179
2180					x = Math.sqrt( xx );
2181					y = xy / x;
2182					z = xz / x;
2183
2184				}
2185
2186			} else if ( yy > zz ) {
2187
2188				// m22 is the largest diagonal term
2189
2190				if ( yy < epsilon ) {
2191
2192					x = 0.707106781;
2193					y = 0;
2194					z = 0.707106781;
2195
2196				} else {
2197
2198					y = Math.sqrt( yy );
2199					x = xy / y;
2200					z = yz / y;
2201
2202				}
2203
2204			} else {
2205
2206				// m33 is the largest diagonal term so base result on this
2207
2208				if ( zz < epsilon ) {
2209
2210					x = 0.707106781;
2211					y = 0.707106781;
2212					z = 0;
2213
2214				} else {
2215
2216					z = Math.sqrt( zz );
2217					x = xz / z;
2218					y = yz / z;
2219
2220				}
2221
2222			}
2223
2224			this.set( x, y, z, angle );
2225
2226			return this; // return 180 deg rotation
2227
2228		}
2229
2230		// as we have reached here there are no singularities so we can handle normally
2231
2232		var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
2233		                   ( m13 - m31 ) * ( m13 - m31 ) +
2234		                   ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
2235
2236		if ( Math.abs( s ) < 0.001 ) s = 1;
2237
2238		// prevent divide by zero, should not happen if matrix is orthogonal and should be
2239		// caught by singularity test above, but I've left it in just in case
2240
2241		this.x = ( m32 - m23 ) / s;
2242		this.y = ( m13 - m31 ) / s;
2243		this.z = ( m21 - m12 ) / s;
2244		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
2245
2246		return this;
2247
2248	},
2249
2250	min: function ( v ) {
2251
2252		this.x = Math.min( this.x, v.x );
2253		this.y = Math.min( this.y, v.y );
2254		this.z = Math.min( this.z, v.z );
2255		this.w = Math.min( this.w, v.w );
2256
2257		return this;
2258
2259	},
2260
2261	max: function ( v ) {
2262
2263		this.x = Math.max( this.x, v.x );
2264		this.y = Math.max( this.y, v.y );
2265		this.z = Math.max( this.z, v.z );
2266		this.w = Math.max( this.w, v.w );
2267
2268		return this;
2269
2270	},
2271
2272	clamp: function ( min, max ) {
2273
2274		// assumes min < max, componentwise
2275
2276		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2277		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2278		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2279		this.w = Math.max( min.w, Math.min( max.w, this.w ) );
2280
2281		return this;
2282
2283	},
2284
2285	clampScalar: function ( minVal, maxVal ) {
2286
2287		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
2288		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
2289		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
2290		this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
2291
2292		return this;
2293
2294	},
2295
2296	clampLength: function ( min, max ) {
2297
2298		var length = this.length();
2299
2300		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2301
2302	},
2303
2304	floor: function () {
2305
2306		this.x = Math.floor( this.x );
2307		this.y = Math.floor( this.y );
2308		this.z = Math.floor( this.z );
2309		this.w = Math.floor( this.w );
2310
2311		return this;
2312
2313	},
2314
2315	ceil: function () {
2316
2317		this.x = Math.ceil( this.x );
2318		this.y = Math.ceil( this.y );
2319		this.z = Math.ceil( this.z );
2320		this.w = Math.ceil( this.w );
2321
2322		return this;
2323
2324	},
2325
2326	round: function () {
2327
2328		this.x = Math.round( this.x );
2329		this.y = Math.round( this.y );
2330		this.z = Math.round( this.z );
2331		this.w = Math.round( this.w );
2332
2333		return this;
2334
2335	},
2336
2337	roundToZero: function () {
2338
2339		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2340		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2341		this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2342		this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
2343
2344		return this;
2345
2346	},
2347
2348	negate: function () {
2349
2350		this.x = - this.x;
2351		this.y = - this.y;
2352		this.z = - this.z;
2353		this.w = - this.w;
2354
2355		return this;
2356
2357	},
2358
2359	dot: function ( v ) {
2360
2361		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
2362
2363	},
2364
2365	lengthSq: function () {
2366
2367		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
2368
2369	},
2370
2371	length: function () {
2372
2373		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
2374
2375	},
2376
2377	manhattanLength: function () {
2378
2379		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
2380
2381	},
2382
2383	normalize: function () {
2384
2385		return this.divideScalar( this.length() || 1 );
2386
2387	},
2388
2389	setLength: function ( length ) {
2390
2391		return this.normalize().multiplyScalar( length );
2392
2393	},
2394
2395	lerp: function ( v, alpha ) {
2396
2397		this.x += ( v.x - this.x ) * alpha;
2398		this.y += ( v.y - this.y ) * alpha;
2399		this.z += ( v.z - this.z ) * alpha;
2400		this.w += ( v.w - this.w ) * alpha;
2401
2402		return this;
2403
2404	},
2405
2406	lerpVectors: function ( v1, v2, alpha ) {
2407
2408		return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
2409
2410	},
2411
2412	equals: function ( v ) {
2413
2414		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
2415
2416	},
2417
2418	fromArray: function ( array, offset ) {
2419
2420		if ( offset === undefined ) offset = 0;
2421
2422		this.x = array[ offset ];
2423		this.y = array[ offset + 1 ];
2424		this.z = array[ offset + 2 ];
2425		this.w = array[ offset + 3 ];
2426
2427		return this;
2428
2429	},
2430
2431	toArray: function ( array, offset ) {
2432
2433		if ( array === undefined ) array = [];
2434		if ( offset === undefined ) offset = 0;
2435
2436		array[ offset ] = this.x;
2437		array[ offset + 1 ] = this.y;
2438		array[ offset + 2 ] = this.z;
2439		array[ offset + 3 ] = this.w;
2440
2441		return array;
2442
2443	},
2444
2445	fromBufferAttribute: function ( attribute, index, offset ) {
2446
2447		if ( offset !== undefined ) {
2448
2449			console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
2450
2451		}
2452
2453		this.x = attribute.getX( index );
2454		this.y = attribute.getY( index );
2455		this.z = attribute.getZ( index );
2456		this.w = attribute.getW( index );
2457
2458		return this;
2459
2460	},
2461
2462	random: function () {
2463
2464		this.x = Math.random();
2465		this.y = Math.random();
2466		this.z = Math.random();
2467		this.w = Math.random();
2468
2469		return this;
2470
2471	}
2472
2473} );
2474
2475/**
2476 * @author szimek / https://github.com/szimek/
2477 * @author alteredq / http://alteredqualia.com/
2478 * @author Marius Kintel / https://github.com/kintel
2479 */
2480
2481/*
2482 In options, we can specify:
2483 * Texture parameters for an auto-generated target texture
2484 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
2485*/
2486function WebGLRenderTarget( width, height, options ) {
2487
2488	this.width = width;
2489	this.height = height;
2490
2491	this.scissor = new Vector4( 0, 0, width, height );
2492	this.scissorTest = false;
2493
2494	this.viewport = new Vector4( 0, 0, width, height );
2495
2496	options = options || {};
2497
2498	this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
2499
2500	this.texture.image = {};
2501	this.texture.image.width = width;
2502	this.texture.image.height = height;
2503
2504	this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
2505	this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
2506
2507	this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
2508	this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
2509	this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
2510
2511}
2512
2513WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
2514
2515	constructor: WebGLRenderTarget,
2516
2517	isWebGLRenderTarget: true,
2518
2519	setSize: function ( width, height ) {
2520
2521		if ( this.width !== width || this.height !== height ) {
2522
2523			this.width = width;
2524			this.height = height;
2525
2526			this.texture.image.width = width;
2527			this.texture.image.height = height;
2528
2529			this.dispose();
2530
2531		}
2532
2533		this.viewport.set( 0, 0, width, height );
2534		this.scissor.set( 0, 0, width, height );
2535
2536	},
2537
2538	clone: function () {
2539
2540		return new this.constructor().copy( this );
2541
2542	},
2543
2544	copy: function ( source ) {
2545
2546		this.width = source.width;
2547		this.height = source.height;
2548
2549		this.viewport.copy( source.viewport );
2550
2551		this.texture = source.texture.clone();
2552
2553		this.depthBuffer = source.depthBuffer;
2554		this.stencilBuffer = source.stencilBuffer;
2555		this.depthTexture = source.depthTexture;
2556
2557		return this;
2558
2559	},
2560
2561	dispose: function () {
2562
2563		this.dispatchEvent( { type: 'dispose' } );
2564
2565	}
2566
2567} );
2568
2569/**
2570 * @author Mugen87 / https://github.com/Mugen87
2571 * @author Matt DesLauriers / @mattdesl
2572 */
2573
2574function WebGLMultisampleRenderTarget( width, height, options ) {
2575
2576	WebGLRenderTarget.call( this, width, height, options );
2577
2578	this.samples = 4;
2579
2580}
2581
2582WebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {
2583
2584	constructor: WebGLMultisampleRenderTarget,
2585
2586	isWebGLMultisampleRenderTarget: true,
2587
2588	copy: function ( source ) {
2589
2590		WebGLRenderTarget.prototype.copy.call( this, source );
2591
2592		this.samples = source.samples;
2593
2594		return this;
2595
2596	}
2597
2598} );
2599
2600/**
2601 * @author mikael emtinger / http://gomo.se/
2602 * @author alteredq / http://alteredqualia.com/
2603 * @author WestLangley / http://github.com/WestLangley
2604 * @author bhouston / http://clara.io
2605 */
2606
2607function Quaternion( x, y, z, w ) {
2608
2609	this._x = x || 0;
2610	this._y = y || 0;
2611	this._z = z || 0;
2612	this._w = ( w !== undefined ) ? w : 1;
2613
2614}
2615
2616Object.assign( Quaternion, {
2617
2618	slerp: function ( qa, qb, qm, t ) {
2619
2620		return qm.copy( qa ).slerp( qb, t );
2621
2622	},
2623
2624	slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
2625
2626		// fuzz-free, array-based Quaternion SLERP operation
2627
2628		var x0 = src0[ srcOffset0 + 0 ],
2629			y0 = src0[ srcOffset0 + 1 ],
2630			z0 = src0[ srcOffset0 + 2 ],
2631			w0 = src0[ srcOffset0 + 3 ],
2632
2633			x1 = src1[ srcOffset1 + 0 ],
2634			y1 = src1[ srcOffset1 + 1 ],
2635			z1 = src1[ srcOffset1 + 2 ],
2636			w1 = src1[ srcOffset1 + 3 ];
2637
2638		if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
2639
2640			var s = 1 - t,
2641
2642				cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
2643
2644				dir = ( cos >= 0 ? 1 : - 1 ),
2645				sqrSin = 1 - cos * cos;
2646
2647			// Skip the Slerp for tiny steps to avoid numeric problems:
2648			if ( sqrSin > Number.EPSILON ) {
2649
2650				var sin = Math.sqrt( sqrSin ),
2651					len = Math.atan2( sin, cos * dir );
2652
2653				s = Math.sin( s * len ) / sin;
2654				t = Math.sin( t * len ) / sin;
2655
2656			}
2657
2658			var tDir = t * dir;
2659
2660			x0 = x0 * s + x1 * tDir;
2661			y0 = y0 * s + y1 * tDir;
2662			z0 = z0 * s + z1 * tDir;
2663			w0 = w0 * s + w1 * tDir;
2664
2665			// Normalize in case we just did a lerp:
2666			if ( s === 1 - t ) {
2667
2668				var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
2669
2670				x0 *= f;
2671				y0 *= f;
2672				z0 *= f;
2673				w0 *= f;
2674
2675			}
2676
2677		}
2678
2679		dst[ dstOffset ] = x0;
2680		dst[ dstOffset + 1 ] = y0;
2681		dst[ dstOffset + 2 ] = z0;
2682		dst[ dstOffset + 3 ] = w0;
2683
2684	},
2685
2686	multiplyQuaternionsFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
2687
2688		var x0 = src0[ srcOffset0 ];
2689		var y0 = src0[ srcOffset0 + 1 ];
2690		var z0 = src0[ srcOffset0 + 2 ];
2691		var w0 = src0[ srcOffset0 + 3 ];
2692
2693		var x1 = src1[ srcOffset1 ];
2694		var y1 = src1[ srcOffset1 + 1 ];
2695		var z1 = src1[ srcOffset1 + 2 ];
2696		var w1 = src1[ srcOffset1 + 3 ];
2697
2698		dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
2699		dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
2700		dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
2701		dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
2702
2703		return dst;
2704
2705	}
2706
2707} );
2708
2709Object.defineProperties( Quaternion.prototype, {
2710
2711	x: {
2712
2713		get: function () {
2714
2715			return this._x;
2716
2717		},
2718
2719		set: function ( value ) {
2720
2721			this._x = value;
2722			this._onChangeCallback();
2723
2724		}
2725
2726	},
2727
2728	y: {
2729
2730		get: function () {
2731
2732			return this._y;
2733
2734		},
2735
2736		set: function ( value ) {
2737
2738			this._y = value;
2739			this._onChangeCallback();
2740
2741		}
2742
2743	},
2744
vendor: 14,380 bytes, lines 2745-3560
2745	z: {
2746
2747		get: function () {
2748
2749			return this._z;
2750
2751		},
2752
2753		set: function ( value ) {
2754
2755			this._z = value;
2756			this._onChangeCallback();
2757
2758		}
2759
2760	},
2761
2762	w: {
2763
2764		get: function () {
2765
2766			return this._w;
2767
2768		},
2769
2770		set: function ( value ) {
2771
2772			this._w = value;
2773			this._onChangeCallback();
2774
2775		}
2776
2777	}
2778
2779} );
2780
2781Object.assign( Quaternion.prototype, {
2782
2783	isQuaternion: true,
2784
2785	set: function ( x, y, z, w ) {
2786
2787		this._x = x;
2788		this._y = y;
2789		this._z = z;
2790		this._w = w;
2791
2792		this._onChangeCallback();
2793
2794		return this;
2795
2796	},
2797
2798	clone: function () {
2799
2800		return new this.constructor( this._x, this._y, this._z, this._w );
2801
2802	},
2803
2804	copy: function ( quaternion ) {
2805
2806		this._x = quaternion.x;
2807		this._y = quaternion.y;
2808		this._z = quaternion.z;
2809		this._w = quaternion.w;
2810
2811		this._onChangeCallback();
2812
2813		return this;
2814
2815	},
2816
2817	setFromEuler: function ( euler, update ) {
2818
2819		if ( ! ( euler && euler.isEuler ) ) {
2820
2821			throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
2822
2823		}
2824
2825		var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
2826
2827		// http://www.mathworks.com/matlabcentral/fileexchange/
2828		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
2829		//	content/SpinCalc.m
2830
2831		var cos = Math.cos;
2832		var sin = Math.sin;
2833
2834		var c1 = cos( x / 2 );
2835		var c2 = cos( y / 2 );
2836		var c3 = cos( z / 2 );
2837
2838		var s1 = sin( x / 2 );
2839		var s2 = sin( y / 2 );
2840		var s3 = sin( z / 2 );
2841
2842		switch ( order ) {
2843
2844			case 'XYZ':
2845				this._x = s1 * c2 * c3 + c1 * s2 * s3;
2846				this._y = c1 * s2 * c3 - s1 * c2 * s3;
2847				this._z = c1 * c2 * s3 + s1 * s2 * c3;
2848				this._w = c1 * c2 * c3 - s1 * s2 * s3;
2849				break;
2850
2851			case 'YXZ':
2852				this._x = s1 * c2 * c3 + c1 * s2 * s3;
2853				this._y = c1 * s2 * c3 - s1 * c2 * s3;
2854				this._z = c1 * c2 * s3 - s1 * s2 * c3;
2855				this._w = c1 * c2 * c3 + s1 * s2 * s3;
2856				break;
2857
2858			case 'ZXY':
2859				this._x = s1 * c2 * c3 - c1 * s2 * s3;
2860				this._y = c1 * s2 * c3 + s1 * c2 * s3;
2861				this._z = c1 * c2 * s3 + s1 * s2 * c3;
2862				this._w = c1 * c2 * c3 - s1 * s2 * s3;
2863				break;
2864
2865			case 'ZYX':
2866				this._x = s1 * c2 * c3 - c1 * s2 * s3;
2867				this._y = c1 * s2 * c3 + s1 * c2 * s3;
2868				this._z = c1 * c2 * s3 - s1 * s2 * c3;
2869				this._w = c1 * c2 * c3 + s1 * s2 * s3;
2870				break;
2871
2872			case 'YZX':
2873				this._x = s1 * c2 * c3 + c1 * s2 * s3;
2874				this._y = c1 * s2 * c3 + s1 * c2 * s3;
2875				this._z = c1 * c2 * s3 - s1 * s2 * c3;
2876				this._w = c1 * c2 * c3 - s1 * s2 * s3;
2877				break;
2878
2879			case 'XZY':
2880				this._x = s1 * c2 * c3 - c1 * s2 * s3;
2881				this._y = c1 * s2 * c3 - s1 * c2 * s3;
2882				this._z = c1 * c2 * s3 + s1 * s2 * c3;
2883				this._w = c1 * c2 * c3 + s1 * s2 * s3;
2884				break;
2885
2886			default:
2887				console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
2888
2889		}
2890
2891		if ( update !== false ) this._onChangeCallback();
2892
2893		return this;
2894
2895	},
2896
2897	setFromAxisAngle: function ( axis, angle ) {
2898
2899		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
2900
2901		// assumes axis is normalized
2902
2903		var halfAngle = angle / 2, s = Math.sin( halfAngle );
2904
2905		this._x = axis.x * s;
2906		this._y = axis.y * s;
2907		this._z = axis.z * s;
2908		this._w = Math.cos( halfAngle );
2909
2910		this._onChangeCallback();
2911
2912		return this;
2913
2914	},
2915
2916	setFromRotationMatrix: function ( m ) {
2917
2918		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
2919
2920		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2921
2922		var te = m.elements,
2923
2924			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2925			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2926			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
2927
2928			trace = m11 + m22 + m33,
2929			s;
2930
2931		if ( trace > 0 ) {
2932
2933			s = 0.5 / Math.sqrt( trace + 1.0 );
2934
2935			this._w = 0.25 / s;
2936			this._x = ( m32 - m23 ) * s;
2937			this._y = ( m13 - m31 ) * s;
2938			this._z = ( m21 - m12 ) * s;
2939
2940		} else if ( m11 > m22 && m11 > m33 ) {
2941
2942			s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
2943
2944			this._w = ( m32 - m23 ) / s;
2945			this._x = 0.25 * s;
2946			this._y = ( m12 + m21 ) / s;
2947			this._z = ( m13 + m31 ) / s;
2948
2949		} else if ( m22 > m33 ) {
2950
2951			s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
2952
2953			this._w = ( m13 - m31 ) / s;
2954			this._x = ( m12 + m21 ) / s;
2955			this._y = 0.25 * s;
2956			this._z = ( m23 + m32 ) / s;
2957
2958		} else {
2959
2960			s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
2961
2962			this._w = ( m21 - m12 ) / s;
2963			this._x = ( m13 + m31 ) / s;
2964			this._y = ( m23 + m32 ) / s;
2965			this._z = 0.25 * s;
2966
2967		}
2968
2969		this._onChangeCallback();
2970
2971		return this;
2972
2973	},
2974
2975	setFromUnitVectors: function ( vFrom, vTo ) {
2976
2977		// assumes direction vectors vFrom and vTo are normalized
2978
2979		var EPS = 0.000001;
2980
2981		var r = vFrom.dot( vTo ) + 1;
2982
2983		if ( r < EPS ) {
2984
2985			r = 0;
2986
2987			if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
2988
2989				this._x = - vFrom.y;
2990				this._y = vFrom.x;
2991				this._z = 0;
2992				this._w = r;
2993
2994			} else {
2995
2996				this._x = 0;
2997				this._y = - vFrom.z;
2998				this._z = vFrom.y;
2999				this._w = r;
3000
3001			}
3002
3003		} else {
3004
3005			// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
3006
3007			this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
3008			this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
3009			this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
3010			this._w = r;
3011
3012		}
3013
3014		return this.normalize();
3015
3016	},
3017
3018	angleTo: function ( q ) {
3019
3020		return 2 * Math.acos( Math.abs( MathUtils.clamp( this.dot( q ), - 1, 1 ) ) );
3021
3022	},
3023
3024	rotateTowards: function ( q, step ) {
3025
3026		var angle = this.angleTo( q );
3027
3028		if ( angle === 0 ) return this;
3029
3030		var t = Math.min( 1, step / angle );
3031
3032		this.slerp( q, t );
3033
3034		return this;
3035
3036	},
3037
3038	inverse: function () {
3039
3040		// quaternion is assumed to have unit length
3041
3042		return this.conjugate();
3043
3044	},
3045
3046	conjugate: function () {
3047
3048		this._x *= - 1;
3049		this._y *= - 1;
3050		this._z *= - 1;
3051
3052		this._onChangeCallback();
3053
3054		return this;
3055
3056	},
3057
3058	dot: function ( v ) {
3059
3060		return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
3061
3062	},
3063
3064	lengthSq: function () {
3065
3066		return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
3067
3068	},
3069
3070	length: function () {
3071
3072		return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
3073
3074	},
3075
3076	normalize: function () {
3077
3078		var l = this.length();
3079
3080		if ( l === 0 ) {
3081
3082			this._x = 0;
3083			this._y = 0;
3084			this._z = 0;
3085			this._w = 1;
3086
3087		} else {
3088
3089			l = 1 / l;
3090
3091			this._x = this._x * l;
3092			this._y = this._y * l;
3093			this._z = this._z * l;
3094			this._w = this._w * l;
3095
3096		}
3097
3098		this._onChangeCallback();
3099
3100		return this;
3101
3102	},
3103
3104	multiply: function ( q, p ) {
3105
3106		if ( p !== undefined ) {
3107
3108			console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
3109			return this.multiplyQuaternions( q, p );
3110
3111		}
3112
3113		return this.multiplyQuaternions( this, q );
3114
3115	},
3116
3117	premultiply: function ( q ) {
3118
3119		return this.multiplyQuaternions( q, this );
3120
3121	},
3122
3123	multiplyQuaternions: function ( a, b ) {
3124
3125		// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
3126
3127		var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
3128		var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
3129
3130		this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
3131		this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
3132		this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
3133		this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
3134
3135		this._onChangeCallback();
3136
3137		return this;
3138
3139	},
3140
3141	slerp: function ( qb, t ) {
3142
3143		if ( t === 0 ) return this;
3144		if ( t === 1 ) return this.copy( qb );
3145
3146		var x = this._x, y = this._y, z = this._z, w = this._w;
3147
3148		// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
3149
3150		var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
3151
3152		if ( cosHalfTheta < 0 ) {
3153
3154			this._w = - qb._w;
3155			this._x = - qb._x;
3156			this._y = - qb._y;
3157			this._z = - qb._z;
3158
3159			cosHalfTheta = - cosHalfTheta;
3160
3161		} else {
3162
3163			this.copy( qb );
3164
3165		}
3166
3167		if ( cosHalfTheta >= 1.0 ) {
3168
3169			this._w = w;
3170			this._x = x;
3171			this._y = y;
3172			this._z = z;
3173
3174			return this;
3175
3176		}
3177
3178		var sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
3179
3180		if ( sqrSinHalfTheta <= Number.EPSILON ) {
3181
3182			var s = 1 - t;
3183			this._w = s * w + t * this._w;
3184			this._x = s * x + t * this._x;
3185			this._y = s * y + t * this._y;
3186			this._z = s * z + t * this._z;
3187
3188			this.normalize();
3189			this._onChangeCallback();
3190
3191			return this;
3192
3193		}
3194
3195		var sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
3196		var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
3197		var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
3198			ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
3199
3200		this._w = ( w * ratioA + this._w * ratioB );
3201		this._x = ( x * ratioA + this._x * ratioB );
3202		this._y = ( y * ratioA + this._y * ratioB );
3203		this._z = ( z * ratioA + this._z * ratioB );
3204
3205		this._onChangeCallback();
3206
3207		return this;
3208
3209	},
3210
3211	equals: function ( quaternion ) {
3212
3213		return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
3214
3215	},
3216
3217	fromArray: function ( array, offset ) {
3218
3219		if ( offset === undefined ) offset = 0;
3220
3221		this._x = array[ offset ];
3222		this._y = array[ offset + 1 ];
3223		this._z = array[ offset + 2 ];
3224		this._w = array[ offset + 3 ];
3225
3226		this._onChangeCallback();
3227
3228		return this;
3229
3230	},
3231
3232	toArray: function ( array, offset ) {
3233
3234		if ( array === undefined ) array = [];
3235		if ( offset === undefined ) offset = 0;
3236
3237		array[ offset ] = this._x;
3238		array[ offset + 1 ] = this._y;
3239		array[ offset + 2 ] = this._z;
3240		array[ offset + 3 ] = this._w;
3241
3242		return array;
3243
3244	},
3245
3246	fromBufferAttribute: function ( attribute, index ) {
3247
3248		this._x = attribute.getX( index );
3249		this._y = attribute.getY( index );
3250		this._z = attribute.getZ( index );
3251		this._w = attribute.getW( index );
3252
3253		return this;
3254
3255	},
3256
3257	_onChange: function ( callback ) {
3258
3259		this._onChangeCallback = callback;
3260
3261		return this;
3262
3263	},
3264
3265	_onChangeCallback: function () {}
3266
3267} );
3268
3269/**
3270 * @author mrdoob / http://mrdoob.com/
3271 * @author kile / http://kile.stravaganza.org/
3272 * @author philogb / http://blog.thejit.org/
3273 * @author mikael emtinger / http://gomo.se/
3274 * @author egraether / http://egraether.com/
3275 * @author WestLangley / http://github.com/WestLangley
3276 */
3277
3278var _vector = new Vector3();
3279var _quaternion = new Quaternion();
3280
3281function Vector3( x, y, z ) {
3282
3283	this.x = x || 0;
3284	this.y = y || 0;
3285	this.z = z || 0;
3286
3287}
3288
3289Object.assign( Vector3.prototype, {
3290
3291	isVector3: true,
3292
3293	set: function ( x, y, z ) {
3294
3295		this.x = x;
3296		this.y = y;
3297		this.z = z;
3298
3299		return this;
3300
3301	},
3302
3303	setScalar: function ( scalar ) {
3304
3305		this.x = scalar;
3306		this.y = scalar;
3307		this.z = scalar;
3308
3309		return this;
3310
3311	},
3312
3313	setX: function ( x ) {
3314
3315		this.x = x;
3316
3317		return this;
3318
3319	},
3320
3321	setY: function ( y ) {
3322
3323		this.y = y;
3324
3325		return this;
3326
3327	},
3328
3329	setZ: function ( z ) {
3330
3331		this.z = z;
3332
3333		return this;
3334
3335	},
3336
3337	setComponent: function ( index, value ) {
3338
3339		switch ( index ) {
3340
3341			case 0: this.x = value; break;
3342			case 1: this.y = value; break;
3343			case 2: this.z = value; break;
3344			default: throw new Error( 'index is out of range: ' + index );
3345
3346		}
3347
3348		return this;
3349
3350	},
3351
3352	getComponent: function ( index ) {
3353
3354		switch ( index ) {
3355
3356			case 0: return this.x;
3357			case 1: return this.y;
3358			case 2: return this.z;
3359			default: throw new Error( 'index is out of range: ' + index );
3360
3361		}
3362
3363	},
3364
3365	clone: function () {
3366
3367		return new this.constructor( this.x, this.y, this.z );
3368
3369	},
3370
3371	copy: function ( v ) {
3372
3373		this.x = v.x;
3374		this.y = v.y;
3375		this.z = v.z;
3376
3377		return this;
3378
3379	},
3380
3381	add: function ( v, w ) {
3382
3383		if ( w !== undefined ) {
3384
3385			console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
3386			return this.addVectors( v, w );
3387
3388		}
3389
3390		this.x += v.x;
3391		this.y += v.y;
3392		this.z += v.z;
3393
3394		return this;
3395
3396	},
3397
3398	addScalar: function ( s ) {
3399
3400		this.x += s;
3401		this.y += s;
3402		this.z += s;
3403
3404		return this;
3405
3406	},
3407
3408	addVectors: function ( a, b ) {
3409
3410		this.x = a.x + b.x;
3411		this.y = a.y + b.y;
3412		this.z = a.z + b.z;
3413
3414		return this;
3415
3416	},
3417
3418	addScaledVector: function ( v, s ) {
3419
3420		this.x += v.x * s;
3421		this.y += v.y * s;
3422		this.z += v.z * s;
3423
3424		return this;
3425
3426	},
3427
3428	sub: function ( v, w ) {
3429
3430		if ( w !== undefined ) {
3431
3432			console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
3433			return this.subVectors( v, w );
3434
3435		}
3436
3437		this.x -= v.x;
3438		this.y -= v.y;
3439		this.z -= v.z;
3440
3441		return this;
3442
3443	},
3444
3445	subScalar: function ( s ) {
3446
3447		this.x -= s;
3448		this.y -= s;
3449		this.z -= s;
3450
3451		return this;
3452
3453	},
3454
3455	subVectors: function ( a, b ) {
3456
3457		this.x = a.x - b.x;
3458		this.y = a.y - b.y;
3459		this.z = a.z - b.z;
3460
3461		return this;
3462
3463	},
3464
3465	multiply: function ( v, w ) {
3466
3467		if ( w !== undefined ) {
3468
3469			console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
3470			return this.multiplyVectors( v, w );
3471
3472		}
3473
3474		this.x *= v.x;
3475		this.y *= v.y;
3476		this.z *= v.z;
3477
3478		return this;
3479
3480	},
3481
3482	multiplyScalar: function ( scalar ) {
3483
3484		this.x *= scalar;
3485		this.y *= scalar;
3486		this.z *= scalar;
3487
3488		return this;
3489
3490	},
3491
3492	multiplyVectors: function ( a, b ) {
3493
3494		this.x = a.x * b.x;
3495		this.y = a.y * b.y;
3496		this.z = a.z * b.z;
3497
3498		return this;
3499
3500	},
3501
3502	applyEuler: function ( euler ) {
3503
3504		if ( ! ( euler && euler.isEuler ) ) {
3505
3506			console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
3507
3508		}
3509
3510		return this.applyQuaternion( _quaternion.setFromEuler( euler ) );
3511
3512	},
3513
3514	applyAxisAngle: function ( axis, angle ) {
3515
3516		return this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );
3517
3518	},
3519
3520	applyMatrix3: function ( m ) {
3521
3522		var x = this.x, y = this.y, z = this.z;
3523		var e = m.elements;
3524
3525		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
3526		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
3527		this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
3528
3529		return this;
3530
3531	},
3532
3533	applyNormalMatrix: function ( m ) {
3534
3535		return this.applyMatrix3( m ).normalize();
3536
3537	},
3538
3539	applyMatrix4: function ( m ) {
3540
3541		var x = this.x, y = this.y, z = this.z;
3542		var e = m.elements;
3543
3544		var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
3545
3546		this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
3547		this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
3548		this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
3549
3550		return this;
3551
3552	},
3553
3554	applyQuaternion: function ( q ) {
3555
3556		var x = this.x, y = this.y, z = this.z;
3557		var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
3558
3559		// calculate quat * vector
3560
3561		var ix = qw * x + qy * z - qz * y;
3562		var iy = qw * y + qz * x - qx * z;
3563		var iz = qw * z + qx * y - qy * x;
3564		var iw = - qx * x - qy * y - qz * z;
3565
3566		// calculate result * inverse quat
3567
3568		this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
3569		this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
3570		this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
3571
3572		return this;
3573
3574	},
3575
3576	project: function ( camera ) {
3577
3578		return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
3579
3580	},
3581
3582	unproject: function ( camera ) {
3583
3584		return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
3585
3586	},
3587
3588	transformDirection: function ( m ) {
3589
3590		// input: THREE.Matrix4 affine matrix
3591		// vector interpreted as a direction
3592
3593		var x = this.x, y = this.y, z = this.z;
3594		var e = m.elements;
3595
3596		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
3597		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
3598		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
3599
3600		return this.normalize();
3601
3602	},
3603
3604	divide: function ( v ) {
3605
3606		this.x /= v.x;
3607		this.y /= v.y;
3608		this.z /= v.z;
3609
3610		return this;
3611
3612	},
3613
3614	divideScalar: function ( scalar ) {
3615
3616		return this.multiplyScalar( 1 / scalar );
3617
3618	},
3619
3620	min: function ( v ) {
3621
3622		this.x = Math.min( this.x, v.x );
3623		this.y = Math.min( this.y, v.y );
3624		this.z = Math.min( this.z, v.z );
3625
3626		return this;
3627
3628	},
3629
3630	max: function ( v ) {
3631
3632		this.x = Math.max( this.x, v.x );
3633		this.y = Math.max( this.y, v.y );
3634		this.z = Math.max( this.z, v.z );
3635
3636		return this;
3637
3638	},
3639
3640	clamp: function ( min, max ) {
3641
3642		// assumes min < max, componentwise
3643
3644		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
3645		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
3646		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
3647
3648		return this;
3649
3650	},
3651
3652	clampScalar: function ( minVal, maxVal ) {
3653
3654		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
3655		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
3656		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
3657
3658		return this;
3659
3660	},
3661
3662	clampLength: function ( min, max ) {
3663
3664		var length = this.length();
3665
3666		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
3667
3668	},
3669
3670	floor: function () {
3671
3672		this.x = Math.floor( this.x );
3673		this.y = Math.floor( this.y );
3674		this.z = Math.floor( this.z );
3675
3676		return this;
3677
3678	},
3679
3680	ceil: function () {
3681
3682		this.x = Math.ceil( this.x );
3683		this.y = Math.ceil( this.y );
3684		this.z = Math.ceil( this.z );
3685
3686		return this;
3687
3688	},
3689
3690	round: function () {
3691
3692		this.x = Math.round( this.x );
3693		this.y = Math.round( this.y );
3694		this.z = Math.round( this.z );
3695
3696		return this;
3697
3698	},
3699
3700	roundToZero: function () {
3701
3702		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
3703		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
3704		this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
3705
3706		return this;
3707
3708	},
3709
3710	negate: function () {
3711
3712		this.x = - this.x;
3713		this.y = - this.y;
3714		this.z = - this.z;
3715
3716		return this;
3717
3718	},
3719
3720	dot: function ( v ) {
3721
3722		return this.x * v.x + this.y * v.y + this.z * v.z;
3723
3724	},
3725
3726	// TODO lengthSquared?
3727
3728	lengthSq: function () {
3729
3730		return this.x * this.x + this.y * this.y + this.z * this.z;
3731
3732	},
3733
3734	length: function () {
3735
3736		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
3737
3738	},
3739
3740	manhattanLength: function () {
3741
3742		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
3743
3744	},
3745
3746	normalize: function () {
3747
3748		return this.divideScalar( this.length() || 1 );
3749
3750	},
3751
3752	setLength: function ( length ) {
3753
3754		return this.normalize().multiplyScalar( length );
3755
3756	},
3757
3758	lerp: function ( v, alpha ) {
3759
3760		this.x += ( v.x - this.x ) * alpha;
3761		this.y += ( v.y - this.y ) * alpha;
3762		this.z += ( v.z - this.z ) * alpha;
3763
3764		return this;
3765
3766	},
3767
3768	lerpVectors: function ( v1, v2, alpha ) {
3769
3770		return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
3771
3772	},
3773
3774	cross: function ( v, w ) {
3775
3776		if ( w !== undefined ) {
3777
3778			console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
3779			return this.crossVectors( v, w );
3780
3781		}
3782
3783		return this.crossVectors( this, v );
3784
3785	},
3786
3787	crossVectors: function ( a, b ) {
3788
3789		var ax = a.x, ay = a.y, az = a.z;
3790		var bx = b.x, by = b.y, bz = b.z;
3791
3792		this.x = ay * bz - az * by;
3793		this.y = az * bx - ax * bz;
3794		this.z = ax * by - ay * bx;
3795
3796		return this;
3797
3798	},
3799
3800	projectOnVector: function ( v ) {
3801
3802		var denominator = v.lengthSq();
3803
3804		if ( denominator === 0 ) return this.set( 0, 0, 0 );
3805
3806		var scalar = v.dot( this ) / denominator;
3807
3808		return this.copy( v ).multiplyScalar( scalar );
3809
3810	},
3811
3812	projectOnPlane: function ( planeNormal ) {
3813
3814		_vector.copy( this ).projectOnVector( planeNormal );
3815
3816		return this.sub( _vector );
3817
3818	},
3819
3820	reflect: function ( normal ) {
3821
3822		// reflect incident vector off plane orthogonal to normal
3823		// normal is assumed to have unit length
3824
3825		return this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
3826
3827	},
3828
3829	angleTo: function ( v ) {
3830
3831		var denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
3832
3833		if ( denominator === 0 ) return Math.PI / 2;
3834
3835		var theta = this.dot( v ) / denominator;
3836
3837		// clamp, to handle numerical problems
3838
3839		return Math.acos( MathUtils.clamp( theta, - 1, 1 ) );
3840
3841	},
3842
3843	distanceTo: function ( v ) {
3844
3845		return Math.sqrt( this.distanceToSquared( v ) );
3846
3847	},
3848
3849	distanceToSquared: function ( v ) {
3850
3851		var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3852
3853		return dx * dx + dy * dy + dz * dz;
3854
3855	},
3856
3857	manhattanDistanceTo: function ( v ) {
3858
3859		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
3860
3861	},
3862
3863	setFromSpherical: function ( s ) {
3864
3865		return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
3866
3867	},
3868
3869	setFromSphericalCoords: function ( radius, phi, theta ) {
3870
3871		var sinPhiRadius = Math.sin( phi ) * radius;
3872
3873		this.x = sinPhiRadius * Math.sin( theta );
3874		this.y = Math.cos( phi ) * radius;
3875		this.z = sinPhiRadius * Math.cos( theta );
3876
3877		return this;
3878
3879	},
3880
3881	setFromCylindrical: function ( c ) {
3882
3883		return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
3884
3885	},
3886
3887	setFromCylindricalCoords: function ( radius, theta, y ) {
3888
3889		this.x = radius * Math.sin( theta );
3890		this.y = y;
3891		this.z = radius * Math.cos( theta );
3892
3893		return this;
3894
3895	},
3896
3897	setFromMatrixPosition: function ( m ) {
3898
3899		var e = m.elements;
3900
3901		this.x = e[ 12 ];
3902		this.y = e[ 13 ];
3903		this.z = e[ 14 ];
3904
3905		return this;
3906
3907	},
3908
3909	setFromMatrixScale: function ( m ) {
3910
3911		var sx = this.setFromMatrixColumn( m, 0 ).length();
3912		var sy = this.setFromMatrixColumn( m, 1 ).length();
3913		var sz = this.setFromMatrixColumn( m, 2 ).length();
3914
3915		this.x = sx;
3916		this.y = sy;
3917		this.z = sz;
3918
3919		return this;
3920
3921	},
3922
3923	setFromMatrixColumn: function ( m, index ) {
3924
3925		return this.fromArray( m.elements, index * 4 );
3926
3927	},
3928
3929	setFromMatrix3Column: function ( m, index ) {
3930
3931		return this.fromArray( m.elements, index * 3 );
3932
3933	},
3934
3935	equals: function ( v ) {
3936
3937		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
3938
3939	},
3940
3941	fromArray: function ( array, offset ) {
3942
3943		if ( offset === undefined ) offset = 0;
3944
3945		this.x = array[ offset ];
3946		this.y = array[ offset + 1 ];
3947		this.z = array[ offset + 2 ];
3948
3949		return this;
3950
3951	},
3952
3953	toArray: function ( array, offset ) {
3954
3955		if ( array === undefined ) array = [];
3956		if ( offset === undefined ) offset = 0;
3957
3958		array[ offset ] = this.x;
3959		array[ offset + 1 ] = this.y;
3960		array[ offset + 2 ] = this.z;
3961
3962		return array;
3963
3964	},
3965
3966	fromBufferAttribute: function ( attribute, index, offset ) {
3967
3968		if ( offset !== undefined ) {
3969
3970			console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );
3971
3972		}
3973
3974		this.x = attribute.getX( index );
3975		this.y = attribute.getY( index );
3976		this.z = attribute.getZ( index );
3977
3978		return this;
3979
3980	},
3981
3982	random: function () {
3983
3984		this.x = Math.random();
3985		this.y = Math.random();
3986		this.z = Math.random();
3987
3988		return this;
3989
3990	}
3991
3992} );
3993
3994var _v1 = new Vector3();
3995var _m1 = new Matrix4();
3996var _zero = new Vector3( 0, 0, 0 );
3997var _one = new Vector3( 1, 1, 1 );
3998var _x = new Vector3();
3999var _y = new Vector3();
4000var _z = new Vector3();
4001
4002/**
4003 * @author mrdoob / http://mrdoob.com/
4004 * @author supereggbert / http://www.paulbrunt.co.uk/
4005 * @author philogb / http://blog.thejit.org/
4006 * @author jordi_ros / http://plattsoft.com
4007 * @author D1plo1d / http://github.com/D1plo1d
4008 * @author alteredq / http://alteredqualia.com/
4009 * @author mikael emtinger / http://gomo.se/
4010 * @author timknip / http://www.floorplanner.com/
4011 * @author bhouston / http://clara.io
4012 * @author WestLangley / http://github.com/WestLangley
4013 */
4014
4015function Matrix4() {
4016
4017	this.elements = [
4018
4019		1, 0, 0, 0,
4020		0, 1, 0, 0,
4021		0, 0, 1, 0,
4022		0, 0, 0, 1
4023
4024	];
4025
4026	if ( arguments.length > 0 ) {
4027
4028		console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
4029
4030	}
4031
4032}
4033
4034Object.assign( Matrix4.prototype, {
4035
4036	isMatrix4: true,
4037
4038	set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
4039
4040		var te = this.elements;
4041
4042		te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
4043		te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
4044		te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
4045		te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
4046
4047		return this;
4048
4049	},
4050
4051	identity: function () {
4052
4053		this.set(
4054
4055			1, 0, 0, 0,
4056			0, 1, 0, 0,
4057			0, 0, 1, 0,
4058			0, 0, 0, 1
4059
4060		);
4061
4062		return this;
4063
4064	},
4065
4066	clone: function () {
4067
4068		return new Matrix4().fromArray( this.elements );
4069
4070	},
4071
4072	copy: function ( m ) {
4073
4074		var te = this.elements;
4075		var me = m.elements;
4076
4077		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
4078		te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
4079		te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
4080		te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
4081
4082		return this;
4083
4084	},
4085
4086	copyPosition: function ( m ) {
4087
4088		var te = this.elements, me = m.elements;
4089
4090		te[ 12 ] = me[ 12 ];
4091		te[ 13 ] = me[ 13 ];
4092		te[ 14 ] = me[ 14 ];
4093
4094		return this;
4095
4096	},
4097
4098	extractBasis: function ( xAxis, yAxis, zAxis ) {
4099
4100		xAxis.setFromMatrixColumn( this, 0 );
4101		yAxis.setFromMatrixColumn( this, 1 );
4102		zAxis.setFromMatrixColumn( this, 2 );
4103
4104		return this;
4105
4106	},
4107
4108	makeBasis: function ( xAxis, yAxis, zAxis ) {
4109
4110		this.set(
4111			xAxis.x, yAxis.x, zAxis.x, 0,
4112			xAxis.y, yAxis.y, zAxis.y, 0,
vendor: 15,119 bytes, lines 4113-4780
4113			xAxis.z, yAxis.z, zAxis.z, 0,
4114			0, 0, 0, 1
4115		);
4116
4117		return this;
4118
4119	},
4120
4121	extractRotation: function ( m ) {
4122
4123		// this method does not support reflection matrices
4124
4125		var te = this.elements;
4126		var me = m.elements;
4127
4128		var scaleX = 1 / _v1.setFromMatrixColumn( m, 0 ).length();
4129		var scaleY = 1 / _v1.setFromMatrixColumn( m, 1 ).length();
4130		var scaleZ = 1 / _v1.setFromMatrixColumn( m, 2 ).length();
4131
4132		te[ 0 ] = me[ 0 ] * scaleX;
4133		te[ 1 ] = me[ 1 ] * scaleX;
4134		te[ 2 ] = me[ 2 ] * scaleX;
4135		te[ 3 ] = 0;
4136
4137		te[ 4 ] = me[ 4 ] * scaleY;
4138		te[ 5 ] = me[ 5 ] * scaleY;
4139		te[ 6 ] = me[ 6 ] * scaleY;
4140		te[ 7 ] = 0;
4141
4142		te[ 8 ] = me[ 8 ] * scaleZ;
4143		te[ 9 ] = me[ 9 ] * scaleZ;
4144		te[ 10 ] = me[ 10 ] * scaleZ;
4145		te[ 11 ] = 0;
4146
4147		te[ 12 ] = 0;
4148		te[ 13 ] = 0;
4149		te[ 14 ] = 0;
4150		te[ 15 ] = 1;
4151
4152		return this;
4153
4154	},
4155
4156	makeRotationFromEuler: function ( euler ) {
4157
4158		if ( ! ( euler && euler.isEuler ) ) {
4159
4160			console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
4161
4162		}
4163
4164		var te = this.elements;
4165
4166		var x = euler.x, y = euler.y, z = euler.z;
4167		var a = Math.cos( x ), b = Math.sin( x );
4168		var c = Math.cos( y ), d = Math.sin( y );
4169		var e = Math.cos( z ), f = Math.sin( z );
4170
4171		if ( euler.order === 'XYZ' ) {
4172
4173			var ae = a * e, af = a * f, be = b * e, bf = b * f;
4174
4175			te[ 0 ] = c * e;
4176			te[ 4 ] = - c * f;
4177			te[ 8 ] = d;
4178
4179			te[ 1 ] = af + be * d;
4180			te[ 5 ] = ae - bf * d;
4181			te[ 9 ] = - b * c;
4182
4183			te[ 2 ] = bf - ae * d;
4184			te[ 6 ] = be + af * d;
4185			te[ 10 ] = a * c;
4186
4187		} else if ( euler.order === 'YXZ' ) {
4188
4189			var ce = c * e, cf = c * f, de = d * e, df = d * f;
4190
4191			te[ 0 ] = ce + df * b;
4192			te[ 4 ] = de * b - cf;
4193			te[ 8 ] = a * d;
4194
4195			te[ 1 ] = a * f;
4196			te[ 5 ] = a * e;
4197			te[ 9 ] = - b;
4198
4199			te[ 2 ] = cf * b - de;
4200			te[ 6 ] = df + ce * b;
4201			te[ 10 ] = a * c;
4202
4203		} else if ( euler.order === 'ZXY' ) {
4204
4205			var ce = c * e, cf = c * f, de = d * e, df = d * f;
4206
4207			te[ 0 ] = ce - df * b;
4208			te[ 4 ] = - a * f;
4209			te[ 8 ] = de + cf * b;
4210
4211			te[ 1 ] = cf + de * b;
4212			te[ 5 ] = a * e;
4213			te[ 9 ] = df - ce * b;
4214
4215			te[ 2 ] = - a * d;
4216			te[ 6 ] = b;
4217			te[ 10 ] = a * c;
4218
4219		} else if ( euler.order === 'ZYX' ) {
4220
4221			var ae = a * e, af = a * f, be = b * e, bf = b * f;
4222
4223			te[ 0 ] = c * e;
4224			te[ 4 ] = be * d - af;
4225			te[ 8 ] = ae * d + bf;
4226
4227			te[ 1 ] = c * f;
4228			te[ 5 ] = bf * d + ae;
4229			te[ 9 ] = af * d - be;
4230
4231			te[ 2 ] = - d;
4232			te[ 6 ] = b * c;
4233			te[ 10 ] = a * c;
4234
4235		} else if ( euler.order === 'YZX' ) {
4236
4237			var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
4238
4239			te[ 0 ] = c * e;
4240			te[ 4 ] = bd - ac * f;
4241			te[ 8 ] = bc * f + ad;
4242
4243			te[ 1 ] = f;
4244			te[ 5 ] = a * e;
4245			te[ 9 ] = - b * e;
4246
4247			te[ 2 ] = - d * e;
4248			te[ 6 ] = ad * f + bc;
4249			te[ 10 ] = ac - bd * f;
4250
4251		} else if ( euler.order === 'XZY' ) {
4252
4253			var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
4254
4255			te[ 0 ] = c * e;
4256			te[ 4 ] = - f;
4257			te[ 8 ] = d * e;
4258
4259			te[ 1 ] = ac * f + bd;
4260			te[ 5 ] = a * e;
4261			te[ 9 ] = ad * f - bc;
4262
4263			te[ 2 ] = bc * f - ad;
4264			te[ 6 ] = b * e;
4265			te[ 10 ] = bd * f + ac;
4266
4267		}
4268
4269		// bottom row
4270		te[ 3 ] = 0;
4271		te[ 7 ] = 0;
4272		te[ 11 ] = 0;
4273
4274		// last column
4275		te[ 12 ] = 0;
4276		te[ 13 ] = 0;
4277		te[ 14 ] = 0;
4278		te[ 15 ] = 1;
4279
4280		return this;
4281
4282	},
4283
4284	makeRotationFromQuaternion: function ( q ) {
4285
4286		return this.compose( _zero, q, _one );
4287
4288	},
4289
4290	lookAt: function ( eye, target, up ) {
4291
4292		var te = this.elements;
4293
4294		_z.subVectors( eye, target );
4295
4296		if ( _z.lengthSq() === 0 ) {
4297
4298			// eye and target are in the same position
4299
4300			_z.z = 1;
4301
4302		}
4303
4304		_z.normalize();
4305		_x.crossVectors( up, _z );
4306
4307		if ( _x.lengthSq() === 0 ) {
4308
4309			// up and z are parallel
4310
4311			if ( Math.abs( up.z ) === 1 ) {
4312
4313				_z.x += 0.0001;
4314
4315			} else {
4316
4317				_z.z += 0.0001;
4318
4319			}
4320
4321			_z.normalize();
4322			_x.crossVectors( up, _z );
4323
4324		}
4325
4326		_x.normalize();
4327		_y.crossVectors( _z, _x );
4328
4329		te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
4330		te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
4331		te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
4332
4333		return this;
4334
4335	},
4336
4337	multiply: function ( m, n ) {
4338
4339		if ( n !== undefined ) {
4340
4341			console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
4342			return this.multiplyMatrices( m, n );
4343
4344		}
4345
4346		return this.multiplyMatrices( this, m );
4347
4348	},
4349
4350	premultiply: function ( m ) {
4351
4352		return this.multiplyMatrices( m, this );
4353
4354	},
4355
4356	multiplyMatrices: function ( a, b ) {
4357
4358		var ae = a.elements;
4359		var be = b.elements;
4360		var te = this.elements;
4361
4362		var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
4363		var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
4364		var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
4365		var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
4366
4367		var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
4368		var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
4369		var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
4370		var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
4371
4372		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
4373		te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
4374		te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
4375		te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
4376
4377		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
4378		te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
4379		te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
4380		te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
4381
4382		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
4383		te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
4384		te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
4385		te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
4386
4387		te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
4388		te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
4389		te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
4390		te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
4391
4392		return this;
4393
4394	},
4395
4396	multiplyScalar: function ( s ) {
4397
4398		var te = this.elements;
4399
4400		te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
4401		te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
4402		te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
4403		te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
4404
4405		return this;
4406
4407	},
4408
4409	determinant: function () {
4410
4411		var te = this.elements;
4412
4413		var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
4414		var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
4415		var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
4416		var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
4417
4418		//TODO: make this more efficient
4419		//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
4420
4421		return (
4422			n41 * (
4423				+ n14 * n23 * n32
4424				 - n13 * n24 * n32
4425				 - n14 * n22 * n33
4426				 + n12 * n24 * n33
4427				 + n13 * n22 * n34
4428				 - n12 * n23 * n34
4429			) +
4430			n42 * (
4431				+ n11 * n23 * n34
4432				 - n11 * n24 * n33
4433				 + n14 * n21 * n33
4434				 - n13 * n21 * n34
4435				 + n13 * n24 * n31
4436				 - n14 * n23 * n31
4437			) +
4438			n43 * (
4439				+ n11 * n24 * n32
4440				 - n11 * n22 * n34
4441				 - n14 * n21 * n32
4442				 + n12 * n21 * n34
4443				 + n14 * n22 * n31
4444				 - n12 * n24 * n31
4445			) +
4446			n44 * (
4447				- n13 * n22 * n31
4448				 - n11 * n23 * n32
4449				 + n11 * n22 * n33
4450				 + n13 * n21 * n32
4451				 - n12 * n21 * n33
4452				 + n12 * n23 * n31
4453			)
4454
4455		);
4456
4457	},
4458
4459	transpose: function () {
4460
4461		var te = this.elements;
4462		var tmp;
4463
4464		tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
4465		tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
4466		tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
4467
4468		tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
4469		tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
4470		tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
4471
4472		return this;
4473
4474	},
4475
4476	setPosition: function ( x, y, z ) {
4477
4478		var te = this.elements;
4479
4480		if ( x.isVector3 ) {
4481
4482			te[ 12 ] = x.x;
4483			te[ 13 ] = x.y;
4484			te[ 14 ] = x.z;
4485
4486		} else {
4487
4488			te[ 12 ] = x;
4489			te[ 13 ] = y;
4490			te[ 14 ] = z;
4491
4492		}
4493
4494		return this;
4495
4496	},
4497
4498	getInverse: function ( m, throwOnDegenerate ) {
4499
4500		if ( throwOnDegenerate !== undefined ) {
4501
4502			console.warn( "THREE.Matrix4: .getInverse() can no longer be configured to throw on degenerate." );
4503
4504		}
4505
4506		// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
4507		var te = this.elements,
4508			me = m.elements,
4509
4510			n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
4511			n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
4512			n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
4513			n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
4514
4515			t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
4516			t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
4517			t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
4518			t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
4519
4520		var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
4521
4522		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
4523
4524		var detInv = 1 / det;
4525
4526		te[ 0 ] = t11 * detInv;
4527		te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
4528		te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
4529		te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
4530
4531		te[ 4 ] = t12 * detInv;
4532		te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
4533		te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
4534		te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
4535
4536		te[ 8 ] = t13 * detInv;
4537		te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
4538		te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
4539		te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
4540
4541		te[ 12 ] = t14 * detInv;
4542		te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
4543		te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
4544		te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
4545
4546		return this;
4547
4548	},
4549
4550	scale: function ( v ) {
4551
4552		var te = this.elements;
4553		var x = v.x, y = v.y, z = v.z;
4554
4555		te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
4556		te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
4557		te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
4558		te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
4559
4560		return this;
4561
4562	},
4563
4564	getMaxScaleOnAxis: function () {
4565
4566		var te = this.elements;
4567
4568		var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
4569		var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
4570		var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
4571
4572		return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
4573
4574	},
4575
4576	makeTranslation: function ( x, y, z ) {
4577
4578		this.set(
4579
4580			1, 0, 0, x,
4581			0, 1, 0, y,
4582			0, 0, 1, z,
4583			0, 0, 0, 1
4584
4585		);
4586
4587		return this;
4588
4589	},
4590
4591	makeRotationX: function ( theta ) {
4592
4593		var c = Math.cos( theta ), s = Math.sin( theta );
4594
4595		this.set(
4596
4597			1, 0, 0, 0,
4598			0, c, - s, 0,
4599			0, s, c, 0,
4600			0, 0, 0, 1
4601
4602		);
4603
4604		return this;
4605
4606	},
4607
4608	makeRotationY: function ( theta ) {
4609
4610		var c = Math.cos( theta ), s = Math.sin( theta );
4611
4612		this.set(
4613
4614			 c, 0, s, 0,
4615			 0, 1, 0, 0,
4616			- s, 0, c, 0,
4617			 0, 0, 0, 1
4618
4619		);
4620
4621		return this;
4622
4623	},
4624
4625	makeRotationZ: function ( theta ) {
4626
4627		var c = Math.cos( theta ), s = Math.sin( theta );
4628
4629		this.set(
4630
4631			c, - s, 0, 0,
4632			s, c, 0, 0,
4633			0, 0, 1, 0,
4634			0, 0, 0, 1
4635
4636		);
4637
4638		return this;
4639
4640	},
4641
4642	makeRotationAxis: function ( axis, angle ) {
4643
4644		// Based on http://www.gamedev.net/reference/articles/article1199.asp
4645
4646		var c = Math.cos( angle );
4647		var s = Math.sin( angle );
4648		var t = 1 - c;
4649		var x = axis.x, y = axis.y, z = axis.z;
4650		var tx = t * x, ty = t * y;
4651
4652		this.set(
4653
4654			tx * x + c, tx * y - s * z, tx * z + s * y, 0,
4655			tx * y + s * z, ty * y + c, ty * z - s * x, 0,
4656			tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
4657			0, 0, 0, 1
4658
4659		);
4660
4661		 return this;
4662
4663	},
4664
4665	makeScale: function ( x, y, z ) {
4666
4667		this.set(
4668
4669			x, 0, 0, 0,
4670			0, y, 0, 0,
4671			0, 0, z, 0,
4672			0, 0, 0, 1
4673
4674		);
4675
4676		return this;
4677
4678	},
4679
4680	makeShear: function ( x, y, z ) {
4681
4682		this.set(
4683
4684			1, y, z, 0,
4685			x, 1, z, 0,
4686			x, y, 1, 0,
4687			0, 0, 0, 1
4688
4689		);
4690
4691		return this;
4692
4693	},
4694
4695	compose: function ( position, quaternion, scale ) {
4696
4697		var te = this.elements;
4698
4699		var x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
4700		var x2 = x + x,	y2 = y + y, z2 = z + z;
4701		var xx = x * x2, xy = x * y2, xz = x * z2;
4702		var yy = y * y2, yz = y * z2, zz = z * z2;
4703		var wx = w * x2, wy = w * y2, wz = w * z2;
4704
4705		var sx = scale.x, sy = scale.y, sz = scale.z;
4706
4707		te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
4708		te[ 1 ] = ( xy + wz ) * sx;
4709		te[ 2 ] = ( xz - wy ) * sx;
4710		te[ 3 ] = 0;
4711
4712		te[ 4 ] = ( xy - wz ) * sy;
4713		te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
4714		te[ 6 ] = ( yz + wx ) * sy;
4715		te[ 7 ] = 0;
4716
4717		te[ 8 ] = ( xz + wy ) * sz;
4718		te[ 9 ] = ( yz - wx ) * sz;
4719		te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
4720		te[ 11 ] = 0;
4721
4722		te[ 12 ] = position.x;
4723		te[ 13 ] = position.y;
4724		te[ 14 ] = position.z;
4725		te[ 15 ] = 1;
4726
4727		return this;
4728
4729	},
4730
4731	decompose: function ( position, quaternion, scale ) {
4732
4733		var te = this.elements;
4734
4735		var sx = _v1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
4736		var sy = _v1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
4737		var sz = _v1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
4738
4739		// if determine is negative, we need to invert one scale
4740		var det = this.determinant();
4741		if ( det < 0 ) sx = - sx;
4742
4743		position.x = te[ 12 ];
4744		position.y = te[ 13 ];
4745		position.z = te[ 14 ];
4746
4747		// scale the rotation part
4748		_m1.copy( this );
4749
4750		var invSX = 1 / sx;
4751		var invSY = 1 / sy;
4752		var invSZ = 1 / sz;
4753
4754		_m1.elements[ 0 ] *= invSX;
4755		_m1.elements[ 1 ] *= invSX;
4756		_m1.elements[ 2 ] *= invSX;
4757
4758		_m1.elements[ 4 ] *= invSY;
4759		_m1.elements[ 5 ] *= invSY;
4760		_m1.elements[ 6 ] *= invSY;
4761
4762		_m1.elements[ 8 ] *= invSZ;
4763		_m1.elements[ 9 ] *= invSZ;
4764		_m1.elements[ 10 ] *= invSZ;
4765
4766		quaternion.setFromRotationMatrix( _m1 );
4767
4768		scale.x = sx;
4769		scale.y = sy;
4770		scale.z = sz;
4771
4772		return this;
4773
4774	},
4775
4776	makePerspective: function ( left, right, top, bottom, near, far ) {
4777
4778		if ( far === undefined ) {
4779
4780			console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a 
4780new signature. Please check the docs.' );
4781
4782		}
4783
4784		var te = this.elements;
4785		var x = 2 * near / ( right - left );
4786		var y = 2 * near / ( top - bottom );
4787
4788		var a = ( right + left ) / ( right - left );
4789		var b = ( top + bottom ) / ( top - bottom );
4790		var c = - ( far + near ) / ( far - near );
4791		var d = - 2 * far * near / ( far - near );
4792
4793		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a;	te[ 12 ] = 0;
4794		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b;	te[ 13 ] = 0;
4795		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c;	te[ 14 ] = d;
4796		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
4797
4798		return this;
4799
4800	},
4801
4802	makeOrthographic: function ( left, right, top, bottom, near, far ) {
4803
4804		var te = this.elements;
4805		var w = 1.0 / ( right - left );
4806		var h = 1.0 / ( top - bottom );
4807		var p = 1.0 / ( far - near );
4808
4809		var x = ( right + left ) * w;
4810		var y = ( top + bottom ) * h;
4811		var z = ( far + near ) * p;
4812
4813		te[ 0 ] = 2 * w;	te[ 4 ] = 0;	te[ 8 ] = 0;	te[ 12 ] = - x;
4814		te[ 1 ] = 0;	te[ 5 ] = 2 * h;	te[ 9 ] = 0;	te[ 13 ] = - y;
4815		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = - 2 * p;	te[ 14 ] = - z;
4816		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = 0;	te[ 15 ] = 1;
4817
4818		return this;
4819
4820	},
4821
4822	equals: function ( matrix ) {
4823
4824		var te = this.elements;
4825		var me = matrix.elements;
4826
4827		for ( var i = 0; i < 16; i ++ ) {
4828
4829			if ( te[ i ] !== me[ i ] ) return false;
4830
4831		}
4832
4833		return true;
4834
4835	},
4836
4837	fromArray: function ( array, offset ) {
4838
4839		if ( offset === undefined ) offset = 0;
4840
4841		for ( var i = 0; i < 16; i ++ ) {
4842
4843			this.elements[ i ] = array[ i + offset ];
4844
4845		}
4846
4847		return this;
4848
4849	},
4850
4851	toArray: function ( array, offset ) {
4852
4853		if ( array === undefined ) array = [];
4854		if ( offset === undefined ) offset = 0;
4855
4856		var te = this.elements;
4857
4858		array[ offset ] = te[ 0 ];
4859		array[ offset + 1 ] = te[ 1 ];
4860		array[ offset + 2 ] = te[ 2 ];
4861		array[ offset + 3 ] = te[ 3 ];
4862
4863		array[ offset + 4 ] = te[ 4 ];
4864		array[ offset + 5 ] = te[ 5 ];
4865		array[ offset + 6 ] = te[ 6 ];
4866		array[ offset + 7 ] = te[ 7 ];
4867
4868		array[ offset + 8 ] = te[ 8 ];
4869		array[ offset + 9 ] = te[ 9 ];
4870		array[ offset + 10 ] = te[ 10 ];
4871		array[ offset + 11 ] = te[ 11 ];
4872
4873		array[ offset + 12 ] = te[ 12 ];
4874		array[ offset + 13 ] = te[ 13 ];
4875		array[ offset + 14 ] = te[ 14 ];
4876		array[ offset + 15 ] = te[ 15 ];
4877
4878		return array;
4879
4880	}
4881
4882} );
4883
4884/**
4885 * @author mrdoob / http://mrdoob.com/
4886 * @author WestLangley / http://github.com/WestLangley
4887 * @author bhouston / http://clara.io
4888 */
4889
4890var _matrix = new Matrix4();
4891var _quaternion$1 = new Quaternion();
4892
4893function Euler( x, y, z, order ) {
4894
4895	this._x = x || 0;
4896	this._y = y || 0;
4897	this._z = z || 0;
4898	this._order = order || Euler.DefaultOrder;
4899
4900}
4901
4902Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
4903
4904Euler.DefaultOrder = 'XYZ';
4905
4906Object.defineProperties( Euler.prototype, {
4907
4908	x: {
4909
4910		get: function () {
4911
4912			return this._x;
4913
4914		},
4915
4916		set: function ( value ) {
4917
4918			this._x = value;
4919			this._onChangeCallback();
4920
4921		}
4922
4923	},
4924
4925	y: {
4926
4927		get: function () {
4928
4929			return this._y;
4930
4931		},
4932
4933		set: function ( value ) {
4934
4935			this._y = value;
4936			this._onChangeCallback();
4937
4938		}
4939
4940	},
4941
4942	z: {
4943
4944		get: function () {
4945
4946			return this._z;
4947
4948		},
4949
4950		set: function ( value ) {
4951
4952			this._z = value;
4953			this._onChangeCallback();
4954
4955		}
4956
4957	},
4958
4959	order: {
4960
4961		get: function () {
4962
4963			return this._order;
4964
4965		},
4966
4967		set: function ( value ) {
4968
4969			this._order = value;
4970			this._onChangeCallback();
4971
4972		}
4973
4974	}
4975
4976} );
4977
4978Object.assign( Euler.prototype, {
4979
4980	isEuler: true,
4981
4982	set: function ( x, y, z, order ) {
4983
4984		this._x = x;
4985		this._y = y;
4986		this._z = z;
4987		this._order = order || this._order;
4988
4989		this._onChangeCallback();
4990
4991		return this;
4992
4993	},
4994
4995	clone: function () {
4996
4997		return new this.constructor( this._x, this._y, this._z, this._order );
4998
4999	},
5000
5001	copy: function ( euler ) {
5002
5003		this._x = euler._x;
5004		this._y = euler._y;
5005		this._z = euler._z;
5006		this._order = euler._order;
5007
5008		this._onChangeCallback();
5009
5010		return this;
5011
5012	},
5013
5014	setFromRotationMatrix: function ( m, order, update ) {
5015
5016		var clamp = MathUtils.clamp;
5017
5018		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
5019
5020		var te = m.elements;
5021		var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
5022		var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
5023		var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
5024
5025		order = order || this._order;
5026
5027		switch ( order ) {
5028
5029			case 'XYZ':
5030
5031				this._y = Math.asin( clamp( m13, - 1, 1 ) );
5032
5033				if ( Math.abs( m13 ) < 0.9999999 ) {
5034
5035					this._x = Math.atan2( - m23, m33 );
5036					this._z = Math.atan2( - m12, m11 );
5037
5038				} else {
5039
5040					this._x = Math.atan2( m32, m22 );
5041					this._z = 0;
5042
5043				}
5044
5045				break;
5046
5047			case 'YXZ':
5048
5049				this._x = Math.asin( - clamp( m23, - 1, 1 ) );
5050
5051				if ( Math.abs( m23 ) < 0.9999999 ) {
5052
5053					this._y = Math.atan2( m13, m33 );
5054					this._z = Math.atan2( m21, m22 );
5055
5056				} else {
5057
5058					this._y = Math.atan2( - m31, m11 );
5059					this._z = 0;
5060
5061				}
5062
5063				break;
5064
5065			case 'ZXY':
5066
5067				this._x = Math.asin( clamp( m32, - 1, 1 ) );
5068
5069				if ( Math.abs( m32 ) < 0.9999999 ) {
5070
5071					this._y = Math.atan2( - m31, m33 );
5072					this._z = Math.atan2( - m12, m22 );
5073
5074				} else {
5075
5076					this._y = 0;
5077					this._z = Math.atan2( m21, m11 );
5078
5079				}
5080
5081				break;
5082
5083			case 'ZYX':
5084
5085				this._y = Math.asin( - clamp( m31, - 1, 1 ) );
5086
5087				if ( Math.abs( m31 ) < 0.9999999 ) {
5088
5089					this._x = Math.atan2( m32, m33 );
5090					this._z = Math.atan2( m21, m11 );
5091
5092				} else {
5093
5094					this._x = 0;
5095					this._z = Math.atan2( - m12, m22 );
5096
5097				}
5098
5099				break;
5100
5101			case 'YZX':
5102
5103				this._z = Math.asin( clamp( m21, - 1, 1 ) );
5104
5105				if ( Math.abs( m21 ) < 0.9999999 ) {
5106
5107					this._x = Math.atan2( - m23, m22 );
5108					this._y = Math.atan2( - m31, m11 );
5109
5110				} else {
5111
5112					this._x = 0;
5113					this._y = Math.atan2( m13, m33 );
5114
5115				}
5116
5117				break;
5118
5119			case 'XZY':
5120
5121				this._z = Math.asin( - clamp( m12, - 1, 1 ) );
5122
5123				if ( Math.abs( m12 ) < 0.9999999 ) {
5124
5125					this._x = Math.atan2( m32, m22 );
5126					this._y = Math.atan2( m13, m11 );
5127
5128				} else {
5129
5130					this._x = Math.atan2( - m23, m33 );
5131					this._y = 0;
5132
5133				}
5134
5135				break;
5136
5137			default:
5138
5139				console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
5140
5141		}
5142
5143		this._order = order;
5144
5145		if ( update !== false ) this._onChangeCallback();
5146
5147		return this;
5148
5149	},
5150
5151	setFromQuaternion: function ( q, order, update ) {
5152
5153		_matrix.makeRotationFromQuaternion( q );
5154
5155		return this.setFromRotationMatrix( _matrix, order, update );
5156
5157	},
5158
5159	setFromVector3: function ( v, order ) {
5160
5161		return this.set( v.x, v.y, v.z, order || this._order );
5162
5163	},
5164
5165	reorder: function ( newOrder ) {
5166
5167		// WARNING: this discards revolution information -bhouston
5168
5169		_quaternion$1.setFromEuler( this );
5170
5171		return this.setFromQuaternion( _quaternion$1, newOrder );
5172
5173	},
5174
5175	equals: function ( euler ) {
5176
5177		return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
5178
5179	},
5180
5181	fromArray: function ( array ) {
5182
5183		this._x = array[ 0 ];
5184		this._y = array[ 1 ];
5185		this._z = array[ 2 ];
5186		if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
5187
5188		this._onChangeCallback();
5189
5190		return this;
5191
5192	},
5193
5194	toArray: function ( array, offset ) {
5195
5196		if ( array === undefined ) array = [];
5197		if ( offset === undefined ) offset = 0;
5198
5199		array[ offset ] = this._x;
5200		array[ offset + 1 ] = this._y;
5201		array[ offset + 2 ] = this._z;
5202		array[ offset + 3 ] = this._order;
5203
5204		return array;
5205
5206	},
5207
5208	toVector3: function ( optionalResult ) {
5209
5210		if ( optionalResult ) {
5211
5212			return optionalResult.set( this._x, this._y, this._z );
5213
5214		} else {
5215
5216			return new Vector3( this._x, this._y, this._z );
5217
5218		}
5219
5220	},
5221
5222	_onChange: function ( callback ) {
5223
5224		this._onChangeCallback = callback;
5225
5226		return this;
5227
5228	},
5229
5230	_onChangeCallback: function () {}
5231
5232} );
5233
5234/**
5235 * @author mrdoob / http://mrdoob.com/
5236 */
5237
5238function Layers() {
5239
5240	this.mask = 1 | 0;
5241
5242}
5243
5244Object.assign( Layers.prototype, {
5245
5246	set: function ( channel ) {
5247
5248		this.mask = 1 << channel | 0;
5249
5250	},
5251
5252	enable: function ( channel ) {
5253
5254		this.mask |= 1 << channel | 0;
5255
5256	},
5257
5258	enableAll: function () {
5259
5260		this.mask = 0xffffffff | 0;
5261
5262	},
5263
5264	toggle: function ( channel ) {
5265
5266		this.mask ^= 1 << channel | 0;
5267
5268	},
5269
5270	disable: function ( channel ) {
5271
5272		this.mask &= ~ ( 1 << channel | 0 );
5273
5274	},
5275
5276	disableAll: function () {
5277
5278		this.mask = 0;
5279
5280	},
5281
5282	test: function ( layers ) {
5283
5284		return ( this.mask & layers.mask ) !== 0;
5285
5286	}
5287
5288} );
5289
5290var _object3DId = 0;
5291
5292var _v1$1 = new Vector3();
5293var _q1 = new Quaternion();
5294var _m1$1 = new Matrix4();
5295var _target = new Vector3();
5296
5297var _position = new Vector3();
5298var _scale = new Vector3();
5299var _quaternion$2 = new Quaternion();
5300
5301var _xAxis = new Vector3( 1, 0, 0 );
5302var _yAxis = new Vector3( 0, 1, 0 );
5303var _zAxis = new Vector3( 0, 0, 1 );
5304
5305var _addedEvent = { type: 'added' };
5306var _removedEvent = { type: 'removed' };
5307
5308/**
5309 * @author mrdoob / http://mrdoob.com/
5310 * @author mikael emtinger / http://gomo.se/
5311 * @author alteredq / http://alteredqualia.com/
5312 * @author WestLangley / http://github.com/WestLangley
5313 * @author elephantatwork / www.elephantatwork.ch
5314 */
5315
5316function Object3D() {
5317
5318	Object.defineProperty( this, 'id', { value: _object3DId ++ } );
5319
5320	this.uuid = MathUtils.generateUUID();
5321
5322	this.name = '';
5323	this.type = 'Object3D';
5324
5325	this.parent = null;
5326	this.children = [];
5327
5328	this.up = Object3D.DefaultUp.clone();
5329
5330	var position = new Vector3();
5331	var rotation = new Euler();
5332	var quaternion = new Quaternion();
5333	var scale = new Vector3( 1, 1, 1 );
5334
5335	function onRotationChange() {
5336
5337		quaternion.setFromEuler( rotation, false );
5338
5339	}
5340
5341	function onQuaternionChange() {
5342
5343		rotation.setFromQuaternion( quaternion, undefined, false );
5344
5345	}
5346
5347	rotation._onChange( onRotationChange );
5348	quaternion._onChange( onQuaternionChange );
5349
5350	Object.defineProperties( this, {
5351		position: {
5352			configurable: true,
5353			enumerable: true,
5354			value: position
5355		},
5356		rotation: {
5357			configurable: true,
5358			enumerable: true,
5359			value: rotation
5360		},
5361		quaternion: {
5362			configurable: true,
5363			enumerable: true,
5364			value: quaternion
5365		},
5366		scale: {
5367			configurable: true,
5368			enumerable: true,
5369			value: scale
5370		},
5371		modelViewMatrix: {
5372			value: new Matrix4()
5373		},
5374		normalMatrix: {
5375			value: new Matrix3()
5376		}
5377	} );
5378
5379	this.matrix = new Matrix4();
5380	this.matrixWorld = new Matrix4();
5381
5382	this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
5383	this.matrixWorldNeedsUpdate = false;
vendor: 7,965 bytes, lines 5384-5856
5384
5385	this.layers = new Layers();
5386	this.visible = true;
5387
5388	this.castShadow = false;
5389	this.receiveShadow = false;
5390
5391	this.frustumCulled = true;
5392	this.renderOrder = 0;
5393
5394	this.userData = {};
5395
5396}
5397
5398Object3D.DefaultUp = new Vector3( 0, 1, 0 );
5399Object3D.DefaultMatrixAutoUpdate = true;
5400
5401Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
5402
5403	constructor: Object3D,
5404
5405	isObject3D: true,
5406
5407	onBeforeRender: function () {},
5408	onAfterRender: function () {},
5409
5410	applyMatrix4: function ( matrix ) {
5411
5412		if ( this.matrixAutoUpdate ) this.updateMatrix();
5413
5414		this.matrix.premultiply( matrix );
5415
5416		this.matrix.decompose( this.position, this.quaternion, this.scale );
5417
5418	},
5419
5420	applyQuaternion: function ( q ) {
5421
5422		this.quaternion.premultiply( q );
5423
5424		return this;
5425
5426	},
5427
5428	setRotationFromAxisAngle: function ( axis, angle ) {
5429
5430		// assumes axis is normalized
5431
5432		this.quaternion.setFromAxisAngle( axis, angle );
5433
5434	},
5435
5436	setRotationFromEuler: function ( euler ) {
5437
5438		this.quaternion.setFromEuler( euler, true );
5439
5440	},
5441
5442	setRotationFromMatrix: function ( m ) {
5443
5444		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
5445
5446		this.quaternion.setFromRotationMatrix( m );
5447
5448	},
5449
5450	setRotationFromQuaternion: function ( q ) {
5451
5452		// assumes q is normalized
5453
5454		this.quaternion.copy( q );
5455
5456	},
5457
5458	rotateOnAxis: function ( axis, angle ) {
5459
5460		// rotate object on axis in object space
5461		// axis is assumed to be normalized
5462
5463		_q1.setFromAxisAngle( axis, angle );
5464
5465		this.quaternion.multiply( _q1 );
5466
5467		return this;
5468
5469	},
5470
5471	rotateOnWorldAxis: function ( axis, angle ) {
5472
5473		// rotate object on axis in world space
5474		// axis is assumed to be normalized
5475		// method assumes no rotated parent
5476
5477		_q1.setFromAxisAngle( axis, angle );
5478
5479		this.quaternion.premultiply( _q1 );
5480
5481		return this;
5482
5483	},
5484
5485	rotateX: function ( angle ) {
5486
5487		return this.rotateOnAxis( _xAxis, angle );
5488
5489	},
5490
5491	rotateY: function ( angle ) {
5492
5493		return this.rotateOnAxis( _yAxis, angle );
5494
5495	},
5496
5497	rotateZ: function ( angle ) {
5498
5499		return this.rotateOnAxis( _zAxis, angle );
5500
5501	},
5502
5503	translateOnAxis: function ( axis, distance ) {
5504
5505		// translate object by distance along axis in object space
5506		// axis is assumed to be normalized
5507
5508		_v1$1.copy( axis ).applyQuaternion( this.quaternion );
5509
5510		this.position.add( _v1$1.multiplyScalar( distance ) );
5511
5512		return this;
5513
5514	},
5515
5516	translateX: function ( distance ) {
5517
5518		return this.translateOnAxis( _xAxis, distance );
5519
5520	},
5521
5522	translateY: function ( distance ) {
5523
5524		return this.translateOnAxis( _yAxis, distance );
5525
5526	},
5527
5528	translateZ: function ( distance ) {
5529
5530		return this.translateOnAxis( _zAxis, distance );
5531
5532	},
5533
5534	localToWorld: function ( vector ) {
5535
5536		return vector.applyMatrix4( this.matrixWorld );
5537
5538	},
5539
5540	worldToLocal: function ( vector ) {
5541
5542		return vector.applyMatrix4( _m1$1.getInverse( this.matrixWorld ) );
5543
5544	},
5545
5546	lookAt: function ( x, y, z ) {
5547
5548		// This method does not support objects having non-uniformly-scaled parent(s)
5549
5550		if ( x.isVector3 ) {
5551
5552			_target.copy( x );
5553
5554		} else {
5555
5556			_target.set( x, y, z );
5557
5558		}
5559
5560		var parent = this.parent;
5561
5562		this.updateWorldMatrix( true, false );
5563
5564		_position.setFromMatrixPosition( this.matrixWorld );
5565
5566		if ( this.isCamera || this.isLight ) {
5567
5568			_m1$1.lookAt( _position, _target, this.up );
5569
5570		} else {
5571
5572			_m1$1.lookAt( _target, _position, this.up );
5573
5574		}
5575
5576		this.quaternion.setFromRotationMatrix( _m1$1 );
5577
5578		if ( parent ) {
5579
5580			_m1$1.extractRotation( parent.matrixWorld );
5581			_q1.setFromRotationMatrix( _m1$1 );
5582			this.quaternion.premultiply( _q1.inverse() );
5583
5584		}
5585
5586	},
5587
5588	add: function ( object ) {
5589
5590		if ( arguments.length > 1 ) {
5591
5592			for ( var i = 0; i < arguments.length; i ++ ) {
5593
5594				this.add( arguments[ i ] );
5595
5596			}
5597
5598			return this;
5599
5600		}
5601
5602		if ( object === this ) {
5603
5604			console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
5605			return this;
5606
5607		}
5608
5609		if ( ( object && object.isObject3D ) ) {
5610
5611			if ( object.parent !== null ) {
5612
5613				object.parent.remove( object );
5614
5615			}
5616
5617			object.parent = this;
5618			this.children.push( object );
5619
5620			object.dispatchEvent( _addedEvent );
5621
5622		} else {
5623
5624			console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
5625
5626		}
5627
5628		return this;
5629
5630	},
5631
5632	remove: function ( object ) {
5633
5634		if ( arguments.length > 1 ) {
5635
5636			for ( var i = 0; i < arguments.length; i ++ ) {
5637
5638				this.remove( arguments[ i ] );
5639
5640			}
5641
5642			return this;
5643
5644		}
5645
5646		var index = this.children.indexOf( object );
5647
5648		if ( index !== - 1 ) {
5649
5650			object.parent = null;
5651			this.children.splice( index, 1 );
5652
5653			object.dispatchEvent( _removedEvent );
5654
5655		}
5656
5657		return this;
5658
5659	},
5660
5661	attach: function ( object ) {
5662
5663		// adds object as a child of this, while maintaining the object's world transform
5664
5665		this.updateWorldMatrix( true, false );
5666
5667		_m1$1.getInverse( this.matrixWorld );
5668
5669		if ( object.parent !== null ) {
5670
5671			object.parent.updateWorldMatrix( true, false );
5672
5673			_m1$1.multiply( object.parent.matrixWorld );
5674
5675		}
5676
5677		object.applyMatrix4( _m1$1 );
5678
5679		object.updateWorldMatrix( false, false );
5680
5681		this.add( object );
5682
5683		return this;
5684
5685	},
5686
5687	getObjectById: function ( id ) {
5688
5689		return this.getObjectByProperty( 'id', id );
5690
5691	},
5692
5693	getObjectByName: function ( name ) {
5694
5695		return this.getObjectByProperty( 'name', name );
5696
5697	},
5698
5699	getObjectByProperty: function ( name, value ) {
5700
5701		if ( this[ name ] === value ) return this;
5702
5703		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
5704
5705			var child = this.children[ i ];
5706			var object = child.getObjectByProperty( name, value );
5707
5708			if ( object !== undefined ) {
5709
5710				return object;
5711
5712			}
5713
5714		}
5715
5716		return undefined;
5717
5718	},
5719
5720	getWorldPosition: function ( target ) {
5721
5722		if ( target === undefined ) {
5723
5724			console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );
5725			target = new Vector3();
5726
5727		}
5728
5729		this.updateMatrixWorld( true );
5730
5731		return target.setFromMatrixPosition( this.matrixWorld );
5732
5733	},
5734
5735	getWorldQuaternion: function ( target ) {
5736
5737		if ( target === undefined ) {
5738
5739			console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );
5740			target = new Quaternion();
5741
5742		}
5743
5744		this.updateMatrixWorld( true );
5745
5746		this.matrixWorld.decompose( _position, target, _scale );
5747
5748		return target;
5749
5750	},
5751
5752	getWorldScale: function ( target ) {
5753
5754		if ( target === undefined ) {
5755
5756			console.warn( 'THREE.Object3D: .getWorldScale() target is now required' );
5757			target = new Vector3();
5758
5759		}
5760
5761		this.updateMatrixWorld( true );
5762
5763		this.matrixWorld.decompose( _position, _quaternion$2, target );
5764
5765		return target;
5766
5767	},
5768
5769	getWorldDirection: function ( target ) {
5770
5771		if ( target === undefined ) {
5772
5773			console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );
5774			target = new Vector3();
5775
5776		}
5777
5778		this.updateMatrixWorld( true );
5779
5780		var e = this.matrixWorld.elements;
5781
5782		return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
5783
5784	},
5785
5786	raycast: function () {},
5787
5788	traverse: function ( callback ) {
5789
5790		callback( this );
5791
5792		var children = this.children;
5793
5794		for ( var i = 0, l = children.length; i < l; i ++ ) {
5795
5796			children[ i ].traverse( callback );
5797
5798		}
5799
5800	},
5801
5802	traverseVisible: function ( callback ) {
5803
5804		if ( this.visible === false ) return;
5805
5806		callback( this );
5807
5808		var children = this.children;
5809
5810		for ( var i = 0, l = children.length; i < l; i ++ ) {
5811
5812			children[ i ].traverseVisible( callback );
5813
5814		}
5815
5816	},
5817
5818	traverseAncestors: function ( callback ) {
5819
5820		var parent = this.parent;
5821
5822		if ( parent !== null ) {
5823
5824			callback( parent );
5825
5826			parent.traverseAncestors( callback );
5827
5828		}
5829
5830	},
5831
5832	updateMatrix: function () {
5833
5834		this.matrix.compose( this.position, this.quaternion, this.scale );
5835
5836		this.matrixWorldNeedsUpdate = true;
5837
5838	},
5839
5840	updateMatrixWorld: function ( force ) {
5841
5842		if ( this.matrixAutoUpdate ) this.updateMatrix();
5843
5844		if ( this.matrixWorldNeedsUpdate || force ) {
5845
5846			if ( this.parent === null ) {
5847
5848				this.matrixWorld.copy( this.matrix );
5849
5850			} else {
5851
5852				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
5853
5854			}
5855
5856			this.matrixWorldNeedsUpdate = false;
vendor: 6,160 bytes, lines 5857-6170
5857
5858			force = true;
5859
5860		}
5861
5862		// update children
5863
5864		var children = this.children;
5865
5866		for ( var i = 0, l = children.length; i < l; i ++ ) {
5867
5868			children[ i ].updateMatrixWorld( force );
5869
5870		}
5871
5872	},
5873
5874	updateWorldMatrix: function ( updateParents, updateChildren ) {
5875
5876		var parent = this.parent;
5877
5878		if ( updateParents === true && parent !== null ) {
5879
5880			parent.updateWorldMatrix( true, false );
5881
5882		}
5883
5884		if ( this.matrixAutoUpdate ) this.updateMatrix();
5885
5886		if ( this.parent === null ) {
5887
5888			this.matrixWorld.copy( this.matrix );
5889
5890		} else {
5891
5892			this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
5893
5894		}
5895
5896		// update children
5897
5898		if ( updateChildren === true ) {
5899
5900			var children = this.children;
5901
5902			for ( var i = 0, l = children.length; i < l; i ++ ) {
5903
5904				children[ i ].updateWorldMatrix( false, true );
5905
5906			}
5907
5908		}
5909
5910	},
5911
5912	toJSON: function ( meta ) {
5913
5914		// meta is a string when called from JSON.stringify
5915		var isRootObject = ( meta === undefined || typeof meta === 'string' );
5916
5917		var output = {};
5918
5919		// meta is a hash used to collect geometries, materials.
5920		// not providing it implies that this is the root object
5921		// being serialized.
5922		if ( isRootObject ) {
5923
5924			// initialize meta obj
5925			meta = {
5926				geometries: {},
5927				materials: {},
5928				textures: {},
5929				images: {},
5930				shapes: {}
5931			};
5932
5933			output.metadata = {
5934				version: 4.5,
5935				type: 'Object',
5936				generator: 'Object3D.toJSON'
5937			};
5938
5939		}
5940
5941		// standard Object3D serialization
5942
5943		var object = {};
5944
5945		object.uuid = this.uuid;
5946		object.type = this.type;
5947
5948		if ( this.name !== '' ) object.name = this.name;
5949		if ( this.castShadow === true ) object.castShadow = true;
5950		if ( this.receiveShadow === true ) object.receiveShadow = true;
5951		if ( this.visible === false ) object.visible = false;
5952		if ( this.frustumCulled === false ) object.frustumCulled = false;
5953		if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
5954		if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
5955
5956		object.layers = this.layers.mask;
5957		object.matrix = this.matrix.toArray();
5958
5959		if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
5960
5961		// object specific properties
5962
5963		if ( this.isInstancedMesh ) {
5964
5965			object.type = 'InstancedMesh';
5966			object.count = this.count;
5967			object.instanceMatrix = this.instanceMatrix.toJSON();
5968
5969		}
5970
5971		//
5972
5973		function serialize( library, element ) {
5974
5975			if ( library[ element.uuid ] === undefined ) {
5976
5977				library[ element.uuid ] = element.toJSON( meta );
5978
5979			}
5980
5981			return element.uuid;
5982
5983		}
5984
5985		if ( this.isMesh || this.isLine || this.isPoints ) {
5986
5987			object.geometry = serialize( meta.geometries, this.geometry );
5988
5989			var parameters = this.geometry.parameters;
5990
5991			if ( parameters !== undefined && parameters.shapes !== undefined ) {
5992
5993				var shapes = parameters.shapes;
5994
5995				if ( Array.isArray( shapes ) ) {
5996
5997					for ( var i = 0, l = shapes.length; i < l; i ++ ) {
5998
5999						var shape = shapes[ i ];
6000
6001						serialize( meta.shapes, shape );
6002
6003					}
6004
6005				} else {
6006
6007					serialize( meta.shapes, shapes );
6008
6009				}
6010
6011			}
6012
6013		}
6014
6015		if ( this.material !== undefined ) {
6016
6017			if ( Array.isArray( this.material ) ) {
6018
6019				var uuids = [];
6020
6021				for ( var i = 0, l = this.material.length; i < l; i ++ ) {
6022
6023					uuids.push( serialize( meta.materials, this.material[ i ] ) );
6024
6025				}
6026
6027				object.material = uuids;
6028
6029			} else {
6030
6031				object.material = serialize( meta.materials, this.material );
6032
6033			}
6034
6035		}
6036
6037		//
6038
6039		if ( this.children.length > 0 ) {
6040
6041			object.children = [];
6042
6043			for ( var i = 0; i < this.children.length; i ++ ) {
6044
6045				object.children.push( this.children[ i ].toJSON( meta ).object );
6046
6047			}
6048
6049		}
6050
6051		if ( isRootObject ) {
6052
6053			var geometries = extractFromCache( meta.geometries );
6054			var materials = extractFromCache( meta.materials );
6055			var textures = extractFromCache( meta.textures );
6056			var images = extractFromCache( meta.images );
6057			var shapes = extractFromCache( meta.shapes );
6058
6059			if ( geometries.length > 0 ) output.geometries = geometries;
6060			if ( materials.length > 0 ) output.materials = materials;
6061			if ( textures.length > 0 ) output.textures = textures;
6062			if ( images.length > 0 ) output.images = images;
6063			if ( shapes.length > 0 ) output.shapes = shapes;
6064
6065		}
6066
6067		output.object = object;
6068
6069		return output;
6070
6071		// extract data from the cache hash
6072		// remove metadata on each item
6073		// and return as array
6074		function extractFromCache( cache ) {
6075
6076			var values = [];
6077			for ( var key in cache ) {
6078
6079				var data = cache[ key ];
6080				delete data.metadata;
6081				values.push( data );
6082
6083			}
6084
6085			return values;
6086
6087		}
6088
6089	},
6090
6091	clone: function ( recursive ) {
6092
6093		return new this.constructor().copy( this, recursive );
6094
6095	},
6096
6097	copy: function ( source, recursive ) {
6098
6099		if ( recursive === undefined ) recursive = true;
6100
6101		this.name = source.name;
6102
6103		this.up.copy( source.up );
6104
6105		this.position.copy( source.position );
6106		this.quaternion.copy( source.quaternion );
6107		this.scale.copy( source.scale );
6108
6109		this.matrix.copy( source.matrix );
6110		this.matrixWorld.copy( source.matrixWorld );
6111
6112		this.matrixAutoUpdate = source.matrixAutoUpdate;
6113		this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
6114
6115		this.layers.mask = source.layers.mask;
6116		this.visible = source.visible;
6117
6118		this.castShadow = source.castShadow;
6119		this.receiveShadow = source.receiveShadow;
6120
6121		this.frustumCulled = source.frustumCulled;
6122		this.renderOrder = source.renderOrder;
6123
6124		this.userData = JSON.parse( JSON.stringify( source.userData ) );
6125
6126		if ( recursive === true ) {
6127
6128			for ( var i = 0; i < source.children.length; i ++ ) {
6129
6130				var child = source.children[ i ];
6131				this.add( child.clone() );
6132
6133			}
6134
6135		}
6136
6137		return this;
6138
6139	}
6140
6141} );
6142
6143/**
6144 * @author mrdoob / http://mrdoob.com/
6145 */
6146
6147function Scene() {
6148
6149	Object3D.call( this );
6150
6151	this.type = 'Scene';
6152
6153	this.background = null;
6154	this.environment = null;
6155	this.fog = null;
6156
6157	this.overrideMaterial = null;
6158
6159	this.autoUpdate = true; // checked by the renderer
6160
6161	if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
6162
6163		__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
6164
6165	}
6166
6167}
6168
6169Scene.prototype = Object.assign( Object.create( Object3D.prototype ), {
6170
6171	constructor: Scene,
6172
6173	isScene: true,
6174
6175	copy: function ( source, recursive ) {
6176
6177		Object3D.prototype.copy.call( this, source, recursive );
6178
6179		if ( source.background !== null ) this.background = source.background.clone();
6180		if ( source.environment !== null ) this.environment = source.environment.clone();
6181		if ( source.fog !== null ) this.fog = source.fog.clone();
6182
6183		if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
6184
6185		this.autoUpdate = source.autoUpdate;
6186		this.matrixAutoUpdate = source.matrixAutoUpdate;
6187
6188		return this;
6189
6190	},
6191
6192	toJSON: function ( meta ) {
6193
6194		var data = Object3D.prototype.toJSON.call( this, meta );
6195
6196		if ( this.background !== null ) data.object.background = this.background.toJSON( meta );
6197		if ( this.environment !== null ) data.object.environment = this.environment.toJSON( meta );
6198		if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
6199
6200		return data;
6201
6202	},
6203
6204	dispose: function () {
6205
6206		this.dispatchEvent( { type: 'dispose' } );
6207
6208	}
6209
6210} );
6211
6212var _points = [
6213	new Vector3(),
6214	new Vector3(),
6215	new Vector3(),
6216	new Vector3(),
6217	new Vector3(),
6218	new Vector3(),
6219	new Vector3(),
6220	new Vector3()
6221];
6222
6223var _vector$1 = new Vector3();
6224
6225var _box = new Box3();
6226
6227// triangle centered vertices
6228
6229var _v0 = new Vector3();
6230var _v1$2 = new Vector3();
6231var _v2 = new Vector3();
6232
6233// triangle edge vectors
6234
6235var _f0 = new Vector3();
6236var _f1 = new Vector3();
6237var _f2 = new Vector3();
6238
6239var _center = new Vector3();
6240var _extents = new Vector3();
6241var _triangleNormal = new Vector3();
6242var _testAxis = new Vector3();
6243
6244/**
6245 * @author bhouston / http://clara.io
6246 * @author WestLangley / http://github.com/WestLangley
6247 */
6248
6249function Box3( min, max ) {
6250
6251	this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );
6252	this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );
6253
6254}
6255
6256
6257Object.assign( Box3.prototype, {
6258
6259	isBox3: true,
6260
6261	set: function ( min, max ) {
6262
6263		this.min.copy( min );
6264		this.max.copy( max );
6265
6266		return this;
6267
6268	},
6269
6270	setFromArray: function ( array ) {
6271
6272		var minX = + Infinity;
6273		var minY = + Infinity;
6274		var minZ = + Infinity;
6275
6276		var maxX = - Infinity;
6277		var maxY = - Infinity;
6278		var maxZ = - Infinity;
6279
6280		for ( var i = 0, l = array.length; i < l; i += 3 ) {
6281
6282			var x = array[ i ];
6283			var y = array[ i + 1 ];
6284			var z = array[ i + 2 ];
6285
6286			if ( x < minX ) minX = x;
6287			if ( y < minY ) minY = y;
6288			if ( z < minZ ) minZ = z;
6289
6290			if ( x > maxX ) maxX = x;
6291			if ( y > maxY ) maxY = y;
6292			if ( z > maxZ ) maxZ = z;
6293
6294		}
6295
6296		this.min.set( minX, minY, minZ );
6297		this.max.set( maxX, maxY, maxZ );
6298
6299		return this;
6300
6301	},
6302
6303	setFromBufferAttribute: function ( attribute ) {
6304
6305		var minX = + Infinity;
6306		var minY = + Infinity;
6307		var minZ = + Infinity;
6308
6309		var maxX = - Infinity;
6310		var maxY = - Infinity;
6311		var maxZ = - Infinity;
6312
6313		for ( var i = 0, l = attribute.count; i < l; i ++ ) {
6314
6315			var x = attribute.getX( i );
6316			var y = attribute.getY( i );
6317			var z = attribute.getZ( i );
6318
6319			if ( x < minX ) minX = x;
6320			if ( y < minY ) minY = y;
6321			if ( z < minZ ) minZ = z;
6322
6323			if ( x > maxX ) maxX = x;
6324			if ( y > maxY ) maxY = y;
6325			if ( z > maxZ ) maxZ = z;
6326
6327		}
6328
6329		this.min.set( minX, minY, minZ );
6330		this.max.set( maxX, maxY, maxZ );
6331
6332		return this;
6333
6334	},
6335
6336	setFromPoints: function ( points ) {
6337
6338		this.makeEmpty();
6339
6340		for ( var i = 0, il = points.length; i < il; i ++ ) {
6341
6342			this.expandByPoint( points[ i ] );
6343
6344		}
6345
6346		return this;
6347
6348	},
6349
6350	setFromCenterAndSize: function ( center, size ) {
6351
6352		var halfSize = _vector$1.copy( size ).multiplyScalar( 0.5 );
6353
6354		this.min.copy( center ).sub( halfSize );
6355		this.max.copy( center ).add( halfSize );
6356
6357		return this;
6358
6359	},
6360
6361	setFromObject: function ( object ) {
6362
6363		this.makeEmpty();
6364
6365		return this.expandByObject( object );
6366
6367	},
6368
6369	clone: function () {
6370
6371		return new this.constructor().copy( this );
6372
6373	},
6374
6375	copy: function ( box ) {
6376
6377		this.min.copy( box.min );
6378		this.max.copy( box.max );
6379
6380		return this;
6381
6382	},
6383
6384	makeEmpty: function () {
6385
6386		this.min.x = this.min.y = this.min.z = + Infinity;
6387		this.max.x = this.max.y = this.max.z = - Infinity;
6388
6389		return this;
6390
6391	},
6392
6393	isEmpty: function () {
6394
6395		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
6396
6397		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
6398
6399	},
6400
6401	getCenter: function ( target ) {
6402
6403		if ( target === undefined ) {
6404
6405			console.warn( 'THREE.Box3: .getCenter() target is now required' );
6406			target = new Vector3();
6407
6408		}
6409
6410		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
6411
6412	},
6413
6414	getSize: function ( target ) {
6415
6416		if ( target === undefined ) {
6417
6418			console.warn( 'THREE.Box3: .getSize() target is now required' );
6419			target = new Vector3();
6420
6421		}
6422
6423		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
6424
6425	},
6426
6427	expandByPoint: function ( point ) {
6428
6429		this.min.min( point );
6430		this.max.max( point );
6431
6432		return this;
6433
6434	},
6435
6436	expandByVector: function ( vector ) {
6437
6438		this.min.sub( vector );
6439		this.max.add( vector );
6440
6441		return this;
6442
6443	},
6444
6445	expandByScalar: function ( scalar ) {
6446
6447		this.min.addScalar( - scalar );
6448		this.max.addScalar( scalar );
6449
6450		return this;
6451
6452	},
6453
6454	expandByObject: function ( object ) {
6455
6456		// Computes the world-axis-aligned bounding box of an object (including its children),
6457		// accounting for both the object's, and children's, world transforms
6458
6459		object.updateWorldMatrix( false, false );
6460
6461		var geometry = object.geometry;
6462
6463		if ( geometry !== undefined ) {
6464
6465			if ( geometry.boundingBox === null ) {
6466
6467				geometry.computeBoundingBox();
6468
6469			}
6470
6471			_box.copy( geometry.boundingBox );
6472			_box.applyMatrix4( object.matrixWorld );
6473
6474			this.union( _box );
6475
6476		}
6477
6478		var children = object.children;
6479
6480		for ( var i = 0, l = children.length; i < l; i ++ ) {
6481
6482			this.expandByObject( children[ i ] );
6483
6484		}
6485
6486		return this;
6487
6488	},
6489
6490	containsPoint: function ( point ) {
6491
6492		return point.x < this.min.x || point.x > this.max.x ||
6493			point.y < this.min.y || point.y > this.max.y ||
6494			point.z < this.min.z || point.z > this.max.z ? false : true;
6495
6496	},
6497
6498	containsBox: function ( box ) {
6499
6500		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
6501			this.min.y <= box.min.y && box.max.y <= this.max.y &&
6502			this.min.z <= box.min.z && box.max.z <= this.max.z;
6503
6504	},
6505
6506	getParameter: function ( point, target ) {
6507
6508		// This can potentially have a divide by zero if the box
6509		// has a size dimension of 0.
6510
6511		if ( target === undefined ) {
6512
6513			console.warn( 'THREE.Box3: .getParameter() target is now required' );
6514			target = new Vector3();
6515
6516		}
6517
6518		return target.set(
6519			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
6520			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
6521			( point.z - this.min.z ) / ( this.max.z - this.min.z )
6522		);
6523
6524	},
6525
6526	intersectsBox: function ( box ) {
6527
6528		// using 6 splitting planes to rule out intersections.
6529		return box.max.x < this.min.x || box.min.x > this.max.x ||
6530			box.max.y < this.min.y || box.min.y > this.max.y ||
6531			box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
6532
6533	},
6534
6535	intersectsSphere: function ( sphere ) {
6536
6537		// Find the point on the AABB closest to the sphere center.
6538		this.clampPoint( sphere.center, _vector$1 );
6539
6540		// If that point is inside the sphere, the AABB and sphere intersect.
6541		return _vector$1.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
6542
6543	},
6544
6545	intersectsPlane: function ( plane ) {
6546
6547		// We compute the minimum and maximum dot product values. If those values
6548		// are on the same side (back or front) of the plane, then there is no intersection.
6549
6550		var min, max;
6551
6552		if ( plane.normal.x > 0 ) {
6553
6554			min = plane.normal.x * this.min.x;
6555			max = plane.normal.x * this.max.x;
6556
6557		} else {
6558
6559			min = plane.normal.x * this.max.x;
6560			max = plane.normal.x * this.min.x;
6561
6562		}
6563
6564		if ( plane.normal.y > 0 ) {
6565
6566			min += plane.normal.y * this.min.y;
6567			max += plane.normal.y * this.max.y;
6568
6569		} else {
6570
6571			min += plane.normal.y * this.max.y;
6572			max += plane.normal.y * this.min.y;
6573
6574		}
6575
6576		if ( plane.normal.z > 0 ) {
6577
6578			min += plane.normal.z * this.min.z;
6579			max += plane.normal.z * this.max.z;
6580
6581		} else {
6582
6583			min += plane.normal.z * this.max.z;
6584			max += plane.normal.z * this.min.z;
6585
6586		}
6587
6588		return ( min <= - plane.constant && max >= - plane.constant );
6589
6590	},
6591
6592	intersectsTriangle: function ( triangle ) {
6593
6594		if ( this.isEmpty() ) {
6595
6596			return false;
6597
6598		}
6599
6600		// compute box center and extents
6601		this.getCenter( _center );
6602		_extents.subVectors( this.max, _center );
6603
6604		// translate triangle to aabb origin
6605		_v0.subVectors( triangle.a, _center );
6606		_v1$2.subVectors( triangle.b, _center );
6607		_v2.subVectors( triangle.c, _center );
6608
6609		// compute edge vectors for triangle
6610		_f0.subVectors( _v1$2, _v0 );
6611		_f1.subVectors( _v2, _v1$2 );
6612		_f2.subVectors( _v0, _v2 );
6613
6614		// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
6615		// make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation
6616		// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
6617		var axes = [
6618			0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
6619			_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
6620			- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
6621		];
6622		if ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {
6623
6624			return false;
6625
6626		}
6627
6628		// test 3 face normals from the aabb
6629		axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
6630		if ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {
6631
6632			return false;
6633
6634		}
6635
6636		// finally testing the face normal of the triangle
6637		// use already existing triangle edge vectors here
6638		_triangleNormal.crossVectors( _f0, _f1 );
6639		axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
6640
6641		return satForAxes( axes, _v0, _v1$2, _v2, _extents );
6642
6643	},
6644
6645	clampPoint: function ( point, target ) {
6646
6647		if ( target === undefined ) {
6648
6649			console.warn( 'THREE.Box3: .clampPoint() target is now required' );
6650			target = new Vector3();
6651
6652		}
6653
6654		return target.copy( point ).clamp( this.min, this.max );
6655
6656	},
6657
6658	distanceToPoint: function ( point ) {
6659
6660		var clampedPoint = _vector$1.copy( point ).clamp( this.min, this.max );
6661
6662		return clampedPoint.sub( point ).length();
6663
6664	},
6665
6666	getBoundingSphere: function ( target ) {
6667
6668		if ( target === undefined ) {
6669
6670			console.error( 'THREE.Box3: .getBoundingSphere() target is now required' );
6671			//target = new Sphere(); // removed to avoid cyclic dependency
6672
6673		}
6674
6675		this.getCenter( target.center );
6676
6677		target.radius = this.getSize( _vector$1 ).length() * 0.5;
6678
6679		return target;
6680
6681	},
6682
6683	intersect: function ( box ) {
6684
6685		this.min.max( box.min );
6686		this.max.min( box.max );
6687
6688		// 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.
6689		if ( this.isEmpty() ) this.makeEmpty();
6690
6691		return this;
6692
6693	},
6694
6695	union: function ( box ) {
6696
6697		this.min.min( box.min );
6698		this.max.max( box.max );
6699
6700		return this;
6701
6702	},
6703
6704	applyMatrix4: function ( matrix ) {
6705
6706		// transform of empty box is an empty box.
6707		if ( this.isEmpty() ) return this;
6708
6709		// NOTE: I am using a binary pattern to specify all 2^3 combinations below
6710		_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
6711		_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
6712		_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
6713		_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
6714		_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
6715		_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
6716		_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
6717		_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
6718
6719		this.setFromPoints( _points );
6720
6721		return this;
6722
6723	},
6724
6725	translate: function ( offset ) {
6726
6727		this.min.add( offset );
6728		this.max.add( offset );
6729
6730		return this;
6731
6732	},
6733
6734	equals: function ( box ) {
6735
6736		return box.min.equals( this.min ) && box.max.equals( this.max );
6737
6738	}
6739
6740} );
6741
6742function satForAxes( axes, v0, v1, v2, extents ) {
6743
6744	var i, j;
6745
6746	for ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {
6747
6748		_testAxis.fromArray( axes, i );
6749		// project the aabb onto the seperating axis
6750		var r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
6751		// project all 3 vertices of the triangle onto the seperating axis
6752		var p0 = v0.dot( _testAxis );
6753		var p1 = v1.dot( _testAxis );
6754		var p2 = v2.dot( _testAxis );
6755		// actual test, basically see if either of the most extreme of the triangle points intersects r
6756		if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
6757
6758			// points of the projected triangle are outside the projected half-length of the aabb
6759			// the axis is seperating and we can exit
6760			return false;
6761
6762		}
6763
6764	}
6765
6766	return true;
6767
6768}
6769
6770var _box$1 = new Box3();
6771
6772/**
6773 * @author bhouston / http://clara.io
6774 * @author mrdoob / http://mrdoob.com/
6775 */
6776
6777function Sphere( center, radius ) {
6778
6779	this.center = ( center !== undefined ) ? center : new Vector3();
6780	this.radius = ( radius !== undefined ) ? radius : - 1;
6781
6782}
6783
6784Object.assign( Sphere.prototype, {
6785
6786	set: function ( center, radius ) {
6787
6788		this.center.copy( center );
6789		this.radius = radius;
6790
6791		return this;
6792
6793	},
6794
6795	setFromPoints: function ( points, optionalCenter ) {
6796
6797		var center = this.center;
6798
6799		if ( optionalCenter !== undefined ) {
6800
6801			center.copy( optionalCenter );
6802
6803		} else {
6804
6805			_box$1.setFromPoints( points ).getCenter( center );
6806
6807		}
6808
6809		var maxRadiusSq = 0;
6810
6811		for ( var i = 0, il = points.length; i < il; i ++ ) {
6812
6813			maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
6814
6815		}
6816
6817		this.radius = Math.sqrt( maxRadiusSq );
6818
6819		return this;
6820
6821	},
6822
6823	clone: function () {
6824
6825		return new this.constructor().copy( this );
6826
6827	},
6828
6829	copy: function ( sphere ) {
6830
6831		this.center.copy( sphere.center );
6832		this.radius = sphere.radius;
6833
6834		return this;
6835
6836	},
6837
6838	isEmpty: function () {
6839
6840		return ( this.radius < 0 );
6841
6842	},
6843
6844	makeEmpty: function () {
6845
6846		this.center.set( 0, 0, 0 );
6847		this.radius = - 1;
6848
6849		return this;
6850
6851	},
6852
6853	containsPoint: function ( point ) {
6854
6855		return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
6856
6857	},
6858
6859	distanceToPoint: function ( point ) {
6860
6861		return ( point.distanceTo( this.center ) - this.radius );
6862
6863	},
6864
6865	intersectsSphere: function ( sphere ) {
6866
6867		var radiusSum = this.radius + sphere.radius;
6868
6869		return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
6870
6871	},
6872
6873	intersectsBox: function ( box ) {
6874
6875		return box.intersectsSphere( this );
6876
6877	},
6878
6879	intersectsPlane: function ( plane ) {
6880
6881		return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
6882
6883	},
6884
6885	clampPoint: function ( point, target ) {
6886
6887		var deltaLengthSq = this.center.distanceToSquared( point );
6888
6889		if ( target === undefined ) {
6890
6891			console.warn( 'THREE.Sphere: .clampPoint() target is now required' );
6892			target = new Vector3();
6893
6894		}
6895
6896		target.copy( point );
6897
6898		if ( deltaLengthSq > ( this.radius * this.radius ) ) {
6899
6900			target.sub( this.center ).normalize();
6901			target.multiplyScalar( this.radius ).add( this.center );
6902
6903		}
6904
6905		return target;
6906
6907	},
6908
6909	getBoundingBox: function ( target ) {
6910
6911		if ( target === undefined ) {
6912
6913			console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );
6914			target = new Box3();
6915
6916		}
6917
6918		if ( this.isEmpty() ) {
6919
6920			// Empty sphere produces empty bounding box
6921			target.makeEmpty();
6922			return target;
6923
6924		}
6925
6926		target.set( this.center, this.center );
6927		target.expandByScalar( this.radius );
6928
6929		return target;
6930
6931	},
6932
6933	applyMatrix4: function ( matrix ) {
6934
6935		this.center.applyMatrix4( matrix );
6936		this.radius = this.radius * matrix.getMaxScaleOnAxis();
6937
6938		return this;
6939
6940	},
6941
6942	translate: function ( offset ) {
6943
6944		this.center.add( offset );
6945
6946		return this;
6947
6948	},
6949
6950	equals: function ( sphere ) {
6951
6952		return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
6953
6954	}
6955
6956} );
6957
6958var _vector$2 = new Vector3();
6959var _segCenter = new Vector3();
6960var _segDir = new Vector3();
6961var _diff = new Vector3();
6962
6963var _edge1 = new Vector3();
6964var _edge2 = new Vector3();
6965var _normal = new Vector3();
6966
6967/**
6968 * @author bhouston / http://clara.io
6969 */
6970
6971function Ray( origin, direction ) {
6972
6973	this.origin = ( origin !== undefined ) ? origin : new Vector3();
6974	this.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );
6975
6976}
6977
6978Object.assign( Ray.prototype, {
6979
6980	set: function ( origin, direction ) {
6981
6982		this.origin.copy( origin );
6983		this.direction.copy( direction );
6984
6985		return this;
6986
6987	},
6988
6989	clone: function () {
6990
6991		return new this.constructor().copy( this );
6992
6993	},
6994
6995	copy: function ( ray ) {
6996
6997		this.origin.copy( ray.origin );
6998		this.direction.copy( ray.direction );
6999
7000		return this;
7001
7002	},
7003
7004	at: function ( t, target ) {
7005
7006		if ( target === undefined ) {
7007
7008			console.warn( 'THREE.Ray: .at() target is now required' );
7009			target = new Vector3();
7010
7011		}
7012
7013		return target.copy( this.direction ).multiplyScalar( t ).add( this.origin );
7014
7015	},
7016
7017	lookAt: function ( v ) {
7018
7019		this.direction.copy( v ).sub( this.origin ).normalize();
7020
7021		return this;
7022
7023	},
7024
7025	recast: function ( t ) {
7026
7027		this.origin.copy( this.at( t, _vector$2 ) );
7028
7029		return this;
7030
7031	},
7032
7033	closestPointToPoint: function ( point, target ) {
7034
7035		if ( target === undefined ) {
7036
7037			console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );
7038			target = new Vector3();
7039
7040		}
7041
7042		target.subVectors( point, this.origin );
7043
7044		var directionDistance = target.dot( this.direction );
7045
7046		if ( directionDistance < 0 ) {
7047
7048			return target.copy( this.origin );
7049
7050		}
7051
7052		return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
7053
7054	},
7055
7056	distanceToPoint: function ( point ) {
7057
7058		return Math.sqrt( this.distanceSqToPoint( point ) );
7059
7060	},
7061
7062	distanceSqToPoint: function ( point ) {
7063
7064		var directionDistance = _vector$2.subVectors( point, this.origin ).dot( this.direction );
7065
7066		// point behind the ray
7067
7068		if ( directionDistance < 0 ) {
7069
7070			return this.origin.distanceToSquared( point );
7071
7072		}
7073
7074		_vector$2.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
7075
7076		return _vector$2.distanceToSquared( point );
7077
7078	},
7079
7080	distanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
7081
7082		// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h
7083		// It returns the min distance between the ray and the segment
7084		// defined by v0 and v1
7085		// It can also set two optional targets :
7086		// - The closest point on the ray
7087		// - The closest point on the segment
7088
7089		_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
7090		_segDir.copy( v1 ).sub( v0 ).normalize();
7091		_diff.copy( this.origin ).sub( _segCenter );
7092
7093		var segExtent = v0.distanceTo( v1 ) * 0.5;
7094		var a01 = - this.direction.dot( _segDir );
7095		var b0 = _diff.dot( this.direction );
7096		var b1 = - _diff.dot( _segDir );
7097		var c = _diff.lengthSq();
7098		var det = Math.abs( 1 - a01 * a01 );
7099		var s0, s1, sqrDist, extDet;
7100
7101		if ( det > 0 ) {
7102
7103			// The ray and segment are not parallel.
7104
7105			s0 = a01 * b1 - b0;
7106			s1 = a01 * b0 - b1;
7107			extDet = segExtent * det;
7108
7109			if ( s0 >= 0 ) {
7110
7111				if ( s1 >= - extDet ) {
7112
7113					if ( s1 <= extDet ) {
7114
7115						// region 0
7116						// Minimum at interior points of ray and segment.
7117
7118						var invDet = 1 / det;
7119						s0 *= invDet;
7120						s1 *= invDet;
7121						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
7122
7123					} else {
7124
7125						// region 1
7126
7127						s1 = segExtent;
7128						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
7129						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7130
7131					}
7132
7133				} else {
7134
7135					// region 5
7136
7137					s1 = - segExtent;
7138					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
7139					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7140
7141				}
7142
7143			} else {
7144
7145				if ( s1 <= - extDet ) {
7146
7147					// region 4
7148
7149					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
7150					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
7151					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7152
7153				} else if ( s1 <= extDet ) {
7154
7155					// region 3
7156
7157					s0 = 0;
7158					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
7159					sqrDist = s1 * ( s1 + 2 * b1 ) + c;
7160
7161				} else {
7162
7163					// region 2
7164
7165					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
7166					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
7167					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7168
7169				}
7170
7171			}
7172
7173		} else {
7174
7175			// Ray and segment are parallel.
7176
7177			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
7178			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
7179			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
7180
7181		}
7182
7183		if ( optionalPointOnRay ) {
7184
7185			optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );
7186
7187		}
7188
7189		if ( optionalPointOnSegment ) {
7190
7191			optionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );
7192
7193		}
7194
7195		return sqrDist;
7196
7197	},
7198
7199	intersectSphere: function ( sphere, target ) {
7200
7201		_vector$2.subVectors( sphere.center, this.origin );
7202		var tca = _vector$2.dot( this.direction );
7203		var d2 = _vector$2.dot( _vector$2 ) - tca * tca;
7204		var radius2 = sphere.radius * sphere.radius;
7205
7206		if ( d2 > radius2 ) return null;
7207
7208		var thc = Math.sqrt( radius2 - d2 );
7209
7210		// t0 = first intersect point - entrance on front of sphere
7211		var t0 = tca - thc;
7212
7213		// t1 = second intersect point - exit point on back of sphere
7214		var t1 = tca + thc;
7215
7216		// test to see if both t0 and t1 are behind the ray - if so, return null
7217		if ( t0 < 0 && t1 < 0 ) return null;
7218
7219		// test to see if t0 is behind the ray:
7220		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
7221		// in order to always return an intersect point that is in front of the ray.
vendor: 4,311 bytes, lines 7222-7437
7222		if ( t0 < 0 ) return this.at( t1, target );
7223
7224		// else t0 is in front of the ray, so return the first collision point scaled by t0
7225		return this.at( t0, target );
7226
7227	},
7228
7229	intersectsSphere: function ( sphere ) {
7230
7231		return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
7232
7233	},
7234
7235	distanceToPlane: function ( plane ) {
7236
7237		var denominator = plane.normal.dot( this.direction );
7238
7239		if ( denominator === 0 ) {
7240
7241			// line is coplanar, return origin
7242			if ( plane.distanceToPoint( this.origin ) === 0 ) {
7243
7244				return 0;
7245
7246			}
7247
7248			// Null is preferable to undefined since undefined means.... it is undefined
7249
7250			return null;
7251
7252		}
7253
7254		var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
7255
7256		// Return if the ray never intersects the plane
7257
7258		return t >= 0 ? t : null;
7259
7260	},
7261
7262	intersectPlane: function ( plane, target ) {
7263
7264		var t = this.distanceToPlane( plane );
7265
7266		if ( t === null ) {
7267
7268			return null;
7269
7270		}
7271
7272		return this.at( t, target );
7273
7274	},
7275
7276	intersectsPlane: function ( plane ) {
7277
7278		// check if the ray lies on the plane first
7279
7280		var distToPoint = plane.distanceToPoint( this.origin );
7281
7282		if ( distToPoint === 0 ) {
7283
7284			return true;
7285
7286		}
7287
7288		var denominator = plane.normal.dot( this.direction );
7289
7290		if ( denominator * distToPoint < 0 ) {
7291
7292			return true;
7293
7294		}
7295
7296		// ray origin is behind the plane (and is pointing behind it)
7297
7298		return false;
7299
7300	},
7301
7302	intersectBox: function ( box, target ) {
7303
7304		var tmin, tmax, tymin, tymax, tzmin, tzmax;
7305
7306		var invdirx = 1 / this.direction.x,
7307			invdiry = 1 / this.direction.y,
7308			invdirz = 1 / this.direction.z;
7309
7310		var origin = this.origin;
7311
7312		if ( invdirx >= 0 ) {
7313
7314			tmin = ( box.min.x - origin.x ) * invdirx;
7315			tmax = ( box.max.x - origin.x ) * invdirx;
7316
7317		} else {
7318
7319			tmin = ( box.max.x - origin.x ) * invdirx;
7320			tmax = ( box.min.x - origin.x ) * invdirx;
7321
7322		}
7323
7324		if ( invdiry >= 0 ) {
7325
7326			tymin = ( box.min.y - origin.y ) * invdiry;
7327			tymax = ( box.max.y - origin.y ) * invdiry;
7328
7329		} else {
7330
7331			tymin = ( box.max.y - origin.y ) * invdiry;
7332			tymax = ( box.min.y - origin.y ) * invdiry;
7333
7334		}
7335
7336		if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
7337
7338		// These lines also handle the case where tmin or tmax is NaN
7339		// (result of 0 * Infinity). x !== x returns true if x is NaN
7340
7341		if ( tymin > tmin || tmin !== tmin ) tmin = tymin;
7342
7343		if ( tymax < tmax || tmax !== tmax ) tmax = tymax;
7344
7345		if ( invdirz >= 0 ) {
7346
7347			tzmin = ( box.min.z - origin.z ) * invdirz;
7348			tzmax = ( box.max.z - origin.z ) * invdirz;
7349
7350		} else {
7351
7352			tzmin = ( box.max.z - origin.z ) * invdirz;
7353			tzmax = ( box.min.z - origin.z ) * invdirz;
7354
7355		}
7356
7357		if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
7358
7359		if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
7360
7361		if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
7362
7363		//return point closest to the ray (positive side)
7364
7365		if ( tmax < 0 ) return null;
7366
7367		return this.at( tmin >= 0 ? tmin : tmax, target );
7368
7369	},
7370
7371	intersectsBox: function ( box ) {
7372
7373		return this.intersectBox( box, _vector$2 ) !== null;
7374
7375	},
7376
7377	intersectTriangle: function ( a, b, c, backfaceCulling, target ) {
7378
7379		// Compute the offset origin, edges, and normal.
7380
7381		// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
7382
7383		_edge1.subVectors( b, a );
7384		_edge2.subVectors( c, a );
7385		_normal.crossVectors( _edge1, _edge2 );
7386
7387		// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
7388		// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
7389		//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
7390		//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
7391		//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
7392		var DdN = this.direction.dot( _normal );
7393		var sign;
7394
7395		if ( DdN > 0 ) {
7396
7397			if ( backfaceCulling ) return null;
7398			sign = 1;
7399
7400		} else if ( DdN < 0 ) {
7401
7402			sign = - 1;
7403			DdN = - DdN;
7404
7405		} else {
7406
7407			return null;
7408
7409		}
7410
7411		_diff.subVectors( this.origin, a );
7412		var DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
7413
7414		// b1 < 0, no intersection
7415		if ( DdQxE2 < 0 ) {
7416
7417			return null;
7418
7419		}
7420
7421		var DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
7422
7423		// b2 < 0, no intersection
7424		if ( DdE1xQ < 0 ) {
7425
7426			return null;
7427
7428		}
7429
7430		// b1+b2 > 1, no intersection
7431		if ( DdQxE2 + DdE1xQ > DdN ) {
7432
7433			return null;
7434
7435		}
7436
7437		// Line intersects triangle, check if ray does.
7438		var QdN = - sign * _diff.dot( _normal );
7439
7440		// t < 0, no intersection
7441		if ( QdN < 0 ) {
7442
7443			return null;
7444
7445		}
7446
7447		// Ray intersects triangle.
7448		return this.at( QdN / DdN, target );
7449
7450	},
7451
7452	applyMatrix4: function ( matrix4 ) {
7453
7454		this.origin.applyMatrix4( matrix4 );
7455		this.direction.transformDirection( matrix4 );
7456
7457		return this;
7458
7459	},
7460
7461	equals: function ( ray ) {
7462
7463		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
7464
7465	}
7466
7467} );
7468
7469/**
7470 * @author bhouston / http://clara.io
7471 */
7472
7473var _vector1 = new Vector3();
7474var _vector2 = new Vector3();
7475var _normalMatrix = new Matrix3();
7476
7477function Plane( normal, constant ) {
7478
7479	// normal is assumed to be normalized
7480
7481	this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );
7482	this.constant = ( constant !== undefined ) ? constant : 0;
7483
7484}
7485
7486Object.assign( Plane.prototype, {
7487
7488	isPlane: true,
7489
7490	set: function ( normal, constant ) {
7491
7492		this.normal.copy( normal );
7493		this.constant = constant;
7494
7495		return this;
7496
7497	},
7498
7499	setComponents: function ( x, y, z, w ) {
7500
7501		this.normal.set( x, y, z );
7502		this.constant = w;
7503
7504		return this;
7505
7506	},
7507
7508	setFromNormalAndCoplanarPoint: function ( normal, point ) {
7509
7510		this.normal.copy( normal );
7511		this.constant = - point.dot( this.normal );
7512
7513		return this;
7514
7515	},
7516
7517	setFromCoplanarPoints: function ( a, b, c ) {
7518
7519		var normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
7520
7521		// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
7522
7523		this.setFromNormalAndCoplanarPoint( normal, a );
7524
7525		return this;
7526
7527	},
7528
7529	clone: function () {
7530
7531		return new this.constructor().copy( this );
7532
7533	},
7534
7535	copy: function ( plane ) {
7536
7537		this.normal.copy( plane.normal );
7538		this.constant = plane.constant;
7539
7540		return this;
7541
7542	},
7543
7544	normalize: function () {
7545
7546		// Note: will lead to a divide by zero if the plane is invalid.
7547
7548		var inverseNormalLength = 1.0 / this.normal.length();
7549		this.normal.multiplyScalar( inverseNormalLength );
7550		this.constant *= inverseNormalLength;
7551
7552		return this;
7553
7554	},
7555
7556	negate: function () {
7557
7558		this.constant *= - 1;
7559		this.normal.negate();
7560
7561		return this;
7562
7563	},
7564
7565	distanceToPoint: function ( point ) {
7566
7567		return this.normal.dot( point ) + this.constant;
7568
7569	},
7570
7571	distanceToSphere: function ( sphere ) {
7572
7573		return this.distanceToPoint( sphere.center ) - sphere.radius;
7574
7575	},
7576
7577	projectPoint: function ( point, target ) {
7578
7579		if ( target === undefined ) {
7580
7581			console.warn( 'THREE.Plane: .projectPoint() target is now required' );
7582			target = new Vector3();
7583
7584		}
7585
7586		return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );
7587
7588	},
7589
7590	intersectLine: function ( line, target ) {
7591
7592		if ( target === undefined ) {
7593
7594			console.warn( 'THREE.Plane: .intersectLine() target is now required' );
7595			target = new Vector3();
7596
7597		}
7598
7599		var direction = line.delta( _vector1 );
7600
7601		var denominator = this.normal.dot( direction );
7602
7603		if ( denominator === 0 ) {
7604
7605			// line is coplanar, return origin
7606			if ( this.distanceToPoint( line.start ) === 0 ) {
7607
7608				return target.copy( line.start );
7609
7610			}
7611
7612			// Unsure if this is the correct method to handle this case.
7613			return undefined;
7614
7615		}
7616
7617		var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
7618
7619		if ( t < 0 || t > 1 ) {
7620
7621			return undefined;
7622
7623		}
7624
7625		return target.copy( direction ).multiplyScalar( t ).add( line.start );
7626
7627	},
7628
7629	intersectsLine: function ( line ) {
7630
7631		// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
7632
7633		var startSign = this.distanceToPoint( line.start );
7634		var endSign = this.distanceToPoint( line.end );
7635
7636		return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
7637
7638	},
7639
7640	intersectsBox: function ( box ) {
7641
7642		return box.intersectsPlane( this );
7643
7644	},
7645
7646	intersectsSphere: function ( sphere ) {
7647
7648		return sphere.intersectsPlane( this );
7649
7650	},
7651
7652	coplanarPoint: function ( target ) {
7653
7654		if ( target === undefined ) {
7655
7656			console.warn( 'THREE.Plane: .coplanarPoint() target is now required' );
7657			target = new Vector3();
7658
7659		}
7660
7661		return target.copy( this.normal ).multiplyScalar( - this.constant );
7662
7663	},
7664
7665	applyMatrix4: function ( matrix, optionalNormalMatrix ) {
7666
7667		var normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
7668
7669		var referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
7670
7671		var normal = this.normal.applyMatrix3( normalMatrix ).normalize();
7672
7673		this.constant = - referencePoint.dot( normal );
7674
7675		return this;
7676
7677	},
7678
7679	translate: function ( offset ) {
7680
7681		this.constant -= offset.dot( this.normal );
7682
7683		return this;
7684
7685	},
7686
7687	equals: function ( plane ) {
7688
7689		return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
7690
7691	}
7692
7693} );
7694
7695/**
7696 * @author bhouston / http://clara.io
7697 * @author mrdoob / http://mrdoob.com/
7698 */
7699
7700var _v0$1 = new Vector3();
7701var _v1$3 = new Vector3();
7702var _v2$1 = new Vector3();
7703var _v3 = new Vector3();
7704
7705var _vab = new Vector3();
7706var _vac = new Vector3();
7707var _vbc = new Vector3();
7708var _vap = new Vector3();
7709var _vbp = new Vector3();
7710var _vcp = new Vector3();
7711
7712function Triangle( a, b, c ) {
7713
7714	this.a = ( a !== undefined ) ? a : new Vector3();
7715	this.b = ( b !== undefined ) ? b : new Vector3();
7716	this.c = ( c !== undefined ) ? c : new Vector3();
7717
7718}
7719
7720Object.assign( Triangle, {
7721
7722	getNormal: function ( a, b, c, target ) {
7723
7724		if ( target === undefined ) {
7725
7726			console.warn( 'THREE.Triangle: .getNormal() target is now required' );
7727			target = new Vector3();
7728
7729		}
7730
7731		target.subVectors( c, b );
7732		_v0$1.subVectors( a, b );
7733		target.cross( _v0$1 );
7734
7735		var targetLengthSq = target.lengthSq();
7736		if ( targetLengthSq > 0 ) {
7737
7738			return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
7739
7740		}
7741
7742		return target.set( 0, 0, 0 );
7743
7744	},
7745
7746	// static/instance method to calculate barycentric coordinates
7747	// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
7748	getBarycoord: function ( point, a, b, c, target ) {
7749
7750		_v0$1.subVectors( c, a );
7751		_v1$3.subVectors( b, a );
7752		_v2$1.subVectors( point, a );
7753
7754		var dot00 = _v0$1.dot( _v0$1 );
7755		var dot01 = _v0$1.dot( _v1$3 );
7756		var dot02 = _v0$1.dot( _v2$1 );
7757		var dot11 = _v1$3.dot( _v1$3 );
7758		var dot12 = _v1$3.dot( _v2$1 );
7759
7760		var denom = ( dot00 * dot11 - dot01 * dot01 );
7761
7762		if ( target === undefined ) {
7763
7764			console.warn( 'THREE.Triangle: .getBarycoord() target is now required' );
7765			target = new Vector3();
7766
7767		}
7768
7769		// collinear or singular triangle
7770		if ( denom === 0 ) {
7771
7772			// arbitrary location outside of triangle?
7773			// not sure if this is the best idea, maybe should be returning undefined
7774			return target.set( - 2, - 1, - 1 );
7775
7776		}
7777
7778		var invDenom = 1 / denom;
7779		var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
7780		var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
7781
7782		// barycentric coordinates must always sum to 1
7783		return target.set( 1 - u - v, v, u );
7784
7785	},
7786
7787	containsPoint: function ( point, a, b, c ) {
7788
7789		Triangle.getBarycoord( point, a, b, c, _v3 );
7790
7791		return ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );
7792
7793	},
7794
7795	getUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {
7796
7797		this.getBarycoord( point, p1, p2, p3, _v3 );
7798
7799		target.set( 0, 0 );
7800		target.addScaledVector( uv1, _v3.x );
7801		target.addScaledVector( uv2, _v3.y );
7802		target.addScaledVector( uv3, _v3.z );
7803
7804		return target;
7805
7806	},
7807
7808	isFrontFacing: function ( a, b, c, direction ) {
7809
7810		_v0$1.subVectors( c, b );
7811		_v1$3.subVectors( a, b );
7812
7813		// strictly front facing
7814		return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
7815
7816	}
7817
7818} );
7819
7820Object.assign( Triangle.prototype, {
7821
7822	set: function ( a, b, c ) {
7823
7824		this.a.copy( a );
7825		this.b.copy( b );
7826		this.c.copy( c );
7827
7828		return this;
7829
7830	},
7831
7832	setFromPointsAndIndices: function ( points, i0, i1, i2 ) {
7833
7834		this.a.copy( points[ i0 ] );
7835		this.b.copy( points[ i1 ] );
7836		this.c.copy( points[ i2 ] );
7837
7838		return this;
7839
7840	},
7841
7842	clone: function () {
7843
7844		return new this.constructor().copy( this );
7845
7846	},
7847
7848	copy: function ( triangle ) {
7849
7850		this.a.copy( triangle.a );
7851		this.b.copy( triangle.b );
7852		this.c.copy( triangle.c );
7853
7854		return this;
7855
7856	},
7857
7858	getArea: function () {
7859
7860		_v0$1.subVectors( this.c, this.b );
7861		_v1$3.subVectors( this.a, this.b );
7862
7863		return _v0$1.cross( _v1$3 ).length() * 0.5;
7864
7865	},
7866
7867	getMidpoint: function ( target ) {
7868
7869		if ( target === undefined ) {
7870
7871			console.warn( 'THREE.Triangle: .getMidpoint() target is now required' );
7872			target = new Vector3();
7873
7874		}
7875
7876		return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
7877
7878	},
7879
7880	getNormal: function ( target ) {
7881
7882		return Triangle.getNormal( this.a, this.b, this.c, target );
7883
7884	},
7885
7886	getPlane: function ( target ) {
7887
7888		if ( target === undefined ) {
7889
7890			console.warn( 'THREE.Triangle: .getPlane() target is now required' );
7891			target = new Plane();
7892
7893		}
7894
7895		return target.setFromCoplanarPoints( this.a, this.b, this.c );
7896
7897	},
7898
7899	getBarycoord: function ( point, target ) {
7900
7901		return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
7902
7903	},
7904
7905	getUV: function ( point, uv1, uv2, uv3, target ) {
7906
7907		return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
7908
7909	},
7910
7911	containsPoint: function ( point ) {
7912
7913		return Triangle.containsPoint( point, this.a, this.b, this.c );
7914
7915	},
7916
7917	isFrontFacing: function ( direction ) {
7918
7919		return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
7920
7921	},
7922
7923	intersectsBox: function ( box ) {
7924
7925		return box.intersectsTriangle( this );
7926
7927	},
7928
7929	closestPointToPoint: function ( p, target ) {
7930
7931		if ( target === undefined ) {
7932
7933			console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );
7934			target = new Vector3();
7935
7936		}
7937
7938		var a = this.a, b = this.b, c = this.c;
7939		var v, w;
7940
7941		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
7942		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
7943		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
7944		// basically, we're distinguishing which of the voronoi regions of the triangle
7945		// the point lies in with the minimum amount of redundant computation.
7946
7947		_vab.subVectors( b, a );
7948		_vac.subVectors( c, a );
7949		_vap.subVectors( p, a );
7950		var d1 = _vab.dot( _vap );
7951		var d2 = _vac.dot( _vap );
7952		if ( d1 <= 0 && d2 <= 0 ) {
7953
7954			// vertex region of A; barycentric coords (1, 0, 0)
7955			return target.copy( a );
7956
7957		}
7958
7959		_vbp.subVectors( p, b );
7960		var d3 = _vab.dot( _vbp );
7961		var d4 = _vac.dot( _vbp );
7962		if ( d3 >= 0 && d4 <= d3 ) {
7963
7964			// vertex region of B; barycentric coords (0, 1, 0)
7965			return target.copy( b );
7966
7967		}
7968
7969		var vc = d1 * d4 - d3 * d2;
7970		if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
7971
7972			v = d1 / ( d1 - d3 );
7973			// edge region of AB; barycentric coords (1-v, v, 0)
7974			return target.copy( a ).addScaledVector( _vab, v );
7975
7976		}
7977
7978		_vcp.subVectors( p, c );
7979		var d5 = _vab.dot( _vcp );
7980		var d6 = _vac.dot( _vcp );
7981		if ( d6 >= 0 && d5 <= d6 ) {
7982
7983			// vertex region of C; barycentric coords (0, 0, 1)
7984			return target.copy( c );
7985
7986		}
7987
7988		var vb = d5 * d2 - d1 * d6;
7989		if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
7990
7991			w = d2 / ( d2 - d6 );
7992			// edge region of AC; barycentric coords (1-w, 0, w)
7993			return target.copy( a ).addScaledVector( _vac, w );
7994
7995		}
7996
7997		var va = d3 * d6 - d5 * d4;
7998		if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
7999
8000			_vbc.subVectors( c, b );
8001			w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
8002			// edge region of BC; barycentric coords (0, 1-w, w)
8003			return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
8004
8005		}
8006
8007		// face region
8008		var denom = 1 / ( va + vb + vc );
8009		// u = va * denom
8010		v = vb * denom;
8011		w = vc * denom;
8012
8013		return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
8014
8015	},
8016
8017	equals: function ( triangle ) {
8018
8019		return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
8020
8021	}
8022
8023} );
8024
8025/**
8026 * @author mrdoob / http://mrdoob.com/
8027 */
8028
8029var _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
8030	'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
8031	'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
8032	'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
8033	'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
8034	'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
8035	'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
8036	'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
8037	'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
8038	'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
8039	'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
8040	'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
8041	'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
8042	'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
8043	'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
8044	'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
8045	'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
8046	'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
8047	'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
8048	'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
vendor: 5,188 bytes, lines 8049-8306
8049	'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
8050	'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
8051	'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
8052	'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
8053
8054var _hslA = { h: 0, s: 0, l: 0 };
8055var _hslB = { h: 0, s: 0, l: 0 };
8056
8057function Color( r, g, b ) {
8058
8059	if ( g === undefined && b === undefined ) {
8060
8061		// r is THREE.Color, hex or string
8062		return this.set( r );
8063
8064	}
8065
8066	return this.setRGB( r, g, b );
8067
8068}
8069
8070function hue2rgb( p, q, t ) {
8071
8072	if ( t < 0 ) t += 1;
8073	if ( t > 1 ) t -= 1;
8074	if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
8075	if ( t < 1 / 2 ) return q;
8076	if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
8077	return p;
8078
8079}
8080
8081function SRGBToLinear( c ) {
8082
8083	return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
8084
8085}
8086
8087function LinearToSRGB( c ) {
8088
8089	return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
8090
8091}
8092
8093Object.assign( Color.prototype, {
8094
8095	isColor: true,
8096
8097	r: 1, g: 1, b: 1,
8098
8099	set: function ( value ) {
8100
8101		if ( value && value.isColor ) {
8102
8103			this.copy( value );
8104
8105		} else if ( typeof value === 'number' ) {
8106
8107			this.setHex( value );
8108
8109		} else if ( typeof value === 'string' ) {
8110
8111			this.setStyle( value );
8112
8113		}
8114
8115		return this;
8116
8117	},
8118
8119	setScalar: function ( scalar ) {
8120
8121		this.r = scalar;
8122		this.g = scalar;
8123		this.b = scalar;
8124
8125		return this;
8126
8127	},
8128
8129	setHex: function ( hex ) {
8130
8131		hex = Math.floor( hex );
8132
8133		this.r = ( hex >> 16 & 255 ) / 255;
8134		this.g = ( hex >> 8 & 255 ) / 255;
8135		this.b = ( hex & 255 ) / 255;
8136
8137		return this;
8138
8139	},
8140
8141	setRGB: function ( r, g, b ) {
8142
8143		this.r = r;
8144		this.g = g;
8145		this.b = b;
8146
8147		return this;
8148
8149	},
8150
8151	setHSL: function ( h, s, l ) {
8152
8153		// h,s,l ranges are in 0.0 - 1.0
8154		h = MathUtils.euclideanModulo( h, 1 );
8155		s = MathUtils.clamp( s, 0, 1 );
8156		l = MathUtils.clamp( l, 0, 1 );
8157
8158		if ( s === 0 ) {
8159
8160			this.r = this.g = this.b = l;
8161
8162		} else {
8163
8164			var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
8165			var q = ( 2 * l ) - p;
8166
8167			this.r = hue2rgb( q, p, h + 1 / 3 );
8168			this.g = hue2rgb( q, p, h );
8169			this.b = hue2rgb( q, p, h - 1 / 3 );
8170
8171		}
8172
8173		return this;
8174
8175	},
8176
8177	setStyle: function ( style ) {
8178
8179		function handleAlpha( string ) {
8180
8181			if ( string === undefined ) return;
8182
8183			if ( parseFloat( string ) < 1 ) {
8184
8185				console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
8186
8187			}
8188
8189		}
8190
8191
8192		var m;
8193
8194		if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) {
8195
8196			// rgb / hsl
8197
8198			var color;
8199			var name = m[ 1 ];
8200			var components = m[ 2 ];
8201
8202			switch ( name ) {
8203
8204				case 'rgb':
8205				case 'rgba':
8206
8207					if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
8208
8209						// rgb(255,0,0) rgba(255,0,0,0.5)
8210						this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
8211						this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
8212						this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
8213
8214						handleAlpha( color[ 5 ] );
8215
8216						return this;
8217
8218					}
8219
8220					if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
8221
8222						// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
8223						this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
8224						this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
8225						this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
8226
8227						handleAlpha( color[ 5 ] );
8228
8229						return this;
8230
8231					}
8232
8233					break;
8234
8235				case 'hsl':
8236				case 'hsla':
8237
8238					if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) {
8239
8240						// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
8241						var h = parseFloat( color[ 1 ] ) / 360;
8242						var s = parseInt( color[ 2 ], 10 ) / 100;
8243						var l = parseInt( color[ 3 ], 10 ) / 100;
8244
8245						handleAlpha( color[ 5 ] );
8246
8247						return this.setHSL( h, s, l );
8248
8249					}
8250
8251					break;
8252
8253			}
8254
8255		} else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
8256
8257			// hex color
8258
8259			var hex = m[ 1 ];
8260			var size = hex.length;
8261
8262			if ( size === 3 ) {
8263
8264				// #ff0
8265				this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
8266				this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
8267				this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
8268
8269				return this;
8270
8271			} else if ( size === 6 ) {
8272
8273				// #ff0000
8274				this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
8275				this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
8276				this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
8277
8278				return this;
8279
8280			}
8281
8282		}
8283
8284		if ( style && style.length > 0 ) {
8285
8286			return this.setColorName( style );
8287
8288		}
8289
8290		return this;
8291
8292	},
8293
8294	setColorName: function ( style ) {
8295
8296		// color keywords
8297		var hex = _colorKeywords[ style ];
8298
8299		if ( hex !== undefined ) {
8300
8301			// red
8302			this.setHex( hex );
8303
8304		} else {
8305
8306			// unknown color
8307			console.warn( 'THREE.Color: Unknown color ' + style );
8308
8309		}
8310
8311		return this;
8312
8313	},
8314
8315	clone: function () {
8316
8317		return new this.constructor( this.r, this.g, this.b );
8318
8319	},
8320
8321	copy: function ( color ) {
8322
8323		this.r = color.r;
8324		this.g = color.g;
8325		this.b = color.b;
8326
8327		return this;
8328
8329	},
8330
8331	copyGammaToLinear: function ( color, gammaFactor ) {
8332
8333		if ( gammaFactor === undefined ) gammaFactor = 2.0;
8334
8335		this.r = Math.pow( color.r, gammaFactor );
8336		this.g = Math.pow( color.g, gammaFactor );
8337		this.b = Math.pow( color.b, gammaFactor );
8338
8339		return this;
8340
8341	},
8342
8343	copyLinearToGamma: function ( color, gammaFactor ) {
8344
8345		if ( gammaFactor === undefined ) gammaFactor = 2.0;
8346
8347		var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
8348
8349		this.r = Math.pow( color.r, safeInverse );
8350		this.g = Math.pow( color.g, safeInverse );
8351		this.b = Math.pow( color.b, safeInverse );
8352
8353		return this;
8354
8355	},
8356
8357	convertGammaToLinear: function ( gammaFactor ) {
8358
8359		this.copyGammaToLinear( this, gammaFactor );
8360
8361		return this;
8362
8363	},
8364
8365	convertLinearToGamma: function ( gammaFactor ) {
8366
8367		this.copyLinearToGamma( this, gammaFactor );
8368
8369		return this;
8370
8371	},
8372
8373	copySRGBToLinear: function ( color ) {
8374
8375		this.r = SRGBToLinear( color.r );
8376		this.g = SRGBToLinear( color.g );
8377		this.b = SRGBToLinear( color.b );
8378
8379		return this;
8380
8381	},
8382
8383	copyLinearToSRGB: function ( color ) {
8384
8385		this.r = LinearToSRGB( color.r );
8386		this.g = LinearToSRGB( color.g );
8387		this.b = LinearToSRGB( color.b );
8388
8389		return this;
8390
8391	},
8392
8393	convertSRGBToLinear: function () {
8394
8395		this.copySRGBToLinear( this );
8396
8397		return this;
8398
8399	},
8400
8401	convertLinearToSRGB: function () {
8402
8403		this.copyLinearToSRGB( this );
8404
8405		return this;
8406
8407	},
8408
8409	getHex: function () {
8410
8411		return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
8412
8413	},
8414
8415	getHexString: function () {
8416
8417		return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
8418
8419	},
8420
8421	getHSL: function ( target ) {
8422
8423		// h,s,l ranges are in 0.0 - 1.0
8424
8425		if ( target === undefined ) {
8426
8427			console.warn( 'THREE.Color: .getHSL() target is now required' );
8428			target = { h: 0, s: 0, l: 0 };
8429
8430		}
8431
8432		var r = this.r, g = this.g, b = this.b;
8433
8434		var max = Math.max( r, g, b );
8435		var min = Math.min( r, g, b );
8436
8437		var hue, saturation;
8438		var lightness = ( min + max ) / 2.0;
8439
8440		if ( min === max ) {
8441
8442			hue = 0;
8443			saturation = 0;
8444
8445		} else {
8446
8447			var delta = max - min;
8448
8449			saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
8450
8451			switch ( max ) {
8452
8453				case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
8454				case g: hue = ( b - r ) / delta + 2; break;
8455				case b: hue = ( r - g ) / delta + 4; break;
8456
8457			}
8458
8459			hue /= 6;
8460
8461		}
8462
8463		target.h = hue;
8464		target.s = saturation;
8465		target.l = lightness;
8466
8467		return target;
8468
8469	},
8470
8471	getStyle: function () {
8472
8473		return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
8474
8475	},
8476
8477	offsetHSL: function ( h, s, l ) {
8478
8479		this.getHSL( _hslA );
8480
8481		_hslA.h += h; _hslA.s += s; _hslA.l += l;
8482
8483		this.setHSL( _hslA.h, _hslA.s, _hslA.l );
8484
8485		return this;
8486
8487	},
8488
8489	add: function ( color ) {
8490
8491		this.r += color.r;
8492		this.g += color.g;
8493		this.b += color.b;
8494
8495		return this;
8496
8497	},
8498
8499	addColors: function ( color1, color2 ) {
8500
8501		this.r = color1.r + color2.r;
8502		this.g = color1.g + color2.g;
8503		this.b = color1.b + color2.b;
8504
8505		return this;
8506
8507	},
8508
8509	addScalar: function ( s ) {
8510
8511		this.r += s;
8512		this.g += s;
8513		this.b += s;
8514
8515		return this;
8516
8517	},
8518
8519	sub: function ( color ) {
8520
8521		this.r = Math.max( 0, this.r - color.r );
8522		this.g = Math.max( 0, this.g - color.g );
8523		this.b = Math.max( 0, this.b - color.b );
8524
8525		return this;
8526
8527	},
8528
8529	multiply: function ( color ) {
8530
8531		this.r *= color.r;
8532		this.g *= color.g;
8533		this.b *= color.b;
8534
8535		return this;
8536
8537	},
8538
8539	multiplyScalar: function ( s ) {
8540
8541		this.r *= s;
8542		this.g *= s;
8543		this.b *= s;
8544
8545		return this;
8546
8547	},
8548
8549	lerp: function ( color, alpha ) {
8550
8551		this.r += ( color.r - this.r ) * alpha;
8552		this.g += ( color.g - this.g ) * alpha;
8553		this.b += ( color.b - this.b ) * alpha;
8554
8555		return this;
8556
8557	},
8558
8559	lerpHSL: function ( color, alpha ) {
8560
8561		this.getHSL( _hslA );
8562		color.getHSL( _hslB );
8563
8564		var h = MathUtils.lerp( _hslA.h, _hslB.h, alpha );
8565		var s = MathUtils.lerp( _hslA.s, _hslB.s, alpha );
8566		var l = MathUtils.lerp( _hslA.l, _hslB.l, alpha );
8567
8568		this.setHSL( h, s, l );
8569
8570		return this;
8571
8572	},
8573
8574	equals: function ( c ) {
8575
8576		return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
8577
8578	},
8579
8580	fromArray: function ( array, offset ) {
8581
8582		if ( offset === undefined ) offset = 0;
8583
8584		this.r = array[ offset ];
8585		this.g = array[ offset + 1 ];
8586		this.b = array[ offset + 2 ];
8587
8588		return this;
8589
8590	},
8591
8592	toArray: function ( array, offset ) {
8593
8594		if ( array === undefined ) array = [];
8595		if ( offset === undefined ) offset = 0;
8596
8597		array[ offset ] = this.r;
8598		array[ offset + 1 ] = this.g;
8599		array[ offset + 2 ] = this.b;
8600
8601		return array;
8602
8603	},
8604
8605	toJSON: function () {
8606
8607		return this.getHex();
8608
8609	}
8610
8611} );
8612
8613Color.NAMES = _colorKeywords;
8614
8615/**
8616 * @author mrdoob / http://mrdoob.com/
8617 * @author alteredq / http://alteredqualia.com/
8618 */
8619
8620function Face3( a, b, c, normal, color, materialIndex ) {
8621
8622	this.a = a;
8623	this.b = b;
8624	this.c = c;
8625
8626	this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();
8627	this.vertexNormals = Array.isArray( normal ) ? normal : [];
8628
8629	this.color = ( color && color.isColor ) ? color : new Color();
8630	this.vertexColors = Array.isArray( color ) ? color : [];
8631
8632	this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
8633
8634}
8635
8636Object.assign( Face3.prototype, {
8637
8638	clone: function () {
8639
8640		return new this.constructor().copy( this );
8641
8642	},
8643
8644	copy: function ( source ) {
8645
8646		this.a = source.a;
8647		this.b = source.b;
8648		this.c = source.c;
8649
8650		this.normal.copy( source.normal );
8651		this.color.copy( source.color );
8652
8653		this.materialIndex = source.materialIndex;
8654
8655		for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {
8656
8657			this.vertexNormals[ i ] = source.vertexNormals[ i ].clone();
8658
8659		}
8660
8661		for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {
8662
8663			this.vertexColors[ i ] = source.vertexColors[ i ].clone();
8664
8665		}
8666
8667		return this;
8668
8669	}
8670
8671} );
8672
8673/**
8674 * @author mrdoob / http://mrdoob.com/
8675 * @author alteredq / http://alteredqualia.com/
8676 */
8677
8678var materialId = 0;
8679
8680function Material() {
8681
8682	Object.defineProperty( this, 'id', { value: materialId ++ } );
8683
8684	this.uuid = MathUtils.generateUUID();
8685
8686	this.name = '';
8687	this.type = 'Material';
8688
8689	this.fog = true;
8690
8691	this.blending = NormalBlending;
8692	this.side = FrontSide;
8693	this.flatShading = false;
8694	this.vertexColors = false;
8695
8696	this.opacity = 1;
8697	this.transparent = false;
8698
8699	this.blendSrc = SrcAlphaFactor;
8700	this.blendDst = OneMinusSrcAlphaFactor;
8701	this.blendEquation = AddEquation;
8702	this.blendSrcAlpha = null;
8703	this.blendDstAlpha = null;
8704	this.blendEquationAlpha = null;
8705
8706	this.depthFunc = LessEqualDepth;
8707	this.depthTest = true;
8708	this.depthWrite = true;
8709
8710	this.stencilWriteMask = 0xff;
8711	this.stencilFunc = AlwaysStencilFunc;
8712	this.stencilRef = 0;
8713	this.stencilFuncMask = 0xff;
8714	this.stencilFail = KeepStencilOp;
8715	this.stencilZFail = KeepStencilOp;
8716	this.stencilZPass = KeepStencilOp;
8717	this.stencilWrite = false;
8718
8719	this.clippingPlanes = null;
8720	this.clipIntersection = false;
8721	this.clipShadows = false;
8722
8723	this.shadowSide = null;
8724
8725	this.colorWrite = true;
8726
8727	this.precision = null; // override the renderer's default precision for this material
8728
8729	this.polygonOffset = false;
8730	this.polygonOffsetFactor = 0;
8731	this.polygonOffsetUnits = 0;
8732
8733	this.dithering = false;
8734
8735	this.alphaTest = 0;
8736	this.premultipliedAlpha = false;
8737
8738	this.visible = true;
8739
8740	this.toneMapped = true;
8741
8742	this.userData = {};
8743
8744	this.version = 0;
8745
8746}
8747
8748Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
8749
8750	constructor: Material,
8751
8752	isMaterial: true,
8753
8754	onBeforeCompile: function () {},
8755
8756	setValues: function ( values ) {
8757
8758		if ( values === undefined ) return;
8759
8760		for ( var key in values ) {
8761
8762			var newValue = values[ key ];
8763
8764			if ( newValue === undefined ) {
8765
8766				console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
8767				continue;
8768
8769			}
8770
8771			// for backward compatability if shading is set in the constructor
8772			if ( key === 'shading' ) {
8773
8774				console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
8775				this.flatShading = ( newValue === FlatShading ) ? true : false;
vendor: 6,735 bytes, lines 8776-8975
8776				continue;
8777
8778			}
8779
8780			var currentValue = this[ key ];
8781
8782			if ( currentValue === undefined ) {
8783
8784				console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
8785				continue;
8786
8787			}
8788
8789			if ( currentValue && currentValue.isColor ) {
8790
8791				currentValue.set( newValue );
8792
8793			} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
8794
8795				currentValue.copy( newValue );
8796
8797			} else {
8798
8799				this[ key ] = newValue;
8800
8801			}
8802
8803		}
8804
8805	},
8806
8807	toJSON: function ( meta ) {
8808
8809		var isRoot = ( meta === undefined || typeof meta === 'string' );
8810
8811		if ( isRoot ) {
8812
8813			meta = {
8814				textures: {},
8815				images: {}
8816			};
8817
8818		}
8819
8820		var data = {
8821			metadata: {
8822				version: 4.5,
8823				type: 'Material',
8824				generator: 'Material.toJSON'
8825			}
8826		};
8827
8828		// standard Material serialization
8829		data.uuid = this.uuid;
8830		data.type = this.type;
8831
8832		if ( this.name !== '' ) data.name = this.name;
8833
8834		if ( this.color && this.color.isColor ) data.color = this.color.getHex();
8835
8836		if ( this.roughness !== undefined ) data.roughness = this.roughness;
8837		if ( this.metalness !== undefined ) data.metalness = this.metalness;
8838
8839		if ( this.sheen && this.sheen.isColor ) data.sheen = this.sheen.getHex();
8840		if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
8841		if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
8842
8843		if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
8844		if ( this.shininess !== undefined ) data.shininess = this.shininess;
8845		if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
8846		if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
8847
8848		if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
8849
8850			data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
8851
8852		}
8853
8854		if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
8855
8856			data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
8857
8858		}
8859
8860		if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
8861
8862			data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
8863			data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
8864
8865		}
8866
8867		if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
8868		if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
8869		if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
8870		if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
8871
8872		if ( this.aoMap && this.aoMap.isTexture ) {
8873
8874			data.aoMap = this.aoMap.toJSON( meta ).uuid;
8875			data.aoMapIntensity = this.aoMapIntensity;
8876
8877		}
8878
8879		if ( this.bumpMap && this.bumpMap.isTexture ) {
8880
8881			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
8882			data.bumpScale = this.bumpScale;
8883
8884		}
8885
8886		if ( this.normalMap && this.normalMap.isTexture ) {
8887
8888			data.normalMap = this.normalMap.toJSON( meta ).uuid;
8889			data.normalMapType = this.normalMapType;
8890			data.normalScale = this.normalScale.toArray();
8891
8892		}
8893
8894		if ( this.displacementMap && this.displacementMap.isTexture ) {
8895
8896			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
8897			data.displacementScale = this.displacementScale;
8898			data.displacementBias = this.displacementBias;
8899
8900		}
8901
8902		if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
8903		if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
8904
8905		if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
8906		if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
8907
8908		if ( this.envMap && this.envMap.isTexture ) {
8909
8910			data.envMap = this.envMap.toJSON( meta ).uuid;
8911			data.reflectivity = this.reflectivity; // Scale behind envMap
8912			data.refractionRatio = this.refractionRatio;
8913
8914			if ( this.combine !== undefined ) data.combine = this.combine;
8915			if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
8916
8917		}
8918
8919		if ( this.gradientMap && this.gradientMap.isTexture ) {
8920
8921			data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
8922
8923		}
8924
8925		if ( this.size !== undefined ) data.size = this.size;
8926		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
8927
8928		if ( this.blending !== NormalBlending ) data.blending = this.blending;
8929		if ( this.flatShading === true ) data.flatShading = this.flatShading;
8930		if ( this.side !== FrontSide ) data.side = this.side;
8931		if ( this.vertexColors ) data.vertexColors = true;
8932
8933		if ( this.opacity < 1 ) data.opacity = this.opacity;
8934		if ( this.transparent === true ) data.transparent = this.transparent;
8935
8936		data.depthFunc = this.depthFunc;
8937		data.depthTest = this.depthTest;
8938		data.depthWrite = this.depthWrite;
8939
8940		data.stencilWrite = this.stencilWrite;
8941		data.stencilWriteMask = this.stencilWriteMask;
8942		data.stencilFunc = this.stencilFunc;
8943		data.stencilRef = this.stencilRef;
8944		data.stencilFuncMask = this.stencilFuncMask;
8945		data.stencilFail = this.stencilFail;
8946		data.stencilZFail = this.stencilZFail;
8947		data.stencilZPass = this.stencilZPass;
8948
8949		// rotation (SpriteMaterial)
8950		if ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;
8951
8952		if ( this.polygonOffset === true ) data.polygonOffset = true;
8953		if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
8954		if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
8955
8956		if ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;
8957		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
8958		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
8959		if ( this.scale !== undefined ) data.scale = this.scale;
8960
8961		if ( this.dithering === true ) data.dithering = true;
8962
8963		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
8964		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
8965
8966		if ( this.wireframe === true ) data.wireframe = this.wireframe;
8967		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
8968		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
8969		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
8970
8971		if ( this.morphTargets === true ) data.morphTargets = true;
8972		if ( this.morphNormals === true ) data.morphNormals = true;
8973		if ( this.skinning === true ) data.skinning = true;
8974
8975		if ( this.visible === false ) data.visible = false;
vendor: 4,149 bytes, lines 8976-9173
8976
8977		if ( this.toneMapped === false ) data.toneMapped = false;
8978
8979		if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
8980
8981		// TODO: Copied from Object3D.toJSON
8982
8983		function extractFromCache( cache ) {
8984
8985			var values = [];
8986
8987			for ( var key in cache ) {
8988
8989				var data = cache[ key ];
8990				delete data.metadata;
8991				values.push( data );
8992
8993			}
8994
8995			return values;
8996
8997		}
8998
8999		if ( isRoot ) {
9000
9001			var textures = extractFromCache( meta.textures );
9002			var images = extractFromCache( meta.images );
9003
9004			if ( textures.length > 0 ) data.textures = textures;
9005			if ( images.length > 0 ) data.images = images;
9006
9007		}
9008
9009		return data;
9010
9011	},
9012
9013	clone: function () {
9014
9015		return new this.constructor().copy( this );
9016
9017	},
9018
9019	copy: function ( source ) {
9020
9021		this.name = source.name;
9022
9023		this.fog = source.fog;
9024
9025		this.blending = source.blending;
9026		this.side = source.side;
9027		this.flatShading = source.flatShading;
9028		this.vertexColors = source.vertexColors;
9029
9030		this.opacity = source.opacity;
9031		this.transparent = source.transparent;
9032
9033		this.blendSrc = source.blendSrc;
9034		this.blendDst = source.blendDst;
9035		this.blendEquation = source.blendEquation;
9036		this.blendSrcAlpha = source.blendSrcAlpha;
9037		this.blendDstAlpha = source.blendDstAlpha;
9038		this.blendEquationAlpha = source.blendEquationAlpha;
9039
9040		this.depthFunc = source.depthFunc;
9041		this.depthTest = source.depthTest;
9042		this.depthWrite = source.depthWrite;
9043
9044		this.stencilWriteMask = source.stencilWriteMask;
9045		this.stencilFunc = source.stencilFunc;
9046		this.stencilRef = source.stencilRef;
9047		this.stencilFuncMask = source.stencilFuncMask;
9048		this.stencilFail = source.stencilFail;
9049		this.stencilZFail = source.stencilZFail;
9050		this.stencilZPass = source.stencilZPass;
9051		this.stencilWrite = source.stencilWrite;
9052
9053		var srcPlanes = source.clippingPlanes,
9054			dstPlanes = null;
9055
9056		if ( srcPlanes !== null ) {
9057
9058			var n = srcPlanes.length;
9059			dstPlanes = new Array( n );
9060
9061			for ( var i = 0; i !== n; ++ i )
9062				dstPlanes[ i ] = srcPlanes[ i ].clone();
9063
9064		}
9065
9066		this.clippingPlanes = dstPlanes;
9067		this.clipIntersection = source.clipIntersection;
9068		this.clipShadows = source.clipShadows;
9069
9070		this.shadowSide = source.shadowSide;
9071
9072		this.colorWrite = source.colorWrite;
9073
9074		this.precision = source.precision;
9075
9076		this.polygonOffset = source.polygonOffset;
9077		this.polygonOffsetFactor = source.polygonOffsetFactor;
9078		this.polygonOffsetUnits = source.polygonOffsetUnits;
9079
9080		this.dithering = source.dithering;
9081
9082		this.alphaTest = source.alphaTest;
9083		this.premultipliedAlpha = source.premultipliedAlpha;
9084
9085		this.visible = source.visible;
9086
9087		this.toneMapped = source.toneMapped;
9088
9089		this.userData = JSON.parse( JSON.stringify( source.userData ) );
9090
9091		return this;
9092
9093	},
9094
9095	dispose: function () {
9096
9097		this.dispatchEvent( { type: 'dispose' } );
9098
9099	}
9100
9101} );
9102
9103Object.defineProperty( Material.prototype, 'needsUpdate', {
9104
9105	set: function ( value ) {
9106
9107		if ( value === true ) this.version ++;
9108
9109	}
9110
9111} );
9112
9113/**
9114 * @author mrdoob / http://mrdoob.com/
9115 * @author alteredq / http://alteredqualia.com/
9116 *
9117 * parameters = {
9118 *  color: <hex>,
9119 *  opacity: <float>,
9120 *  map: new THREE.Texture( <Image> ),
9121 *
9122 *  lightMap: new THREE.Texture( <Image> ),
9123 *  lightMapIntensity: <float>
9124 *
9125 *  aoMap: new THREE.Texture( <Image> ),
9126 *  aoMapIntensity: <float>
9127 *
9128 *  specularMap: new THREE.Texture( <Image> ),
9129 *
9130 *  alphaMap: new THREE.Texture( <Image> ),
9131 *
9132 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
9133 *  combine: THREE.Multiply,
9134 *  reflectivity: <float>,
9135 *  refractionRatio: <float>,
9136 *
9137 *  depthTest: <bool>,
9138 *  depthWrite: <bool>,
9139 *
9140 *  wireframe: <boolean>,
9141 *  wireframeLinewidth: <float>,
9142 *
9143 *  skinning: <bool>,
9144 *  morphTargets: <bool>
9145 * }
9146 */
9147
9148function MeshBasicMaterial( parameters ) {
9149
9150	Material.call( this );
9151
9152	this.type = 'MeshBasicMaterial';
9153
9154	this.color = new Color( 0xffffff ); // emissive
9155
9156	this.map = null;
9157
9158	this.lightMap = null;
9159	this.lightMapIntensity = 1.0;
9160
9161	this.aoMap = null;
9162	this.aoMapIntensity = 1.0;
9163
9164	this.specularMap = null;
9165
9166	this.alphaMap = null;
9167
9168	this.envMap = null;
9169	this.combine = MultiplyOperation;
9170	this.reflectivity = 1;
9171	this.refractionRatio = 0.98;
9172
9173	this.wireframe = false;
vendor: 10,660 bytes, lines 9174-9732
9174	this.wireframeLinewidth = 1;
9175	this.wireframeLinecap = 'round';
9176	this.wireframeLinejoin = 'round';
9177
9178	this.skinning = false;
9179	this.morphTargets = false;
9180
9181	this.setValues( parameters );
9182
9183}
9184
9185MeshBasicMaterial.prototype = Object.create( Material.prototype );
9186MeshBasicMaterial.prototype.constructor = MeshBasicMaterial;
9187
9188MeshBasicMaterial.prototype.isMeshBasicMaterial = true;
9189
9190MeshBasicMaterial.prototype.copy = function ( source ) {
9191
9192	Material.prototype.copy.call( this, source );
9193
9194	this.color.copy( source.color );
9195
9196	this.map = source.map;
9197
9198	this.lightMap = source.lightMap;
9199	this.lightMapIntensity = source.lightMapIntensity;
9200
9201	this.aoMap = source.aoMap;
9202	this.aoMapIntensity = source.aoMapIntensity;
9203
9204	this.specularMap = source.specularMap;
9205
9206	this.alphaMap = source.alphaMap;
9207
9208	this.envMap = source.envMap;
9209	this.combine = source.combine;
9210	this.reflectivity = source.reflectivity;
9211	this.refractionRatio = source.refractionRatio;
9212
9213	this.wireframe = source.wireframe;
9214	this.wireframeLinewidth = source.wireframeLinewidth;
9215	this.wireframeLinecap = source.wireframeLinecap;
9216	this.wireframeLinejoin = source.wireframeLinejoin;
9217
9218	this.skinning = source.skinning;
9219	this.morphTargets = source.morphTargets;
9220
9221	return this;
9222
9223};
9224
9225/**
9226 * @author mrdoob / http://mrdoob.com/
9227 */
9228
9229var _vector$3 = new Vector3();
9230
9231function BufferAttribute( array, itemSize, normalized ) {
9232
9233	if ( Array.isArray( array ) ) {
9234
9235		throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
9236
9237	}
9238
9239	this.name = '';
9240
9241	this.array = array;
9242	this.itemSize = itemSize;
9243	this.count = array !== undefined ? array.length / itemSize : 0;
9244	this.normalized = normalized === true;
9245
9246	this.usage = StaticDrawUsage;
9247	this.updateRange = { offset: 0, count: - 1 };
9248
9249	this.version = 0;
9250
9251}
9252
9253Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', {
9254
9255	set: function ( value ) {
9256
9257		if ( value === true ) this.version ++;
9258
9259	}
9260
9261} );
9262
9263Object.assign( BufferAttribute.prototype, {
9264
9265	isBufferAttribute: true,
9266
9267	onUploadCallback: function () {},
9268
9269	setUsage: function ( value ) {
9270
9271		this.usage = value;
9272
9273		return this;
9274
9275	},
9276
9277	copy: function ( source ) {
9278
9279		this.name = source.name;
9280		this.array = new source.array.constructor( source.array );
9281		this.itemSize = source.itemSize;
9282		this.count = source.count;
9283		this.normalized = source.normalized;
9284
9285		this.usage = source.usage;
9286
9287		return this;
9288
9289	},
9290
9291	copyAt: function ( index1, attribute, index2 ) {
9292
9293		index1 *= this.itemSize;
9294		index2 *= attribute.itemSize;
9295
9296		for ( var i = 0, l = this.itemSize; i < l; i ++ ) {
9297
9298			this.array[ index1 + i ] = attribute.array[ index2 + i ];
9299
9300		}
9301
9302		return this;
9303
9304	},
9305
9306	copyArray: function ( array ) {
9307
9308		this.array.set( array );
9309
9310		return this;
9311
9312	},
9313
9314	copyColorsArray: function ( colors ) {
9315
9316		var array = this.array, offset = 0;
9317
9318		for ( var i = 0, l = colors.length; i < l; i ++ ) {
9319
9320			var color = colors[ i ];
9321
9322			if ( color === undefined ) {
9323
9324				console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );
9325				color = new Color();
9326
9327			}
9328
9329			array[ offset ++ ] = color.r;
9330			array[ offset ++ ] = color.g;
9331			array[ offset ++ ] = color.b;
9332
9333		}
9334
9335		return this;
9336
9337	},
9338
9339	copyVector2sArray: function ( vectors ) {
9340
9341		var array = this.array, offset = 0;
9342
9343		for ( var i = 0, l = vectors.length; i < l; i ++ ) {
9344
9345			var vector = vectors[ i ];
9346
9347			if ( vector === undefined ) {
9348
9349				console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );
9350				vector = new Vector2();
9351
9352			}
9353
9354			array[ offset ++ ] = vector.x;
9355			array[ offset ++ ] = vector.y;
9356
9357		}
9358
9359		return this;
9360
9361	},
9362
9363	copyVector3sArray: function ( vectors ) {
9364
9365		var array = this.array, offset = 0;
9366
9367		for ( var i = 0, l = vectors.length; i < l; i ++ ) {
9368
9369			var vector = vectors[ i ];
9370
9371			if ( vector === undefined ) {
9372
9373				console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );
9374				vector = new Vector3();
9375
9376			}
9377
9378			array[ offset ++ ] = vector.x;
9379			array[ offset ++ ] = vector.y;
9380			array[ offset ++ ] = vector.z;
9381
9382		}
9383
9384		return this;
9385
9386	},
9387
9388	copyVector4sArray: function ( vectors ) {
9389
9390		var array = this.array, offset = 0;
9391
9392		for ( var i = 0, l = vectors.length; i < l; i ++ ) {
9393
9394			var vector = vectors[ i ];
9395
9396			if ( vector === undefined ) {
9397
9398				console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );
9399				vector = new Vector4();
9400
9401			}
9402
9403			array[ offset ++ ] = vector.x;
9404			array[ offset ++ ] = vector.y;
9405			array[ offset ++ ] = vector.z;
9406			array[ offset ++ ] = vector.w;
9407
9408		}
9409
9410		return this;
9411
9412	},
9413
9414	applyMatrix3: function ( m ) {
9415
9416		for ( var i = 0, l = this.count; i < l; i ++ ) {
9417
9418			_vector$3.x = this.getX( i );
9419			_vector$3.y = this.getY( i );
9420			_vector$3.z = this.getZ( i );
9421
9422			_vector$3.applyMatrix3( m );
9423
9424			this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9425
9426		}
9427
9428		return this;
9429
9430	},
9431
9432	applyMatrix4: function ( m ) {
9433
9434		for ( var i = 0, l = this.count; i < l; i ++ ) {
9435
9436			_vector$3.x = this.getX( i );
9437			_vector$3.y = this.getY( i );
9438			_vector$3.z = this.getZ( i );
9439
9440			_vector$3.applyMatrix4( m );
9441
9442			this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9443
9444		}
9445
9446		return this;
9447
9448	},
9449
9450	applyNormalMatrix: function ( m ) {
9451
9452		for ( var i = 0, l = this.count; i < l; i ++ ) {
9453
9454			_vector$3.x = this.getX( i );
9455			_vector$3.y = this.getY( i );
9456			_vector$3.z = this.getZ( i );
9457
9458			_vector$3.applyNormalMatrix( m );
9459
9460			this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9461
9462		}
9463
9464		return this;
9465
9466	},
9467
9468	transformDirection: function ( m ) {
9469
9470		for ( var i = 0, l = this.count; i < l; i ++ ) {
9471
9472			_vector$3.x = this.getX( i );
9473			_vector$3.y = this.getY( i );
9474			_vector$3.z = this.getZ( i );
9475
9476			_vector$3.transformDirection( m );
9477
9478			this.setXYZ( i, _vector$3.x, _vector$3.y, _vector$3.z );
9479
9480		}
9481
9482		return this;
9483
9484	},
9485
9486	set: function ( value, offset ) {
9487
9488		if ( offset === undefined ) offset = 0;
9489
9490		this.array.set( value, offset );
9491
9492		return this;
9493
9494	},
9495
9496	getX: function ( index ) {
9497
9498		return this.array[ index * this.itemSize ];
9499
9500	},
9501
9502	setX: function ( index, x ) {
9503
9504		this.array[ index * this.itemSize ] = x;
9505
9506		return this;
9507
9508	},
9509
9510	getY: function ( index ) {
9511
9512		return this.array[ index * this.itemSize + 1 ];
9513
9514	},
9515
9516	setY: function ( index, y ) {
9517
9518		this.array[ index * this.itemSize + 1 ] = y;
9519
9520		return this;
9521
9522	},
9523
9524	getZ: function ( index ) {
9525
9526		return this.array[ index * this.itemSize + 2 ];
9527
9528	},
9529
9530	setZ: function ( index, z ) {
9531
9532		this.array[ index * this.itemSize + 2 ] = z;
9533
9534		return this;
9535
9536	},
9537
9538	getW: function ( index ) {
9539
9540		return this.array[ index * this.itemSize + 3 ];
9541
9542	},
9543
9544	setW: function ( index, w ) {
9545
9546		this.array[ index * this.itemSize + 3 ] = w;
9547
9548		return this;
9549
9550	},
9551
9552	setXY: function ( index, x, y ) {
9553
9554		index *= this.itemSize;
9555
9556		this.array[ index + 0 ] = x;
9557		this.array[ index + 1 ] = y;
9558
9559		return this;
9560
9561	},
9562
9563	setXYZ: function ( index, x, y, z ) {
9564
9565		index *= this.itemSize;
9566
9567		this.array[ index + 0 ] = x;
9568		this.array[ index + 1 ] = y;
9569		this.array[ index + 2 ] = z;
9570
9571		return this;
9572
9573	},
9574
9575	setXYZW: function ( index, x, y, z, w ) {
9576
9577		index *= this.itemSize;
9578
9579		this.array[ index + 0 ] = x;
9580		this.array[ index + 1 ] = y;
9581		this.array[ index + 2 ] = z;
9582		this.array[ index + 3 ] = w;
9583
9584		return this;
9585
9586	},
9587
9588	onUpload: function ( callback ) {
9589
9590		this.onUploadCallback = callback;
9591
9592		return this;
9593
9594	},
9595
9596	clone: function () {
9597
9598		return new this.constructor( this.array, this.itemSize ).copy( this );
9599
9600	},
9601
9602	toJSON: function () {
9603
9604		return {
9605			itemSize: this.itemSize,
9606			type: this.array.constructor.name,
9607			array: Array.prototype.slice.call( this.array ),
9608			normalized: this.normalized
9609		};
9610
9611	}
9612
9613} );
9614
9615//
9616
9617function Int8BufferAttribute( array, itemSize, normalized ) {
9618
9619	BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );
9620
9621}
9622
9623Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9624Int8BufferAttribute.prototype.constructor = Int8BufferAttribute;
9625
9626
9627function Uint8BufferAttribute( array, itemSize, normalized ) {
9628
9629	BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
9630
9631}
9632
9633Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9634Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;
9635
9636
9637function Uint8ClampedBufferAttribute( array, itemSize, normalized ) {
9638
9639	BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );
9640
9641}
9642
9643Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9644Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;
9645
9646
9647function Int16BufferAttribute( array, itemSize, normalized ) {
9648
9649	BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );
9650
9651}
9652
9653Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9654Int16BufferAttribute.prototype.constructor = Int16BufferAttribute;
9655
9656
9657function Uint16BufferAttribute( array, itemSize, normalized ) {
9658
9659	BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );
9660
9661}
9662
9663Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9664Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;
9665
9666
9667function Int32BufferAttribute( array, itemSize, normalized ) {
9668
9669	BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );
9670
9671}
9672
9673Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9674Int32BufferAttribute.prototype.constructor = Int32BufferAttribute;
9675
9676
9677function Uint32BufferAttribute( array, itemSize, normalized ) {
9678
9679	BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );
9680
9681}
9682
9683Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9684Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;
9685
9686
9687function Float32BufferAttribute( array, itemSize, normalized ) {
9688
9689	BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );
9690
9691}
9692
9693Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9694Float32BufferAttribute.prototype.constructor = Float32BufferAttribute;
9695
9696
9697function Float64BufferAttribute( array, itemSize, normalized ) {
9698
9699	BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );
9700
9701}
9702
9703Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
9704Float64BufferAttribute.prototype.constructor = Float64BufferAttribute;
9705
9706/**
9707 * @author mrdoob / http://mrdoob.com/
9708 */
9709
9710function DirectGeometry() {
9711
9712	this.vertices = [];
9713	this.normals = [];
9714	this.colors = [];
9715	this.uvs = [];
9716	this.uvs2 = [];
9717
9718	this.groups = [];
9719
9720	this.morphTargets = {};
9721
9722	this.skinWeights = [];
9723	this.skinIndices = [];
9724
9725	// this.lineDistances = [];
9726
9727	this.boundingBox = null;
9728	this.boundingSphere = null;
9729
9730	// update flags
9731
9732	this.verticesNeedUpdate = false;
vendor: 17,705 bytes, lines 9733-10653
9733	this.normalsNeedUpdate = false;
9734	this.colorsNeedUpdate = false;
9735	this.uvsNeedUpdate = false;
9736	this.groupsNeedUpdate = false;
9737
9738}
9739
9740Object.assign( DirectGeometry.prototype, {
9741
9742	computeGroups: function ( geometry ) {
9743
9744		var group;
9745		var groups = [];
9746		var materialIndex = undefined;
9747
9748		var faces = geometry.faces;
9749
9750		for ( var i = 0; i < faces.length; i ++ ) {
9751
9752			var face = faces[ i ];
9753
9754			// materials
9755
9756			if ( face.materialIndex !== materialIndex ) {
9757
9758				materialIndex = face.materialIndex;
9759
9760				if ( group !== undefined ) {
9761
9762					group.count = ( i * 3 ) - group.start;
9763					groups.push( group );
9764
9765				}
9766
9767				group = {
9768					start: i * 3,
9769					materialIndex: materialIndex
9770				};
9771
9772			}
9773
9774		}
9775
9776		if ( group !== undefined ) {
9777
9778			group.count = ( i * 3 ) - group.start;
9779			groups.push( group );
9780
9781		}
9782
9783		this.groups = groups;
9784
9785	},
9786
9787	fromGeometry: function ( geometry ) {
9788
9789		var faces = geometry.faces;
9790		var vertices = geometry.vertices;
9791		var faceVertexUvs = geometry.faceVertexUvs;
9792
9793		var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
9794		var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
9795
9796		// morphs
9797
9798		var morphTargets = geometry.morphTargets;
9799		var morphTargetsLength = morphTargets.length;
9800
9801		var morphTargetsPosition;
9802
9803		if ( morphTargetsLength > 0 ) {
9804
9805			morphTargetsPosition = [];
9806
9807			for ( var i = 0; i < morphTargetsLength; i ++ ) {
9808
9809				morphTargetsPosition[ i ] = {
9810					name: morphTargets[ i ].name,
9811				 	data: []
9812				};
9813
9814			}
9815
9816			this.morphTargets.position = morphTargetsPosition;
9817
9818		}
9819
9820		var morphNormals = geometry.morphNormals;
9821		var morphNormalsLength = morphNormals.length;
9822
9823		var morphTargetsNormal;
9824
9825		if ( morphNormalsLength > 0 ) {
9826
9827			morphTargetsNormal = [];
9828
9829			for ( var i = 0; i < morphNormalsLength; i ++ ) {
9830
9831				morphTargetsNormal[ i ] = {
9832					name: morphNormals[ i ].name,
9833				 	data: []
9834				};
9835
9836			}
9837
9838			this.morphTargets.normal = morphTargetsNormal;
9839
9840		}
9841
9842		// skins
9843
9844		var skinIndices = geometry.skinIndices;
9845		var skinWeights = geometry.skinWeights;
9846
9847		var hasSkinIndices = skinIndices.length === vertices.length;
9848		var hasSkinWeights = skinWeights.length === vertices.length;
9849
9850		//
9851
9852		if ( vertices.length > 0 && faces.length === 0 ) {
9853
9854			console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );
9855
9856		}
9857
9858		for ( var i = 0; i < faces.length; i ++ ) {
9859
9860			var face = faces[ i ];
9861
9862			this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );
9863
9864			var vertexNormals = face.vertexNormals;
9865
9866			if ( vertexNormals.length === 3 ) {
9867
9868				this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
9869
9870			} else {
9871
9872				var normal = face.normal;
9873
9874				this.normals.push( normal, normal, normal );
9875
9876			}
9877
9878			var vertexColors = face.vertexColors;
9879
9880			if ( vertexColors.length === 3 ) {
9881
9882				this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
9883
9884			} else {
9885
9886				var color = face.color;
9887
9888				this.colors.push( color, color, color );
9889
9890			}
9891
9892			if ( hasFaceVertexUv === true ) {
9893
9894				var vertexUvs = faceVertexUvs[ 0 ][ i ];
9895
9896				if ( vertexUvs !== undefined ) {
9897
9898					this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
9899
9900				} else {
9901
9902					console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
9903
9904					this.uvs.push( new Vector2(), new Vector2(), new Vector2() );
9905
9906				}
9907
9908			}
9909
9910			if ( hasFaceVertexUv2 === true ) {
9911
9912				var vertexUvs = faceVertexUvs[ 1 ][ i ];
9913
9914				if ( vertexUvs !== undefined ) {
9915
9916					this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
9917
9918				} else {
9919
9920					console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
9921
9922					this.uvs2.push( new Vector2(), new Vector2(), new Vector2() );
9923
9924				}
9925
9926			}
9927
9928			// morphs
9929
9930			for ( var j = 0; j < morphTargetsLength; j ++ ) {
9931
9932				var morphTarget = morphTargets[ j ].vertices;
9933
9934				morphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );
9935
9936			}
9937
9938			for ( var j = 0; j < morphNormalsLength; j ++ ) {
9939
9940				var morphNormal = morphNormals[ j ].vertexNormals[ i ];
9941
9942				morphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );
9943
9944			}
9945
9946			// skins
9947
9948			if ( hasSkinIndices ) {
9949
9950				this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );
9951
9952			}
9953
9954			if ( hasSkinWeights ) {
9955
9956				this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );
9957
9958			}
9959
9960		}
9961
9962		this.computeGroups( geometry );
9963
9964		this.verticesNeedUpdate = geometry.verticesNeedUpdate;
9965		this.normalsNeedUpdate = geometry.normalsNeedUpdate;
9966		this.colorsNeedUpdate = geometry.colorsNeedUpdate;
9967		this.uvsNeedUpdate = geometry.uvsNeedUpdate;
9968		this.groupsNeedUpdate = geometry.groupsNeedUpdate;
9969
9970		if ( geometry.boundingSphere !== null ) {
9971
9972			this.boundingSphere = geometry.boundingSphere.clone();
9973
9974		}
9975
9976		if ( geometry.boundingBox !== null ) {
9977
9978			this.boundingBox = geometry.boundingBox.clone();
9979
9980		}
9981
9982		return this;
9983
9984	}
9985
9986} );
9987
9988/**
9989 * @author mrdoob / http://mrdoob.com/
9990 */
9991
9992function arrayMax( array ) {
9993
9994	if ( array.length === 0 ) return - Infinity;
9995
9996	var max = array[ 0 ];
9997
9998	for ( var i = 1, l = array.length; i < l; ++ i ) {
9999
10000		if ( array[ i ] > max ) max = array[ i ];
10001
10002	}
10003
10004	return max;
10005
10006}
10007
10008/**
10009 * @author alteredq / http://alteredqualia.com/
10010 * @author mrdoob / http://mrdoob.com/
10011 */
10012
10013var _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id
10014
10015var _m1$2 = new Matrix4();
10016var _obj = new Object3D();
10017var _offset = new Vector3();
10018var _box$2 = new Box3();
10019var _boxMorphTargets = new Box3();
10020var _vector$4 = new Vector3();
10021
10022function BufferGeometry() {
10023
10024	Object.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );
10025
10026	this.uuid = MathUtils.generateUUID();
10027
10028	this.name = '';
10029	this.type = 'BufferGeometry';
10030
10031	this.index = null;
10032	this.attributes = {};
10033
10034	this.morphAttributes = {};
10035	this.morphTargetsRelative = false;
10036
10037	this.groups = [];
10038
10039	this.boundingBox = null;
10040	this.boundingSphere = null;
10041
10042	this.drawRange = { start: 0, count: Infinity };
10043
10044	this.userData = {};
10045
10046}
10047
10048BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
10049
10050	constructor: BufferGeometry,
10051
10052	isBufferGeometry: true,
10053
10054	getIndex: function () {
10055
10056		return this.index;
10057
10058	},
10059
10060	setIndex: function ( index ) {
10061
10062		if ( Array.isArray( index ) ) {
10063
10064			this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
10065
10066		} else {
10067
10068			this.index = index;
10069
10070		}
10071
10072	},
10073
10074	getAttribute: function ( name ) {
10075
10076		return this.attributes[ name ];
10077
10078	},
10079
10080	setAttribute: function ( name, attribute ) {
10081
10082		this.attributes[ name ] = attribute;
10083
10084		return this;
10085
10086	},
10087
10088	deleteAttribute: function ( name ) {
10089
10090		delete this.attributes[ name ];
10091
10092		return this;
10093
10094	},
10095
10096	addGroup: function ( start, count, materialIndex ) {
10097
10098		this.groups.push( {
10099
10100			start: start,
10101			count: count,
10102			materialIndex: materialIndex !== undefined ? materialIndex : 0
10103
10104		} );
10105
10106	},
10107
10108	clearGroups: function () {
10109
10110		this.groups = [];
10111
10112	},
10113
10114	setDrawRange: function ( start, count ) {
10115
10116		this.drawRange.start = start;
10117		this.drawRange.count = count;
10118
10119	},
10120
10121	applyMatrix4: function ( matrix ) {
10122
10123		var position = this.attributes.position;
10124
10125		if ( position !== undefined ) {
10126
10127			position.applyMatrix4( matrix );
10128
10129			position.needsUpdate = true;
10130
10131		}
10132
10133		var normal = this.attributes.normal;
10134
10135		if ( normal !== undefined ) {
10136
10137			var normalMatrix = new Matrix3().getNormalMatrix( matrix );
10138
10139			normal.applyNormalMatrix( normalMatrix );
10140
10141			normal.needsUpdate = true;
10142
10143		}
10144
10145		var tangent = this.attributes.tangent;
10146
10147		if ( tangent !== undefined ) {
10148
10149			tangent.transformDirection( matrix );
10150
10151			tangent.needsUpdate = true;
10152
10153		}
10154
10155		if ( this.boundingBox !== null ) {
10156
10157			this.computeBoundingBox();
10158
10159		}
10160
10161		if ( this.boundingSphere !== null ) {
10162
10163			this.computeBoundingSphere();
10164
10165		}
10166
10167		return this;
10168
10169	},
10170
10171	rotateX: function ( angle ) {
10172
10173		// rotate geometry around world x-axis
10174
10175		_m1$2.makeRotationX( angle );
10176
10177		this.applyMatrix4( _m1$2 );
10178
10179		return this;
10180
10181	},
10182
10183	rotateY: function ( angle ) {
10184
10185		// rotate geometry around world y-axis
10186
10187		_m1$2.makeRotationY( angle );
10188
10189		this.applyMatrix4( _m1$2 );
10190
10191		return this;
10192
10193	},
10194
10195	rotateZ: function ( angle ) {
10196
10197		// rotate geometry around world z-axis
10198
10199		_m1$2.makeRotationZ( angle );
10200
10201		this.applyMatrix4( _m1$2 );
10202
10203		return this;
10204
10205	},
10206
10207	translate: function ( x, y, z ) {
10208
10209		// translate geometry
10210
10211		_m1$2.makeTranslation( x, y, z );
10212
10213		this.applyMatrix4( _m1$2 );
10214
10215		return this;
10216
10217	},
10218
10219	scale: function ( x, y, z ) {
10220
10221		// scale geometry
10222
10223		_m1$2.makeScale( x, y, z );
10224
10225		this.applyMatrix4( _m1$2 );
10226
10227		return this;
10228
10229	},
10230
10231	lookAt: function ( vector ) {
10232
10233		_obj.lookAt( vector );
10234
10235		_obj.updateMatrix();
10236
10237		this.applyMatrix4( _obj.matrix );
10238
10239		return this;
10240
10241	},
10242
10243	center: function () {
10244
10245		this.computeBoundingBox();
10246
10247		this.boundingBox.getCenter( _offset ).negate();
10248
10249		this.translate( _offset.x, _offset.y, _offset.z );
10250
10251		return this;
10252
10253	},
10254
10255	setFromObject: function ( object ) {
10256
10257		// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );
10258
10259		var geometry = object.geometry;
10260
10261		if ( object.isPoints || object.isLine ) {
10262
10263			var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );
10264			var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );
10265
10266			this.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );
10267			this.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );
10268
10269			if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {
10270
10271				var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );
10272
10273				this.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
10274
10275			}
10276
10277			if ( geometry.boundingSphere !== null ) {
10278
10279				this.boundingSphere = geometry.boundingSphere.clone();
10280
10281			}
10282
10283			if ( geometry.boundingBox !== null ) {
10284
10285				this.boundingBox = geometry.boundingBox.clone();
10286
10287			}
10288
10289		} else if ( object.isMesh ) {
10290
10291			if ( geometry && geometry.isGeometry ) {
10292
10293				this.fromGeometry( geometry );
10294
10295			}
10296
10297		}
10298
10299		return this;
10300
10301	},
10302
10303	setFromPoints: function ( points ) {
10304
10305		var position = [];
10306
10307		for ( var i = 0, l = points.length; i < l; i ++ ) {
10308
10309			var point = points[ i ];
10310			position.push( point.x, point.y, point.z || 0 );
10311
10312		}
10313
10314		this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
10315
10316		return this;
10317
10318	},
10319
10320	updateFromObject: function ( object ) {
10321
10322		var geometry = object.geometry;
10323
10324		if ( object.isMesh ) {
10325
10326			var direct = geometry.__directGeometry;
10327
10328			if ( geometry.elementsNeedUpdate === true ) {
10329
10330				direct = undefined;
10331				geometry.elementsNeedUpdate = false;
10332
10333			}
10334
10335			if ( direct === undefined ) {
10336
10337				return this.fromGeometry( geometry );
10338
10339			}
10340
10341			direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
10342			direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
10343			direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
10344			direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
10345			direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
10346
10347			geometry.verticesNeedUpdate = false;
10348			geometry.normalsNeedUpdate = false;
10349			geometry.colorsNeedUpdate = false;
10350			geometry.uvsNeedUpdate = false;
10351			geometry.groupsNeedUpdate = false;
10352
10353			geometry = direct;
10354
10355		}
10356
10357		var attribute;
10358
10359		if ( geometry.verticesNeedUpdate === true ) {
10360
10361			attribute = this.attributes.position;
10362
10363			if ( attribute !== undefined ) {
10364
10365				attribute.copyVector3sArray( geometry.vertices );
10366				attribute.needsUpdate = true;
10367
10368			}
10369
10370			geometry.verticesNeedUpdate = false;
10371
10372		}
10373
10374		if ( geometry.normalsNeedUpdate === true ) {
10375
10376			attribute = this.attributes.normal;
10377
10378			if ( attribute !== undefined ) {
10379
10380				attribute.copyVector3sArray( geometry.normals );
10381				attribute.needsUpdate = true;
10382
10383			}
10384
10385			geometry.normalsNeedUpdate = false;
10386
10387		}
10388
10389		if ( geometry.colorsNeedUpdate === true ) {
10390
10391			attribute = this.attributes.color;
10392
10393			if ( attribute !== undefined ) {
10394
10395				attribute.copyColorsArray( geometry.colors );
10396				attribute.needsUpdate = true;
10397
10398			}
10399
10400			geometry.colorsNeedUpdate = false;
10401
10402		}
10403
10404		if ( geometry.uvsNeedUpdate ) {
10405
10406			attribute = this.attributes.uv;
10407
10408			if ( attribute !== undefined ) {
10409
10410				attribute.copyVector2sArray( geometry.uvs );
10411				attribute.needsUpdate = true;
10412
10413			}
10414
10415			geometry.uvsNeedUpdate = false;
10416
10417		}
10418
10419		if ( geometry.lineDistancesNeedUpdate ) {
10420
10421			attribute = this.attributes.lineDistance;
10422
10423			if ( attribute !== undefined ) {
10424
10425				attribute.copyArray( geometry.lineDistances );
10426				attribute.needsUpdate = true;
10427
10428			}
10429
10430			geometry.lineDistancesNeedUpdate = false;
10431
10432		}
10433
10434		if ( geometry.groupsNeedUpdate ) {
10435
10436			geometry.computeGroups( object.geometry );
10437			this.groups = geometry.groups;
10438
10439			geometry.groupsNeedUpdate = false;
10440
10441		}
10442
10443		return this;
10444
10445	},
10446
10447	fromGeometry: function ( geometry ) {
10448
10449		geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
10450
10451		return this.fromDirectGeometry( geometry.__directGeometry );
10452
10453	},
10454
10455	fromDirectGeometry: function ( geometry ) {
10456
10457		var positions = new Float32Array( geometry.vertices.length * 3 );
10458		this.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );
10459
10460		if ( geometry.normals.length > 0 ) {
10461
10462			var normals = new Float32Array( geometry.normals.length * 3 );
10463			this.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );
10464
10465		}
10466
10467		if ( geometry.colors.length > 0 ) {
10468
10469			var colors = new Float32Array( geometry.colors.length * 3 );
10470			this.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );
10471
10472		}
10473
10474		if ( geometry.uvs.length > 0 ) {
10475
10476			var uvs = new Float32Array( geometry.uvs.length * 2 );
10477			this.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );
10478
10479		}
10480
10481		if ( geometry.uvs2.length > 0 ) {
10482
10483			var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
10484			this.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
10485
10486		}
10487
10488		// groups
10489
10490		this.groups = geometry.groups;
10491
10492		// morphs
10493
10494		for ( var name in geometry.morphTargets ) {
10495
10496			var array = [];
10497			var morphTargets = geometry.morphTargets[ name ];
10498
10499			for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
10500
10501				var morphTarget = morphTargets[ i ];
10502
10503				var attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );
10504				attribute.name = morphTarget.name;
10505
10506				array.push( attribute.copyVector3sArray( morphTarget.data ) );
10507
10508			}
10509
10510			this.morphAttributes[ name ] = array;
10511
10512		}
10513
10514		// skinning
10515
10516		if ( geometry.skinIndices.length > 0 ) {
10517
10518			var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
10519			this.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );
10520
10521		}
10522
10523		if ( geometry.skinWeights.length > 0 ) {
10524
10525			var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
10526			this.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );
10527
10528		}
10529
10530		//
10531
10532		if ( geometry.boundingSphere !== null ) {
10533
10534			this.boundingSphere = geometry.boundingSphere.clone();
10535
10536		}
10537
10538		if ( geometry.boundingBox !== null ) {
10539
10540			this.boundingBox = geometry.boundingBox.clone();
10541
10542		}
10543
10544		return this;
10545
10546	},
10547
10548	computeBoundingBox: function () {
10549
10550		if ( this.boundingBox === null ) {
10551
10552			this.boundingBox = new Box3();
10553
10554		}
10555
10556		var position = this.attributes.position;
10557		var morphAttributesPosition = this.morphAttributes.position;
10558
10559		if ( position !== undefined ) {
10560
10561			this.boundingBox.setFromBufferAttribute( position );
10562
10563			// process morph attributes if present
10564
10565			if ( morphAttributesPosition ) {
10566
10567				for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10568
10569					var morphAttribute = morphAttributesPosition[ i ];
10570					_box$2.setFromBufferAttribute( morphAttribute );
10571
10572					if ( this.morphTargetsRelative ) {
10573
10574						_vector$4.addVectors( this.boundingBox.min, _box$2.min );
10575						this.boundingBox.expandByPoint( _vector$4 );
10576
10577						_vector$4.addVectors( this.boundingBox.max, _box$2.max );
10578						this.boundingBox.expandByPoint( _vector$4 );
10579
10580					} else {
10581
10582						this.boundingBox.expandByPoint( _box$2.min );
10583						this.boundingBox.expandByPoint( _box$2.max );
10584
10585					}
10586
10587				}
10588
10589			}
10590
10591		} else {
10592
10593			this.boundingBox.makeEmpty();
10594
10595		}
10596
10597		if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
10598
10599			console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
10600
10601		}
10602
10603	},
10604
10605	computeBoundingSphere: function () {
10606
10607		if ( this.boundingSphere === null ) {
10608
10609			this.boundingSphere = new Sphere();
10610
10611		}
10612
10613		var position = this.attributes.position;
10614		var morphAttributesPosition = this.morphAttributes.position;
10615
10616		if ( position ) {
10617
10618			// first, find the center of the bounding sphere
10619
10620			var center = this.boundingSphere.center;
10621
10622			_box$2.setFromBufferAttribute( position );
10623
10624			// process morph attributes if present
10625
10626			if ( morphAttributesPosition ) {
10627
10628				for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10629
10630					var morphAttribute = morphAttributesPosition[ i ];
10631					_boxMorphTargets.setFromBufferAttribute( morphAttribute );
10632
10633					if ( this.morphTargetsRelative ) {
10634
10635						_vector$4.addVectors( _box$2.min, _boxMorphTargets.min );
10636						_box$2.expandByPoint( _vector$4 );
10637
10638						_vector$4.addVectors( _box$2.max, _boxMorphTargets.max );
10639						_box$2.expandByPoint( _vector$4 );
10640
10641					} else {
10642
10643						_box$2.expandByPoint( _boxMorphTargets.min );
10644						_box$2.expandByPoint( _boxMorphTargets.max );
10645
10646					}
10647
10648				}
10649
10650			}
10651
10652			_box$2.getCenter( center );
10653
10654			// second, try to find a boundingSphere with a radius smaller than the
10655			// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
10656
10657			var maxRadiusSq = 0;
10658
10659			for ( var i = 0, il = position.count; i < il; i ++ ) {
10660
10661				_vector$4.fromBufferAttribute( position, i );
10662
10663				maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
10664
10665			}
10666
10667			// process morph attributes if present
10668
10669			if ( morphAttributesPosition ) {
10670
10671				for ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10672
10673					var morphAttribute = morphAttributesPosition[ i ];
10674					var morphTargetsRelative = this.morphTargetsRelative;
10675
10676					for ( var j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
10677
10678						_vector$4.fromBufferAttribute( morphAttribute, j );
10679
10680						if ( morphTargetsRelative ) {
10681
10682							_offset.fromBufferAttribute( position, j );
10683							_vector$4.add( _offset );
10684
10685						}
10686
10687						maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$4 ) );
10688
10689					}
10690
10691				}
10692
10693			}
10694
10695			this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
10696
10697			if ( isNaN( this.boundingSphere.radius ) ) {
10698
10699				console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
10700
10701			}
10702
10703		}
10704
10705	},
10706
10707	computeFaceNormals: function () {
10708
10709		// backwards compatibility
10710
10711	},
10712
10713	computeVertexNormals: function () {
10714
10715		var index = this.index;
10716		var attributes = this.attributes;
10717
10718		if ( attributes.position ) {
10719
10720			var positions = attributes.position.array;
10721
10722			if ( attributes.normal === undefined ) {
10723
10724				this.setAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );
10725
10726			} else {
10727
10728				// reset existing normals to zero
10729
10730				var array = attributes.normal.array;
10731
10732				for ( var i = 0, il = array.length; i < il; i ++ ) {
10733
10734					array[ i ] = 0;
10735
10736				}
10737
10738			}
10739
10740			var normals = attributes.normal.array;
10741
10742			var vA, vB, vC;
10743			var pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
10744			var cb = new Vector3(), ab = new Vector3();
10745
10746			// indexed elements
10747
10748			if ( index ) {
10749
10750				var indices = index.array;
10751
10752				for ( var i = 0, il = index.count; i < il; i += 3 ) {
10753
10754					vA = indices[ i + 0 ] * 3;
10755					vB = indices[ i + 1 ] * 3;
10756					vC = indices[ i + 2 ] * 3;
10757
10758					pA.fromArray( positions, vA );
10759					pB.fromArray( positions, vB );
10760					pC.fromArray( positions, vC );
10761
10762					cb.subVectors( pC, pB );
10763					ab.subVectors( pA, pB );
10764					cb.cross( ab );
10765
10766					normals[ vA ] += cb.x;
10767					normals[ vA + 1 ] += cb.y;
10768					normals[ vA + 2 ] += cb.z;
10769
10770					normals[ vB ] += cb.x;
10771					normals[ vB + 1 ] += cb.y;
10772					normals[ vB + 2 ] += cb.z;
10773
10774					normals[ vC ] += cb.x;
10775					normals[ vC + 1 ] += cb.y;
10776					normals[ vC + 2 ] += cb.z;
10777
10778				}
10779
10780			} else {
10781
10782				// non-indexed elements (unconnected triangle soup)
10783
10784				for ( var i = 0, il = positions.length; i < il; i += 9 ) {
10785
10786					pA.fromArray( positions, i );
10787					pB.fromArray( positions, i + 3 );
10788					pC.fromArray( positions, i + 6 );
10789
10790					cb.subVectors( pC, pB );
10791					ab.subVectors( pA, pB );
10792					cb.cross( ab );
10793
10794					normals[ i ] = cb.x;
10795					normals[ i + 1 ] = cb.y;
10796					normals[ i + 2 ] = cb.z;
10797
10798					normals[ i + 3 ] = cb.x;
10799					normals[ i + 4 ] = cb.y;
10800					normals[ i + 5 ] = cb.z;
10801
10802					normals[ i + 6 ] = cb.x;
10803					normals[ i + 7 ] = cb.y;
10804					normals[ i + 8 ] = cb.z;
10805
10806				}
10807
10808			}
10809
10810			this.normalizeNormals();
10811
10812			attributes.normal.needsUpdate = true;
10813
10814		}
10815
10816	},
10817
10818	merge: function ( geometry, offset ) {
10819
10820		if ( ! ( geometry && geometry.isBufferGeometry ) ) {
10821
10822			console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );
10823			return;
10824
10825		}
10826
10827		if ( offset === undefined ) {
10828
10829			offset = 0;
10830
10831			console.warn(
10832				'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '
10833				+ 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'
10834			);
10835
10836		}
10837
10838		var attributes = this.attributes;
10839
10840		for ( var key in attributes ) {
10841
10842			if ( geometry.attributes[ key ] === undefined ) continue;
10843
10844			var attribute1 = attributes[ key ];
10845			var attributeArray1 = attribute1.array;
10846
10847			var attribute2 = geometry.attributes[ key ];
10848			var attributeArray2 = attribute2.array;
10849
10850			var attributeOffset = attribute2.itemSize * offset;
10851			var length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );
10852
10853			for ( var i = 0, j = attributeOffset; i < length; i ++, j ++ ) {
10854
10855				attributeArray1[ j ] = attributeArray2[ i ];
10856
10857			}
10858
10859		}
10860
10861		return this;
10862
10863	},
10864
10865	normalizeNormals: function () {
10866
10867		var normals = this.attributes.normal;
10868
10869		for ( var i = 0, il = normals.count; i < il; i ++ ) {
10870
10871			_vector$4.x = normals.getX( i );
10872			_vector$4.y = normals.getY( i );
10873			_vector$4.z = normals.getZ( i );
10874
10875			_vector$4.normalize();
10876
10877			normals.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );
10878
10879		}
10880
10881	},
10882
10883	toNonIndexed: function () {
10884
10885		function convertBufferAttribute( attribute, indices ) {
10886
10887			var array = attribute.array;
10888			var itemSize = attribute.itemSize;
10889
10890			var array2 = new array.constructor( indices.length * itemSize );
10891
10892			var index = 0, index2 = 0;
10893
10894			for ( var i = 0, l = indices.length; i < l; i ++ ) {
10895
10896				index = indices[ i ] * itemSize;
10897
10898				for ( var j = 0; j < itemSize; j ++ ) {
10899
10900					array2[ index2 ++ ] = array[ index ++ ];
10901
10902				}
10903
10904			}
10905
10906			return new BufferAttribute( array2, itemSize );
10907
10908		}
10909
10910		//
10911
10912		if ( this.index === null ) {
10913
10914			console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );
10915			return this;
10916
10917		}
10918
10919		var geometry2 = new BufferGeometry();
10920
10921		var indices = this.index.array;
10922		var attributes = this.attributes;
10923
10924		// attributes
10925
10926		for ( var name in attributes ) {
10927
10928			var attribute = attributes[ name ];
10929
10930			var newAttribute = convertBufferAttribute( attribute, indices );
10931
10932			geometry2.setAttribute( name, newAttribute );
10933
10934		}
10935
10936		// morph attributes
10937
10938		var morphAttributes = this.morphAttributes;
10939
10940		for ( name in morphAttributes ) {
10941
10942			var morphArray = [];
10943			var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
10944
10945			for ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {
10946
10947				var attribute = morphAttribute[ i ];
10948
10949				var newAttribute = convertBufferAttribute( attribute, indices );
10950
10951				morphArray.push( newAttribute );
10952
10953			}
10954
10955			geometry2.morphAttributes[ name ] = morphArray;
10956
10957		}
10958
10959		geometry2.morphTargetsRelative = this.morphTargetsRelative;
10960
10961		// groups
10962
10963		var groups = this.groups;
10964
10965		for ( var i = 0, l = groups.length; i < l; i ++ ) {
10966
10967			var group = groups[ i ];
10968			geometry2.addGroup( group.start, group.count, group.materialIndex );
10969
10970		}
10971
10972		return geometry2;
10973
10974	},
vendor: 16,177 bytes, lines 10975-11736
10975
10976	toJSON: function () {
10977
10978		var data = {
10979			metadata: {
10980				version: 4.5,
10981				type: 'BufferGeometry',
10982				generator: 'BufferGeometry.toJSON'
10983			}
10984		};
10985
10986		// standard BufferGeometry serialization
10987
10988		data.uuid = this.uuid;
10989		data.type = this.type;
10990		if ( this.name !== '' ) data.name = this.name;
10991		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
10992
10993		if ( this.parameters !== undefined ) {
10994
10995			var parameters = this.parameters;
10996
10997			for ( var key in parameters ) {
10998
10999				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
11000
11001			}
11002
11003			return data;
11004
11005		}
11006
11007		data.data = { attributes: {} };
11008
11009		var index = this.index;
11010
11011		if ( index !== null ) {
11012
11013			data.data.index = {
11014				type: index.array.constructor.name,
11015				array: Array.prototype.slice.call( index.array )
11016			};
11017
11018		}
11019
11020		var attributes = this.attributes;
11021
11022		for ( var key in attributes ) {
11023
11024			var attribute = attributes[ key ];
11025
11026			var attributeData = attribute.toJSON();
11027
11028			if ( attribute.name !== '' ) attributeData.name = attribute.name;
11029
11030			data.data.attributes[ key ] = attributeData;
11031
11032		}
11033
11034		var morphAttributes = {};
11035		var hasMorphAttributes = false;
11036
11037		for ( var key in this.morphAttributes ) {
11038
11039			var attributeArray = this.morphAttributes[ key ];
11040
11041			var array = [];
11042
11043			for ( var i = 0, il = attributeArray.length; i < il; i ++ ) {
11044
11045				var attribute = attributeArray[ i ];
11046
11047				var attributeData = attribute.toJSON();
11048
11049				if ( attribute.name !== '' ) attributeData.name = attribute.name;
11050
11051				array.push( attributeData );
11052
11053			}
11054
11055			if ( array.length > 0 ) {
11056
11057				morphAttributes[ key ] = array;
11058
11059				hasMorphAttributes = true;
11060
11061			}
11062
11063		}
11064
11065		if ( hasMorphAttributes ) {
11066
11067			data.data.morphAttributes = morphAttributes;
11068			data.data.morphTargetsRelative = this.morphTargetsRelative;
11069
11070		}
11071
11072		var groups = this.groups;
11073
11074		if ( groups.length > 0 ) {
11075
11076			data.data.groups = JSON.parse( JSON.stringify( groups ) );
11077
11078		}
11079
11080		var boundingSphere = this.boundingSphere;
11081
11082		if ( boundingSphere !== null ) {
11083
11084			data.data.boundingSphere = {
11085				center: boundingSphere.center.toArray(),
11086				radius: boundingSphere.radius
11087			};
11088
11089		}
11090
11091		return data;
11092
11093	},
11094
11095	clone: function () {
11096
11097		/*
11098		 // Handle primitives
11099
11100		 var parameters = this.parameters;
11101
11102		 if ( parameters !== undefined ) {
11103
11104		 var values = [];
11105
11106		 for ( var key in parameters ) {
11107
11108		 values.push( parameters[ key ] );
11109
11110		 }
11111
11112		 var geometry = Object.create( this.constructor.prototype );
11113		 this.constructor.apply( geometry, values );
11114		 return geometry;
11115
11116		 }
11117
11118		 return new this.constructor().copy( this );
11119		 */
11120
11121		return new BufferGeometry().copy( this );
11122
11123	},
11124
11125	copy: function ( source ) {
11126
11127		var name, i, l;
11128
11129		// reset
11130
11131		this.index = null;
11132		this.attributes = {};
11133		this.morphAttributes = {};
11134		this.groups = [];
11135		this.boundingBox = null;
11136		this.boundingSphere = null;
11137
11138		// name
11139
11140		this.name = source.name;
11141
11142		// index
11143
11144		var index = source.index;
11145
11146		if ( index !== null ) {
11147
11148			this.setIndex( index.clone() );
11149
11150		}
11151
11152		// attributes
11153
11154		var attributes = source.attributes;
11155
11156		for ( name in attributes ) {
11157
11158			var attribute = attributes[ name ];
11159			this.setAttribute( name, attribute.clone() );
11160
11161		}
11162
11163		// morph attributes
11164
11165		var morphAttributes = source.morphAttributes;
11166
11167		for ( name in morphAttributes ) {
11168
11169			var array = [];
11170			var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
11171
11172			for ( i = 0, l = morphAttribute.length; i < l; i ++ ) {
11173
11174				array.push( morphAttribute[ i ].clone() );
11175
11176			}
11177
11178			this.morphAttributes[ name ] = array;
11179
11180		}
11181
11182		this.morphTargetsRelative = source.morphTargetsRelative;
11183
11184		// groups
11185
11186		var groups = source.groups;
11187
11188		for ( i = 0, l = groups.length; i < l; i ++ ) {
11189
11190			var group = groups[ i ];
11191			this.addGroup( group.start, group.count, group.materialIndex );
11192
11193		}
11194
11195		// bounding box
11196
11197		var boundingBox = source.boundingBox;
11198
11199		if ( boundingBox !== null ) {
11200
11201			this.boundingBox = boundingBox.clone();
11202
11203		}
11204
11205		// bounding sphere
11206
11207		var boundingSphere = source.boundingSphere;
11208
11209		if ( boundingSphere !== null ) {
11210
11211			this.boundingSphere = boundingSphere.clone();
11212
11213		}
11214
11215		// draw range
11216
11217		this.drawRange.start = source.drawRange.start;
11218		this.drawRange.count = source.drawRange.count;
11219
11220		// user data
11221
11222		this.userData = source.userData;
11223
11224		return this;
11225
11226	},
11227
11228	dispose: function () {
11229
11230		this.dispatchEvent( { type: 'dispose' } );
11231
11232	}
11233
11234} );
11235
11236/**
11237 * @author mrdoob / http://mrdoob.com/
11238 * @author alteredq / http://alteredqualia.com/
11239 * @author mikael emtinger / http://gomo.se/
11240 * @author jonobr1 / http://jonobr1.com/
11241 */
11242
11243var _inverseMatrix = new Matrix4();
11244var _ray = new Ray();
11245var _sphere = new Sphere();
11246
11247var _vA = new Vector3();
11248var _vB = new Vector3();
11249var _vC = new Vector3();
11250
11251var _tempA = new Vector3();
11252var _tempB = new Vector3();
11253var _tempC = new Vector3();
11254
11255var _morphA = new Vector3();
11256var _morphB = new Vector3();
11257var _morphC = new Vector3();
11258
11259var _uvA = new Vector2();
11260var _uvB = new Vector2();
11261var _uvC = new Vector2();
11262
11263var _intersectionPoint = new Vector3();
11264var _intersectionPointWorld = new Vector3();
11265
11266function Mesh( geometry, material ) {
11267
11268	Object3D.call( this );
11269
11270	this.type = 'Mesh';
11271
11272	this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
11273	this.material = material !== undefined ? material : new MeshBasicMaterial();
11274
11275	this.updateMorphTargets();
11276
11277}
11278
11279Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), {
11280
11281	constructor: Mesh,
11282
11283	isMesh: true,
11284
11285	copy: function ( source ) {
11286
11287		Object3D.prototype.copy.call( this, source );
11288
11289		if ( source.morphTargetInfluences !== undefined ) {
11290
11291			this.morphTargetInfluences = source.morphTargetInfluences.slice();
11292
11293		}
11294
11295		if ( source.morphTargetDictionary !== undefined ) {
11296
11297			this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
11298
11299		}
11300
11301		return this;
11302
11303	},
11304
11305	updateMorphTargets: function () {
11306
11307		var geometry = this.geometry;
11308		var m, ml, name;
11309
11310		if ( geometry.isBufferGeometry ) {
11311
11312			var morphAttributes = geometry.morphAttributes;
11313			var keys = Object.keys( morphAttributes );
11314
11315			if ( keys.length > 0 ) {
11316
11317				var morphAttribute = morphAttributes[ keys[ 0 ] ];
11318
11319				if ( morphAttribute !== undefined ) {
11320
11321					this.morphTargetInfluences = [];
11322					this.morphTargetDictionary = {};
11323
11324					for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
11325
11326						name = morphAttribute[ m ].name || String( m );
11327
11328						this.morphTargetInfluences.push( 0 );
11329						this.morphTargetDictionary[ name ] = m;
11330
11331					}
11332
11333				}
11334
11335			}
11336
11337		} else {
11338
11339			var morphTargets = geometry.morphTargets;
11340
11341			if ( morphTargets !== undefined && morphTargets.length > 0 ) {
11342
11343				console.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
11344
11345			}
11346
11347		}
11348
11349	},
11350
11351	raycast: function ( raycaster, intersects ) {
11352
11353		var geometry = this.geometry;
11354		var material = this.material;
11355		var matrixWorld = this.matrixWorld;
11356
11357		if ( material === undefined ) return;
11358
11359		// Checking boundingSphere distance to ray
11360
11361		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
11362
11363		_sphere.copy( geometry.boundingSphere );
11364		_sphere.applyMatrix4( matrixWorld );
11365
11366		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
11367
11368		//
11369
11370		_inverseMatrix.getInverse( matrixWorld );
11371		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
11372
11373		// Check boundingBox before continuing
11374
11375		if ( geometry.boundingBox !== null ) {
11376
11377			if ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;
11378
11379		}
11380
11381		var intersection;
11382
11383		if ( geometry.isBufferGeometry ) {
11384
11385			var a, b, c;
11386			var index = geometry.index;
11387			var position = geometry.attributes.position;
11388			var morphPosition = geometry.morphAttributes.position;
11389			var morphTargetsRelative = geometry.morphTargetsRelative;
11390			var uv = geometry.attributes.uv;
11391			var uv2 = geometry.attributes.uv2;
11392			var groups = geometry.groups;
11393			var drawRange = geometry.drawRange;
11394			var i, j, il, jl;
11395			var group, groupMaterial;
11396			var start, end;
11397
11398			if ( index !== null ) {
11399
11400				// indexed buffer geometry
11401
11402				if ( Array.isArray( material ) ) {
11403
11404					for ( i = 0, il = groups.length; i < il; i ++ ) {
11405
11406						group = groups[ i ];
11407						groupMaterial = material[ group.materialIndex ];
11408
11409						start = Math.max( group.start, drawRange.start );
11410						end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
11411
11412						for ( j = start, jl = end; j < jl; j += 3 ) {
11413
11414							a = index.getX( j );
11415							b = index.getX( j + 1 );
11416							c = index.getX( j + 2 );
11417
11418							intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11419
11420							if ( intersection ) {
11421
11422								intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
11423								intersection.face.materialIndex = group.materialIndex;
11424								intersects.push( intersection );
11425
11426							}
11427
11428						}
11429
11430					}
11431
11432				} else {
11433
11434					start = Math.max( 0, drawRange.start );
11435					end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
11436
11437					for ( i = start, il = end; i < il; i += 3 ) {
11438
11439						a = index.getX( i );
11440						b = index.getX( i + 1 );
11441						c = index.getX( i + 2 );
11442
11443						intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11444
11445						if ( intersection ) {
11446
11447							intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
11448							intersects.push( intersection );
11449
11450						}
11451
11452					}
11453
11454				}
11455
11456			} else if ( position !== undefined ) {
11457
11458				// non-indexed buffer geometry
11459
11460				if ( Array.isArray( material ) ) {
11461
11462					for ( i = 0, il = groups.length; i < il; i ++ ) {
11463
11464						group = groups[ i ];
11465						groupMaterial = material[ group.materialIndex ];
11466
11467						start = Math.max( group.start, drawRange.start );
11468						end = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );
11469
11470						for ( j = start, jl = end; j < jl; j += 3 ) {
11471
11472							a = j;
11473							b = j + 1;
11474							c = j + 2;
11475
11476							intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11477
11478							if ( intersection ) {
11479
11480								intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
11481								intersection.face.materialIndex = group.materialIndex;
11482								intersects.push( intersection );
11483
11484							}
11485
11486						}
11487
11488					}
11489
11490				} else {
11491
11492					start = Math.max( 0, drawRange.start );
11493					end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
11494
11495					for ( i = start, il = end; i < il; i += 3 ) {
11496
11497						a = i;
11498						b = i + 1;
11499						c = i + 2;
11500
11501						intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );
11502
11503						if ( intersection ) {
11504
11505							intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
11506							intersects.push( intersection );
11507
11508						}
11509
11510					}
11511
11512				}
11513
11514			}
11515
11516		} else if ( geometry.isGeometry ) {
11517
11518			var fvA, fvB, fvC;
11519			var isMultiMaterial = Array.isArray( material );
11520
11521			var vertices = geometry.vertices;
11522			var faces = geometry.faces;
11523			var uvs;
11524
11525			var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
11526			if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;
11527
11528			for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
11529
11530				var face = faces[ f ];
11531				var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;
11532
11533				if ( faceMaterial === undefined ) continue;
11534
11535				fvA = vertices[ face.a ];
11536				fvB = vertices[ face.b ];
11537				fvC = vertices[ face.c ];
11538
11539				intersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );
11540
11541				if ( intersection ) {
11542
11543					if ( uvs && uvs[ f ] ) {
11544
11545						var uvs_f = uvs[ f ];
11546						_uvA.copy( uvs_f[ 0 ] );
11547						_uvB.copy( uvs_f[ 1 ] );
11548						_uvC.copy( uvs_f[ 2 ] );
11549
11550						intersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );
11551
11552					}
11553
11554					intersection.face = face;
11555					intersection.faceIndex = f;
11556					intersects.push( intersection );
11557
11558				}
11559
11560			}
11561
11562		}
11563
11564	},
11565
11566	clone: function () {
11567
11568		return new this.constructor( this.geometry, this.material ).copy( this );
11569
11570	}
11571
11572} );
11573
11574function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
11575
11576	var intersect;
11577
11578	if ( material.side === BackSide ) {
11579
11580		intersect = ray.intersectTriangle( pC, pB, pA, true, point );
11581
11582	} else {
11583
11584		intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );
11585
11586	}
11587
11588	if ( intersect === null ) return null;
11589
11590	_intersectionPointWorld.copy( point );
11591	_intersectionPointWorld.applyMatrix4( object.matrixWorld );
11592
11593	var distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
11594
11595	if ( distance < raycaster.near || distance > raycaster.far ) return null;
11596
11597	return {
11598		distance: distance,
11599		point: _intersectionPointWorld.clone(),
11600		object: object
11601	};
11602
11603}
11604
11605function checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {
11606
11607	_vA.fromBufferAttribute( position, a );
11608	_vB.fromBufferAttribute( position, b );
11609	_vC.fromBufferAttribute( position, c );
11610
11611	var morphInfluences = object.morphTargetInfluences;
11612
11613	if ( material.morphTargets && morphPosition && morphInfluences ) {
11614
11615		_morphA.set( 0, 0, 0 );
11616		_morphB.set( 0, 0, 0 );
11617		_morphC.set( 0, 0, 0 );
11618
11619		for ( var i = 0, il = morphPosition.length; i < il; i ++ ) {
11620
11621			var influence = morphInfluences[ i ];
11622			var morphAttribute = morphPosition[ i ];
11623
11624			if ( influence === 0 ) continue;
11625
11626			_tempA.fromBufferAttribute( morphAttribute, a );
11627			_tempB.fromBufferAttribute( morphAttribute, b );
11628			_tempC.fromBufferAttribute( morphAttribute, c );
11629
11630			if ( morphTargetsRelative ) {
11631
11632				_morphA.addScaledVector( _tempA, influence );
11633				_morphB.addScaledVector( _tempB, influence );
11634				_morphC.addScaledVector( _tempC, influence );
11635
11636			} else {
11637
11638				_morphA.addScaledVector( _tempA.sub( _vA ), influence );
11639				_morphB.addScaledVector( _tempB.sub( _vB ), influence );
11640				_morphC.addScaledVector( _tempC.sub( _vC ), influence );
11641
11642			}
11643
11644		}
11645
11646		_vA.add( _morphA );
11647		_vB.add( _morphB );
11648		_vC.add( _morphC );
11649
11650	}
11651
11652	if ( object.isSkinnedMesh ) {
11653
11654		object.boneTransform( a, _vA );
11655		object.boneTransform( b, _vB );
11656		object.boneTransform( c, _vC );
11657
11658	}
11659
11660	var intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
11661
11662	if ( intersection ) {
11663
11664		if ( uv ) {
11665
11666			_uvA.fromBufferAttribute( uv, a );
11667			_uvB.fromBufferAttribute( uv, b );
11668			_uvC.fromBufferAttribute( uv, c );
11669
11670			intersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
11671
11672		}
11673
11674		if ( uv2 ) {
11675
11676			_uvA.fromBufferAttribute( uv2, a );
11677			_uvB.fromBufferAttribute( uv2, b );
11678			_uvC.fromBufferAttribute( uv2, c );
11679
11680			intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );
11681
11682		}
11683
11684		var face = new Face3( a, b, c );
11685		Triangle.getNormal( _vA, _vB, _vC, face.normal );
11686
11687		intersection.face = face;
11688
11689	}
11690
11691	return intersection;
11692
11693}
11694
11695/**
11696 * @author mrdoob / http://mrdoob.com/
11697 * @author kile / http://kile.stravaganza.org/
11698 * @author alteredq / http://alteredqualia.com/
11699 * @author mikael emtinger / http://gomo.se/
11700 * @author zz85 / http://www.lab4games.net/zz85/blog
11701 * @author bhouston / http://clara.io
11702 */
11703
11704var _geometryId = 0; // Geometry uses even numbers as Id
11705var _m1$3 = new Matrix4();
11706var _obj$1 = new Object3D();
11707var _offset$1 = new Vector3();
11708
11709function Geometry() {
11710
11711	Object.defineProperty( this, 'id', { value: _geometryId += 2 } );
11712
11713	this.uuid = MathUtils.generateUUID();
11714
11715	this.name = '';
11716	this.type = 'Geometry';
11717
11718	this.vertices = [];
11719	this.colors = [];
11720	this.faces = [];
11721	this.faceVertexUvs = [[]];
11722
11723	this.morphTargets = [];
11724	this.morphNormals = [];
11725
11726	this.skinWeights = [];
11727	this.skinIndices = [];
11728
11729	this.lineDistances = [];
11730
11731	this.boundingBox = null;
11732	this.boundingSphere = null;
11733
11734	// update flags
11735
11736	this.elementsNeedUpdate = false;
11737	this.verticesNeedUpdate = false;
11738	this.uvsNeedUpdate = false;
11739	this.normalsNeedUpdate = false;
11740	this.colorsNeedUpdate = false;
11741	this.lineDistancesNeedUpdate = false;
11742	this.groupsNeedUpdate = false;
11743
11744}
11745
11746Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
11747
11748	constructor: Geometry,
11749
11750	isGeometry: true,
11751
11752	applyMatrix4: function ( matrix ) {
11753
11754		var normalMatrix = new Matrix3().getNormalMatrix( matrix );
11755
11756		for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
11757
11758			var vertex = this.vertices[ i ];
11759			vertex.applyMatrix4( matrix );
11760
11761		}
11762
11763		for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
11764
11765			var face = this.faces[ i ];
11766			face.normal.applyMatrix3( normalMatrix ).normalize();
11767
11768			for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
11769
11770				face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
11771
11772			}
11773
11774		}
11775
11776		if ( this.boundingBox !== null ) {
11777
11778			this.computeBoundingBox();
11779
11780		}
11781
11782		if ( this.boundingSphere !== null ) {
11783
11784			this.computeBoundingSphere();
11785
11786		}
11787
11788		this.verticesNeedUpdate = true;
11789		this.normalsNeedUpdate = true;
11790
11791		return this;
11792
11793	},
11794
11795	rotateX: function ( angle ) {
11796
11797		// rotate geometry around world x-axis
11798
11799		_m1$3.makeRotationX( angle );
11800
11801		this.applyMatrix4( _m1$3 );
11802
11803		return this;
11804
11805	},
11806
11807	rotateY: function ( angle ) {
11808
11809		// rotate geometry around world y-axis
11810
11811		_m1$3.makeRotationY( angle );
11812
11813		this.applyMatrix4( _m1$3 );
11814
11815		return this;
11816
11817	},
11818
11819	rotateZ: function ( angle ) {
11820
11821		// rotate geometry around world z-axis
11822
11823		_m1$3.makeRotationZ( angle );
11824
11825		this.applyMatrix4( _m1$3 );
11826
11827		return this;
11828
11829	},
11830
11831	translate: function ( x, y, z ) {
11832
11833		// translate geometry
11834
11835		_m1$3.makeTranslation( x, y, z );
11836
11837		this.applyMatrix4( _m1$3 );
11838
11839		return this;
11840
11841	},
11842
11843	scale: function ( x, y, z ) {
11844
11845		// scale geometry
11846
11847		_m1$3.makeScale( x, y, z );
11848
11849		this.applyMatrix4( _m1$3 );
11850
11851		return this;
11852
11853	},
11854
11855	lookAt: function ( vector ) {
11856
11857		_obj$1.lookAt( vector );
11858
11859		_obj$1.updateMatrix();
11860
11861		this.applyMatrix4( _obj$1.matrix );
11862
11863		return this;
11864
11865	},
11866
11867	fromBufferGeometry: function ( geometry ) {
11868
11869		var scope = this;
11870
11871		var indices = geometry.index !== null ? geometry.index.array : undefined;
11872		var attributes = geometry.attributes;
11873
11874		if ( attributes.position === undefined ) {
11875
11876			console.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );
11877			return this;
11878
11879		}
11880
11881		var positions = attributes.position.array;
11882		var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
11883		var colors = attributes.color !== undefined ? attributes.color.array : undefined;
11884		var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
11885		var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
11886
11887		if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
11888
11889		for ( var i = 0; i < positions.length; i += 3 ) {
11890
11891			scope.vertices.push( new Vector3().fromArray( positions, i ) );
11892
11893			if ( colors !== undefined ) {
11894
11895				scope.colors.push( new Color().fromArray( colors, i ) );
11896
11897			}
11898
11899		}
11900
11901		function addFace( a, b, c, materialIndex ) {
11902
11903			var vertexColors = ( colors === undefined ) ? [] : [
11904				scope.colors[ a ].clone(),
11905				scope.colors[ b ].clone(),
11906				scope.colors[ c ].clone() ];
11907
11908			var vertexNormals = ( normals === undefined ) ? [] : [
11909				new Vector3().fromArray( normals, a * 3 ),
11910				new Vector3().fromArray( normals, b * 3 ),
11911				new Vector3().fromArray( normals, c * 3 )
11912			];
11913
11914			var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );
11915
11916			scope.faces.push( face );
11917
11918			if ( uvs !== undefined ) {
11919
11920				scope.faceVertexUvs[ 0 ].push( [
11921					new Vector2().fromArray( uvs, a * 2 ),
11922					new Vector2().fromArray( uvs, b * 2 ),
11923					new Vector2().fromArray( uvs, c * 2 )
11924				] );
11925
11926			}
11927
11928			if ( uvs2 !== undefined ) {
11929
11930				scope.faceVertexUvs[ 1 ].push( [
11931					new Vector2().fromArray( uvs2, a * 2 ),
11932					new Vector2().fromArray( uvs2, b * 2 ),
11933					new Vector2().fromArray( uvs2, c * 2 )
11934				] );
11935
11936			}
11937
11938		}
11939
11940		var groups = geometry.groups;
11941
11942		if ( groups.length > 0 ) {
11943
11944			for ( var i = 0; i < groups.length; i ++ ) {
11945
11946				var group = groups[ i ];
11947
11948				var start = group.start;
11949				var count = group.count;
11950
11951				for ( var j = start, jl = start + count; j < jl; j += 3 ) {
11952
11953					if ( indices !== undefined ) {
11954
11955						addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );
11956
11957					} else {
11958
11959						addFace( j, j + 1, j + 2, group.materialIndex );
11960
11961					}
11962
11963				}
11964
11965			}
11966
11967		} else {
11968
11969			if ( indices !== undefined ) {
11970
11971				for ( var i = 0; i < indices.length; i += 3 ) {
11972
11973					addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
11974
11975				}
11976
11977			} else {
11978
11979				for ( var i = 0; i < positions.length / 3; i += 3 ) {
11980
11981					addFace( i, i + 1, i + 2 );
11982
11983				}
11984
11985			}
11986
11987		}
11988
11989		this.computeFaceNormals();
11990
11991		if ( geometry.boundingBox !== null ) {
11992
11993			this.boundingBox = geometry.boundingBox.clone();
11994
11995		}
11996
11997		if ( geometry.boundingSphere !== null ) {
11998
11999			this.boundingSphere = geometry.boundingSphere.clone();
12000
12001		}
12002
12003		return this;
12004
12005	},
12006
12007	center: function () {
12008
12009		this.computeBoundingBox();
12010
12011		this.boundingBox.getCenter( _offset$1 ).negate();
12012
12013		this.translate( _offset$1.x, _offset$1.y, _offset$1.z );
12014
12015		return this;
12016
12017	},
12018
12019	normalize: function () {
12020
12021		this.computeBoundingSphere();
12022
12023		var center = this.boundingSphere.center;
12024		var radius = this.boundingSphere.radius;
12025
12026		var s = radius === 0 ? 1 : 1.0 / radius;
12027
12028		var matrix = new Matrix4();
12029		matrix.set(
12030			s, 0, 0, - s * center.x,
12031			0, s, 0, - s * center.y,
12032			0, 0, s, - s * center.z,
12033			0, 0, 0, 1
12034		);
12035
12036		this.applyMatrix4( matrix );
12037
12038		return this;
12039
12040	},
12041
12042	computeFaceNormals: function () {
12043
12044		var cb = new Vector3(), ab = new Vector3();
12045
12046		for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
12047
12048			var face = this.faces[ f ];
12049
12050			var vA = this.vertices[ face.a ];
12051			var vB = this.vertices[ face.b ];
12052			var vC = this.vertices[ face.c ];
12053
12054			cb.subVectors( vC, vB );
12055			ab.subVectors( vA, vB );
12056			cb.cross( ab );
12057
12058			cb.normalize();
12059
12060			face.normal.copy( cb );
12061
12062		}
12063
12064	},
12065
12066	computeVertexNormals: function ( areaWeighted ) {
12067
12068		if ( areaWeighted === undefined ) areaWeighted = true;
12069
12070		var v, vl, f, fl, face, vertices;
12071
12072		vertices = new Array( this.vertices.length );
12073
12074		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
12075
12076			vertices[ v ] = new Vector3();
12077
12078		}
12079
12080		if ( areaWeighted ) {
12081
12082			// vertex normals weighted by triangle areas
12083			// http://www.iquilezles.org/www/articles/normals/normals.htm
12084
12085			var vA, vB, vC;
12086			var cb = new Vector3(), ab = new Vector3();
12087
12088			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12089
12090				face = this.faces[ f ];
12091
12092				vA = this.vertices[ face.a ];
12093				vB = this.vertices[ face.b ];
12094				vC = this.vertices[ face.c ];
12095
12096				cb.subVectors( vC, vB );
12097				ab.subVectors( vA, vB );
12098				cb.cross( ab );
12099
12100				vertices[ face.a ].add( cb );
12101				vertices[ face.b ].add( cb );
12102				vertices[ face.c ].add( cb );
12103
12104			}
12105
12106		} else {
12107
12108			this.computeFaceNormals();
12109
12110			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12111
12112				face = this.faces[ f ];
12113
12114				vertices[ face.a ].add( face.normal );
12115				vertices[ face.b ].add( face.normal );
12116				vertices[ face.c ].add( face.normal );
12117
12118			}
12119
12120		}
12121
12122		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
12123
12124			vertices[ v ].normalize();
12125
12126		}
12127
12128		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12129
12130			face = this.faces[ f ];
12131
12132			var vertexNormals = face.vertexNormals;
12133
12134			if ( vertexNormals.length === 3 ) {
12135
12136				vertexNormals[ 0 ].copy( vertices[ face.a ] );
12137				vertexNormals[ 1 ].copy( vertices[ face.b ] );
12138				vertexNormals[ 2 ].copy( vertices[ face.c ] );
12139
12140			} else {
12141
12142				vertexNormals[ 0 ] = vertices[ face.a ].clone();
12143				vertexNormals[ 1 ] = vertices[ face.b ].clone();
12144				vertexNormals[ 2 ] = vertices[ face.c ].clone();
12145
12146			}
12147
12148		}
12149
12150		if ( this.faces.length > 0 ) {
12151
12152			this.normalsNeedUpdate = true;
12153
12154		}
12155
12156	},
12157
12158	computeFlatVertexNormals: function () {
12159
12160		var f, fl, face;
12161
12162		this.computeFaceNormals();
12163
12164		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12165
12166			face = this.faces[ f ];
12167
12168			var vertexNormals = face.vertexNormals;
12169
12170			if ( vertexNormals.length === 3 ) {
12171
12172				vertexNormals[ 0 ].copy( face.normal );
12173				vertexNormals[ 1 ].copy( face.normal );
12174				vertexNormals[ 2 ].copy( face.normal );
12175
12176			} else {
12177
12178				vertexNormals[ 0 ] = face.normal.clone();
12179				vertexNormals[ 1 ] = face.normal.clone();
12180				vertexNormals[ 2 ] = face.normal.clone();
12181
12182			}
12183
12184		}
12185
12186		if ( this.faces.length > 0 ) {
12187
12188			this.normalsNeedUpdate = true;
12189
12190		}
12191
12192	},
12193
12194	computeMorphNormals: function () {
12195
12196		var i, il, f, fl, face;
12197
12198		// save original normals
12199		// - create temp variables on first access
12200		//   otherwise just copy (for faster repeated calls)
12201
12202		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12203
12204			face = this.faces[ f ];
12205
12206			if ( ! face.__originalFaceNormal ) {
12207
12208				face.__originalFaceNormal = face.normal.clone();
12209
12210			} else {
12211
12212				face.__originalFaceNormal.copy( face.normal );
12213
12214			}
12215
12216			if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
12217
12218			for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
12219
12220				if ( ! face.__originalVertexNormals[ i ] ) {
12221
12222					face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
12223
12224				} else {
12225
12226					face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
12227
12228				}
12229
12230			}
12231
12232		}
12233
12234		// use temp geometry to compute face and vertex normals for each morph
12235
12236		var tmpGeo = new Geometry();
12237		tmpGeo.faces = this.faces;
12238
12239		for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
12240
12241			// create on first access
12242
12243			if ( ! this.morphNormals[ i ] ) {
12244
12245				this.morphNormals[ i ] = {};
12246				this.morphNormals[ i ].faceNormals = [];
12247				this.morphNormals[ i ].vertexNormals = [];
12248
12249				var dstNormalsFace = this.morphNormals[ i ].faceNormals;
12250				var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
12251
12252				var faceNormal, vertexNormals;
12253
12254				for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12255
12256					faceNormal = new Vector3();
12257					vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };
12258
12259					dstNormalsFace.push( faceNormal );
12260					dstNormalsVertex.push( vertexNormals );
12261
12262				}
12263
12264			}
12265
12266			var morphNormals = this.morphNormals[ i ];
12267
12268			// set vertices to morph target
12269
12270			tmpGeo.vertices = this.morphTargets[ i ].vertices;
12271
12272			// compute morph normals
12273
12274			tmpGeo.computeFaceNormals();
12275			tmpGeo.computeVertexNormals();
12276
12277			// store morph normals
12278
12279			var faceNormal, vertexNormals;
12280
12281			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12282
12283				face = this.faces[ f ];
12284
12285				faceNormal = morphNormals.faceNormals[ f ];
12286				vertexNormals = morphNormals.vertexNormals[ f ];
12287
12288				faceNormal.copy( face.normal );
12289
12290				vertexNormals.a.copy( face.vertexNormals[ 0 ] );
12291				vertexNormals.b.copy( face.vertexNormals[ 1 ] );
12292				vertexNormals.c.copy( face.vertexNormals[ 2 ] );
12293
12294			}
12295
12296		}
12297
12298		// restore original normals
12299
12300		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
12301
12302			face = this.faces[ f ];
12303
vendor: 26,128 bytes, lines 12304-13596
12304			face.normal = face.__originalFaceNormal;
12305			face.vertexNormals = face.__originalVertexNormals;
12306
12307		}
12308
12309	},
12310
12311	computeBoundingBox: function () {
12312
12313		if ( this.boundingBox === null ) {
12314
12315			this.boundingBox = new Box3();
12316
12317		}
12318
12319		this.boundingBox.setFromPoints( this.vertices );
12320
12321	},
12322
12323	computeBoundingSphere: function () {
12324
12325		if ( this.boundingSphere === null ) {
12326
12327			this.boundingSphere = new Sphere();
12328
12329		}
12330
12331		this.boundingSphere.setFromPoints( this.vertices );
12332
12333	},
12334
12335	merge: function ( geometry, matrix, materialIndexOffset ) {
12336
12337		if ( ! ( geometry && geometry.isGeometry ) ) {
12338
12339			console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );
12340			return;
12341
12342		}
12343
12344		var normalMatrix,
12345			vertexOffset = this.vertices.length,
12346			vertices1 = this.vertices,
12347			vertices2 = geometry.vertices,
12348			faces1 = this.faces,
12349			faces2 = geometry.faces,
12350			colors1 = this.colors,
12351			colors2 = geometry.colors;
12352
12353		if ( materialIndexOffset === undefined ) materialIndexOffset = 0;
12354
12355		if ( matrix !== undefined ) {
12356
12357			normalMatrix = new Matrix3().getNormalMatrix( matrix );
12358
12359		}
12360
12361		// vertices
12362
12363		for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
12364
12365			var vertex = vertices2[ i ];
12366
12367			var vertexCopy = vertex.clone();
12368
12369			if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );
12370
12371			vertices1.push( vertexCopy );
12372
12373		}
12374
12375		// colors
12376
12377		for ( var i = 0, il = colors2.length; i < il; i ++ ) {
12378
12379			colors1.push( colors2[ i ].clone() );
12380
12381		}
12382
12383		// faces
12384
12385		for ( i = 0, il = faces2.length; i < il; i ++ ) {
12386
12387			var face = faces2[ i ], faceCopy, normal, color,
12388				faceVertexNormals = face.vertexNormals,
12389				faceVertexColors = face.vertexColors;
12390
12391			faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
12392			faceCopy.normal.copy( face.normal );
12393
12394			if ( normalMatrix !== undefined ) {
12395
12396				faceCopy.normal.applyMatrix3( normalMatrix ).normalize();
12397
12398			}
12399
12400			for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
12401
12402				normal = faceVertexNormals[ j ].clone();
12403
12404				if ( normalMatrix !== undefined ) {
12405
12406					normal.applyMatrix3( normalMatrix ).normalize();
12407
12408				}
12409
12410				faceCopy.vertexNormals.push( normal );
12411
12412			}
12413
12414			faceCopy.color.copy( face.color );
12415
12416			for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
12417
12418				color = faceVertexColors[ j ];
12419				faceCopy.vertexColors.push( color.clone() );
12420
12421			}
12422
12423			faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
12424
12425			faces1.push( faceCopy );
12426
12427		}
12428
12429		// uvs
12430
12431		for ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
12432
12433			var faceVertexUvs2 = geometry.faceVertexUvs[ i ];
12434
12435			if ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = [];
12436
12437			for ( var j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {
12438
12439				var uvs2 = faceVertexUvs2[ j ], uvsCopy = [];
12440
12441				for ( var k = 0, kl = uvs2.length; k < kl; k ++ ) {
12442
12443					uvsCopy.push( uvs2[ k ].clone() );
12444
12445				}
12446
12447				this.faceVertexUvs[ i ].push( uvsCopy );
12448
12449			}
12450
12451		}
12452
12453	},
12454
12455	mergeMesh: function ( mesh ) {
12456
12457		if ( ! ( mesh && mesh.isMesh ) ) {
12458
12459			console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );
12460			return;
12461
12462		}
12463
12464		if ( mesh.matrixAutoUpdate ) mesh.updateMatrix();
12465
12466		this.merge( mesh.geometry, mesh.matrix );
12467
12468	},
12469
12470	/*
12471	 * Checks for duplicate vertices with hashmap.
12472	 * Duplicated vertices are removed
12473	 * and faces' vertices are updated.
12474	 */
12475
12476	mergeVertices: function () {
12477
12478		var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)
12479		var unique = [], changes = [];
12480
12481		var v, key;
12482		var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001
12483		var precision = Math.pow( 10, precisionPoints );
12484		var i, il, face;
12485		var indices, j, jl;
12486
12487		for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
12488
12489			v = this.vertices[ i ];
12490			key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
12491
12492			if ( verticesMap[ key ] === undefined ) {
12493
12494				verticesMap[ key ] = i;
12495				unique.push( this.vertices[ i ] );
12496				changes[ i ] = unique.length - 1;
12497
12498			} else {
12499
12500				//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
12501				changes[ i ] = changes[ verticesMap[ key ] ];
12502
12503			}
12504
12505		}
12506
12507
12508		// if faces are completely degenerate after merging vertices, we
12509		// have to remove them from the geometry.
12510		var faceIndicesToRemove = [];
12511
12512		for ( i = 0, il = this.faces.length; i < il; i ++ ) {
12513
12514			face = this.faces[ i ];
12515
12516			face.a = changes[ face.a ];
12517			face.b = changes[ face.b ];
12518			face.c = changes[ face.c ];
12519
12520			indices = [ face.a, face.b, face.c ];
12521
12522			// if any duplicate vertices are found in a Face3
12523			// we have to remove the face as nothing can be saved
12524			for ( var n = 0; n < 3; n ++ ) {
12525
12526				if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {
12527
12528					faceIndicesToRemove.push( i );
12529					break;
12530
12531				}
12532
12533			}
12534
12535		}
12536
12537		for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
12538
12539			var idx = faceIndicesToRemove[ i ];
12540
12541			this.faces.splice( idx, 1 );
12542
12543			for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
12544
12545				this.faceVertexUvs[ j ].splice( idx, 1 );
12546
12547			}
12548
12549		}
12550
12551		// Use unique set of vertices
12552
12553		var diff = this.vertices.length - unique.length;
12554		this.vertices = unique;
12555		return diff;
12556
12557	},
12558
12559	setFromPoints: function ( points ) {
12560
12561		this.vertices = [];
12562
12563		for ( var i = 0, l = points.length; i < l; i ++ ) {
12564
12565			var point = points[ i ];
12566			this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
12567
12568		}
12569
12570		return this;
12571
12572	},
12573
12574	sortFacesByMaterialIndex: function () {
12575
12576		var faces = this.faces;
12577		var length = faces.length;
12578
12579		// tag faces
12580
12581		for ( var i = 0; i < length; i ++ ) {
12582
12583			faces[ i ]._id = i;
12584
12585		}
12586
12587		// sort faces
12588
12589		function materialIndexSort( a, b ) {
12590
12591			return a.materialIndex - b.materialIndex;
12592
12593		}
12594
12595		faces.sort( materialIndexSort );
12596
12597		// sort uvs
12598
12599		var uvs1 = this.faceVertexUvs[ 0 ];
12600		var uvs2 = this.faceVertexUvs[ 1 ];
12601
12602		var newUvs1, newUvs2;
12603
12604		if ( uvs1 && uvs1.length === length ) newUvs1 = [];
12605		if ( uvs2 && uvs2.length === length ) newUvs2 = [];
12606
12607		for ( var i = 0; i < length; i ++ ) {
12608
12609			var id = faces[ i ]._id;
12610
12611			if ( newUvs1 ) newUvs1.push( uvs1[ id ] );
12612			if ( newUvs2 ) newUvs2.push( uvs2[ id ] );
12613
12614		}
12615
12616		if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;
12617		if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;
12618
12619	},
12620
12621	toJSON: function () {
12622
12623		var data = {
12624			metadata: {
12625				version: 4.5,
12626				type: 'Geometry',
12627				generator: 'Geometry.toJSON'
12628			}
12629		};
12630
12631		// standard Geometry serialization
12632
12633		data.uuid = this.uuid;
12634		data.type = this.type;
12635		if ( this.name !== '' ) data.name = this.name;
12636
12637		if ( this.parameters !== undefined ) {
12638
12639			var parameters = this.parameters;
12640
12641			for ( var key in parameters ) {
12642
12643				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
12644
12645			}
12646
12647			return data;
12648
12649		}
12650
12651		var vertices = [];
12652
12653		for ( var i = 0; i < this.vertices.length; i ++ ) {
12654
12655			var vertex = this.vertices[ i ];
12656			vertices.push( vertex.x, vertex.y, vertex.z );
12657
12658		}
12659
12660		var faces = [];
12661		var normals = [];
12662		var normalsHash = {};
12663		var colors = [];
12664		var colorsHash = {};
12665		var uvs = [];
12666		var uvsHash = {};
12667
12668		for ( var i = 0; i < this.faces.length; i ++ ) {
12669
12670			var face = this.faces[ i ];
12671
12672			var hasMaterial = true;
12673			var hasFaceUv = false; // deprecated
12674			var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;
12675			var hasFaceNormal = face.normal.length() > 0;
12676			var hasFaceVertexNormal = face.vertexNormals.length > 0;
12677			var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
12678			var hasFaceVertexColor = face.vertexColors.length > 0;
12679
12680			var faceType = 0;
12681
12682			faceType = setBit( faceType, 0, 0 ); // isQuad
12683			faceType = setBit( faceType, 1, hasMaterial );
12684			faceType = setBit( faceType, 2, hasFaceUv );
12685			faceType = setBit( faceType, 3, hasFaceVertexUv );
12686			faceType = setBit( faceType, 4, hasFaceNormal );
12687			faceType = setBit( faceType, 5, hasFaceVertexNormal );
12688			faceType = setBit( faceType, 6, hasFaceColor );
12689			faceType = setBit( faceType, 7, hasFaceVertexColor );
12690
12691			faces.push( faceType );
12692			faces.push( face.a, face.b, face.c );
12693			faces.push( face.materialIndex );
12694
12695			if ( hasFaceVertexUv ) {
12696
12697				var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];
12698
12699				faces.push(
12700					getUvIndex( faceVertexUvs[ 0 ] ),
12701					getUvIndex( faceVertexUvs[ 1 ] ),
12702					getUvIndex( faceVertexUvs[ 2 ] )
12703				);
12704
12705			}
12706
12707			if ( hasFaceNormal ) {
12708
12709				faces.push( getNormalIndex( face.normal ) );
12710
12711			}
12712
12713			if ( hasFaceVertexNormal ) {
12714
12715				var vertexNormals = face.vertexNormals;
12716
12717				faces.push(
12718					getNormalIndex( vertexNormals[ 0 ] ),
12719					getNormalIndex( vertexNormals[ 1 ] ),
12720					getNormalIndex( vertexNormals[ 2 ] )
12721				);
12722
12723			}
12724
12725			if ( hasFaceColor ) {
12726
12727				faces.push( getColorIndex( face.color ) );
12728
12729			}
12730
12731			if ( hasFaceVertexColor ) {
12732
12733				var vertexColors = face.vertexColors;
12734
12735				faces.push(
12736					getColorIndex( vertexColors[ 0 ] ),
12737					getColorIndex( vertexColors[ 1 ] ),
12738					getColorIndex( vertexColors[ 2 ] )
12739				);
12740
12741			}
12742
12743		}
12744
12745		function setBit( value, position, enabled ) {
12746
12747			return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );
12748
12749		}
12750
12751		function getNormalIndex( normal ) {
12752
12753			var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
12754
12755			if ( normalsHash[ hash ] !== undefined ) {
12756
12757				return normalsHash[ hash ];
12758
12759			}
12760
12761			normalsHash[ hash ] = normals.length / 3;
12762			normals.push( normal.x, normal.y, normal.z );
12763
12764			return normalsHash[ hash ];
12765
12766		}
12767
12768		function getColorIndex( color ) {
12769
12770			var hash = color.r.toString() + color.g.toString() + color.b.toString();
12771
12772			if ( colorsHash[ hash ] !== undefined ) {
12773
12774				return colorsHash[ hash ];
12775
12776			}
12777
12778			colorsHash[ hash ] = colors.length;
12779			colors.push( color.getHex() );
12780
12781			return colorsHash[ hash ];
12782
12783		}
12784
12785		function getUvIndex( uv ) {
12786
12787			var hash = uv.x.toString() + uv.y.toString();
12788
12789			if ( uvsHash[ hash ] !== undefined ) {
12790
12791				return uvsHash[ hash ];
12792
12793			}
12794
12795			uvsHash[ hash ] = uvs.length / 2;
12796			uvs.push( uv.x, uv.y );
12797
12798			return uvsHash[ hash ];
12799
12800		}
12801
12802		data.data = {};
12803
12804		data.data.vertices = vertices;
12805		data.data.normals = normals;
12806		if ( colors.length > 0 ) data.data.colors = colors;
12807		if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility
12808		data.data.faces = faces;
12809
12810		return data;
12811
12812	},
12813
12814	clone: function () {
12815
12816		/*
12817		 // Handle primitives
12818
12819		 var parameters = this.parameters;
12820
12821		 if ( parameters !== undefined ) {
12822
12823		 var values = [];
12824
12825		 for ( var key in parameters ) {
12826
12827		 values.push( parameters[ key ] );
12828
12829		 }
12830
12831		 var geometry = Object.create( this.constructor.prototype );
12832		 this.constructor.apply( geometry, values );
12833		 return geometry;
12834
12835		 }
12836
12837		 return new this.constructor().copy( this );
12838		 */
12839
12840		return new Geometry().copy( this );
12841
12842	},
12843
12844	copy: function ( source ) {
12845
12846		var i, il, j, jl, k, kl;
12847
12848		// reset
12849
12850		this.vertices = [];
12851		this.colors = [];
12852		this.faces = [];
12853		this.faceVertexUvs = [[]];
12854		this.morphTargets = [];
12855		this.morphNormals = [];
12856		this.skinWeights = [];
12857		this.skinIndices = [];
12858		this.lineDistances = [];
12859		this.boundingBox = null;
12860		this.boundingSphere = null;
12861
12862		// name
12863
12864		this.name = source.name;
12865
12866		// vertices
12867
12868		var vertices = source.vertices;
12869
12870		for ( i = 0, il = vertices.length; i < il; i ++ ) {
12871
12872			this.vertices.push( vertices[ i ].clone() );
12873
12874		}
12875
12876		// colors
12877
12878		var colors = source.colors;
12879
12880		for ( i = 0, il = colors.length; i < il; i ++ ) {
12881
12882			this.colors.push( colors[ i ].clone() );
12883
12884		}
12885
12886		// faces
12887
12888		var faces = source.faces;
12889
12890		for ( i = 0, il = faces.length; i < il; i ++ ) {
12891
12892			this.faces.push( faces[ i ].clone() );
12893
12894		}
12895
12896		// face vertex uvs
12897
12898		for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {
12899
12900			var faceVertexUvs = source.faceVertexUvs[ i ];
12901
12902			if ( this.faceVertexUvs[ i ] === undefined ) {
12903
12904				this.faceVertexUvs[ i ] = [];
12905
12906			}
12907
12908			for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {
12909
12910				var uvs = faceVertexUvs[ j ], uvsCopy = [];
12911
12912				for ( k = 0, kl = uvs.length; k < kl; k ++ ) {
12913
12914					var uv = uvs[ k ];
12915
12916					uvsCopy.push( uv.clone() );
12917
12918				}
12919
12920				this.faceVertexUvs[ i ].push( uvsCopy );
12921
12922			}
12923
12924		}
12925
12926		// morph targets
12927
12928		var morphTargets = source.morphTargets;
12929
12930		for ( i = 0, il = morphTargets.length; i < il; i ++ ) {
12931
12932			var morphTarget = {};
12933			morphTarget.name = morphTargets[ i ].name;
12934
12935			// vertices
12936
12937			if ( morphTargets[ i ].vertices !== undefined ) {
12938
12939				morphTarget.vertices = [];
12940
12941				for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {
12942
12943					morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );
12944
12945				}
12946
12947			}
12948
12949			// normals
12950
12951			if ( morphTargets[ i ].normals !== undefined ) {
12952
12953				morphTarget.normals = [];
12954
12955				for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {
12956
12957					morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );
12958
12959				}
12960
12961			}
12962
12963			this.morphTargets.push( morphTarget );
12964
12965		}
12966
12967		// morph normals
12968
12969		var morphNormals = source.morphNormals;
12970
12971		for ( i = 0, il = morphNormals.length; i < il; i ++ ) {
12972
12973			var morphNormal = {};
12974
12975			// vertex normals
12976
12977			if ( morphNormals[ i ].vertexNormals !== undefined ) {
12978
12979				morphNormal.vertexNormals = [];
12980
12981				for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {
12982
12983					var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];
12984					var destVertexNormal = {};
12985
12986					destVertexNormal.a = srcVertexNormal.a.clone();
12987					destVertexNormal.b = srcVertexNormal.b.clone();
12988					destVertexNormal.c = srcVertexNormal.c.clone();
12989
12990					morphNormal.vertexNormals.push( destVertexNormal );
12991
12992				}
12993
12994			}
12995
12996			// face normals
12997
12998			if ( morphNormals[ i ].faceNormals !== undefined ) {
12999
13000				morphNormal.faceNormals = [];
13001
13002				for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {
13003
13004					morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );
13005
13006				}
13007
13008			}
13009
13010			this.morphNormals.push( morphNormal );
13011
13012		}
13013
13014		// skin weights
13015
13016		var skinWeights = source.skinWeights;
13017
13018		for ( i = 0, il = skinWeights.length; i < il; i ++ ) {
13019
13020			this.skinWeights.push( skinWeights[ i ].clone() );
13021
13022		}
13023
13024		// skin indices
13025
13026		var skinIndices = source.skinIndices;
13027
13028		for ( i = 0, il = skinIndices.length; i < il; i ++ ) {
13029
13030			this.skinIndices.push( skinIndices[ i ].clone() );
13031
13032		}
13033
13034		// line distances
13035
13036		var lineDistances = source.lineDistances;
13037
13038		for ( i = 0, il = lineDistances.length; i < il; i ++ ) {
13039
13040			this.lineDistances.push( lineDistances[ i ] );
13041
13042		}
13043
13044		// bounding box
13045
13046		var boundingBox = source.boundingBox;
13047
13048		if ( boundingBox !== null ) {
13049
13050			this.boundingBox = boundingBox.clone();
13051
13052		}
13053
13054		// bounding sphere
13055
13056		var boundingSphere = source.boundingSphere;
13057
13058		if ( boundingSphere !== null ) {
13059
13060			this.boundingSphere = boundingSphere.clone();
13061
13062		}
13063
13064		// update flags
13065
13066		this.elementsNeedUpdate = source.elementsNeedUpdate;
13067		this.verticesNeedUpdate = source.verticesNeedUpdate;
13068		this.uvsNeedUpdate = source.uvsNeedUpdate;
13069		this.normalsNeedUpdate = source.normalsNeedUpdate;
13070		this.colorsNeedUpdate = source.colorsNeedUpdate;
13071		this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;
13072		this.groupsNeedUpdate = source.groupsNeedUpdate;
13073
13074		return this;
13075
13076	},
13077
13078	dispose: function () {
13079
13080		this.dispatchEvent( { type: 'dispose' } );
13081
13082	}
13083
13084} );
13085
13086/**
13087 * @author mrdoob / http://mrdoob.com/
13088 * @author Mugen87 / https://github.com/Mugen87
13089 */
13090
13091// BoxGeometry
13092
13093class BoxGeometry extends Geometry {
13094
13095	constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {
13096
13097		super();
13098
13099		this.type = 'BoxGeometry';
13100
13101		this.parameters = {
13102			width: width,
13103			height: height,
13104			depth: depth,
13105			widthSegments: widthSegments,
13106			heightSegments: heightSegments,
13107			depthSegments: depthSegments
13108		};
13109
13110		this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );
13111		this.mergeVertices();
13112
13113	}
13114
13115}
13116
13117// BoxBufferGeometry
13118
13119class BoxBufferGeometry extends BufferGeometry {
13120
13121	constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {
13122
13123		super();
13124
13125		this.type = 'BoxBufferGeometry';
13126
13127		this.parameters = {
13128			width: width,
13129			height: height,
13130			depth: depth,
13131			widthSegments: widthSegments,
13132			heightSegments: heightSegments,
13133			depthSegments: depthSegments
13134		};
13135
13136		var scope = this;
13137
13138		width = width || 1;
13139		height = height || 1;
13140		depth = depth || 1;
13141
13142		// segments
13143
13144		widthSegments = Math.floor( widthSegments ) || 1;
13145		heightSegments = Math.floor( heightSegments ) || 1;
13146		depthSegments = Math.floor( depthSegments ) || 1;
13147
13148		// buffers
13149
13150		var indices = [];
13151		var vertices = [];
13152		var normals = [];
13153		var uvs = [];
13154
13155		// helper variables
13156
13157		var numberOfVertices = 0;
13158		var groupStart = 0;
13159
13160		// build each side of the box geometry
13161
13162		buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
13163		buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
13164		buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
13165		buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
13166		buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
13167		buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
13168
13169		// build geometry
13170
13171		this.setIndex( indices );
13172		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
13173		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
13174		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
13175
13176		function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
13177
13178			var segmentWidth = width / gridX;
13179			var segmentHeight = height / gridY;
13180
13181			var widthHalf = width / 2;
13182			var heightHalf = height / 2;
13183			var depthHalf = depth / 2;
13184
13185			var gridX1 = gridX + 1;
13186			var gridY1 = gridY + 1;
13187
13188			var vertexCounter = 0;
13189			var groupCount = 0;
13190
13191			var ix, iy;
13192
13193			var vector = new Vector3();
13194
13195			// generate vertices, normals and uvs
13196
13197			for ( iy = 0; iy < gridY1; iy ++ ) {
13198
13199				var y = iy * segmentHeight - heightHalf;
13200
13201				for ( ix = 0; ix < gridX1; ix ++ ) {
13202
13203					var x = ix * segmentWidth - widthHalf;
13204
13205					// set values to correct vector component
13206
13207					vector[ u ] = x * udir;
13208					vector[ v ] = y * vdir;
13209					vector[ w ] = depthHalf;
13210
13211					// now apply vector to vertex buffer
13212
13213					vertices.push( vector.x, vector.y, vector.z );
13214
13215					// set values to correct vector component
13216
13217					vector[ u ] = 0;
13218					vector[ v ] = 0;
13219					vector[ w ] = depth > 0 ? 1 : - 1;
13220
13221					// now apply vector to normal buffer
13222
13223					normals.push( vector.x, vector.y, vector.z );
13224
13225					// uvs
13226
13227					uvs.push( ix / gridX );
13228					uvs.push( 1 - ( iy / gridY ) );
13229
13230					// counters
13231
13232					vertexCounter += 1;
13233
13234				}
13235
13236			}
13237
13238			// indices
13239
13240			// 1. you need three indices to draw a single face
13241			// 2. a single segment consists of two faces
13242			// 3. so we need to generate six (2*3) indices per segment
13243
13244			for ( iy = 0; iy < gridY; iy ++ ) {
13245
13246				for ( ix = 0; ix < gridX; ix ++ ) {
13247
13248					var a = numberOfVertices + ix + gridX1 * iy;
13249					var b = numberOfVertices + ix + gridX1 * ( iy + 1 );
13250					var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
13251					var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
13252
13253					// faces
13254
13255					indices.push( a, b, d );
13256					indices.push( b, c, d );
13257
13258					// increase counter
13259
13260					groupCount += 6;
13261
13262				}
13263
13264			}
13265
13266			// add a group to the geometry. this will ensure multi material support
13267
13268			scope.addGroup( groupStart, groupCount, materialIndex );
13269
13270			// calculate new start value for groups
13271
13272			groupStart += groupCount;
13273
13274			// update total number of vertices
13275
13276			numberOfVertices += vertexCounter;
13277
13278		}
13279
13280	}
13281
13282}
13283
13284/**
13285 * Uniform Utilities
13286 */
13287
13288function cloneUniforms( src ) {
13289
13290	var dst = {};
13291
13292	for ( var u in src ) {
13293
13294		dst[ u ] = {};
13295
13296		for ( var p in src[ u ] ) {
13297
13298			var property = src[ u ][ p ];
13299
13300			if ( property && ( property.isColor ||
13301				property.isMatrix3 || property.isMatrix4 ||
13302				property.isVector2 || property.isVector3 || property.isVector4 ||
13303				property.isTexture ) ) {
13304
13305				dst[ u ][ p ] = property.clone();
13306
13307			} else if ( Array.isArray( property ) ) {
13308
13309				dst[ u ][ p ] = property.slice();
13310
13311			} else {
13312
13313				dst[ u ][ p ] = property;
13314
13315			}
13316
13317		}
13318
13319	}
13320
13321	return dst;
13322
13323}
13324
13325function mergeUniforms( uniforms ) {
13326
13327	var merged = {};
13328
13329	for ( var u = 0; u < uniforms.length; u ++ ) {
13330
13331		var tmp = cloneUniforms( uniforms[ u ] );
13332
13333		for ( var p in tmp ) {
13334
13335			merged[ p ] = tmp[ p ];
13336
13337		}
13338
13339	}
13340
13341	return merged;
13342
13343}
13344
13345// Legacy
13346
13347var UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
13348
13349var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
13350
13351var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
13352
13353/**
13354 * @author alteredq / http://alteredqualia.com/
13355 *
13356 * parameters = {
13357 *  defines: { "label" : "value" },
13358 *  uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } },
13359 *
13360 *  fragmentShader: <string>,
13361 *  vertexShader: <string>,
13362 *
13363 *  wireframe: <boolean>,
13364 *  wireframeLinewidth: <float>,
13365 *
13366 *  lights: <bool>,
13367 *
13368 *  skinning: <bool>,
13369 *  morphTargets: <bool>,
13370 *  morphNormals: <bool>
13371 * }
13372 */
13373
13374function ShaderMaterial( parameters ) {
13375
13376	Material.call( this );
13377
13378	this.type = 'ShaderMaterial';
13379
13380	this.defines = {};
13381	this.uniforms = {};
13382
13383	this.vertexShader = default_vertex;
13384	this.fragmentShader = default_fragment;
13385
13386	this.linewidth = 1;
13387
13388	this.wireframe = false;
13389	this.wireframeLinewidth = 1;
13390
13391	this.fog = false; // set to use scene fog
13392	this.lights = false; // set to use scene lights
13393	this.clipping = false; // set to use user-defined clipping planes
13394
13395	this.skinning = false; // set to use skinning attribute streams
13396	this.morphTargets = false; // set to use morph targets
13397	this.morphNormals = false; // set to use morph normals
13398
13399	this.extensions = {
13400		derivatives: false, // set to use derivatives
13401		fragDepth: false, // set to use fragment depth values
13402		drawBuffers: false, // set to use draw buffers
13403		shaderTextureLOD: false // set to use shader texture LOD
13404	};
13405
13406	// When rendered geometry doesn't include these attributes but the material does,
13407	// use these default values in WebGL. This avoids errors when buffer data is missing.
13408	this.defaultAttributeValues = {
13409		'color': [ 1, 1, 1 ],
13410		'uv': [ 0, 0 ],
13411		'uv2': [ 0, 0 ]
13412	};
13413
13414	this.index0AttributeName = undefined;
13415	this.uniformsNeedUpdate = false;
13416
13417	if ( parameters !== undefined ) {
13418
13419		if ( parameters.attributes !== undefined ) {
13420
13421			console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
13422
13423		}
13424
13425		this.setValues( parameters );
13426
13427	}
13428
13429}
13430
13431ShaderMaterial.prototype = Object.create( Material.prototype );
13432ShaderMaterial.prototype.constructor = ShaderMaterial;
13433
13434ShaderMaterial.prototype.isShaderMaterial = true;
13435
13436ShaderMaterial.prototype.copy = function ( source ) {
13437
13438	Material.prototype.copy.call( this, source );
13439
13440	this.fragmentShader = source.fragmentShader;
13441	this.vertexShader = source.vertexShader;
13442
13443	this.uniforms = cloneUniforms( source.uniforms );
13444
13445	this.defines = Object.assign( {}, source.defines );
13446
13447	this.wireframe = source.wireframe;
13448	this.wireframeLinewidth = source.wireframeLinewidth;
13449
13450	this.lights = source.lights;
13451	this.clipping = source.clipping;
13452
13453	this.skinning = source.skinning;
13454
13455	this.morphTargets = source.morphTargets;
13456	this.morphNormals = source.morphNormals;
13457
13458	this.extensions = source.extensions;
13459
13460	return this;
13461
13462};
13463
13464ShaderMaterial.prototype.toJSON = function ( meta ) {
13465
13466	var data = Material.prototype.toJSON.call( this, meta );
13467
13468	data.uniforms = {};
13469
13470	for ( var name in this.uniforms ) {
13471
13472		var uniform = this.uniforms[ name ];
13473		var value = uniform.value;
13474
13475		if ( value && value.isTexture ) {
13476
13477			data.uniforms[ name ] = {
13478				type: 't',
13479				value: value.toJSON( meta ).uuid
13480			};
13481
13482		} else if ( value && value.isColor ) {
13483
13484			data.uniforms[ name ] = {
13485				type: 'c',
13486				value: value.getHex()
13487			};
13488
13489		} else if ( value && value.isVector2 ) {
13490
13491			data.uniforms[ name ] = {
13492				type: 'v2',
13493				value: value.toArray()
13494			};
13495
13496		} else if ( value && value.isVector3 ) {
13497
13498			data.uniforms[ name ] = {
13499				type: 'v3',
13500				value: value.toArray()
13501			};
13502
13503		} else if ( value && value.isVector4 ) {
13504
13505			data.uniforms[ name ] = {
13506				type: 'v4',
13507				value: value.toArray()
13508			};
13509
13510		} else if ( value && value.isMatrix3 ) {
13511
13512			data.uniforms[ name ] = {
13513				type: 'm3',
13514				value: value.toArray()
13515			};
13516
13517		} else if ( value && value.isMatrix4 ) {
13518
13519			data.uniforms[ name ] = {
13520				type: 'm4',
13521				value: value.toArray()
13522			};
13523
13524		} else {
13525
13526			data.uniforms[ name ] = {
13527				value: value
13528			};
13529
13530			// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
13531
13532		}
13533
13534	}
13535
13536	if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
13537
13538	data.vertexShader = this.vertexShader;
13539	data.fragmentShader = this.fragmentShader;
13540
13541	var extensions = {};
13542
13543	for ( var key in this.extensions ) {
13544
13545		if ( this.extensions[ key ] === true ) extensions[ key ] = true;
13546
13547	}
13548
13549	if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
13550
13551	return data;
13552
13553};
13554
13555/**
13556 * @author mrdoob / http://mrdoob.com/
13557 * @author mikael emtinger / http://gomo.se/
13558 * @author WestLangley / http://github.com/WestLangley
13559*/
13560
13561function Camera() {
13562
13563	Object3D.call( this );
13564
13565	this.type = 'Camera';
13566
13567	this.matrixWorldInverse = new Matrix4();
13568
13569	this.projectionMatrix = new Matrix4();
13570	this.projectionMatrixInverse = new Matrix4();
13571
13572}
13573
13574Camera.prototype = Object.assign( Object.create( Object3D.prototype ), {
13575
13576	constructor: Camera,
13577
13578	isCamera: true,
13579
13580	copy: function ( source, recursive ) {
13581
13582		Object3D.prototype.copy.call( this, source, recursive );
13583
13584		this.matrixWorldInverse.copy( source.matrixWorldInverse );
13585
13586		this.projectionMatrix.copy( source.projectionMatrix );
13587		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
13588
13589		return this;
13590
13591	},
13592
13593	getWorldDirection: function ( target ) {
13594
13595		if ( target === undefined ) {
13596
vendor: 4,994 bytes, lines 13597-13810
13597			console.warn( 'THREE.Camera: .getWorldDirection() target is now required' );
13598			target = new Vector3();
13599
13600		}
13601
13602		this.updateMatrixWorld( true );
13603
13604		var e = this.matrixWorld.elements;
13605
13606		return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
13607
13608	},
13609
13610	updateMatrixWorld: function ( force ) {
13611
13612		Object3D.prototype.updateMatrixWorld.call( this, force );
13613
13614		this.matrixWorldInverse.getInverse( this.matrixWorld );
13615
13616	},
13617
13618	updateWorldMatrix: function ( updateParents, updateChildren ) {
13619
13620		Object3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren );
13621
13622		this.matrixWorldInverse.getInverse( this.matrixWorld );
13623
13624	},
13625
13626	clone: function () {
13627
13628		return new this.constructor().copy( this );
13629
13630	}
13631
13632} );
13633
13634/**
13635 * @author mrdoob / http://mrdoob.com/
13636 * @author greggman / http://games.greggman.com/
13637 * @author zz85 / http://www.lab4games.net/zz85/blog
13638 * @author tschw
13639 */
13640
13641function PerspectiveCamera( fov, aspect, near, far ) {
13642
13643	Camera.call( this );
13644
13645	this.type = 'PerspectiveCamera';
13646
13647	this.fov = fov !== undefined ? fov : 50;
13648	this.zoom = 1;
13649
13650	this.near = near !== undefined ? near : 0.1;
13651	this.far = far !== undefined ? far : 2000;
13652	this.focus = 10;
13653
13654	this.aspect = aspect !== undefined ? aspect : 1;
13655	this.view = null;
13656
13657	this.filmGauge = 35;	// width of the film (default in millimeters)
13658	this.filmOffset = 0;	// horizontal film offset (same unit as gauge)
13659
13660	this.updateProjectionMatrix();
13661
13662}
13663
13664PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
13665
13666	constructor: PerspectiveCamera,
13667
13668	isPerspectiveCamera: true,
13669
13670	copy: function ( source, recursive ) {
13671
13672		Camera.prototype.copy.call( this, source, recursive );
13673
13674		this.fov = source.fov;
13675		this.zoom = source.zoom;
13676
13677		this.near = source.near;
13678		this.far = source.far;
13679		this.focus = source.focus;
13680
13681		this.aspect = source.aspect;
13682		this.view = source.view === null ? null : Object.assign( {}, source.view );
13683
13684		this.filmGauge = source.filmGauge;
13685		this.filmOffset = source.filmOffset;
13686
13687		return this;
13688
13689	},
13690
13691	/**
13692	 * Sets the FOV by focal length in respect to the current .filmGauge.
13693	 *
13694	 * The default film gauge is 35, so that the focal length can be specified for
13695	 * a 35mm (full frame) camera.
13696	 *
13697	 * Values for focal length and film gauge must have the same unit.
13698	 */
13699	setFocalLength: function ( focalLength ) {
13700
13701		// see http://www.bobatkins.com/photography/technical/field_of_view.html
13702		var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
13703
13704		this.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope );
13705		this.updateProjectionMatrix();
13706
13707	},
13708
13709	/**
13710	 * Calculates the focal length from the current .fov and .filmGauge.
13711	 */
13712	getFocalLength: function () {
13713
13714		var vExtentSlope = Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov );
13715
13716		return 0.5 * this.getFilmHeight() / vExtentSlope;
13717
13718	},
13719
13720	getEffectiveFOV: function () {
13721
13722		return MathUtils.RAD2DEG * 2 * Math.atan(
13723			Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom );
13724
13725	},
13726
13727	getFilmWidth: function () {
13728
13729		// film not completely covered in portrait format (aspect < 1)
13730		return this.filmGauge * Math.min( this.aspect, 1 );
13731
13732	},
13733
13734	getFilmHeight: function () {
13735
13736		// film not completely covered in landscape format (aspect > 1)
13737		return this.filmGauge / Math.max( this.aspect, 1 );
13738
13739	},
13740
13741	/**
13742	 * Sets an offset in a larger frustum. This is useful for multi-window or
13743	 * multi-monitor/multi-machine setups.
13744	 *
13745	 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
13746	 * the monitors are in grid like this
13747	 *
13748	 *   +---+---+---+
13749	 *   | A | B | C |
13750	 *   +---+---+---+
13751	 *   | D | E | F |
13752	 *   +---+---+---+
13753	 *
13754	 * then for each monitor you would call it like this
13755	 *
13756	 *   var w = 1920;
13757	 *   var h = 1080;
13758	 *   var fullWidth = w * 3;
13759	 *   var fullHeight = h * 2;
13760	 *
13761	 *   --A--
13762	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
13763	 *   --B--
13764	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
13765	 *   --C--
13766	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
13767	 *   --D--
13768	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
13769	 *   --E--
13770	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
13771	 *   --F--
13772	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
13773	 *
13774	 *   Note there is no reason monitors have to be the same size or in a grid.
13775	 */
13776	setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
13777
13778		this.aspect = fullWidth / fullHeight;
13779
13780		if ( this.view === null ) {
13781
13782			this.view = {
13783				enabled: true,
13784				fullWidth: 1,
13785				fullHeight: 1,
13786				offsetX: 0,
13787				offsetY: 0,
13788				width: 1,
13789				height: 1
13790			};
13791
13792		}
13793
13794		this.view.enabled = true;
13795		this.view.fullWidth = fullWidth;
13796		this.view.fullHeight = fullHeight;
13797		this.view.offsetX = x;
13798		this.view.offsetY = y;
13799		this.view.width = width;
13800		this.view.height = height;
13801
13802		this.updateProjectionMatrix();
13803
13804	},
13805
13806	clearViewOffset: function () {
13807
13808		if ( this.view !== null ) {
13809
13810			this.view.enabled = false;
vendor: 4,331 bytes, lines 13811-13984
13811
13812		}
13813
13814		this.updateProjectionMatrix();
13815
13816	},
13817
13818	updateProjectionMatrix: function () {
13819
13820		var near = this.near,
13821			top = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom,
13822			height = 2 * top,
13823			width = this.aspect * height,
13824			left = - 0.5 * width,
13825			view = this.view;
13826
13827		if ( this.view !== null && this.view.enabled ) {
13828
13829			var fullWidth = view.fullWidth,
13830				fullHeight = view.fullHeight;
13831
13832			left += view.offsetX * width / fullWidth;
13833			top -= view.offsetY * height / fullHeight;
13834			width *= view.width / fullWidth;
13835			height *= view.height / fullHeight;
13836
13837		}
13838
13839		var skew = this.filmOffset;
13840		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
13841
13842		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
13843
13844		this.projectionMatrixInverse.getInverse( this.projectionMatrix );
13845
13846	},
13847
13848	toJSON: function ( meta ) {
13849
13850		var data = Object3D.prototype.toJSON.call( this, meta );
13851
13852		data.object.fov = this.fov;
13853		data.object.zoom = this.zoom;
13854
13855		data.object.near = this.near;
13856		data.object.far = this.far;
13857		data.object.focus = this.focus;
13858
13859		data.object.aspect = this.aspect;
13860
13861		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
13862
13863		data.object.filmGauge = this.filmGauge;
13864		data.object.filmOffset = this.filmOffset;
13865
13866		return data;
13867
13868	}
13869
13870} );
13871
13872/**
13873 * Camera for rendering cube maps
13874 *	- renders scene into axis-aligned cube
13875 *
13876 * @author alteredq / http://alteredqualia.com/
13877 */
13878
13879var fov = 90, aspect = 1;
13880
13881function CubeCamera( near, far, cubeResolution, options ) {
13882
13883	Object3D.call( this );
13884
13885	this.type = 'CubeCamera';
13886
13887	var cameraPX = new PerspectiveCamera( fov, aspect, near, far );
13888	cameraPX.up.set( 0, - 1, 0 );
13889	cameraPX.lookAt( new Vector3( 1, 0, 0 ) );
13890	this.add( cameraPX );
13891
13892	var cameraNX = new PerspectiveCamera( fov, aspect, near, far );
13893	cameraNX.up.set( 0, - 1, 0 );
13894	cameraNX.lookAt( new Vector3( - 1, 0, 0 ) );
13895	this.add( cameraNX );
13896
13897	var cameraPY = new PerspectiveCamera( fov, aspect, near, far );
13898	cameraPY.up.set( 0, 0, 1 );
13899	cameraPY.lookAt( new Vector3( 0, 1, 0 ) );
13900	this.add( cameraPY );
13901
13902	var cameraNY = new PerspectiveCamera( fov, aspect, near, far );
13903	cameraNY.up.set( 0, 0, - 1 );
13904	cameraNY.lookAt( new Vector3( 0, - 1, 0 ) );
13905	this.add( cameraNY );
13906
13907	var cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
13908	cameraPZ.up.set( 0, - 1, 0 );
13909	cameraPZ.lookAt( new Vector3( 0, 0, 1 ) );
13910	this.add( cameraPZ );
13911
13912	var cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
13913	cameraNZ.up.set( 0, - 1, 0 );
13914	cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );
13915	this.add( cameraNZ );
13916
13917	options = options || { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };
13918
13919	this.renderTarget = new WebGLCubeRenderTarget( cubeResolution, options );
13920	this.renderTarget.texture.name = "CubeCamera";
13921
13922	this.update = function ( renderer, scene ) {
13923
13924		if ( this.parent === null ) this.updateMatrixWorld();
13925
13926		var currentRenderTarget = renderer.getRenderTarget();
13927
13928		var renderTarget = this.renderTarget;
13929		var generateMipmaps = renderTarget.texture.generateMipmaps;
13930
13931		renderTarget.texture.generateMipmaps = false;
13932
13933		renderer.setRenderTarget( renderTarget, 0 );
13934		renderer.render( scene, cameraPX );
13935
13936		renderer.setRenderTarget( renderTarget, 1 );
13937		renderer.render( scene, cameraNX );
13938
13939		renderer.setRenderTarget( renderTarget, 2 );
13940		renderer.render( scene, cameraPY );
13941
13942		renderer.setRenderTarget( renderTarget, 3 );
13943		renderer.render( scene, cameraNY );
13944
13945		renderer.setRenderTarget( renderTarget, 4 );
13946		renderer.render( scene, cameraPZ );
13947
13948		renderTarget.texture.generateMipmaps = generateMipmaps;
13949
13950		renderer.setRenderTarget( renderTarget, 5 );
13951		renderer.render( scene, cameraNZ );
13952
13953		renderer.setRenderTarget( currentRenderTarget );
13954
13955	};
13956
13957	this.clear = function ( renderer, color, depth, stencil ) {
13958
13959		var currentRenderTarget = renderer.getRenderTarget();
13960
13961		var renderTarget = this.renderTarget;
13962
13963		for ( var i = 0; i < 6; i ++ ) {
13964
13965			renderer.setRenderTarget( renderTarget, i );
13966
13967			renderer.clear( color, depth, stencil );
13968
13969		}
13970
13971		renderer.setRenderTarget( currentRenderTarget );
13972
13973	};
13974
13975}
13976
13977CubeCamera.prototype = Object.create( Object3D.prototype );
13978CubeCamera.prototype.constructor = CubeCamera;
13979
13980/**
13981 * @author alteredq / http://alteredqualia.com
13982 * @author WestLangley / http://github.com/WestLangley
13983 */
13984
13985function WebGLCubeRenderTarget( size, options, dummy ) {
13986
13987	if ( Number.isInteger( options ) ) {
13988
13989		console.warn( 'THREE.WebGLCubeRenderTarget: constructor signature is now WebGLCubeRenderTarget( size, options )' );
13990
13991		options = dummy;
13992
13993	}
13994
13995	WebGLRenderTarget.call( this, size, size, options );
13996
13997}
13998
13999WebGLCubeRenderTarget.prototype = Object.create( WebGLRenderTarget.prototype );
14000WebGLCubeRenderTarget.prototype.constructor = WebGLCubeRenderTarget;
14001
14002WebGLCubeRenderTarget.prototype.isWebGLCubeRenderTarget = true;
14003
14004WebGLCubeRenderTarget.prototype.fromEquirectangularTexture = function ( renderer, texture ) {
14005
14006	this.texture.type = texture.type;
14007	this.texture.format = texture.format;
14008	this.texture.encoding = texture.encoding;
14009
14010	var scene = new Scene();
14011
14012	var shader = {
14013
14014		uniforms: {
14015			tEquirect: { value: null },
14016		},
14017
14018		vertexShader: [
14019
14020			"varying vec3 vWorldDirection;",
14021
14022			"vec3 transformDirection( in vec3 dir, in mat4 matrix ) {",
14023
14024			"	return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );",
14025
14026			"}",
14027
14028			"void main() {",
14029
14030			"	vWorldDirection = transformDirection( position, modelMatrix );",
14031
14032			"	#include <begin_vertex>",
14033			"	#include <project_vertex>",
14034
14035			"}"
14036
14037		].join( '\n' ),
14038
14039		fragmentShader: [
14040
14041			"uniform sampler2D tEquirect;",
14042
14043			"varying vec3 vWorldDirection;",
14044
14045			"#define RECIPROCAL_PI 0.31830988618",
14046			"#define RECIPROCAL_PI2 0.15915494",
14047
14048			"void main() {",
14049
14050			"	vec3 direction = normalize( vWorldDirection );",
14051
14052			"	vec2 sampleUV;",
14053
14054			"	sampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;",
14055
14056			"	sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;",
14057
14058			"	gl_FragColor = texture2D( tEquirect, sampleUV );",
14059
14060			"}"
14061
14062		].join( '\n' ),
14063	};
14064
14065	var material = new ShaderMaterial( {
14066
14067		type: 'CubemapFromEquirect',
14068
14069		uniforms: cloneUniforms( shader.uniforms ),
14070		vertexShader: shader.vertexShader,
14071		fragmentShader: shader.fragmentShader,
14072		side: BackSide,
14073		blending: NoBlending
14074
14075	} );
14076
14077	material.uniforms.tEquirect.value = texture;
14078
14079	var mesh = new Mesh( new BoxBufferGeometry( 5, 5, 5 ), material );
14080
14081	scene.add( mesh );
14082
14083	var camera = new CubeCamera( 1, 10, 1 );
14084
14085	camera.renderTarget = this;
14086	camera.renderTarget.texture.name = 'CubeCameraTexture';
14087
14088	camera.update( renderer, scene );
14089
14090	mesh.geometry.dispose();
14091	mesh.material.dispose();
14092
14093	return this;
14094
14095};
14096
14097/**
14098 * @author alteredq / http://alteredqualia.com/
14099 */
14100
14101function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
14102
14103	Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
14104
14105	this.image = { data: data || null, width: width || 1, height: height || 1 };
14106
14107	this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
14108	this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
14109
14110	this.generateMipmaps = false;
14111	this.flipY = false;
14112	this.unpackAlignment = 1;
14113
14114	this.needsUpdate = true;
14115
14116}
14117
14118DataTexture.prototype = Object.create( Texture.prototype );
14119DataTexture.prototype.constructor = DataTexture;
14120
14121DataTexture.prototype.isDataTexture = true;
14122
14123/**
14124 * @author mrdoob / http://mrdoob.com/
14125 * @author alteredq / http://alteredqualia.com/
14126 * @author bhouston / http://clara.io
14127 */
14128
14129var _sphere$1 = new Sphere();
14130var _vector$5 = new Vector3();
14131
14132function Frustum( p0, p1, p2, p3, p4, p5 ) {
14133
14134	this.planes = [
14135
14136		( p0 !== undefined ) ? p0 : new Plane(),
14137		( p1 !== undefined ) ? p1 : new Plane(),
14138		( p2 !== undefined ) ? p2 : new Plane(),
14139		( p3 !== undefined ) ? p3 : new Plane(),
14140		( p4 !== undefined ) ? p4 : new Plane(),
14141		( p5 !== undefined ) ? p5 : new Plane()
14142
14143	];
14144
14145}
14146
14147Object.assign( Frustum.prototype, {
14148
14149	set: function ( p0, p1, p2, p3, p4, p5 ) {
14150
14151		var planes = this.planes;
14152
14153		planes[ 0 ].copy( p0 );
14154		planes[ 1 ].copy( p1 );
14155		planes[ 2 ].copy( p2 );
14156		planes[ 3 ].copy( p3 );
14157		planes[ 4 ].copy( p4 );
14158		planes[ 5 ].copy( p5 );
14159
14160		return this;
14161
14162	},
14163
14164	clone: function () {
14165
14166		return new this.constructor().copy( this );
14167
14168	},
14169
14170	copy: function ( frustum ) {
14171
14172		var planes = this.planes;
14173
14174		for ( var i = 0; i < 6; i ++ ) {
14175
14176			planes[ i ].copy( frustum.planes[ i ] );
14177
14178		}
14179
14180		return this;
14181
14182	},
14183
14184	setFromProjectionMatrix: function ( m ) {
14185
14186		var planes = this.planes;
14187		var me = m.elements;
14188		var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
14189		var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
14190		var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
14191		var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
14192
14193		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
14194		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
14195		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
14196		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
14197		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
14198		planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
14199
14200		return this;
14201
14202	},
14203
14204	intersectsObject: function ( object ) {
14205
14206		var geometry = object.geometry;
14207
14208		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
14209
14210		_sphere$1.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
14211
14212		return this.intersectsSphere( _sphere$1 );
14213
14214	},
14215
14216	intersectsSprite: function ( sprite ) {
14217
14218		_sphere$1.center.set( 0, 0, 0 );
14219		_sphere$1.radius = 0.7071067811865476;
14220		_sphere$1.applyMatrix4( sprite.matrixWorld );
14221
14222		return this.intersectsSphere( _sphere$1 );
14223
14224	},
14225
14226	intersectsSphere: function ( sphere ) {
14227
14228		var planes = this.planes;
14229		var center = sphere.center;
14230		var negRadius = - sphere.radius;
14231
14232		for ( var i = 0; i < 6; i ++ ) {
14233
vendor: 4,154 bytes, lines 14234-14504
14234			var distance = planes[ i ].distanceToPoint( center );
14235
14236			if ( distance < negRadius ) {
14237
14238				return false;
14239
14240			}
14241
14242		}
14243
14244		return true;
14245
14246	},
14247
14248	intersectsBox: function ( box ) {
14249
14250		var planes = this.planes;
14251
14252		for ( var i = 0; i < 6; i ++ ) {
14253
14254			var plane = planes[ i ];
14255
14256			// corner at max distance
14257
14258			_vector$5.x = plane.normal.x > 0 ? box.max.x : box.min.x;
14259			_vector$5.y = plane.normal.y > 0 ? box.max.y : box.min.y;
14260			_vector$5.z = plane.normal.z > 0 ? box.max.z : box.min.z;
14261
14262			if ( plane.distanceToPoint( _vector$5 ) < 0 ) {
14263
14264				return false;
14265
14266			}
14267
14268		}
14269
14270		return true;
14271
14272	},
14273
14274	containsPoint: function ( point ) {
14275
14276		var planes = this.planes;
14277
14278		for ( var i = 0; i < 6; i ++ ) {
14279
14280			if ( planes[ i ].distanceToPoint( point ) < 0 ) {
14281
14282				return false;
14283
14284			}
14285
14286		}
14287
14288		return true;
14289
14290	}
14291
14292} );
14293
14294/**
14295 * Uniforms library for shared webgl shaders
14296 */
14297
14298var UniformsLib = {
14299
14300	common: {
14301
14302		diffuse: { value: new Color( 0xeeeeee ) },
14303		opacity: { value: 1.0 },
14304
14305		map: { value: null },
14306		uvTransform: { value: new Matrix3() },
14307		uv2Transform: { value: new Matrix3() },
14308
14309		alphaMap: { value: null },
14310
14311	},
14312
14313	specularmap: {
14314
14315		specularMap: { value: null },
14316
14317	},
14318
14319	envmap: {
14320
14321		envMap: { value: null },
14322		flipEnvMap: { value: - 1 },
14323		reflectivity: { value: 1.0 },
14324		refractionRatio: { value: 0.98 },
14325		maxMipLevel: { value: 0 }
14326
14327	},
14328
14329	aomap: {
14330
14331		aoMap: { value: null },
14332		aoMapIntensity: { value: 1 }
14333
14334	},
14335
14336	lightmap: {
14337
14338		lightMap: { value: null },
14339		lightMapIntensity: { value: 1 }
14340
14341	},
14342
14343	emissivemap: {
14344
14345		emissiveMap: { value: null }
14346
14347	},
14348
14349	bumpmap: {
14350
14351		bumpMap: { value: null },
14352		bumpScale: { value: 1 }
14353
14354	},
14355
14356	normalmap: {
14357
14358		normalMap: { value: null },
14359		normalScale: { value: new Vector2( 1, 1 ) }
14360
14361	},
14362
14363	displacementmap: {
14364
14365		displacementMap: { value: null },
14366		displacementScale: { value: 1 },
14367		displacementBias: { value: 0 }
14368
14369	},
14370
14371	roughnessmap: {
14372
14373		roughnessMap: { value: null }
14374
14375	},
14376
14377	metalnessmap: {
14378
14379		metalnessMap: { value: null }
14380
14381	},
14382
14383	gradientmap: {
14384
14385		gradientMap: { value: null }
14386
14387	},
14388
14389	fog: {
14390
14391		fogDensity: { value: 0.00025 },
14392		fogNear: { value: 1 },
14393		fogFar: { value: 2000 },
14394		fogColor: { value: new Color( 0xffffff ) }
14395
14396	},
14397
14398	lights: {
14399
14400		ambientLightColor: { value: [] },
14401
14402		lightProbe: { value: [] },
14403
14404		directionalLights: { value: [], properties: {
14405			direction: {},
14406			color: {}
14407		} },
14408
14409		directionalLightShadows: { value: [], properties: {
14410			shadowBias: {},
14411			shadowRadius: {},
14412			shadowMapSize: {}
14413		} },
14414
14415		directionalShadowMap: { value: [] },
14416		directionalShadowMatrix: { value: [] },
14417
14418		spotLights: { value: [], properties: {
14419			color: {},
14420			position: {},
14421			direction: {},
14422			distance: {},
14423			coneCos: {},
14424			penumbraCos: {},
14425			decay: {}
14426		} },
14427
14428		spotLightShadows: { value: [], properties: {
14429			shadowBias: {},
14430			shadowRadius: {},
14431			shadowMapSize: {}
14432		} },
14433
14434		spotShadowMap: { value: [] },
14435		spotShadowMatrix: { value: [] },
14436
14437		pointLights: { value: [], properties: {
14438			color: {},
14439			position: {},
14440			decay: {},
14441			distance: {}
14442		} },
14443
14444		pointLightShadows: { value: [], properties: {
14445			shadowBias: {},
14446			shadowRadius: {},
14447			shadowMapSize: {},
14448			shadowCameraNear: {},
14449			shadowCameraFar: {}
14450		} },
14451
14452		pointShadowMap: { value: [] },
14453		pointShadowMatrix: { value: [] },
14454
14455		hemisphereLights: { value: [], properties: {
14456			direction: {},
14457			skyColor: {},
14458			groundColor: {}
14459		} },
14460
14461		// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
14462		rectAreaLights: { value: [], properties: {
14463			color: {},
14464			position: {},
14465			width: {},
14466			height: {}
14467		} }
14468
14469	},
14470
14471	points: {
14472
14473		diffuse: { value: new Color( 0xeeeeee ) },
14474		opacity: { value: 1.0 },
14475		size: { value: 1.0 },
14476		scale: { value: 1.0 },
14477		map: { value: null },
14478		alphaMap: { value: null },
14479		uvTransform: { value: new Matrix3() }
14480
14481	},
14482
14483	sprite: {
14484
14485		diffuse: { value: new Color( 0xeeeeee ) },
14486		opacity: { value: 1.0 },
14487		center: { value: new Vector2( 0.5, 0.5 ) },
14488		rotation: { value: 0.0 },
14489		map: { value: null },
14490		alphaMap: { value: null },
14491		uvTransform: { value: new Matrix3() }
14492
14493	}
14494
14495};
14496
14497/**
14498 * @author mrdoob / http://mrdoob.com/
14499 */
14500
14501function WebGLAnimation() {
14502
14503	var context = null;
14504	var isAnimating = false;
14505	var animationLoop = null;
14506
14507	function onAnimationFrame( time, frame ) {
14508
14509		if ( isAnimating === false ) return;
14510
14511		animationLoop( time, frame );
14512
14513		context.requestAnimationFrame( onAnimationFrame );
14514
14515	}
14516
14517	return {
14518
14519		start: function () {
14520
14521			if ( isAnimating === true ) return;
14522			if ( animationLoop === null ) return;
14523
14524			context.requestAnimationFrame( onAnimationFrame );
14525
14526			isAnimating = true;
14527
14528		},
14529
14530		stop: function () {
14531
14532			isAnimating = false;
14533
14534		},
14535
14536		setAnimationLoop: function ( callback ) {
14537
14538			animationLoop = callback;
14539
14540		},
14541
14542		setContext: function ( value ) {
14543
14544			context = value;
14545
14546		}
14547
14548	};
14549
14550}
14551
14552/**
14553 * @author mrdoob / http://mrdoob.com/
14554 */
14555
14556function WebGLAttributes( gl, capabilities ) {
14557
14558	var isWebGL2 = capabilities.isWebGL2;
14559
14560	var buffers = new WeakMap();
14561
14562	function createBuffer( attribute, bufferType ) {
14563
14564		var array = attribute.array;
14565		var usage = attribute.usage;
14566
14567		var buffer = gl.createBuffer();
14568
14569		gl.bindBuffer( bufferType, buffer );
14570		gl.bufferData( bufferType, array, usage );
14571
14572		attribute.onUploadCallback();
14573
14574		var type = 5126;
14575
14576		if ( array instanceof Float32Array ) {
14577
14578			type = 5126;
14579
14580		} else if ( array instanceof Float64Array ) {
14581
14582			console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );
14583
14584		} else if ( array instanceof Uint16Array ) {
14585
14586			type = 5123;
14587
14588		} else if ( array instanceof Int16Array ) {
14589
14590			type = 5122;
14591
14592		} else if ( array instanceof Uint32Array ) {
14593
14594			type = 5125;
14595
14596		} else if ( array instanceof Int32Array ) {
14597
14598			type = 5124;
14599
14600		} else if ( array instanceof Int8Array ) {
14601
14602			type = 5120;
14603
14604		} else if ( array instanceof Uint8Array ) {
14605
14606			type = 5121;
14607
14608		}
14609
14610		return {
14611			buffer: buffer,
14612			type: type,
14613			bytesPerElement: array.BYTES_PER_ELEMENT,
14614			version: attribute.version
14615		};
14616
14617	}
14618
14619	function updateBuffer( buffer, attribute, bufferType ) {
14620
14621		var array = attribute.array;
14622		var updateRange = attribute.updateRange;
14623
14624		gl.bindBuffer( bufferType, buffer );
14625
14626		if ( updateRange.count === - 1 ) {
14627
14628			// Not using update ranges
14629
14630			gl.bufferSubData( bufferType, 0, array );
14631
14632		} else {
14633
14634			if ( isWebGL2 ) {
14635
14636				gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
14637					array, updateRange.offset, updateRange.count );
14638
14639			} else {
14640
14641				gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
14642					array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
14643
14644			}
14645
14646			updateRange.count = - 1; // reset range
14647
14648		}
14649
14650	}
14651
14652	//
14653
14654	function get( attribute ) {
14655
14656		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
14657
14658		return buffers.get( attribute );
14659
14660	}
14661
14662	function remove( attribute ) {
14663
14664		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
14665
14666		var data = buffers.get( attribute );
14667
14668		if ( data ) {
14669
14670			gl.deleteBuffer( data.buffer );
14671
14672			buffers.delete( attribute );
14673
14674		}
14675
14676	}
14677
14678	function update( attribute, bufferType ) {
14679
14680		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
14681
14682		var data = buffers.get( attribute );
14683
14684		if ( data === undefined ) {
14685
14686			buffers.set( attribute, createBuffer( attribute, bufferType ) );
14687
14688		} else if ( data.version < attribute.version ) {
14689
14690			updateBuffer( data.buffer, attribute, bufferType );
14691
14692			data.version = attribute.version;
14693
14694		}
14695
14696	}
14697
14698	return {
14699
14700		get: get,
14701		remove: remove,
14702		update: update
14703
14704	};
14705
14706}
14707
14708/**
14709 * @author mrdoob / http://mrdoob.com/
14710 * @author Mugen87 / https://github.com/Mugen87
14711 */
14712
14713// PlaneGeometry
14714
14715function PlaneGeometry( width, height, widthSegments, heightSegments ) {
14716
14717	Geometry.call( this );
14718
14719	this.type = 'PlaneGeometry';
14720
14721	this.parameters = {
14722		width: width,
14723		height: height,
14724		widthSegments: widthSegments,
14725		heightSegments: heightSegments
14726	};
14727
14728	this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
14729	this.mergeVertices();
14730
14731}
14732
14733PlaneGeometry.prototype = Object.create( Geometry.prototype );
14734PlaneGeometry.prototype.constructor = PlaneGeometry;
14735
14736// PlaneBufferGeometry
14737
14738function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {
14739
14740	BufferGeometry.call( this );
14741
14742	this.type = 'PlaneBufferGeometry';
14743
14744	this.parameters = {
14745		width: width,
14746		height: height,
14747		widthSegments: widthSegments,
14748		heightSegments: heightSegments
14749	};
14750
14751	width = width || 1;
14752	height = height || 1;
14753
14754	var width_half = width / 2;
14755	var height_half = height / 2;
14756
14757	var gridX = Math.floor( widthSegments ) || 1;
14758	var gridY = Math.floor( heightSegments ) || 1;
14759
14760	var gridX1 = gridX + 1;
14761	var gridY1 = gridY + 1;
14762
14763	var segment_width = width / gridX;
14764	var segment_height = height / gridY;
14765
14766	var ix, iy;
14767
14768	// buffers
14769
14770	var indices = [];
14771	var vertices = [];
14772	var normals = [];
14773	var uvs = [];
14774
14775	// generate vertices, normals and uvs
14776
14777	for ( iy = 0; iy < gridY1; iy ++ ) {
14778
14779		var y = iy * segment_height - height_half;
14780
14781		for ( ix = 0; ix < gridX1; ix ++ ) {
14782
14783			var x = ix * segment_width - width_half;
14784
14785			vertices.push( x, - y, 0 );
14786
14787			normals.push( 0, 0, 1 );
14788
14789			uvs.push( ix / gridX );
14790			uvs.push( 1 - ( iy / gridY ) );
14791
14792		}
14793
14794	}
14795
14796	// indices
14797
14798	for ( iy = 0; iy < gridY; iy ++ ) {
14799
14800		for ( ix = 0; ix < gridX; ix ++ ) {
14801
14802			var a = ix + gridX1 * iy;
14803			var b = ix + gridX1 * ( iy + 1 );
14804			var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
14805			var d = ( ix + 1 ) + gridX1 * iy;
14806
14807			// faces
14808
14809			indices.push( a, b, d );
14810			indices.push( b, c, d );
14811
14812		}
14813
14814	}
14815
14816	// build geometry
14817
14818	this.setIndex( indices );
14819	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
14820	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
14821	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
14822
14823}
14824
14825PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
14826PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;
14827
14828var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
14829
14830var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
14831
14832var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif";
14833
14834var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif";
14835
14836var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
14837
14838var begin_vertex = "vec3 transformed = vec3( position );";
14839
14840var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
14841
14842var bsdfs = "vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );
14842\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE  = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS  = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x >
14842 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha  = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n}\n#endif";
14843
14844var 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}
14844\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif";
14845
14846var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif";
14847
14848var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
14849
14850var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
14851
14852var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
14853
14854var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif";
14855
14856var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
14857
14858var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif";
14859
14860var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif";
14861
14862var 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#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n  return m[ 2 ][ 3 ] == - 1.0;\n}";
14863
14864var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_maxMipLevel 8.0\n#define cubeUV_minMipLevel 4.0\n#define cubeUV_maxTileSize 256.0\n#define cubeUV_minTileSize 16.0\nfloat getFace(vec3 direction) {\n    vec3 absDirection = abs(direction);\n    float face = -1.0;\n    if (absDirection.x > absDirection.z) {\n      if (absDirection.x > absDirection.y)\n        face = direction.x > 0.0 ? 0.0 : 3.0;\n      else\n        face = direction.y > 0.0 ? 1.0 : 4.0;\n    } else {\n      if (absDirection.z > absDirection.y)\n        face = direction.z > 0.0 ? 2.0 : 5.0;\n      else\n        face = direction.y > 0.0 ? 1.0 : 4.0;\n    }\n    return face;\n}\nvec2 getUV(vec3 direction, float face) {\n    vec2 uv;\n    if (face == 0.0) {\n      uv = vec2(-direction.z, direction.y) / abs(direction.x);\n    } else if (face == 1.0) {\n      uv = vec2(direction.x, -direction.z) / abs(direction.y);\n    } else if (face == 2.0) {\n      uv = direction.xy / abs(direction.z);\n    } else if (face == 3.0) {\n      uv = vec2(direction.z, direction.y) / abs(direction.x);\n    } else if (face == 4.0) {\n      uv = direction.xz / abs(direction.y);\n    } else {\n      uv = vec2(-direction.x, direction.y) / abs(direction.z);\n    }\n    return 0.5 * (uv + 1.0);\n}\nvec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\n  float face = getFace(direction);\n  float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\n  mipInt = max(mipInt, cubeUV_minMipLevel);\n  float faceSize = exp2(mipInt);\n  float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\n  vec2 uv = getUV(direction, face) * (faceSize - 1.0);\n  vec2 f = fract(uv);\n  uv += 0.5 - f;\n  if (face > 2.0) {\n    uv.y += faceSize;\n    face -= 3.0;\n  }\n  uv.x += face * faceSize;\n  if(mipInt < cubeUV_maxMipLevel){\n    uv.y += 2.0 * cubeUV_maxTileSize;\n  }\n  uv.y += filterInt * 2.0 * cubeUV_minTileSize;\n  uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\n  uv *= texelSize;\n  vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n  uv.x += texelSize;\n  vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n  uv.y += texelSize;\n  vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n  uv.x -= texelSize;\n  vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n  vec3 tm = mix(tl, tr, f.x);\n  vec3 bm = mix(bl, br, f.x);\n  return mix(tm, bm, f.y);\n}\n#define r0 1.0\n#define v0 0.339\n#define m0 -2.0\n#define r1 0.8\n#define v1 0.276\n#define m1 -1.0\n#define r4 0.4\n#define v4 0.046\n#define m4 2.0\n#define r5 0.305\n#define v5 0.016\n#define m5 3.0\n#define r6 0.21\n#define v6 0.0038\n#define m6 4.0\nfloat roughnessToMip(float roughness) {\
14864n  float mip = 0.0;\n  if (roughness >= r1) {\n    mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\n  } else if (roughness >= r4) {\n    mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\n  } else if (roughness >= r5) {\n    mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\n  } else if (roughness >= r6) {\n    mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\n  } else {\n    mip = -2.0 * log2(1.16 * roughness);  }\n  return mip;\n}\nvec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {\n  float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel);\n  float mipF = fract(mip);\n  float mipInt = floor(mip);\n  vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt);\n  if (mipF == 0.0) {\n    return vec4(color0, 1.0);\n  } else {\n    vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0);\n    return vec4(mix(color0, color1, mipF), 1.0);\n  }\n}\n#endif";
14865
14866var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif";
14867
14868var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
14869
14870var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif";
14871
14872var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
14873
14874var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
14875
14876var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
14877
14878var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value )  {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}
14878\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}";
14879
14880var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\t\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t}  else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#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\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif";
14881
14882var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif";
14883
14884var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif";
14885
14886var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif";
14887
14888var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) { \n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t}
14888 else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif";
14889
14890var fog_vertex = "#ifdef USE_FOG\n\tfogDepth = -mvPosition.z;\n#endif";
14891
14892var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif";
14893
14894var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
14895
14896var 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";
14897
14898var gradientmap_pars_fragment = "#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn texture2D( gradientMap, coord ).rgb;\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}";
14899
14900var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif";
14901
14902var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
14903
14904var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif";
14905
14906var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\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}
14906\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif";
14907
14908var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t  vec3 reflectVec = reflect( -viewDir, normal );\n\t\t  reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t  vec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#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";
14909
14910var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
14911
14912var lights_toon_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct ToonMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)";
14913
14914var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
14915
14916var 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\tfloat dotNL = saturate( dot
14916( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)";
14917
14918var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;
14918\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheen;\n#endif";
14919
14920var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot
14920( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
14921
14922var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
14923
14924var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\t#endif\n#endif";
14925
14926var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif";
14927
14928var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
14929
14930var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
14931
14932var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif";
14933
14934var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif";
14935
14936var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif";
14937
14938var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
14939
14940var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif";
14941
14942var map_particle_pars_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
14943
14944var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
14945
14946var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
14947
14948var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif";
14949
14950var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
14951
14952var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t#endif\n#endif";
14953
14954var normal_fragment_begin = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;";
14955
14956var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );
14956\n\t#else\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif";
14957
14958var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif";
14959
14960var clearcoat_normal_fragment_begin = "#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";
14961
14962var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\n\t#endif\n#endif";
14963
14964var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif";
14965
14966var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}";
14967
14968var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
14969
14970var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;";
14971
14972var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
14973
14974var dithering_pars_fragment = "#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif";
14975
14976var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
14977
14978var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
14979
14980var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];
14980\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );
14980\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif";
14981
14982var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
14983
14984var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif";
14985
14986var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}";
14987
14988var 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";
14989
14990var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif";
14991
14992var 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";
14993
14994var 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;
14994\n\tskinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif";
14995
14996var 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";
14997
14998var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
14999
15000var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
15001
15002var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\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}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n}";
15003
15004var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";
15005
15006var uv_pars_vertex = "#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif";
15007
15008var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
15009
15010var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
15011
15012var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif";
15013
15014var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
15015
15016var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif";
15017
15018var background_frag = "uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
15019
15020var background_vert = "varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}";
15021
15022var cube_frag = "#include <envmap_common_pars_fragment>\nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include <envmap_fragment>\n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
15023
15024var cube_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
15025
15026var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}";
15027
15028var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}";
15029
15030var 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}";
15031
15032var 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}";
15033
15034var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\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\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
15035
15036var equirect_vert = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
15037
15038var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
15039
15040var 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\tvLineDistance = scale * lineDistance;\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
15041
15042var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
15043
15044var 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}";
15045
15046var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
15047
15048var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
15049
15050var meshmatcap_frag = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 +
15050 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
15051
15052var meshmatcap_vert = "#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
15053
15054var meshtoon_frag = "#define TOON\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 <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_toon_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + 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}";
15055
15056var meshtoon_vert = "#define TOON\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
15057
15058var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <cube_uv_reflection_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
15059
15060var 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}";
15061
15062var meshphysical_frag = "#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSPARENCY\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSPARENCY\n\tuniform float transparency;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;
15062\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#ifdef TRANSPARENCY\n\t\tdiffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );\n\t#endif\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
15063
15064var meshphysical_vert = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
15065
15066var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}";
15067
15068var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}";
15069
15070var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
15071
15072var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}";
15073
15074var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
15075
15076var shadow_vert = "#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
15077
15078var sprite_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
15079
15080var sprite_vert = "uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
15081
15082var ShaderChunk = {
15083	alphamap_fragment: alphamap_fragment,
15084	alphamap_pars_fragment: alphamap_pars_fragment,
15085	alphatest_fragment: alphatest_fragment,
15086	aomap_fragment: aomap_fragment,
15087	aomap_pars_fragment: aomap_pars_fragment,
15088	begin_vertex: begin_vertex,
15089	beginnormal_vertex: beginnormal_vertex,
15090	bsdfs: bsdfs,
15091	bumpmap_pars_fragment: bumpmap_pars_fragment,
15092	clipping_planes_fragment: clipping_planes_fragment,
15093	clipping_planes_pars_fragment: clipping_planes_pars_fragment,
15094	clipping_planes_pars_vertex: clipping_planes_pars_vertex,
15095	clipping_planes_vertex: clipping_planes_vertex,
15096	color_fragment: color_fragment,
15097	color_pars_fragment: color_pars_fragment,
15098	color_pars_vertex: color_pars_vertex,
15099	color_vertex: color_vertex,
15100	common: common,
15101	cube_uv_reflection_fragment: cube_uv_reflection_fragment,
15102	defaultnormal_vertex: defaultnormal_vertex,
15103	displacementmap_pars_vertex: displacementmap_pars_vertex,
15104	displacementmap_vertex: displacementmap_vertex,
15105	emissivemap_fragment: emissivemap_fragment,
15106	emissivemap_pars_fragment: emissivemap_pars_fragment,
15107	encodings_fragment: encodings_fragment,
15108	encodings_pars_fragment: encodings_pars_fragment,
15109	envmap_fragment: envmap_fragment,
15110	envmap_common_pars_fragment: envmap_common_pars_fragment,
15111	envmap_pars_fragment: envmap_pars_fragment,
15112	envmap_pars_vertex: envmap_pars_vertex,
15113	envmap_physical_pars_fragment: envmap_physical_pars_fragment,
15114	envmap_vertex: envmap_vertex,
15115	fog_vertex: fog_vertex,
15116	fog_pars_vertex: fog_pars_vertex,
15117	fog_fragment: fog_fragment,
15118	fog_pars_fragment: fog_pars_fragment,
15119	gradientmap_pars_fragment: gradientmap_pars_fragment,
15120	lightmap_fragment: lightmap_fragment,
15121	lightmap_pars_fragment: lightmap_pars_fragment,
15122	lights_lambert_vertex: lights_lambert_vertex,
15123	lights_pars_begin: lights_pars_begin,
15124	lights_toon_fragment: lights_toon_fragment,
15125	lights_toon_pars_fragment: lights_toon_pars_fragment,
15126	lights_phong_fragment: lights_phong_fragment,
15127	lights_phong_pars_fragment: lights_phong_pars_fragment,
15128	lights_physical_fragment: lights_physical_fragment,
15129	lights_physical_pars_fragment: lights_physical_pars_fragment,
15130	lights_fragment_begin: lights_fragment_begin,
15131	lights_fragment_maps: lights_fragment_maps,
15132	lights_fragment_end: lights_fragment_end,
15133	logdepthbuf_fragment: logdepthbuf_fragment,
15134	logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
15135	logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
15136	logdepthbuf_vertex: logdepthbuf_vertex,
15137	map_fragment: map_fragment,
15138	map_pars_fragment: map_pars_fragment,
15139	map_particle_fragment: map_particle_fragment,
15140	map_particle_pars_fragment: map_particle_pars_fragment,
15141	metalnessmap_fragment: metalnessmap_fragment,
15142	metalnessmap_pars_fragment: metalnessmap_pars_fragment,
15143	morphnormal_vertex: morphnormal_vertex,
15144	morphtarget_pars_vertex: morphtarget_pars_vertex,
15145	morphtarget_vertex: morphtarget_vertex,
15146	normal_fragment_begin: normal_fragment_begin,
15147	normal_fragment_maps: normal_fragment_maps,
15148	normalmap_pars_fragment: normalmap_pars_fragment,
15149	clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
15150	clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
15151	clearcoat_pars_fragment: clearcoat_pars_fragment,
15152	packing: packing,
15153	premultiplied_alpha_fragment: premultiplied_alpha_fragment,
15154	project_vertex: project_vertex,
15155	dithering_fragment: dithering_fragment,
15156	dithering_pars_fragment: dithering_pars_fragment,
15157	roughnessmap_fragment: roughnessmap_fragment,
15158	roughnessmap_pars_fragment: roughnessmap_pars_fragment,
15159	shadowmap_pars_fragment: shadowmap_pars_fragment,
15160	shadowmap_pars_vertex: shadowmap_pars_vertex,
15161	shadowmap_vertex: shadowmap_vertex,
15162	shadowmask_pars_fragment: shadowmask_pars_fragment,
15163	skinbase_vertex: skinbase_vertex,
15164	skinning_pars_vertex: skinning_pars_vertex,
15165	skinning_vertex: skinning_vertex,
15166	skinnormal_vertex: skinnormal_vertex,
15167	specularmap_fragment: specularmap_fragment,
15168	specularmap_pars_fragment: specularmap_pars_fragment,
15169	tonemapping_fragment: tonemapping_fragment,
15170	tonemapping_pars_fragment: tonemapping_pars_fragment,
15171	uv_pars_fragment: uv_pars_fragment,
15172	uv_pars_vertex: uv_pars_vertex,
15173	uv_vertex: uv_vertex,
15174	uv2_pars_fragment: uv2_pars_fragment,
15175	uv2_pars_vertex: uv2_pars_vertex,
15176	uv2_vertex: uv2_vertex,
15177	worldpos_vertex: worldpos_vertex,
15178
15179	background_frag: background_frag,
15180	background_vert: background_vert,
15181	cube_frag: cube_frag,
15182	cube_vert: cube_vert,
15183	depth_frag: depth_frag,
15184	depth_vert: depth_vert,
15185	distanceRGBA_frag: distanceRGBA_frag,
15186	distanceRGBA_vert: distanceRGBA_vert,
15187	equirect_frag: equirect_frag,
15188	equirect_vert: equirect_vert,
15189	linedashed_frag: linedashed_frag,
15190	linedashed_vert: linedashed_vert,
15191	meshbasic_frag: meshbasic_frag,
15192	meshbasic_vert: meshbasic_vert,
15193	meshlambert_frag: meshlambert_frag,
15194	meshlambert_vert: meshlambert_vert,
15195	meshmatcap_frag: meshmatcap_frag,
15196	meshmatcap_vert: meshmatcap_vert,
15197	meshtoon_frag: meshtoon_frag,
15198	meshtoon_vert: meshtoon_vert,
15199	meshphong_frag: meshphong_frag,
15200	meshphong_vert: meshphong_vert,
15201	meshphysical_frag: meshphysical_frag,
15202	meshphysical_vert: meshphysical_vert,
15203	normal_frag: normal_frag,
15204	normal_vert: normal_vert,
15205	points_frag: points_frag,
15206	points_vert: points_vert,
15207	shadow_frag: shadow_frag,
15208	shadow_vert: shadow_vert,
15209	sprite_frag: sprite_frag,
15210	sprite_vert: sprite_vert
15211};
15212
15213/**
15214 * @author alteredq / http://alteredqualia.com/
15215 * @author mrdoob / http://mrdoob.com/
15216 * @author mikael emtinger / http://gomo.se/
15217 */
15218
15219var ShaderLib = {
15220
15221	basic: {
15222
15223		uniforms: mergeUniforms( [
15224			UniformsLib.common,
15225			UniformsLib.specularmap,
15226			UniformsLib.envmap,
15227			UniformsLib.aomap,
15228			UniformsLib.lightmap,
15229			UniformsLib.fog
15230		] ),
15231
15232		vertexShader: ShaderChunk.meshbasic_vert,
15233		fragmentShader: ShaderChunk.meshbasic_frag
15234
15235	},
15236
15237	lambert: {
15238
15239		uniforms: mergeUniforms( [
15240			UniformsLib.common,
15241			UniformsLib.specularmap,
15242			UniformsLib.envmap,
15243			UniformsLib.aomap,
15244			UniformsLib.lightmap,
15245			UniformsLib.emissivemap,
15246			UniformsLib.fog,
15247			UniformsLib.lights,
15248			{
15249				emissive: { value: new Color( 0x000000 ) }
15250			}
15251		] ),
15252
15253		vertexShader: ShaderChunk.meshlambert_vert,
15254		fragmentShader: ShaderChunk.meshlambert_frag
15255
15256	},
15257
15258	phong: {
15259
15260		uniforms: mergeUniforms( [
15261			UniformsLib.common,
15262			UniformsLib.specularmap,
15263			UniformsLib.envmap,
15264			UniformsLib.
vendor: 4,907 bytes, lines 15264-15525
15264aomap,
15265			UniformsLib.lightmap,
15266			UniformsLib.emissivemap,
15267			UniformsLib.bumpmap,
15268			UniformsLib.normalmap,
15269			UniformsLib.displacementmap,
15270			UniformsLib.fog,
15271			UniformsLib.lights,
15272			{
15273				emissive: { value: new Color( 0x000000 ) },
15274				specular: { value: new Color( 0x111111 ) },
15275				shininess: { value: 30 }
15276			}
15277		] ),
15278
15279		vertexShader: ShaderChunk.meshphong_vert,
15280		fragmentShader: ShaderChunk.meshphong_frag
15281
15282	},
15283
15284	standard: {
15285
15286		uniforms: mergeUniforms( [
15287			UniformsLib.common,
15288			UniformsLib.envmap,
15289			UniformsLib.aomap,
15290			UniformsLib.lightmap,
15291			UniformsLib.emissivemap,
15292			UniformsLib.bumpmap,
15293			UniformsLib.normalmap,
15294			UniformsLib.displacementmap,
15295			UniformsLib.roughnessmap,
15296			UniformsLib.metalnessmap,
15297			UniformsLib.fog,
15298			UniformsLib.lights,
15299			{
15300				emissive: { value: new Color( 0x000000 ) },
15301				roughness: { value: 1.0 },
15302				metalness: { value: 0.0 },
15303				envMapIntensity: { value: 1 } // temporary
15304			}
15305		] ),
15306
15307		vertexShader: ShaderChunk.meshphysical_vert,
15308		fragmentShader: ShaderChunk.meshphysical_frag
15309
15310	},
15311
15312	toon: {
15313
15314		uniforms: mergeUniforms( [
15315			UniformsLib.common,
15316			UniformsLib.specularmap,
15317			UniformsLib.aomap,
15318			UniformsLib.lightmap,
15319			UniformsLib.emissivemap,
15320			UniformsLib.bumpmap,
15321			UniformsLib.normalmap,
15322			UniformsLib.displacementmap,
15323			UniformsLib.gradientmap,
15324			UniformsLib.fog,
15325			UniformsLib.lights,
15326			{
15327				emissive: { value: new Color( 0x000000 ) },
15328				specular: { value: new Color( 0x111111 ) },
15329				shininess: { value: 30 }
15330			}
15331		] ),
15332
15333		vertexShader: ShaderChunk.meshtoon_vert,
15334		fragmentShader: ShaderChunk.meshtoon_frag
15335
15336	},
15337
15338	matcap: {
15339
15340		uniforms: mergeUniforms( [
15341			UniformsLib.common,
15342			UniformsLib.bumpmap,
15343			UniformsLib.normalmap,
15344			UniformsLib.displacementmap,
15345			UniformsLib.fog,
15346			{
15347				matcap: { value: null }
15348			}
15349		] ),
15350
15351		vertexShader: ShaderChunk.meshmatcap_vert,
15352		fragmentShader: ShaderChunk.meshmatcap_frag
15353
15354	},
15355
15356	points: {
15357
15358		uniforms: mergeUniforms( [
15359			UniformsLib.points,
15360			UniformsLib.fog
15361		] ),
15362
15363		vertexShader: ShaderChunk.points_vert,
15364		fragmentShader: ShaderChunk.points_frag
15365
15366	},
15367
15368	dashed: {
15369
15370		uniforms: mergeUniforms( [
15371			UniformsLib.common,
15372			UniformsLib.fog,
15373			{
15374				scale: { value: 1 },
15375				dashSize: { value: 1 },
15376				totalSize: { value: 2 }
15377			}
15378		] ),
15379
15380		vertexShader: ShaderChunk.linedashed_vert,
15381		fragmentShader: ShaderChunk.linedashed_frag
15382
15383	},
15384
15385	depth: {
15386
15387		uniforms: mergeUniforms( [
15388			UniformsLib.common,
15389			UniformsLib.displacementmap
15390		] ),
15391
15392		vertexShader: ShaderChunk.depth_vert,
15393		fragmentShader: ShaderChunk.depth_frag
15394
15395	},
15396
15397	normal: {
15398
15399		uniforms: mergeUniforms( [
15400			UniformsLib.common,
15401			UniformsLib.bumpmap,
15402			UniformsLib.normalmap,
15403			UniformsLib.displacementmap,
15404			{
15405				opacity: { value: 1.0 }
15406			}
15407		] ),
15408
15409		vertexShader: ShaderChunk.normal_vert,
15410		fragmentShader: ShaderChunk.normal_frag
15411
15412	},
15413
15414	sprite: {
15415
15416		uniforms: mergeUniforms( [
15417			UniformsLib.sprite,
15418			UniformsLib.fog
15419		] ),
15420
15421		vertexShader: ShaderChunk.sprite_vert,
15422		fragmentShader: ShaderChunk.sprite_frag
15423
15424	},
15425
15426	background: {
15427
15428		uniforms: {
15429			uvTransform: { value: new Matrix3() },
15430			t2D: { value: null },
15431		},
15432
15433		vertexShader: ShaderChunk.background_vert,
15434		fragmentShader: ShaderChunk.background_frag
15435
15436	},
15437	/* -------------------------------------------------------------------------
15438	//	Cube map shader
15439	 ------------------------------------------------------------------------- */
15440
15441	cube: {
15442
15443		uniforms: mergeUniforms( [
15444			UniformsLib.envmap,
15445			{
15446				opacity: { value: 1.0 }
15447			}
15448		] ),
15449
15450		vertexShader: ShaderChunk.cube_vert,
15451		fragmentShader: ShaderChunk.cube_frag
15452
15453	},
15454
15455	equirect: {
15456
15457		uniforms: {
15458			tEquirect: { value: null },
15459		},
15460
15461		vertexShader: ShaderChunk.equirect_vert,
15462		fragmentShader: ShaderChunk.equirect_frag
15463
15464	},
15465
15466	distanceRGBA: {
15467
15468		uniforms: mergeUniforms( [
15469			UniformsLib.common,
15470			UniformsLib.displacementmap,
15471			{
15472				referencePosition: { value: new Vector3() },
15473				nearDistance: { value: 1 },
15474				farDistance: { value: 1000 }
15475			}
15476		] ),
15477
15478		vertexShader: ShaderChunk.distanceRGBA_vert,
15479		fragmentShader: ShaderChunk.distanceRGBA_frag
15480
15481	},
15482
15483	shadow: {
15484
15485		uniforms: mergeUniforms( [
15486			UniformsLib.lights,
15487			UniformsLib.fog,
15488			{
15489				color: { value: new Color( 0x00000 ) },
15490				opacity: { value: 1.0 }
15491			},
15492		] ),
15493
15494		vertexShader: ShaderChunk.shadow_vert,
15495		fragmentShader: ShaderChunk.shadow_frag
15496
15497	}
15498
15499};
15500
15501ShaderLib.physical = {
15502
15503	uniforms: mergeUniforms( [
15504		ShaderLib.standard.uniforms,
15505		{
15506			clearcoat: { value: 0 },
15507			clearcoatMap: { value: null },
15508			clearcoatRoughness: { value: 0 },
15509			clearcoatRoughnessMap: { value: null },
15510			clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
15511			clearcoatNormalMap: { value: null },
15512			sheen: { value: new Color( 0x000000 ) },
15513			transparency: { value: 0 },
15514		}
15515	] ),
15516
15517	vertexShader: ShaderChunk.meshphysical_vert,
15518	fragmentShader: ShaderChunk.meshphysical_frag
15519
15520};
15521
15522/**
15523 * @author mrdoob / http://mrdoob.com/
15524 */
15525
vendor: 17,557 bytes, lines 15526-16393
15526function WebGLBackground( renderer, state, objects, premultipliedAlpha ) {
15527
15528	var clearColor = new Color( 0x000000 );
15529	var clearAlpha = 0;
15530
15531	var planeMesh;
15532	var boxMesh;
15533
15534	var currentBackground = null;
15535	var currentBackgroundVersion = 0;
15536	var currentTonemapping = null;
15537
15538	function render( renderList, scene, camera, forceClear ) {
15539
15540		var background = scene.background;
15541
15542		// Ignore background in AR
15543		// TODO: Reconsider this.
15544
15545		var xr = renderer.xr;
15546		var session = xr.getSession && xr.getSession();
15547
15548		if ( session && session.environmentBlendMode === 'additive' ) {
15549
15550			background = null;
15551
15552		}
15553
15554		if ( background === null ) {
15555
15556			setClear( clearColor, clearAlpha );
15557
15558		} else if ( background && background.isColor ) {
15559
15560			setClear( background, 1 );
15561			forceClear = true;
15562
15563		}
15564
15565		if ( renderer.autoClear || forceClear ) {
15566
15567			renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
15568
15569		}
15570
15571		if ( background && ( background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping ) ) {
15572
15573			if ( boxMesh === undefined ) {
15574
15575				boxMesh = new Mesh(
15576					new BoxBufferGeometry( 1, 1, 1 ),
15577					new ShaderMaterial( {
15578						type: 'BackgroundCubeMaterial',
15579						uniforms: cloneUniforms( ShaderLib.cube.uniforms ),
15580						vertexShader: ShaderLib.cube.vertexShader,
15581						fragmentShader: ShaderLib.cube.fragmentShader,
15582						side: BackSide,
15583						depthTest: false,
15584						depthWrite: false,
15585						fog: false
15586					} )
15587				);
15588
15589				boxMesh.geometry.deleteAttribute( 'normal' );
15590				boxMesh.geometry.deleteAttribute( 'uv' );
15591
15592				boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
15593
15594					this.matrixWorld.copyPosition( camera.matrixWorld );
15595
15596				};
15597
15598				// enable code injection for non-built-in material
15599				Object.defineProperty( boxMesh.material, 'envMap', {
15600
15601					get: function () {
15602
15603						return this.uniforms.envMap.value;
15604
15605					}
15606
15607				} );
15608
15609				objects.update( boxMesh );
15610
15611			}
15612
15613			var texture = background.isWebGLCubeRenderTarget ? background.texture : background;
15614
15615			boxMesh.material.uniforms.envMap.value = texture;
15616			boxMesh.material.uniforms.flipEnvMap.value = texture.isCubeTexture ? - 1 : 1;
15617
15618			if ( currentBackground !== background ||
15619				currentBackgroundVersion !== texture.version ||
15620				currentTonemapping !== renderer.toneMapping ) {
15621
15622				boxMesh.material.needsUpdate = true;
15623
15624				currentBackground = background;
15625				currentBackgroundVersion = texture.version;
15626				currentTonemapping = renderer.toneMapping;
15627
15628			}
15629
15630			// push to the pre-sorted opaque render list
15631			renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
15632
15633		} else if ( background && background.isTexture ) {
15634
15635			if ( planeMesh === undefined ) {
15636
15637				planeMesh = new Mesh(
15638					new PlaneBufferGeometry( 2, 2 ),
15639					new ShaderMaterial( {
15640						type: 'BackgroundMaterial',
15641						uniforms: cloneUniforms( ShaderLib.background.uniforms ),
15642						vertexShader: ShaderLib.background.vertexShader,
15643						fragmentShader: ShaderLib.background.fragmentShader,
15644						side: FrontSide,
15645						depthTest: false,
15646						depthWrite: false,
15647						fog: false
15648					} )
15649				);
15650
15651				planeMesh.geometry.deleteAttribute( 'normal' );
15652
15653				// enable code injection for non-built-in material
15654				Object.defineProperty( planeMesh.material, 'map', {
15655
15656					get: function () {
15657
15658						return this.uniforms.t2D.value;
15659
15660					}
15661
15662				} );
15663
15664				objects.update( planeMesh );
15665
15666			}
15667
15668			planeMesh.material.uniforms.t2D.value = background;
15669
15670			if ( background.matrixAutoUpdate === true ) {
15671
15672				background.updateMatrix();
15673
15674			}
15675
15676			planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
15677
15678			if ( currentBackground !== background ||
15679				currentBackgroundVersion !== background.version ||
15680				currentTonemapping !== renderer.toneMapping ) {
15681
15682				planeMesh.material.needsUpdate = true;
15683
15684				currentBackground = background;
15685				currentBackgroundVersion = background.version;
15686				currentTonemapping = renderer.toneMapping;
15687
15688			}
15689
15690
15691			// push to the pre-sorted opaque render list
15692			renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
15693
15694		}
15695
15696	}
15697
15698	function setClear( color, alpha ) {
15699
15700		state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );
15701
15702	}
15703
15704	return {
15705
15706		getClearColor: function () {
15707
15708			return clearColor;
15709
15710		},
15711		setClearColor: function ( color, alpha ) {
15712
15713			clearColor.set( color );
15714			clearAlpha = alpha !== undefined ? alpha : 1;
15715			setClear( clearColor, clearAlpha );
15716
15717		},
15718		getClearAlpha: function () {
15719
15720			return clearAlpha;
15721
15722		},
15723		setClearAlpha: function ( alpha ) {
15724
15725			clearAlpha = alpha;
15726			setClear( clearColor, clearAlpha );
15727
15728		},
15729		render: render
15730
15731	};
15732
15733}
15734
15735/**
15736 * @author mrdoob / http://mrdoob.com/
15737 */
15738
15739function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
15740
15741	var isWebGL2 = capabilities.isWebGL2;
15742
15743	var mode;
15744
15745	function setMode( value ) {
15746
15747		mode = value;
15748
15749	}
15750
15751	function render( start, count ) {
15752
15753		gl.drawArrays( mode, start, count );
15754
15755		info.update( count, mode );
15756
15757	}
15758
15759	function renderInstances( geometry, start, count, primcount ) {
15760
15761		if ( primcount === 0 ) return;
15762
15763		var extension, methodName;
15764
15765		if ( isWebGL2 ) {
15766
15767			extension = gl;
15768			methodName = 'drawArraysInstanced';
15769
15770		} else {
15771
15772			extension = extensions.get( 'ANGLE_instanced_arrays' );
15773			methodName = 'drawArraysInstancedANGLE';
15774
15775			if ( extension === null ) {
15776
15777				console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
15778				return;
15779
15780			}
15781
15782		}
15783
15784		extension[ methodName ]( mode, start, count, primcount );
15785
15786		info.update( count, mode, primcount );
15787
15788	}
15789
15790	//
15791
15792	this.setMode = setMode;
15793	this.render = render;
15794	this.renderInstances = renderInstances;
15795
15796}
15797
15798/**
15799 * @author mrdoob / http://mrdoob.com/
15800 */
15801
15802function WebGLCapabilities( gl, extensions, parameters ) {
15803
15804	var maxAnisotropy;
15805
15806	function getMaxAnisotropy() {
15807
15808		if ( maxAnisotropy !== undefined ) return maxAnisotropy;
15809
15810		var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
15811
15812		if ( extension !== null ) {
15813
15814			maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
15815
15816		} else {
15817
15818			maxAnisotropy = 0;
15819
15820		}
15821
15822		return maxAnisotropy;
15823
15824	}
15825
15826	function getMaxPrecision( precision ) {
15827
15828		if ( precision === 'highp' ) {
15829
15830			if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
15831				gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
15832
15833				return 'highp';
15834
15835			}
15836
15837			precision = 'mediump';
15838
15839		}
15840
15841		if ( precision === 'mediump' ) {
15842
15843			if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
15844				gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
15845
15846				return 'mediump';
15847
15848			}
15849
15850		}
15851
15852		return 'lowp';
15853
15854	}
15855
15856	/* eslint-disable no-undef */
15857	var isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||
15858		( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );
15859	/* eslint-enable no-undef */
15860
15861	var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
15862	var maxPrecision = getMaxPrecision( precision );
15863
15864	if ( maxPrecision !== precision ) {
15865
15866		console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
15867		precision = maxPrecision;
15868
15869	}
15870
15871	var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
15872
15873	var maxTextures = gl.getParameter( 34930 );
15874	var maxVertexTextures = gl.getParameter( 35660 );
15875	var maxTextureSize = gl.getParameter( 3379 );
15876	var maxCubemapSize = gl.getParameter( 34076 );
15877
15878	var maxAttributes = gl.getParameter( 34921 );
15879	var maxVertexUniforms = gl.getParameter( 36347 );
15880	var maxVaryings = gl.getParameter( 36348 );
15881	var maxFragmentUniforms = gl.getParameter( 36349 );
15882
15883	var vertexTextures = maxVertexTextures > 0;
15884	var floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
15885	var floatVertexTextures = vertexTextures && floatFragmentTextures;
15886
15887	var maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
15888
15889	return {
15890
15891		isWebGL2: isWebGL2,
15892
15893		getMaxAnisotropy: getMaxAnisotropy,
15894		getMaxPrecision: getMaxPrecision,
15895
15896		precision: precision,
15897		logarithmicDepthBuffer: logarithmicDepthBuffer,
15898
15899		maxTextures: maxTextures,
15900		maxVertexTextures: maxVertexTextures,
15901		maxTextureSize: maxTextureSize,
15902		maxCubemapSize: maxCubemapSize,
15903
15904		maxAttributes: maxAttributes,
15905		maxVertexUniforms: maxVertexUniforms,
15906		maxVaryings: maxVaryings,
15907		maxFragmentUniforms: maxFragmentUniforms,
15908
15909		vertexTextures: vertexTextures,
15910		floatFragmentTextures: floatFragmentTextures,
15911		floatVertexTextures: floatVertexTextures,
15912
15913		maxSamples: maxSamples
15914
15915	};
15916
15917}
15918
15919/**
15920 * @author tschw
15921 */
15922
15923function WebGLClipping() {
15924
15925	var scope = this,
15926
15927		globalState = null,
15928		numGlobalPlanes = 0,
15929		localClippingEnabled = false,
15930		renderingShadows = false,
15931
15932		plane = new Plane(),
15933		viewNormalMatrix = new Matrix3(),
15934
15935		uniform = { value: null, needsUpdate: false };
15936
15937	this.uniform = uniform;
15938	this.numPlanes = 0;
15939	this.numIntersection = 0;
15940
15941	this.init = function ( planes, enableLocalClipping, camera ) {
15942
15943		var enabled =
15944			planes.length !== 0 ||
15945			enableLocalClipping ||
15946			// enable state of previous frame - the clipping code has to
15947			// run another frame in order to reset the state:
15948			numGlobalPlanes !== 0 ||
15949			localClippingEnabled;
15950
15951		localClippingEnabled = enableLocalClipping;
15952
15953		globalState = projectPlanes( planes, camera, 0 );
15954		numGlobalPlanes = planes.length;
15955
15956		return enabled;
15957
15958	};
15959
15960	this.beginShadows = function () {
15961
15962		renderingShadows = true;
15963		projectPlanes( null );
15964
15965	};
15966
15967	this.endShadows = function () {
15968
15969		renderingShadows = false;
15970		resetGlobalState();
15971
15972	};
15973
15974	this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {
15975
15976		if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
15977
15978			// there's no local clipping
15979
15980			if ( renderingShadows ) {
15981
15982				// there's no global clipping
15983
15984				projectPlanes( null );
15985
15986			} else {
15987
15988				resetGlobalState();
15989
15990			}
15991
15992		} else {
15993
15994			var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
15995				lGlobal = nGlobal * 4,
15996
15997				dstArray = cache.clippingState || null;
15998
15999			uniform.value = dstArray; // ensure unique state
16000
16001			dstArray = projectPlanes( planes, camera, lGlobal, fromCache );
16002
16003			for ( var i = 0; i !== lGlobal; ++ i ) {
16004
16005				dstArray[ i ] = globalState[ i ];
16006
16007			}
16008
16009			cache.clippingState = dstArray;
16010			this.numIntersection = clipIntersection ? this.numPlanes : 0;
16011			this.numPlanes += nGlobal;
16012
16013		}
16014
16015
16016	};
16017
16018	function resetGlobalState() {
16019
16020		if ( uniform.value !== globalState ) {
16021
16022			uniform.value = globalState;
16023			uniform.needsUpdate = numGlobalPlanes > 0;
16024
16025		}
16026
16027		scope.numPlanes = numGlobalPlanes;
16028		scope.numIntersection = 0;
16029
16030	}
16031
16032	function projectPlanes( planes, camera, dstOffset, skipTransform ) {
16033
16034		var nPlanes = planes !== null ? planes.length : 0,
16035			dstArray = null;
16036
16037		if ( nPlanes !== 0 ) {
16038
16039			dstArray = uniform.value;
16040
16041			if ( skipTransform !== true || dstArray === null ) {
16042
16043				var flatSize = dstOffset + nPlanes * 4,
16044					viewMatrix = camera.matrixWorldInverse;
16045
16046				viewNormalMatrix.getNormalMatrix( viewMatrix );
16047
16048				if ( dstArray === null || dstArray.length < flatSize ) {
16049
16050					dstArray = new Float32Array( flatSize );
16051
16052				}
16053
16054				for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
16055
16056					plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
16057
16058					plane.normal.toArray( dstArray, i4 );
16059					dstArray[ i4 + 3 ] = plane.constant;
16060
16061				}
16062
16063			}
16064
16065			uniform.value = dstArray;
16066			uniform.needsUpdate = true;
16067
16068		}
16069
16070		scope.numPlanes = nPlanes;
16071		scope.numIntersection = 0;
16072
16073		return dstArray;
16074
16075	}
16076
16077}
16078
16079/**
16080 * @author mrdoob / http://mrdoob.com/
16081 */
16082
16083function WebGLExtensions( gl ) {
16084
16085	var extensions = {};
16086
16087	return {
16088
16089		get: function ( name ) {
16090
16091			if ( extensions[ name ] !== undefined ) {
16092
16093				return extensions[ name ];
16094
16095			}
16096
16097			var extension;
16098
16099			switch ( name ) {
16100
16101				case 'WEBGL_depth_texture':
16102					extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
16103					break;
16104
16105				case 'EXT_texture_filter_anisotropic':
16106					extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
16107					break;
16108
16109				case 'WEBGL_compressed_texture_s3tc':
16110					extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
16111					break;
16112
16113				case 'WEBGL_compressed_texture_pvrtc':
16114					extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
16115					break;
16116
16117				default:
16118					extension = gl.getExtension( name );
16119
16120			}
16121
16122			if ( extension === null ) {
16123
16124				console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
16125
16126			}
16127
16128			extensions[ name ] = extension;
16129
16130			return extension;
16131
16132		}
16133
16134	};
16135
16136}
16137
16138/**
16139 * @author mrdoob / http://mrdoob.com/
16140 */
16141
16142function WebGLGeometries( gl, attributes, info ) {
16143
16144	var geometries = new WeakMap();
16145	var wireframeAttributes = new WeakMap();
16146
16147	function onGeometryDispose( event ) {
16148
16149		var geometry = event.target;
16150		var buffergeometry = geometries.get( geometry );
16151
16152		if ( buffergeometry.index !== null ) {
16153
16154			attributes.remove( buffergeometry.index );
16155
16156		}
16157
16158		for ( var name in buffergeometry.attributes ) {
16159
16160			attributes.remove( buffergeometry.attributes[ name ] );
16161
16162		}
16163
16164		geometry.removeEventListener( 'dispose', onGeometryDispose );
16165
16166		geometries.delete( geometry );
16167
16168		var attribute = wireframeAttributes.get( buffergeometry );
16169
16170		if ( attribute ) {
16171
16172			attributes.remove( attribute );
16173			wireframeAttributes.delete( buffergeometry );
16174
16175		}
16176
16177		//
16178
16179		info.memory.geometries --;
16180
16181	}
16182
16183	function get( object, geometry ) {
16184
16185		var buffergeometry = geometries.get( geometry );
16186
16187		if ( buffergeometry ) return buffergeometry;
16188
16189		geometry.addEventListener( 'dispose', onGeometryDispose );
16190
16191		if ( geometry.isBufferGeometry ) {
16192
16193			buffergeometry = geometry;
16194
16195		} else if ( geometry.isGeometry ) {
16196
16197			if ( geometry._bufferGeometry === undefined ) {
16198
16199				geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
16200
16201			}
16202
16203			buffergeometry = geometry._bufferGeometry;
16204
16205		}
16206
16207		geometries.set( geometry, buffergeometry );
16208
16209		info.memory.geometries ++;
16210
16211		return buffergeometry;
16212
16213	}
16214
16215	function update( geometry ) {
16216
16217		var index = geometry.index;
16218		var geometryAttributes = geometry.attributes;
16219
16220		if ( index !== null ) {
16221
16222			attributes.update( index, 34963 );
16223
16224		}
16225
16226		for ( var name in geometryAttributes ) {
16227
16228			attributes.update( geometryAttributes[ name ], 34962 );
16229
16230		}
16231
16232		// morph targets
16233
16234		var morphAttributes = geometry.morphAttributes;
16235
16236		for ( var name in morphAttributes ) {
16237
16238			var array = morphAttributes[ name ];
16239
16240			for ( var i = 0, l = array.length; i < l; i ++ ) {
16241
16242				attributes.update( array[ i ], 34962 );
16243
16244			}
16245
16246		}
16247
16248	}
16249
16250	function updateWireframeAttribute( geometry ) {
16251
16252		var indices = [];
16253
16254		var geometryIndex = geometry.index;
16255		var geometryPosition = geometry.attributes.position;
16256		var version = 0;
16257
16258		if ( geometryIndex !== null ) {
16259
16260			var array = geometryIndex.array;
16261			version = geometryIndex.version;
16262
16263			for ( var i = 0, l = array.length; i < l; i += 3 ) {
16264
16265				var a = array[ i + 0 ];
16266				var b = array[ i + 1 ];
16267				var c = array[ i + 2 ];
16268
16269				indices.push( a, b, b, c, c, a );
16270
16271			}
16272
16273		} else {
16274
16275			var array = geometryPosition.array;
16276			version = geometryPosition.version;
16277
16278			for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
16279
16280				var a = i + 0;
16281				var b = i + 1;
16282				var c = i + 2;
16283
16284				indices.push( a, b, b, c, c, a );
16285
16286			}
16287
16288		}
16289
16290		var attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
16291		attribute.version = version;
16292
16293		attributes.update( attribute, 34963 );
16294
16295		//
16296
16297		var previousAttribute = wireframeAttributes.get( geometry );
16298
16299		if ( previousAttribute ) attributes.remove( previousAttribute );
16300
16301		//
16302
16303		wireframeAttributes.set( geometry, attribute );
16304
16305	}
16306
16307	function getWireframeAttribute( geometry ) {
16308
16309		var currentAttribute = wireframeAttributes.get( geometry );
16310
16311		if ( currentAttribute ) {
16312
16313			var geometryIndex = geometry.index;
16314
16315			if ( geometryIndex !== null ) {
16316
16317				// if the attribute is obsolete, create a new one
16318
16319				if ( currentAttribute.version < geometryIndex.version ) {
16320
16321					updateWireframeAttribute( geometry );
16322
16323				}
16324
16325			}
16326
16327		} else {
16328
16329			updateWireframeAttribute( geometry );
16330
16331		}
16332
16333		return wireframeAttributes.get( geometry );
16334
16335	}
16336
16337	return {
16338
16339		get: get,
16340		update: update,
16341
16342		getWireframeAttribute: getWireframeAttribute
16343
16344	};
16345
16346}
16347
16348/**
16349 * @author mrdoob / http://mrdoob.com/
16350 */
16351
16352function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
16353
16354	var isWebGL2 = capabilities.isWebGL2;
16355
16356	var mode;
16357
16358	function setMode( value ) {
16359
16360		mode = value;
16361
16362	}
16363
16364	var type, bytesPerElement;
16365
16366	function setIndex( value ) {
16367
16368		type = value.type;
16369		bytesPerElement = value.bytesPerElement;
16370
16371	}
16372
16373	function render( start, count ) {
16374
16375		gl.drawElements( mode, count, type, start * bytesPerElement );
16376
16377		info.update( count, mode );
16378
16379	}
16380
16381	function renderInstances( geometry, start, count, primcount ) {
16382
16383		if ( primcount === 0 ) return;
16384
16385		var extension, methodName;
16386
16387		if ( isWebGL2 ) {
16388
16389			extension = gl;
16390			methodName = 'drawElementsInstanced';
16391
16392		} else {
16393
16394			extension = extensions.get( 'ANGLE_instanced_arrays' );
16395			methodName = 'drawElementsInstancedANGLE';
16396
16397			if ( extension === null ) {
16398
16399				console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
16400				return;
16401
16402			}
16403
16404		}
16405
16406		extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
16407
16408		info.update( count, mode, primcount );
16409
16410	}
16411
16412	//
16413
16414	this.setMode = setMode;
16415	this.setIndex = setIndex;
16416	this.render = render;
16417	this.renderInstances = renderInstances;
16418
16419}
16420
16421/**
16422 * @author Mugen87 / https://github.com/Mugen87
16423 */
16424
16425function WebGLInfo( gl ) {
16426
16427	var memory = {
16428		geometries: 0,
16429		textures: 0
16430	};
16431
16432	var render = {
16433		frame: 0,
16434		calls: 0,
16435		triangles: 0,
16436		points: 0,
16437		lines: 0
16438	};
16439
16440	function update( count, mode, instanceCount ) {
16441
16442		instanceCount = instanceCount || 1;
16443
16444		render.calls ++;
16445
16446		switch ( mode ) {
16447
16448			case 4:
16449				render.triangles += instanceCount * ( count / 3 );
16450				break;
16451
16452			case 1:
16453				render.lines += instanceCount * ( count / 2 );
16454				break;
16455
16456			case 3:
16457				render.lines += instanceCount * ( count - 1 );
16458				break;
16459
16460			case 2:
16461				render.lines += instanceCount * count;
16462				break;
16463
16464			case 0:
16465				render.points += instanceCount * count;
16466				break;
16467
16468			default:
16469				console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
16470				break;
16471
16472		}
16473
16474	}
16475
16476	function reset() {
16477
16478		render.frame ++;
16479		render.calls = 0;
16480		render.triangles = 0;
16481		render.points = 0;
16482		render.lines = 0;
16483
16484	}
16485
16486	return {
16487		memory: memory,
16488		render: render,
16489		programs: null,
16490		autoReset: true,
16491		reset: reset,
16492		update: update
16493	};
16494
16495}
16496
16497/**
16498 * @author mrdoob / http://mrdoob.com/
16499 */
16500
16501function absNumericalSort( a, b ) {
16502
16503	return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
16504
16505}
16506
16507function WebGLMorphtargets( gl ) {
16508
16509	var influencesList = {};
16510	var morphInfluences = new Float32Array( 8 );
16511
16512	function update( object, geometry, material, program ) {
16513
16514		var objectInfluences = object.morphTargetInfluences;
16515
16516		// When object doesn't have morph target influences defined, we treat it as a 0-length array
16517		// This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
16518
16519		var length = objectInfluences === undefined ? 0 : objectInfluences.length;
16520
16521		var influences = influencesList[ geometry.id ];
16522
16523		if ( influences === undefined ) {
16524
16525			// initialise list
16526
16527			influences = [];
16528
16529			for ( var i = 0; i < length; i ++ ) {
16530
16531				influences[ i ] = [ i, 0 ];
16532
16533			}
16534
16535			influencesList[ geometry.id ] = influences;
16536
16537		}
16538
16539		var morphTargets = material.morphTargets && geometry.morphAttributes.position;
16540		var morphNormals = material.morphNormals && geometry.morphAttributes.normal;
16541
16542		// Remove current morphAttributes
16543
16544		for ( var i = 0; i < length; i ++ ) {
16545
16546			var influence = influences[ i ];
16547
16548			if ( influence[ 1 ] !== 0 ) {
16549
16550				if ( morphTargets ) geometry.deleteAttribute( 'morphTarget' + i );
16551				if ( morphNormals ) geometry.deleteAttribute( 'morphNormal' + i );
16552
16553			}
16554
16555		}
16556
16557		// Collect influences
16558
16559		for ( var i = 0; i < length; i ++ ) {
16560
16561			var influence = influences[ i ];
16562
16563			influence[ 0 ] = i;
16564			influence[ 1 ] = objectInfluences[ i ];
16565
16566		}
16567
16568		influences.sort( absNumericalSort );
16569
16570		// Add morphAttributes
16571
16572		var morphInfluencesSum = 0;
16573
16574		for ( var i = 0; i < 8; i ++ ) {
16575
16576			var influence = influences[ i ];
16577
16578			if ( influence ) {
16579
16580				var index = influence[ 0 ];
16581				var value = influence[ 1 ];
16582
16583				if ( value ) {
16584
16585					if ( morphTargets ) geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
16586					if ( morphNormals ) geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
16587
16588					morphInfluences[ i ] = value;
16589					morphInfluencesSum += value;
16590					continue;
16591
16592				}
16593
16594			}
16595
16596			morphInfluences[ i ] = 0;
16597
16598		}
16599
16600		// GLSL shader uses formula baseinfluence * base + sum(target * influence)
16601		// This allows us to switch between absolute morphs and relative morphs without changing shader code
16602		// When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
16603		var morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
16604
16605		program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
16606		program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
16607
16608	}
16609
16610	return {
16611
16612		update: update
16613
16614	};
16615
16616}
16617
16618/**
16619 * @author mrdoob / http://mrdoob.com/
16620 */
16621
16622function WebGLObjects( gl, geometries, attributes, info ) {
16623
16624	var updateMap = new WeakMap();
16625
16626	function update( object ) {
16627
16628		var frame = info.render.frame;
16629
16630		var geometry = object.geometry;
16631		var buffergeometry = geometries.get( object, geometry );
16632
16633		// Update once per frame
16634
16635		if ( updateMap.get( buffergeometry ) !== frame ) {
16636
16637			if ( geometry.isGeometry ) {
16638
16639				buffergeometry.updateFromObject( object );
16640
16641			}
16642
16643			geometries.update( buffergeometry );
16644
16645			updateMap.set( buffergeometry, frame );
16646
16647		}
16648
16649		if ( object.isInstancedMesh ) {
16650
16651			attributes.update( object.instanceMatrix, 34962 );
16652
16653		}
16654
16655		return buffergeometry;
16656
16657	}
16658
16659	function dispose() {
16660
16661		updateMap = new WeakMap();
16662
16663	}
16664
16665	return {
16666
16667		update: update,
vendor: 33,199 bytes, lines 16668-18252
16668		dispose: dispose
16669
16670	};
16671
16672}
16673
16674/**
16675 * @author mrdoob / http://mrdoob.com/
16676 */
16677
16678function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
16679
16680	images = images !== undefined ? images : [];
16681	mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
16682	format = format !== undefined ? format : RGBFormat;
16683
16684	Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
16685
16686	this.flipY = false;
16687
16688}
16689
16690CubeTexture.prototype = Object.create( Texture.prototype );
16691CubeTexture.prototype.constructor = CubeTexture;
16692
16693CubeTexture.prototype.isCubeTexture = true;
16694
16695Object.defineProperty( CubeTexture.prototype, 'images', {
16696
16697	get: function () {
16698
16699		return this.image;
16700
16701	},
16702
16703	set: function ( value ) {
16704
16705		this.image = value;
16706
16707	}
16708
16709} );
16710
16711/**
16712 * @author Takahiro https://github.com/takahirox
16713 */
16714
16715function DataTexture2DArray( data, width, height, depth ) {
16716
16717	Texture.call( this, null );
16718
16719	this.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };
16720
16721	this.magFilter = NearestFilter;
16722	this.minFilter = NearestFilter;
16723
16724	this.wrapR = ClampToEdgeWrapping;
16725
16726	this.generateMipmaps = false;
16727	this.flipY = false;
16728
16729	this.needsUpdate = true;
16730
16731}
16732
16733DataTexture2DArray.prototype = Object.create( Texture.prototype );
16734DataTexture2DArray.prototype.constructor = DataTexture2DArray;
16735DataTexture2DArray.prototype.isDataTexture2DArray = true;
16736
16737/**
16738 * @author Artur Trzesiok
16739 */
16740
16741function DataTexture3D( data, width, height, depth ) {
16742
16743	// We're going to add .setXXX() methods for setting properties later.
16744	// Users can still set in DataTexture3D directly.
16745	//
16746	//	var texture = new THREE.DataTexture3D( data, width, height, depth );
16747	// 	texture.anisotropy = 16;
16748	//
16749	// See #14839
16750
16751	Texture.call( this, null );
16752
16753	this.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };
16754
16755	this.magFilter = NearestFilter;
16756	this.minFilter = NearestFilter;
16757
16758	this.wrapR = ClampToEdgeWrapping;
16759
16760	this.generateMipmaps = false;
16761	this.flipY = false;
16762
16763	this.needsUpdate = true;
16764
16765
16766}
16767
16768DataTexture3D.prototype = Object.create( Texture.prototype );
16769DataTexture3D.prototype.constructor = DataTexture3D;
16770DataTexture3D.prototype.isDataTexture3D = true;
16771
16772/**
16773 * @author tschw
16774 * @author Mugen87 / https://github.com/Mugen87
16775 * @author mrdoob / http://mrdoob.com/
16776 *
16777 * Uniforms of a program.
16778 * Those form a tree structure with a special top-level container for the root,
16779 * which you get by calling 'new WebGLUniforms( gl, program )'.
16780 *
16781 *
16782 * Properties of inner nodes including the top-level container:
16783 *
16784 * .seq - array of nested uniforms
16785 * .map - nested uniforms by name
16786 *
16787 *
16788 * Methods of all nodes except the top-level container:
16789 *
16790 * .setValue( gl, value, [textures] )
16791 *
16792 * 		uploads a uniform value(s)
16793 *  	the 'textures' parameter is needed for sampler uniforms
16794 *
16795 *
16796 * Static methods of the top-level container (textures factorizations):
16797 *
16798 * .upload( gl, seq, values, textures )
16799 *
16800 * 		sets uniforms in 'seq' to 'values[id].value'
16801 *
16802 * .seqWithValue( seq, values ) : filteredSeq
16803 *
16804 * 		filters 'seq' entries with corresponding entry in values
16805 *
16806 *
16807 * Methods of the top-level container (textures factorizations):
16808 *
16809 * .setValue( gl, name, value, textures )
16810 *
16811 * 		sets uniform with  name 'name' to 'value'
16812 *
16813 * .setOptional( gl, obj, prop )
16814 *
16815 * 		like .set for an optional property of the object
16816 *
16817 */
16818
16819var emptyTexture = new Texture();
16820var emptyTexture2dArray = new DataTexture2DArray();
16821var emptyTexture3d = new DataTexture3D();
16822var emptyCubeTexture = new CubeTexture();
16823
16824// --- Utilities ---
16825
16826// Array Caches (provide typed arrays for temporary by size)
16827
16828var arrayCacheF32 = [];
16829var arrayCacheI32 = [];
16830
16831// Float32Array caches used for uploading Matrix uniforms
16832
16833var mat4array = new Float32Array( 16 );
16834var mat3array = new Float32Array( 9 );
16835var mat2array = new Float32Array( 4 );
16836
16837// Flattening for arrays of vectors and matrices
16838
16839function flatten( array, nBlocks, blockSize ) {
16840
16841	var firstElem = array[ 0 ];
16842
16843	if ( firstElem <= 0 || firstElem > 0 ) return array;
16844	// unoptimized: ! isNaN( firstElem )
16845	// see http://jacksondunstan.com/articles/983
16846
16847	var n = nBlocks * blockSize,
16848		r = arrayCacheF32[ n ];
16849
16850	if ( r === undefined ) {
16851
16852		r = new Float32Array( n );
16853		arrayCacheF32[ n ] = r;
16854
16855	}
16856
16857	if ( nBlocks !== 0 ) {
16858
16859		firstElem.toArray( r, 0 );
16860
16861		for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {
16862
16863			offset += blockSize;
16864			array[ i ].toArray( r, offset );
16865
16866		}
16867
16868	}
16869
16870	return r;
16871
16872}
16873
16874function arraysEqual( a, b ) {
16875
16876	if ( a.length !== b.length ) return false;
16877
16878	for ( var i = 0, l = a.length; i < l; i ++ ) {
16879
16880		if ( a[ i ] !== b[ i ] ) return false;
16881
16882	}
16883
16884	return true;
16885
16886}
16887
16888function copyArray( a, b ) {
16889
16890	for ( var i = 0, l = b.length; i < l; i ++ ) {
16891
16892		a[ i ] = b[ i ];
16893
16894	}
16895
16896}
16897
16898// Texture unit allocation
16899
16900function allocTexUnits( textures, n ) {
16901
16902	var r = arrayCacheI32[ n ];
16903
16904	if ( r === undefined ) {
16905
16906		r = new Int32Array( n );
16907		arrayCacheI32[ n ] = r;
16908
16909	}
16910
16911	for ( var i = 0; i !== n; ++ i )
16912		r[ i ] = textures.allocateTextureUnit();
16913
16914	return r;
16915
16916}
16917
16918// --- Setters ---
16919
16920// Note: Defining these methods externally, because they come in a bunch
16921// and this way their names minify.
16922
16923// Single scalar
16924
16925function setValueV1f( gl, v ) {
16926
16927	var cache = this.cache;
16928
16929	if ( cache[ 0 ] === v ) return;
16930
16931	gl.uniform1f( this.addr, v );
16932
16933	cache[ 0 ] = v;
16934
16935}
16936
16937// Single float vector (from flat array or THREE.VectorN)
16938
16939function setValueV2f( gl, v ) {
16940
16941	var cache = this.cache;
16942
16943	if ( v.x !== undefined ) {
16944
16945		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
16946
16947			gl.uniform2f( this.addr, v.x, v.y );
16948
16949			cache[ 0 ] = v.x;
16950			cache[ 1 ] = v.y;
16951
16952		}
16953
16954	} else {
16955
16956		if ( arraysEqual( cache, v ) ) return;
16957
16958		gl.uniform2fv( this.addr, v );
16959
16960		copyArray( cache, v );
16961
16962	}
16963
16964}
16965
16966function setValueV3f( gl, v ) {
16967
16968	var cache = this.cache;
16969
16970	if ( v.x !== undefined ) {
16971
16972		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
16973
16974			gl.uniform3f( this.addr, v.x, v.y, v.z );
16975
16976			cache[ 0 ] = v.x;
16977			cache[ 1 ] = v.y;
16978			cache[ 2 ] = v.z;
16979
16980		}
16981
16982	} else if ( v.r !== undefined ) {
16983
16984		if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
16985
16986			gl.uniform3f( this.addr, v.r, v.g, v.b );
16987
16988			cache[ 0 ] = v.r;
16989			cache[ 1 ] = v.g;
16990			cache[ 2 ] = v.b;
16991
16992		}
16993
16994	} else {
16995
16996		if ( arraysEqual( cache, v ) ) return;
16997
16998		gl.uniform3fv( this.addr, v );
16999
17000		copyArray( cache, v );
17001
17002	}
17003
17004}
17005
17006function setValueV4f( gl, v ) {
17007
17008	var cache = this.cache;
17009
17010	if ( v.x !== undefined ) {
17011
17012		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
17013
17014			gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
17015
17016			cache[ 0 ] = v.x;
17017			cache[ 1 ] = v.y;
17018			cache[ 2 ] = v.z;
17019			cache[ 3 ] = v.w;
17020
17021		}
17022
17023	} else {
17024
17025		if ( arraysEqual( cache, v ) ) return;
17026
17027		gl.uniform4fv( this.addr, v );
17028
17029		copyArray( cache, v );
17030
17031	}
17032
17033}
17034
17035// Single matrix (from flat array or MatrixN)
17036
17037function setValueM2( gl, v ) {
17038
17039	var cache = this.cache;
17040	var elements = v.elements;
17041
17042	if ( elements === undefined ) {
17043
17044		if ( arraysEqual( cache, v ) ) return;
17045
17046		gl.uniformMatrix2fv( this.addr, false, v );
17047
17048		copyArray( cache, v );
17049
17050	} else {
17051
17052		if ( arraysEqual( cache, elements ) ) return;
17053
17054		mat2array.set( elements );
17055
17056		gl.uniformMatrix2fv( this.addr, false, mat2array );
17057
17058		copyArray( cache, elements );
17059
17060	}
17061
17062}
17063
17064function setValueM3( gl, v ) {
17065
17066	var cache = this.cache;
17067	var elements = v.elements;
17068
17069	if ( elements === undefined ) {
17070
17071		if ( arraysEqual( cache, v ) ) return;
17072
17073		gl.uniformMatrix3fv( this.addr, false, v );
17074
17075		copyArray( cache, v );
17076
17077	} else {
17078
17079		if ( arraysEqual( cache, elements ) ) return;
17080
17081		mat3array.set( elements );
17082
17083		gl.uniformMatrix3fv( this.addr, false, mat3array );
17084
17085		copyArray( cache, elements );
17086
17087	}
17088
17089}
17090
17091function setValueM4( gl, v ) {
17092
17093	var cache = this.cache;
17094	var elements = v.elements;
17095
17096	if ( elements === undefined ) {
17097
17098		if ( arraysEqual( cache, v ) ) return;
17099
17100		gl.uniformMatrix4fv( this.addr, false, v );
17101
17102		copyArray( cache, v );
17103
17104	} else {
17105
17106		if ( arraysEqual( cache, elements ) ) return;
17107
17108		mat4array.set( elements );
17109
17110		gl.uniformMatrix4fv( this.addr, false, mat4array );
17111
17112		copyArray( cache, elements );
17113
17114	}
17115
17116}
17117
17118// Single texture (2D / Cube)
17119
17120function setValueT1( gl, v, textures ) {
17121
17122	var cache = this.cache;
17123	var unit = textures.allocateTextureUnit();
17124
17125	if ( cache[ 0 ] !== unit ) {
17126
17127		gl.uniform1i( this.addr, unit );
17128		cache[ 0 ] = unit;
17129
17130	}
17131
17132	textures.safeSetTexture2D( v || emptyTexture, unit );
17133
17134}
17135
17136function setValueT2DArray1( gl, v, textures ) {
17137
17138	var cache = this.cache;
17139	var unit = textures.allocateTextureUnit();
17140
17141	if ( cache[ 0 ] !== unit ) {
17142
17143		gl.uniform1i( this.addr, unit );
17144		cache[ 0 ] = unit;
17145
17146	}
17147
17148	textures.setTexture2DArray( v || emptyTexture2dArray, unit );
17149
17150}
17151
17152function setValueT3D1( gl, v, textures ) {
17153
17154	var cache = this.cache;
17155	var unit = textures.allocateTextureUnit();
17156
17157	if ( cache[ 0 ] !== unit ) {
17158
17159		gl.uniform1i( this.addr, unit );
17160		cache[ 0 ] = unit;
17161
17162	}
17163
17164	textures.setTexture3D( v || emptyTexture3d, unit );
17165
17166}
17167
17168function setValueT6( gl, v, textures ) {
17169
17170	var cache = this.cache;
17171	var unit = textures.allocateTextureUnit();
17172
17173	if ( cache[ 0 ] !== unit ) {
17174
17175		gl.uniform1i( this.addr, unit );
17176		cache[ 0 ] = unit;
17177
17178	}
17179
17180	textures.safeSetTextureCube( v || emptyCubeTexture, unit );
17181
17182}
17183
17184// Integer / Boolean vectors or arrays thereof (always flat arrays)
17185
17186function setValueV1i( gl, v ) {
17187
17188	var cache = this.cache;
17189
17190	if ( cache[ 0 ] === v ) return;
17191
17192	gl.uniform1i( this.addr, v );
17193
17194	cache[ 0 ] = v;
17195
17196}
17197
17198function setValueV2i( gl, v ) {
17199
17200	var cache = this.cache;
17201
17202	if ( arraysEqual( cache, v ) ) return;
17203
17204	gl.uniform2iv( this.addr, v );
17205
17206	copyArray( cache, v );
17207
17208}
17209
17210function setValueV3i( gl, v ) {
17211
17212	var cache = this.cache;
17213
17214	if ( arraysEqual( cache, v ) ) return;
17215
17216	gl.uniform3iv( this.addr, v );
17217
17218	copyArray( cache, v );
17219
17220}
17221
17222function setValueV4i( gl, v ) {
17223
17224	var cache = this.cache;
17225
17226	if ( arraysEqual( cache, v ) ) return;
17227
17228	gl.uniform4iv( this.addr, v );
17229
17230	copyArray( cache, v );
17231
17232}
17233
17234// uint
17235
17236function setValueV1ui( gl, v ) {
17237
17238	var cache = this.cache;
17239
17240	if ( cache[ 0 ] === v ) return;
17241
17242	gl.uniform1ui( this.addr, v );
17243
17244	cache[ 0 ] = v;
17245
17246}
17247
17248// Helper to pick the right setter for the singular case
17249
17250function getSingularSetter( type ) {
17251
17252	switch ( type ) {
17253
17254		case 0x1406: return setValueV1f; // FLOAT
17255		case 0x8b50: return setValueV2f; // _VEC2
17256		case 0x8b51: return setValueV3f; // _VEC3
17257		case 0x8b52: return setValueV4f; // _VEC4
17258
17259		case 0x8b5a: return setValueM2; // _MAT2
17260		case 0x8b5b: return setValueM3; // _MAT3
17261		case 0x8b5c: return setValueM4; // _MAT4
17262
17263		case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
17264		case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
17265		case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
17266		case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
17267
17268		case 0x1405: return setValueV1ui; // UINT
17269
17270		case 0x8b5e: // SAMPLER_2D
17271		case 0x8d66: // SAMPLER_EXTERNAL_OES
17272		case 0x8dca: // INT_SAMPLER_2D
17273		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
17274		case 0x8b62: // SAMPLER_2D_SHADOW
17275			return setValueT1;
17276
17277		case 0x8b5f: // SAMPLER_3D
17278		case 0x8dcb: // INT_SAMPLER_3D
17279		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
17280			return setValueT3D1;
17281
17282		case 0x8b60: // SAMPLER_CUBE
17283		case 0x8dcc: // INT_SAMPLER_CUBE
17284		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
17285		case 0x8dc5: // SAMPLER_CUBE_SHADOW
17286			return setValueT6;
17287
17288		case 0x8dc1: // SAMPLER_2D_ARRAY
17289		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
17290		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
17291		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
17292			return setValueT2DArray1;
17293
17294	}
17295
17296}
17297
17298// Array of scalars
17299function setValueV1fArray( gl, v ) {
17300
17301	gl.uniform1fv( this.addr, v );
17302
17303}
17304
17305// Integer / Boolean vectors or arrays thereof (always flat arrays)
17306function setValueV1iArray( gl, v ) {
17307
17308	gl.uniform1iv( this.addr, v );
17309
17310}
17311
17312function setValueV2iArray( gl, v ) {
17313
17314	gl.uniform2iv( this.addr, v );
17315
17316}
17317
17318function setValueV3iArray( gl, v ) {
17319
17320	gl.uniform3iv( this.addr, v );
17321
17322}
17323
17324function setValueV4iArray( gl, v ) {
17325
17326	gl.uniform4iv( this.addr, v );
17327
17328}
17329
17330
17331// Array of vectors (flat or from THREE classes)
17332
17333function setValueV2fArray( gl, v ) {
17334
17335	var data = flatten( v, this.size, 2 );
17336
17337	gl.uniform2fv( this.addr, data );
17338
17339}
17340
17341function setValueV3fArray( gl, v ) {
17342
17343	var data = flatten( v, this.size, 3 );
17344
17345	gl.uniform3fv( this.addr, data );
17346
17347}
17348
17349function setValueV4fArray( gl, v ) {
17350
17351	var data = flatten( v, this.size, 4 );
17352
17353	gl.uniform4fv( this.addr, data );
17354
17355}
17356
17357// Array of matrices (flat or from THREE clases)
17358
17359function setValueM2Array( gl, v ) {
17360
17361	var data = flatten( v, this.size, 4 );
17362
17363	gl.uniformMatrix2fv( this.addr, false, data );
17364
17365}
17366
17367function setValueM3Array( gl, v ) {
17368
17369	var data = flatten( v, this.size, 9 );
17370
17371	gl.uniformMatrix3fv( this.addr, false, data );
17372
17373}
17374
17375function setValueM4Array( gl, v ) {
17376
17377	var data = flatten( v, this.size, 16 );
17378
17379	gl.uniformMatrix4fv( this.addr, false, data );
17380
17381}
17382
17383// Array of textures (2D / Cube)
17384
17385function setValueT1Array( gl, v, textures ) {
17386
17387	var n = v.length;
17388
17389	var units = allocTexUnits( textures, n );
17390
17391	gl.uniform1iv( this.addr, units );
17392
17393	for ( var i = 0; i !== n; ++ i ) {
17394
17395		textures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );
17396
17397	}
17398
17399}
17400
17401function setValueT6Array( gl, v, textures ) {
17402
17403	var n = v.length;
17404
17405	var units = allocTexUnits( textures, n );
17406
17407	gl.uniform1iv( this.addr, units );
17408
17409	for ( var i = 0; i !== n; ++ i ) {
17410
17411		textures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
17412
17413	}
17414
17415}
17416
17417// Helper to pick the right setter for a pure (bottom-level) array
17418
17419function getPureArraySetter( type ) {
17420
17421	switch ( type ) {
17422
17423		case 0x1406: return setValueV1fArray; // FLOAT
17424		case 0x8b50: return setValueV2fArray; // _VEC2
17425		case 0x8b51: return setValueV3fArray; // _VEC3
17426		case 0x8b52: return setValueV4fArray; // _VEC4
17427
17428		case 0x8b5a: return setValueM2Array; // _MAT2
17429		case 0x8b5b: return setValueM3Array; // _MAT3
17430		case 0x8b5c: return setValueM4Array; // _MAT4
17431
17432		case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
17433		case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
17434		case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
17435		case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
17436
17437		case 0x8b5e: // SAMPLER_2D
17438		case 0x8d66: // SAMPLER_EXTERNAL_OES
17439		case 0x8dca: // INT_SAMPLER_2D
17440		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
17441		case 0x8b62: // SAMPLER_2D_SHADOW
17442			return setValueT1Array;
17443
17444		case 0x8b60: // SAMPLER_CUBE
17445		case 0x8dcc: // INT_SAMPLER_CUBE
17446		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
17447		case 0x8dc5: // SAMPLER_CUBE_SHADOW
17448			return setValueT6Array;
17449
17450	}
17451
17452}
17453
17454// --- Uniform Classes ---
17455
17456function SingleUniform( id, activeInfo, addr ) {
17457
17458	this.id = id;
17459	this.addr = addr;
17460	this.cache = [];
17461	this.setValue = getSingularSetter( activeInfo.type );
17462
17463	// this.path = activeInfo.name; // DEBUG
17464
17465}
17466
17467function PureArrayUniform( id, activeInfo, addr ) {
17468
17469	this.id = id;
17470	this.addr = addr;
17471	this.cache = [];
17472	this.size = activeInfo.size;
17473	this.setValue = getPureArraySetter( activeInfo.type );
17474
17475	// this.path = activeInfo.name; // DEBUG
17476
17477}
17478
17479PureArrayUniform.prototype.updateCache = function ( data ) {
17480
17481	var cache = this.cache;
17482
17483	if ( data instanceof Float32Array && cache.length !== data.length ) {
17484
17485		this.cache = new Float32Array( data.length );
17486
17487	}
17488
17489	copyArray( cache, data );
17490
17491};
17492
17493function StructuredUniform( id ) {
17494
17495	this.id = id;
17496
17497	this.seq = [];
17498	this.map = {};
17499
17500}
17501
17502StructuredUniform.prototype.setValue = function ( gl, value, textures ) {
17503
17504	var seq = this.seq;
17505
17506	for ( var i = 0, n = seq.length; i !== n; ++ i ) {
17507
17508		var u = seq[ i ];
17509		u.setValue( gl, value[ u.id ], textures );
17510
17511	}
17512
17513};
17514
17515// --- Top-level ---
17516
17517// Parser - builds up the property tree from the path strings
17518
17519var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g;
17520
17521// extracts
17522// 	- the identifier (member name or array index)
17523//  - followed by an optional right bracket (found when array index)
17524//  - followed by an optional left bracket or dot (type of subscript)
17525//
17526// Note: These portions can be read in a non-overlapping fashion and
17527// allow straightforward parsing of the hierarchy that WebGL encodes
17528// in the uniform names.
17529
17530function addUniform( container, uniformObject ) {
17531
17532	container.seq.push( uniformObject );
17533	container.map[ uniformObject.id ] = uniformObject;
17534
17535}
17536
17537function parseUniform( activeInfo, addr, container ) {
17538
17539	var path = activeInfo.name,
17540		pathLength = path.length;
17541
17542	// reset RegExp object, because of the early exit of a previous run
17543	RePathPart.lastIndex = 0;
17544
17545	while ( true ) {
17546
17547		var match = RePathPart.exec( path ),
17548			matchEnd = RePathPart.lastIndex,
17549
17550			id = match[ 1 ],
17551			idIsIndex = match[ 2 ] === ']',
17552			subscript = match[ 3 ];
17553
17554		if ( idIsIndex ) id = id | 0; // convert to integer
17555
17556		if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
17557
17558			// bare name or "pure" bottom-level array "[0]" suffix
17559
17560			addUniform( container, subscript === undefined ?
17561				new SingleUniform( id, activeInfo, addr ) :
17562				new PureArrayUniform( id, activeInfo, addr ) );
17563
17564			break;
17565
17566		} else {
17567
17568			// step into inner node / create it in case it doesn't exist
17569
17570			var map = container.map, next = map[ id ];
17571
17572			if ( next === undefined ) {
17573
17574				next = new StructuredUniform( id );
17575				addUniform( container, next );
17576
17577			}
17578
17579			container = next;
17580
17581		}
17582
17583	}
17584
17585}
17586
17587// Root Container
17588
17589function WebGLUniforms( gl, program ) {
17590
17591	this.seq = [];
17592	this.map = {};
17593
17594	var n = gl.getProgramParameter( program, 35718 );
17595
17596	for ( var i = 0; i < n; ++ i ) {
17597
17598		var info = gl.getActiveUniform( program, i ),
17599			addr = gl.getUniformLocation( program, info.name );
17600
17601		parseUniform( info, addr, this );
17602
17603	}
17604
17605}
17606
17607WebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {
17608
17609	var u = this.map[ name ];
17610
17611	if ( u !== undefined ) u.setValue( gl, value, textures );
17612
17613};
17614
17615WebGLUniforms.prototype.setOptional = function ( gl, object, name ) {
17616
17617	var v = object[ name ];
17618
17619	if ( v !== undefined ) this.setValue( gl, name, v );
17620
17621};
17622
17623
17624// Static interface
17625
17626WebGLUniforms.upload = function ( gl, seq, values, textures ) {
17627
17628	for ( var i = 0, n = seq.length; i !== n; ++ i ) {
17629
17630		var u = seq[ i ],
17631			v = values[ u.id ];
17632
17633		if ( v.needsUpdate !== false ) {
17634
17635			// note: always updating when .needsUpdate is undefined
17636			u.setValue( gl, v.value, textures );
17637
17638		}
17639
17640	}
17641
17642};
17643
17644WebGLUniforms.seqWithValue = function ( seq, values ) {
17645
17646	var r = [];
17647
17648	for ( var i = 0, n = seq.length; i !== n; ++ i ) {
17649
17650		var u = seq[ i ];
17651		if ( u.id in values ) r.push( u );
17652
17653	}
17654
17655	return r;
17656
17657};
17658
17659/**
17660 * @author mrdoob / http://mrdoob.com/
17661 */
17662
17663function WebGLShader( gl, type, string ) {
17664
17665	var shader = gl.createShader( type );
17666
17667	gl.shaderSource( shader, string );
17668	gl.compileShader( shader );
17669
17670	return shader;
17671
17672}
17673
17674/**
17675 * @author mrdoob / http://mrdoob.com/
17676 */
17677
17678var programIdCount = 0;
17679
17680function addLineNumbers( string ) {
17681
17682	var lines = string.split( '\n' );
17683
17684	for ( var i = 0; i < lines.length; i ++ ) {
17685
17686		lines[ i ] = ( i + 1 ) + ': ' + lines[ i ];
17687
17688	}
17689
17690	return lines.join( '\n' );
17691
17692}
17693
17694function getEncodingComponents( encoding ) {
17695
17696	switch ( encoding ) {
17697
17698		case LinearEncoding:
17699			return [ 'Linear', '( value )' ];
17700		case sRGBEncoding:
17701			return [ 'sRGB', '( value )' ];
17702		case RGBEEncoding:
17703			return [ 'RGBE', '( value )' ];
17704		case RGBM7Encoding:
17705			return [ 'RGBM', '( value, 7.0 )' ];
17706		case RGBM16Encoding:
17707			return [ 'RGBM', '( value, 16.0 )' ];
17708		case RGBDEncoding:
17709			return [ 'RGBD', '( value, 256.0 )' ];
17710		case GammaEncoding:
17711			return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
17712		case LogLuvEncoding:
17713			return [ 'LogLuv', '( value )' ];
17714		default:
17715			throw new Error( 'unsupported encoding: ' + encoding );
17716
17717	}
17718
17719}
17720
17721function getShaderErrors( gl, shader, type ) {
17722
17723	var status = gl.getShaderParameter( shader, 35713 );
17724	var log = gl.getShaderInfoLog( shader ).trim();
17725
17726	if ( status && log === '' ) return '';
17727
17728	// --enable-privileged-webgl-extension
17729	// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
17730
17731	var source = gl.getShaderSource( shader );
17732
17733	return 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\n' + log + addLineNumbers( source );
17734
17735}
17736
17737function getTexelDecodingFunction( functionName, encoding ) {
17738
17739	var components = getEncodingComponents( encoding );
17740	return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';
17741
17742}
17743
17744function getTexelEncodingFunction( functionName, encoding ) {
17745
17746	var components = getEncodingComponents( encoding );
17747	return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
17748
17749}
17750
17751function getToneMappingFunction( functionName, toneMapping ) {
17752
17753	var toneMappingName;
17754
17755	switch ( toneMapping ) {
17756
17757		case LinearToneMapping:
17758			toneMappingName = 'Linear';
17759			break;
17760
17761		case ReinhardToneMapping:
17762			toneMappingName = 'Reinhard';
17763			break;
17764
17765		case Uncharted2ToneMapping:
17766			toneMappingName = 'Uncharted2';
17767			break;
17768
17769		case CineonToneMapping:
17770			toneMappingName = 'OptimizedCineon';
17771			break;
17772
17773		case ACESFilmicToneMapping:
17774			toneMappingName = 'ACESFilmic';
17775			break;
17776
17777		default:
17778			throw new Error( 'unsupported toneMapping: ' + toneMapping );
17779
17780	}
17781
17782	return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
17783
17784}
17785
17786function generateExtensions( parameters ) {
17787
17788	var chunks = [
17789		( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',
17790		( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
17791		( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',
17792		( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
17793	];
17794
17795	return chunks.filter( filterEmptyLine ).join( '\n' );
17796
17797}
17798
17799function generateDefines( defines ) {
17800
17801	var chunks = [];
17802
17803	for ( var name in defines ) {
17804
17805		var value = defines[ name ];
17806
17807		if ( value === false ) continue;
17808
17809		chunks.push( '#define ' + name + ' ' + value );
17810
17811	}
17812
17813	return chunks.join( '\n' );
17814
17815}
17816
17817function fetchAttributeLocations( gl, program ) {
17818
17819	var attributes = {};
17820
17821	var n = gl.getProgramParameter( program, 35721 );
17822
17823	for ( var i = 0; i < n; i ++ ) {
17824
17825		var info = gl.getActiveAttrib( program, i );
17826		var name = info.name;
17827
17828		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
17829
17830		attributes[ name ] = gl.getAttribLocation( program, name );
17831
17832	}
17833
17834	return attributes;
17835
17836}
17837
17838function filterEmptyLine( string ) {
17839
17840	return string !== '';
17841
17842}
17843
17844function replaceLightNums( string, parameters ) {
17845
17846	return string
17847		.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
17848		.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
17849		.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
17850		.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
17851		.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
17852		.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
17853		.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
17854		.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
17855
17856}
17857
17858function replaceClippingPlaneNums( string, parameters ) {
17859
17860	return string
17861		.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
17862		.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
17863
17864}
17865
17866// Resolve Includes
17867
17868var includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
17869
17870function resolveIncludes( string ) {
17871
17872	return string.replace( includePattern, includeReplacer );
17873
17874}
17875
17876function includeReplacer( match, include ) {
17877
17878	var string = ShaderChunk[ include ];
17879
17880	if ( string === undefined ) {
17881
17882		throw new Error( 'Can not resolve #include <' + include + '>' );
17883
17884	}
17885
17886	return resolveIncludes( string );
17887
17888}
17889
17890// Unroll Loops
17891
17892var deprecatedUnrollLoopPattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
17893var unrollLoopPattern = /#pragma unroll_loop_start[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}[\s]+?#pragma unroll_loop_end/g;
17894
17895function unrollLoops( string ) {
17896
17897	return string
17898		.replace( unrollLoopPattern, loopReplacer )
17899		.replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );
17900
17901}
17902
17903function deprecatedLoopReplacer( match, start, end, snippet ) {
17904
17905	console.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );
17906	return loopReplacer( match, start, end, snippet );
17907
17908}
17909
17910function loopReplacer( match, start, end, snippet ) {
17911
17912	var string = '';
17913
17914	for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {
17915
17916		string += snippet
17917			.replace( /\[ i \]/g, '[ ' + i + ' ]' )
17918			.replace( /UNROLLED_LOOP_INDEX/g, i );
17919
17920	}
17921
17922	return string;
17923
17924}
17925
17926//
17927
17928function generatePrecision( parameters ) {
17929
17930	var precisionstring = "precision " + parameters.precision + " float;\nprecision " + parameters.precision + " int;";
17931
17932	if ( parameters.precision === "highp" ) {
17933
17934		precisionstring += "\n#define HIGH_PRECISION";
17935
17936	} else if ( parameters.precision === "mediump" ) {
17937
17938		precisionstring += "\n#define MEDIUM_PRECISION";
17939
17940	} else if ( parameters.precision === "lowp" ) {
17941
17942		precisionstring += "\n#define LOW_PRECISION";
17943
17944	}
17945
17946	return precisionstring;
17947
17948}
17949
17950function generateShadowMapTypeDefine( parameters ) {
17951
17952	var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
17953
17954	if ( parameters.shadowMapType === PCFShadowMap ) {
17955
17956		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
17957
17958	} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
17959
17960		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
17961
17962	} else if ( parameters.shadowMapType === VSMShadowMap ) {
17963
17964		shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
17965
17966	}
17967
17968	return shadowMapTypeDefine;
17969
17970}
17971
17972function generateEnvMapTypeDefine( parameters ) {
17973
17974	var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
17975
17976	if ( parameters.envMap ) {
17977
17978		switch ( parameters.envMapMode ) {
17979
17980			case CubeReflectionMapping:
17981			case CubeRefractionMapping:
17982				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
17983				break;
17984
17985			case CubeUVReflectionMapping:
17986			case CubeUVRefractionMapping:
17987				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
17988				break;
17989
17990			case EquirectangularReflectionMapping:
17991			case EquirectangularRefractionMapping:
17992				envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
17993				break;
17994
17995			case SphericalReflectionMapping:
17996				envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
17997				break;
17998
17999		}
18000
18001	}
18002
18003	return envMapTypeDefine;
18004
18005}
18006
18007function generateEnvMapModeDefine( parameters ) {
18008
18009	var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
18010
18011	if ( parameters.envMap ) {
18012
18013		switch ( parameters.envMapMode ) {
18014
18015			case CubeRefractionMapping:
18016			case EquirectangularRefractionMapping:
18017				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
18018				break;
18019
18020		}
18021
18022	}
18023
18024	return envMapModeDefine;
18025
18026}
18027
18028function generateEnvMapBlendingDefine( parameters ) {
18029
18030	var envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
18031
18032	if ( parameters.envMap ) {
18033
18034		switch ( parameters.combine ) {
18035
18036			case MultiplyOperation:
18037				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
18038				break;
18039
18040			case MixOperation:
18041				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
18042				break;
18043
18044			case AddOperation:
18045				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
18046				break;
18047
18048		}
18049
18050	}
18051
18052	return envMapBlendingDefine;
18053
18054}
18055
18056function WebGLProgram( renderer, cacheKey, parameters ) {
18057
18058	var gl = renderer.getContext();
18059
18060	var defines = parameters.defines;
18061
18062	var vertexShader = parameters.vertexShader;
18063	var fragmentShader = parameters.fragmentShader;
18064	var shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
18065	var envMapTypeDefine = generateEnvMapTypeDefine( parameters );
18066	var envMapModeDefine = generateEnvMapModeDefine( parameters );
18067	var envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
18068
18069
18070	var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
18071
18072	var customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
18073
18074	var customDefines = generateDefines( defines );
18075
18076	var program = gl.createProgram();
18077
18078	var prefixVertex, prefixFragment;
18079
18080	if ( parameters.isRawShaderMaterial ) {
18081
18082		prefixVertex = [
18083
18084			customDefines
18085
18086		].filter( filterEmptyLine ).join( '\n' );
18087
18088		if ( prefixVertex.length > 0 ) {
18089
18090			prefixVertex += '\n';
18091
18092		}
18093
18094		prefixFragment = [
18095
18096			customExtensions,
18097			customDefines
18098
18099		].filter( filterEmptyLine ).join( '\n' );
18100
18101		if ( prefixFragment.length > 0 ) {
18102
18103			prefixFragment += '\n';
18104
18105		}
18106
18107	} else {
18108
18109		prefixVertex = [
18110
18111			generatePrecision( parameters ),
18112
18113			'#define SHADER_NAME ' + parameters.shaderName,
18114
18115			customDefines,
18116
18117			parameters.instancing ? '#define USE_INSTANCING' : '',
18118			parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
18119
18120			'#define GAMMA_FACTOR ' + gammaFactorDefine,
18121
18122			'#define MAX_BONES ' + parameters.maxBones,
18123			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
18124			( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
18125
18126			parameters.map ? '#define USE_MAP' : '',
18127			parameters.envMap ? '#define USE_ENVMAP' : '',
18128			parameters.envMap ? '#define ' + envMapModeDefine : '',
18129			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
18130			parameters.aoMap ? '#define USE_AOMAP' : '',
18131			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
18132			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
18133			parameters.normalMap ? '#define USE_NORMALMAP' : '',
18134			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
18135			( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
18136
18137			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
18138			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
18139			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
18140			parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
18141			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
18142			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
18143			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
18144			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
18145
18146			parameters.vertexTangents ? '#define USE_TANGENT' : '',
18147			parameters.vertexColors ? '#define USE_COLOR' : '',
18148			parameters.vertexUvs ? '#define USE_UV' : '',
18149			parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
18150
18151			parameters.flatShading ? '#define FLAT_SHADED' : '',
18152
18153			parameters.skinning ? '#define USE_SKINNING' : '',
18154			parameters.useVertexTexture ? '#define BONE_TEXTURE' : '',
18155
18156			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
18157			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
18158			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
18159			parameters.flipSided ? '#define FLIP_SIDED' : '',
18160
18161			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
18162			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
18163
18164			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
18165
18166			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
18167			( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
18168
18169			'uniform mat4 modelMatrix;',
18170			'uniform mat4 modelViewMatrix;',
18171			'uniform mat4 projectionMatrix;',
18172			'uniform mat4 viewMatrix;',
18173			'uniform mat3 normalMatrix;',
18174			'uniform vec3 cameraPosition;',
18175			'uniform bool isOrthographic;',
18176
18177			'#ifdef USE_INSTANCING',
18178
18179			' attribute mat4 instanceMatrix;',
18180
18181			'#endif',
18182
18183			'attribute vec3 position;',
18184			'attribute vec3 normal;',
18185			'attribute vec2 uv;',
18186
18187			'#ifdef USE_TANGENT',
18188
18189			'	attribute vec4 tangent;',
18190
18191			'#endif',
18192
18193			'#ifdef USE_COLOR',
18194
18195			'	attribute vec3 color;',
18196
18197			'#endif',
18198
18199			'#ifdef USE_MORPHTARGETS',
18200
18201			'	attribute vec3 morphTarget0;',
18202			'	attribute vec3 morphTarget1;',
18203			'	attribute vec3 morphTarget2;',
18204			'	attribute vec3 morphTarget3;',
18205
18206			'	#ifdef USE_MORPHNORMALS',
18207
18208			'		attribute vec3 morphNormal0;',
18209			'		attribute vec3 morphNormal1;',
18210			'		attribute vec3 morphNormal2;',
18211			'		attribute vec3 morphNormal3;',
18212
18213			'	#else',
18214
18215			'		attribute vec3 morphTarget4;',
18216			'		attribute vec3 morphTarget5;',
18217			'		attribute vec3 morphTarget6;',
18218			'		attribute vec3 morphTarget7;',
18219
18220			'	#endif',
18221
18222			'#endif',
18223
18224			'#ifdef USE_SKINNING',
18225
18226			'	attribute vec4 skinIndex;',
18227			'	attribute vec4 skinWeight;',
18228
18229			'#endif',
18230
18231			'\n'
18232
18233		].filter( filterEmptyLine ).join( '\n' );
18234
18235		prefixFragment = [
18236
18237			customExtensions,
18238
18239			generatePrecision( parameters ),
18240
18241			'#define SHADER_NAME ' + parameters.shaderName,
18242
18243			customDefines,
18244
18245			parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer
18246
18247			'#define GAMMA_FACTOR ' + gammaFactorDefine,
18248
18249			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
18250			( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
18251
18252			parameters.map ? '#define USE_MAP' : '',
18253			parameters.matcap ? '#define USE_MATCAP' : '',
18254			parameters.envMap ? '#define USE_ENVMAP' : '',
18255			parameters.envMap ? '#define ' + envMapTypeDefine : '',
18256			parameters.envMap ? '#define ' + envMapModeDefine : '',
18257			parameters.envMap ? '#define ' + envMapBlendingDefine : '',
18258			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
18259			parameters.aoMap ? '#define USE_AOMAP' : '',
18260			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
18261			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
18262			parameters.normalMap ? '#define USE_NORMALMAP' : '',
18263			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
18264			( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
18265			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
18266			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
18267			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
18268			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
18269			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
18270			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
18271			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
18272
18273			parameters.sheen ? '#define USE_SHEEN' : '',
18274
18275			parameters.vertexTangents ? '#define USE_TANGENT' : '',
18276			parameters.vertexColors ? '#define USE_COLOR' : '',
18277			parameters.vertexUvs ? '#define USE_UV' : '',
18278			parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
18279
18280			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
18281
18282			parameters.flatShading ? '#define FLAT_SHADED' : '',
18283
18284			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
18285			parameters.flipSided ? '#define FLIP_SIDED' : '',
18286
18287			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
18288			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
18289
18290			parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
18291
18292			parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
18293
18294			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
18295			( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
18296
18297			( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',
18298
18299			'uniform mat4 viewMatrix;',
18300			'uniform vec3 cameraPosition;',
18301			'uniform bool isOrthographic;',
18302
18303			( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
18304			( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
18305			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
18306
18307			parameters.dithering ? '#define DITHERING' : '',
18308
18309			( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding || parameters.lightMapEncoding ) ?
18310				ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
18311			parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',
18312			parameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',
18313			parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',
18314			parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',
18315			parameters.lightMapEncoding ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',
18316			parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',
18317
18318			parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
18319
18320			'\n'
18321
18322		].filter( filterEmptyLine ).join( '\n' );
18323
18324	}
18325
18326	vertexShader = resolveIncludes( vertexShader );
18327	vertexShader = replaceLightNums( vertexShader, parameters );
18328	vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
18329
18330	fragmentShader = resolveIncludes( fragmentShader );
18331	fragmentShader = replaceLightNums( fragmentShader, parameters );
18332	fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
18333
18334	vertexShader = unrollLoops( vertexShader );
18335	fragmentShader = unrollLoops( fragmentShader );
18336
18337	if ( parameters.isWebGL2 && ! parameters.isRawShaderMaterial ) {
18338
18339		var isGLSL3ShaderMaterial = false;
18340
18341		var versionRegex = /^\s*#version\s+300\s+es\s*\n/;
18342
18343		if ( parameters.isShaderMaterial &&
18344			vertexShader.match( versionRegex ) !== null &&
18345			fragmentShader.match( versionRegex ) !== null ) {
18346
18347			isGLSL3ShaderMaterial = true;
18348
18349			vertexShader = vertexShader.replace( versionRegex, '' );
18350			fragmentShader = fragmentShader.replace( versionRegex, '' );
18351
18352		}
18353
18354		// GLSL 3.0 conversion
18355
18356		prefixVertex = [
18357			'#version 300 es\n',
18358			'#define attribute in',
18359			'#define varying out',
18360			'#define texture2D texture'
18361		].join( '\n' ) + '\n' + prefixVertex;
18362
18363		prefixFragment = [
18364			'#version 300 es\n',
18365			'#define varying in',
18366			isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
18367			isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
18368			'#define gl_FragDepthEXT gl_FragDepth',
18369			'#define texture2D texture',
18370			'#define textureCube texture',
18371			'#define texture2DProj textureProj',
18372			'#define texture2DLodEXT textureLod',
18373			'#define texture2DProjLodEXT textureProjLod',
18374			'#define textureCubeLodEXT textureLod',
18375			'#define texture2DGradEXT textureGrad',
18376			'#define texture2DProjGradEXT textureProjGrad',
18377			'#define textureCubeGradEXT textureGrad'
18378		].join( '\n' ) + '\n' + prefixFragment;
18379
18380	}
18381
18382	var vertexGlsl = prefixVertex + vertexShader;
18383	var fragmentGlsl = prefixFragment + fragmentShader;
18384
18385	// console.log( '*VERTEX*', vertexGlsl );
18386	// console.log( '*FRAGMENT*', fragmentGlsl );
18387
18388	var glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
18389	var glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
18390
18391	gl.attachShader( program, glVertexShader );
18392	gl.attachShader( program, glFragmentShader );
18393
18394	// Force a particular attribute to index 0.
18395
18396	if ( parameters.index0AttributeName !== undefined ) {
18397
18398		gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
18399
18400	} else if ( parameters.morphTargets === true ) {
18401
18402		// programs with morphTargets displace position out of attribute 0
18403		gl.bindAttribLocation( program, 0, 'position' );
18404
18405	}
18406
18407	gl.linkProgram( program );
18408
18409	// check for link errors
18410	if ( renderer.debug.checkShaderErrors ) {
18411
18412		var programLog = gl.getProgramInfoLog( program ).trim();
18413		var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
18414		var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
18415
18416		var runnable = true;
18417		var haveDiagnostics = true;
18418
18419		if ( gl.getProgramParameter( program, 35714 ) === false ) {
18420
18421			runnable = false;
18422
18423			var vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
18424			var fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
18425
18426			console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );
18427
18428		} else if ( programLog !== '' ) {
18429
18430			console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );
18431
18432		} else if ( vertexLog === '' || fragmentLog === '' ) {
18433
18434			haveDiagnostics = false;
18435
18436		}
18437
18438		if ( haveDiagnostics ) {
18439
18440			this.diagnostics = {
18441
18442				runnable: runnable,
18443
18444				programLog: programLog,
18445
18446				vertexShader: {
18447
18448					log: vertexLog,
18449					prefix: prefixVertex
18450
18451				},
18452
18453				fragmentShader: {
18454
18455					log: fragmentLog,
18456					prefix: prefixFragment
18457
18458				}
18459
18460			};
18461
18462		}
18463
18464	}
18465
18466	// Clean up
18467
18468	// Crashes in iOS9 and iOS10. #18402
18469	// gl.detachShader( program, glVertexShader );
18470	// gl.detachShader( program, glFragmentShader );
18471
18472	gl.deleteShader( glVertexShader );
18473	gl.deleteShader( glFragmentShader );
18474
18475	// set up caching for uniform locations
18476
18477	var cachedUniforms;
18478
18479	this.getUniforms = function () {
18480
18481		if ( cachedUniforms === undefined ) {
18482
18483			cachedUniforms = new WebGLUniforms( gl, program );
18484
18485		}
18486
18487		return cachedUniforms;
18488
18489	};
18490
18491	// set up caching for attribute locations
18492
18493	var cachedAttributes;
18494
18495	this.getAttributes = function () {
18496
18497		if ( cachedAttributes === undefined ) {
18498
18499			cachedAttributes = fetchAttributeLocations( gl, program );
18500
18501		}
18502
18503		return cachedAttributes;
18504
18505	};
18506
18507	// free resource
18508
18509	this.destroy = function () {
18510
18511		gl.deleteProgram( program );
18512		this.program = undefined;
18513
18514	};
18515
18516	//
18517
18518	this.name = parameters.shaderName;
18519	this.id = programIdCount ++;
18520	this.cacheKey = cacheKey;
18521	this.usedTimes = 1;
18522	this.program = program;
18523	this.vertexShader = glVertexShader;
18524	this.fragmentShader = glFragmentShader;
18525
18526	return this;
18527
18528}
18529
18530/**
18531 * @author mrdoob / http://mrdoob.com/
18532 */
18533
18534function WebGLPrograms( renderer, extensions, capabilities ) {
18535
18536	var programs = [];
18537
18538	var isWebGL2 = capabilities.isWebGL2;
18539	var logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
18540	var floatVertexTextures = capabilities.floatVertexTextures;
18541	var precision = capabilities.precision;
18542	var maxVertexUniforms = capabilities.maxVertexUniforms;
18543	var vertexTextures = capabilities.vertexTextures;
18544
18545	var shaderIDs = {
18546		MeshDepthMaterial: 'depth',
18547		MeshDistanceMaterial: 'distanceRGBA',
18548		MeshNormalMaterial: 'normal',
18549		MeshBasicMaterial: 'basic',
18550		MeshLambertMaterial: 'lambert',
18551		MeshPhongMaterial: 'phong',
18552		MeshToonMaterial: 'toon',
18553		MeshStandardMaterial: 'physical',
18554		MeshPhysicalMaterial: 'physical',
18555		MeshMatcapMaterial: 'matcap',
18556		LineBasicMaterial: 'basic',
18557		LineDashedMaterial: 'dashed',
18558		PointsMaterial: 'points',
18559		ShadowMaterial: 'shadow',
18560		SpriteMaterial: 'sprite'
18561	};
18562
18563	var parameterNames = [
18564		"precision", "isWebGL2", "supportsVertexTextures", "outputEncoding", "instancing",
18565		"map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding", "envMapCubeUV",
18566		"lightMap", "lightMapEncoding", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "tangentSpaceNormalMap", "clearcoatMap", "clearcoatRoughnessMap", "clearcoatNormalMap", "displacementMap", "specularMap",
18567		"roughnessMap", "metalnessMap", "gradientMap",
18568		"alphaMap", "combine", "vertexColors", "vertexTangents", "vertexUvs", "uvsVertexOnly", "fog", "useFog", "fogExp2",
18569		"flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning",
18570		"maxBones", "useVertexTexture", "morphTargets", "morphNormals",
18571		"maxMorphTargets", "maxMorphNormals", "premultipliedAlpha",
18572		"numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights",
18573		"numDirLightShadows", "numPointLightShadows", "numSpotLightShadows",
18574		"shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights',
18575		"alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering",
18576		"sheen"
18577	];
18578
18579	function getShaderObject( material, shaderID ) {
18580
18581		var shaderobject;
18582
18583		if ( shaderID ) {
18584
18585			var shader = ShaderLib[ shaderID ];
18586
18587			shaderobject = {
18588				name: material.type,
18589				uniforms: UniformsUtils.clone( shader.uniforms ),
18590				vertexShader: shader.vertexShader,
18591				fragmentShader: shader.fragmentShader
18592			};
18593
18594		} else {
18595
18596			shaderobject = {
18597				name: material.type,
18598				uniforms: material.uniforms,
18599				vertexShader: material.vertexShader,
18600				fragmentShader: material.fragmentShader
18601			};
18602
18603		}
18604
18605		return shaderobject;
18606
18607	}
18608
18609	function allocateBones( object ) {
18610
18611		var skeleton = object.skeleton;
18612		var bones = skeleton.bones;
18613
18614		if ( floatVertexTextures ) {
18615
18616			return 1024;
18617
18618		} else {
18619
18620			// default for when object is not specified
18621			// ( for example when prebuilding shader to be used with multiple objects )
18622			//
18623			//  - leave some extra space for other uniforms
18624			//  - limit here is ANGLE's 254 max uniform vectors
18625			//    (up to 54 should be safe)
18626
18627			var nVertexUniforms = maxVertexUniforms;
18628			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
18629
18630			var maxBones = Math.min( nVertexMatrices, bones.length );
18631
18632			if ( maxBones < bones.length ) {
18633
18634				console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );
18635				return 0;
18636
18637			}
18638
18639			return maxBones;
18640
18641		}
18642
18643	}
18644
18645	function getTextureEncodingFromMap( map ) {
18646
18647		var encoding;
18648
18649		if ( ! map ) {
18650
18651			encoding = LinearEncoding;
18652
18653		} else if ( map.isTexture ) {
18654
18655			encoding = map.encoding;
18656
18657		} else if ( map.isWebGLRenderTarget ) {
18658
18659			console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
18660			encoding = map.texture.encoding;
18661
18662		}
18663
18664		return encoding;
18665
18666	}
18667
18668	this.getParameters = function ( material, lights, shadows, scene, nClipPlanes, nClipIntersection, object ) {
18669
18670		var fog = scene.fog;
18671		var environment = material.isMeshStandardMaterial ? scene.environment : null;
18672
18673		var envMap = material.envMap || environment;
18674
18675		var shaderID = shaderIDs[ material.type ];
18676
18677		// heuristics to create shader parameters according to lights in the scene
18678		// (not to blow over maxLights budget)
18679
18680		var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;
18681
18682		if ( material.precision !== null ) {
18683
18684			precision = capabilities.getMaxPrecision( material.precision );
18685
18686			if ( precision !== material.precision ) {
18687
18688				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
18689
18690			}
18691
18692		}
18693
18694		var shaderobject = getShaderObject( material, shaderID );
18695		material.onBeforeCompile( shaderobject, renderer );
18696
18697		var currentRenderTarget = renderer.getRenderTarget();
18698
18699		var parameters = {
18700
18701			isWebGL2: isWebGL2,
18702
18703			shaderID: shaderID,
18704			shaderName: shaderobject.name,
18705
18706			uniforms: shaderobject.uniforms,
18707			vertexShader: shaderobject.vertexShader,
18708			fragmentShader: shaderobject.fragmentShader,
18709			defines: material.defines,
18710
18711			isRawShaderMaterial: material.isRawShaderMaterial,
18712			isShaderMaterial: material.isShaderMaterial,
18713
18714			precision: precision,
18715
18716			instancing: object.isInstancedMesh === true,
18717
18718			supportsVertexTextures: vertexTextures,
18719			outputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,
18720			map: !! material.map,
18721			mapEncoding: getTextureEncodingFromMap( material.map ),
18722			matcap: !! material.matcap,
18723			matcapEncoding: getTextureEncodingFromMap( material.matcap ),
18724			envMap: !! envMap,
18725			envMapMode: envMap && envMap.mapping,
18726			envMapEncoding: getTextureEncodingFromMap( envMap ),
18727			envMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),
18728			lightMap: !! material.lightMap,
18729			lightMapEncoding: getTextureEncodingFromMap( material.lightMap ),
18730			aoMap: !! material.aoMap,
18731			emissiveMap: !! material.emissiveMap,
18732			emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),
18733			bumpMap: !! material.bumpMap,
18734			normalMap: !! material.normalMap,
18735			objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
18736			tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
18737			clearcoatMap: !! material.clearcoatMap,
18738			clearcoatRoughnessMap: !! material.clearcoatRoughnessMap,
18739			clearcoatNormalMap: !! material.clearcoatNormalMap,
18740			displacementMap: !! material.displacementMap,
18741			roughnessMap: !! material.roughnessMap,
18742			metalnessMap: !! material.metalnessMap,
18743			specularMap: !! material.specularMap,
18744			alphaMap: !! material.alphaMap,
18745
18746			gradientMap: !! material.gradientMap,
18747
18748			sheen: !! material.sheen,
18749
18750			combine: material.combine,
18751
18752			vertexTangents: ( material.normalMap && material.vertexTangents ),
18753			vertexColors: material.vertexColors,
18754			vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap,
18755			uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap ) && !! material.displacementMap,
18756
18757			fog: !! fog,
18758			useFog: material.fog,
18759			fogExp2: ( fog && fog.isFogExp2 ),
18760
18761			flatShading: material.flatShading,
18762
18763			sizeAttenuation: material.sizeAttenuation,
18764			logarithmicDepthBuffer: logarithmicDepthBuffer,
18765
18766			skinning: material.skinning && maxBones > 0,
18767			maxBones: maxBones,
18768			useVertexTexture: floatVertexTextures,
18769
18770			morphTargets: material.morphTargets,
18771			morphNormals: material.morphNormals,
18772			maxMorphTargets: renderer.maxMorphTargets,
18773			maxMorphNormals: renderer.maxMorphNormals,
18774
18775			numDirLights: lights.directional.length,
18776			numPointLights: lights.point.length,
18777			numSpotLights: lights.spot.length,
18778			numRectAreaLights: lights.rectArea.length,
18779			numHemiLights: lights.hemi.length,
18780
18781			numDirLightShadows: lights.directionalShadowMap.length,
18782			numPointLightShadows: lights.pointShadowMap.length,
18783			numSpotLightShadows: lights.spotShadowMap.length,
18784
18785			numClippingPlanes: nClipPlanes,
18786			numClipIntersection: nClipIntersection,
18787
18788			dithering: material.dithering,
18789
18790			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
18791			shadowMapType: renderer.shadowMap.type,
18792
18793			toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
18794			physicallyCorrectLights: renderer.physicallyCorrectLights,
18795
18796			premultipliedAlpha: material.premultipliedAlpha,
18797
18798			alphaTest: material.alphaTest,
18799			doubleSided: material.side === DoubleSide,
18800			flipSided: material.side === BackSide,
18801
18802			depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,
18803
18804			index0AttributeName: material.index0AttributeName,
18805
18806			extensionDerivatives: material.extensions && material.extensions.derivatives,
18807			extensionFragDepth: material.extensions && material.extensions.fragDepth,
18808			extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
18809			extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
18810
18811			rendererExtensionFragDepth: isWebGL2 || extensions.get( 'EXT_frag_depth' ) !== null,
18812			rendererExtensionDrawBuffers: isWebGL2 || extensions.get( 'WEBGL_draw_buffers' ) !== null,
18813			rendererExtensionShaderTextureLod: isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) !== null,
18814
18815			onBeforeCompile: material.onBeforeCompile
18816
18817		};
18818
18819		return parameters;
18820
18821	};
18822
18823	this.getProgramCacheKey = function ( parameters ) {
18824
18825		var array = [];
18826
18827		if ( parameters.shaderID ) {
18828
18829			array.push( parameters.shaderID );
18830
18831		} else {
18832
18833			array.push( parameters.fragmentShader );
18834			array.push( parameters.vertexShader );
18835
18836		}
18837
18838		if ( parameters.defines !== undefined ) {
18839
18840			for ( var name in parameters.defines ) {
18841
18842				array.push( name );
18843				array.push( parameters.defines[ name ] );
18844
18845			}
18846
18847		}
18848
18849		if ( parameters.isRawShaderMaterial === undefined ) {
18850
18851			for ( var i = 0; i < parameterNames.length; i ++ ) {
18852
18853				array.push( parameters[ parameterNames[ i ] ] );
18854
18855			}
18856
18857			array.push( renderer.outputEncoding );
18858			array.push( renderer.gammaFactor );
18859
18860		}
18861
18862		array.push( parameters.onBeforeCompile.toString() );
18863
18864		return array.join();
18865
18866	};
18867
18868	this.acquireProgram = function ( parameters, cacheKey ) {
18869
18870		var program;
18871
18872		// Check if code has been already compiled
18873		for ( var p = 0, pl = programs.length; p < pl; p ++ ) {
18874
18875			var preexistingProgram = programs[ p ];
18876
18877			if ( preexistingProgram.cacheKey === cacheKey ) {
18878
18879				program = preexistingProgram;
18880				++ program.usedTimes;
18881
18882				break;
18883
18884			}
18885
18886		}
18887
18888		if ( program === undefined ) {
18889
18890			program = new WebGLProgram( renderer, cacheKey, parameters );
18891			programs.push( program );
18892
18893		}
18894
18895		return program;
18896
18897	};
18898
18899	this.releaseProgram = function ( program ) {
18900
18901		if ( -- program.usedTimes === 0 ) {
18902
18903			// Remove from unordered set
18904			var i = programs.indexOf( program );
18905			programs[ i ] = programs[ programs.length - 1 ];
18906			programs.pop();
18907
18908			// Free WebGL resources
18909			program.destroy();
18910
18911		}
18912
18913	};
18914
18915	// Exposed for resource monitoring & error feedback via renderer.info:
18916	this.programs = programs;
18917
18918}
18919
18920/**
18921 * @author fordacious / fordacious.github.io
18922 */
18923
18924function WebGLProperties() {
18925
18926	var properties = new WeakMap();
18927
18928	function get( object ) {
18929
18930		var map = properties.get( object );
18931
18932		if ( map === undefined ) {
18933
18934			map = {};
18935			properties.set( object, map );
18936
18937		}
18938
18939		return map;
18940
18941	}
18942
18943	function remove( object ) {
18944
18945		properties.delete( object );
18946
18947	}
18948
18949	function update( object, key, value ) {
18950
18951		properties.get( object )[ key ] = value;
18952
18953	}
18954
18955	function dispose() {
18956
18957		properties = new WeakMap();
18958
18959	}
18960
18961	return {
18962		get: get,
18963		remove: remove,
18964		update: update,
vendor: 27,895 bytes, lines 18965-20236
18965		dispose: dispose
18966	};
18967
18968}
18969
18970/**
18971 * @author mrdoob / http://mrdoob.com/
18972 */
18973
18974function painterSortStable( a, b ) {
18975
18976	if ( a.groupOrder !== b.groupOrder ) {
18977
18978		return a.groupOrder - b.groupOrder;
18979
18980	} else if ( a.renderOrder !== b.renderOrder ) {
18981
18982		return a.renderOrder - b.renderOrder;
18983
18984	} else if ( a.program !== b.program ) {
18985
18986		return a.program.id - b.program.id;
18987
18988	} else if ( a.material.id !== b.material.id ) {
18989
18990		return a.material.id - b.material.id;
18991
18992	} else if ( a.z !== b.z ) {
18993
18994		return a.z - b.z;
18995
18996	} else {
18997
18998		return a.id - b.id;
18999
19000	}
19001
19002}
19003
19004function reversePainterSortStable( a, b ) {
19005
19006	if ( a.groupOrder !== b.groupOrder ) {
19007
19008		return a.groupOrder - b.groupOrder;
19009
19010	} else if ( a.renderOrder !== b.renderOrder ) {
19011
19012		return a.renderOrder - b.renderOrder;
19013
19014	} else if ( a.z !== b.z ) {
19015
19016		return b.z - a.z;
19017
19018	} else {
19019
19020		return a.id - b.id;
19021
19022	}
19023
19024}
19025
19026
19027function WebGLRenderList() {
19028
19029	var renderItems = [];
19030	var renderItemsIndex = 0;
19031
19032	var opaque = [];
19033	var transparent = [];
19034
19035	var defaultProgram = { id: - 1 };
19036
19037	function init() {
19038
19039		renderItemsIndex = 0;
19040
19041		opaque.length = 0;
19042		transparent.length = 0;
19043
19044	}
19045
19046	function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
19047
19048		var renderItem = renderItems[ renderItemsIndex ];
19049
19050		if ( renderItem === undefined ) {
19051
19052			renderItem = {
19053				id: object.id,
19054				object: object,
19055				geometry: geometry,
19056				material: material,
19057				program: material.program || defaultProgram,
19058				groupOrder: groupOrder,
19059				renderOrder: object.renderOrder,
19060				z: z,
19061				group: group
19062			};
19063
19064			renderItems[ renderItemsIndex ] = renderItem;
19065
19066		} else {
19067
19068			renderItem.id = object.id;
19069			renderItem.object = object;
19070			renderItem.geometry = geometry;
19071			renderItem.material = material;
19072			renderItem.program = material.program || defaultProgram;
19073			renderItem.groupOrder = groupOrder;
19074			renderItem.renderOrder = object.renderOrder;
19075			renderItem.z = z;
19076			renderItem.group = group;
19077
19078		}
19079
19080		renderItemsIndex ++;
19081
19082		return renderItem;
19083
19084	}
19085
19086	function push( object, geometry, material, groupOrder, z, group ) {
19087
19088		var renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
19089
19090		( material.transparent === true ? transparent : opaque ).push( renderItem );
19091
19092	}
19093
19094	function unshift( object, geometry, material, groupOrder, z, group ) {
19095
19096		var renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
19097
19098		( material.transparent === true ? transparent : opaque ).unshift( renderItem );
19099
19100	}
19101
19102	function sort( customOpaqueSort, customTransparentSort ) {
19103
19104		if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
19105		if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
19106
19107	}
19108
19109	function finish() {
19110
19111		// Clear references from inactive renderItems in the list
19112
19113		for ( var i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
19114
19115			var renderItem = renderItems[ i ];
19116
19117			if ( renderItem.id === null ) break;
19118
19119			renderItem.id = null;
19120			renderItem.object = null;
19121			renderItem.geometry = null;
19122			renderItem.material = null;
19123			renderItem.program = null;
19124			renderItem.group = null;
19125
19126		}
19127
19128	}
19129
19130	return {
19131		opaque: opaque,
19132		transparent: transparent,
19133
19134		init: init,
19135		push: push,
19136		unshift: unshift,
19137		finish: finish,
19138
19139		sort: sort
19140	};
19141
19142}
19143
19144function WebGLRenderLists() {
19145
19146	var lists = new WeakMap();
19147
19148	function onSceneDispose( event ) {
19149
19150		var scene = event.target;
19151
19152		scene.removeEventListener( 'dispose', onSceneDispose );
19153
19154		lists.delete( scene );
19155
19156	}
19157
19158	function get( scene, camera ) {
19159
19160		var cameras = lists.get( scene );
19161		var list;
19162		if ( cameras === undefined ) {
19163
19164			list = new WebGLRenderList();
19165			lists.set( scene, new WeakMap() );
19166			lists.get( scene ).set( camera, list );
19167
19168			scene.addEventListener( 'dispose', onSceneDispose );
19169
19170		} else {
19171
19172			list = cameras.get( camera );
19173			if ( list === undefined ) {
19174
19175				list = new WebGLRenderList();
19176				cameras.set( camera, list );
19177
19178			}
19179
19180		}
19181
19182		return list;
19183
19184	}
19185
19186	function dispose() {
19187
19188		lists = new WeakMap();
19189
19190	}
19191
19192	return {
19193		get: get,
19194		dispose: dispose
19195	};
19196
19197}
19198
19199/**
19200 * @author mrdoob / http://mrdoob.com/
19201 */
19202
19203function UniformsCache() {
19204
19205	var lights = {};
19206
19207	return {
19208
19209		get: function ( light ) {
19210
19211			if ( lights[ light.id ] !== undefined ) {
19212
19213				return lights[ light.id ];
19214
19215			}
19216
19217			var uniforms;
19218
19219			switch ( light.type ) {
19220
19221				case 'DirectionalLight':
19222					uniforms = {
19223						direction: new Vector3(),
19224						color: new Color()
19225					};
19226					break;
19227
19228				case 'SpotLight':
19229					uniforms = {
19230						position: new Vector3(),
19231						direction: new Vector3(),
19232						color: new Color(),
19233						distance: 0,
19234						coneCos: 0,
19235						penumbraCos: 0,
19236						decay: 0
19237					};
19238					break;
19239
19240				case 'PointLight':
19241					uniforms = {
19242						position: new Vector3(),
19243						color: new Color(),
19244						distance: 0,
19245						decay: 0
19246					};
19247					break;
19248
19249				case 'HemisphereLight':
19250					uniforms = {
19251						direction: new Vector3(),
19252						skyColor: new Color(),
19253						groundColor: new Color()
19254					};
19255					break;
19256
19257				case 'RectAreaLight':
19258					uniforms = {
19259						color: new Color(),
19260						position: new Vector3(),
19261						halfWidth: new Vector3(),
19262						halfHeight: new Vector3()
19263					};
19264					break;
19265
19266			}
19267
19268			lights[ light.id ] = uniforms;
19269
19270			return uniforms;
19271
19272		}
19273
19274	};
19275
19276}
19277
19278function ShadowUniformsCache() {
19279
19280	var lights = {};
19281
19282	return {
19283
19284		get: function ( light ) {
19285
19286			if ( lights[ light.id ] !== undefined ) {
19287
19288				return lights[ light.id ];
19289
19290			}
19291
19292			var uniforms;
19293
19294			switch ( light.type ) {
19295
19296				case 'DirectionalLight':
19297					uniforms = {
19298						shadowBias: 0,
19299						shadowRadius: 1,
19300						shadowMapSize: new Vector2()
19301					};
19302					break;
19303
19304				case 'SpotLight':
19305					uniforms = {
19306						shadowBias: 0,
19307						shadowRadius: 1,
19308						shadowMapSize: new Vector2()
19309					};
19310					break;
19311
19312				case 'PointLight':
19313					uniforms = {
19314						shadowBias: 0,
19315						shadowRadius: 1,
19316						shadowMapSize: new Vector2(),
19317						shadowCameraNear: 1,
19318						shadowCameraFar: 1000
19319					};
19320					break;
19321
19322				// TODO (abelnation): set RectAreaLight shadow uniforms
19323
19324			}
19325
19326			lights[ light.id ] = uniforms;
19327
19328			return uniforms;
19329
19330		}
19331
19332	};
19333
19334}
19335
19336
19337
19338var nextVersion = 0;
19339
19340function shadowCastingLightsFirst( lightA, lightB ) {
19341
19342	return ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );
19343
19344}
19345
19346function WebGLLights() {
19347
19348	var cache = new UniformsCache();
19349
19350	var shadowCache = ShadowUniformsCache();
19351
19352	var state = {
19353
19354		version: 0,
19355
19356		hash: {
19357			directionalLength: - 1,
19358			pointLength: - 1,
19359			spotLength: - 1,
19360			rectAreaLength: - 1,
19361			hemiLength: - 1,
19362
19363			numDirectionalShadows: - 1,
19364			numPointShadows: - 1,
19365			numSpotShadows: - 1
19366		},
19367
19368		ambient: [ 0, 0, 0 ],
19369		probe: [],
19370		directional: [],
19371		directionalShadow: [],
19372		directionalShadowMap: [],
19373		directionalShadowMatrix: [],
19374		spot: [],
19375		spotShadow: [],
19376		spotShadowMap: [],
19377		spotShadowMatrix: [],
19378		rectArea: [],
19379		point: [],
19380		pointShadow: [],
19381		pointShadowMap: [],
19382		pointShadowMatrix: [],
19383		hemi: []
19384
19385	};
19386
19387	for ( var i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
19388
19389	var vector3 = new Vector3();
19390	var matrix4 = new Matrix4();
19391	var matrix42 = new Matrix4();
19392
19393	function setup( lights, shadows, camera ) {
19394
19395		var r = 0, g = 0, b = 0;
19396
19397		for ( var i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
19398
19399		var directionalLength = 0;
19400		var pointLength = 0;
19401		var spotLength = 0;
19402		var rectAreaLength = 0;
19403		var hemiLength = 0;
19404
19405		var numDirectionalShadows = 0;
19406		var numPointShadows = 0;
19407		var numSpotShadows = 0;
19408
19409		var viewMatrix = camera.matrixWorldInverse;
19410
19411		lights.sort( shadowCastingLightsFirst );
19412
19413		for ( var i = 0, l = lights.length; i < l; i ++ ) {
19414
19415			var light = lights[ i ];
19416
19417			var color = light.color;
19418			var intensity = light.intensity;
19419			var distance = light.distance;
19420
19421			var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
19422
19423			if ( light.isAmbientLight ) {
19424
19425				r += color.r * intensity;
19426				g += color.g * intensity;
19427				b += color.b * intensity;
19428
19429			} else if ( light.isLightProbe ) {
19430
19431				for ( var j = 0; j < 9; j ++ ) {
19432
19433					state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
19434
19435				}
19436
19437			} else if ( light.isDirectionalLight ) {
19438
19439				var uniforms = cache.get( light );
19440
19441				uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
19442				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
19443				vector3.setFromMatrixPosition( light.target.matrixWorld );
19444				uniforms.direction.sub( vector3 );
19445				uniforms.direction.transformDirection( viewMatrix );
19446
19447				if ( light.castShadow ) {
19448
19449					var shadow = light.shadow;
19450
19451					var shadowUniforms = shadowCache.get( light );
19452
19453					shadowUniforms.shadowBias = shadow.bias;
19454					shadowUniforms.shadowRadius = shadow.radius;
19455					shadowUniforms.shadowMapSize = shadow.mapSize;
19456
19457					state.directionalShadow[ directionalLength ] = shadowUniforms;
19458					state.directionalShadowMap[ directionalLength ] = shadowMap;
19459					state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
19460
19461					numDirectionalShadows ++;
19462
19463				}
19464
19465				state.directional[ directionalLength ] = uniforms;
19466
19467				directionalLength ++;
19468
19469			} else if ( light.isSpotLight ) {
19470
19471				var uniforms = cache.get( light );
19472
19473				uniforms.position.setFromMatrixPosition( light.matrixWorld );
19474				uniforms.position.applyMatrix4( viewMatrix );
19475
19476				uniforms.color.copy( color ).multiplyScalar( intensity );
19477				uniforms.distance = distance;
19478
19479				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
19480				vector3.setFromMatrixPosition( light.target.matrixWorld );
19481				uniforms.direction.sub( vector3 );
19482				uniforms.direction.transformDirection( viewMatrix );
19483
19484				uniforms.coneCos = Math.cos( light.angle );
19485				uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
19486				uniforms.decay = light.decay;
19487
19488				if ( light.castShadow ) {
19489
19490					var shadow = light.shadow;
19491
19492					var shadowUniforms = shadowCache.get( light );
19493
19494					shadowUniforms.shadowBias = shadow.bias;
19495					shadowUniforms.shadowRadius = shadow.radius;
19496					shadowUniforms.shadowMapSize = shadow.mapSize;
19497
19498					state.spotShadow[ spotLength ] = shadowUniforms;
19499					state.spotShadowMap[ spotLength ] = shadowMap;
19500					state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
19501
19502					numSpotShadows ++;
19503
19504				}
19505
19506				state.spot[ spotLength ] = uniforms;
19507
19508				spotLength ++;
19509
19510			} else if ( light.isRectAreaLight ) {
19511
19512				var uniforms = cache.get( light );
19513
19514				// (a) intensity is the total visible light emitted
19515				//uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );
19516
19517				// (b) intensity is the brightness of the light
19518				uniforms.color.copy( color ).multiplyScalar( intensity );
19519
19520				uniforms.position.setFromMatrixPosition( light.matrixWorld );
19521				uniforms.position.applyMatrix4( viewMatrix );
19522
19523				// extract local rotation of light to derive width/height half vectors
19524				matrix42.identity();
19525				matrix4.copy( light.matrixWorld );
19526				matrix4.premultiply( viewMatrix );
19527				matrix42.extractRotation( matrix4 );
19528
19529				uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
19530				uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
19531
19532				uniforms.halfWidth.applyMatrix4( matrix42 );
19533				uniforms.halfHeight.applyMatrix4( matrix42 );
19534
19535				// TODO (abelnation): RectAreaLight distance?
19536				// uniforms.distance = distance;
19537
19538				state.rectArea[ rectAreaLength ] = uniforms;
19539
19540				rectAreaLength ++;
19541
19542			} else if ( light.isPointLight ) {
19543
19544				var uniforms = cache.get( light );
19545
19546				uniforms.position.setFromMatrixPosition( light.matrixWorld );
19547				uniforms.position.applyMatrix4( viewMatrix );
19548
19549				uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
19550				uniforms.distance = light.distance;
19551				uniforms.decay = light.decay;
19552
19553				if ( light.castShadow ) {
19554
19555					var shadow = light.shadow;
19556
19557					var shadowUniforms = shadowCache.get( light );
19558
19559					shadowUniforms.shadowBias = shadow.bias;
19560					shadowUniforms.shadowRadius = shadow.radius;
19561					shadowUniforms.shadowMapSize = shadow.mapSize;
19562					shadowUniforms.shadowCameraNear = shadow.camera.near;
19563					shadowUniforms.shadowCameraFar = shadow.camera.far;
19564
19565					state.pointShadow[ pointLength ] = shadowUniforms;
19566					state.pointShadowMap[ pointLength ] = shadowMap;
19567					state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
19568
19569					numPointShadows ++;
19570
19571				}
19572
19573				state.point[ pointLength ] = uniforms;
19574
19575				pointLength ++;
19576
19577			} else if ( light.isHemisphereLight ) {
19578
19579				var uniforms = cache.get( light );
19580
19581				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
19582				uniforms.direction.transformDirection( viewMatrix );
19583				uniforms.direction.normalize();
19584
19585				uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
19586				uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
19587
19588				state.hemi[ hemiLength ] = uniforms;
19589
19590				hemiLength ++;
19591
19592			}
19593
19594		}
19595
19596		state.ambient[ 0 ] = r;
19597		state.ambient[ 1 ] = g;
19598		state.ambient[ 2 ] = b;
19599
19600		var hash = state.hash;
19601
19602		if ( hash.directionalLength !== directionalLength ||
19603			hash.pointLength !== pointLength ||
19604			hash.spotLength !== spotLength ||
19605			hash.rectAreaLength !== rectAreaLength ||
19606			hash.hemiLength !== hemiLength ||
19607			hash.numDirectionalShadows !== numDirectionalShadows ||
19608			hash.numPointShadows !== numPointShadows ||
19609			hash.numSpotShadows !== numSpotShadows ) {
19610
19611			state.directional.length = directionalLength;
19612			state.spot.length = spotLength;
19613			state.rectArea.length = rectAreaLength;
19614			state.point.length = pointLength;
19615			state.hemi.length = hemiLength;
19616
19617			state.directionalShadow.length = numDirectionalShadows;
19618			state.directionalShadowMap.length = numDirectionalShadows;
19619			state.pointShadow.length = numPointShadows;
19620			state.pointShadowMap.length = numPointShadows;
19621			state.spotShadow.length = numSpotShadows;
19622			state.spotShadowMap.length = numSpotShadows;
19623			state.directionalShadowMatrix.length = numDirectionalShadows;
19624			state.pointShadowMatrix.length = numPointShadows;
19625			state.spotShadowMatrix.length = numSpotShadows;
19626
19627			hash.directionalLength = directionalLength;
19628			hash.pointLength = pointLength;
19629			hash.spotLength = spotLength;
19630			hash.rectAreaLength = rectAreaLength;
19631			hash.hemiLength = hemiLength;
19632
19633			hash.numDirectionalShadows = numDirectionalShadows;
19634			hash.numPointShadows = numPointShadows;
19635			hash.numSpotShadows = numSpotShadows;
19636
19637			state.version = nextVersion ++;
19638
19639		}
19640
19641	}
19642
19643	return {
19644		setup: setup,
19645		state: state
19646	};
19647
19648}
19649
19650/**
19651 * @author Mugen87 / https://github.com/Mugen87
19652 */
19653
19654function WebGLRenderState() {
19655
19656	var lights = new WebGLLights();
19657
19658	var lightsArray = [];
19659	var shadowsArray = [];
19660
19661	function init() {
19662
19663		lightsArray.length = 0;
19664		shadowsArray.length = 0;
19665
19666	}
19667
19668	function pushLight( light ) {
19669
19670		lightsArray.push( light );
19671
19672	}
19673
19674	function pushShadow( shadowLight ) {
19675
19676		shadowsArray.push( shadowLight );
19677
19678	}
19679
19680	function setupLights( camera ) {
19681
19682		lights.setup( lightsArray, shadowsArray, camera );
19683
19684	}
19685
19686	var state = {
19687		lightsArray: lightsArray,
19688		shadowsArray: shadowsArray,
19689
19690		lights: lights
19691	};
19692
19693	return {
19694		init: init,
19695		state: state,
19696		setupLights: setupLights,
19697
19698		pushLight: pushLight,
19699		pushShadow: pushShadow
19700	};
19701
19702}
19703
19704function WebGLRenderStates() {
19705
19706	var renderStates = new WeakMap();
19707
19708	function onSceneDispose( event ) {
19709
19710		var scene = event.target;
19711
19712		scene.removeEventListener( 'dispose', onSceneDispose );
19713
19714		renderStates.delete( scene );
19715
19716	}
19717
19718	function get( scene, camera ) {
19719
19720		var renderState;
19721
19722		if ( renderStates.has( scene ) === false ) {
19723
19724			renderState = new WebGLRenderState();
19725			renderStates.set( scene, new WeakMap() );
19726			renderStates.get( scene ).set( camera, renderState );
19727
19728			scene.addEventListener( 'dispose', onSceneDispose );
19729
19730		} else {
19731
19732			if ( renderStates.get( scene ).has( camera ) === false ) {
19733
19734				renderState = new WebGLRenderState();
19735				renderStates.get( scene ).set( camera, renderState );
19736
19737			} else {
19738
19739				renderState = renderStates.get( scene ).get( camera );
19740
19741			}
19742
19743		}
19744
19745		return renderState;
19746
19747	}
19748
19749	function dispose() {
19750
19751		renderStates = new WeakMap();
19752
19753	}
19754
19755	return {
19756		get: get,
19757		dispose: dispose
19758	};
19759
19760}
19761
19762/**
19763 * @author mrdoob / http://mrdoob.com/
19764 * @author alteredq / http://alteredqualia.com/
19765 * @author bhouston / https://clara.io
19766 * @author WestLangley / http://github.com/WestLangley
19767 *
19768 * parameters = {
19769 *
19770 *  opacity: <float>,
19771 *
19772 *  map: new THREE.Texture( <Image> ),
19773 *
19774 *  alphaMap: new THREE.Texture( <Image> ),
19775 *
19776 *  displacementMap: new THREE.Texture( <Image> ),
19777 *  displacementScale: <float>,
19778 *  displacementBias: <float>,
19779 *
19780 *  wireframe: <boolean>,
19781 *  wireframeLinewidth: <float>
19782 * }
19783 */
19784
19785function MeshDepthMaterial( parameters ) {
19786
19787	Material.call( this );
19788
19789	this.type = 'MeshDepthMaterial';
19790
19791	this.depthPacking = BasicDepthPacking;
19792
19793	this.skinning = false;
19794	this.morphTargets = false;
19795
19796	this.map = null;
19797
19798	this.alphaMap = null;
19799
19800	this.displacementMap = null;
19801	this.displacementScale = 1;
19802	this.displacementBias = 0;
19803
19804	this.wireframe = false;
19805	this.wireframeLinewidth = 1;
19806
19807	this.fog = false;
19808
19809	this.setValues( parameters );
19810
19811}
19812
19813MeshDepthMaterial.prototype = Object.create( Material.prototype );
19814MeshDepthMaterial.prototype.constructor = MeshDepthMaterial;
19815
19816MeshDepthMaterial.prototype.isMeshDepthMaterial = true;
19817
19818MeshDepthMaterial.prototype.copy = function ( source ) {
19819
19820	Material.prototype.copy.call( this, source );
19821
19822	this.depthPacking = source.depthPacking;
19823
19824	this.skinning = source.skinning;
19825	this.morphTargets = source.morphTargets;
19826
19827	this.map = source.map;
19828
19829	this.alphaMap = source.alphaMap;
19830
19831	this.displacementMap = source.displacementMap;
19832	this.displacementScale = source.displacementScale;
19833	this.displacementBias = source.displacementBias;
19834
19835	this.wireframe = source.wireframe;
19836	this.wireframeLinewidth = source.wireframeLinewidth;
19837
19838	return this;
19839
19840};
19841
19842/**
19843 * @author WestLangley / http://github.com/WestLangley
19844 *
19845 * parameters = {
19846 *
19847 *  referencePosition: <float>,
19848 *  nearDistance: <float>,
19849 *  farDistance: <float>,
19850 *
19851 *  skinning: <bool>,
19852 *  morphTargets: <bool>,
19853 *
19854 *  map: new THREE.Texture( <Image> ),
19855 *
19856 *  alphaMap: new THREE.Texture( <Image> ),
19857 *
19858 *  displacementMap: new THREE.Texture( <Image> ),
19859 *  displacementScale: <float>,
19860 *  displacementBias: <float>
19861 *
19862 * }
19863 */
19864
19865function MeshDistanceMaterial( parameters ) {
19866
19867	Material.call( this );
19868
19869	this.type = 'MeshDistanceMaterial';
19870
19871	this.referencePosition = new Vector3();
19872	this.nearDistance = 1;
19873	this.farDistance = 1000;
19874
19875	this.skinning = false;
19876	this.morphTargets = false;
19877
19878	this.map = null;
19879
19880	this.alphaMap = null;
19881
19882	this.displacementMap = null;
19883	this.displacementScale = 1;
19884	this.displacementBias = 0;
19885
19886	this.fog = false;
19887
19888	this.setValues( parameters );
19889
19890}
19891
19892MeshDistanceMaterial.prototype = Object.create( Material.prototype );
19893MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;
19894
19895MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;
19896
19897MeshDistanceMaterial.prototype.copy = function ( source ) {
19898
19899	Material.prototype.copy.call( this, source );
19900
19901	this.referencePosition.copy( source.referencePosition );
19902	this.nearDistance = source.nearDistance;
19903	this.farDistance = source.farDistance;
19904
19905	this.skinning = source.skinning;
19906	this.morphTargets = source.morphTargets;
19907
19908	this.map = source.map;
19909
19910	this.alphaMap = source.alphaMap;
19911
19912	this.displacementMap = source.displacementMap;
19913	this.displacementScale = source.displacementScale;
19914	this.displacementBias = source.displacementBias;
19915
19916	return this;
19917
19918};
19919
19920var vsm_frag = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n  float mean = 0.0;\n  float squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy  ) / resolution ) );\n  for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n    #ifdef HORIZONAL_PASS\n      vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n      mean += distribution.x;\n      squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n    #else\n      float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0,  i )  * radius ) / resolution ) );\n      mean += depth;\n      squared_mean += depth * depth;\n    #endif\n  }\n  mean = mean * HALF_SAMPLE_RATE;\n  squared_mean = squared_mean * HALF_SAMPLE_RATE;\n  float std_dev = sqrt( squared_mean - mean * mean );\n  gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
19921
19922var vsm_vert = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
19923
19924/**
19925 * @author alteredq / http://alteredqualia.com/
19926 * @author mrdoob / http://mrdoob.com/
19927 */
19928
19929function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
19930
19931	var _frustum = new Frustum(),
19932
19933		_shadowMapSize = new Vector2(),
19934		_viewportSize = new Vector2(),
19935
19936		_viewport = new Vector4(),
19937
19938		_depthMaterials = [],
19939		_distanceMaterials = [],
19940
19941		_materialCache = {};
19942
19943	var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };
19944
19945	var shadowMaterialVertical = new ShaderMaterial( {
19946
19947		defines: {
19948			SAMPLE_RATE: 2.0 / 8.0,
19949			HALF_SAMPLE_RATE: 1.0 / 8.0
19950		},
19951
19952		uniforms: {
19953			shadow_pass: { value: null },
19954			resolution: { value: new Vector2() },
19955			radius: { value: 4.0 }
19956		},
19957
19958		vertexShader: vsm_vert,
19959
19960		fragmentShader: vsm_frag
19961
19962	} );
19963
19964	var shadowMaterialHorizonal = shadowMaterialVertical.clone();
19965	shadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;
19966
19967	var fullScreenTri = new BufferGeometry();
19968	fullScreenTri.setAttribute(
19969		"position",
19970		new BufferAttribute(
19971			new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
19972			3
19973		)
19974	);
19975
19976	var fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
19977
19978	var scope = this;
19979
19980	this.enabled = false;
19981
19982	this.autoUpdate = true;
19983	this.needsUpdate = false;
19984
19985	this.type = PCFShadowMap;
19986
19987	this.render = function ( lights, scene, camera ) {
19988
19989		if ( scope.enabled === false ) return;
19990		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
19991
19992		if ( lights.length === 0 ) return;
19993
19994		var currentRenderTarget = _renderer.getRenderTarget();
19995		var activeCubeFace = _renderer.getActiveCubeFace();
19996		var activeMipmapLevel = _renderer.getActiveMipmapLevel();
19997
19998		var _state = _renderer.state;
19999
20000		// Set GL state for depth map.
20001		_state.setBlending( NoBlending );
20002		_state.buffers.color.setClear( 1, 1, 1, 1 );
20003		_state.buffers.depth.setTest( true );
20004		_state.setScissorTest( false );
20005
20006		// render depth map
20007
20008		for ( var i = 0, il = lights.length; i < il; i ++ ) {
20009
20010			var light = lights[ i ];
20011			var shadow = light.shadow;
20012
20013			if ( shadow === undefined ) {
20014
20015				console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
20016				continue;
20017
20018			}
20019
20020			_shadowMapSize.copy( shadow.mapSize );
20021
20022			var shadowFrameExtents = shadow.getFrameExtents();
20023
20024			_shadowMapSize.multiply( shadowFrameExtents );
20025
20026			_viewportSize.copy( shadow.mapSize );
20027
20028			if ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {
20029
20030				if ( _shadowMapSize.x > maxTextureSize ) {
20031
20032					_viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );
20033					_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
20034					shadow.mapSize.x = _viewportSize.x;
20035
20036				}
20037
20038				if ( _shadowMapSize.y > maxTextureSize ) {
20039
20040					_viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );
20041					_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
20042					shadow.mapSize.y = _viewportSize.y;
20043
20044				}
20045
20046			}
20047
20048			if ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
20049
20050				var pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };
20051
20052				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
20053				shadow.map.texture.name = light.name + ".shadowMap";
20054
20055				shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
20056
20057				shadow.camera.updateProjectionMatrix();
20058
20059			}
20060
20061			if ( shadow.map === null ) {
20062
20063				var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };
20064
20065				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
20066				shadow.map.texture.name = light.name + ".shadowMap";
20067
20068				shadow.camera.updateProjectionMatrix();
20069
20070			}
20071
20072			_renderer.setRenderTarget( shadow.map );
20073			_renderer.clear();
20074
20075			var viewportCount = shadow.getViewportCount();
20076
20077			for ( var vp = 0; vp < viewportCount; vp ++ ) {
20078
20079				var viewport = shadow.getViewport( vp );
20080
20081				_viewport.set(
20082					_viewportSize.x * viewport.x,
20083					_viewportSize.y * viewport.y,
20084					_viewportSize.x * viewport.z,
20085					_viewportSize.y * viewport.w
20086				);
20087
20088				_state.viewport( _viewport );
20089
20090				shadow.updateMatrices( light, vp );
20091
20092				_frustum = shadow.getFrustum();
20093
20094				renderObject( scene, camera, shadow.camera, light, this.type );
20095
20096			}
20097
20098			// do blur pass for VSM
20099
20100			if ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {
20101
20102				VSMPass( shadow, camera );
20103
20104			}
20105
20106		}
20107
20108		scope.needsUpdate = false;
20109
20110		_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
20111
20112	};
20113
20114	function VSMPass( shadow, camera ) {
20115
20116		var geometry = _objects.update( fullScreenMesh );
20117
20118		// vertical pass
20119
20120		shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
20121		shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
20122		shadowMaterialVertical.uniforms.radius.value = shadow.radius;
20123		_renderer.setRenderTarget( shadow.mapPass );
20124		_renderer.clear();
20125		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
20126
20127		// horizonal pass
20128
20129		shadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;
20130		shadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;
20131		shadowMaterialHorizonal.uniforms.radius.value = shadow.radius;
20132		_renderer.setRenderTarget( shadow.map );
20133		_renderer.clear();
20134		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );
20135
20136	}
20137
20138	function getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {
20139
20140		var index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
20141
20142		var material = _depthMaterials[ index ];
20143
20144		if ( material === undefined ) {
20145
20146			material = new MeshDepthMaterial( {
20147
20148				depthPacking: RGBADepthPacking,
20149
20150				morphTargets: useMorphing,
20151				skinning: useSkinning
20152
20153			} );
20154
20155			_depthMaterials[ index ] = material;
20156
20157		}
20158
20159		return material;
20160
20161	}
20162
20163	function getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {
20164
20165		var index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;
20166
20167		var material = _distanceMaterials[ index ];
20168
20169		if ( material === undefined ) {
20170
20171			material = new MeshDistanceMaterial( {
20172
20173				morphTargets: useMorphing,
20174				skinning: useSkinning
20175
20176			} );
20177
20178			_distanceMaterials[ index ] = material;
20179
20180		}
20181
20182		return material;
20183
20184	}
20185
20186	function getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {
20187
20188		var result = null;
20189
20190		var getMaterialVariant = getDepthMaterialVariant;
20191		var customMaterial = object.customDepthMaterial;
20192
20193		if ( light.isPointLight === true ) {
20194
20195			getMaterialVariant = getDistanceMaterialVariant;
20196			customMaterial = object.customDistanceMaterial;
20197
20198		}
20199
20200		if ( customMaterial === undefined ) {
20201
20202			var useMorphing = false;
20203
20204			if ( material.morphTargets === true ) {
20205
20206				useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;
20207
20208			}
20209
20210			var useSkinning = false;
20211
20212			if ( object.isSkinnedMesh === true ) {
20213
20214				if ( material.skinning === true ) {
20215
20216					useSkinning = true;
20217
20218				} else {
20219
20220					console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );
20221
20222				}
20223
20224			}
20225
20226			var useInstancing = object.isInstancedMesh === true;
20227
20228			result = getMaterialVariant( useMorphing, useSkinning, useInstancing );
20229
20230		} else {
20231
20232			result = customMaterial;
20233
20234		}
20235
20236		if ( _renderer.localClippingEnabled &&
20237				material.clipShadows === true &&
20238				material.clippingPlanes.length !== 0 ) {
20239
20240			// in this case we need a unique material instance reflecting the
20241			// appropriate state
20242
20243			var keyA = result.uuid, keyB = material.uuid;
20244
20245			var materialsForVariant = _materialCache[ keyA ];
20246
20247			if ( materialsForVariant === undefined ) {
20248
20249				materialsForVariant = {};
20250				_materialCache[ keyA ] = materialsForVariant;
20251
20252			}
20253
20254			var cachedMaterial = materialsForVariant[ keyB ];
20255
20256			if ( cachedMaterial === undefined ) {
20257
20258				cachedMaterial = result.clone();
20259				materialsForVariant[ keyB ] = cachedMaterial;
20260
20261			}
20262
20263			result = cachedMaterial;
20264
20265		}
20266
20267		result.visible = material.visible;
20268		result.wireframe = material.wireframe;
20269
20270		if ( type === VSMShadowMap ) {
20271
20272			result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
20273
20274		} else {
20275
20276			result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
20277
20278		}
20279
20280		result.clipShadows = material.clipShadows;
20281		result.clippingPlanes = material.clippingPlanes;
20282		result.clipIntersection = material.clipIntersection;
20283
20284		result.wireframeLinewidth = material.wireframeLinewidth;
20285		result.linewidth = material.linewidth;
20286
20287		if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
20288
20289			result.referencePosition.setFromMatrixPosition( light.matrixWorld );
20290			result.nearDistance = shadowCameraNear;
20291			result.farDistance = shadowCameraFar;
20292
20293		}
20294
20295		return result;
20296
20297	}
20298
20299	function renderObject( object, camera, shadowCamera, light, type ) {
20300
20301		if ( object.visible === false ) return;
20302
20303		var visible = object.layers.test( camera.layers );
20304
20305		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
20306
20307			if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
20308
20309				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
20310
20311				var geometry = _objects.update( object );
20312				var material = object.material;
20313
20314				if ( Array.isArray( material ) ) {
20315
20316					var groups = geometry.groups;
20317
20318					for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
20319
20320						var group = groups[ k ];
20321						var groupMaterial = material[ group.materialIndex ];
20322
20323						if ( groupMaterial && groupMaterial.visible ) {
20324
20325							var depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
20326
20327							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
20328
20329						}
20330
20331					}
20332
20333				} else if ( material.visible ) {
20334
20335					var depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );
20336
20337					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
20338
20339				}
20340
20341			}
20342
20343		}
20344
20345		var children = object.children;
20346
20347		for ( var i = 0, l = children.length; i < l; i ++ ) {
20348
20349			renderObject( children[ i ], camera, shadowCamera, light, type );
20350
20351		}
20352
20353	}
20354
20355}
20356
20357/**
20358 * @author mrdoob / http://mrdoob.com/
20359 */
20360
20361function WebGLState( gl, extensions, capabilities ) {
20362
20363	var isWebGL2 = capabilities.isWebGL2;
20364
20365	function ColorBuffer() {
20366
20367		var locked = false;
20368
20369		var color = new Vector4();
20370		var currentColorMask = null;
20371		var currentColorClear = new Vector4( 0, 0, 0, 0 );
20372
20373		return {
20374
20375			setMask: function ( colorMask ) {
20376
20377				if ( currentColorMask !== colorMask && ! locked ) {
20378
20379					gl.colorMask( colorMask, colorMask, colorMask, colorMask );
20380					currentColorMask = colorMask;
20381
20382				}
20383
20384			},
20385
20386			setLocked: function ( lock ) {
20387
20388				locked = lock;
20389
20390			},
20391
20392			setClear: function ( r, g, b, a, premultipliedAlpha ) {
20393
20394				if ( premultipliedAlpha === true ) {
20395
20396					r *= a; g *= a; b *= a;
20397
20398				}
20399
20400				color.set( r, g, b, a );
20401
20402				if ( currentColorClear.equals( color ) === false ) {
20403
20404					gl.clearColor( r, g, b, a );
20405					currentColorClear.copy( color );
20406
20407				}
20408
20409			},
20410
20411			reset: function () {
20412
20413				locked = false;
20414
20415				currentColorMask = null;
20416				currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
20417
20418			}
20419
20420		};
20421
20422	}
20423
20424	function DepthBuffer() {
20425
20426		var locked = false;
20427
20428		var currentDepthMask = null;
20429		var currentDepthFunc = null;
20430		var currentDepthClear = null;
20431
20432		return {
20433
20434			setTest: function ( depthTest ) {
20435
20436				if ( depthTest ) {
20437
20438					enable( 2929 );
20439
20440				} else {
20441
20442					disable( 2929 );
20443
20444				}
20445
20446			},
20447
20448			setMask: function ( depthMask ) {
20449
20450				if ( currentDepthMask !== depthMask && ! locked ) {
20451
20452					gl.depthMask( depthMask );
20453					currentDepthMask = depthMask;
20454
20455				}
20456
20457			},
20458
20459			setFunc: function ( depthFunc ) {
20460
20461				if ( currentDepthFunc !== depthFunc ) {
20462
20463					if ( depthFunc ) {
20464
20465						switch ( depthFunc ) {
20466
20467							case NeverDepth:
20468
20469								gl.depthFunc( 512 );
20470								break;
20471
20472							case AlwaysDepth:
20473
20474								gl.depthFunc( 519 );
20475								break;
20476
20477							case LessDepth:
20478
20479								gl.depthFunc( 513 );
20480								break;
20481
20482							case LessEqualDepth:
20483
20484								gl.depthFunc( 515 );
20485								break;
20486
20487							case EqualDepth:
20488
20489								gl.depthFunc( 514 );
20490								break;
20491
20492							case GreaterEqualDepth:
20493
20494								gl.depthFunc( 518 );
20495								break;
20496
20497							case GreaterDepth:
20498
20499								gl.depthFunc( 516 );
20500								break;
20501
20502							case NotEqualDepth:
20503
20504								gl.depthFunc( 517 );
20505								break;
20506
20507							default:
20508
20509								gl.depthFunc( 515 );
20510
20511						}
20512
20513					} else {
20514
20515						gl.depthFunc( 515 );
20516
20517					}
20518
20519					currentDepthFunc = depthFunc;
20520
20521				}
20522
20523			},
20524
20525			setLocked: function ( lock ) {
20526
20527				locked = lock;
20528
20529			},
20530
20531			setClear: function ( depth ) {
20532
20533				if ( currentDepthClear !== depth ) {
20534
20535					gl.clearDepth( depth );
20536					currentDepthClear = depth;
20537
20538				}
20539
20540			},
20541
20542			reset: function () {
20543
20544				locked = false;
20545
20546				currentDepthMask = null;
20547				currentDepthFunc = null;
20548				currentDepthClear = null;
20549
20550			}
20551
20552		};
20553
20554	}
20555
20556	function StencilBuffer() {
20557
20558		var locked = false;
20559
20560		var currentStencilMask = null;
20561		var currentStencilFunc = null;
20562		var currentStencilRef = null;
20563		var currentStencilFuncMask = null;
20564		var currentStencilFail = null;
20565		var currentStencilZFail = null;
20566		var currentStencilZPass = null;
20567		var currentStencilClear = null;
20568
20569		return {
20570
20571			setTest: function ( stencilTest ) {
20572
20573				if ( ! locked ) {
20574
20575					if ( stencilTest ) {
20576
20577						enable( 2960 );
20578
20579					} else {
20580
20581						disable( 2960 );
20582
20583					}
20584
20585				}
20586
20587			},
20588
20589			setMask: function ( stencilMask ) {
20590
20591				if ( currentStencilMask !== stencilMask && ! locked ) {
20592
20593					gl.stencilMask( stencilMask );
20594					currentStencilMask = stencilMask;
20595
20596				}
20597
20598			},
20599
20600			setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
20601
20602				if ( currentStencilFunc !== stencilFunc ||
20603				     currentStencilRef 	!== stencilRef 	||
20604				     currentStencilFuncMask !== stencilMask ) {
20605
20606					gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
20607
20608					currentStencilFunc = stencilFunc;
20609					currentStencilRef = stencilRef;
20610					currentStencilFuncMask = stencilMask;
20611
20612				}
20613
20614			},
20615
20616			setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
20617
20618				if ( currentStencilFail	 !== stencilFail 	||
20619				     currentStencilZFail !== stencilZFail ||
20620				     currentStencilZPass !== stencilZPass ) {
20621
20622					gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
20623
20624					currentStencilFail = stencilFail;
20625					currentStencilZFail = stencilZFail;
20626					currentStencilZPass = stencilZPass;
20627
20628				}
20629
20630			},
20631
20632			setLocked: function ( lock ) {
20633
20634				locked = lock;
20635
20636			},
20637
20638			setClear: function ( stencil ) {
20639
20640				if ( currentStencilClear !== stencil ) {
20641
20642					gl.clearStencil( stencil );
20643					currentStencilClear = stencil;
20644
20645				}
20646
20647			},
20648
20649			reset: function () {
20650
20651				locked = false;
20652
20653				currentStencilMask = null;
20654				currentStencilFunc = null;
20655				currentStencilRef = null;
20656				currentStencilFuncMask = null;
20657				currentStencilFail = null;
20658				currentStencilZFail = null;
20659				currentStencilZPass = null;
20660				currentStencilClear = null;
20661
20662			}
20663
20664		};
20665
20666	}
20667
20668	//
20669
20670	var colorBuffer = new ColorBuffer();
20671	var depthBuffer = new DepthBuffer();
20672	var stencilBuffer = new StencilBuffer();
20673
20674	var maxVertexAttributes = gl.getParameter( 34921 );
20675	var newAttributes = new Uint8Array( maxVertexAttributes );
20676	var enabledAttributes = new Uint8Array( maxVertexAttributes );
20677	var attributeDivisors = new Uint8Array( maxVertexAttributes );
20678
20679	var enabledCapabilities = {};
20680
20681	var currentProgram = null;
20682
20683	var currentBlendingEnabled = null;
20684	var currentBlending = null;
20685	var currentBlendEquation = null;
20686	var currentBlendSrc = null;
20687	var currentBlendDst = null;
20688	var currentBlendEquationAlpha = null;
20689	var currentBlendSrcAlpha = null;
20690	var currentBlendDstAlpha = null;
20691	var currentPremultipledAlpha = false;
20692
20693	var currentFlipSided = null;
20694	var currentCullFace = null;
20695
20696	var currentLineWidth = null;
20697
20698	var currentPolygonOffsetFactor = null;
20699	var currentPolygonOffsetUnits = null;
20700
20701	var maxTextures = gl.getParameter( 35661 );
20702
20703	var lineWidthAvailable = false;
20704	var version = 0;
20705	var glVersion = gl.getParameter( 7938 );
20706
20707	if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
20708
20709		version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] );
20710		lineWidthAvailable = ( version >= 1.0 );
20711
20712	} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
20713
20714		version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
20715		lineWidthAvailable = ( version >= 2.0 );
20716
20717	}
20718
20719	var currentTextureSlot = null;
20720	var currentBoundTextures = {};
20721
20722	var currentScissor = new Vector4();
20723	var currentViewport = new Vector4();
20724
20725	function createTexture( type, target, count ) {
20726
20727		var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
20728		var texture = gl.createTexture();
20729
20730		gl.bindTexture( type, texture );
20731		gl.texParameteri( type, 10241, 9728 );
20732		gl.texParameteri( type, 10240, 9728 );
20733
20734		for ( var i = 0; i < count; i ++ ) {
20735
20736			gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
20737
20738		}
20739
20740		return texture;
20741
20742	}
20743
20744	var emptyTextures = {};
20745	emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
20746	emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
20747
20748	// init
20749
20750	colorBuffer.setClear( 0, 0, 0, 1 );
20751	depthBuffer.setClear( 1 );
20752	stencilBuffer.setClear( 0 );
20753
20754	enable( 2929 );
20755	depthBuffer.setFunc( LessEqualDepth );
20756
20757	setFlipSided( false );
20758	setCullFace( CullFaceBack );
20759	enable( 2884 );
20760
20761	setBlending( NoBlending );
20762
20763	//
20764
20765	function initAttributes() {
20766
20767		for ( var i = 0, l = newAttributes.length; i < l; i ++ ) {
20768
20769			newAttributes[ i ] = 0;
20770
20771		}
20772
20773	}
20774
20775	function enableAttribute( attribute ) {
20776
20777		enableAttributeAndDivisor( attribute, 0 );
20778
20779	}
20780
20781	function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
20782
20783		newAttributes[ attribute ] = 1;
20784
20785		if ( enabledAttributes[ attribute ] === 0 ) {
20786
20787			gl.enableVertexAttribArray( attribute );
20788			enabledAttributes[ attribute ] = 1;
20789
20790		}
20791
20792		if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
20793
20794			var extension = isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
20795
20796			extension[ isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
20797			attributeDivisors[ attribute ] = meshPerAttribute;
20798
20799		}
20800
20801	}
20802
20803	function disableUnusedAttributes() {
20804
20805		for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {
20806
20807			if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
20808
20809				gl.disableVertexAttribArray( i );
20810				enabledAttributes[ i ] = 0;
20811
20812			}
20813
20814		}
20815
20816	}
20817
20818	function vertexAttribPointer( index, size, type, normalized, stride, offset ) {
20819
20820		if ( isWebGL2 === true && ( type === 5124 || type === 5125 ) ) {
20821
20822			gl.vertexAttribIPointer( index, size, type, normalized, stride, offset );
20823
20824		} else {
20825
20826			gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
20827
20828		}
20829
20830	}
20831
20832	function enable( id ) {
20833
20834		if ( enabledCapabilities[ id ] !== true ) {
20835
20836			gl.enable( id );
20837			enabledCapabilities[ id ] = true;
20838
20839		}
20840
20841	}
20842
20843	function disable( id ) {
20844
20845		if ( enabledCapabilities[ id ] !== false ) {
20846
20847			gl.disable( id );
20848			enabledCapabilities[ id ] = false;
20849
20850		}
20851
20852	}
20853
20854	function useProgram( program ) {
20855
20856		if ( currentProgram !== program ) {
20857
20858			gl.useProgram( program );
20859
20860			currentProgram = program;
20861
20862			return true;
20863
20864		}
20865
20866		return false;
20867
20868	}
20869
20870	var equationToGL = {
20871		[ AddEquation ]: 32774,
20872		[ SubtractEquation ]: 32778,
20873		[ ReverseSubtractEquation ]: 32779
20874	};
20875
20876	if ( isWebGL2 ) {
20877
20878		equationToGL[ MinEquation ] = 32775;
20879		equationToGL[ MaxEquation ] = 32776;
20880
20881	} else {
20882
20883		var extension = extensions.get( 'EXT_blend_minmax' );
20884
20885		if ( extension !== null ) {
20886
20887			equationToGL[ MinEquation ] = extension.MIN_EXT;
20888			equationToGL[ MaxEquation ] = extension.MAX_EXT;
20889
20890		}
20891
20892	}
20893
20894	var factorToGL = {
20895		[ ZeroFactor ]: 0,
20896		[ OneFactor ]: 1,
20897		[ SrcColorFactor ]: 768,
20898		[ SrcAlphaFactor ]: 770,
20899		[ SrcAlphaSaturateFactor ]: 776,
20900		[ DstColorFactor ]: 774,
20901		[ DstAlphaFactor ]: 772,
20902		[ OneMinusSrcColorFactor ]: 769,
20903		[ OneMinusSrcAlphaFactor ]: 771,
20904		[ OneMinusDstColorFactor ]: 775,
20905		[ OneMinusDstAlphaFactor ]: 773
20906	};
20907
20908	function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
20909
20910		if ( blending === NoBlending ) {
20911
20912			if ( currentBlendingEnabled ) {
20913
20914				disable( 3042 );
20915				currentBlendingEnabled = false;
vendor: 62,457 bytes, lines 20916-23546
20916
20917			}
20918
20919			return;
20920
20921		}
20922
20923		if ( ! currentBlendingEnabled ) {
20924
20925			enable( 3042 );
20926			currentBlendingEnabled = true;
20927
20928		}
20929
20930		if ( blending !== CustomBlending ) {
20931
20932			if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
20933
20934				if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
20935
20936					gl.blendEquation( 32774 );
20937
20938					currentBlendEquation = AddEquation;
20939					currentBlendEquationAlpha = AddEquation;
20940
20941				}
20942
20943				if ( premultipliedAlpha ) {
20944
20945					switch ( blending ) {
20946
20947						case NormalBlending:
20948							gl.blendFuncSeparate( 1, 771, 1, 771 );
20949							break;
20950
20951						case AdditiveBlending:
20952							gl.blendFunc( 1, 1 );
20953							break;
20954
20955						case SubtractiveBlending:
20956							gl.blendFuncSeparate( 0, 0, 769, 771 );
20957							break;
20958
20959						case MultiplyBlending:
20960							gl.blendFuncSeparate( 0, 768, 0, 770 );
20961							break;
20962
20963						default:
20964							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
20965							break;
20966
20967					}
20968
20969				} else {
20970
20971					switch ( blending ) {
20972
20973						case NormalBlending:
20974							gl.blendFuncSeparate( 770, 771, 1, 771 );
20975							break;
20976
20977						case AdditiveBlending:
20978							gl.blendFunc( 770, 1 );
20979							break;
20980
20981						case SubtractiveBlending:
20982							gl.blendFunc( 0, 769 );
20983							break;
20984
20985						case MultiplyBlending:
20986							gl.blendFunc( 0, 768 );
20987							break;
20988
20989						default:
20990							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
20991							break;
20992
20993					}
20994
20995				}
20996
20997				currentBlendSrc = null;
20998				currentBlendDst = null;
20999				currentBlendSrcAlpha = null;
21000				currentBlendDstAlpha = null;
21001
21002				currentBlending = blending;
21003				currentPremultipledAlpha = premultipliedAlpha;
21004
21005			}
21006
21007			return;
21008
21009		}
21010
21011		// custom blending
21012
21013		blendEquationAlpha = blendEquationAlpha || blendEquation;
21014		blendSrcAlpha = blendSrcAlpha || blendSrc;
21015		blendDstAlpha = blendDstAlpha || blendDst;
21016
21017		if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
21018
21019			gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
21020
21021			currentBlendEquation = blendEquation;
21022			currentBlendEquationAlpha = blendEquationAlpha;
21023
21024		}
21025
21026		if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
21027
21028			gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
21029
21030			currentBlendSrc = blendSrc;
21031			currentBlendDst = blendDst;
21032			currentBlendSrcAlpha = blendSrcAlpha;
21033			currentBlendDstAlpha = blendDstAlpha;
21034
21035		}
21036
21037		currentBlending = blending;
21038		currentPremultipledAlpha = null;
21039
21040	}
21041
21042	function setMaterial( material, frontFaceCW ) {
21043
21044		material.side === DoubleSide
21045			? disable( 2884 )
21046			: enable( 2884 );
21047
21048		var flipSided = ( material.side === BackSide );
21049		if ( frontFaceCW ) flipSided = ! flipSided;
21050
21051		setFlipSided( flipSided );
21052
21053		( material.blending === NormalBlending && material.transparent === false )
21054			? setBlending( NoBlending )
21055			: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
21056
21057		depthBuffer.setFunc( material.depthFunc );
21058		depthBuffer.setTest( material.depthTest );
21059		depthBuffer.setMask( material.depthWrite );
21060		colorBuffer.setMask( material.colorWrite );
21061
21062		var stencilWrite = material.stencilWrite;
21063		stencilBuffer.setTest( stencilWrite );
21064		if ( stencilWrite ) {
21065
21066			stencilBuffer.setMask( material.stencilWriteMask );
21067			stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
21068			stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
21069
21070		}
21071
21072		setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
21073
21074	}
21075
21076	//
21077
21078	function setFlipSided( flipSided ) {
21079
21080		if ( currentFlipSided !== flipSided ) {
21081
21082			if ( flipSided ) {
21083
21084				gl.frontFace( 2304 );
21085
21086			} else {
21087
21088				gl.frontFace( 2305 );
21089
21090			}
21091
21092			currentFlipSided = flipSided;
21093
21094		}
21095
21096	}
21097
21098	function setCullFace( cullFace ) {
21099
21100		if ( cullFace !== CullFaceNone ) {
21101
21102			enable( 2884 );
21103
21104			if ( cullFace !== currentCullFace ) {
21105
21106				if ( cullFace === CullFaceBack ) {
21107
21108					gl.cullFace( 1029 );
21109
21110				} else if ( cullFace === CullFaceFront ) {
21111
21112					gl.cullFace( 1028 );
21113
21114				} else {
21115
21116					gl.cullFace( 1032 );
21117
21118				}
21119
21120			}
21121
21122		} else {
21123
21124			disable( 2884 );
21125
21126		}
21127
21128		currentCullFace = cullFace;
21129
21130	}
21131
21132	function setLineWidth( width ) {
21133
21134		if ( width !== currentLineWidth ) {
21135
21136			if ( lineWidthAvailable ) gl.lineWidth( width );
21137
21138			currentLineWidth = width;
21139
21140		}
21141
21142	}
21143
21144	function setPolygonOffset( polygonOffset, factor, units ) {
21145
21146		if ( polygonOffset ) {
21147
21148			enable( 32823 );
21149
21150			if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
21151
21152				gl.polygonOffset( factor, units );
21153
21154				currentPolygonOffsetFactor = factor;
21155				currentPolygonOffsetUnits = units;
21156
21157			}
21158
21159		} else {
21160
21161			disable( 32823 );
21162
21163		}
21164
21165	}
21166
21167	function setScissorTest( scissorTest ) {
21168
21169		if ( scissorTest ) {
21170
21171			enable( 3089 );
21172
21173		} else {
21174
21175			disable( 3089 );
21176
21177		}
21178
21179	}
21180
21181	// texture
21182
21183	function activeTexture( webglSlot ) {
21184
21185		if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
21186
21187		if ( currentTextureSlot !== webglSlot ) {
21188
21189			gl.activeTexture( webglSlot );
21190			currentTextureSlot = webglSlot;
21191
21192		}
21193
21194	}
21195
21196	function bindTexture( webglType, webglTexture ) {
21197
21198		if ( currentTextureSlot === null ) {
21199
21200			activeTexture();
21201
21202		}
21203
21204		var boundTexture = currentBoundTextures[ currentTextureSlot ];
21205
21206		if ( boundTexture === undefined ) {
21207
21208			boundTexture = { type: undefined, texture: undefined };
21209			currentBoundTextures[ currentTextureSlot ] = boundTexture;
21210
21211		}
21212
21213		if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
21214
21215			gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
21216
21217			boundTexture.type = webglType;
21218			boundTexture.texture = webglTexture;
21219
21220		}
21221
21222	}
21223
21224	function unbindTexture() {
21225
21226		var boundTexture = currentBoundTextures[ currentTextureSlot ];
21227
21228		if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
21229
21230			gl.bindTexture( boundTexture.type, null );
21231
21232			boundTexture.type = undefined;
21233			boundTexture.texture = undefined;
21234
21235		}
21236
21237	}
21238
21239	function compressedTexImage2D() {
21240
21241		try {
21242
21243			gl.compressedTexImage2D.apply( gl, arguments );
21244
21245		} catch ( error ) {
21246
21247			console.error( 'THREE.WebGLState:', error );
21248
21249		}
21250
21251	}
21252
21253	function texImage2D() {
21254
21255		try {
21256
21257			gl.texImage2D.apply( gl, arguments );
21258
21259		} catch ( error ) {
21260
21261			console.error( 'THREE.WebGLState:', error );
21262
21263		}
21264
21265	}
21266
21267	function texImage3D() {
21268
21269		try {
21270
21271			gl.texImage3D.apply( gl, arguments );
21272
21273		} catch ( error ) {
21274
21275			console.error( 'THREE.WebGLState:', error );
21276
21277		}
21278
21279	}
21280
21281	//
21282
21283	function scissor( scissor ) {
21284
21285		if ( currentScissor.equals( scissor ) === false ) {
21286
21287			gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
21288			currentScissor.copy( scissor );
21289
21290		}
21291
21292	}
21293
21294	function viewport( viewport ) {
21295
21296		if ( currentViewport.equals( viewport ) === false ) {
21297
21298			gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
21299			currentViewport.copy( viewport );
21300
21301		}
21302
21303	}
21304
21305	//
21306
21307	function reset() {
21308
21309		for ( var i = 0; i < enabledAttributes.length; i ++ ) {
21310
21311			if ( enabledAttributes[ i ] === 1 ) {
21312
21313				gl.disableVertexAttribArray( i );
21314				enabledAttributes[ i ] = 0;
21315
21316			}
21317
21318		}
21319
21320		enabledCapabilities = {};
21321
21322		currentTextureSlot = null;
21323		currentBoundTextures = {};
21324
21325		currentProgram = null;
21326
21327		currentBlending = null;
21328
21329		currentFlipSided = null;
21330		currentCullFace = null;
21331
21332		colorBuffer.reset();
21333		depthBuffer.reset();
21334		stencilBuffer.reset();
21335
21336	}
21337
21338	return {
21339
21340		buffers: {
21341			color: colorBuffer,
21342			depth: depthBuffer,
21343			stencil: stencilBuffer
21344		},
21345
21346		initAttributes: initAttributes,
21347		enableAttribute: enableAttribute,
21348		enableAttributeAndDivisor: enableAttributeAndDivisor,
21349		disableUnusedAttributes: disableUnusedAttributes,
21350		vertexAttribPointer: vertexAttribPointer,
21351		enable: enable,
21352		disable: disable,
21353
21354		useProgram: useProgram,
21355
21356		setBlending: setBlending,
21357		setMaterial: setMaterial,
21358
21359		setFlipSided: setFlipSided,
21360		setCullFace: setCullFace,
21361
21362		setLineWidth: setLineWidth,
21363		setPolygonOffset: setPolygonOffset,
21364
21365		setScissorTest: setScissorTest,
21366
21367		activeTexture: activeTexture,
21368		bindTexture: bindTexture,
21369		unbindTexture: unbindTexture,
21370		compressedTexImage2D: compressedTexImage2D,
21371		texImage2D: texImage2D,
21372		texImage3D: texImage3D,
21373
21374		scissor: scissor,
21375		viewport: viewport,
21376
21377		reset: reset
21378
21379	};
21380
21381}
21382
21383/**
21384 * @author mrdoob / http://mrdoob.com/
21385 */
21386
21387function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
21388
21389	var isWebGL2 = capabilities.isWebGL2;
21390	var maxTextures = capabilities.maxTextures;
21391	var maxCubemapSize = capabilities.maxCubemapSize;
21392	var maxTextureSize = capabilities.maxTextureSize;
21393	var maxSamples = capabilities.maxSamples;
21394
21395	var _videoTextures = new WeakMap();
21396	var _canvas;
21397
21398	// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
21399	// also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
21400	// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
21401
21402	var useOffscreenCanvas = false;
21403
21404	try {
21405
21406		useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
21407			&& ( new OffscreenCanvas( 1, 1 ).getContext( "2d" ) ) !== null;
21408
21409	} catch ( err ) {
21410
21411		// Ignore any errors
21412
21413	}
21414
21415	function createCanvas( width, height ) {
21416
21417		// Use OffscreenCanvas when available. Specially needed in web workers
21418
21419		return useOffscreenCanvas ?
21420			new OffscreenCanvas( width, height ) :
21421			document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );
21422
21423	}
21424
21425	function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
21426
21427		var scale = 1;
21428
21429		// handle case if texture exceeds max size
21430
21431		if ( image.width > maxSize || image.height > maxSize ) {
21432
21433			scale = maxSize / Math.max( image.width, image.height );
21434
21435		}
21436
21437		// only perform resize if necessary
21438
21439		if ( scale < 1 || needsPowerOfTwo === true ) {
21440
21441			// only perform resize for certain image types
21442
21443			if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
21444				( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
21445				( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
21446
21447				var floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor;
21448
21449				var width = floor( scale * image.width );
21450				var height = floor( scale * image.height );
21451
21452				if ( _canvas === undefined ) _canvas = createCanvas( width, height );
21453
21454				// cube textures can't reuse the same canvas
21455
21456				var canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
21457
21458				canvas.width = width;
21459				canvas.height = height;
21460
21461				var context = canvas.getContext( '2d' );
21462				context.drawImage( image, 0, 0, width, height );
21463
21464				console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
21465
21466				return canvas;
21467
21468			} else {
21469
21470				if ( 'data' in image ) {
21471
21472					console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
21473
21474				}
21475
21476				return image;
21477
21478			}
21479
21480		}
21481
21482		return image;
21483
21484	}
21485
21486	function isPowerOfTwo( image ) {
21487
21488		return MathUtils.isPowerOfTwo( image.width ) && MathUtils.isPowerOfTwo( image.height );
21489
21490	}
21491
21492	function textureNeedsPowerOfTwo( texture ) {
21493
21494		if ( isWebGL2 ) return false;
21495
21496		return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
21497			( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
21498
21499	}
21500
21501	function textureNeedsGenerateMipmaps( texture, supportsMips ) {
21502
21503		return texture.generateMipmaps && supportsMips &&
21504			texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
21505
21506	}
21507
21508	function generateMipmap( target, texture, width, height ) {
21509
21510		_gl.generateMipmap( target );
21511
21512		var textureProperties = properties.get( texture );
21513
21514		// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11
21515		textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;
21516
21517	}
21518
21519	function getInternalFormat( internalFormatName, glFormat, glType ) {
21520
21521		if ( isWebGL2 === false ) return glFormat;
21522
21523		if ( internalFormatName !== null ) {
21524
21525			if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
21526
21527			console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
21528
21529		}
21530
21531		var internalFormat = glFormat;
21532
21533		if ( glFormat === 6403 ) {
21534
21535			if ( glType === 5126 ) internalFormat = 33326;
21536			if ( glType === 5131 ) internalFormat = 33325;
21537			if ( glType === 5121 ) internalFormat = 33321;
21538
21539		}
21540
21541		if ( glFormat === 6407 ) {
21542
21543			if ( glType === 5126 ) internalFormat = 34837;
21544			if ( glType === 5131 ) internalFormat = 34843;
21545			if ( glType === 5121 ) internalFormat = 32849;
21546
21547		}
21548
21549		if ( glFormat === 6408 ) {
21550
21551			if ( glType === 5126 ) internalFormat = 34836;
21552			if ( glType === 5131 ) internalFormat = 34842;
21553			if ( glType === 5121 ) internalFormat = 32856;
21554
21555		}
21556
21557		if ( internalFormat === 33325 || internalFormat === 33326 ||
21558			internalFormat === 34842 || internalFormat === 34836 ) {
21559
21560			extensions.get( 'EXT_color_buffer_float' );
21561
21562		}
21563
21564		return internalFormat;
21565
21566	}
21567
21568	// Fallback filters for non-power-of-2 textures
21569
21570	function filterFallback( f ) {
21571
21572		if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {
21573
21574			return 9728;
21575
21576		}
21577
21578		return 9729;
21579
21580	}
21581
21582	//
21583
21584	function onTextureDispose( event ) {
21585
21586		var texture = event.target;
21587
21588		texture.removeEventListener( 'dispose', onTextureDispose );
21589
21590		deallocateTexture( texture );
21591
21592		if ( texture.isVideoTexture ) {
21593
21594			_videoTextures.delete( texture );
21595
21596		}
21597
21598		info.memory.textures --;
21599
21600	}
21601
21602	function onRenderTargetDispose( event ) {
21603
21604		var renderTarget = event.target;
21605
21606		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
21607
21608		deallocateRenderTarget( renderTarget );
21609
21610		info.memory.textures --;
21611
21612	}
21613
21614	//
21615
21616	function deallocateTexture( texture ) {
21617
21618		var textureProperties = properties.get( texture );
21619
21620		if ( textureProperties.__webglInit === undefined ) return;
21621
21622		_gl.deleteTexture( textureProperties.__webglTexture );
21623
21624		properties.remove( texture );
21625
21626	}
21627
21628	function deallocateRenderTarget( renderTarget ) {
21629
21630		var renderTargetProperties = properties.get( renderTarget );
21631		var textureProperties = properties.get( renderTarget.texture );
21632
21633		if ( ! renderTarget ) return;
21634
21635		if ( textureProperties.__webglTexture !== undefined ) {
21636
21637			_gl.deleteTexture( textureProperties.__webglTexture );
21638
21639		}
21640
21641		if ( renderTarget.depthTexture ) {
21642
21643			renderTarget.depthTexture.dispose();
21644
21645		}
21646
21647		if ( renderTarget.isWebGLCubeRenderTarget ) {
21648
21649			for ( var i = 0; i < 6; i ++ ) {
21650
21651				_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
21652				if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
21653
21654			}
21655
21656		} else {
21657
21658			_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
21659			if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
21660			if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
21661			if ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );
21662			if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
21663
21664		}
21665
21666		properties.remove( renderTarget.texture );
21667		properties.remove( renderTarget );
21668
21669	}
21670
21671	//
21672
21673	var textureUnits = 0;
21674
21675	function resetTextureUnits() {
21676
21677		textureUnits = 0;
21678
21679	}
21680
21681	function allocateTextureUnit() {
21682
21683		var textureUnit = textureUnits;
21684
21685		if ( textureUnit >= maxTextures ) {
21686
21687			console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );
21688
21689		}
21690
21691		textureUnits += 1;
21692
21693		return textureUnit;
21694
21695	}
21696
21697	//
21698
21699	function setTexture2D( texture, slot ) {
21700
21701		var textureProperties = properties.get( texture );
21702
21703		if ( texture.isVideoTexture ) updateVideoTexture( texture );
21704
21705		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
21706
21707			var image = texture.image;
21708
21709			if ( image === undefined ) {
21710
21711				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );
21712
21713			} else if ( image.complete === false ) {
21714
21715				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
21716
21717			} else {
21718
21719				uploadTexture( textureProperties, texture, slot );
21720				return;
21721
21722			}
21723
21724		}
21725
21726		state.activeTexture( 33984 + slot );
21727		state.bindTexture( 3553, textureProperties.__webglTexture );
21728
21729	}
21730
21731	function setTexture2DArray( texture, slot ) {
21732
21733		var textureProperties = properties.get( texture );
21734
21735		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
21736
21737			uploadTexture( textureProperties, texture, slot );
21738			return;
21739
21740		}
21741
21742		state.activeTexture( 33984 + slot );
21743		state.bindTexture( 35866, textureProperties.__webglTexture );
21744
21745	}
21746
21747	function setTexture3D( texture, slot ) {
21748
21749		var textureProperties = properties.get( texture );
21750
21751		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
21752
21753			uploadTexture( textureProperties, texture, slot );
21754			return;
21755
21756		}
21757
21758		state.activeTexture( 33984 + slot );
21759		state.bindTexture( 32879, textureProperties.__webglTexture );
21760
21761	}
21762
21763	function setTextureCube( texture, slot ) {
21764
21765		if ( texture.image.length !== 6 ) return;
21766
21767		var textureProperties = properties.get( texture );
21768
21769		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
21770
21771			initTexture( textureProperties, texture );
21772
21773			state.activeTexture( 33984 + slot );
21774			state.bindTexture( 34067, textureProperties.__webglTexture );
21775
21776			_gl.pixelStorei( 37440, texture.flipY );
21777
21778			var isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );
21779			var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
21780
21781			var cubeImage = [];
21782
21783			for ( var i = 0; i < 6; i ++ ) {
21784
21785				if ( ! isCompressed && ! isDataTexture ) {
21786
21787					cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
21788
21789				} else {
21790
21791					cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
21792
21793				}
21794
21795			}
21796
21797			var image = cubeImage[ 0 ],
21798				supportsMips = isPowerOfTwo( image ) || isWebGL2,
21799				glFormat = utils.convert( texture.format ),
21800				glType = utils.convert( texture.type ),
21801				glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
21802
21803			setTextureParameters( 34067, texture, supportsMips );
21804
21805			var mipmaps;
21806
21807			if ( isCompressed ) {
21808
21809				for ( var i = 0; i < 6; i ++ ) {
21810
21811					mipmaps = cubeImage[ i ].mipmaps;
21812
21813					for ( var j = 0; j < mipmaps.length; j ++ ) {
21814
21815						var mipmap = mipmaps[ j ];
21816
21817						if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
21818
21819							if ( glFormat !== null ) {
21820
21821								state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
21822
21823							} else {
21824
21825								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
21826
21827							}
21828
21829						} else {
21830
21831							state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
21832
21833						}
21834
21835					}
21836
21837				}
21838
21839				textureProperties.__maxMipLevel = mipmaps.length - 1;
21840
21841			} else {
21842
21843				mipmaps = texture.mipmaps;
21844
21845				for ( var i = 0; i < 6; i ++ ) {
21846
21847					if ( isDataTexture ) {
21848
21849						state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
21850
21851						for ( var j = 0; j < mipmaps.length; j ++ ) {
21852
21853							var mipmap = mipmaps[ j ];
21854							var mipmapImage = mipmap.image[ i ].image;
21855
21856							state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
21857
21858						}
21859
21860					} else {
21861
21862						state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
21863
21864						for ( var j = 0; j < mipmaps.length; j ++ ) {
21865
21866							var mipmap = mipmaps[ j ];
21867
21868							state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
21869
21870						}
21871
21872					}
21873
21874				}
21875
21876				textureProperties.__maxMipLevel = mipmaps.length;
21877
21878			}
21879
21880			if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
21881
21882				// We assume images for cube map have the same size.
21883				generateMipmap( 34067, texture, image.width, image.height );
21884
21885			}
21886
21887			textureProperties.__version = texture.version;
21888
21889			if ( texture.onUpdate ) texture.onUpdate( texture );
21890
21891		} else {
21892
21893			state.activeTexture( 33984 + slot );
21894			state.bindTexture( 34067, textureProperties.__webglTexture );
21895
21896		}
21897
21898	}
21899
21900	function setTextureCubeDynamic( texture, slot ) {
21901
21902		state.activeTexture( 33984 + slot );
21903		state.bindTexture( 34067, properties.get( texture ).__webglTexture );
21904
21905	}
21906
21907	var wrappingToGL = {
21908		[ RepeatWrapping ]: 10497,
21909		[ ClampToEdgeWrapping ]: 33071,
21910		[ MirroredRepeatWrapping ]: 33648
21911	};
21912
21913	var filterToGL = {
21914		[ NearestFilter ]: 9728,
21915		[ NearestMipmapNearestFilter ]: 9984,
21916		[ NearestMipmapLinearFilter ]: 9986,
21917
21918		[ LinearFilter ]: 9729,
21919		[ LinearMipmapNearestFilter ]: 9985,
21920		[ LinearMipmapLinearFilter ]: 9987
21921	};
21922
21923	function setTextureParameters( textureType, texture, supportsMips ) {
21924
21925		if ( supportsMips ) {
21926
21927			_gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );
21928			_gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );
21929
21930			if ( textureType === 32879 || textureType === 35866 ) {
21931
21932				_gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );
21933
21934			}
21935
21936			_gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );
21937			_gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );
21938
21939		} else {
21940
21941			_gl.texParameteri( textureType, 10242, 33071 );
21942			_gl.texParameteri( textureType, 10243, 33071 );
21943
21944			if ( textureType === 32879 || textureType === 35866 ) {
21945
21946				_gl.texParameteri( textureType, 32882, 33071 );
21947
21948			}
21949
21950			if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
21951
21952				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
21953
21954			}
21955
21956			_gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
21957			_gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
21958
21959			if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
21960
21961				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
21962
21963			}
21964
21965		}
21966
21967		var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
21968
21969		if ( extension ) {
21970
21971			if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
21972			if ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
21973
21974			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
21975
21976				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
21977				properties.get( texture ).__currentAnisotropy = texture.anisotropy;
21978
21979			}
21980
21981		}
21982
21983	}
21984
21985	function initTexture( textureProperties, texture ) {
21986
21987		if ( textureProperties.__webglInit === undefined ) {
21988
21989			textureProperties.__webglInit = true;
21990
21991			texture.addEventListener( 'dispose', onTextureDispose );
21992
21993			textureProperties.__webglTexture = _gl.createTexture();
21994
21995			info.memory.textures ++;
21996
21997		}
21998
21999	}
22000
22001	function uploadTexture( textureProperties, texture, slot ) {
22002
22003		var textureType = 3553;
22004
22005		if ( texture.isDataTexture2DArray ) textureType = 35866;
22006		if ( texture.isDataTexture3D ) textureType = 32879;
22007
22008		initTexture( textureProperties, texture );
22009
22010		state.activeTexture( 33984 + slot );
22011		state.bindTexture( textureType, textureProperties.__webglTexture );
22012
22013		_gl.pixelStorei( 37440, texture.flipY );
22014		_gl.pixelStorei( 37441, texture.premultiplyAlpha );
22015		_gl.pixelStorei( 3317, texture.unpackAlignment );
22016
22017		var needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;
22018		var image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
22019
22020		var supportsMips = isPowerOfTwo( image ) || isWebGL2,
22021			glFormat = utils.convert( texture.format ),
22022			glType = utils.convert( texture.type ),
22023			glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );
22024
22025		setTextureParameters( textureType, texture, supportsMips );
22026
22027		var mipmap, mipmaps = texture.mipmaps;
22028
22029		if ( texture.isDepthTexture ) {
22030
22031			// populate depth texture with dummy data
22032
22033			glInternalFormat = 6402;
22034
22035			if ( isWebGL2 ) {
22036
22037				if ( texture.type === FloatType ) {
22038
22039					glInternalFormat = 36012;
22040
22041				} else if ( texture.type === UnsignedIntType ) {
22042
22043					glInternalFormat = 33190;
22044
22045				} else if ( texture.type === UnsignedInt248Type ) {
22046
22047					glInternalFormat = 35056;
22048
22049				} else {
22050
22051					glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D
22052
22053				}
22054
22055			} else {
22056
22057				if ( texture.type === FloatType ) {
22058
22059					console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
22060
22061				}
22062
22063			}
22064
22065			// validation checks for WebGL 1
22066
22067			if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
22068
22069				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
22070				// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
22071				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
22072				if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
22073
22074					console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
22075
22076					texture.type = UnsignedShortType;
22077					glType = utils.convert( texture.type );
22078
22079				}
22080
22081			}
22082
22083			if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) {
22084
22085				// Depth stencil textures need the DEPTH_STENCIL internal format
22086				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
22087				glInternalFormat = 34041;
22088
22089				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
22090				// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
22091				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
22092				if ( texture.type !== UnsignedInt248Type ) {
22093
22094					console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
22095
22096					texture.type = UnsignedInt248Type;
22097					glType = utils.convert( texture.type );
22098
22099				}
22100
22101			}
22102
22103			//
22104
22105			state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
22106
22107		} else if ( texture.isDataTexture ) {
22108
22109			// use manually created mipmaps if available
22110			// if there are no manual mipmaps
22111			// set 0 level mipmap and then use GL to generate other mipmap levels
22112
22113			if ( mipmaps.length > 0 && supportsMips ) {
22114
22115				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
22116
22117					mipmap = mipmaps[ i ];
22118					state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
22119
22120				}
22121
22122				texture.generateMipmaps = false;
22123				textureProperties.__maxMipLevel = mipmaps.length - 1;
22124
22125			} else {
22126
22127				state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
22128				textureProperties.__maxMipLevel = 0;
22129
22130			}
22131
22132		} else if ( texture.isCompressedTexture ) {
22133
22134			for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
22135
22136				mipmap = mipmaps[ i ];
22137
22138				if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {
22139
22140					if ( glFormat !== null ) {
22141
22142						state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
22143
22144					} else {
22145
22146						console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
22147
22148					}
22149
22150				} else {
22151
22152					state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
22153
22154				}
22155
22156			}
22157
22158			textureProperties.__maxMipLevel = mipmaps.length - 1;
22159
22160		} else if ( texture.isDataTexture2DArray ) {
22161
22162			state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
22163			textureProperties.__maxMipLevel = 0;
22164
22165		} else if ( texture.isDataTexture3D ) {
22166
22167			state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
22168			textureProperties.__maxMipLevel = 0;
22169
22170		} else {
22171
22172			// regular Texture (image, video, canvas)
22173
22174			// use manually created mipmaps if available
22175			// if there are no manual mipmaps
22176			// set 0 level mipmap and then use GL to generate other mipmap levels
22177
22178			if ( mipmaps.length > 0 && supportsMips ) {
22179
22180				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
22181
22182					mipmap = mipmaps[ i ];
22183					state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
22184
22185				}
22186
22187				texture.generateMipmaps = false;
22188				textureProperties.__maxMipLevel = mipmaps.length - 1;
22189
22190			} else {
22191
22192				state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
22193				textureProperties.__maxMipLevel = 0;
22194
22195			}
22196
22197		}
22198
22199		if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
22200
22201			generateMipmap( textureType, texture, image.width, image.height );
22202
22203		}
22204
22205		textureProperties.__version = texture.version;
22206
22207		if ( texture.onUpdate ) texture.onUpdate( texture );
22208
22209	}
22210
22211	// Render targets
22212
22213	// Setup storage for target texture and bind it to correct framebuffer
22214	function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {
22215
22216		var glFormat = utils.convert( renderTarget.texture.format );
22217		var glType = utils.convert( renderTarget.texture.type );
22218		var glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
22219		state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
22220		_gl.bindFramebuffer( 36160, framebuffer );
22221		_gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
22222		_gl.bindFramebuffer( 36160, null );
22223
22224	}
22225
22226	// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
22227	function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
22228
22229		_gl.bindRenderbuffer( 36161, renderbuffer );
22230
22231		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
22232
22233			var glInternalFormat = 33189;
22234
22235			if ( isMultisample ) {
22236
22237				var depthTexture = renderTarget.depthTexture;
22238
22239				if ( depthTexture && depthTexture.isDepthTexture ) {
22240
22241					if ( depthTexture.type === FloatType ) {
22242
22243						glInternalFormat = 36012;
22244
22245					} else if ( depthTexture.type === UnsignedIntType ) {
22246
22247						glInternalFormat = 33190;
22248
22249					}
22250
22251				}
22252
22253				var samples = getRenderTargetSamples( renderTarget );
22254
22255				_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
22256
22257			} else {
22258
22259				_gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
22260
22261			}
22262
22263			_gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
22264
22265		} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
22266
22267			if ( isMultisample ) {
22268
22269				var samples = getRenderTargetSamples( renderTarget );
22270
22271				_gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );
22272
22273			} else {
22274
22275				_gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
22276
22277			}
22278
22279
22280			_gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
22281
22282		} else {
22283
22284			var glFormat = utils.convert( renderTarget.texture.format );
22285			var glType = utils.convert( renderTarget.texture.type );
22286			var glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
22287
22288			if ( isMultisample ) {
22289
22290				var samples = getRenderTargetSamples( renderTarget );
22291
22292				_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
22293
22294			} else {
22295
22296				_gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
22297
22298			}
22299
22300		}
22301
22302		_gl.bindRenderbuffer( 36161, null );
22303
22304	}
22305
22306	// Setup resources for a Depth Texture for a FBO (needs an extension)
22307	function setupDepthTexture( framebuffer, renderTarget ) {
22308
22309		var isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
22310		if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
22311
22312		_gl.bindFramebuffer( 36160, framebuffer );
22313
22314		if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
22315
22316			throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
22317
22318		}
22319
22320		// upload an empty depth texture with framebuffer size
22321		if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
22322				renderTarget.depthTexture.image.width !== renderTarget.width ||
22323				renderTarget.depthTexture.image.height !== renderTarget.height ) {
22324
22325			renderTarget.depthTexture.image.width = renderTarget.width;
22326			renderTarget.depthTexture.image.height = renderTarget.height;
22327			renderTarget.depthTexture.needsUpdate = true;
22328
22329		}
22330
22331		setTexture2D( renderTarget.depthTexture, 0 );
22332
22333		var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
22334
22335		if ( renderTarget.depthTexture.format === DepthFormat ) {
22336
22337			_gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
22338
22339		} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
22340
22341			_gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
22342
22343		} else {
22344
22345			throw new Error( 'Unknown depthTexture format' );
22346
22347		}
22348
22349	}
22350
22351	// Setup GL resources for a non-texture depth buffer
22352	function setupDepthRenderbuffer( renderTarget ) {
22353
22354		var renderTargetProperties = properties.get( renderTarget );
22355
22356		var isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
22357
22358		if ( renderTarget.depthTexture ) {
22359
22360			if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
22361
22362			setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
22363
22364		} else {
22365
22366			if ( isCube ) {
22367
22368				renderTargetProperties.__webglDepthbuffer = [];
22369
22370				for ( var i = 0; i < 6; i ++ ) {
22371
22372					_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
22373					renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
22374					setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
22375
22376				}
22377
22378			} else {
22379
22380				_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
22381				renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
22382				setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
22383
22384			}
22385
22386		}
22387
22388		_gl.bindFramebuffer( 36160, null );
22389
22390	}
22391
22392	// Set up GL resources for the render target
22393	function setupRenderTarget( renderTarget ) {
22394
22395		var renderTargetProperties = properties.get( renderTarget );
22396		var textureProperties = properties.get( renderTarget.texture );
22397
22398		renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
22399
22400		textureProperties.__webglTexture = _gl.createTexture();
22401
22402		info.memory.textures ++;
22403
22404		var isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
22405		var isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
22406		var supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
22407
22408		// Handles WebGL2 RGBFormat fallback - #18858
22409
22410		if ( isWebGL2 && renderTarget.texture.format === RGBFormat && ( renderTarget.texture.type === FloatType || renderTarget.texture.type === HalfFloatType ) ) {
22411
22412			renderTarget.texture.format = RGBAFormat;
22413
22414			console.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );
22415
22416		}
22417
22418		// Setup framebuffer
22419
22420		if ( isCube ) {
22421
22422			renderTargetProperties.__webglFramebuffer = [];
22423
22424			for ( var i = 0; i < 6; i ++ ) {
22425
22426				renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
22427
22428			}
22429
22430		} else {
22431
22432			renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
22433
22434			if ( isMultisample ) {
22435
22436				if ( isWebGL2 ) {
22437
22438					renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
22439					renderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();
22440
22441					_gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );
22442
22443					var glFormat = utils.convert( renderTarget.texture.format );
22444					var glType = utils.convert( renderTarget.texture.type );
22445					var glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );
22446					var samples = getRenderTargetSamples( renderTarget );
22447					_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
22448
22449					_gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
22450					_gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );
22451					_gl.bindRenderbuffer( 36161, null );
22452
22453					if ( renderTarget.depthBuffer ) {
22454
22455						renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
22456						setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
22457
22458					}
22459
22460					_gl.bindFramebuffer( 36160, null );
22461
22462
22463				} else {
22464
22465					console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
22466
22467				}
22468
22469			}
22470
22471		}
22472
22473		// Setup color buffer
22474
22475		if ( isCube ) {
22476
22477			state.bindTexture( 34067, textureProperties.__webglTexture );
22478			setTextureParameters( 34067, renderTarget.texture, supportsMips );
22479
22480			for ( var i = 0; i < 6; i ++ ) {
22481
22482				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );
22483
22484			}
22485
22486			if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
22487
22488				generateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );
22489
22490			}
22491
22492			state.bindTexture( 34067, null );
22493
22494		} else {
22495
22496			state.bindTexture( 3553, textureProperties.__webglTexture );
22497			setTextureParameters( 3553, renderTarget.texture, supportsMips );
22498			setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );
22499
22500			if ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {
22501
22502				generateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );
22503
22504			}
22505
22506			state.bindTexture( 3553, null );
22507
22508		}
22509
22510		// Setup depth and stencil buffers
22511
22512		if ( renderTarget.depthBuffer ) {
22513
22514			setupDepthRenderbuffer( renderTarget );
22515
22516		}
22517
22518	}
22519
22520	function updateRenderTargetMipmap( renderTarget ) {
22521
22522		var texture = renderTarget.texture;
22523		var supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;
22524
22525		if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
22526
22527			var target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
22528			var webglTexture = properties.get( texture ).__webglTexture;
22529
22530			state.bindTexture( target, webglTexture );
22531			generateMipmap( target, texture, renderTarget.width, renderTarget.height );
22532			state.bindTexture( target, null );
22533
22534		}
22535
22536	}
22537
22538	function updateMultisampleRenderTarget( renderTarget ) {
22539
22540		if ( renderTarget.isWebGLMultisampleRenderTarget ) {
22541
22542			if ( isWebGL2 ) {
22543
22544				var renderTargetProperties = properties.get( renderTarget );
22545
22546				_gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
22547				_gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
22548
22549				var width = renderTarget.width;
22550				var height = renderTarget.height;
22551				var mask = 16384;
22552
22553				if ( renderTarget.depthBuffer ) mask |= 256;
22554				if ( renderTarget.stencilBuffer ) mask |= 1024;
22555
22556				_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
22557
22558				_gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905
22559
22560			} else {
22561
22562				console.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );
22563
22564			}
22565
22566		}
22567
22568	}
22569
22570	function getRenderTargetSamples( renderTarget ) {
22571
22572		return ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?
22573			Math.min( maxSamples, renderTarget.samples ) : 0;
22574
22575	}
22576
22577	function updateVideoTexture( texture ) {
22578
22579		var frame = info.render.frame;
22580
22581		// Check the last frame we updated the VideoTexture
22582
22583		if ( _videoTextures.get( texture ) !== frame ) {
22584
22585			_videoTextures.set( texture, frame );
22586			texture.update();
22587
22588		}
22589
22590	}
22591
22592	// backwards compatibility
22593
22594	var warnedTexture2D = false;
22595	var warnedTextureCube = false;
22596
22597	function safeSetTexture2D( texture, slot ) {
22598
22599		if ( texture && texture.isWebGLRenderTarget ) {
22600
22601			if ( warnedTexture2D === false ) {
22602
22603				console.warn( "THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead." );
22604				warnedTexture2D = true;
22605
22606			}
22607
22608			texture = texture.texture;
22609
22610		}
22611
22612		setTexture2D( texture, slot );
22613
22614	}
22615
22616	function safeSetTextureCube( texture, slot ) {
22617
22618		if ( texture && texture.isWebGLCubeRenderTarget ) {
22619
22620			if ( warnedTextureCube === false ) {
22621
22622				console.warn( "THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
22623				warnedTextureCube = true;
22624
22625			}
22626
22627			texture = texture.texture;
22628
22629		}
22630
22631		// currently relying on the fact that WebGLCubeRenderTarget.texture is a Texture and NOT a CubeTexture
22632		// TODO: unify these code paths
22633		if ( ( texture && texture.isCubeTexture ) ||
22634			( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
22635
22636			// CompressedTexture can have Array in image :/
22637
22638			// this function alone should take care of cube textures
22639			setTextureCube( texture, slot );
22640
22641		} else {
22642
22643			// assumed: texture property of THREE.WebGLCubeRenderTarget
22644			setTextureCubeDynamic( texture, slot );
22645
22646		}
22647
22648	}
22649
22650	//
22651
22652	this.allocateTextureUnit = allocateTextureUnit;
22653	this.resetTextureUnits = resetTextureUnits;
22654
22655	this.setTexture2D = setTexture2D;
22656	this.setTexture2DArray = setTexture2DArray;
22657	this.setTexture3D = setTexture3D;
22658	this.setTextureCube = setTextureCube;
22659	this.setTextureCubeDynamic = setTextureCubeDynamic;
22660	this.setupRenderTarget = setupRenderTarget;
22661	this.updateRenderTargetMipmap = updateRenderTargetMipmap;
22662	this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
22663
22664	this.safeSetTexture2D = safeSetTexture2D;
22665	this.safeSetTextureCube = safeSetTextureCube;
22666
22667}
22668
22669/**
22670 * @author thespite / http://www.twitter.com/thespite
22671 */
22672
22673function WebGLUtils( gl, extensions, capabilities ) {
22674
22675	var isWebGL2 = capabilities.isWebGL2;
22676
22677	function convert( p ) {
22678
22679		var extension;
22680
22681		if ( p === UnsignedByteType ) return 5121;
22682		if ( p === UnsignedShort4444Type ) return 32819;
22683		if ( p === UnsignedShort5551Type ) return 32820;
22684		if ( p === UnsignedShort565Type ) return 33635;
22685
22686		if ( p === ByteType ) return 5120;
22687		if ( p === ShortType ) return 5122;
22688		if ( p === UnsignedShortType ) return 5123;
22689		if ( p === IntType ) return 5124;
22690		if ( p === UnsignedIntType ) return 5125;
22691		if ( p === FloatType ) return 5126;
22692
22693		if ( p === HalfFloatType ) {
22694
22695			if ( isWebGL2 ) return 5131;
22696
22697			extension = extensions.get( 'OES_texture_half_float' );
22698
22699			if ( extension !== null ) {
22700
22701				return extension.HALF_FLOAT_OES;
22702
22703			} else {
22704
22705				return null;
22706
22707			}
22708
22709		}
22710
22711		if ( p === AlphaFormat ) return 6406;
22712		if ( p === RGBFormat ) return 6407;
22713		if ( p === RGBAFormat ) return 6408;
22714		if ( p === LuminanceFormat ) return 6409;
22715		if ( p === LuminanceAlphaFormat ) return 6410;
22716		if ( p === DepthFormat ) return 6402;
22717		if ( p === DepthStencilFormat ) return 34041;
22718		if ( p === RedFormat ) return 6403;
22719
22720		// WebGL2 formats.
22721
22722		if ( p === RedIntegerFormat ) return 36244;
22723		if ( p === RGFormat ) return 33319;
22724		if ( p === RGIntegerFormat ) return 33320;
22725		if ( p === RGBIntegerFormat ) return 36248;
22726		if ( p === RGBAIntegerFormat ) return 36249;
22727
22728		if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||
22729			p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
22730
22731			extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
22732
22733			if ( extension !== null ) {
22734
22735				if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
22736				if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
22737				if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
22738				if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
22739
22740			} else {
22741
22742				return null;
22743
22744			}
22745
22746		}
22747
22748		if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||
22749			p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
22750
22751			extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
22752
22753			if ( extension !== null ) {
22754
22755				if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
22756				if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
22757				if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
22758				if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
22759
22760			} else {
22761
22762				return null;
22763
22764			}
22765
22766		}
22767
22768		if ( p === RGB_ETC1_Format ) {
22769
22770			extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
22771
22772			if ( extension !== null ) {
22773
22774				return extension.COMPRESSED_RGB_ETC1_WEBGL;
22775
22776			} else {
22777
22778				return null;
22779
22780			}
22781
22782		}
22783
22784		if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
22785
22786			extension = extensions.get( 'WEBGL_compressed_texture_etc' );
22787
22788			if ( extension !== null ) {
22789
22790				if ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;
22791				if ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;
22792
22793			}
22794
22795		}
22796
22797		if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
22798			p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
22799			p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
22800			p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
22801			p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||
22802			p === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||
22803			p === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||
22804			p === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||
22805			p === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||
22806			p === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {
22807
22808			extension = extensions.get( 'WEBGL_compressed_texture_astc' );
22809
22810			if ( extension !== null ) {
22811
22812				// TODO Complete?
22813
22814				return p;
22815
22816			} else {
22817
22818				return null;
22819
22820			}
22821
22822		}
22823
22824		if ( p === RGBA_BPTC_Format ) {
22825
22826			extension = extensions.get( 'EXT_texture_compression_bptc' );
22827
22828			if ( extension !== null ) {
22829
22830				// TODO Complete?
22831
22832				return p;
22833
22834			} else {
22835
22836				return null;
22837
22838			}
22839
22840		}
22841
22842		if ( p === UnsignedInt248Type ) {
22843
22844			if ( isWebGL2 ) return 34042;
22845
22846			extension = extensions.get( 'WEBGL_depth_texture' );
22847
22848			if ( extension !== null ) {
22849
22850				return extension.UNSIGNED_INT_24_8_WEBGL;
22851
22852			} else {
22853
22854				return null;
22855
22856			}
22857
22858		}
22859
22860	}
22861
22862	return { convert: convert };
22863
22864}
22865
22866/**
22867 * @author mrdoob / http://mrdoob.com/
22868 */
22869
22870function ArrayCamera( array ) {
22871
22872	PerspectiveCamera.call( this );
22873
22874	this.cameras = array || [];
22875
22876}
22877
22878ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {
22879
22880	constructor: ArrayCamera,
22881
22882	isArrayCamera: true
22883
22884} );
22885
22886/**
22887 * @author mrdoob / http://mrdoob.com/
22888 */
22889
22890function Group() {
22891
22892	Object3D.call( this );
22893
22894	this.type = 'Group';
22895
22896}
22897
22898Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
22899
22900	constructor: Group,
22901
22902	isGroup: true
22903
22904} );
22905
22906/**
22907 * @author Mugen87 / https://github.com/Mugen87
22908 */
22909
22910function WebXRController() {
22911
22912	this._targetRay = null;
22913	this._grip = null;
22914
22915}
22916
22917Object.assign( WebXRController.prototype, {
22918
22919	constructor: WebXRController,
22920
22921	getTargetRaySpace: function () {
22922
22923		if ( this._targetRay === null ) {
22924
22925			this._targetRay = new Group();
22926			this._targetRay.matrixAutoUpdate = false;
22927			this._targetRay.visible = false;
22928
22929		}
22930
22931		return this._targetRay;
22932
22933	},
22934
22935	getGripSpace: function () {
22936
22937		if ( this._grip === null ) {
22938
22939			this._grip = new Group();
22940			this._grip.matrixAutoUpdate = false;
22941			this._grip.visible = false;
22942
22943		}
22944
22945		return this._grip;
22946
22947	},
22948
22949	dispatchEvent: function ( event ) {
22950
22951		if ( this._targetRay !== null ) {
22952
22953			this._targetRay.dispatchEvent( event );
22954
22955		}
22956
22957		if ( this._grip !== null ) {
22958
22959			this._grip.dispatchEvent( event );
22960
22961		}
22962
22963		return this;
22964
22965	},
22966
22967	disconnect: function ( inputSource ) {
22968
22969		this.dispatchEvent( { type: 'disconnected', data: inputSource } );
22970
22971		if ( this._targetRay !== null ) {
22972
22973			this._targetRay.visible = false;
22974
22975		}
22976
22977		if ( this._grip !== null ) {
22978
22979			this._grip.visible = false;
22980
22981		}
22982
22983		return this;
22984
22985	},
22986
22987	update: function ( inputSource, frame, referenceSpace ) {
22988
22989		var inputPose = null;
22990		var gripPose = null;
22991
22992		var targetRay = this._targetRay;
22993		var grip = this._grip;
22994
22995		if ( inputSource ) {
22996
22997			if ( targetRay !== null ) {
22998
22999				inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
23000
23001				if ( inputPose !== null ) {
23002
23003					targetRay.matrix.fromArray( inputPose.transform.matrix );
23004					targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
23005
23006				}
23007
23008			}
23009
23010			if ( grip !== null && inputSource.gripSpace ) {
23011
23012				gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
23013
23014				if ( gripPose !== null ) {
23015
23016					grip.matrix.fromArray( gripPose.transform.matrix );
23017					grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
23018
23019				}
23020
23021			}
23022
23023		}
23024
23025		if ( targetRay !== null ) {
23026
23027			targetRay.visible = ( inputPose !== null );
23028
23029		}
23030
23031		if ( grip !== null ) {
23032
23033			grip.visible = ( gripPose !== null );
23034
23035		}
23036
23037		return this;
23038
23039	}
23040
23041} );
23042
23043/**
23044 * @author mrdoob / http://mrdoob.com/
23045 */
23046
23047function WebXRManager( renderer, gl ) {
23048
23049	var scope = this;
23050
23051	var session = null;
23052
23053	var framebufferScaleFactor = 1.0;
23054
23055	var referenceSpace = null;
23056	var referenceSpaceType = 'local-floor';
23057
23058	var pose = null;
23059
23060	var controllers = [];
23061	var inputSourcesMap = new Map();
23062
23063	//
23064
23065	var cameraL = new PerspectiveCamera();
23066	cameraL.layers.enable( 1 );
23067	cameraL.viewport = new Vector4();
23068
23069	var cameraR = new PerspectiveCamera();
23070	cameraR.layers.enable( 2 );
23071	cameraR.viewport = new Vector4();
23072
23073	var cameras = [ cameraL, cameraR ];
23074
23075	var cameraVR = new ArrayCamera();
23076	cameraVR.layers.enable( 1 );
23077	cameraVR.layers.enable( 2 );
23078
23079	var _currentDepthNear = null;
23080	var _currentDepthFar = null;
23081
23082	//
23083
23084	this.enabled = false;
23085
23086	this.isPresenting = false;
23087
23088	this.getController = function ( index ) {
23089
23090		var controller = controllers[ index ];
23091
23092		if ( controller === undefined ) {
23093
23094			controller = new WebXRController();
23095			controllers[ index ] = controller;
23096
23097		}
23098
23099		return controller.getTargetRaySpace();
23100
23101	};
23102
23103	this.getControllerGrip = function ( index ) {
23104
23105		var controller = controllers[ index ];
23106
23107		if ( controller === undefined ) {
23108
23109			controller = new WebXRController();
23110			controllers[ index ] = controller;
23111
23112		}
23113
23114		return controller.getGripSpace();
23115
23116	};
23117
23118	//
23119
23120	function onSessionEvent( event ) {
23121
23122		var controller = inputSourcesMap.get( event.inputSource );
23123
23124		if ( controller ) {
23125
23126			controller.dispatchEvent( { type: event.type } );
23127
23128		}
23129
23130	}
23131
23132	function onSessionEnd() {
23133
23134		inputSourcesMap.forEach( function ( controller, inputSource ) {
23135
23136			controller.disconnect( inputSource );
23137
23138		} );
23139
23140		inputSourcesMap.clear();
23141
23142		//
23143
23144		renderer.setFramebuffer( null );
23145		renderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830
23146		animation.stop();
23147
23148		scope.isPresenting = false;
23149
23150		scope.dispatchEvent( { type: 'sessionend' } );
23151
23152	}
23153
23154	function onRequestReferenceSpace( value ) {
23155
23156		referenceSpace = value;
23157
23158		animation.setContext( session );
23159		animation.start();
23160
23161		scope.isPresenting = true;
23162
23163		scope.dispatchEvent( { type: 'sessionstart' } );
23164
23165	}
23166
23167	this.setFramebufferScaleFactor = function ( value ) {
23168
23169		framebufferScaleFactor = value;
23170
23171		if ( scope.isPresenting === true ) {
23172
23173			console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
23174
23175		}
23176
23177	};
23178
23179	this.setReferenceSpaceType = function ( value ) {
23180
23181		referenceSpaceType = value;
23182
23183		if ( scope.isPresenting === true ) {
23184
23185			console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
23186
23187		}
23188
23189	};
23190
23191	this.getReferenceSpace = function () {
23192
23193		return referenceSpace;
23194
23195	};
23196
23197	this.getSession = function () {
23198
23199		return session;
23200
23201	};
23202
23203	this.setSession = function ( value ) {
23204
23205		session = value;
23206
23207		if ( session !== null ) {
23208
23209			session.addEventListener( 'select', onSessionEvent );
23210			session.addEventListener( 'selectstart', onSessionEvent );
23211			session.addEventListener( 'selectend', onSessionEvent );
23212			session.addEventListener( 'squeeze', onSessionEvent );
23213			session.addEventListener( 'squeezestart', onSessionEvent );
23214			session.addEventListener( 'squeezeend', onSessionEvent );
23215			session.addEventListener( 'end', onSessionEnd );
23216
23217			var attributes = gl.getContextAttributes();
23218
23219			var layerInit = {
23220				antialias: attributes.antialias,
23221				alpha: attributes.alpha,
23222				depth: attributes.depth,
23223				stencil: attributes.stencil,
23224				framebufferScaleFactor: framebufferScaleFactor
23225			};
23226
23227			// eslint-disable-next-line no-undef
23228			var baseLayer = new XRWebGLLayer( session, gl, layerInit );
23229
23230			session.updateRenderState( { baseLayer: baseLayer } );
23231
23232			session.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );
23233
23234			//
23235
23236			session.addEventListener( 'inputsourceschange', updateInputSources );
23237
23238		}
23239
23240	};
23241
23242	function updateInputSources( event ) {
23243
23244		var inputSources = session.inputSources;
23245
23246		// Assign inputSources to available controllers
23247
23248		for ( var i = 0; i < controllers.length; i ++ ) {
23249
23250			inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
23251
23252		}
23253
23254		// Notify disconnected
23255
23256		for ( var i = 0; i < event.removed.length; i ++ ) {
23257
23258			var inputSource = event.removed[ i ];
23259			var controller = inputSourcesMap.get( inputSource );
23260
23261			if ( controller ) {
23262
23263				controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
23264				inputSourcesMap.delete( inputSource );
23265
23266			}
23267
23268		}
23269
23270		// Notify connected
23271
23272		for ( var i = 0; i < event.added.length; i ++ ) {
23273
23274			var inputSource = event.added[ i ];
23275			var controller = inputSourcesMap.get( inputSource );
23276
23277			if ( controller ) {
23278
23279				controller.dispatchEvent( { type: 'connected', data: inputSource } );
23280
23281			}
23282
23283		}
23284
23285	}
23286
23287	//
23288
23289	var cameraLPos = new Vector3();
23290	var cameraRPos = new Vector3();
23291
23292	/**
23293	 * @author jsantell / https://www.jsantell.com/
23294	 *
23295	 * Assumes 2 cameras that are parallel and share an X-axis, and that
23296	 * the cameras' projection and world matrices have already been set.
23297	 * And that near and far planes are identical for both cameras.
23298	 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
23299	 */
23300	function setProjectionFromUnion( camera, cameraL, cameraR ) {
23301
23302		cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
23303		cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
23304
23305		var ipd = cameraLPos.distanceTo( cameraRPos );
23306
23307		var projL = cameraL.projectionMatrix.elements;
23308		var projR = cameraR.projectionMatrix.elements;
23309
23310		// VR systems will have identical far and near planes, and
23311		// most likely identical top and bottom frustum extents.
23312		// Use the left camera for these values.
23313		var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
23314		var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
23315		var topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
23316		var bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
23317
23318		var leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
23319		var rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
23320		var left = near * leftFov;
23321		var right = near * rightFov;
23322
23323		// Calculate the new camera's position offset from the
23324		// left camera. xOffset should be roughly half `ipd`.
23325		var zOffset = ipd / ( - leftFov + rightFov );
23326		var xOffset = zOffset * - leftFov;
23327
23328		// TODO: Better way to apply this offset?
23329		cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
23330		camera.translateX( xOffset );
23331		camera.translateZ( zOffset );
23332		camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
23333		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
23334
23335		// Find the union of the frustum values of the cameras and scale
23336		// the values so that the near plane's position does not change in world space,
23337		// although must now be relative to the new union camera.
23338		var near2 = near + zOffset;
23339		var far2 = far + zOffset;
23340		var left2 = left - xOffset;
23341		var right2 = right + ( ipd - xOffset );
23342		var top2 = topFov * far / far2 * near2;
23343		var bottom2 = bottomFov * far / far2 * near2;
23344
23345		camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
23346
23347	}
23348
23349	function updateCamera( camera, parent ) {
23350
23351		if ( parent === null ) {
23352
23353			camera.matrixWorld.copy( camera.matrix );
23354
23355		} else {
23356
23357			camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
23358
23359		}
23360
23361		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
23362
23363	}
23364
23365	this.getCamera = function ( camera ) {
23366
23367		cameraVR.near = cameraR.near = cameraL.near = camera.near;
23368		cameraVR.far = cameraR.far = cameraL.far = camera.far;
23369
23370		if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
23371
23372			// Note that the new renderState won't apply until the next frame. See #18320
23373
23374			session.updateRenderState( {
23375				depthNear: cameraVR.near,
23376				depthFar: cameraVR.far
23377			} );
23378
23379			_currentDepthNear = cameraVR.near;
23380			_currentDepthFar = cameraVR.far;
23381
23382		}
23383
23384		var parent = camera.parent;
23385		var cameras = cameraVR.cameras;
23386
23387		updateCamera( cameraVR, parent );
23388
23389		for ( var i = 0; i < cameras.length; i ++ ) {
23390
23391			updateCamera( cameras[ i ], parent );
23392
23393		}
23394
23395		// update camera and its children
23396
23397		camera.matrixWorld.copy( cameraVR.matrixWorld );
23398
23399		var children = camera.children;
23400
23401		for ( var i = 0, l = children.length; i < l; i ++ ) {
23402
23403			children[ i ].updateMatrixWorld( true );
23404
23405		}
23406
23407		// update projection matrix for proper view frustum culling
23408
23409		if ( cameras.length === 2 ) {
23410
23411			setProjectionFromUnion( cameraVR, cameraL, cameraR );
23412
23413		} else {
23414
23415			// assume single camera setup (AR)
23416
23417			cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
23418
23419		}
23420
23421		return cameraVR;
23422
23423	};
23424
23425	// Animation Loop
23426
23427	var onAnimationFrameCallback = null;
23428
23429	function onAnimationFrame( time, frame ) {
23430
23431		pose = frame.getViewerPose( referenceSpace );
23432
23433		if ( pose !== null ) {
23434
23435			var views = pose.views;
23436			var baseLayer = session.renderState.baseLayer;
23437
23438			renderer.setFramebuffer( baseLayer.framebuffer );
23439
23440			var cameraVRNeedsUpdate = false;
23441
23442			// check if it's necessary to rebuild cameraVR's camera list
23443
23444			if ( views.length !== cameraVR.cameras.length ) {
23445
23446				cameraVR.cameras.length = 0;
23447				cameraVRNeedsUpdate = true;
23448
23449			}
23450
23451			for ( var i = 0; i < views.length; i ++ ) {
23452
23453				var view = views[ i ];
23454				var viewport = baseLayer.getViewport( view );
23455
23456				var camera = cameras[ i ];
23457				camera.matrix.fromArray( view.transform.matrix );
23458				camera.projectionMatrix.fromArray( view.projectionMatrix );
23459				camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
23460
23461				if ( i === 0 ) {
23462
23463					cameraVR.matrix.copy( camera.matrix );
23464
23465				}
23466
23467				if ( cameraVRNeedsUpdate === true ) {
23468
23469					cameraVR.cameras.push( camera );
23470
23471				}
23472
23473			}
23474
23475		}
23476
23477		//
23478
23479		var inputSources = session.inputSources;
23480
23481		for ( var i = 0; i < controllers.length; i ++ ) {
23482
23483			var controller = controllers[ i ];
23484			var inputSource = inputSources[ i ];
23485
23486			controller.update( inputSource, frame, referenceSpace );
23487
23488		}
23489
23490		if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
23491
23492	}
23493
23494	var animation = new WebGLAnimation();
23495	animation.setAnimationLoop( onAnimationFrame );
23496
23497	this.setAnimationLoop = function ( callback ) {
23498
23499		onAnimationFrameCallback = callback;
23500
23501	};
23502
23503	this.dispose = function () {};
23504
23505}
23506
23507Object.assign( WebXRManager.prototype, EventDispatcher.prototype );
23508
23509/**
23510 * @author supereggbert / http://www.paulbrunt.co.uk/
23511 * @author mrdoob / http://mrdoob.com/
23512 * @author alteredq / http://alteredqualia.com/
23513 * @author szimek / https://github.com/szimek/
23514 * @author tschw
23515 */
23516
23517function WebGLRenderer( parameters ) {
23518
23519	parameters = parameters || {};
23520
23521	var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),
23522		_context = parameters.context !== undefined ? parameters.context : null,
23523
23524		_alpha = parameters.alpha !== undefined ? parameters.alpha : false,
23525		_depth = parameters.depth !== undefined ? parameters.depth : true,
23526		_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
23527		_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
23528		_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
23529		_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
23530		_powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
23531		_failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
23532
23533	var currentRenderList = null;
23534	var currentRenderState = null;
23535
23536	// public properties
23537
23538	this.domElement = _canvas;
23539
23540	// Debug configuration container
23541	this.debug = {
23542
23543		/**
23544		 * Enables error checking and reporting when shader programs are being compiled
23545		 * @type {boolean}
23546		 */
23547		checkShaderErrors: true
23548	};
23549
23550	// clearing
23551
23552	this.autoClear = true;
23553	this.autoClearColor = true;
23554	this.autoClearDepth = true;
23555	this.autoClearStencil = true;
23556
23557	// scene graph
23558
23559	this.sortObjects = true;
23560
23561	// user-defined clipping
23562
23563	this.clippingPlanes = [];
23564	this.localClippingEnabled = false;
23565
23566	// physically based shading
23567
23568	this.gammaFactor = 2.0;	// for backwards compatibility
23569	this.outputEncoding = LinearEncoding;
23570
23571	// physical lights
23572
23573	this.physicallyCorrectLights = false;
23574
23575	// tone mapping
23576
23577	this.toneMapping = NoToneMapping;
23578	this.toneMappingExposure = 1.0;
23579	this.toneMappingWhitePoint = 1.0;
23580
23581	// morphs
23582
23583	this.maxMorphTargets = 8;
23584	this.maxMorphNormals = 4;
23585
23586	// internal properties
23587
23588	var _this = this,
23589
23590		_isContextLost = false,
23591
23592		// internal state cache
23593
23594		_framebuffer = null,
23595
23596		_currentActiveCubeFace = 0,
23597		_currentActiveMipmapLevel = 0,
23598		_currentRenderTarget = null,
23599		_currentFramebuffer = null,
23600		_currentMaterialId = - 1,
23601
23602		// geometry and program caching
23603
23604		_currentGeometryProgram = {
23605			geometry: null,
23606			program: null,
23607			wireframe: false
23608		},
23609
23610		_currentCamera = null,
23611		_currentArrayCamera = null,
23612
23613		_currentViewport = new Vector4(),
23614		_currentScissor = new Vector4(),
23615		_currentScissorTest = null,
23616
23617		//
23618
23619		_width = _canvas.width,
23620		_height = _canvas.height,
23621
23622		_pixelRatio = 1,
23623		_opaqueSort = null,
23624		_transparentSort = null,
23625
23626		_viewport = new Vector4( 0, 0, _width, _height ),
23627		_scissor = new Vector4( 0, 0, _width, _height ),
23628		_scissorTest = false,
23629
23630		// frustum
23631
23632		_frustum = new Frustum(),
23633
23634		// clipping
23635
23636		_clipping = new WebGLClipping(),
23637		_clippingEnabled = false,
23638		_localClippingEnabled = false,
23639
23640		// camera matrices cache
23641
23642		_projScreenMatrix = new Matrix4(),
23643
23644		_vector3 = new Vector3();
23645
23646	function getTargetPixelRatio() {
23647
23648		return _currentRenderTarget === null ? _pixelRatio : 1;
23649
23650	}
23651
23652	// initialize
23653
23654	var _gl;
23655
23656	try {
23657
23658		var contextAttributes = {
23659			alpha: _alpha,
23660			depth: _depth,
23661			stencil: _stencil,
23662			antialias: _antialias,
23663			premultipliedAlpha: _premultipliedAlpha,
23664			preserveDrawingBuffer: _preserveDrawingBuffer,
23665			powerPreference: _powerPreference,
23666			failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat,
23667			xrCompatible: true
23668		};
23669
23670		// event listeners must be registered before WebGL context is created, see #12753
23671
23672		_canvas.addEventListener( 'webglcontextlost', onContextLost, false );
23673		_canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
23674
23675		_gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );
23676
23677		if ( _gl === null ) {
23678
23679			if ( _canvas.getContext( 'webgl' ) !== null ) {
23680
23681				throw new Error( 'Error creating WebGL context with your selected attributes.' );
23682
23683			} else {
23684
23685				throw new Error( 'Error creating WebGL context.' );
23686
23687			}
23688
23689		}
23690
23691		// Some experimental-webgl implementations do not have getShaderPrecisionFormat
23692
23693		if ( _gl.getShaderPrecisionFormat === undefined ) {
23694
23695			_gl.getShaderPrecisionFormat = function () {
23696
23697				return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
23698
23699			};
23700
23701		}
23702
23703	} catch ( error ) {
23704
23705		console.error( 'THREE.WebGLRenderer: ' + error.message );
23706		throw error;
23707
23708	}
23709
23710	var extensions, capabilities, state, info;
23711	var properties, textures, attributes, geometries, objects;
23712	var programCache, renderLists, renderStates;
23713
23714	var background, morphtargets, bufferRenderer, indexedBufferRenderer;
23715
23716	var utils;
23717
23718	function initGLContext() {
23719
23720		extensions = new WebGLExtensions( _gl );
23721
23722		capabilities = new WebGLCapabilities( _gl, extensions, parameters );
23723
23724		if ( capabilities.isWebGL2 === false ) {
23725
23726			extensions.get( 'WEBGL_depth_texture' );
23727			extensions.get( 'OES_texture_float' );
23728			extensions.get( 'OES_texture_half_float' );
23729			extensions.get( 'OES_texture_half_float_linear' );
23730			extensions.get( 'OES_standard_derivatives' );
23731			extensions.get( 'OES_element_index_uint' );
23732			extensions.get( 'ANGLE_instanced_arrays' );
23733
23734		}
23735
23736		extensions.get( 'OES_texture_float_linear' );
23737
23738		utils = new WebGLUtils( _gl, extensions, capabilities );
23739
23740		state = new WebGLState( _gl, extensions, capabilities );
23741		state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
23742		state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
23743
23744		info = new WebGLInfo( _gl );
23745		properties = new WebGLProperties();
23746		textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
23747		attributes = new WebGLAttributes( _gl, capabilities );
23748		geometries = new WebGLGeometries( _gl, attributes, info );
23749		objects = new WebGLObjects( _gl, geometries, attributes, info );
23750		morphtargets = new WebGLMorphtargets( _gl );
23751		programCache = new WebGLPrograms( _this, extensions, capabilities );
23752		renderLists = new WebGLRenderLists();
23753		renderStates = new WebGLRenderStates();
23754
vendor: 15,437 bytes, lines 23755-24505
23755		background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
23756
23757		bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
23758		indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
23759
23760		info.programs = programCache.programs;
23761
23762		_this.capabilities = capabilities;
23763		_this.extensions = extensions;
23764		_this.properties = properties;
23765		_this.renderLists = renderLists;
23766		_this.state = state;
23767		_this.info = info;
23768
23769	}
23770
23771	initGLContext();
23772
23773	// xr
23774
23775	var xr = new WebXRManager( _this, _gl );
23776
23777	this.xr = xr;
23778
23779	// shadow map
23780
23781	var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
23782
23783	this.shadowMap = shadowMap;
23784
23785	// API
23786
23787	this.getContext = function () {
23788
23789		return _gl;
23790
23791	};
23792
23793	this.getContextAttributes = function () {
23794
23795		return _gl.getContextAttributes();
23796
23797	};
23798
23799	this.forceContextLoss = function () {
23800
23801		var extension = extensions.get( 'WEBGL_lose_context' );
23802		if ( extension ) extension.loseContext();
23803
23804	};
23805
23806	this.forceContextRestore = function () {
23807
23808		var extension = extensions.get( 'WEBGL_lose_context' );
23809		if ( extension ) extension.restoreContext();
23810
23811	};
23812
23813	this.getPixelRatio = function () {
23814
23815		return _pixelRatio;
23816
23817	};
23818
23819	this.setPixelRatio = function ( value ) {
23820
23821		if ( value === undefined ) return;
23822
23823		_pixelRatio = value;
23824
23825		this.setSize( _width, _height, false );
23826
23827	};
23828
23829	this.getSize = function ( target ) {
23830
23831		if ( target === undefined ) {
23832
23833			console.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );
23834
23835			target = new Vector2();
23836
23837		}
23838
23839		return target.set( _width, _height );
23840
23841	};
23842
23843	this.setSize = function ( width, height, updateStyle ) {
23844
23845		if ( xr.isPresenting ) {
23846
23847			console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
23848			return;
23849
23850		}
23851
23852		_width = width;
23853		_height = height;
23854
23855		_canvas.width = Math.floor( width * _pixelRatio );
23856		_canvas.height = Math.floor( height * _pixelRatio );
23857
23858		if ( updateStyle !== false ) {
23859
23860			_canvas.style.width = width + 'px';
23861			_canvas.style.height = height + 'px';
23862
23863		}
23864
23865		this.setViewport( 0, 0, width, height );
23866
23867	};
23868
23869	this.getDrawingBufferSize = function ( target ) {
23870
23871		if ( target === undefined ) {
23872
23873			console.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );
23874
23875			target = new Vector2();
23876
23877		}
23878
23879		return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
23880
23881	};
23882
23883	this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
23884
23885		_width = width;
23886		_height = height;
23887
23888		_pixelRatio = pixelRatio;
23889
23890		_canvas.width = Math.floor( width * pixelRatio );
23891		_canvas.height = Math.floor( height * pixelRatio );
23892
23893		this.setViewport( 0, 0, width, height );
23894
23895	};
23896
23897	this.getCurrentViewport = function ( target ) {
23898
23899		if ( target === undefined ) {
23900
23901			console.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );
23902
23903			target = new Vector4();
23904
23905		}
23906
23907		return target.copy( _currentViewport );
23908
23909	};
23910
23911	this.getViewport = function ( target ) {
23912
23913		return target.copy( _viewport );
23914
23915	};
23916
23917	this.setViewport = function ( x, y, width, height ) {
23918
23919		if ( x.isVector4 ) {
23920
23921			_viewport.set( x.x, x.y, x.z, x.w );
23922
23923		} else {
23924
23925			_viewport.set( x, y, width, height );
23926
23927		}
23928
23929		state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
23930
23931	};
23932
23933	this.getScissor = function ( target ) {
23934
23935		return target.copy( _scissor );
23936
23937	};
23938
23939	this.setScissor = function ( x, y, width, height ) {
23940
23941		if ( x.isVector4 ) {
23942
23943			_scissor.set( x.x, x.y, x.z, x.w );
23944
23945		} else {
23946
23947			_scissor.set( x, y, width, height );
23948
23949		}
23950
23951		state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
23952
23953	};
23954
23955	this.getScissorTest = function () {
23956
23957		return _scissorTest;
23958
23959	};
23960
23961	this.setScissorTest = function ( boolean ) {
23962
23963		state.setScissorTest( _scissorTest = boolean );
23964
23965	};
23966
23967	this.setOpaqueSort = function ( method ) {
23968
23969		_opaqueSort = method;
23970
23971	};
23972
23973	this.setTransparentSort = function ( method ) {
23974
23975		_transparentSort = method;
23976
23977	};
23978
23979	// Clearing
23980
23981	this.getClearColor = function () {
23982
23983		return background.getClearColor();
23984
23985	};
23986
23987	this.setClearColor = function () {
23988
23989		background.setClearColor.apply( background, arguments );
23990
23991	};
23992
23993	this.getClearAlpha = function () {
23994
23995		return background.getClearAlpha();
23996
23997	};
23998
23999	this.setClearAlpha = function () {
24000
24001		background.setClearAlpha.apply( background, arguments );
24002
24003	};
24004
24005	this.clear = function ( color, depth, stencil ) {
24006
24007		var bits = 0;
24008
24009		if ( color === undefined || color ) bits |= 16384;
24010		if ( depth === undefined || depth ) bits |= 256;
24011		if ( stencil === undefined || stencil ) bits |= 1024;
24012
24013		_gl.clear( bits );
24014
24015	};
24016
24017	this.clearColor = function () {
24018
24019		this.clear( true, false, false );
24020
24021	};
24022
24023	this.clearDepth = function () {
24024
24025		this.clear( false, true, false );
24026
24027	};
24028
24029	this.clearStencil = function () {
24030
24031		this.clear( false, false, true );
24032
24033	};
24034
24035	//
24036
24037	this.dispose = function () {
24038
24039		_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
24040		_canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
24041
24042		renderLists.dispose();
24043		renderStates.dispose();
24044		properties.dispose();
24045		objects.dispose();
24046
24047		xr.dispose();
24048
24049		animation.stop();
24050
24051	};
24052
24053	// Events
24054
24055	function onContextLost( event ) {
24056
24057		event.preventDefault();
24058
24059		console.log( 'THREE.WebGLRenderer: Context Lost.' );
24060
24061		_isContextLost = true;
24062
24063	}
24064
24065	function onContextRestore( /* event */ ) {
24066
24067		console.log( 'THREE.WebGLRenderer: Context Restored.' );
24068
24069		_isContextLost = false;
24070
24071		initGLContext();
24072
24073	}
24074
24075	function onMaterialDispose( event ) {
24076
24077		var material = event.target;
24078
24079		material.removeEventListener( 'dispose', onMaterialDispose );
24080
24081		deallocateMaterial( material );
24082
24083	}
24084
24085	// Buffer deallocation
24086
24087	function deallocateMaterial( material ) {
24088
24089		releaseMaterialProgramReference( material );
24090
24091		properties.remove( material );
24092
24093	}
24094
24095
24096	function releaseMaterialProgramReference( material ) {
24097
24098		var programInfo = properties.get( material ).program;
24099
24100		material.program = undefined;
24101
24102		if ( programInfo !== undefined ) {
24103
24104			programCache.releaseProgram( programInfo );
24105
24106		}
24107
24108	}
24109
24110	// Buffer rendering
24111
24112	function renderObjectImmediate( object, program ) {
24113
24114		object.render( function ( object ) {
24115
24116			_this.renderBufferImmediate( object, program );
24117
24118		} );
24119
24120	}
24121
24122	this.renderBufferImmediate = function ( object, program ) {
24123
24124		state.initAttributes();
24125
24126		var buffers = properties.get( object );
24127
24128		if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
24129		if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
24130		if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
24131		if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
24132
24133		var programAttributes = program.getAttributes();
24134
24135		if ( object.hasPositions ) {
24136
24137			_gl.bindBuffer( 34962, buffers.position );
24138			_gl.bufferData( 34962, object.positionArray, 35048 );
24139
24140			state.enableAttribute( programAttributes.position );
24141			_gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );
24142
24143		}
24144
24145		if ( object.hasNormals ) {
24146
24147			_gl.bindBuffer( 34962, buffers.normal );
24148			_gl.bufferData( 34962, object.normalArray, 35048 );
24149
24150			state.enableAttribute( programAttributes.normal );
24151			_gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );
24152
24153		}
24154
24155		if ( object.hasUvs ) {
24156
24157			_gl.bindBuffer( 34962, buffers.uv );
24158			_gl.bufferData( 34962, object.uvArray, 35048 );
24159
24160			state.enableAttribute( programAttributes.uv );
24161			_gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );
24162
24163		}
24164
24165		if ( object.hasColors ) {
24166
24167			_gl.bindBuffer( 34962, buffers.color );
24168			_gl.bufferData( 34962, object.colorArray, 35048 );
24169
24170			state.enableAttribute( programAttributes.color );
24171			_gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );
24172
24173		}
24174
24175		state.disableUnusedAttributes();
24176
24177		_gl.drawArrays( 4, 0, object.count );
24178
24179		object.count = 0;
24180
24181	};
24182
24183	var tempScene = new Scene();
24184
24185	this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
24186
24187		if ( scene === null ) scene = tempScene; // renderBufferDirect second parameter used to be fog (could be null)
24188
24189		var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
24190
24191		var program = setProgram( camera, scene, material, object );
24192
24193		state.setMaterial( material, frontFaceCW );
24194
24195		var updateBuffers = false;
24196
24197		if ( _currentGeometryProgram.geometry !== geometry.id ||
24198			_currentGeometryProgram.program !== program.id ||
24199			_currentGeometryProgram.wireframe !== ( material.wireframe === true ) ) {
24200
24201			_currentGeometryProgram.geometry = geometry.id;
24202			_currentGeometryProgram.program = program.id;
24203			_currentGeometryProgram.wireframe = material.wireframe === true;
24204			updateBuffers = true;
24205
24206		}
24207
24208		if ( material.morphTargets || material.morphNormals ) {
24209
24210			morphtargets.update( object, geometry, material, program );
24211
24212			updateBuffers = true;
24213
24214		}
24215
24216		if ( object.isInstancedMesh === true ) {
24217
24218			updateBuffers = true;
24219
24220		}
24221
24222		//
24223
24224		var index = geometry.index;
24225		var position = geometry.attributes.position;
24226
24227		//
24228
24229		if ( index === null ) {
24230
24231			if ( position === undefined || position.count === 0 ) return;
24232
24233		} else if ( index.count === 0 ) {
24234
24235			return;
24236
24237		}
24238
24239		//
24240
24241		var rangeFactor = 1;
24242
24243		if ( material.wireframe === true ) {
24244
24245			index = geometries.getWireframeAttribute( geometry );
24246			rangeFactor = 2;
24247
24248		}
24249
24250		var attribute;
24251		var renderer = bufferRenderer;
24252
24253		if ( index !== null ) {
24254
24255			attribute = attributes.get( index );
24256
24257			renderer = indexedBufferRenderer;
24258			renderer.setIndex( attribute );
24259
24260		}
24261
24262		if ( updateBuffers ) {
24263
24264			setupVertexAttributes( object, geometry, material, program );
24265
24266			if ( index !== null ) {
24267
24268				_gl.bindBuffer( 34963, attribute.buffer );
24269
24270			}
24271
24272		}
24273
24274		//
24275
24276		var dataCount = ( index !== null ) ? index.count : position.count;
24277
24278		var rangeStart = geometry.drawRange.start * rangeFactor;
24279		var rangeCount = geometry.drawRange.count * rangeFactor;
24280
24281		var groupStart = group !== null ? group.start * rangeFactor : 0;
24282		var groupCount = group !== null ? group.count * rangeFactor : Infinity;
24283
24284		var drawStart = Math.max( rangeStart, groupStart );
24285		var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
24286
24287		var drawCount = Math.max( 0, drawEnd - drawStart + 1 );
24288
24289		if ( drawCount === 0 ) return;
24290
24291		//
24292
24293		if ( object.isMesh ) {
24294
24295			if ( material.wireframe === true ) {
24296
24297				state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
24298				renderer.setMode( 1 );
24299
24300			} else {
24301
24302				renderer.setMode( 4 );
24303
24304			}
24305
24306		} else if ( object.isLine ) {
24307
24308			var lineWidth = material.linewidth;
24309
24310			if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
24311
24312			state.setLineWidth( lineWidth * getTargetPixelRatio() );
24313
24314			if ( object.isLineSegments ) {
24315
24316				renderer.setMode( 1 );
24317
24318			} else if ( object.isLineLoop ) {
24319
24320				renderer.setMode( 2 );
24321
24322			} else {
24323
24324				renderer.setMode( 3 );
24325
24326			}
24327
24328		} else if ( object.isPoints ) {
24329
24330			renderer.setMode( 0 );
24331
24332		} else if ( object.isSprite ) {
24333
24334			renderer.setMode( 4 );
24335
24336		}
24337
24338		if ( object.isInstancedMesh ) {
24339
24340			renderer.renderInstances( geometry, drawStart, drawCount, object.count );
24341
24342		} else if ( geometry.isInstancedBufferGeometry ) {
24343
24344			renderer.renderInstances( geometry, drawStart, drawCount, geometry.maxInstancedCount );
24345
24346		} else {
24347
24348			renderer.render( drawStart, drawCount );
24349
24350		}
24351
24352	};
24353
24354	function setupVertexAttributes( object, geometry, material, program ) {
24355
24356		if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
24357
24358			if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;
24359
24360		}
24361
24362		state.initAttributes();
24363
24364		var geometryAttributes = geometry.attributes;
24365
24366		var programAttributes = program.getAttributes();
24367
24368		var materialDefaultAttributeValues = material.defaultAttributeValues;
24369
24370		for ( var name in programAttributes ) {
24371
24372			var programAttribute = programAttributes[ name ];
24373
24374			if ( programAttribute >= 0 ) {
24375
24376				var geometryAttribute = geometryAttributes[ name ];
24377
24378				if ( geometryAttribute !== undefined ) {
24379
24380					var normalized = geometryAttribute.normalized;
24381					var size = geometryAttribute.itemSize;
24382
24383					var attribute = attributes.get( geometryAttribute );
24384
24385					// TODO Attribute may not be available on context restore
24386
24387					if ( attribute === undefined ) continue;
24388
24389					var buffer = attribute.buffer;
24390					var type = attribute.type;
24391					var bytesPerElement = attribute.bytesPerElement;
24392
24393					if ( geometryAttribute.isInterleavedBufferAttribute ) {
24394
24395						var data = geometryAttribute.data;
24396						var stride = data.stride;
24397						var offset = geometryAttribute.offset;
24398
24399						if ( data && data.isInstancedInterleavedBuffer ) {
24400
24401							state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
24402
24403							if ( geometry.maxInstancedCount === undefined ) {
24404
24405								geometry.maxInstancedCount = data.meshPerAttribute * data.count;
24406
24407							}
24408
24409						} else {
24410
24411							state.enableAttribute( programAttribute );
24412
24413						}
24414
24415						_gl.bindBuffer( 34962, buffer );
24416						state.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
24417
24418					} else {
24419
24420						if ( geometryAttribute.isInstancedBufferAttribute ) {
24421
24422							state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
24423
24424							if ( geometry.maxInstancedCount === undefined ) {
24425
24426								geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
24427
24428							}
24429
24430						} else {
24431
24432							state.enableAttribute( programAttribute );
24433
24434						}
24435
24436						_gl.bindBuffer( 34962, buffer );
24437						state.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
24438
24439					}
24440
24441				} else if ( name === 'instanceMatrix' ) {
24442
24443					var attribute = attributes.get( object.instanceMatrix );
24444
24445					// TODO Attribute may not be available on context restore
24446
24447					if ( attribute === undefined ) continue;
24448
24449					var buffer = attribute.buffer;
24450					var type = attribute.type;
24451
24452					state.enableAttributeAndDivisor( programAttribute + 0, 1 );
24453					state.enableAttributeAndDivisor( programAttribute + 1, 1 );
24454					state.enableAttributeAndDivisor( programAttribute + 2, 1 );
24455					state.enableAttributeAndDivisor( programAttribute + 3, 1 );
24456
24457					_gl.bindBuffer( 34962, buffer );
24458
24459					_gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );
24460					_gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );
24461					_gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );
24462					_gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );
24463
24464				} else if ( materialDefaultAttributeValues !== undefined ) {
24465
24466					var value = materialDefaultAttributeValues[ name ];
24467
24468					if ( value !== undefined ) {
24469
24470						switch ( value.length ) {
24471
24472							case 2:
24473								_gl.vertexAttrib2fv( programAttribute, value );
24474								break;
24475
24476							case 3:
24477								_gl.vertexAttrib3fv( programAttribute, value );
24478								break;
24479
24480							case 4:
24481								_gl.vertexAttrib4fv( programAttribute, value );
24482								break;
24483
24484							default:
24485								_gl.vertexAttrib1fv( programAttribute, value );
24486
24487						}
24488
24489					}
24490
24491				}
24492
24493			}
24494
24495		}
24496
24497		state.disableUnusedAttributes();
24498
24499	}
24500
24501	// Compile
24502
24503	this.compile = function ( scene, camera ) {
24504
24505		currentRenderState = renderStates.get( scene, camera );
24506		currentRenderState.init();
24507
24508		scene.traverse( function ( object ) {
24509
24510			if ( object.isLight ) {
24511
24512				currentRenderState.pushLight( object );
24513
24514				if ( object.castShadow ) {
24515
24516					currentRenderState.pushShadow( object );
24517
24518				}
24519
24520			}
24521
24522		} );
24523
24524		currentRenderState.setupLights( camera );
24525
24526		var compiled = {};
24527
24528		scene.traverse( function ( object ) {
24529
24530			if ( object.material ) {
24531
24532				if ( Array.isArray( object.material ) ) {
24533
24534					for ( var i = 0; i < object.material.length; i ++ ) {
24535
24536						if ( object.material[ i ].uuid in compiled === false ) {
24537
24538							initMaterial( object.material[ i ], scene, object );
24539							compiled[ object.material[ i ].uuid ] = true;
24540
24541						}
24542
24543					}
24544
24545				} else if ( object.material.uuid in compiled === false ) {
24546
24547					initMaterial( object.material, scene, object );
24548					compiled[ object.material.uuid ] = true;
24549
24550				}
24551
24552			}
24553
24554		} );
24555
24556	};
24557
24558	// Animation Loop
24559
24560	var onAnimationFrameCallback = null;
24561
24562	function onAnimationFrame( time ) {
24563
24564		if ( xr.isPresenting ) return;
24565		if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
24566
24567	}
24568
24569	var animation = new WebGLAnimation();
24570	animation.setAnimationLoop( onAnimationFrame );
24571
24572	if ( typeof window !== 'undefined' ) animation.setContext( window );
24573
24574	this.setAnimationLoop = function ( callback ) {
24575
24576		onAnimationFrameCallback = callback;
24577		xr.setAnimationLoop( callback );
24578
24579		animation.start();
24580
24581	};
24582
24583	// Rendering
24584
24585	this.render = function ( scene, camera ) {
24586
24587		var renderTarget, forceClear;
24588
24589		if ( arguments[ 2 ] !== undefined ) {
24590
24591			console.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
24592			renderTarget = arguments[ 2 ];
24593
24594		}
24595
24596		if ( arguments[ 3 ] !== undefined ) {
24597
24598			console.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );
24599			forceClear = arguments[ 3 ];
24600
24601		}
24602
24603		if ( ! ( camera && camera.isCamera ) ) {
24604
24605			console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
24606			return;
24607
24608		}
24609
24610		if ( _isContextLost ) return;
24611
24612		// reset caching for this frame
24613
24614		_currentGeometryProgram.geometry = null;
24615		_currentGeometryProgram.program = null;
24616		_currentGeometryProgram.wireframe = false;
24617		_currentMaterialId = - 1;
24618		_currentCamera = null;
24619
24620		// update scene graph
24621
24622		if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
24623
24624		// update camera matrices and frustum
24625
24626		if ( camera.parent === null ) camera.updateMatrixWorld();
24627
24628		if ( xr.enabled && xr.isPresenting ) {
24629
24630			camera = xr.getCamera( camera );
24631
24632		}
24633
24634		//
24635		scene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );
24636
24637		currentRenderState = renderStates.get( scene, camera );
24638		currentRenderState.init();
24639
24640		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
24641		_frustum.setFromProjectionMatrix( _projScreenMatrix );
24642
24643		_localClippingEnabled = this.localClippingEnabled;
24644		_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
24645
24646		currentRenderList = renderLists.get( scene, camera );
24647		currentRenderList.init();
24648
24649		projectObject( scene, camera, 0, _this.sortObjects );
24650
24651		currentRenderList.finish();
24652
24653		if ( _this.sortObjects === true ) {
24654
24655			currentRenderList.sort( _opaqueSort, _transparentSort );
24656
24657		}
24658
24659		//
24660
24661		if ( _clippingEnabled ) _clipping.beginShadows();
24662
24663		var shadowsArray = currentRenderState.state.shadowsArray;
24664
24665		shadowMap.render( shadowsArray, scene, camera );
24666
24667		currentRenderState.setupLights( camera );
24668
24669		if ( _clippingEnabled ) _clipping.endShadows();
24670
24671		//
24672
24673		if ( this.info.autoReset ) this.info.reset();
24674
24675		if ( renderTarget !== undefined ) {
24676
24677			this.setRenderTarget( renderTarget );
24678
24679		}
24680
24681		//
24682
24683		background.render( currentRenderList, scene, camera, forceClear );
24684
24685		// render scene
24686
24687		var opaqueObjects = currentRenderList.opaque;
24688		var transparentObjects = currentRenderList.transparent;
24689
24690		if ( scene.overrideMaterial ) {
24691
24692			var overrideMaterial = scene.overrideMaterial;
24693
24694			if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );
24695			if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );
24696
24697		} else {
24698
24699			// opaque pass (front-to-back order)
24700
24701			if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );
24702
24703			// transparent pass (back-to-front order)
24704
24705			if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );
24706
24707		}
24708
24709		//
24710
24711		scene.onAfterRender( _this, scene, camera );
24712
24713		//
24714
24715		if ( _currentRenderTarget !== null ) {
24716
24717			// Generate mipmap if we're using any kind of mipmap filtering
24718
24719			textures.updateRenderTargetMipmap( _currentRenderTarget );
24720
vendor: 4,701 bytes, lines 24721-24928
24721			// resolve multisample renderbuffers to a single-sample texture if necessary
24722
24723			textures.updateMultisampleRenderTarget( _currentRenderTarget );
24724
24725		}
24726
24727		// Ensure depth buffer writing is enabled so it can be cleared on next render
24728
24729		state.buffers.depth.setTest( true );
24730		state.buffers.depth.setMask( true );
24731		state.buffers.color.setMask( true );
24732
24733		state.setPolygonOffset( false );
24734
24735		// _gl.finish();
24736
24737		currentRenderList = null;
24738		currentRenderState = null;
24739
24740	};
24741
24742	function projectObject( object, camera, groupOrder, sortObjects ) {
24743
24744		if ( object.visible === false ) return;
24745
24746		var visible = object.layers.test( camera.layers );
24747
24748		if ( visible ) {
24749
24750			if ( object.isGroup ) {
24751
24752				groupOrder = object.renderOrder;
24753
24754			} else if ( object.isLOD ) {
24755
24756				if ( object.autoUpdate === true ) object.update( camera );
24757
24758			} else if ( object.isLight ) {
24759
24760				currentRenderState.pushLight( object );
24761
24762				if ( object.castShadow ) {
24763
24764					currentRenderState.pushShadow( object );
24765
24766				}
24767
24768			} else if ( object.isSprite ) {
24769
24770				if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
24771
24772					if ( sortObjects ) {
24773
24774						_vector3.setFromMatrixPosition( object.matrixWorld )
24775							.applyMatrix4( _projScreenMatrix );
24776
24777					}
24778
24779					var geometry = objects.update( object );
24780					var material = object.material;
24781
24782					if ( material.visible ) {
24783
24784						currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
24785
24786					}
24787
24788				}
24789
24790			} else if ( object.isImmediateRenderObject ) {
24791
24792				if ( sortObjects ) {
24793
24794					_vector3.setFromMatrixPosition( object.matrixWorld )
24795						.applyMatrix4( _projScreenMatrix );
24796
24797				}
24798
24799				currentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );
24800
24801			} else if ( object.isMesh || object.isLine || object.isPoints ) {
24802
24803				if ( object.isSkinnedMesh ) {
24804
24805					// update skeleton only once in a frame
24806
24807					if ( object.skeleton.frame !== info.render.frame ) {
24808
24809						object.skeleton.update();
24810						object.skeleton.frame = info.render.frame;
24811
24812					}
24813
24814				}
24815
24816				if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
24817
24818					if ( sortObjects ) {
24819
24820						_vector3.setFromMatrixPosition( object.matrixWorld )
24821							.applyMatrix4( _projScreenMatrix );
24822
24823					}
24824
24825					var geometry = objects.update( object );
24826					var material = object.material;
24827
24828					if ( Array.isArray( material ) ) {
24829
24830						var groups = geometry.groups;
24831
24832						for ( var i = 0, l = groups.length; i < l; i ++ ) {
24833
24834							var group = groups[ i ];
24835							var groupMaterial = material[ group.materialIndex ];
24836
24837							if ( groupMaterial && groupMaterial.visible ) {
24838
24839								currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
24840
24841							}
24842
24843						}
24844
24845					} else if ( material.visible ) {
24846
24847						currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
24848
24849					}
24850
24851				}
24852
24853			}
24854
24855		}
24856
24857		var children = object.children;
24858
24859		for ( var i = 0, l = children.length; i < l; i ++ ) {
24860
24861			projectObject( children[ i ], camera, groupOrder, sortObjects );
24862
24863		}
24864
24865	}
24866
24867	function renderObjects( renderList, scene, camera, overrideMaterial ) {
24868
24869		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
24870
24871			var renderItem = renderList[ i ];
24872
24873			var object = renderItem.object;
24874			var geometry = renderItem.geometry;
24875			var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
24876			var group = renderItem.group;
24877
24878			if ( camera.isArrayCamera ) {
24879
24880				_currentArrayCamera = camera;
24881
24882				var cameras = camera.cameras;
24883
24884				for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
24885
24886					var camera2 = cameras[ j ];
24887
24888					if ( object.layers.test( camera2.layers ) ) {
24889
24890						state.viewport( _currentViewport.copy( camera2.viewport ) );
24891
24892						currentRenderState.setupLights( camera2 );
24893
24894						renderObject( object, scene, camera2, geometry, material, group );
24895
24896					}
24897
24898				}
24899
24900			} else {
24901
24902				_currentArrayCamera = null;
24903
24904				renderObject( object, scene, camera, geometry, material, group );
24905
24906			}
24907
24908		}
24909
24910	}
24911
24912	function renderObject( object, scene, camera, geometry, material, group ) {
24913
24914		object.onBeforeRender( _this, scene, camera, geometry, material, group );
24915		currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
24916
24917		object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
24918		object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
24919
24920		if ( object.isImmediateRenderObject ) {
24921
24922			var program = setProgram( camera, scene, material, object );
24923
24924			state.setMaterial( material );
24925
24926			_currentGeometryProgram.geometry = null;
24927			_currentGeometryProgram.program = null;
24928			_currentGeometryProgram.wireframe = false;
24929
24930			renderObjectImmediate( object, program );
24931
24932		} else {
24933
24934			_this.renderBufferDirect( camera, scene, geometry, material, object, group );
24935
24936		}
24937
24938		object.onAfterRender( _this, scene, camera, geometry, material, group );
24939		currentRenderState = renderStates.get( scene, _currentArrayCamera || camera );
24940
24941	}
24942
24943	function initMaterial( material, scene, object ) {
24944
24945		var materialProperties = properties.get( material );
24946
24947		var lights = currentRenderState.state.lights;
24948		var shadowsArray = currentRenderState.state.shadowsArray;
24949
24950		var lightsStateVersion = lights.state.version;
24951
24952		var parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, _clipping.numPlanes, _clipping.numIntersection, object );
24953		var programCacheKey = programCache.getProgramCacheKey( parameters );
24954
24955		var program = materialProperties.program;
24956		var programChange = true;
24957
24958		if ( program === undefined ) {
24959
24960			// new material
24961			material.addEventListener( 'dispose', onMaterialDispose );
24962
24963		} else if ( program.cacheKey !== programCacheKey ) {
24964
24965			// changed glsl or parameters
24966			releaseMaterialProgramReference( material );
24967
24968		} else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {
24969
24970			materialProperties.lightsStateVersion = lightsStateVersion;
24971
24972			programChange = false;
24973
24974		} else if ( parameters.shaderID !== undefined ) {
24975
24976			// same glsl and uniform list
24977			return;
24978
24979		} else {
24980
24981			// only rebuild uniform list
24982			programChange = false;
24983
24984		}
24985
24986		if ( programChange ) {
24987
24988			program = programCache.acquireProgram( parameters, programCacheKey );
24989
24990			materialProperties.program = program;
24991			materialProperties.uniforms = parameters.uniforms;
24992			materialProperties.outputEncoding = parameters.outputEncoding;
24993			material.program = program;
24994
24995		}
24996
24997		var programAttributes = program.getAttributes();
24998
24999		if ( material.morphTargets ) {
25000
25001			material.numSupportedMorphTargets = 0;
25002
25003			for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
25004
25005				if ( programAttributes[ 'morphTarget' + i ] >= 0 ) {
25006
25007					material.numSupportedMorphTargets ++;
25008
25009				}
25010
25011			}
25012
25013		}
25014
25015		if ( material.morphNormals ) {
25016
25017			material.numSupportedMorphNormals = 0;
25018
25019			for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
25020
25021				if ( programAttributes[ 'morphNormal' + i ] >= 0 ) {
25022
25023					material.numSupportedMorphNormals ++;
25024
25025				}
25026
25027			}
25028
25029		}
25030
25031		var uniforms = materialProperties.uniforms;
25032
25033		if ( ! material.isShaderMaterial &&
25034			! material.isRawShaderMaterial ||
25035			material.clipping === true ) {
25036
25037			materialProperties.numClippingPlanes = _clipping.numPlanes;
25038			materialProperties.numIntersection = _clipping.numIntersection;
25039			uniforms.clippingPlanes = _clipping.uniform;
25040
25041		}
25042
25043		materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
25044		materialProperties.fog = scene.fog;
25045
25046		// store the light setup it was created for
25047
25048		materialProperties.needsLights = materialNeedsLights( material );
25049		materialProperties.lightsStateVersion = lightsStateVersion;
25050
25051		if ( materialProperties.needsLights ) {
25052
25053			// wire up the material to this renderer's lighting state
25054
25055			uniforms.ambientLightColor.value = lights.state.ambient;
25056			uniforms.lightProbe.value = lights.state.probe;
25057			uniforms.directionalLights.value = lights.state.directional;
25058			uniforms.directionalLightShadows.value = lights.state.directionalShadow;
25059			uniforms.spotLights.value = lights.state.spot;
25060			uniforms.spotLightShadows.value = lights.state.spotShadow;
25061			uniforms.rectAreaLights.value = lights.state.rectArea;
25062			uniforms.pointLights.value = lights.state.point;
25063			uniforms.pointLightShadows.value = lights.state.pointShadow;
25064			uniforms.hemisphereLights.value = lights.state.hemi;
25065
25066			uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
25067			uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
25068			uniforms.spotShadowMap.value = lights.state.spotShadowMap;
25069			uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;
25070			uniforms.pointShadowMap.value = lights.state.pointShadowMap;
25071			uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
25072			// TODO (abelnation): add area lights shadow info to uniforms
25073
25074		}
25075
25076		var progUniforms = materialProperties.program.getUniforms(),
25077			uniformsList =
25078				WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
25079
25080		materialProperties.uniformsList = uniformsList;
25081
25082	}
25083
25084	function setProgram( camera, scene, material, object ) {
25085
25086		textures.resetTextureUnits();
25087
25088		var fog = scene.fog;
25089		var environment = material.isMeshStandardMaterial ? scene.environment : null;
25090		var encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
25091
25092		var materialProperties = properties.get( material );
25093		var lights = currentRenderState.state.lights;
25094
25095		if ( _clippingEnabled ) {
25096
25097			if ( _localClippingEnabled || camera !== _currentCamera ) {
25098
25099				var useCache =
25100					camera === _currentCamera &&
25101					material.id === _currentMaterialId;
25102
25103				// we might want to call this function with some ClippingGroup
25104				// object instead of the material, once it becomes feasible
25105				// (#8465, #8379)
25106				_clipping.setState(
25107					material.clippingPlanes, material.clipIntersection, material.clipShadows,
25108					camera, materialProperties, useCache );
25109
25110			}
25111
25112		}
25113
25114		if ( material.version === materialProperties.__version ) {
25115
25116			if ( materialProperties.program === undefined ) {
25117
25118				initMaterial( material, scene, object );
25119
25120			} else if ( material.fog && materialProperties.fog !== fog ) {
25121
25122				initMaterial( material, scene, object );
25123
25124			} else if ( materialProperties.environment !== environment ) {
25125
25126				initMaterial( material, scene, object );
25127
25128			} else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
25129
25130				initMaterial( material, scene, object );
25131
25132			} else if ( materialProperties.numClippingPlanes !== undefined &&
25133				( materialProperties.numClippingPlanes !== _clipping.numPlanes ||
25134				materialProperties.numIntersection !== _clipping.numIntersection ) ) {
25135
25136				initMaterial( material, scene, object );
25137
25138			} else if ( materialProperties.outputEncoding !== encoding ) {
25139
25140				initMaterial( material, scene, object );
25141
25142			}
25143
25144		} else {
25145
25146			initMaterial( material, scene, object );
25147			materialProperties.__version = material.version;
25148
25149		}
25150
25151		var refreshProgram = false;
25152		var refreshMaterial = false;
25153		var refreshLights = false;
25154
25155		var program = materialProperties.program,
25156			p_uniforms = program.getUniforms(),
25157			m_uniforms = materialProperties.uniforms;
25158
25159		if ( state.useProgram( program.program ) ) {
25160
25161			refreshProgram = true;
25162			refreshMaterial = true;
25163			refreshLights = true;
25164
25165		}
25166
25167		if ( material.id !== _currentMaterialId ) {
25168
25169			_currentMaterialId = material.id;
25170
25171			refreshMaterial = true;
25172
25173		}
25174
25175		if ( refreshProgram || _currentCamera !== camera ) {
25176
25177			p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
25178
25179			if ( capabilities.logarithmicDepthBuffer ) {
25180
25181				p_uniforms.setValue( _gl, 'logDepthBufFC',
25182					2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
25183
25184			}
25185
vendor: 41,417 bytes, lines 25186-27123
25186			if ( _currentCamera !== camera ) {
25187
25188				_currentCamera = camera;
25189
25190				// lighting uniforms depend on the camera so enforce an update
25191				// now, in case this material supports lights - or later, when
25192				// the next material that does gets activated:
25193
25194				refreshMaterial = true;		// set to true on material change
25195				refreshLights = true;		// remains set until update done
25196
25197			}
25198
25199			// load material specific uniforms
25200			// (shader material also gets them for the sake of genericity)
25201
25202			if ( material.isShaderMaterial ||
25203				material.isMeshPhongMaterial ||
25204				material.isMeshToonMaterial ||
25205				material.isMeshStandardMaterial ||
25206				material.envMap ) {
25207
25208				var uCamPos = p_uniforms.map.cameraPosition;
25209
25210				if ( uCamPos !== undefined ) {
25211
25212					uCamPos.setValue( _gl,
25213						_vector3.setFromMatrixPosition( camera.matrixWorld ) );
25214
25215				}
25216
25217			}
25218
25219			if ( material.isMeshPhongMaterial ||
25220				material.isMeshToonMaterial ||
25221				material.isMeshLambertMaterial ||
25222				material.isMeshBasicMaterial ||
25223				material.isMeshStandardMaterial ||
25224				material.isShaderMaterial ) {
25225
25226				p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
25227
25228			}
25229
25230			if ( material.isMeshPhongMaterial ||
25231				material.isMeshToonMaterial ||
25232				material.isMeshLambertMaterial ||
25233				material.isMeshBasicMaterial ||
25234				material.isMeshStandardMaterial ||
25235				material.isShaderMaterial ||
25236				material.skinning ) {
25237
25238				p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
25239
25240			}
25241
25242		}
25243
25244		// skinning uniforms must be set even if material didn't change
25245		// auto-setting of texture unit for bone texture must go before other textures
25246		// otherwise textures used for skinning can take over texture units reserved for other material textures
25247
25248		if ( material.skinning ) {
25249
25250			p_uniforms.setOptional( _gl, object, 'bindMatrix' );
25251			p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
25252
25253			var skeleton = object.skeleton;
25254
25255			if ( skeleton ) {
25256
25257				var bones = skeleton.bones;
25258
25259				if ( capabilities.floatVertexTextures ) {
25260
25261					if ( skeleton.boneTexture === undefined ) {
25262
25263						// layout (1 matrix = 4 pixels)
25264						//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
25265						//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
25266						//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
25267						//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
25268						//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
25269
25270
25271						var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
25272						size = MathUtils.ceilPowerOfTwo( size );
25273						size = Math.max( size, 4 );
25274
25275						var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
25276						boneMatrices.set( skeleton.boneMatrices ); // copy current values
25277
25278						var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
25279
25280						skeleton.boneMatrices = boneMatrices;
25281						skeleton.boneTexture = boneTexture;
25282						skeleton.boneTextureSize = size;
25283
25284					}
25285
25286					p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
25287					p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
25288
25289				} else {
25290
25291					p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );
25292
25293				}
25294
25295			}
25296
25297		}
25298
25299		if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
25300
25301			materialProperties.receiveShadow = object.receiveShadow;
25302			p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
25303
25304		}
25305
25306		if ( refreshMaterial ) {
25307
25308			p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
25309			p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );
25310
25311			if ( materialProperties.needsLights ) {
25312
25313				// the current material requires lighting info
25314
25315				// note: all lighting uniforms are always set correctly
25316				// they simply reference the renderer's state for their
25317				// values
25318				//
25319				// use the current material's .needsUpdate flags to set
25320				// the GL state when required
25321
25322				markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
25323
25324			}
25325
25326			// refresh uniforms common to several materials
25327
25328			if ( fog && material.fog ) {
25329
25330				refreshUniformsFog( m_uniforms, fog );
25331
25332			}
25333
25334			if ( material.isMeshBasicMaterial ) {
25335
25336				refreshUniformsCommon( m_uniforms, material );
25337
25338			} else if ( material.isMeshLambertMaterial ) {
25339
25340				refreshUniformsCommon( m_uniforms, material );
25341				refreshUniformsLambert( m_uniforms, material );
25342
25343			} else if ( material.isMeshToonMaterial ) {
25344
25345				refreshUniformsCommon( m_uniforms, material );
25346				refreshUniformsToon( m_uniforms, material );
25347
25348			} else if ( material.isMeshPhongMaterial ) {
25349
25350				refreshUniformsCommon( m_uniforms, material );
25351				refreshUniformsPhong( m_uniforms, material );
25352
25353			} else if ( material.isMeshStandardMaterial ) {
25354
25355				refreshUniformsCommon( m_uniforms, material, environment );
25356
25357				if ( material.isMeshPhysicalMaterial ) {
25358
25359					refreshUniformsPhysical( m_uniforms, material, environment );
25360
25361				} else {
25362
25363					refreshUniformsStandard( m_uniforms, material, environment );
25364
25365				}
25366
25367			} else if ( material.isMeshMatcapMaterial ) {
25368
25369				refreshUniformsCommon( m_uniforms, material );
25370				refreshUniformsMatcap( m_uniforms, material );
25371
25372			} else if ( material.isMeshDepthMaterial ) {
25373
25374				refreshUniformsCommon( m_uniforms, material );
25375				refreshUniformsDepth( m_uniforms, material );
25376
25377			} else if ( material.isMeshDistanceMaterial ) {
25378
25379				refreshUniformsCommon( m_uniforms, material );
25380				refreshUniformsDistance( m_uniforms, material );
25381
25382			} else if ( material.isMeshNormalMaterial ) {
25383
25384				refreshUniformsCommon( m_uniforms, material );
25385				refreshUniformsNormal( m_uniforms, material );
25386
25387			} else if ( material.isLineBasicMaterial ) {
25388
25389				refreshUniformsLine( m_uniforms, material );
25390
25391				if ( material.isLineDashedMaterial ) {
25392
25393					refreshUniformsDash( m_uniforms, material );
25394
25395				}
25396
25397			} else if ( material.isPointsMaterial ) {
25398
25399				refreshUniformsPoints( m_uniforms, material );
25400
25401			} else if ( material.isSpriteMaterial ) {
25402
25403				refreshUniformsSprites( m_uniforms, material );
25404
25405			} else if ( material.isShadowMaterial ) {
25406
25407				m_uniforms.color.value.copy( material.color );
25408				m_uniforms.opacity.value = material.opacity;
25409
25410			}
25411
25412			// RectAreaLight Texture
25413			// TODO (mrdoob): Find a nicer implementation
25414
25415			if ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1;
25416			if ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2;
25417
25418			WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
25419
25420			if ( material.isShaderMaterial ) {
25421
25422				material.uniformsNeedUpdate = false; // #15581
25423
25424			}
25425
25426		}
25427
25428		if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
25429
25430			WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
25431			material.uniformsNeedUpdate = false;
25432
25433		}
25434
25435		if ( material.isSpriteMaterial ) {
25436
25437			p_uniforms.setValue( _gl, 'center', object.center );
25438
25439		}
25440
25441		// common matrices
25442
25443		p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
25444		p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
25445		p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
25446
25447		return program;
25448
25449	}
25450
25451	// Uniforms (refresh uniforms objects)
25452
25453	function refreshUniformsCommon( uniforms, material, environment ) {
25454
25455		uniforms.opacity.value = material.opacity;
25456
25457		if ( material.color ) {
25458
25459			uniforms.diffuse.value.copy( material.color );
25460
25461		}
25462
25463		if ( material.emissive ) {
25464
25465			uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
25466
25467		}
25468
25469		if ( material.map ) {
25470
25471			uniforms.map.value = material.map;
25472
25473		}
25474
25475		if ( material.alphaMap ) {
25476
25477			uniforms.alphaMap.value = material.alphaMap;
25478
25479		}
25480
25481		if ( material.specularMap ) {
25482
25483			uniforms.specularMap.value = material.specularMap;
25484
25485		}
25486
25487		var envMap = material.envMap || environment;
25488
25489		if ( envMap ) {
25490
25491			uniforms.envMap.value = envMap;
25492
25493			uniforms.flipEnvMap.value = envMap.isCubeTexture ? - 1 : 1;
25494
25495			uniforms.reflectivity.value = material.reflectivity;
25496			uniforms.refractionRatio.value = material.refractionRatio;
25497
25498			uniforms.maxMipLevel.value = properties.get( envMap ).__maxMipLevel;
25499
25500		}
25501
25502		if ( material.lightMap ) {
25503
25504			uniforms.lightMap.value = material.lightMap;
25505			uniforms.lightMapIntensity.value = material.lightMapIntensity;
25506
25507		}
25508
25509		if ( material.aoMap ) {
25510
25511			uniforms.aoMap.value = material.aoMap;
25512			uniforms.aoMapIntensity.value = material.aoMapIntensity;
25513
25514		}
25515
25516		// uv repeat and offset setting priorities
25517		// 1. color map
25518		// 2. specular map
25519		// 3. normal map
25520		// 4. bump map
25521		// 5. alpha map
25522		// 6. emissive map
25523
25524		var uvScaleMap;
25525
25526		if ( material.map ) {
25527
25528			uvScaleMap = material.map;
25529
25530		} else if ( material.specularMap ) {
25531
25532			uvScaleMap = material.specularMap;
25533
25534		} else if ( material.displacementMap ) {
25535
25536			uvScaleMap = material.displacementMap;
25537
25538		} else if ( material.normalMap ) {
25539
25540			uvScaleMap = material.normalMap;
25541
25542		} else if ( material.bumpMap ) {
25543
25544			uvScaleMap = material.bumpMap;
25545
25546		} else if ( material.roughnessMap ) {
25547
25548			uvScaleMap = material.roughnessMap;
25549
25550		} else if ( material.metalnessMap ) {
25551
25552			uvScaleMap = material.metalnessMap;
25553
25554		} else if ( material.alphaMap ) {
25555
25556			uvScaleMap = material.alphaMap;
25557
25558		} else if ( material.emissiveMap ) {
25559
25560			uvScaleMap = material.emissiveMap;
25561
25562		}
25563
25564		if ( uvScaleMap !== undefined ) {
25565
25566			// backwards compatibility
25567			if ( uvScaleMap.isWebGLRenderTarget ) {
25568
25569				uvScaleMap = uvScaleMap.texture;
25570
25571			}
25572
25573			if ( uvScaleMap.matrixAutoUpdate === true ) {
25574
25575				uvScaleMap.updateMatrix();
25576
25577			}
25578
25579			uniforms.uvTransform.value.copy( uvScaleMap.matrix );
25580
25581		}
25582
25583		// uv repeat and offset setting priorities for uv2
25584		// 1. ao map
25585		// 2. light map
25586
25587		var uv2ScaleMap;
25588
25589		if ( material.aoMap ) {
25590
25591			uv2ScaleMap = material.aoMap;
25592
25593		} else if ( material.lightMap ) {
25594
25595			uv2ScaleMap = material.lightMap;
25596
25597		}
25598
25599		if ( uv2ScaleMap !== undefined ) {
25600
25601			// backwards compatibility
25602			if ( uv2ScaleMap.isWebGLRenderTarget ) {
25603
25604				uv2ScaleMap = uv2ScaleMap.texture;
25605
25606			}
25607
25608			if ( uv2ScaleMap.matrixAutoUpdate === true ) {
25609
25610				uv2ScaleMap.updateMatrix();
25611
25612			}
25613
25614			uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );
25615
25616		}
25617
25618	}
25619
25620	function refreshUniformsLine( uniforms, material ) {
25621
25622		uniforms.diffuse.value.copy( material.color );
25623		uniforms.opacity.value = material.opacity;
25624
25625	}
25626
25627	function refreshUniformsDash( uniforms, material ) {
25628
25629		uniforms.dashSize.value = material.dashSize;
25630		uniforms.totalSize.value = material.dashSize + material.gapSize;
25631		uniforms.scale.value = material.scale;
25632
25633	}
25634
25635	function refreshUniformsPoints( uniforms, material ) {
25636
25637		uniforms.diffuse.value.copy( material.color );
25638		uniforms.opacity.value = material.opacity;
25639		uniforms.size.value = material.size * _pixelRatio;
25640		uniforms.scale.value = _height * 0.5;
25641
25642		if ( material.map ) {
25643
25644			uniforms.map.value = material.map;
25645
25646		}
25647
25648		if ( material.alphaMap ) {
25649
25650			uniforms.alphaMap.value = material.alphaMap;
25651
25652		}
25653
25654		// uv repeat and offset setting priorities
25655		// 1. color map
25656		// 2. alpha map
25657
25658		var uvScaleMap;
25659
25660		if ( material.map ) {
25661
25662			uvScaleMap = material.map;
25663
25664		} else if ( material.alphaMap ) {
25665
25666			uvScaleMap = material.alphaMap;
25667
25668		}
25669
25670		if ( uvScaleMap !== undefined ) {
25671
25672			if ( uvScaleMap.matrixAutoUpdate === true ) {
25673
25674				uvScaleMap.updateMatrix();
25675
25676			}
25677
25678			uniforms.uvTransform.value.copy( uvScaleMap.matrix );
25679
25680		}
25681
25682	}
25683
25684	function refreshUniformsSprites( uniforms, material ) {
25685
25686		uniforms.diffuse.value.copy( material.color );
25687		uniforms.opacity.value = material.opacity;
25688		uniforms.rotation.value = material.rotation;
25689
25690		if ( material.map ) {
25691
25692			uniforms.map.value = material.map;
25693
25694		}
25695
25696		if ( material.alphaMap ) {
25697
25698			uniforms.alphaMap.value = material.alphaMap;
25699
25700		}
25701
25702		// uv repeat and offset setting priorities
25703		// 1. color map
25704		// 2. alpha map
25705
25706		var uvScaleMap;
25707
25708		if ( material.map ) {
25709
25710			uvScaleMap = material.map;
25711
25712		} else if ( material.alphaMap ) {
25713
25714			uvScaleMap = material.alphaMap;
25715
25716		}
25717
25718		if ( uvScaleMap !== undefined ) {
25719
25720			if ( uvScaleMap.matrixAutoUpdate === true ) {
25721
25722				uvScaleMap.updateMatrix();
25723
25724			}
25725
25726			uniforms.uvTransform.value.copy( uvScaleMap.matrix );
25727
25728		}
25729
25730	}
25731
25732	function refreshUniformsFog( uniforms, fog ) {
25733
25734		uniforms.fogColor.value.copy( fog.color );
25735
25736		if ( fog.isFog ) {
25737
25738			uniforms.fogNear.value = fog.near;
25739			uniforms.fogFar.value = fog.far;
25740
25741		} else if ( fog.isFogExp2 ) {
25742
25743			uniforms.fogDensity.value = fog.density;
25744
25745		}
25746
25747	}
25748
25749	function refreshUniformsLambert( uniforms, material ) {
25750
25751		if ( material.emissiveMap ) {
25752
25753			uniforms.emissiveMap.value = material.emissiveMap;
25754
25755		}
25756
25757	}
25758
25759	function refreshUniformsPhong( uniforms, material ) {
25760
25761		uniforms.specular.value.copy( material.specular );
25762		uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
25763
25764		if ( material.emissiveMap ) {
25765
25766			uniforms.emissiveMap.value = material.emissiveMap;
25767
25768		}
25769
25770		if ( material.bumpMap ) {
25771
25772			uniforms.bumpMap.value = material.bumpMap;
25773			uniforms.bumpScale.value = material.bumpScale;
25774			if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
25775
25776		}
25777
25778		if ( material.normalMap ) {
25779
25780			uniforms.normalMap.value = material.normalMap;
25781			uniforms.normalScale.value.copy( material.normalScale );
25782			if ( material.side === BackSide ) uniforms.normalScale.value.negate();
25783
25784		}
25785
25786		if ( material.displacementMap ) {
25787
25788			uniforms.displacementMap.value = material.displacementMap;
25789			uniforms.displacementScale.value = material.displacementScale;
25790			uniforms.displacementBias.value = material.displacementBias;
25791
25792		}
25793
25794	}
25795
25796	function refreshUniformsToon( uniforms, material ) {
25797
25798		uniforms.specular.value.copy( material.specular );
25799		uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
25800
25801		if ( material.gradientMap ) {
25802
25803			uniforms.gradientMap.value = material.gradientMap;
25804
25805		}
25806
25807		if ( material.emissiveMap ) {
25808
25809			uniforms.emissiveMap.value = material.emissiveMap;
25810
25811		}
25812
25813		if ( material.bumpMap ) {
25814
25815			uniforms.bumpMap.value = material.bumpMap;
25816			uniforms.bumpScale.value = material.bumpScale;
25817			if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
25818
25819		}
25820
25821		if ( material.normalMap ) {
25822
25823			uniforms.normalMap.value = material.normalMap;
25824			uniforms.normalScale.value.copy( material.normalScale );
25825			if ( material.side === BackSide ) uniforms.normalScale.value.negate();
25826
25827		}
25828
25829		if ( material.displacementMap ) {
25830
25831			uniforms.displacementMap.value = material.displacementMap;
25832			uniforms.displacementScale.value = material.displacementScale;
25833			uniforms.displacementBias.value = material.displacementBias;
25834
25835		}
25836
25837	}
25838
25839	function refreshUniformsStandard( uniforms, material, environment ) {
25840
25841		uniforms.roughness.value = material.roughness;
25842		uniforms.metalness.value = material.metalness;
25843
25844		if ( material.roughnessMap ) {
25845
25846			uniforms.roughnessMap.value = material.roughnessMap;
25847
25848		}
25849
25850		if ( material.metalnessMap ) {
25851
25852			uniforms.metalnessMap.value = material.metalnessMap;
25853
25854		}
25855
25856		if ( material.emissiveMap ) {
25857
25858			uniforms.emissiveMap.value = material.emissiveMap;
25859
25860		}
25861
25862		if ( material.bumpMap ) {
25863
25864			uniforms.bumpMap.value = material.bumpMap;
25865			uniforms.bumpScale.value = material.bumpScale;
25866			if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
25867
25868		}
25869
25870		if ( material.normalMap ) {
25871
25872			uniforms.normalMap.value = material.normalMap;
25873			uniforms.normalScale.value.copy( material.normalScale );
25874			if ( material.side === BackSide ) uniforms.normalScale.value.negate();
25875
25876		}
25877
25878		if ( material.displacementMap ) {
25879
25880			uniforms.displacementMap.value = material.displacementMap;
25881			uniforms.displacementScale.value = material.displacementScale;
25882			uniforms.displacementBias.value = material.displacementBias;
25883
25884		}
25885
25886		if ( material.envMap || environment ) {
25887
25888			//uniforms.envMap.value = material.envMap; // part of uniforms common
25889			uniforms.envMapIntensity.value = material.envMapIntensity;
25890
25891		}
25892
25893	}
25894
25895	function refreshUniformsPhysical( uniforms, material, environment ) {
25896
25897		refreshUniformsStandard( uniforms, material, environment );
25898
25899		uniforms.reflectivity.value = material.reflectivity; // also part of uniforms common
25900
25901		uniforms.clearcoat.value = material.clearcoat;
25902		uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
25903		if ( material.sheen ) uniforms.sheen.value.copy( material.sheen );
25904
25905		if ( material.clearcoatMap ) {
25906
25907			uniforms.clearcoatMap.value = material.clearcoatMap;
25908
25909		}
25910
25911		if ( material.clearcoatRoughnessMap ) {
25912
25913			uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
25914
25915		}
25916
25917		if ( material.clearcoatNormalMap ) {
25918
25919			uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
25920			uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
25921
25922			if ( material.side === BackSide ) {
25923
25924				uniforms.clearcoatNormalScale.value.negate();
25925
25926			}
25927
25928		}
25929
25930		uniforms.transparency.value = material.transparency;
25931
25932	}
25933
25934	function refreshUniformsMatcap( uniforms, material ) {
25935
25936		if ( material.matcap ) {
25937
25938			uniforms.matcap.value = material.matcap;
25939
25940		}
25941
25942		if ( material.bumpMap ) {
25943
25944			uniforms.bumpMap.value = material.bumpMap;
25945			uniforms.bumpScale.value = material.bumpScale;
25946			if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
25947
25948		}
25949
25950		if ( material.normalMap ) {
25951
25952			uniforms.normalMap.value = material.normalMap;
25953			uniforms.normalScale.value.copy( material.normalScale );
25954			if ( material.side === BackSide ) uniforms.normalScale.value.negate();
25955
25956		}
25957
25958		if ( material.displacementMap ) {
25959
25960			uniforms.displacementMap.value = material.displacementMap;
25961			uniforms.displacementScale.value = material.displacementScale;
25962			uniforms.displacementBias.value = material.displacementBias;
25963
25964		}
25965
25966	}
25967
25968	function refreshUniformsDepth( uniforms, material ) {
25969
25970		if ( material.displacementMap ) {
25971
25972			uniforms.displacementMap.value = material.displacementMap;
25973			uniforms.displacementScale.value = material.displacementScale;
25974			uniforms.displacementBias.value = material.displacementBias;
25975
25976		}
25977
25978	}
25979
25980	function refreshUniformsDistance( uniforms, material ) {
25981
25982		if ( material.displacementMap ) {
25983
25984			uniforms.displacementMap.value = material.displacementMap;
25985			uniforms.displacementScale.value = material.displacementScale;
25986			uniforms.displacementBias.value = material.displacementBias;
25987
25988		}
25989
25990		uniforms.referencePosition.value.copy( material.referencePosition );
25991		uniforms.nearDistance.value = material.nearDistance;
25992		uniforms.farDistance.value = material.farDistance;
25993
25994	}
25995
25996	function refreshUniformsNormal( uniforms, material ) {
25997
25998		if ( material.bumpMap ) {
25999
26000			uniforms.bumpMap.value = material.bumpMap;
26001			uniforms.bumpScale.value = material.bumpScale;
26002			if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
26003
26004		}
26005
26006		if ( material.normalMap ) {
26007
26008			uniforms.normalMap.value = material.normalMap;
26009			uniforms.normalScale.value.copy( material.normalScale );
26010			if ( material.side === BackSide ) uniforms.normalScale.value.negate();
26011
26012		}
26013
26014		if ( material.displacementMap ) {
26015
26016			uniforms.displacementMap.value = material.displacementMap;
26017			uniforms.displacementScale.value = material.displacementScale;
26018			uniforms.displacementBias.value = material.displacementBias;
26019
26020		}
26021
26022	}
26023
26024	// If uniforms are marked as clean, they don't need to be loaded to the GPU.
26025
26026	function markUniformsLightsNeedsUpdate( uniforms, value ) {
26027
26028		uniforms.ambientLightColor.needsUpdate = value;
26029		uniforms.lightProbe.needsUpdate = value;
26030
26031		uniforms.directionalLights.needsUpdate = value;
26032		uniforms.directionalLightShadows.needsUpdate = value;
26033		uniforms.pointLights.needsUpdate = value;
26034		uniforms.pointLightShadows.needsUpdate = value;
26035		uniforms.spotLights.needsUpdate = value;
26036		uniforms.spotLightShadows.needsUpdate = value;
26037		uniforms.rectAreaLights.needsUpdate = value;
26038		uniforms.hemisphereLights.needsUpdate = value;
26039
26040	}
26041
26042	function materialNeedsLights( material ) {
26043
26044		return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
26045			material.isMeshStandardMaterial || material.isShadowMaterial ||
26046			( material.isShaderMaterial && material.lights === true );
26047
26048	}
26049
26050	//
26051	this.setFramebuffer = function ( value ) {
26052
26053		if ( _framebuffer !== value && _currentRenderTarget === null ) _gl.bindFramebuffer( 36160, value );
26054
26055		_framebuffer = value;
26056
26057	};
26058
26059	this.getActiveCubeFace = function () {
26060
26061		return _currentActiveCubeFace;
26062
26063	};
26064
26065	this.getActiveMipmapLevel = function () {
26066
26067		return _currentActiveMipmapLevel;
26068
26069	};
26070
26071	this.getRenderTarget = function () {
26072
26073		return _currentRenderTarget;
26074
26075	};
26076
26077	this.setRenderTarget = function ( renderTarget, activeCubeFace, activeMipmapLevel ) {
26078
26079		_currentRenderTarget = renderTarget;
26080		_currentActiveCubeFace = activeCubeFace;
26081		_currentActiveMipmapLevel = activeMipmapLevel;
26082
26083		if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
26084
26085			textures.setupRenderTarget( renderTarget );
26086
26087		}
26088
26089		var framebuffer = _framebuffer;
26090		var isCube = false;
26091
26092		if ( renderTarget ) {
26093
26094			var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
26095
26096			if ( renderTarget.isWebGLCubeRenderTarget ) {
26097
26098				framebuffer = __webglFramebuffer[ activeCubeFace || 0 ];
26099				isCube = true;
26100
26101			} else if ( renderTarget.isWebGLMultisampleRenderTarget ) {
26102
26103				framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
26104
26105			} else {
26106
26107				framebuffer = __webglFramebuffer;
26108
26109			}
26110
26111			_currentViewport.copy( renderTarget.viewport );
26112			_currentScissor.copy( renderTarget.scissor );
26113			_currentScissorTest = renderTarget.scissorTest;
26114
26115		} else {
26116
26117			_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
26118			_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
26119			_currentScissorTest = _scissorTest;
26120
26121		}
26122
26123		if ( _currentFramebuffer !== framebuffer ) {
26124
26125			_gl.bindFramebuffer( 36160, framebuffer );
26126			_currentFramebuffer = framebuffer;
26127
26128		}
26129
26130		state.viewport( _currentViewport );
26131		state.scissor( _currentScissor );
26132		state.setScissorTest( _currentScissorTest );
26133
26134		if ( isCube ) {
26135
26136			var textureProperties = properties.get( renderTarget.texture );
26137			_gl.framebufferTexture2D( 36160, 36064, 34069 + ( activeCubeFace || 0 ), textureProperties.__webglTexture, activeMipmapLevel || 0 );
26138
26139		}
26140
26141	};
26142
26143	this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
26144
26145		if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
26146
26147			console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
26148			return;
26149
26150		}
26151
26152		var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
26153
26154		if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
26155
26156			framebuffer = framebuffer[ activeCubeFaceIndex ];
26157
26158		}
26159
26160		if ( framebuffer ) {
26161
26162			var restore = false;
26163
26164			if ( framebuffer !== _currentFramebuffer ) {
26165
26166				_gl.bindFramebuffer( 36160, framebuffer );
26167
26168				restore = true;
26169
26170			}
26171
26172			try {
26173
26174				var texture = renderTarget.texture;
26175				var textureFormat = texture.format;
26176				var textureType = texture.type;
26177
26178				if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
26179
26180					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
26181					return;
26182
26183				}
26184
26185				if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)
26186					! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
26187					! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
26188
26189					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
26190					return;
26191
26192				}
26193
26194				if ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {
26195
26196					// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
26197
26198					if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
26199
26200						_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
26201
26202					}
26203
26204				} else {
26205
26206					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
26207
26208				}
26209
26210			} finally {
26211
26212				if ( restore ) {
26213
26214					_gl.bindFramebuffer( 36160, _currentFramebuffer );
26215
26216				}
26217
26218			}
26219
26220		}
26221
26222	};
26223
26224	this.copyFramebufferToTexture = function ( position, texture, level ) {
26225
26226		if ( level === undefined ) level = 0;
26227
26228		var levelScale = Math.pow( 2, - level );
26229		var width = Math.floor( texture.image.width * levelScale );
26230		var height = Math.floor( texture.image.height * levelScale );
26231		var glFormat = utils.convert( texture.format );
26232
26233		textures.setTexture2D( texture, 0 );
26234
26235		_gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );
26236
26237		state.unbindTexture();
26238
26239	};
26240
26241	this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {
26242
26243		if ( level === undefined ) level = 0;
26244
26245		var width = srcTexture.image.width;
26246		var height = srcTexture.image.height;
26247		var glFormat = utils.convert( dstTexture.format );
26248		var glType = utils.convert( dstTexture.type );
26249
26250		textures.setTexture2D( dstTexture, 0 );
26251
26252		if ( srcTexture.isDataTexture ) {
26253
26254			_gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
26255
26256		} else {
26257
26258			if ( srcTexture.isCompressedTexture ) {
26259
26260				_gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
26261
26262			} else {
26263
26264				_gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image );
26265
26266			}
26267
26268		}
26269
26270		// Generate mipmaps only when copying level 0
26271		if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 );
26272
26273		state.unbindTexture();
26274
26275	};
26276
26277	this.initTexture = function ( texture ) {
26278
26279		textures.setTexture2D( texture, 0 );
26280
26281		state.unbindTexture();
26282
26283	};
26284
26285	if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
26286
26287		__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef
26288
26289	}
26290
26291}
26292
26293/**
26294 * @author mrdoob / http://mrdoob.com/
26295 * @author alteredq / http://alteredqualia.com/
26296 */
26297
26298function FogExp2( color, density ) {
26299
26300	this.name = '';
26301
26302	this.color = new Color( color );
26303	this.density = ( density !== undefined ) ? density : 0.00025;
26304
26305}
26306
26307Object.assign( FogExp2.prototype, {
26308
26309	isFogExp2: true,
26310
26311	clone: function () {
26312
26313		return new FogExp2( this.color, this.density );
26314
26315	},
26316
26317	toJSON: function ( /* meta */ ) {
26318
26319		return {
26320			type: 'FogExp2',
26321			color: this.color.getHex(),
26322			density: this.density
26323		};
26324
26325	}
26326
26327} );
26328
26329/**
26330 * @author mrdoob / http://mrdoob.com/
26331 * @author alteredq / http://alteredqualia.com/
26332 */
26333
26334function Fog( color, near, far ) {
26335
26336	this.name = '';
26337
26338	this.color = new Color( color );
26339
26340	this.near = ( near !== undefined ) ? near : 1;
26341	this.far = ( far !== undefined ) ? far : 1000;
26342
26343}
26344
26345Object.assign( Fog.prototype, {
26346
26347	isFog: true,
26348
26349	clone: function () {
26350
26351		return new Fog( this.color, this.near, this.far );
26352
26353	},
26354
26355	toJSON: function ( /* meta */ ) {
26356
26357		return {
26358			type: 'Fog',
26359			color: this.color.getHex(),
26360			near: this.near,
26361			far: this.far
26362		};
26363
26364	}
26365
26366} );
26367
26368/**
26369 * @author benaadams / https://twitter.com/ben_a_adams
26370 */
26371
26372function InterleavedBuffer( array, stride ) {
26373
26374	this.array = array;
26375	this.stride = stride;
26376	this.count = array !== undefined ? array.length / stride : 0;
26377
26378	this.usage = StaticDrawUsage;
26379	this.updateRange = { offset: 0, count: - 1 };
26380
26381	this.version = 0;
26382
26383}
26384
26385Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {
26386
26387	set: function ( value ) {
26388
26389		if ( value === true ) this.version ++;
26390
26391	}
26392
26393} );
26394
26395Object.assign( InterleavedBuffer.prototype, {
26396
26397	isInterleavedBuffer: true,
26398
26399	onUploadCallback: function () {},
26400
26401	setUsage: function ( value ) {
26402
26403		this.usage = value;
26404
26405		return this;
26406
26407	},
26408
26409	copy: function ( source ) {
26410
26411		this.array = new source.array.constructor( source.array );
26412		this.count = source.count;
26413		this.stride = source.stride;
26414		this.usage = source.usage;
26415
26416		return this;
26417
26418	},
26419
26420	copyAt: function ( index1, attribute, index2 ) {
26421
26422		index1 *= this.stride;
26423		index2 *= attribute.stride;
26424
26425		for ( var i = 0, l = this.stride; i < l; i ++ ) {
26426
26427			this.array[ index1 + i ] = attribute.array[ index2 + i ];
26428
26429		}
26430
26431		return this;
26432
26433	},
26434
26435	set: function ( value, offset ) {
26436
26437		if ( offset === undefined ) offset = 0;
26438
26439		this.array.set( value, offset );
26440
26441		return this;
26442
26443	},
26444
26445	clone: function () {
26446
26447		return new this.constructor().copy( this );
26448
26449	},
26450
26451	onUpload: function ( callback ) {
26452
26453		this.onUploadCallback = callback;
26454
26455		return this;
26456
26457	}
26458
26459} );
26460
26461/**
26462 * @author benaadams / https://twitter.com/ben_a_adams
26463 */
26464
26465var _vector$6 = new Vector3();
26466
26467function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {
26468
26469	this.data = interleavedBuffer;
26470	this.itemSize = itemSize;
26471	this.offset = offset;
26472
26473	this.normalized = normalized === true;
26474
26475}
26476
26477Object.defineProperties( InterleavedBufferAttribute.prototype, {
26478
26479	count: {
26480
26481		get: function () {
26482
26483			return this.data.count;
26484
26485		}
26486
26487	},
26488
26489	array: {
26490
26491		get: function () {
26492
26493			return this.data.array;
26494
26495		}
26496
26497	}
26498
26499} );
26500
26501Object.assign( InterleavedBufferAttribute.prototype, {
26502
26503	isInterleavedBufferAttribute: true,
26504
26505	applyMatrix4: function ( m ) {
26506
26507		for ( var i = 0, l = this.data.count; i < l; i ++ ) {
26508
26509			_vector$6.x = this.getX( i );
26510			_vector$6.y = this.getY( i );
26511			_vector$6.z = this.getZ( i );
26512
26513			_vector$6.applyMatrix4( m );
26514
26515			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
26516
26517		}
26518
26519		return this;
26520
26521	},
26522
26523	setX: function ( index, x ) {
26524
26525		this.data.array[ index * this.data.stride + this.offset ] = x;
26526
26527		return this;
26528
26529	},
26530
26531	setY: function ( index, y ) {
26532
26533		this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
26534
26535		return this;
26536
26537	},
26538
26539	setZ: function ( index, z ) {
26540
26541		this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
26542
26543		return this;
26544
26545	},
26546
26547	setW: function ( index, w ) {
26548
26549		this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
26550
26551		return this;
26552
26553	},
26554
26555	getX: function ( index ) {
26556
26557		return this.data.array[ index * this.data.stride + this.offset ];
26558
26559	},
26560
26561	getY: function ( index ) {
26562
26563		return this.data.array[ index * this.data.stride + this.offset + 1 ];
26564
26565	},
26566
26567	getZ: function ( index ) {
26568
26569		return this.data.array[ index * this.data.stride + this.offset + 2 ];
26570
26571	},
26572
26573	getW: function ( index ) {
26574
26575		return this.data.array[ index * this.data.stride + this.offset + 3 ];
26576
26577	},
26578
26579	setXY: function ( index, x, y ) {
26580
26581		index = index * this.data.stride + this.offset;
26582
26583		this.data.array[ index + 0 ] = x;
26584		this.data.array[ index + 1 ] = y;
26585
26586		return this;
26587
26588	},
26589
26590	setXYZ: function ( index, x, y, z ) {
26591
26592		index = index * this.data.stride + this.offset;
26593
26594		this.data.array[ index + 0 ] = x;
26595		this.data.array[ index + 1 ] = y;
26596		this.data.array[ index + 2 ] = z;
26597
26598		return this;
26599
26600	},
26601
26602	setXYZW: function ( index, x, y, z, w ) {
26603
26604		index = index * this.data.stride + this.offset;
26605
26606		this.data.array[ index + 0 ] = x;
26607		this.data.array[ index + 1 ] = y;
26608		this.data.array[ index + 2 ] = z;
26609		this.data.array[ index + 3 ] = w;
26610
26611		return this;
26612
26613	}
26614
26615} );
26616
26617/**
26618 * @author alteredq / http://alteredqualia.com/
26619 *
26620 * parameters = {
26621 *  color: <hex>,
26622 *  map: new THREE.Texture( <Image> ),
26623 *  alphaMap: new THREE.Texture( <Image> ),
26624 *  rotation: <float>,
26625 *  sizeAttenuation: <bool>
26626 * }
26627 */
26628
26629function SpriteMaterial( parameters ) {
26630
26631	Material.call( this );
26632
26633	this.type = 'SpriteMaterial';
26634
26635	this.color = new Color( 0xffffff );
26636
26637	this.map = null;
26638
26639	this.alphaMap = null;
26640
26641	this.rotation = 0;
26642
26643	this.sizeAttenuation = true;
26644
26645	this.transparent = true;
26646
26647	this.setValues( parameters );
26648
26649}
26650
26651SpriteMaterial.prototype = Object.create( Material.prototype );
26652SpriteMaterial.prototype.constructor = SpriteMaterial;
26653SpriteMaterial.prototype.isSpriteMaterial = true;
26654
26655SpriteMaterial.prototype.copy = function ( source ) {
26656
26657	Material.prototype.copy.call( this, source );
26658
26659	this.color.copy( source.color );
26660
26661	this.map = source.map;
26662
26663	this.alphaMap = source.alphaMap;
26664
26665	this.rotation = source.rotation;
26666
26667	this.sizeAttenuation = source.sizeAttenuation;
26668
26669	return this;
26670
26671};
26672
26673/**
26674 * @author mikael emtinger / http://gomo.se/
26675 * @author alteredq / http://alteredqualia.com/
26676 */
26677
26678var _geometry;
26679
26680var _intersectPoint = new Vector3();
26681var _worldScale = new Vector3();
26682var _mvPosition = new Vector3();
26683
26684var _alignedPosition = new Vector2();
26685var _rotatedPosition = new Vector2();
26686var _viewWorldMatrix = new Matrix4();
26687
26688var _vA$1 = new Vector3();
26689var _vB$1 = new Vector3();
26690var _vC$1 = new Vector3();
26691
26692var _uvA$1 = new Vector2();
26693var _uvB$1 = new Vector2();
26694var _uvC$1 = new Vector2();
26695
26696function Sprite( material ) {
26697
26698	Object3D.call( this );
26699
26700	this.type = 'Sprite';
26701
26702	if ( _geometry === undefined ) {
26703
26704		_geometry = new BufferGeometry();
26705
26706		var float32Array = new Float32Array( [
26707			- 0.5, - 0.5, 0, 0, 0,
26708			0.5, - 0.5, 0, 1, 0,
26709			0.5, 0.5, 0, 1, 1,
26710			- 0.5, 0.5, 0, 0, 1
26711		] );
26712
26713		var interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
26714
26715		_geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
26716		_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
26717		_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
26718
26719	}
26720
26721	this.geometry = _geometry;
26722	this.material = ( material !== undefined ) ? material : new SpriteMaterial();
26723
26724	this.center = new Vector2( 0.5, 0.5 );
26725
26726}
26727
26728Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), {
26729
26730	constructor: Sprite,
26731
26732	isSprite: true,
26733
26734	raycast: function ( raycaster, intersects ) {
26735
26736		if ( raycaster.camera === null ) {
26737
26738			console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
26739
26740		}
26741
26742		_worldScale.setFromMatrixScale( this.matrixWorld );
26743
26744		_viewWorldMatrix.copy( raycaster.camera.matrixWorld );
26745		this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
26746
26747		_mvPosition.setFromMatrixPosition( this.modelViewMatrix );
26748
26749		if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
26750
26751			_worldScale.multiplyScalar( - _mvPosition.z );
26752
26753		}
26754
26755		var rotation = this.material.rotation;
26756		var sin, cos;
26757		if ( rotation !== 0 ) {
26758
26759			cos = Math.cos( rotation );
26760			sin = Math.sin( rotation );
26761
26762		}
26763
26764		var center = this.center;
26765
26766		transformVertex( _vA$1.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
26767		transformVertex( _vB$1.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
26768		transformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
26769
26770		_uvA$1.set( 0, 0 );
26771		_uvB$1.set( 1, 0 );
26772		_uvC$1.set( 1, 1 );
26773
26774		// check first triangle
26775		var intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );
26776
26777		if ( intersect === null ) {
26778
26779			// check second triangle
26780			transformVertex( _vB$1.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
26781			_uvB$1.set( 0, 1 );
26782
26783			intersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );
26784			if ( intersect === null ) {
26785
26786				return;
26787
26788			}
26789
26790		}
26791
26792		var distance = raycaster.ray.origin.distanceTo( _intersectPoint );
26793
26794		if ( distance < raycaster.near || distance > raycaster.far ) return;
26795
26796		intersects.push( {
26797
26798			distance: distance,
26799			point: _intersectPoint.clone(),
26800			uv: Triangle.getUV( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ),
26801			face: null,
26802			object: this
26803
26804		} );
26805
26806	},
26807
26808	clone: function () {
26809
26810		return new this.constructor( this.material ).copy( this );
26811
26812	},
26813
26814	copy: function ( source ) {
26815
26816		Object3D.prototype.copy.call( this, source );
26817
26818		if ( source.center !== undefined ) this.center.copy( source.center );
26819
26820		return this;
26821
26822	}
26823
26824
26825} );
26826
26827function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
26828
26829	// compute position in camera space
26830	_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
26831
26832	// to check if rotation is not zero
26833	if ( sin !== undefined ) {
26834
26835		_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
26836		_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
26837
26838	} else {
26839
26840		_rotatedPosition.copy( _alignedPosition );
26841
26842	}
26843
26844
26845	vertexPosition.copy( mvPosition );
26846	vertexPosition.x += _rotatedPosition.x;
26847	vertexPosition.y += _rotatedPosition.y;
26848
26849	// transform to world space
26850	vertexPosition.applyMatrix4( _viewWorldMatrix );
26851
26852}
26853
26854/**
26855 * @author mikael emtinger / http://gomo.se/
26856 * @author alteredq / http://alteredqualia.com/
26857 * @author mrdoob / http://mrdoob.com/
26858 */
26859
26860var _v1$4 = new Vector3();
26861var _v2$2 = new Vector3();
26862
26863function LOD() {
26864
26865	Object3D.call( this );
26866
26867	this._currentLevel = 0;
26868
26869	this.type = 'LOD';
26870
26871	Object.defineProperties( this, {
26872		levels: {
26873			enumerable: true,
26874			value: []
26875		}
26876	} );
26877
26878	this.autoUpdate = true;
26879
26880}
26881
26882LOD.prototype = Object.assign( Object.create( Object3D.prototype ), {
26883
26884	constructor: LOD,
26885
26886	isLOD: true,
26887
26888	copy: function ( source ) {
26889
26890		Object3D.prototype.copy.call( this, source, false );
26891
26892		var levels = source.levels;
26893
26894		for ( var i = 0, l = levels.length; i < l; i ++ ) {
26895
26896			var level = levels[ i ];
26897
26898			this.addLevel( level.object.clone(), level.distance );
26899
26900		}
26901
26902		this.autoUpdate = source.autoUpdate;
26903
26904		return this;
26905
26906	},
26907
26908	addLevel: function ( object, distance ) {
26909
26910		if ( distance === undefined ) distance = 0;
26911
26912		distance = Math.abs( distance );
26913
26914		var levels = this.levels;
26915
26916		for ( var l = 0; l < levels.length; l ++ ) {
26917
26918			if ( distance < levels[ l ].distance ) {
26919
26920				break;
26921
26922			}
26923
26924		}
26925
26926		levels.splice( l, 0, { distance: distance, object: object } );
26927
26928		this.add( object );
26929
26930		return this;
26931
26932	},
26933
26934	getCurrentLevel: function () {
26935
26936		return this._currentLevel;
26937
26938	},
26939
26940	getObjectForDistance: function ( distance ) {
26941
26942		var levels = this.levels;
26943
26944		if ( levels.length > 0 ) {
26945
26946			for ( var i = 1, l = levels.length; i < l; i ++ ) {
26947
26948				if ( distance < levels[ i ].distance ) {
26949
26950					break;
26951
26952				}
26953
26954			}
26955
26956			return levels[ i - 1 ].object;
26957
26958		}
26959
26960		return null;
26961
26962	},
26963
26964	raycast: function ( raycaster, intersects ) {
26965
26966		var levels = this.levels;
26967
26968		if ( levels.length > 0 ) {
26969
26970			_v1$4.setFromMatrixPosition( this.matrixWorld );
26971
26972			var distance = raycaster.ray.origin.distanceTo( _v1$4 );
26973
26974			this.getObjectForDistance( distance ).raycast( raycaster, intersects );
26975
26976		}
26977
26978	},
26979
26980	update: function ( camera ) {
26981
26982		var levels = this.levels;
26983
26984		if ( levels.length > 1 ) {
26985
26986			_v1$4.setFromMatrixPosition( camera.matrixWorld );
26987			_v2$2.setFromMatrixPosition( this.matrixWorld );
26988
26989			var distance = _v1$4.distanceTo( _v2$2 ) / camera.zoom;
26990
26991			levels[ 0 ].object.visible = true;
26992
26993			for ( var i = 1, l = levels.length; i < l; i ++ ) {
26994
26995				if ( distance >= levels[ i ].distance ) {
26996
26997					levels[ i - 1 ].object.visible = false;
26998					levels[ i ].object.visible = true;
26999
27000				} else {
27001
27002					break;
27003
27004				}
27005
27006			}
27007
27008			this._currentLevel = i - 1;
27009
27010			for ( ; i < l; i ++ ) {
27011
27012				levels[ i ].object.visible = false;
27013
27014			}
27015
27016		}
27017
27018	},
27019
27020	toJSON: function ( meta ) {
27021
27022		var data = Object3D.prototype.toJSON.call( this, meta );
27023
27024		if ( this.autoUpdate === false ) data.object.autoUpdate = false;
27025
27026		data.object.levels = [];
27027
27028		var levels = this.levels;
27029
27030		for ( var i = 0, l = levels.length; i < l; i ++ ) {
27031
27032			var level = levels[ i ];
27033
27034			data.object.levels.push( {
27035				object: level.object.uuid,
27036				distance: level.distance
27037			} );
27038
27039		}
27040
27041		return data;
27042
27043	}
27044
27045} );
27046
27047/**
27048 * @author mikael emtinger / http://gomo.se/
27049 * @author alteredq / http://alteredqualia.com/
27050 * @author ikerr / http://verold.com
27051 */
27052
27053function SkinnedMesh( geometry, material ) {
27054
27055	if ( geometry && geometry.isGeometry ) {
27056
27057		console.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );
27058
27059	}
27060
27061	Mesh.call( this, geometry, material );
27062
27063	this.type = 'SkinnedMesh';
27064
27065	this.bindMode = 'attached';
27066	this.bindMatrix = new Matrix4();
27067	this.bindMatrixInverse = new Matrix4();
27068
27069}
27070
27071SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
27072
27073	constructor: SkinnedMesh,
27074
27075	isSkinnedMesh: true,
27076
27077	bind: function ( skeleton, bindMatrix ) {
27078
27079		this.skeleton = skeleton;
27080
27081		if ( bindMatrix === undefined ) {
27082
27083			this.updateMatrixWorld( true );
27084
27085			this.skeleton.calculateInverses();
27086
27087			bindMatrix = this.matrixWorld;
27088
27089		}
27090
27091		this.bindMatrix.copy( bindMatrix );
27092		this.bindMatrixInverse.getInverse( bindMatrix );
27093
27094	},
27095
27096	pose: function () {
27097
27098		this.skeleton.pose();
27099
27100	},
27101
27102	normalizeSkinWeights: function () {
27103
27104		var vector = new Vector4();
27105
27106		var skinWeight = this.geometry.attributes.skinWeight;
27107
27108		for ( var i = 0, l = skinWeight.count; i < l; i ++ ) {
27109
27110			vector.x = skinWeight.getX( i );
27111			vector.y = skinWeight.getY( i );
27112			vector.z = skinWeight.getZ( i );
27113			vector.w = skinWeight.getW( i );
27114
27115			var scale = 1.0 / vector.manhattanLength();
27116
27117			if ( scale !== Infinity ) {
27118
27119				vector.multiplyScalar( scale );
27120
27121			} else {
27122
27123				vector.set( 1, 0, 0, 0 );
27123 // do something reasonable
27124
27125			}
27126
27127			skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
27128
27129		}
27130
27131	},
27132
27133	updateMatrixWorld: function ( force ) {
27134
27135		Mesh.prototype.updateMatrixWorld.call( this, force );
27136
27137		if ( this.bindMode === 'attached' ) {
27138
27139			this.bindMatrixInverse.getInverse( this.matrixWorld );
27140
27141		} else if ( this.bindMode === 'detached' ) {
27142
27143			this.bindMatrixInverse.getInverse( this.bindMatrix );
27144
27145		} else {
27146
27147			console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
27148
27149		}
27150
27151	},
27152
27153	clone: function () {
27154
27155		return new this.constructor( this.geometry, this.material ).copy( this );
27156
27157	},
27158
27159	boneTransform: ( function () {
27160
27161		var basePosition = new Vector3();
27162
27163		var skinIndex = new Vector4();
27164		var skinWeight = new Vector4();
27165
27166		var vector = new Vector3();
27167		var matrix = new Matrix4();
27168
27169		return function ( index, target ) {
27170
27171			var skeleton = this.skeleton;
27172			var geometry = this.geometry;
27173
27174			skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
27175			skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
27176
27177			basePosition.fromBufferAttribute( geometry.attributes.position, index ).applyMatrix4( this.bindMatrix );
27178
27179			target.set( 0, 0, 0 );
27180
27181			for ( var i = 0; i < 4; i ++ ) {
27182
27183				var weight = skinWeight.getComponent( i );
27184
27185				if ( weight !== 0 ) {
27186
27187					var boneIndex = skinIndex.getComponent( i );
27188
27189					matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
27190
27191					target.addScaledVector( vector.copy( basePosition ).applyMatrix4( matrix ), weight );
27192
27193				}
27194
27195			}
27196
27197			return target.applyMatrix4( this.bindMatrixInverse );
27198
27199		};
27200
27201	}() )
27202
27203} );
27204
27205/**
27206 * @author mikael emtinger / http://gomo.se/
27207 * @author alteredq / http://alteredqualia.com/
27208 * @author michael guerrero / http://realitymeltdown.com
27209 * @author ikerr / http://verold.com
27210 */
27211
27212var _offsetMatrix = new Matrix4();
27213var _identityMatrix = new Matrix4();
27214
27215function Skeleton( bones, boneInverses ) {
27216
27217	// copy the bone array
27218
27219	bones = bones || [];
27220
27221	this.bones = bones.slice( 0 );
27222	this.boneMatrices = new Float32Array( this.bones.length * 16 );
27223
27224	this.frame = - 1;
27225
27226	// use the supplied bone inverses or calculate the inverses
27227
27228	if ( boneInverses === undefined ) {
27229
27230		this.calculateInverses();
27231
27232	} else {
27233
27234		if ( this.bones.length === boneInverses.length ) {
27235
27236			this.boneInverses = boneInverses.slice( 0 );
27237
27238		} else {
27239
27240			console.warn( 'THREE.Skeleton boneInverses is the wrong length.' );
27241
27242			this.boneInverses = [];
27243
27244			for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
27245
27246				this.boneInverses.push( new Matrix4() );
27247
27248			}
27249
27250		}
27251
27252	}
27253
27254}
27255
27256Object.assign( Skeleton.prototype, {
27257
27258	calculateInverses: function () {
27259
27260		this.boneInverses = [];
27261
27262		for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
27263
27264			var inverse = new Matrix4();
27265
27266			if ( this.bones[ i ] ) {
27267
27268				inverse.getInverse( this.bones[ i ].matrixWorld );
27269
27270			}
27271
27272			this.boneInverses.push( inverse );
27273
27274		}
27275
27276	},
27277
27278	pose: function () {
27279
27280		var bone, i, il;
27281
27282		// recover the bind-time world matrices
27283
27284		for ( i = 0, il = this.bones.length; i < il; i ++ ) {
27285
27286			bone = this.bones[ i ];
27287
27288			if ( bone ) {
27289
27290				bone.matrixWorld.getInverse( this.boneInverses[ i ] );
27291
27292			}
27293
27294		}
27295
27296		// compute the local matrices, positions, rotations and scales
27297
27298		for ( i = 0, il = this.bones.length; i < il; i ++ ) {
27299
27300			bone = this.bones[ i ];
27301
27302			if ( bone ) {
27303
27304				if ( bone.parent && bone.parent.isBone ) {
27305
27306					bone.matrix.getInverse( bone.parent.matrixWorld );
27307					bone.matrix.multiply( bone.matrixWorld );
27308
27309				} else {
27310
27311					bone.matrix.copy( bone.matrixWorld );
27312
27313				}
27314
27315				bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
27316
27317			}
27318
27319		}
27320
27321	},
27322
27323	update: function () {
27324
27325		var bones = this.bones;
27326		var boneInverses = this.boneInverses;
27327		var boneMatrices = this.boneMatrices;
27328		var boneTexture = this.boneTexture;
27329
27330		// flatten bone matrices to array
27331
27332		for ( var i = 0, il = bones.length; i < il; i ++ ) {
27333
27334			// compute the offset between the current and the original transform
27335
27336			var matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
27337
vendor: 5,869 bytes, lines 27338-27642
27338			_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
27339			_offsetMatrix.toArray( boneMatrices, i * 16 );
27340
27341		}
27342
27343		if ( boneTexture !== undefined ) {
27344
27345			boneTexture.needsUpdate = true;
27346
27347		}
27348
27349	},
27350
27351	clone: function () {
27352
27353		return new Skeleton( this.bones, this.boneInverses );
27354
27355	},
27356
27357	getBoneByName: function ( name ) {
27358
27359		for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
27360
27361			var bone = this.bones[ i ];
27362
27363			if ( bone.name === name ) {
27364
27365				return bone;
27366
27367			}
27368
27369		}
27370
27371		return undefined;
27372
27373	},
27374
27375	dispose: function ( ) {
27376
27377		if ( this.boneTexture ) {
27378
27379			this.boneTexture.dispose();
27380
27381			this.boneTexture = undefined;
27382
27383		}
27384
27385	}
27386
27387} );
27388
27389/**
27390 * @author mikael emtinger / http://gomo.se/
27391 * @author alteredq / http://alteredqualia.com/
27392 * @author ikerr / http://verold.com
27393 */
27394
27395function Bone() {
27396
27397	Object3D.call( this );
27398
27399	this.type = 'Bone';
27400
27401}
27402
27403Bone.prototype = Object.assign( Object.create( Object3D.prototype ), {
27404
27405	constructor: Bone,
27406
27407	isBone: true
27408
27409} );
27410
27411/**
27412 * @author mrdoob / http://mrdoob.com/
27413 */
27414
27415var _instanceLocalMatrix = new Matrix4();
27416var _instanceWorldMatrix = new Matrix4();
27417
27418var _instanceIntersects = [];
27419
27420var _mesh = new Mesh();
27421
27422function InstancedMesh( geometry, material, count ) {
27423
27424	Mesh.call( this, geometry, material );
27425
27426	this.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );
27427
27428	this.count = count;
27429
27430	this.frustumCulled = false;
27431
27432}
27433
27434InstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
27435
27436	constructor: InstancedMesh,
27437
27438	isInstancedMesh: true,
27439
27440	getMatrixAt: function ( index, matrix ) {
27441
27442		matrix.fromArray( this.instanceMatrix.array, index * 16 );
27443
27444	},
27445
27446	raycast: function ( raycaster, intersects ) {
27447
27448		var matrixWorld = this.matrixWorld;
27449		var raycastTimes = this.count;
27450
27451		_mesh.geometry = this.geometry;
27452		_mesh.material = this.material;
27453
27454		if ( _mesh.material === undefined ) return;
27455
27456		for ( var instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
27457
27458			// calculate the world matrix for each instance
27459
27460			this.getMatrixAt( instanceId, _instanceLocalMatrix );
27461
27462			_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
27463
27464			// the mesh represents this single instance
27465
27466			_mesh.matrixWorld = _instanceWorldMatrix;
27467
27468			_mesh.raycast( raycaster, _instanceIntersects );
27469
27470			// process the result of raycast
27471
27472			for ( var i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
27473
27474				var intersect = _instanceIntersects[ i ];
27475				intersect.instanceId = instanceId;
27476				intersect.object = this;
27477				intersects.push( intersect );
27478
27479			}
27480
27481			_instanceIntersects.length = 0;
27482
27483		}
27484
27485	},
27486
27487	setMatrixAt: function ( index, matrix ) {
27488
27489		matrix.toArray( this.instanceMatrix.array, index * 16 );
27490
27491	},
27492
27493	updateMorphTargets: function () {
27494
27495	}
27496
27497} );
27498
27499/**
27500 * @author mrdoob / http://mrdoob.com/
27501 * @author alteredq / http://alteredqualia.com/
27502 *
27503 * parameters = {
27504 *  color: <hex>,
27505 *  opacity: <float>,
27506 *
27507 *  linewidth: <float>,
27508 *  linecap: "round",
27509 *  linejoin: "round"
27510 * }
27511 */
27512
27513function LineBasicMaterial( parameters ) {
27514
27515	Material.call( this );
27516
27517	this.type = 'LineBasicMaterial';
27518
27519	this.color = new Color( 0xffffff );
27520
27521	this.linewidth = 1;
27522	this.linecap = 'round';
27523	this.linejoin = 'round';
27524
27525	this.setValues( parameters );
27526
27527}
27528
27529LineBasicMaterial.prototype = Object.create( Material.prototype );
27530LineBasicMaterial.prototype.constructor = LineBasicMaterial;
27531
27532LineBasicMaterial.prototype.isLineBasicMaterial = true;
27533
27534LineBasicMaterial.prototype.copy = function ( source ) {
27535
27536	Material.prototype.copy.call( this, source );
27537
27538	this.color.copy( source.color );
27539
27540	this.linewidth = source.linewidth;
27541	this.linecap = source.linecap;
27542	this.linejoin = source.linejoin;
27543
27544	return this;
27545
27546};
27547
27548/**
27549 * @author mrdoob / http://mrdoob.com/
27550 */
27551
27552var _start = new Vector3();
27553var _end = new Vector3();
27554var _inverseMatrix$1 = new Matrix4();
27555var _ray$1 = new Ray();
27556var _sphere$2 = new Sphere();
27557
27558function Line( geometry, material, mode ) {
27559
27560	if ( mode === 1 ) {
27561
27562		console.error( 'THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.' );
27563
27564	}
27565
27566	Object3D.call( this );
27567
27568	this.type = 'Line';
27569
27570	this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
27571	this.material = material !== undefined ? material : new LineBasicMaterial();
27572
27573}
27574
27575Line.prototype = Object.assign( Object.create( Object3D.prototype ), {
27576
27577	constructor: Line,
27578
27579	isLine: true,
27580
27581	computeLineDistances: function () {
27582
27583		var geometry = this.geometry;
27584
27585		if ( geometry.isBufferGeometry ) {
27586
27587			// we assume non-indexed geometry
27588
27589			if ( geometry.index === null ) {
27590
27591				var positionAttribute = geometry.attributes.position;
27592				var lineDistances = [ 0 ];
27593
27594				for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {
27595
27596					_start.fromBufferAttribute( positionAttribute, i - 1 );
27597					_end.fromBufferAttribute( positionAttribute, i );
27598
27599					lineDistances[ i ] = lineDistances[ i - 1 ];
27600					lineDistances[ i ] += _start.distanceTo( _end );
27601
27602				}
27603
27604				geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
27605
27606			} else {
27607
27608				console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
27609
27610			}
27611
27612		} else if ( geometry.isGeometry ) {
27613
27614			var vertices = geometry.vertices;
27615			var lineDistances = geometry.lineDistances;
27616
27617			lineDistances[ 0 ] = 0;
27618
27619			for ( var i = 1, l = vertices.length; i < l; i ++ ) {
27620
27621				lineDistances[ i ] = lineDistances[ i - 1 ];
27622				lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );
27623
27624			}
27625
27626		}
27627
27628		return this;
27629
27630	},
27631
27632	raycast: function ( raycaster, intersects ) {
27633
27634		var geometry = this.geometry;
27635		var matrixWorld = this.matrixWorld;
27636		var threshold = raycaster.params.Line.threshold;
27637
27638		// Checking boundingSphere distance to ray
27639
27640		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
27641
27642		_sphere$2.copy( geometry.boundingSphere );
27643		_sphere$2.applyMatrix4( matrixWorld );
27644		_sphere$2.radius += threshold;
27645
27646		if ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) return;
27647
27648		//
27649
27650		_inverseMatrix$1.getInverse( matrixWorld );
27651		_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
27652
27653		var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
27654		var localThresholdSq = localThreshold * localThreshold;
27655
27656		var vStart = new Vector3();
27657		var vEnd = new Vector3();
27658		var interSegment = new Vector3();
27659		var interRay = new Vector3();
27660		var step = ( this && this.isLineSegments ) ? 2 : 1;
27661
27662		if ( geometry.isBufferGeometry ) {
27663
27664			var index = geometry.index;
27665			var attributes = geometry.attributes;
27666			var positions = attributes.position.array;
27667
27668			if ( index !== null ) {
27669
27670				var indices = index.array;
27671
27672				for ( var i = 0, l = indices.length - 1; i < l; i += step ) {
27673
27674					var a = indices[ i ];
27675					var b = indices[ i + 1 ];
27676
27677					vStart.fromArray( positions, a * 3 );
27678					vEnd.fromArray( positions, b * 3 );
27679
27680					var distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
27681
27682					if ( distSq > localThresholdSq ) continue;
27683
27684					interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
27685
27686					var distance = raycaster.ray.origin.distanceTo( interRay );
27687
27688					if ( distance < raycaster.near || distance > raycaster.far ) continue;
27689
27690					intersects.push( {
27691
27692						distance: distance,
27693						// What do we want? intersection point on the ray or on the segment??
27694						// point: raycaster.ray.at( distance ),
27695						point: interSegment.clone().applyMatrix4( this.matrixWorld ),
27696						index: i,
27697						face: null,
27698						faceIndex: null,
27699						object: this
27700
27701					} );
27702
27703				}
27704
27705			} else {
27706
27707				for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {
27708
27709					vStart.fromArray( positions, 3 * i );
27710					vEnd.fromArray( positions, 3 * i + 3 );
27711
27712					var distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
27713
27714					if ( distSq > localThresholdSq ) continue;
27715
27716					interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
27717
27718					var distance = raycaster.ray.origin.distanceTo( interRay );
27719
27720					if ( distance < raycaster.near || distance > raycaster.far ) continue;
27721
27722					intersects.push( {
27723
27724						distance: distance,
27725						// What do we want? intersection point on the ray or on the segment??
27726						// point: raycaster.ray.at( distance ),
27727						point: interSegment.clone().applyMatrix4( this.matrixWorld ),
27728						index: i,
27729						face: null,
27730						faceIndex: null,
27731						object: this
27732
27733					} );
27734
27735				}
27736
27737			}
27738
27739		} else if ( geometry.isGeometry ) {
27740
27741			var vertices = geometry.vertices;
27742			var nbVertices = vertices.length;
27743
27744			for ( var i = 0; i < nbVertices - 1; i += step ) {
27745
27746				var distSq = _ray$1.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );
27747
27748				if ( distSq > localThresholdSq ) continue;
27749
27750				interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
27751
27752				var distance = raycaster.ray.origin.distanceTo( interRay );
27753
27754				if ( distance < raycaster.near || distance > raycaster.far ) continue;
27755
27756				intersects.push( {
27757
27758					distance: distance,
27759					// What do we want? intersection point on the ray or on the segment??
27760					// point: raycaster.ray.at( distance ),
27761					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
27762					index: i,
27763					face: null,
27764					faceIndex: null,
27765					object: this
27766
27767				} );
27768
27769			}
27770
27771		}
27772
27773	},
27774
27775	clone: function () {
27776
27777		return new this.constructor( this.geometry, this.material ).copy( this );
27778
27779	}
27780
27781} );
27782
27783/**
27784 * @author mrdoob / http://mrdoob.com/
27785 */
27786
27787var _start$1 = new Vector3();
27788var _end$1 = new Vector3();
27789
27790function LineSegments( geometry, material ) {
27791
27792	Line.call( this, geometry, material );
27793
27794	this.type = 'LineSegments';
27795
27796}
27797
27798LineSegments.prototype = Object.assign( Object.create( Line.prototype ), {
27799
27800	constructor: LineSegments,
27801
27802	isLineSegments: true,
27803
27804	computeLineDistances: function () {
27805
27806		var geometry = this.geometry;
27807
27808		if ( geometry.isBufferGeometry ) {
27809
27810			// we assume non-indexed geometry
27811
27812			if ( geometry.index === null ) {
27813
27814				var positionAttribute = geometry.attributes.position;
27815				var lineDistances = [];
27816
27817				for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {
27818
27819					_start$1.fromBufferAttribute( positionAttribute, i );
27820					_end$1.fromBufferAttribute( positionAttribute, i + 1 );
27821
27822					lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
27823					lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
27824
27825				}
27826
27827				geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
27828
27829			} else {
27830
27831				console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
27832
27833			}
27834
27835		} else if ( geometry.isGeometry ) {
27836
27837			var vertices = geometry.vertices;
27838			var lineDistances = geometry.lineDistances;
27839
27840			for ( var i = 0, l = vertices.length; i < l; i += 2 ) {
27841
27842				_start$1.copy( vertices[ i ] );
27843				_end$1.copy( vertices[ i + 1 ] );
27844
27845				lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
27846				lineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );
27847
27848			}
27849
27850		}
27851
27852		return this;
27853
27854	}
27855
27856} );
27857
27858/**
27859 * @author mgreter / http://github.com/mgreter
27860 */
27861
27862function LineLoop( geometry, material ) {
27863
27864	Line.call( this, geometry, material );
27865
27866	this.type = 'LineLoop';
27867
27868}
27869
27870LineLoop.prototype = Object.assign( Object.create( Line.prototype ), {
27871
27872	constructor: LineLoop,
27873
27874	isLineLoop: true,
27875
27876} );
27877
27878/**
27879 * @author mrdoob / http://mrdoob.com/
27880 * @author alteredq / http://alteredqualia.com/
27881 *
27882 * parameters = {
27883 *  color: <hex>,
27884 *  opacity: <float>,
27885 *  map: new THREE.Texture( <Image> ),
27886 *  alphaMap: new THREE.Texture( <Image> ),
27887 *
27888 *  size: <float>,
27889 *  sizeAttenuation: <bool>
27890 *
27891 *  morphTargets: <bool>
27892 * }
27893 */
27894
27895function PointsMaterial( parameters ) {
27896
27897	Material.call( this );
27898
27899	this.type = 'PointsMaterial';
27900
27901	this.color = new Color( 0xffffff );
27902
27903	this.map = null;
27904
27905	this.alphaMap = null;
27906
27907	this.size = 1;
27908	this.sizeAttenuation = true;
27909
27910	this.morphTargets = false;
vendor: 7,961 bytes, lines 27911-28255
27911
27912	this.setValues( parameters );
27913
27914}
27915
27916PointsMaterial.prototype = Object.create( Material.prototype );
27917PointsMaterial.prototype.constructor = PointsMaterial;
27918
27919PointsMaterial.prototype.isPointsMaterial = true;
27920
27921PointsMaterial.prototype.copy = function ( source ) {
27922
27923	Material.prototype.copy.call( this, source );
27924
27925	this.color.copy( source.color );
27926
27927	this.map = source.map;
27928
27929	this.alphaMap = source.alphaMap;
27930
27931	this.size = source.size;
27932	this.sizeAttenuation = source.sizeAttenuation;
27933
27934	this.morphTargets = source.morphTargets;
27935
27936	return this;
27937
27938};
27939
27940/**
27941 * @author alteredq / http://alteredqualia.com/
27942 */
27943
27944var _inverseMatrix$2 = new Matrix4();
27945var _ray$2 = new Ray();
27946var _sphere$3 = new Sphere();
27947var _position$1 = new Vector3();
27948
27949function Points( geometry, material ) {
27950
27951	Object3D.call( this );
27952
27953	this.type = 'Points';
27954
27955	this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
27956	this.material = material !== undefined ? material : new PointsMaterial();
27957
27958	this.updateMorphTargets();
27959
27960}
27961
27962Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
27963
27964	constructor: Points,
27965
27966	isPoints: true,
27967
27968	raycast: function ( raycaster, intersects ) {
27969
27970		var geometry = this.geometry;
27971		var matrixWorld = this.matrixWorld;
27972		var threshold = raycaster.params.Points.threshold;
27973
27974		// Checking boundingSphere distance to ray
27975
27976		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
27977
27978		_sphere$3.copy( geometry.boundingSphere );
27979		_sphere$3.applyMatrix4( matrixWorld );
27980		_sphere$3.radius += threshold;
27981
27982		if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
27983
27984		//
27985
27986		_inverseMatrix$2.getInverse( matrixWorld );
27987		_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
27988
27989		var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
27990		var localThresholdSq = localThreshold * localThreshold;
27991
27992		if ( geometry.isBufferGeometry ) {
27993
27994			var index = geometry.index;
27995			var attributes = geometry.attributes;
27996			var positions = attributes.position.array;
27997
27998			if ( index !== null ) {
27999
28000				var indices = index.array;
28001
28002				for ( var i = 0, il = indices.length; i < il; i ++ ) {
28003
28004					var a = indices[ i ];
28005
28006					_position$1.fromArray( positions, a * 3 );
28007
28008					testPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
28009
28010				}
28011
28012			} else {
28013
28014				for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
28015
28016					_position$1.fromArray( positions, i * 3 );
28017
28018					testPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
28019
28020				}
28021
28022			}
28023
28024		} else {
28025
28026			var vertices = geometry.vertices;
28027
28028			for ( var i = 0, l = vertices.length; i < l; i ++ ) {
28029
28030				testPoint( vertices[ i ], i, localThresholdSq, matrixWorld, raycaster, intersects, this );
28031
28032			}
28033
28034		}
28035
28036	},
28037
28038	updateMorphTargets: function () {
28039
28040		var geometry = this.geometry;
28041		var m, ml, name;
28042
28043		if ( geometry.isBufferGeometry ) {
28044
28045			var morphAttributes = geometry.morphAttributes;
28046			var keys = Object.keys( morphAttributes );
28047
28048			if ( keys.length > 0 ) {
28049
28050				var morphAttribute = morphAttributes[ keys[ 0 ] ];
28051
28052				if ( morphAttribute !== undefined ) {
28053
28054					this.morphTargetInfluences = [];
28055					this.morphTargetDictionary = {};
28056
28057					for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
28058
28059						name = morphAttribute[ m ].name || String( m );
28060
28061						this.morphTargetInfluences.push( 0 );
28062						this.morphTargetDictionary[ name ] = m;
28063
28064					}
28065
28066				}
28067
28068			}
28069
28070		} else {
28071
28072			var morphTargets = geometry.morphTargets;
28073
28074			if ( morphTargets !== undefined && morphTargets.length > 0 ) {
28075
28076				console.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );
28077
28078			}
28079
28080		}
28081
28082	},
28083
28084	clone: function () {
28085
28086		return new this.constructor( this.geometry, this.material ).copy( this );
28087
28088	}
28089
28090} );
28091
28092function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
28093
28094	var rayPointDistanceSq = _ray$2.distanceSqToPoint( point );
28095
28096	if ( rayPointDistanceSq < localThresholdSq ) {
28097
28098		var intersectPoint = new Vector3();
28099
28100		_ray$2.closestPointToPoint( point, intersectPoint );
28101		intersectPoint.applyMatrix4( matrixWorld );
28102
28103		var distance = raycaster.ray.origin.distanceTo( intersectPoint );
28104
28105		if ( distance < raycaster.near || distance > raycaster.far ) return;
28106
28107		intersects.push( {
28108
28109			distance: distance,
28110			distanceToRay: Math.sqrt( rayPointDistanceSq ),
28111			point: intersectPoint,
28112			index: index,
28113			face: null,
28114			object: object
28115
28116		} );
28117
28118	}
28119
28120}
28121
28122/**
28123 * @author mrdoob / http://mrdoob.com/
28124 */
28125
28126function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
28127
28128	Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28129
28130	this.format = format !== undefined ? format : RGBFormat;
28131
28132	this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
28133	this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
28134
28135	this.generateMipmaps = false;
28136
28137}
28138
28139VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {
28140
28141	constructor: VideoTexture,
28142
28143	isVideoTexture: true,
28144
28145	update: function () {
28146
28147		var video = this.image;
28148
28149		if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
28150
28151			this.needsUpdate = true;
28152
28153		}
28154
28155	}
28156
28157} );
28158
28159/**
28160 * @author alteredq / http://alteredqualia.com/
28161 */
28162
28163function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
28164
28165	Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
28166
28167	this.image = { width: width, height: height };
28168	this.mipmaps = mipmaps;
28169
28170	// no flipping for cube textures
28171	// (also flipping doesn't work for compressed textures )
28172
28173	this.flipY = false;
28174
28175	// can't generate mipmaps for compressed textures
28176	// mips must be embedded in DDS files
28177
28178	this.generateMipmaps = false;
28179
28180}
28181
28182CompressedTexture.prototype = Object.create( Texture.prototype );
28183CompressedTexture.prototype.constructor = CompressedTexture;
28184
28185CompressedTexture.prototype.isCompressedTexture = true;
28186
28187/**
28188 * @author mrdoob / http://mrdoob.com/
28189 */
28190
28191function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
28192
28193	Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28194
28195	this.needsUpdate = true;
28196
28197}
28198
28199CanvasTexture.prototype = Object.create( Texture.prototype );
28200CanvasTexture.prototype.constructor = CanvasTexture;
28201CanvasTexture.prototype.isCanvasTexture = true;
28202
28203/**
28204 * @author Matt DesLauriers / @mattdesl
28205 * @author atix / arthursilber.de
28206 */
28207
28208function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
28209
28210	format = format !== undefined ? format : DepthFormat;
28211
28212	if ( format !== DepthFormat && format !== DepthStencilFormat ) {
28213
28214		throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
28215
28216	}
28217
28218	if ( type === undefined && format === DepthFormat ) type = UnsignedShortType;
28219	if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
28220
28221	Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28222
28223	this.image = { width: width, height: height };
28224
28225	this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
28226	this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
28227
28228	this.flipY = false;
28229	this.generateMipmaps	= false;
28230
28231}
28232
28233DepthTexture.prototype = Object.create( Texture.prototype );
28234DepthTexture.prototype.constructor = DepthTexture;
28235DepthTexture.prototype.isDepthTexture = true;
28236
28237/**
28238 * @author mrdoob / http://mrdoob.com/
28239 * @author Mugen87 / https://github.com/Mugen87
28240 */
28241
28242function WireframeGeometry( geometry ) {
28243
28244	BufferGeometry.call( this );
28245
28246	this.type = 'WireframeGeometry';
28247
28248	// buffer
28249
28250	var vertices = [];
28251
28252	// helper variables
28253
28254	var i, j, l, o, ol;
28255	var edge = [ 0, 0 ], edges = {}, e, edge1, edge2;
28256	var key, keys = [ 'a', 'b', 'c' ];
28257	var vertex;
28258
28259	// different logic for Geometry and BufferGeometry
28260
28261	if ( geometry && geometry.isGeometry ) {
28262
28263		// create a data structure that contains all edges without duplicates
28264
28265		var faces = geometry.faces;
28266
28267		for ( i = 0, l = faces.length; i < l; i ++ ) {
28268
28269			var face = faces[ i ];
28270
28271			for ( j = 0; j < 3; j ++ ) {
28272
28273				edge1 = face[ keys[ j ] ];
28274				edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
28275				edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
28276				edge[ 1 ] = Math.max( edge1, edge2 );
28277
28278				key = edge[ 0 ] + ',' + edge[ 1 ];
28279
28280				if ( edges[ key ] === undefined ) {
28281
28282					edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
28283
28284				}
28285
28286			}
28287
28288		}
28289
28290		// generate vertices
28291
28292		for ( key in edges ) {
28293
28294			e = edges[ key ];
28295
28296			vertex = geometry.vertices[ e.index1 ];
28297			vertices.push( vertex.x, vertex.y, vertex.z );
28298
28299			vertex = geometry.vertices[ e.index2 ];
28300			vertices.push( vertex.x, vertex.y, vertex.z );
28301
28302		}
28303
28304	} else if ( geometry && geometry.isBufferGeometry ) {
28305
28306		var position, indices, groups;
28307		var group, start, count;
28308		var index1, index2;
28309
28310		vertex = new Vector3();
28311
28312		if ( geometry.index !== null ) {
28313
28314			// indexed BufferGeometry
28315
28316			position = geometry.attributes.position;
28317			indices = geometry.index;
28318			groups = geometry.groups;
28319
28320			if ( groups.length === 0 ) {
28321
28322				groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
28323
28324			}
28325
28326			// create a data structure that contains all eges without duplicates
28327
28328			for ( o = 0, ol = groups.length; o < ol; ++ o ) {
28329
28330				group = groups[ o ];
28331
28332				start = group.start;
28333				count = group.count;
28334
28335				for ( i = start, l = ( start + count ); i < l; i += 3 ) {
28336
28337					for ( j = 0; j < 3; j ++ ) {
28338
28339						edge1 = indices.getX( i + j );
28340						edge2 = indices.getX( i + ( j + 1 ) % 3 );
28341						edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates
28342						edge[ 1 ] = Math.max( edge1, edge2 );
28343
28344						key = edge[ 0 ] + ',' + edge[ 1 ];
28345
28346						if ( edges[ key ] === undefined ) {
28347
28348							edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };
28349
28350						}
28351
28352					}
28353
28354				}
28355
28356			}
28357
28358			// generate vertices
28359
28360			for ( key in edges ) {
28361
28362				e = edges[ key ];
28363
28364				vertex.fromBufferAttribute( position, e.index1 );
28365				vertices.push( vertex.x, vertex.y, vertex.z );
28366
28367				vertex.fromBufferAttribute( position, e.index2 );
28368				vertices.push( vertex.x, vertex.y, vertex.z );
28369
28370			}
28371
28372		} else {
28373
28374			// non-indexed BufferGeometry
28375
28376			position = geometry.attributes.position;
28377
28378			for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
28379
28380				for ( j = 0; j < 3; j ++ ) {
28381
28382					// three edges per triangle, an edge is represented as (index1, index2)
28383					// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
28384
28385					index1 = 3 * i + j;
28386					vertex.fromBufferAttribute( position, index1 );
28387					vertices.push( vertex.x, vertex.y, vertex.z );
28388
28389					index2 = 3 * i + ( ( j + 1 ) % 3 );
28390					vertex.fromBufferAttribute( position, index2 );
28391					vertices.push( vertex.x, vertex.y, vertex.z );
28392
28393				}
28394
28395			}
28396
28397		}
28398
28399	}
28400
28401	// build geometry
28402
28403	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28404
28405}
28406
28407WireframeGeometry.prototype = Object.create( BufferGeometry.prototype );
28408WireframeGeometry.prototype.constructor = WireframeGeometry;
28409
28410/**
28411 * @author zz85 / https://github.com/zz85
28412 * @author Mugen87 / https://github.com/Mugen87
28413 *
28414 * Parametric Surfaces Geometry
28415 * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
28416 */
28417
28418// ParametricGeometry
28419
28420function ParametricGeometry( func, slices, stacks ) {
28421
28422	Geometry.call( this );
28423
28424	this.type = 'ParametricGeometry';
28425
28426	this.parameters = {
28427		func: func,
28428		slices: slices,
28429		stacks: stacks
28430	};
28431
28432	this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
28433	this.mergeVertices();
28434
28435}
28436
28437ParametricGeometry.prototype = Object.create( Geometry.prototype );
28438ParametricGeometry.prototype.constructor = ParametricGeometry;
28439
28440// ParametricBufferGeometry
28441
28442function ParametricBufferGeometry( func, slices, stacks ) {
28443
28444	BufferGeometry.call( this );
28445
28446	this.type = 'ParametricBufferGeometry';
28447
28448	this.parameters = {
28449		func: func,
28450		slices: slices,
28451		stacks: stacks
28452	};
28453
28454	// buffers
28455
28456	var indices = [];
28457	var vertices = [];
28458	var normals = [];
28459	var uvs = [];
28460
28461	var EPS = 0.00001;
28462
28463	var normal = new Vector3();
28464
28465	var p0 = new Vector3(), p1 = new Vector3();
28466	var pu = new Vector3(), pv = new Vector3();
28467
28468	var i, j;
28469
28470	if ( func.length < 3 ) {
28471
28472		console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
28473
28474	}
28475
28476	// generate vertices, normals and uvs
28477
28478	var sliceCount = slices + 1;
28479
28480	for ( i = 0; i <= stacks; i ++ ) {
28481
28482		var v = i / stacks;
28483
28484		for ( j = 0; j <= slices; j ++ ) {
28485
28486			var u = j / slices;
28487
28488			// vertex
28489
28490			func( u, v, p0 );
28491			vertices.push( p0.x, p0.y, p0.z );
28492
28493			// normal
28494
28495			// approximate tangent vectors via finite differences
28496
28497			if ( u - EPS >= 0 ) {
28498
28499				func( u - EPS, v, p1 );
28500				pu.subVectors( p0, p1 );
28501
28502			} else {
28503
28504				func( u + EPS, v, p1 );
28505				pu.subVectors( p1, p0 );
28506
28507			}
28508
28509			if ( v - EPS >= 0 ) {
28510
28511				func( u, v - EPS, p1 );
28512				pv.subVectors( p0, p1 );
28513
28514			} else {
28515
28516				func( u, v + EPS, p1 );
28517				pv.subVectors( p1, p0 );
28518
28519			}
28520
28521			// cross product of tangent vectors returns surface normal
28522
28523			normal.crossVectors( pu, pv ).normalize();
28524			normals.push( normal.x, normal.y, normal.z );
28525
28526			// uv
28527
28528			uvs.push( u, v );
28529
28530		}
28531
28532	}
28533
28534	// generate indices
28535
28536	for ( i = 0; i < stacks; i ++ ) {
28537
28538		for ( j = 0; j < slices; j ++ ) {
28539
28540			var a = i * sliceCount + j;
28541			var b = i * sliceCount + j + 1;
28542			var c = ( i + 1 ) * sliceCount + j + 1;
28543			var d = ( i + 1 ) * sliceCount + j;
28544
28545			// faces one and two
28546
28547			indices.push( a, b, d );
28548			indices.push( b, c, d );
28549
28550		}
28551
28552	}
28553
28554	// build geometry
28555
28556	this.setIndex( indices );
28557	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
28558	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
28559	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
28560
28561}
28562
28563ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28564ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
28565
28566/**
28567 * @author clockworkgeek / https://github.com/clockworkgeek
28568 * @author timothypratley / https://github.com/timothypratley
28569 * @author WestLangley / http://github.com/WestLangley
28570 * @author Mugen87 / https://github.com/Mugen87
28571 */
28572
28573// PolyhedronGeometry
28574
28575function PolyhedronGeometry( vertices, indices, radius, detail ) {
28576
28577	Geometry.call( this );
28578
28579	this.type = 'PolyhedronGeometry';
28580
28581	this.parameters = {
28582		vertices: vertices,
28583		indices: indices,
28584		radius: radius,
28585		detail: detail
28586	};
28587
28588	this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
28589	this.mergeVertices();
28590
28591}
28592
28593PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
28594PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
28595
28596// PolyhedronBufferGeometry
28597
28598function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
28599
28600	BufferGeometry.call( this );
28601
28602	this.type = 'PolyhedronBufferGeometry';
28603
28604	this.parameters = {
28605		vertices: vertices,
28606		indices: indices,
28607		radius: radius,
28608		detail: detail
28609	};
28610
28611	radius = radius || 1;
28612	detail = detail || 0;
28613
28614	// default buffer data
28615
28616	var vertexBuffer = [];
28617	var uvBuffer = [];
28618
28619	// the subdivision creates the vertex buffer data
28620
28621	subdivide( detail );
28622
28623	// all vertices should lie on a conceptual sphere with a given radius
28624
28625	applyRadius( radius );
28626
28627	// finally, create the uv data
28628
28629	generateUVs();
28630
28631	// build non-indexed geometry
28632
28633	this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
28634	this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
28635	this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
28636
28637	if ( detail === 0 ) {
28638
28639		this.computeVertexNormals(); // flat normals
28640
28641	} else {
28642
28643		this.normalizeNormals(); // smooth normals
28644
28645	}
28646
28647	// helper functions
28648
28649	function subdivide( detail ) {
28650
28651		var a = new Vector3();
28652		var b = new Vector3();
28653		var c = new Vector3();
28654
28655		// iterate over all faces and apply a subdivison with the given detail value
28656
28657		for ( var i = 0; i < indices.length; i += 3 ) {
28658
28659			// get the vertices of the face
28660
28661			getVertexByIndex( indices[ i + 0 ], a );
28662			getVertexByIndex( indices[ i + 1 ], b );
28663			getVertexByIndex( indices[ i + 2 ], c );
28664
28665			// perform subdivision
28666
28667			subdivideFace( a, b, c, detail );
28668
28669		}
28670
28671	}
28672
28673	function subdivideFace( a, b, c, detail ) {
28674
28675		var cols = Math.pow( 2, detail );
28676
28677		// we use this multidimensional array as a data structure for creating the subdivision
28678
28679		var v = [];
28680
28681		var i, j;
28682
28683		// construct all of the vertices for this subdivision
28684
28685		for ( i = 0; i <= cols; i ++ ) {
28686
28687			v[ i ] = [];
28688
28689			var aj = a.clone().lerp( c, i / cols );
28690			var bj = b.clone().lerp( c, i / cols );
28691
28692			var rows = cols - i;
28693
28694			for ( j = 0; j <= rows; j ++ ) {
28695
28696				if ( j === 0 && i === cols ) {
28697
28698					v[ i ][ j ] = aj;
28699
28700				} else {
28701
28702					v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
28703
28704				}
28705
28706			}
28707
28708		}
28709
28710		// construct all of the faces
28711
28712		for ( i = 0; i < cols; i ++ ) {
28713
28714			for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
28715
28716				var k = Math.floor( j / 2 );
28717
28718				if ( j % 2 === 0 ) {
28719
28720					pushVertex( v[ i ][ k + 1 ] );
28721					pushVertex( v[ i + 1 ][ k ] );
28722					pushVertex( v[ i ][ k ] );
28723
28724				} else {
28725
28726					pushVertex( v[ i ][ k + 1 ] );
28727					pushVertex( v[ i + 1 ][ k + 1 ] );
28728					pushVertex( v[ i + 1 ][ k ] );
28729
28730				}
28731
28732			}
28733
28734		}
28735
28736	}
28737
28738	function applyRadius( radius ) {
28739
28740		var vertex = new Vector3();
28741
28742		// iterate over the entire buffer and apply the radius to each vertex
28743
28744		for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
28745
28746			vertex.x = vertexBuffer[ i + 0 ];
28747			vertex.y = vertexBuffer[ i + 1 ];
28748			vertex.z = vertexBuffer[ i + 2 ];
28749
28750			vertex.normalize().multiplyScalar( radius );
28751
28752			vertexBuffer[ i + 0 ] = vertex.x;
28753			vertexBuffer[ i + 1 ] = vertex.y;
28754			vertexBuffer[ i + 2 ] = vertex.z;
28755
28756		}
28757
28758	}
28759
28760	function generateUVs() {
28761
28762		var vertex = new Vector3();
28763
28764		for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
28765
28766			vertex.x = vertexBuffer[ i + 0 ];
28767			vertex.y = vertexBuffer[ i + 1 ];
28768			vertex.z = vertexBuffer[ i + 2 ];
28769
28770			var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
28771			var v = inclination( vertex ) / Math.PI + 0.5;
28772			uvBuffer.push( u, 1 - v );
28773
28774		}
28775
28776		correctUVs();
28777
28778		correctSeam();
28779
28780	}
28781
28782	function correctSeam() {
28783
28784		// handle case when face straddles the seam, see #3269
28785
28786		for ( var i = 0; i < uvBuffer.length; i += 6 ) {
28787
28788			// uv data of a single face
28789
28790			var x0 = uvBuffer[ i + 0 ];
28791			var x1 = uvBuffer[ i + 2 ];
28792			var x2 = uvBuffer[ i + 4 ];
28793
28794			var max = Math.max( x0, x1, x2 );
28795			var min = Math.min( x0, x1, x2 );
28796
28797			// 0.9 is somewhat arbitrary
28798
28799			if ( max > 0.9 && min < 0.1 ) {
28800
28801				if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
28802				if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
28803				if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
28804
28805			}
28806
28807		}
28808
28809	}
28810
28811	function pushVertex( vertex ) {
28812
28813		vertexBuffer.push( vertex.x, vertex.y, vertex.z );
28814
28815	}
28816
28817	function getVertexByIndex( index, vertex ) {
28818
28819		var stride = index * 3;
28820
28821		vertex.x = vertices[ stride + 0 ];
28822		vertex.y = vertices[ stride + 1 ];
28823		vertex.z = vertices[ stride + 2 ];
28824
28825	}
28826
28827	function correctUVs() {
28828
28829		var a = new Vector3();
28830		var b = new Vector3();
28831		var c = new Vector3();
28832
28833		var centroid = new Vector3();
28834
28835		var uvA = new Vector2();
28836		var uvB = new Vector2();
28837		var uvC = new Vector2();
28838
28839		for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
28840
28841			a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
28842			b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
28843			c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
28844
28845			uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
28846			uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
28847			uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
28848
28849			centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
28850
28851			var azi = azimuth( centroid );
28852
28853			correctUV( uvA, j + 0, a, azi );
28854			correctUV( uvB, j + 2, b, azi );
28855			correctUV( uvC, j + 4, c, azi );
28856
28857		}
28858
28859	}
28860
28861	function correctUV( uv, stride, vector, azimuth ) {
28862
28863		if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
28864
28865			uvBuffer[ stride ] = uv.x - 1;
28866
28867		}
28868
28869		if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
28870
28871			uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
28872
28873		}
28874
28875	}
28876
28877	// Angle around the Y axis, counter-clockwise when looking from above.
28878
28879	function azimuth( vector ) {
28880
28881		return Math.atan2( vector.z, - vector.x );
28882
28883	}
28884
28885
28886	// Angle above the XZ plane.
28887
28888	function inclination( vector ) {
28889
28890		return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
28891
28892	}
28893
28894}
28895
28896PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
28897PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
28898
28899/**
28900 * @author timothypratley / https://github.com/timothypratley
28901 * @author Mugen87 / https://github.com/Mugen87
28902 */
28903
28904// TetrahedronGeometry
28905
28906function TetrahedronGeometry( radius, detail ) {
28907
28908	Geometry.call( this );
28909
28910	this.type = 'TetrahedronGeometry';
28911
28912	this.parameters = {
28913		radius: radius,
28914		detail: detail
28915	};
28916
28917	this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );
28918	this.mergeVertices();
28919
28920}
28921
28922TetrahedronGeometry.prototype = Object.create( Geometry.prototype );
28923TetrahedronGeometry.prototype.constructor = TetrahedronGeometry;
28924
28925// TetrahedronBufferGeometry
28926
28927function TetrahedronBufferGeometry( radius, detail ) {
28928
28929	var vertices = [
28930		1, 1, 1, 	- 1, - 1, 1, 	- 1, 1, - 1, 	1, - 1, - 1
28931	];
28932
28933	var indices = [
28934		2, 1, 0, 	0, 3, 2,	1, 3, 0,	2, 3, 1
28935	];
28936
28937	PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
28938
28939	this.type = 'TetrahedronBufferGeometry';
28940
28941	this.parameters = {
28942		radius: radius,
28943		detail: detail
28944	};
28945
28946}
28947
28948TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
28949TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;
28950
28951/**
28952 * @author timothypratley / https://github.com/timothypratley
28953 * @author Mugen87 / https://github.com/Mugen87
28954 */
28955
28956// OctahedronGeometry
28957
28958function OctahedronGeometry( radius, detail ) {
28959
28960	Geometry.call( this );
28961
28962	this.type = 'OctahedronGeometry';
28963
28964	this.parameters = {
28965		radius: radius,
28966		detail: detail
28967	};
28968
28969	this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );
28970	this.mergeVertices();
28971
28972}
28973
28974OctahedronGeometry.prototype = Object.create( Geometry.prototype );
28975OctahedronGeometry.prototype.constructor = OctahedronGeometry;
28976
28977// OctahedronBufferGeometry
28978
28979function OctahedronBufferGeometry( radius, detail ) {
28980
28981	var vertices = [
28982		1, 0, 0, 	- 1, 0, 0,	0, 1, 0,
28983		0, - 1, 0, 	0, 0, 1,	0, 0, - 1
28984	];
28985
28986	var indices = [
28987		0, 2, 4,	0, 4, 3,	0, 3, 5,
28988		0, 5, 2,	1, 2, 5,	1, 5, 3,
28989		1, 3, 4,	1, 4, 2
28990	];
28991
28992	PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
28993
28994	this.type = 'OctahedronBufferGeometry';
28995
28996	this.parameters = {
28997		radius: radius,
28998		detail: detail
28999	};
29000
29001}
29002
29003OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
29004OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;
29005
29006/**
29007 * @author timothypratley / https://github.com/timothypratley
29008 * @author Mugen87 / https://github.com/Mugen87
29009 */
29010
29011// IcosahedronGeometry
29012
29013function IcosahedronGeometry( radius, detail ) {
29014
29015	Geometry.call( this );
29016
29017	this.type = 'IcosahedronGeometry';
29018
29019	this.parameters = {
29020		radius: radius,
29021		detail: detail
29022	};
29023
29024	this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );
29025	this.mergeVertices();
29026
29027}
29028
29029IcosahedronGeometry.prototype = Object.create( Geometry.prototype );
29030IcosahedronGeometry.prototype.constructor = IcosahedronGeometry;
29031
29032// IcosahedronBufferGeometry
29033
29034function IcosahedronBufferGeometry( radius, detail ) {
29035
29036	var t = ( 1 + Math.sqrt( 5 ) ) / 2;
29037
29038	var vertices = [
29039		- 1, t, 0, 	1, t, 0, 	- 1, - t, 0, 	1, - t, 0,
29040		 0, - 1, t, 	0, 1, t,	0, - 1, - t, 	0, 1, - t,
29041		 t, 0, - 1, 	t, 0, 1, 	- t, 0, - 1, 	- t, 0, 1
29042	];
29043
29044	var indices = [
29045		 0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
29046		 1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
29047		 3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
29048		 4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
29049	];
29050
29051	PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
29052
29053	this.type = 'IcosahedronBufferGeometry';
29054
29055	this.parameters = {
29056		radius: radius,
29057		detail: detail
29058	};
29059
29060}
29061
29062IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
29063IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;
29064
29065/**
29066 * @author Abe Pazos / https://hamoid.com
29067 * @author Mugen87 / https://github.com/Mugen87
29068 */
29069
29070// DodecahedronGeometry
29071
29072function DodecahedronGeometry( radius, detail ) {
29073
29074	Geometry.call( this );
29075
29076	this.type = 'DodecahedronGeometry';
29077
29078	this.parameters = {
29079		radius: radius,
29080		detail: detail
29081	};
29082
29083	this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );
29084	this.mergeVertices();
29085
29086}
29087
29088DodecahedronGeometry.prototype = Object.create( Geometry.prototype );
29089DodecahedronGeometry.prototype.constructor = DodecahedronGeometry;
29090
29091// DodecahedronBufferGeometry
29092
29093function DodecahedronBufferGeometry( radius, detail ) {
29094
29095	var t = ( 1 + Math.sqrt( 5 ) ) / 2;
29096	var r = 1 / t;
29097
29098	var vertices = [
29099
29100		// (±1, ±1, ±1)
29101		- 1, - 1, - 1,	- 1, - 1, 1,
29102		- 1, 1, - 1, - 1, 1, 1,
29103		1, - 1, - 1, 1, - 1, 1,
29104		1, 1, - 1, 1, 1, 1,
29105
29106		// (0, ±1/φ, ±φ)
29107		 0, - r, - t, 0, - r, t,
29108		 0, r, - t, 0, r, t,
29109
29110		// (±1/φ, ±φ, 0)
29111		- r, - t, 0, - r, t, 0,
29112		 r, - t, 0, r, t, 0,
29113
29114		// (±φ, 0, ±1/φ)
29115		- t, 0, - r, t, 0, - r,
29116		- t, 0, r, t, 0, r
29117	];
29118
29119	var indices = [
29120		3, 11, 7, 	3, 7, 15, 	3, 15, 13,
29121		7, 19, 17, 	7, 17, 6, 	7, 6, 15,
29122		17, 4, 8, 	17, 8, 10, 	17, 10, 6,
29123		8, 0, 16, 	8, 16, 2, 	8, 2, 10,
29124		0, 12, 1, 	0, 1, 18, 	0, 18, 16,
29125		6, 10, 2, 	6, 2, 13, 	6, 13, 15,
29126		2, 16, 18, 	2, 18, 3, 	2, 3, 13,
29127		18, 1, 9, 	18, 9, 11, 	18, 11, 3,
29128		4, 14, 12, 	4, 12, 0, 	4, 0, 8,
29129		11, 9, 5, 	11, 5, 19, 	11, 19, 7,
29130		19, 5, 14, 	19, 14, 4, 	19, 4, 17,
29131		1, 12, 14, 	1, 14, 5, 	1, 5, 9
29132	];
29133
29134	PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );
29135
29136	this.type = 'DodecahedronBufferGeometry';
29137
29138	this.parameters = {
29139		radius: radius,
29140		detail: detail
29141	};
29142
29143}
29144
29145DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );
29146DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;
29147
29148/**
29149 * @author oosmoxiecode / https://github.com/oosmoxiecode
29150 * @author WestLangley / https://github.com/WestLangley
29151 * @author zz85 / https://github.com/zz85
29152 * @author miningold / https://github.com/miningold
29153 * @author jonobr1 / https://github.com/jonobr1
29154 * @author Mugen87 / https://github.com/Mugen87
29155 *
29156 */
29157
29158// TubeGeometry
29159
29160function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {
29161
29162	Geometry.call( this );
29163
29164	this.type = 'TubeGeometry';
29165
29166	this.parameters = {
29167		path: path,
29168		tubularSegments: tubularSegments,
29169		radius: radius,
29170		radialSegments: radialSegments,
29171		closed: closed
29172	};
29173
29174	if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' );
29175
29176	var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );
29177
29178	// expose internals
29179
29180	this.tangents = bufferGeometry.tangents;
29181	this.normals = bufferGeometry.normals;
29182	this.binormals = bufferGeometry.binormals;
29183
29184	// create geometry
29185
29186	this.fromBufferGeometry( bufferGeometry );
29187	this.mergeVertices();
29188
29189}
29190
29191TubeGeometry.prototype = Object.create( Geometry.prototype );
29192TubeGeometry.prototype.constructor = TubeGeometry;
29193
29194// TubeBufferGeometry
29195
29196function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
29197
29198	BufferGeometry.call( this );
29199
29200	this.type = 'TubeBufferGeometry';
29201
29202	this.parameters = {
29203		path: path,
29204		tubularSegments: tubularSegments,
29205		radius: radius,
29206		radialSegments: radialSegments,
29207		closed: closed
29208	};
29209
29210	tubularSegments = tubularSegments || 64;
29211	radius = radius || 1;
29212	radialSegments = radialSegments || 8;
29213	closed = closed || false;
29214
29215	var frames = path.computeFrenetFrames( tubularSegments, closed );
29216
29217	// expose internals
29218
29219	this.tangents = frames.tangents;
29220	this.normals = frames.normals;
29221	this.binormals = frames.binormals;
29222
29223	// helper variables
29224
29225	var vertex = new Vector3();
29226	var normal = new Vector3();
29227	var uv = new Vector2();
29228	var P = new Vector3();
29229
29230	var i, j;
29231
29232	// buffer
29233
29234	var vertices = [];
29235	var normals = [];
29236	var uvs = [];
29237	var indices = [];
29238
29239	// create buffer data
29240
29241	generateBufferData();
29242
29243	// build geometry
29244
29245	this.setIndex( indices );
29246	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29247	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29248	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29249
29250	// functions
29251
29252	function generateBufferData() {
29253
29254		for ( i = 0; i < tubularSegments; i ++ ) {
29255
29256			generateSegment( i );
29257
29258		}
29259
29260		// if the geometry is not closed, generate the last row of vertices and normals
29261		// at the regular position on the given path
29262		//
29263		// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
29264
29265		generateSegment( ( closed === false ) ? tubularSegments : 0 );
29266
29267		// uvs are generated in a separate function.
29268		// this makes it easy compute correct values for closed geometries
29269
29270		generateUVs();
29271
29272		// finally create faces
29273
29274		generateIndices();
29275
29276	}
29277
29278	function generateSegment( i ) {
29279
29280		// we use getPointAt to sample evenly distributed points from the given path
29281
29282		P = path.getPointAt( i / tubularSegments, P );
29283
29284		// retrieve corresponding normal and binormal
29285
29286		var N = frames.normals[ i ];
29287		var B = frames.binormals[ i ];
29288
29289		// generate normals and vertices for the current segment
29290
29291		for ( j = 0; j <= radialSegments; j ++ ) {
29292
29293			var v = j / radialSegments * Math.PI * 2;
29294
29295			var sin = Math.sin( v );
29296			var cos = - Math.cos( v );
29297
29298			// normal
29299
29300			normal.x = ( cos * N.x + sin * B.x );
29301			normal.y = ( cos * N.y + sin * B.y );
29302			normal.z = ( cos * N.z + sin * B.z );
29303			normal.normalize();
29304
29305			normals.push( normal.x, normal.y, normal.z );
29306
29307			// vertex
29308
29309			vertex.x = P.x + radius * normal.x;
29310			vertex.y = P.y + radius * normal.y;
29311			vertex.z = P.z + radius * normal.z;
29312
29313			vertices.push( vertex.x, vertex.y, vertex.z );
29314
29315		}
29316
29317	}
29318
29319	function generateIndices() {
29320
29321		for ( j = 1; j <= tubularSegments; j ++ ) {
29322
29323			for ( i = 1; i <= radialSegments; i ++ ) {
29324
29325				var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
29326				var b = ( radialSegments + 1 ) * j + ( i - 1 );
29327				var c = ( radialSegments + 1 ) * j + i;
29328				var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
29329
29330				// faces
29331
29332				indices.push( a, b, d );
29333				indices.push( b, c, d );
29334
29335			}
29336
29337		}
29338
29339	}
29340
29341	function generateUVs() {
29342
29343		for ( i = 0; i <= tubularSegments; i ++ ) {
29344
29345			for ( j = 0; j <= radialSegments; j ++ ) {
29346
29347				uv.x = i / tubularSegments;
29348				uv.y = j / radialSegments;
29349
29350				uvs.push( uv.x, uv.y );
29351
29352			}
29353
29354		}
29355
29356	}
29357
29358}
29359
29360TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29361TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
29362
29363TubeBufferGeometry.prototype.toJSON = function () {
29364
29365	var data = BufferGeometry.prototype.toJSON.call( this );
29366
29367	data.path = this.parameters.path.toJSON();
29368
29369	return data;
29370
29371};
29372
29373/**
29374 * @author oosmoxiecode
29375 * @author Mugen87 / https://github.com/Mugen87
29376 *
29377 * based on http://www.blackpawn.com/texts/pqtorus/
29378 */
29379
29380// TorusKnotGeometry
29381
29382function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
29383
29384	Geometry.call( this );
29385
29386	this.type = 'TorusKnotGeometry';
29387
29388	this.parameters = {
29389		radius: radius,
29390		tube: tube,
29391		tubularSegments: tubularSegments,
29392		radialSegments: radialSegments,
29393		p: p,
29394		q: q
29395	};
29396
29397	if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
29398
29399	this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
29400	this.mergeVertices();
29401
29402}
29403
29404TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
29405TorusKnotGeometry.prototype.constructor = TorusKnotGeometry;
29406
29407// TorusKnotBufferGeometry
29408
29409function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {
29410
29411	BufferGeometry.call( this );
29412
29413	this.type = 'TorusKnotBufferGeometry';
29414
29415	this.parameters = {
29416		radius: radius,
29417		tube: tube,
29418		tubularSegments: tubularSegments,
29419		radialSegments: radialSegments,
29420		p: p,
29421		q: q
29422	};
29423
29424	radius = radius || 1;
29425	tube = tube || 0.4;
29426	tubularSegments = Math.floor( tubularSegments ) || 64;
29427	radialSegments = Math.floor( radialSegments ) || 8;
29428	p = p || 2;
29429	q = q || 3;
29430
29431	// buffers
29432
29433	var indices = [];
29434	var vertices = [];
29435	var normals = [];
29436	var uvs = [];
29437
29438	// helper variables
29439
29440	var i, j;
29441
29442	var vertex = new Vector3();
29443	var normal = new Vector3();
29444
29445	var P1 = new Vector3();
29446	var P2 = new Vector3();
29447
29448	var B = new Vector3();
29449	var T = new Vector3();
29450	var N = new Vector3();
29451
29452	// generate vertices, normals and uvs
29453
29454	for ( i = 0; i <= tubularSegments; ++ i ) {
29455
29456		// the radian "u" is used to calculate the position on the torus curve of the current tubular segement
29457
29458		var u = i / tubularSegments * p * Math.PI * 2;
29459
29460		// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
29461		// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
29462
29463		calculatePositionOnCurve( u, p, q, radius, P1 );
29464		calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
29465
29466		// calculate orthonormal basis
29467
29468		T.subVectors( P2, P1 );
29469		N.addVectors( P2, P1 );
29470		B.crossVectors( T, N );
29471		N.crossVectors( B, T );
29472
29473		// normalize B, N. T can be ignored, we don't use it
29474
29475		B.normalize();
29476		N.normalize();
29477
29478		for ( j = 0; j <= radialSegments; ++ j ) {
29479
29480			// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
29481			// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
29482
29483			var v = j / radialSegments * Math.PI * 2;
29484			var cx = - tube * Math.cos( v );
29485			var cy = tube * Math.sin( v );
29486
29487			// now calculate the final vertex position.
29488			// first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
29489
29490			vertex.x = P1.x + ( cx * N.x + cy * B.x );
29491			vertex.y = P1.y + ( cx * N.y + cy * B.y );
29492			vertex.z = P1.z + ( cx * N.z + cy * B.z );
29493
29494			vertices.push( vertex.x, vertex.y, vertex.z );
29495
29496			// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
29497
29498			normal.subVectors( vertex, P1 ).normalize();
29499
29500			normals.push( normal.x, normal.y, normal.z );
29501
29502			// uv
29503
29504			uvs.push( i / tubularSegments );
29505			uvs.push( j / radialSegments );
29506
29507		}
29508
29509	}
29510
29511	// generate indices
29512
29513	for ( j = 1; j <= tubularSegments; j ++ ) {
29514
29515		for ( i = 1; i <= radialSegments; i ++ ) {
29516
29517			// indices
29518
29519			var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
29520			var b = ( radialSegments + 1 ) * j + ( i - 1 );
29521			var c = ( radialSegments + 1 ) * j + i;
29522			var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
29523
29524			// faces
29525
29526			indices.push( a, b, d );
29527			indices.push( b, c, d );
29528
29529		}
29530
29531	}
29532
29533	// build geometry
29534
29535	this.setIndex( indices );
29536	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29537	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29538	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29539
29540	// this function calculates the current position on the torus curve
29541
29542	function calculatePositionOnCurve( u, p, q, radius, position ) {
29543
29544		var cu = Math.cos( u );
29545		var su = Math.sin( u );
29546		var quOverP = q / p * u;
29547		var cs = Math.cos( quOverP );
29548
29549		position.x = radius * ( 2 + cs ) * 0.5 * cu;
29550		position.y = radius * ( 2 + cs ) * su * 0.5;
29551		position.z = radius * Math.sin( quOverP ) * 0.5;
29552
29553	}
29554
29555}
29556
29557TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29558TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;
29559
29560/**
29561 * @author oosmoxiecode
29562 * @author mrdoob / http://mrdoob.com/
29563 * @author Mugen87 / https://github.com/Mugen87
29564 */
29565
29566// TorusGeometry
29567
29568function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
29569
29570	Geometry.call( this );
29571
29572	this.type = 'TorusGeometry';
29573
29574	this.parameters = {
29575		radius: radius,
29576		tube: tube,
29577		radialSegments: radialSegments,
29578		tubularSegments: tubularSegments,
29579		arc: arc
29580	};
29581
29582	this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );
29583	this.mergeVertices();
29584
29585}
29586
29587TorusGeometry.prototype = Object.create( Geometry.prototype );
29588TorusGeometry.prototype.constructor = TorusGeometry;
29589
29590// TorusBufferGeometry
29591
29592function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {
29593
29594	BufferGeometry.call( this );
29595
29596	this.type = 'TorusBufferGeometry';
29597
29598	this.parameters = {
29599		radius: radius,
29600		tube: tube,
29601		radialSegments: radialSegments,
29602		tubularSegments: tubularSegments,
29603		arc: arc
29604	};
29605
29606	radius = radius || 1;
29607	tube = tube || 0.4;
29608	radialSegments = Math.floor( radialSegments ) || 8;
29609	tubularSegments = Math.floor( tubularSegments ) || 6;
29610	arc = arc || Math.PI * 2;
29611
29612	// buffers
29613
29614	var indices = [];
29615	var vertices = [];
29616	var normals = [];
29617	var uvs = [];
29618
29619	// helper variables
29620
29621	var center = new Vector3();
29622	var vertex = new Vector3();
29623	var normal = new Vector3();
29624
29625	var j, i;
29626
29627	// generate vertices, normals and uvs
29628
29629	for ( j = 0; j <= radialSegments; j ++ ) {
29630
29631		for ( i = 0; i <= tubularSegments; i ++ ) {
29632
29633			var u = i / tubularSegments * arc;
29634			var v = j / radialSegments * Math.PI * 2;
29635
29636			// vertex
29637
29638			vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
29639			vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
29640			vertex.z = tube * Math.sin( v );
29641
29642			vertices.push( vertex.x, vertex.y, vertex.z );
29643
29644			// normal
29645
29646			center.x = radius * Math.cos( u );
29647			center.y = radius * Math.sin( u );
29648			normal.subVectors( vertex, center ).normalize();
29649
29650			normals.push( normal.x, normal.y, normal.z );
29651
29652			// uv
29653
29654			uvs.push( i / tubularSegments );
29655			uvs.push( j / radialSegments );
29656
29657		}
29658
29659	}
29660
29661	// generate indices
29662
29663	for ( j = 1; j <= radialSegments; j ++ ) {
29664
29665		for ( i = 1; i <= tubularSegments; i ++ ) {
29666
29667			// indices
29668
29669			var a = ( tubularSegments + 1 ) * j + i - 1;
29670			var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
29671			var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
29672			var d = ( tubularSegments + 1 ) * j + i;
29673
29674			// faces
29675
29676			indices.push( a, b, d );
29677			indices.push( b, c, d );
29678
29679		}
29680
29681	}
29682
29683	// build geometry
29684
29685	this.setIndex( indices );
29686	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29687	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29688	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29689
29690}
29691
29692TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
29693TorusBufferGeometry.prototype.constructor = TorusBufferGeometry;
29694
29695/**
29696 * @author Mugen87 / https://github.com/Mugen87
29697 * Port from https://github.com/mapbox/earcut (v2.2.2)
29698 */
29699
29700var Earcut = {
29701
29702	triangulate: function ( data, holeIndices, dim ) {
29703
29704		dim = dim || 2;
29705
29706		var hasHoles = holeIndices && holeIndices.length,
29707			outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length,
29708			outerNode = linkedList( data, 0, outerLen, dim, true ),
29709			triangles = [];
29710
29711		if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
29712
29713		var minX, minY, maxX, maxY, x, y, invSize;
29714
29715		if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
29716
29717		// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
29718		if ( data.length > 80 * dim ) {
29719
29720			minX = maxX = data[ 0 ];
29721			minY = maxY = data[ 1 ];
29722
29723			for ( var i = dim; i < outerLen; i += dim ) {
29724
29725				x = data[ i ];
29726				y = data[ i + 1 ];
29727				if ( x < minX ) minX = x;
29728				if ( y < minY ) minY = y;
29729				if ( x > maxX ) maxX = x;
29730				if ( y > maxY ) maxY = y;
29731
29732			}
29733
29734			// minX, minY and invSize are later used to transform coords into integers for z-order calculation
29735			invSize = Math.max( maxX - minX, maxY - minY );
29736			invSize = invSize !== 0 ? 1 / invSize : 0;
29737
29738		}
29739
29740		earcutLinked( outerNode, triangles, dim, minX, minY, invSize );
29741
29742		return triangles;
29743
29744	}
29745
29746};
29747
29748// create a circular doubly linked list from polygon points in the specified winding order
29749function linkedList( data, start, end, dim, clockwise ) {
29750
29751	var i, last;
29752
29753	if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
29754
29755		for ( i = start; i < end;
29755 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
29756
29757	} else {
29758
29759		for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
29760
29761	}
29762
29763	if ( last && equals( last, last.next ) ) {
29764
29765		removeNode( last );
29766		last = last.next;
29767
29768	}
29769
29770	return last;
29771
29772}
29773
29774// eliminate colinear or duplicate points
29775function filterPoints( start, end ) {
29776
29777	if ( ! start ) return start;
29778	if ( ! end ) end = start;
29779
29780	var p = start,
29781		again;
29782	do {
29783
29784		again = false;
29785
29786		if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
29787
29788			removeNode( p );
29789			p = end = p.prev;
29790			if ( p === p.next ) break;
29791			again = true;
29792
29793		} else {
29794
29795			p = p.next;
29796
29797		}
29798
29799	} while ( again || p !== end );
29800
29801	return end;
29802
29803}
29804
29805// main ear slicing loop which triangulates a polygon (given as a linked list)
29806function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
29807
29808	if ( ! ear ) return;
29809
29810	// interlink polygon nodes in z-order
29811	if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
29812
29813	var stop = ear,
29814		prev, next;
29815
29816	// iterate through ears, slicing them one by one
29817	while ( ear.prev !== ear.next ) {
29818
29819		prev = ear.prev;
29820		next = ear.next;
29821
29822		if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
29823
29824			// cut off the triangle
29825			triangles.push( prev.i / dim );
29826			triangles.push( ear.i / dim );
29827			triangles.push( next.i / dim );
29828
29829			removeNode( ear );
29830
29831			// skipping the next vertex leads to less sliver triangles
29832			ear = next.next;
29833			stop = next.next;
29834
29835			continue;
29836
29837		}
29838
29839		ear = next;
29840
29841		// if we looped through the whole remaining polygon and can't find any more ears
29842		if ( ear === stop ) {
29843
29844			// try filtering points and slicing again
29845			if ( ! pass ) {
29846
29847				earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
29848
29849				// if this didn't work, try curing all small self-intersections locally
29850
29851			} else if ( pass === 1 ) {
29852
29853				ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
29854				earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
29855
29856				// as a last resort, try splitting the remaining polygon into two
29857
29858			} else if ( pass === 2 ) {
29859
29860				splitEarcut( ear, triangles, dim, minX, minY, invSize );
29861
29862			}
29863
29864			break;
29865
29866		}
29867
29868	}
29869
29870}
29871
29872// check whether a polygon node forms a valid ear with adjacent nodes
29873function isEar( ear ) {
29874
29875	var a = ear.prev,
29876		b = ear,
29877		c = ear.next;
29878
29879	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
29880
29881	// now make sure we don't have other points inside the potential ear
29882	var p = ear.next.next;
29883
29884	while ( p !== ear.prev ) {
29885
29886		if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
29887			area( p.prev, p, p.next ) >= 0 ) return false;
29888		p = p.next;
29889
29890	}
29891
29892	return true;
29893
29894}
29895
29896function isEarHashed( ear, minX, minY, invSize ) {
29897
29898	var a = ear.prev,
29899		b = ear,
29900		c = ear.next;
29901
29902	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
29903
29904	// triangle bbox; min & max are calculated like this for speed
29905	var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),
29906		minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),
29907		maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),
29908		maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );
29909
29910	// z-order range for the current triangle bbox;
29911	var minZ = zOrder( minTX, minTY, minX, minY, invSize ),
29912		maxZ = zOrder( maxTX, maxTY, minX, minY, invSize );
29913
29914	var p = ear.prevZ,
29915		n = ear.nextZ;
29916
29917	// look for points inside the triangle in both directions
29918	while ( p && p.z >= minZ && n && n.z <= maxZ ) {
29919
29920		if ( p !== ear.prev && p !== ear.next &&
29921			pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
29922			area( p.prev, p, p.next ) >= 0 ) return false;
29923		p = p.prevZ;
29924
29925		if ( n !== ear.prev && n !== ear.next &&
29926			pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
29927			area( n.prev, n, n.next ) >= 0 ) return false;
29928		n = n.nextZ;
29929
29930	}
29931
29932	// look for remaining points in decreasing z-order
29933	while ( p && p.z >= minZ ) {
29934
29935		if ( p !== ear.prev && p !== ear.next &&
29936			pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&
29937			area( p.prev, p, p.next ) >= 0 ) return false;
vendor: 16,168 bytes, lines 29938-30704
29938		p = p.prevZ;
29939
29940	}
29941
29942	// look for remaining points in increasing z-order
29943	while ( n && n.z <= maxZ ) {
29944
29945		if ( n !== ear.prev && n !== ear.next &&
29946			pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&
29947			area( n.prev, n, n.next ) >= 0 ) return false;
29948		n = n.nextZ;
29949
29950	}
29951
29952	return true;
29953
29954}
29955
29956// go through all polygon nodes and cure small local self-intersections
29957function cureLocalIntersections( start, triangles, dim ) {
29958
29959	var p = start;
29960	do {
29961
29962		var a = p.prev,
29963			b = p.next.next;
29964
29965		if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
29966
29967			triangles.push( a.i / dim );
29968			triangles.push( p.i / dim );
29969			triangles.push( b.i / dim );
29970
29971			// remove two nodes involved
29972			removeNode( p );
29973			removeNode( p.next );
29974
29975			p = start = b;
29976
29977		}
29978
29979		p = p.next;
29980
29981	} while ( p !== start );
29982
29983	return filterPoints( p );
29984
29985}
29986
29987// try splitting polygon into two and triangulate them independently
29988function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
29989
29990	// look for a valid diagonal that divides the polygon into two
29991	var a = start;
29992	do {
29993
29994		var b = a.next.next;
29995		while ( b !== a.prev ) {
29996
29997			if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
29998
29999				// split the polygon in two by the diagonal
30000				var c = splitPolygon( a, b );
30001
30002				// filter colinear points around the cuts
30003				a = filterPoints( a, a.next );
30004				c = filterPoints( c, c.next );
30005
30006				// run earcut on each half
30007				earcutLinked( a, triangles, dim, minX, minY, invSize );
30008				earcutLinked( c, triangles, dim, minX, minY, invSize );
30009				return;
30010
30011			}
30012
30013			b = b.next;
30014
30015		}
30016
30017		a = a.next;
30018
30019	} while ( a !== start );
30020
30021}
30022
30023// link every hole into the outer loop, producing a single-ring polygon without holes
30024function eliminateHoles( data, holeIndices, outerNode, dim ) {
30025
30026	var queue = [],
30027		i, len, start, end, list;
30028
30029	for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
30030
30031		start = holeIndices[ i ] * dim;
30032		end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
30033		list = linkedList( data, start, end, dim, false );
30034		if ( list === list.next ) list.steiner = true;
30035		queue.push( getLeftmost( list ) );
30036
30037	}
30038
30039	queue.sort( compareX );
30040
30041	// process holes from left to right
30042	for ( i = 0; i < queue.length; i ++ ) {
30043
30044		eliminateHole( queue[ i ], outerNode );
30045		outerNode = filterPoints( outerNode, outerNode.next );
30046
30047	}
30048
30049	return outerNode;
30050
30051}
30052
30053function compareX( a, b ) {
30054
30055	return a.x - b.x;
30056
30057}
30058
30059// find a bridge between vertices that connects hole with an outer ring and and link it
30060function eliminateHole( hole, outerNode ) {
30061
30062	outerNode = findHoleBridge( hole, outerNode );
30063	if ( outerNode ) {
30064
30065		var b = splitPolygon( outerNode, hole );
30066
30067		// filter collinear points around the cuts
30068		filterPoints( outerNode, outerNode.next );
30069		filterPoints( b, b.next );
30070
30071	}
30072
30073}
30074
30075// David Eberly's algorithm for finding a bridge between hole and outer polygon
30076function findHoleBridge( hole, outerNode ) {
30077
30078	var p = outerNode,
30079		hx = hole.x,
30080		hy = hole.y,
30081		qx = - Infinity,
30082		m;
30083
30084	// find a segment intersected by a ray from the hole's leftmost point to the left;
30085	// segment's endpoint with lesser x will be potential connection point
30086	do {
30087
30088		if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
30089
30090			var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
30091			if ( x <= hx && x > qx ) {
30092
30093				qx = x;
30094				if ( x === hx ) {
30095
30096					if ( hy === p.y ) return p;
30097					if ( hy === p.next.y ) return p.next;
30098
30099				}
30100
30101				m = p.x < p.next.x ? p : p.next;
30102
30103			}
30104
30105		}
30106
30107		p = p.next;
30108
30109	} while ( p !== outerNode );
30110
30111	if ( ! m ) return null;
30112
30113	if ( hx === qx ) return m; // hole touches outer segment; pick leftmost endpoint
30114
30115	// look for points inside the triangle of hole point, segment intersection and endpoint;
30116	// if there are no points found, we have a valid connection;
30117	// otherwise choose the point of the minimum angle with the ray as connection point
30118
30119	var stop = m,
30120		mx = m.x,
30121		my = m.y,
30122		tanMin = Infinity,
30123		tan;
30124
30125	p = m;
30126
30127	do {
30128
30129		if ( hx >= p.x && p.x >= mx && hx !== p.x &&
30130				pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
30131
30132			tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
30133
30134			if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
30135
30136				m = p;
30137				tanMin = tan;
30138
30139			}
30140
30141		}
30142
30143		p = p.next;
30144
30145	} while ( p !== stop );
30146
30147	return m;
30148
30149}
30150
30151// whether sector in vertex m contains sector in vertex p in the same coordinates
30152function sectorContainsSector( m, p ) {
30153
30154	return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
30155
30156}
30157
30158// interlink polygon nodes in z-order
30159function indexCurve( start, minX, minY, invSize ) {
30160
30161	var p = start;
30162	do {
30163
30164		if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
30165		p.prevZ = p.prev;
30166		p.nextZ = p.next;
30167		p = p.next;
30168
30169	} while ( p !== start );
30170
30171	p.prevZ.nextZ = null;
30172	p.prevZ = null;
30173
30174	sortLinked( p );
30175
30176}
30177
30178// Simon Tatham's linked list merge sort algorithm
30179// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
30180function sortLinked( list ) {
30181
30182	var i, p, q, e, tail, numMerges, pSize, qSize,
30183		inSize = 1;
30184
30185	do {
30186
30187		p = list;
30188		list = null;
30189		tail = null;
30190		numMerges = 0;
30191
30192		while ( p ) {
30193
30194			numMerges ++;
30195			q = p;
30196			pSize = 0;
30197			for ( i = 0; i < inSize; i ++ ) {
30198
30199				pSize ++;
30200				q = q.nextZ;
30201				if ( ! q ) break;
30202
30203			}
30204
30205			qSize = inSize;
30206
30207			while ( pSize > 0 || ( qSize > 0 && q ) ) {
30208
30209				if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
30210
30211					e = p;
30212					p = p.nextZ;
30213					pSize --;
30214
30215				} else {
30216
30217					e = q;
30218					q = q.nextZ;
30219					qSize --;
30220
30221				}
30222
30223				if ( tail ) tail.nextZ = e;
30224				else list = e;
30225
30226				e.prevZ = tail;
30227				tail = e;
30228
30229			}
30230
30231			p = q;
30232
30233		}
30234
30235		tail.nextZ = null;
30236		inSize *= 2;
30237
30238	} while ( numMerges > 1 );
30239
30240	return list;
30241
30242}
30243
30244// z-order of a point given coords and inverse of the longer side of data bbox
30245function zOrder( x, y, minX, minY, invSize ) {
30246
30247	// coords are transformed into non-negative 15-bit integer range
30248	x = 32767 * ( x - minX ) * invSize;
30249	y = 32767 * ( y - minY ) * invSize;
30250
30251	x = ( x | ( x << 8 ) ) & 0x00FF00FF;
30252	x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
30253	x = ( x | ( x << 2 ) ) & 0x33333333;
30254	x = ( x | ( x << 1 ) ) & 0x55555555;
30255
30256	y = ( y | ( y << 8 ) ) & 0x00FF00FF;
30257	y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
30258	y = ( y | ( y << 2 ) ) & 0x33333333;
30259	y = ( y | ( y << 1 ) ) & 0x55555555;
30260
30261	return x | ( y << 1 );
30262
30263}
30264
30265// find the leftmost node of a polygon ring
30266function getLeftmost( start ) {
30267
30268	var p = start,
30269		leftmost = start;
30270	do {
30271
30272		if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
30273		p = p.next;
30274
30275	} while ( p !== start );
30276
30277	return leftmost;
30278
30279}
30280
30281// check if a point lies within a convex triangle
30282function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
30283
30284	return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&
30285			( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&
30286			( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;
30287
30288}
30289
30290// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
30291function isValidDiagonal( a, b ) {
30292
30293	return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges
30294		( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
30295		( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
30296		equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
30297
30298}
30299
30300// signed area of a triangle
30301function area( p, q, r ) {
30302
30303	return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
30304
30305}
30306
30307// check if two points are equal
30308function equals( p1, p2 ) {
30309
30310	return p1.x === p2.x && p1.y === p2.y;
30311
30312}
30313
30314// check if two segments intersect
30315function intersects( p1, q1, p2, q2 ) {
30316
30317	var o1 = sign( area( p1, q1, p2 ) );
30318	var o2 = sign( area( p1, q1, q2 ) );
30319	var o3 = sign( area( p2, q2, p1 ) );
30320	var o4 = sign( area( p2, q2, q1 ) );
30321
30322	if ( o1 !== o2 && o3 !== o4 ) return true; // general case
30323
30324	if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
30325	if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
30326	if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
30327	if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
30328
30329	return false;
30330
30331}
30332
30333// for collinear points p, q, r, check if point q lies on segment pr
30334function onSegment( p, q, r ) {
30335
30336	return q.x <= Math.max( p.x, r.x ) && q.x >= Math.min( p.x, r.x ) && q.y <= Math.max( p.y, r.y ) && q.y >= Math.min( p.y, r.y );
30337
30338}
30339
30340function sign( num ) {
30341
30342	return num > 0 ? 1 : num < 0 ? - 1 : 0;
30343
30344}
30345
30346// check if a polygon diagonal intersects any polygon segments
30347function intersectsPolygon( a, b ) {
30348
30349	var p = a;
30350	do {
30351
30352		if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
30353				intersects( p, p.next, a, b ) ) return true;
30354		p = p.next;
30355
30356	} while ( p !== a );
30357
30358	return false;
30359
30360}
30361
30362// check if a polygon diagonal is locally inside the polygon
30363function locallyInside( a, b ) {
30364
30365	return area( a.prev, a, a.next ) < 0 ?
30366		area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
30367		area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
30368
30369}
30370
30371// check if the middle point of a polygon diagonal is inside the polygon
30372function middleInside( a, b ) {
30373
30374	var p = a,
30375		inside = false,
30376		px = ( a.x + b.x ) / 2,
30377		py = ( a.y + b.y ) / 2;
30378	do {
30379
30380		if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
30381				( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
30382			inside = ! inside;
30383		p = p.next;
30384
30385	} while ( p !== a );
30386
30387	return inside;
30388
30389}
30390
30391// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
30392// if one belongs to the outer ring and another to a hole, it merges it into a single ring
30393function splitPolygon( a, b ) {
30394
30395	var a2 = new Node( a.i, a.x, a.y ),
30396		b2 = new Node( b.i, b.x, b.y ),
30397		an = a.next,
30398		bp = b.prev;
30399
30400	a.next = b;
30401	b.prev = a;
30402
30403	a2.next = an;
30404	an.prev = a2;
30405
30406	b2.next = a2;
30407	a2.prev = b2;
30408
30409	bp.next = b2;
30410	b2.prev = bp;
30411
30412	return b2;
30413
30414}
30415
30416// create a node and optionally link it with previous one (in a circular doubly linked list)
30417function insertNode( i, x, y, last ) {
30418
30419	var p = new Node( i, x, y );
30420
30421	if ( ! last ) {
30422
30423		p.prev = p;
30424		p.next = p;
30425
30426	} else {
30427
30428		p.next = last.next;
30429		p.prev = last;
30430		last.next.prev = p;
30431		last.next = p;
30432
30433	}
30434
30435	return p;
30436
30437}
30438
30439function removeNode( p ) {
30440
30441	p.next.prev = p.prev;
30442	p.prev.next = p.next;
30443
30444	if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
30445	if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
30446
30447}
30448
30449function Node( i, x, y ) {
30450
30451	// vertex index in coordinates array
30452	this.i = i;
30453
30454	// vertex coordinates
30455	this.x = x;
30456	this.y = y;
30457
30458	// previous and next vertex nodes in a polygon ring
30459	this.prev = null;
30460	this.next = null;
30461
30462	// z-order curve value
30463	this.z = null;
30464
30465	// previous and next nodes in z-order
30466	this.prevZ = null;
30467	this.nextZ = null;
30468
30469	// indicates whether this is a steiner point
30470	this.steiner = false;
30471
30472}
30473
30474function signedArea( data, start, end, dim ) {
30475
30476	var sum = 0;
30477	for ( var i = start, j = end - dim; i < end; i += dim ) {
30478
30479		sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
30480		j = i;
30481
30482	}
30483
30484	return sum;
30485
30486}
30487
30488/**
30489 * @author zz85 / http://www.lab4games.net/zz85/blog
30490 */
30491
30492var ShapeUtils = {
30493
30494	// calculate area of the contour polygon
30495
30496	area: function ( contour ) {
30497
30498		var n = contour.length;
30499		var a = 0.0;
30500
30501		for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
30502
30503			a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
30504
30505		}
30506
30507		return a * 0.5;
30508
30509	},
30510
30511	isClockWise: function ( pts ) {
30512
30513		return ShapeUtils.area( pts ) < 0;
30514
30515	},
30516
30517	triangulateShape: function ( contour, holes ) {
30518
30519		var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
30520		var holeIndices = []; // array of hole indices
30521		var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
30522
30523		removeDupEndPts( contour );
30524		addContour( vertices, contour );
30525
30526		//
30527
30528		var holeIndex = contour.length;
30529
30530		holes.forEach( removeDupEndPts );
30531
30532		for ( var i = 0; i < holes.length; i ++ ) {
30533
30534			holeIndices.push( holeIndex );
30535			holeIndex += holes[ i ].length;
30536			addContour( vertices, holes[ i ] );
30537
30538		}
30539
30540		//
30541
30542		var triangles = Earcut.triangulate( vertices, holeIndices );
30543
30544		//
30545
30546		for ( var i = 0; i < triangles.length; i += 3 ) {
30547
30548			faces.push( triangles.slice( i, i + 3 ) );
30549
30550		}
30551
30552		return faces;
30553
30554	}
30555
30556};
30557
30558function removeDupEndPts( points ) {
30559
30560	var l = points.length;
30561
30562	if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
30563
30564		points.pop();
30565
30566	}
30567
30568}
30569
30570function addContour( vertices, contour ) {
30571
30572	for ( var i = 0; i < contour.length; i ++ ) {
30573
30574		vertices.push( contour[ i ].x );
30575		vertices.push( contour[ i ].y );
30576
30577	}
30578
30579}
30580
30581/**
30582 * @author zz85 / http://www.lab4games.net/zz85/blog
30583 *
30584 * Creates extruded geometry from a path shape.
30585 *
30586 * parameters = {
30587 *
30588 *  curveSegments: <int>, // number of points on the curves
30589 *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
30590 *  depth: <float>, // Depth to extrude the shape
30591 *
30592 *  bevelEnabled: <bool>, // turn on bevel
30593 *  bevelThickness: <float>, // how deep into the original shape bevel goes
30594 *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
30595 *  bevelOffset: <float>, // how far from shape outline does bevel start
30596 *  bevelSegments: <int>, // number of bevel layers
30597 *
30598 *  extrudePath: <THREE.Curve> // curve to extrude shape along
30599 *
30600 *  UVGenerator: <Object> // object that provides UV generator functions
30601 *
30602 * }
30603 */
30604
30605// ExtrudeGeometry
30606
30607function ExtrudeGeometry( shapes, options ) {
30608
30609	Geometry.call( this );
30610
30611	this.type = 'ExtrudeGeometry';
30612
30613	this.parameters = {
30614		shapes: shapes,
30615		options: options
30616	};
30617
30618	this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );
30619	this.mergeVertices();
30620
30621}
30622
30623ExtrudeGeometry.prototype = Object.create( Geometry.prototype );
30624ExtrudeGeometry.prototype.constructor = ExtrudeGeometry;
30625
30626ExtrudeGeometry.prototype.toJSON = function () {
30627
30628	var data = Geometry.prototype.toJSON.call( this );
30629
30630	var shapes = this.parameters.shapes;
30631	var options = this.parameters.options;
30632
30633	return toJSON( shapes, options, data );
30634
30635};
30636
30637// ExtrudeBufferGeometry
30638
30639function ExtrudeBufferGeometry( shapes, options ) {
30640
30641	BufferGeometry.call( this );
30642
30643	this.type = 'ExtrudeBufferGeometry';
30644
30645	this.parameters = {
30646		shapes: shapes,
30647		options: options
30648	};
30649
30650	shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
30651
30652	var scope = this;
30653
30654	var verticesArray = [];
30655	var uvArray = [];
30656
30657	for ( var i = 0, l = shapes.length; i < l; i ++ ) {
30658
30659		var shape = shapes[ i ];
30660		addShape( shape );
30661
30662	}
30663
30664	// build geometry
30665
30666	this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
30667	this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
30668
30669	this.computeVertexNormals();
30670
30671	// functions
30672
30673	function addShape( shape ) {
30674
30675		var placeholder = [];
30676
30677		// options
30678
30679		var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
30680		var steps = options.steps !== undefined ? options.steps : 1;
30681		var depth = options.depth !== undefined ? options.depth : 100;
30682
30683		var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
30684		var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
30685		var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
30686		var bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
30687		var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
30688
30689		var extrudePath = options.extrudePath;
30690
30691		var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
30692
30693		// deprecated options
30694
30695		if ( options.amount !== undefined ) {
30696
30697			console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );
30698			depth = options.amount;
30699
30700		}
30701
30702		//
30703
30704		var extrudePts, extrudeByPath = false;
30705		var splineTube, binormal, normal, position2;
30706
30707		if ( extrudePath ) {
30708
30709			extrudePts = extrudePath.getSpacedPoints( steps );
30710
30711			extrudeByPath = true;
30712			bevelEnabled = false; // bevels not supported for path extrusion
30713
30714			// SETUP TNB variables
30715
30716			// TODO1 - have a .isClosed in spline?
30717
30718			splineTube = extrudePath.computeFrenetFrames( steps, false );
30719
30720			// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
30721
30722			binormal = new Vector3();
30723			normal = new Vector3();
30724			position2 = new Vector3();
30725
30726		}
30727
30728		// Safeguards if bevels are not enabled
30729
30730		if ( ! bevelEnabled ) {
30731
30732			bevelSegments = 0;
30733			bevelThickness = 0;
30734			bevelSize = 0;
30735			bevelOffset = 0;
30736
30737		}
30738
30739		// Variables initialization
30740
30741		var ahole, h, hl; // looping of holes
30742
30743		var shapePoints = shape.extractPoints( curveSegments );
30744
30745		var vertices = shapePoints.shape;
30746		var holes = shapePoints.holes;
30747
30748		var reverse = ! ShapeUtils.isClockWise( vertices );
30749
30750		if ( reverse ) {
30751
30752			vertices = vertices.reverse();
30753
30754			// Maybe we should also check if holes are in the opposite direction, just to be safe ...
30755
30756			for ( h = 0, hl = holes.length; h < hl; h ++ ) {
30757
30758				ahole = holes[ h ];
30759
30760				if ( ShapeUtils.isClockWise( ahole ) ) {
30761
30762					holes[ h ] = ahole.reverse();
30763
30764				}
30765
30766			}
30767
30768		}
30769
30770
30771		var faces = ShapeUtils.triangulateShape( vertices, holes );
30772
30773		/* Vertices */
30774
30775		var contour = vertices; // vertices has all points but contour has only points of circumference
30776
30777		for ( h = 0, hl = holes.length; h < hl; h ++ ) {
30778
30779			ahole = holes[ h ];
30780
30781			vertices = vertices.concat( ahole );
30782
30783		}
30784
30785
30786		function scalePt2( pt, vec, size ) {
30787
30788			if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" );
30789
30790			return vec.clone().multiplyScalar( size ).add( pt );
30791
30792		}
30793
30794		var b, bs, t, z,
30795			vert, vlen = vertices.length,
30796			face, flen = faces.length;
30797
30798
30799		// Find directions for point movement
30800
30801
30802		function getBevelVec( inPt, inPrev, inNext ) {
30803
30804			// computes for inPt the corresponding point inPt' on a new contour
30805			//   shifted by 1 unit (length of normalized vector) to the left
30806			// if we walk along contour clockwise, this new contour is outside the old one
30807			//
30808			// inPt' is the intersection of the two lines parallel to the two
30809			//  adjacent edges of inPt at a distance of 1 unit on the left side.
30810
30811			var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
30812
30813			// good reading for geometry algorithms (here: line-line intersection)
30814			// http://geomalgorithms.com/a05-_intersect-1.html
30815
30816			var v_prev_x = inPt.x - inPrev.x,
30817				v_prev_y = inPt.y - inPrev.y;
30818			var v_next_x = inNext.x - inPt.x,
30819				v_next_y = inNext.y - inPt.y;
30820
30821			var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
30822
30823			// check for collinear edges
30824			var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
30825
30826			if ( Math.abs( collinear0 ) > Number.EPSILON ) {
30827
30828				// not collinear
30829
30830				// length of vectors for normalizing
30831
30832				var v_prev_len = Math.sqrt( v_prev_lensq );
30833				var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
30834
30835				// shift adjacent points by unit vectors to the left
30836
30837				var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
30838				var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
30839
30840				var ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
30841				var ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
30842
30843				// scaling factor for v_prev to intersection point
30844
30845				var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
30846						( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
30847					( v_prev_x * v_next_y - v_prev_y * v_next_x );
30848
30849				// vector from inPt to intersection point
30850
30851				v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
30852				v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
30853
30854				// Don't normalize!, otherwise sharp corners become ugly
30855				//  but prevent crazy spikes
30856				var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
30857				if ( v_trans_lensq <= 2 ) {
30858
30859					return new Vector2( v_trans_x, v_trans_y );
30860
30861				} else {
30862
30863					shrink_by = Math.sqrt( v_trans_lensq / 2 );
30864
30865				}
30866
30867			} else {
30868
30869				// handle special case of collinear edges
30870
30871				var direction_eq = false; // assumes: opposite
30872				if ( v_prev_x > Number.EPSILON ) {
30873
30874					if ( v_next_x > Number.EPSILON ) {
30875
30876						direction_eq = true;
30877
30878					}
30879
30880				} else {
30881
30882					if ( v_prev_x < - Number.EPSILON ) {
30883
30884						if ( v_next_x < - Number.EPSILON ) {
30885
30886							direction_eq = true;
30887
30888						}
30889
30890					} else {
30891
30892						if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
30893
30894							direction_eq = true;
30895
30896						}
30897
30898					}
30899
30900				}
30901
30902				if ( direction_eq ) {
30903
30904					// console.log("Warning: lines are a straight sequence");
30905					v_trans_x = - v_prev_y;
30906					v_trans_y = v_prev_x;
30907					shrink_by = Math.sqrt( v_prev_lensq );
30908
30909				} else {
30910
30911					// console.log("Warning: lines are a straight spike");
30912					v_trans_x = v_prev_x;
30913					v_trans_y = v_prev_y;
30914					shrink_by = Math.sqrt( v_prev_lensq / 2 );
30915
30916				}
30917
30918			}
30919
30920			return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
30921
30922		}
30923
30924
30925		var contourMovements = [];
30926
30927		for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
30928
30929			if ( j === il ) j = 0;
30930			if ( k === il ) k = 0;
30931
30932			//  (j)---(i)---(k)
30933			// console.log('i,j,k', i, j , k)
30934
30935			contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
30936
30937		}
30938
30939		var holesMovements = [],
30940			oneHoleMovements, verticesMovements = contourMovements.concat();
30941
30942		for ( h = 0, hl = holes.length; h < hl; h ++ ) {
30943
30944			ahole = holes[ h ];
30945
30946			oneHoleMovements = [];
30947
30948			for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
30949
30950				if ( j === il ) j = 0;
30951				if ( k === il ) k = 0;
30952
30953				//  (j)---(i)---(k)
30954				oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
30955
30956			}
30957
30958			holesMovements.push( oneHoleMovements );
30959			verticesMovements = verticesMovements.concat( oneHoleMovements );
30960
30961		}
30962
30963
30964		// Loop bevelSegments, 1 for the front, 1 for the back
30965
30966		for ( b = 0; b < bevelSegments; b ++ ) {
30967
30968			//for ( b = bevelSegments; b > 0; b -- ) {
30969
30970			t = b / bevelSegments;
30971			z = bevelThickness * Math.cos( t * Math.PI / 2 );
30972			bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
30973
30974			// contract shape
30975
30976			for ( i = 0, il = contour.length; i < il; i ++ ) {
30977
30978				vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
30979
30980				v( vert.x, vert.y, - z );
30981
30982			}
30983
30984			// expand holes
30985
30986			for ( h = 0, hl = holes.length; h < hl; h ++ ) {
30987
30988				ahole = holes[ h ];
30989				oneHoleMovements = holesMovements[ h ];
30990
30991				for ( i = 0, il = ahole.length; i < il; i ++ ) {
30992
30993					vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
30994
30995					v( vert.x, vert.y, - z );
30996
30997				}
30998
30999			}
31000
31001		}
31002
31003		bs = bevelSize + bevelOffset;
31004
31005		// Back facing vertices
31006
31007		for ( i = 0; i < vlen; i ++ ) {
31008
31009			vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
31010
31011			if ( ! extrudeByPath ) {
31012
31013				v( vert.x, vert.y, 0 );
31014
31015			} else {
31016
31017				// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
31018
31019				normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
31020				binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
31021
31022				position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
31023
31024				v( position2.x, position2.y, position2.z );
31025
31026			}
31027
31028		}
31029
31030		// Add stepped vertices...
31031		// Including front facing vertices
31032
31033		var s;
31034
31035		for ( s = 1; s <= steps; s ++ ) {
31036
31037			for ( i = 0; i < vlen; i ++ ) {
31038
31039				vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
31040
31041				if ( ! extrudeByPath ) {
31042
31043					v( vert.x, vert.y, depth / steps * s );
31044
31045				} else {
31046
31047					// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
31048
31049					normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
31050					binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
31051
31052					position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
31053
31054					v( position2.x, position2.y, position2.z );
31055
31056				}
31057
31058			}
31059
31060		}
31061
31062
31063		// Add bevel segments planes
31064
31065		//for ( b = 1; b <= bevelSegments; b ++ ) {
31066		for ( b = bevelSegments - 1; b >= 0; b -- ) {
31067
31068			t = b / bevelSegments;
31069			z = bevelThickness * Math.cos( t * Math.PI / 2 );
31070			bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
31071
31072			// contract shape
31073
31074			for ( i = 0, il = contour.length; i < il; i ++ ) {
31075
31076				vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
31077				v( vert.x, vert.y, depth + z );
31078
31079			}
31080
31081			// expand holes
31082
31083			for ( h = 0, hl = holes.length; h < hl; h ++ ) {
31084
31085				ahole = holes[ h ];
31086				oneHoleMovements = holesMovements[ h ];
31087
31088				for ( i = 0, il = ahole.length; i < il; i ++ ) {
31089
31090					vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
31091
31092					if ( ! extrudeByPath ) {
31093
31094						v( vert.x, vert.y, depth + z );
31095
31096					} else {
31097
31098						v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
31099
31100					}
31101
31102				}
31103
31104			}
31105
31106		}
31107
31108		/* Faces */
31109
31110		// Top and bottom faces
31111
31112		buildLidFaces();
31113
31114		// Sides faces
31115
31116		buildSideFaces();
31117
31118
31119		/////  Internal functions
31120
31121		function buildLidFaces() {
31122
31123			var start = verticesArray.length / 3;
31124
31125			if ( bevelEnabled ) {
31126
31127				var layer = 0; // steps + 1
31128				var offset = vlen * layer;
31129
31130				// Bottom faces
31131
31132				for ( i = 0; i < flen; i ++ ) {
31133
31134					face = faces[ i ];
31135					f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
31136
31137				}
31138
31139				layer = steps + bevelSegments * 2;
31140				offset = vlen * layer;
31141
31142				// Top faces
31143
31144				for ( i = 0; i < flen; i ++ ) {
31145
31146					face = faces[ i ];
31147					f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
31148
31149				}
31150
31151			} else {
31152
31153				// Bottom faces
31154
31155				for ( i = 0; i < flen; i ++ ) {
31156
31157					face = faces[ i ];
31158					f3( face[ 2 ], face[ 1 ], face[ 0 ] );
31159
31160				}
31161
31162				// Top faces
31163
31164				for ( i = 0; i < flen; i ++ ) {
31165
31166					face = faces[ i ];
31167					f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
31168
31169				}
31170
31171			}
31172
31173			scope.addGroup( start, verticesArray.length / 3 - start, 0 );
31174
31175		}
31176
31177		// Create faces for the z-sides of the shape
31178
31179		function buildSideFaces() {
31180
31181			var start = verticesArray.length / 3;
31182			var layeroffset = 0;
31183			sidewalls( contour, layeroffset );
31184			layeroffset += contour.length;
31185
31186			for ( h = 0, hl = holes.length; h < hl; h ++ ) {
31187
31188				ahole = holes[ h ];
31189				sidewalls( ahole, layeroffset );
31190
31191				//, true
31192				layeroffset += ahole.length;
31193
31194			}
31195
31196
31197			scope.addGroup( start, verticesArray.length / 3 - start, 1 );
31198
31199
31200		}
31201
31202		function sidewalls( contour, layeroffset ) {
31203
31204			var j, k;
31205			i = contour.length;
31206
31207			while ( -- i >= 0 ) {
31208
31209				j = i;
31210				k = i - 1;
31211				if ( k < 0 ) k = contour.length - 1;
31212
31213				//console.log('b', i,j, i-1, k,vertices.length);
31214
31215				var s = 0,
31216					sl = steps + bevelSegments * 2;
31217
31218				for ( s = 0; s < sl; s ++ ) {
31219
31220					var slen1 = vlen * s;
31221					var slen2 = vlen * ( s + 1 );
31222
31223					var a = layeroffset + j + slen1,
31224						b = layeroffset + k + slen1,
31225						c = layeroffset + k + slen2,
31226						d = layeroffset + j + slen2;
31227
31228					f4( a, b, c, d );
31229
31230				}
31231
31232			}
31233
31234		}
31235
31236		function v( x, y, z ) {
31237
31238			placeholder.push( x );
31239			placeholder.push( y );
31240			placeholder.push( z );
31241
31242		}
31243
31244
31245		function f3( a, b, c ) {
31246
31247			addVertex( a );
31248			addVertex( b );
31249			addVertex( c );
31250
31251			var nextIndex = verticesArray.length / 3;
31252			var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
31253
31254			addUV( uvs[ 0 ] );
31255			addUV( uvs[ 1 ] );
31256			addUV( uvs[ 2 ] );
31257
31258		}
31259
31260		function f4( a, b, c, d ) {
31261
31262			addVertex( a );
31263			addVertex( b );
31264			addVertex( d );
31265
31266			addVertex( b );
31267			addVertex( c );
31268			addVertex( d );
31269
31270
31271			var nextIndex = verticesArray.length / 3;
31272			var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
31273
31274			addUV( uvs[ 0 ] );
31275			addUV( uvs[ 1 ] );
31276			addUV( uvs[ 3 ] );
31277
31278			addUV( uvs[ 1 ] );
31279			addUV( uvs[ 2 ] );
31280			addUV( uvs[ 3 ] );
31281
31282		}
31283
31284		function addVertex( index ) {
31285
31286			verticesArray.push( placeholder[ index * 3 + 0 ] );
31287			verticesArray.push( placeholder[ index * 3 + 1 ] );
31288			verticesArray.push( placeholder[ index * 3 + 2 ] );
31289
31290		}
31291
31292
31293		function addUV( vector2 ) {
31294
31295			uvArray.push( vector2.x );
31296			uvArray.push( vector2.y );
31297
31298		}
31299
31300	}
31301
31302}
31303
31304ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
31305ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;
31306
31307ExtrudeBufferGeometry.prototype.toJSON = function () {
31308
31309	var data = BufferGeometry.prototype.toJSON.call( this );
31310
31311	var shapes = this.parameters.shapes;
31312	var options = this.parameters.options;
31313
31314	return toJSON( shapes, options, data );
31315
31316};
31317
31318//
31319
31320var WorldUVGenerator = {
31321
31322	generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
31323
31324		var a_x = vertices[ indexA * 3 ];
31325		var a_y = vertices[ indexA * 3 + 1 ];
31326		var b_x = vertices[ indexB * 3 ];
31327		var b_y = vertices[ indexB * 3 + 1 ];
31328		var c_x = vertices[ indexC * 3 ];
31329		var c_y = vertices[ indexC * 3 + 1 ];
31330
31331		return [
31332			new Vector2( a_x, a_y ),
31333			new Vector2( b_x, b_y ),
31334			new Vector2( c_x, c_y )
31335		];
31336
31337	},
31338
31339	generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
31340
31341		var a_x = vertices[ indexA * 3 ];
31342		var a_y = vertices[ indexA * 3 + 1 ];
31343		var a_z = vertices[ indexA * 3 + 2 ];
31344		var b_x = vertices[ indexB * 3 ];
31345		var b_y = vertices[ indexB * 3 + 1 ];
31346		var b_z = vertices[ indexB * 3 + 2 ];
31347		var c_x = vertices[ indexC * 3 ];
31348		var c_y = vertices[ indexC * 3 + 1 ];
31349		var c_z = vertices[ indexC * 3 + 2 ];
31350		var d_x = vertices[ indexD * 3 ];
31351		var d_y = vertices[ indexD * 3 + 1 ];
31352		var d_z = vertices[ indexD * 3 + 2 ];
31353
31354		if ( Math.abs( a_y - b_y ) < 0.01 ) {
31355
31356			return [
31357				new Vector2( a_x, 1 - a_z ),
31358				new Vector2( b_x, 1 - b_z ),
31359				new Vector2( c_x, 1 - c_z ),
31360				new Vector2( d_x, 1 - d_z )
31361			];
31362
31363		} else {
31364
31365			return [
31366				new Vector2( a_y, 1 - a_z ),
31367				new Vector2( b_y, 1 - b_z ),
31368				new Vector2( c_y, 1 - c_z ),
31369				new Vector2( d_y, 1 - d_z )
31370			];
31371
31372		}
31373
31374	}
31375};
31376
31377function toJSON( shapes, options, data ) {
31378
31379	//
31380
31381	data.shapes = [];
31382
31383	if ( Array.isArray( shapes ) ) {
31384
31385		for ( var i = 0, l = shapes.length; i < l; i ++ ) {
31386
31387			var shape = shapes[ i ];
31388
31389			data.shapes.push( shape.uuid );
31390
31391		}
31392
31393	} else {
31394
31395		data.shapes.push( shapes.uuid );
31396
31397	}
31398
31399	//
31400
31401	if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
31402
31403	return data;
31404
31405}
31406
31407/**
31408 * @author zz85 / http://www.lab4games.net/zz85/blog
31409 * @author alteredq / http://alteredqualia.com/
31410 *
31411 * Text = 3D Text
31412 *
31413 * parameters = {
31414 *  font: <THREE.Font>, // font
31415 *
31416 *  size: <float>, // size of the text
31417 *  height: <float>, // thickness to extrude text
31418 *  curveSegments: <int>, // number of points on the curves
31419 *
31420 *  bevelEnabled: <bool>, // turn on bevel
31421 *  bevelThickness: <float>, // how deep into text bevel goes
31422 *  bevelSize: <float>, // how far from text outline (including bevelOffset) is bevel
31423 *  bevelOffset: <float> // how far from text outline does bevel start
31424 * }
31425 */
31426
31427// TextGeometry
31428
31429function TextGeometry( text, parameters ) {
31430
31431	Geometry.call( this );
31432
31433	this.type = 'TextGeometry';
31434
31435	this.parameters = {
31436		text: text,
31437		parameters: parameters
31438	};
31439
31440	this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );
31441	this.mergeVertices();
31442
31443}
31444
31445TextGeometry.prototype = Object.create( Geometry.prototype );
31446TextGeometry.prototype.constructor = TextGeometry;
31447
31448// TextBufferGeometry
31449
31450function TextBufferGeometry( text, parameters ) {
31451
31452	parameters = parameters || {};
31453
31454	var font = parameters.font;
31455
31456	if ( ! ( font && font.isFont ) ) {
31457
31458		console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );
31459		return new Geometry();
31460
31461	}
31462
31463	var shapes = font.generateShapes( text, parameters.size );
31464
31465	// translate parameters to ExtrudeGeometry API
31466
31467	parameters.depth = parameters.height !== undefined ? parameters.height : 50;
31468
31469	// defaults
31470
31471	if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
31472	if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
31473	if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
31474
31475	ExtrudeBufferGeometry.call( this, shapes, parameters );
31476
31477	this.type = 'TextBufferGeometry';
31478
31479}
31480
31481TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );
31482TextBufferGeometry.prototype.constructor = TextBufferGeometry;
31483
31484/**
31485 * @author mrdoob / http://mrdoob.com/
31486 * @author benaadams / https://twitter.com/ben_a_adams
31487 * @author Mugen87 / https://github.com/Mugen87
31488 */
31489
31490// SphereGeometry
31491
31492function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
31493
31494	Geometry.call( this );
31495
31496	this.type = 'SphereGeometry';
31497
31498	this.parameters = {
31499		radius: radius,
31500		widthSegments: widthSegments,
31501		heightSegments: heightSegments,
31502		phiStart: phiStart,
31503		phiLength: phiLength,
31504		thetaStart: thetaStart,
31505		thetaLength: thetaLength
31506	};
31507
31508	this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );
31509	this.mergeVertices();
31510
31511}
31512
31513SphereGeometry.prototype = Object.create( Geometry.prototype );
31514SphereGeometry.prototype.constructor = SphereGeometry;
31515
31516// SphereBufferGeometry
31517
31518function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
31519
31520	BufferGeometry.call( this );
31521
31522	this.type = 'SphereBufferGeometry';
31523
31524	this.parameters = {
31525		radius: radius,
31526		widthSegments: widthSegments,
31527		heightSegments: heightSegments,
31528		phiStart: phiStart,
31529		phiLength: phiLength,
31530		thetaStart: thetaStart,
31531		thetaLength: thetaLength
31532	};
31533
31534	radius = radius || 1;
31535
31536	widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );
31537	heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );
31538
31539	phiStart = phiStart !== undefined ? phiStart : 0;
31540	phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
31541
31542	thetaStart = thetaStart !== undefined ? thetaStart : 0;
31543	thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
31544
31545	var thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
31546
31547	var ix, iy;
31548
31549	var index = 0;
31550	var grid = [];
31551
31552	var vertex = new Vector3();
31553	var normal = new Vector3();
31554
31555	// buffers
31556
31557	var indices = [];
31558	var vertices = [];
31559	var normals = [];
31560	var uvs = [];
31561
31562	// generate vertices, normals and uvs
31563
31564	for ( iy = 0; iy <= heightSegments; iy ++ ) {
31565
31566		var verticesRow = [];
31567
31568		var v = iy / heightSegments;
31569
31570		// special case for the poles
31571
31572		var uOffset = 0;
31573
31574		if ( iy == 0 && thetaStart == 0 ) {
31575
31576			uOffset = 0.5 / widthSegments;
31577
31578		} else if ( iy == heightSegments && thetaEnd == Math.PI ) {
31579
31580			uOffset = - 0.5 / widthSegments;
31581
31582		}
31583
31584		for ( ix = 0; ix <= widthSegments; ix ++ ) {
31585
31586			var u = ix / widthSegments;
31587
31588			// vertex
31589
31590			vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
31591			vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
31592			vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
31593
31594			vertices.push( vertex.x, vertex.y, vertex.z );
31595
31596			// normal
31597
31598			normal.copy( vertex ).normalize();
31599			normals.push( normal.x, normal.y, normal.z );
31600
31601			// uv
31602
31603			uvs.push( u + uOffset, 1 - v );
31604
31605			verticesRow.push( index ++ );
31606
31607		}
31608
31609		grid.push( verticesRow );
31610
31611	}
31612
31613	// indices
31614
31615	for ( iy = 0; iy < heightSegments; iy ++ ) {
31616
31617		for ( ix = 0; ix < widthSegments; ix ++ ) {
31618
31619			var a = grid[ iy ][ ix + 1 ];
31620			var b = grid[ iy ][ ix ];
31621			var c = grid[ iy + 1 ][ ix ];
31622			var d = grid[ iy + 1 ][ ix + 1 ];
31623
31624			if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
31625			if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
31626
31627		}
31628
31629	}
31630
31631	// build geometry
31632
31633	this.setIndex( indices );
31634	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31635	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
31636	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31637
31638}
31639
31640SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
31641SphereBufferGeometry.prototype.constructor = SphereBufferGeometry;
31642
31643/**
31644 * @author Kaleb Murphy
31645 * @author Mugen87 / https://github.com/Mugen87
31646 */
31647
31648// RingGeometry
31649
31650function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
31651
31652	Geometry.call( this );
31653
31654	this.type = 'RingGeometry';
31655
31656	this.parameters = {
31657		innerRadius: innerRadius,
31658		outerRadius: outerRadius,
31659		thetaSegments: thetaSegments,
31660		phiSegments: phiSegments,
31661		thetaStart: thetaStart,
31662		thetaLength: thetaLength
31663	};
31664
31665	this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );
31666	this.mergeVertices();
31667
31668}
31669
31670RingGeometry.prototype = Object.create( Geometry.prototype );
31671RingGeometry.prototype.constructor = RingGeometry;
31672
31673// RingBufferGeometry
31674
31675function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
31676
31677	BufferGeometry.call( this );
31678
31679	this.type = 'RingBufferGeometry';
31680
31681	this.parameters = {
31682		innerRadius: innerRadius,
31683		outerRadius: outerRadius,
31684		thetaSegments: thetaSegments,
31685		phiSegments: phiSegments,
31686		thetaStart: thetaStart,
31687		thetaLength: thetaLength
31688	};
31689
31690	innerRadius = innerRadius || 0.5;
31691	outerRadius = outerRadius || 1;
31692
31693	thetaStart = thetaStart !== undefined ? thetaStart : 0;
31694	thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
31695
31696	thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;
31697	phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;
31698
31699	// buffers
31700
31701	var indices = [];
31702	var vertices = [];
31703	var normals = [];
31704	var uvs = [];
31705
31706	// some helper variables
31707
31708	var segment;
31709	var radius = innerRadius;
31710	var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
31711	var vertex = new Vector3();
31712	var uv = new Vector2();
31713	var j, i;
31714
31715	// generate vertices, normals and uvs
31716
31717	for ( j = 0; j <= phiSegments; j ++ ) {
31718
31719		for ( i = 0; i <= thetaSegments; i ++ ) {
31720
31721			// values are generate from the inside of the ring to the outside
31722
31723			segment = thetaStart + i / thetaSegments * thetaLength;
31724
31725			// vertex
31726
31727			vertex.x = radius * Math.cos( segment );
31728			vertex.y = radius * Math.sin( segment );
31729
31730			vertices.push( vertex.x, vertex.y, vertex.z );
31731
31732			// normal
31733
31734			normals.push( 0, 0, 1 );
31735
31736			// uv
31737
31738			uv.x = ( vertex.x / outerRadius + 1 ) / 2;
31739			uv.y = ( vertex.y / outerRadius + 1 ) / 2;
31740
31741			uvs.push( uv.x, uv.y );
31742
31743		}
31744
31745		// increase the radius for next row of vertices
31746
31747		radius += radiusStep;
31748
31749	}
31750
31751	// indices
31752
31753	for ( j = 0; j < phiSegments; j ++ ) {
31754
31755		var thetaSegmentLevel = j * ( thetaSegments + 1 );
31756
31757		for ( i = 0; i < thetaSegments; i ++ ) {
31758
31759			segment = i + thetaSegmentLevel;
31760
31761			var a = segment;
31762			var b = segment + thetaSegments + 1;
31763			var c = segment + thetaSegments + 2;
31764			var d = segment + 1;
31765
31766			// faces
31767
31768			indices.push( a, b, d );
31769			indices.push( b, c, d );
31770
31771		}
31772
31773	}
31774
31775	// build geometry
31776
31777	this.setIndex( indices );
31778	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31779	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
31780	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31781
31782}
31783
31784RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
31785RingBufferGeometry.prototype.constructor = RingBufferGeometry;
31786
31787/**
31788 * @author zz85 / https://github.com/zz85
31789 * @author bhouston / http://clara.io
31790 * @author Mugen87 / https://github.com/Mugen87
31791 */
31792
31793// LatheGeometry
31794
31795function LatheGeometry( points, segments, phiStart, phiLength ) {
31796
31797	Geometry.call( this );
31798
31799	this.type = 'LatheGeometry';
31800
31801	this.parameters = {
31802		points: points,
31803		segments: segments,
31804		phiStart: phiStart,
31805		phiLength: phiLength
31806	};
31807
31808	this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
31809	this.mergeVertices();
31810
31811}
31812
31813LatheGeometry.prototype = Object.create( Geometry.prototype );
31814LatheGeometry.prototype.constructor = LatheGeometry;
31815
31816// LatheBufferGeometry
31817
31818function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
31819
31820	BufferGeometry.call( this );
31821
31822	this.type = 'LatheBufferGeometry';
31823
31824	this.parameters = {
31825		points: points,
31826		segments: segments,
31827		phiStart: phiStart,
31828		phiLength: phiLength
31829	};
31830
31831	segments = Math.floor( segments ) || 12;
31832	phiStart = phiStart || 0;
31833	phiLength = phiLength || Math.PI * 2;
31834
31835	// clamp phiLength so it's in range of [ 0, 2PI ]
31836
31837	phiLength = MathUtils.clamp( phiLength, 0, Math.PI * 2 );
31838
31839
31840	// buffers
31841
31842	var indices = [];
31843	var vertices = [];
31844	var uvs = [];
31845
31846	// helper variables
31847
31848	var base;
31849	var inverseSegments = 1.0 / segments;
31850	var vertex = new Vector3();
31851	var uv = new Vector2();
31852	var i, j;
31853
31854	// generate vertices and uvs
31855
31856	for ( i = 0; i <= segments; i ++ ) {
31857
31858		var phi = phiStart + i * inverseSegments * phiLength;
31859
31860		var sin = Math.sin( phi );
31861		var cos = Math.cos( phi );
31862
31863		for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
31864
31865			// vertex
31866
31867			vertex.x = points[ j ].x * sin;
31868			vertex.y = points[ j ].y;
31869			vertex.z = points[ j ].x * cos;
31870
31871			vertices.push( vertex.x, vertex.y, vertex.z );
31872
31873			// uv
31874
31875			uv.x = i / segments;
31876			uv.y = j / ( points.length - 1 );
31877
31878			uvs.push( uv.x, uv.y );
31879
31880
31881		}
31882
31883	}
31884
31885	// indices
31886
31887	for ( i = 0; i < segments; i ++ ) {
31888
31889		for ( j = 0; j < ( points.length - 1 ); j ++ ) {
31890
31891			base = j + i * points.length;
31892
31893			var a = base;
31894			var b = base + points.length;
31895			var c = base + points.length + 1;
31896			var d = base + 1;
31897
31898			// faces
31899
31900			indices.push( a, b, d );
31901			indices.push( b, c, d );
31902
31903		}
31904
31905	}
31906
31907	// build geometry
31908
31909	this.setIndex( indices );
31910	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31911	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
31912
31913	// generate normals
31914
31915	this.computeVertexNormals();
31916
31917	// if the geometry is closed, we need to average the normals along the seam.
31918	// because the corresponding vertices are identical (but still have different UVs).
31919
31920	if ( phiLength === Math.PI * 2 ) {
31921
31922		var normals = this.attributes.normal.array;
31923		var n1 = new Vector3();
31924		var n2 = new Vector3();
31925		var n = new Vector3();
31926
31927		// this is the buffer offset for the last line of vertices
31928
31929		base = segments * points.length * 3;
31930
31931		for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
31932
31933			// select the normal of the vertex in the first line
31934
31935			n1.x = normals[ j + 0 ];
31936			n1.y = normals[ j + 1 ];
31937			n1.z = normals[ j + 2 ];
31938
31939			// select the normal of the vertex in the last line
31940
31941			n2.x = normals[ base + j + 0 ];
31942			n2.y = normals[ base + j + 1 ];
31943			n2.z = normals[ base + j + 2 ];
31944
31945			// average normals
31946
31947			n.addVectors( n1, n2 ).normalize();
31948
31949			// assign the new values to both normals
31950
31951			normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
31952			normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
31953			normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
31954
31955		}
31956
31957	}
31958
31959}
31960
31961LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
31962LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
31963
31964/**
31965 * @author jonobr1 / http://jonobr1.com
31966 * @author Mugen87 / https://github.com/Mugen87
31967 */
31968
31969// ShapeGeometry
31970
31971function ShapeGeometry( shapes, curveSegments ) {
31972
31973	Geometry.call( this );
31974
31975	this.type = 'ShapeGeometry';
31976
31977	if ( typeof curveSegments === 'object' ) {
31978
31979		console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );
31980
31981		curveSegments = curveSegments.curveSegments;
31982
31983	}
31984
31985	this.parameters = {
31986		shapes: shapes,
31987		curveSegments: curveSegments
31988	};
31989
31990	this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );
31991	this.mergeVertices();
31992
31993}
31994
31995ShapeGeometry.prototype = Object.create( Geometry.prototype );
31996ShapeGeometry.prototype.constructor = ShapeGeometry;
31997
31998ShapeGeometry.prototype.toJSON = function () {
31999
32000	var data = Geometry.prototype.toJSON.call( this );
32001
32002	var shapes = this.parameters.shapes;
32003
32004	return toJSON$1( shapes, data );
32005
32006};
32007
32008// ShapeBufferGeometry
32009
32010function ShapeBufferGeometry( shapes, curveSegments ) {
32011
32012	BufferGeometry.call( this );
32013
32014	this.type = 'ShapeBufferGeometry';
32015
32016	this.parameters = {
32017		shapes: shapes,
32018		curveSegments: curveSegments
32019	};
32020
32021	curveSegments = curveSegments || 12;
32022
32023	// buffers
32024
32025	var indices = [];
32026	var vertices = [];
32027	var normals = [];
32028	var uvs = [];
32029
32030	// helper variables
32031
32032	var groupStart = 0;
32033	var groupCount = 0;
32034
32035	// allow single and array values for "shapes" parameter
32036
32037	if ( Array.isArray( shapes ) === false ) {
32038
32039		addShape( shapes );
32040
32041	} else {
32042
32043		for ( var i = 0; i < shapes.length; i ++ ) {
32044
32045			addShape( shapes[ i ] );
32046
32047			this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
32048
32049			groupStart += groupCount;
32050			groupCount = 0;
32051
32052		}
32053
32054	}
32055
32056	// build geometry
32057
32058	this.setIndex( indices );
32059	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32060	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32061	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32062
32063
32064	// helper functions
32065
32066	function addShape( shape ) {
32067
32068		var i, l, shapeHole;
32069
32070		var indexOffset = vertices.length / 3;
32071		var points = shape.extractPoints( curveSegments );
32072
32073		var shapeVertices = points.shape;
32074		var shapeHoles = points.holes;
32075
32076		// check direction of vertices
32077
32078		if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
32079
32080			shapeVertices = shapeVertices.reverse();
32081
32082		}
32083
32084		for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
32085
32086			shapeHole = shapeHoles[ i ];
32087
32088			if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
32089
32090				shapeHoles[ i ] = shapeHole.reverse();
32091
32092			}
32093
32094		}
32095
32096		var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
32097
32098		// join vertices of inner and outer paths to a single array
32099
32100		for ( i = 0, l = shapeHoles.length; i < l; i ++ ) {
32101
32102			shapeHole = shapeHoles[ i ];
32103			shapeVertices = shapeVertices.concat( shapeHole );
32104
32105		}
32106
32107		// vertices, normals, uvs
32108
32109		for ( i = 0, l = shapeVertices.length; i < l; i ++ ) {
32110
32111			var vertex = shapeVertices[ i ];
32112
32113			vertices.push( vertex.x, vertex.y, 0 );
32114			normals.push( 0, 0, 1 );
32115			uvs.push( vertex.x, vertex.y ); // world uvs
32116
32117		}
32118
32119		// incides
32120
32121		for ( i = 0, l = faces.length; i < l; i ++ ) {
32122
32123			var face = faces[ i ];
32124
32125			var a = face[ 0 ] + indexOffset;
32126			var b = face[ 1 ] + indexOffset;
32127			var c = face[ 2 ] + indexOffset;
32128
32129			indices.push( a, b, c );
32130			groupCount += 3;
32131
32132		}
32133
32134	}
32135
32136}
32137
32138ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
32139ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;
32140
32141ShapeBufferGeometry.prototype.toJSON = function () {
32142
32143	var data = BufferGeometry.prototype.toJSON.call( this );
32144
32145	var shapes = this.parameters.shapes;
32146
32147	return toJSON$1( shapes, data );
32148
32149};
32150
32151//
32152
32153function toJSON$1( shapes, data ) {
32154
32155	data.shapes = [];
32156
32157	if ( Array.isArray( shapes ) ) {
32158
32159		for ( var i = 0, l = shapes.length; i < l; i ++ ) {
32160
32161			var shape = shapes[ i ];
32162
32163			data.shapes.push( shape.uuid );
32164
32165		}
32166
32167	} else {
32168
32169		data.shapes.push( shapes.uuid );
32170
32171	}
32172
32173	return data;
32174
32175}
32176
32177/**
32178 * @author WestLangley / http://github.com/WestLangley
32179 * @author Mugen87 / https://github.com/Mugen87
32180 */
32181
32182function EdgesGeometry( geometry, thresholdAngle ) {
32183
32184	BufferGeometry.call( this );
32185
32186	this.type = 'EdgesGeometry';
32187
32188	this.parameters = {
32189		thresholdAngle: thresholdAngle
32190	};
32191
32192	thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
32193
32194	// buffer
32195
32196	var vertices = [];
32197
32198	// helper variables
32199
32200	var thresholdDot = Math.cos( MathUtils.DEG2RAD * thresholdAngle );
32201	var edge = [ 0, 0 ], edges = {}, edge1, edge2;
32202	var key, keys = [ 'a', 'b', 'c' ];
32203
32204	// prepare source geometry
32205
32206	var geometry2;
32207
32208	if ( geometry.isBufferGeometry ) {
32209
32210		geometry2 = new Geometry();
32211		geometry2.fromBufferGeometry( geometry );
32212
32213	} else {
32214
32215		geometry2 = geometry.clone();
32216
32217	}
32218
32219	geometry2.mergeVertices();
32220	geometry2.computeFaceNormals();
32221
32222	var sourceVertices = geometry2.vertices;
32223	var faces = geometry2.faces;
32224
32225	// now create a data structure where each entry represents an edge with its adjoining faces
32226
32227	for ( var i = 0, l = faces.length; i < l; i ++ ) {
32228
32229		var face = faces[ i ];
32230
32231		for ( var j = 0; j < 3; j ++ ) {
32232
32233			edge1 = face[ keys[ j ] ];
32234			edge2 = face[ keys[ ( j + 1 ) % 3 ] ];
32235			edge[ 0 ] = Math.min( edge1, edge2 );
32236			edge[ 1 ] = Math.max( edge1, edge2 );
32237
32238			key = edge[ 0 ] + ',' + edge[ 1 ];
32239
32240			if ( edges[ key ] === undefined ) {
32241
32242				edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };
32243
32244			} else {
32245
32246				edges[ key ].face2 = i;
32247
32248			}
32249
32250		}
32251
32252	}
32253
32254	// generate vertices
32255
32256	for ( key in edges ) {
32257
32258		var e = edges[ key ];
32259
32260		// an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.
32261
32262		if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {
32263
32264			var vertex = sourceVertices[ e.index1 ];
32265			vertices.push( vertex.x, vertex.y, vertex.z );
32266
32267			vertex = sourceVertices[ e.index2 ];
32268			vertices.push( vertex.x, vertex.y, vertex.z );
32269
32270		}
32271
32272	}
32273
32274	// build geometry
32275
32276	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32277
32278}
32279
32280EdgesGeometry.prototype = Object.create( BufferGeometry.prototype );
32281EdgesGeometry.prototype.constructor = EdgesGeometry;
32282
32283/**
32284 * @author mrdoob / http://mrdoob.com/
32285 * @author Mugen87 / https://github.com/Mugen87
32286 */
32287
32288// CylinderGeometry
32289
32290function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
32291
32292	Geometry.call( this );
32293
32294	this.type = 'CylinderGeometry';
32295
32296	this.parameters = {
32297		radiusTop: radiusTop,
32298		radiusBottom: radiusBottom,
32299		height: height,
32300		radialSegments: radialSegments,
32301		heightSegments: heightSegments,
32302		openEnded: openEnded,
32303		thetaStart: thetaStart,
32304		thetaLength: thetaLength
32305	};
32306
32307	this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );
32308	this.mergeVertices();
32309
32310}
32311
32312CylinderGeometry.prototype = Object.create( Geometry.prototype );
32313CylinderGeometry.prototype.constructor = CylinderGeometry;
32314
32315// CylinderBufferGeometry
32316
32317function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
32318
32319	BufferGeometry.call( this );
32320
32321	this.type = 'CylinderBufferGeometry';
32322
32323	this.parameters = {
32324		radiusTop: radiusTop,
32325		radiusBottom: radiusBottom,
32326		height: height,
32327		radialSegments: radialSegments,
32328		heightSegments: heightSegments,
32329		openEnded: openEnded,
32330		thetaStart: thetaStart,
32331		thetaLength: thetaLength
32332	};
32333
32334	var scope = this;
32335
32336	radiusTop = radiusTop !== undefined ? radiusTop : 1;
32337	radiusBottom = radiusBottom !== undefined ? radiusBottom : 1;
32338	height = height || 1;
32339
32340	radialSegments = Math.floor( radialSegments ) || 8;
32341	heightSegments = Math.floor( heightSegments ) || 1;
32342
32343	openEnded = openEnded !== undefined ? openEnded : false;
32344	thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
32345	thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
32346
32347	// buffers
32348
32349	var indices = [];
32350	var vertices = [];
32351	var normals = [];
32352	var uvs = [];
32353
32354	// helper variables
32355
32356	var index = 0;
32357	var indexArray = [];
32358	var halfHeight = height / 2;
32359	var groupStart = 0;
32360
32361	// generate geometry
32362
32363	generateTorso();
32364
32365	if ( openEnded === false ) {
32366
32367		if ( radiusTop > 0 ) generateCap( true );
32368		if ( radiusBottom > 0 ) generateCap( false );
32369
32370	}
32371
32372	// build geometry
32373
32374	this.setIndex( indices );
32375	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32376	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32377	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32378
32379	function generateTorso() {
32380
32381		var x, y;
32382		var normal = new Vector3();
32383		var vertex = new Vector3();
32384
32385		var groupCount = 0;
32386
32387		// this will be used to calculate the normal
32388		var slope = ( radiusBottom - radiusTop ) / height;
32389
32390		// generate vertices, normals and uvs
32391
32392		for ( y = 0; y <= heightSegments; y ++ ) {
32393
32394			var indexRow = [];
32395
32396			var v = y / heightSegments;
32397
32398			// calculate the radius of the current row
32399
32400			var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
32401
32402			for ( x = 0; x <= radialSegments; x ++ ) {
32403
32404				var u = x / radialSegments;
32405
32406				var theta = u * thetaLength + thetaStart;
32407
32408				var sinTheta = Math.sin( theta );
32409				var cosTheta = Math.cos( theta );
32410
32411				// vertex
32412
32413				vertex.x = radius * sinTheta;
32414				vertex.y = - v * height + halfHeight;
32415				vertex.z = radius * cosTheta;
32416				vertices.push( vertex.x, vertex.y, vertex.z );
32417
32418				// normal
32419
32420				normal.set( sinTheta, slope, cosTheta ).normalize();
32421				normals.push( normal.x, normal.y, normal.z );
32422
32423				// uv
32424
32425				uvs.push( u, 1 - v );
32426
32427				// save index of vertex in respective row
32428
32429				indexRow.push( index ++ );
32430
32431			}
32432
32433			// now save vertices of the row in our index array
32434
32435			indexArray.push( indexRow );
32436
32437		}
32438
32439		// generate indices
32440
32441		for ( x = 0; x < radialSegments; x ++ ) {
32442
32443			for ( y = 0; y < heightSegments; y ++ ) {
32444
32445				// we use the index array to access the correct indices
32446
32447				var a = indexArray[ y ][ x ];
32448				var b = indexArray[ y + 1 ][ x ];
32449				var c = indexArray[ y + 1 ][ x + 1 ];
32450				var d = indexArray[ y ][ x + 1 ];
32451
32452				// faces
32453
32454				indices.push( a, b, d );
32455				indices.push( b, c, d );
32456
32457				// update group counter
32458
32459				groupCount += 6;
32460
32461			}
32462
32463		}
32464
32465		// add a group to the geometry. this will ensure multi material support
32466
32467		scope.addGroup( groupStart, groupCount, 0 );
32468
32469		// calculate new start value for groups
32470
32471		groupStart += groupCount;
32472
32473	}
32474
32475	function generateCap( top ) {
32476
32477		var x, centerIndexStart, centerIndexEnd;
32478
32479		var uv = new Vector2();
32480		var vertex = new Vector3();
32481
32482		var groupCount = 0;
32483
32484		var radius = ( top === true ) ? radiusTop : radiusBottom;
32485		var sign = ( top === true ) ? 1 : - 1;
32486
32487		// save the index of the first center vertex
32488		centerIndexStart = index;
32489
32490		// first we generate the center vertex data of the cap.
32491		// because the geometry needs one set of uvs per face,
32492		// we must generate a center vertex per face/segment
32493
32494		for ( x = 1; x <= radialSegments; x ++ ) {
32495
32496			// vertex
32497
32498			vertices.push( 0, halfHeight * sign, 0 );
32499
32500			// normal
32501
32502			normals.push( 0, sign, 0 );
32503
32504			// uv
32505
32506			uvs.push( 0.5, 0.5 );
32507
32508			// increase index
32509
32510			index ++;
32511
32512		}
32513
32514		// save the index of the last center vertex
32515
32516		centerIndexEnd = index;
32517
32518		// now we generate the surrounding vertices, normals and uvs
32519
32520		for ( x = 0; x <= radialSegments; x ++ ) {
32521
32522			var u = x / radialSegments;
32523			var theta = u * thetaLength + thetaStart;
32524
32525			var cosTheta = Math.cos( theta );
32526			var sinTheta = Math.sin( theta );
32527
32528			// vertex
32529
32530			vertex.x = radius * sinTheta;
32531			vertex.y = halfHeight * sign;
32532			vertex.z = radius * cosTheta;
32533			vertices.push( vertex.x, vertex.y, vertex.z );
32534
32535			// normal
32536
32537			normals.push( 0, sign, 0 );
32538
32539			// uv
32540
32541			uv.x = ( cosTheta * 0.5 ) + 0.5;
32542			uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
32543			uvs.push( uv.x, uv.y );
32544
32545			// increase index
32546
32547			index ++;
32548
32549		}
32550
32551		// generate indices
32552
32553		for ( x = 0; x < radialSegments; x ++ ) {
32554
32555			var c = centerIndexStart + x;
32556			var i = centerIndexEnd + x;
32557
32558			if ( top === true ) {
32559
32560				// face top
32561
32562				indices.push( i, i + 1, c );
32563
32564			} else {
32565
32566				// face bottom
32567
32568				indices.push( i + 1, i, c );
32569
32570			}
32571
32572			groupCount += 3;
32573
32574		}
32575
32576		// add a group to the geometry. this will ensure multi material support
32577
32578		scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
32579
32580		// calculate new start value for groups
32581
32582		groupStart += groupCount;
32583
32584	}
32585
32586}
32587
32588CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
32589CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;
32590
32591/**
32592 * @author abelnation / http://github.com/abelnation
32593 */
32594
32595// ConeGeometry
32596
32597function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
32598
32599	CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
32600
32601	this.type = 'ConeGeometry';
32602
32603	this.parameters = {
32604		radius: radius,
32605		height: height,
32606		radialSegments: radialSegments,
32607		heightSegments: heightSegments,
32608		openEnded: openEnded,
32609		thetaStart: thetaStart,
32610		thetaLength: thetaLength
32611	};
32612
32613}
32614
32615ConeGeometry.prototype = Object.create( CylinderGeometry.prototype );
32616ConeGeometry.prototype.constructor = ConeGeometry;
32617
32618// ConeBufferGeometry
32619
32620function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
32621
32622	CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
32623
32624	this.type = 'ConeBufferGeometry';
32625
32626	this.parameters = {
32627		radius: radius,
32628		height: height,
32629		radialSegments: radialSegments,
32630		heightSegments: heightSegments,
32631		openEnded: openEnded,
32632		thetaStart: thetaStart,
32633		thetaLength: thetaLength
32634	};
32635
32636}
32637
32638ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );
32639ConeBufferGeometry.prototype.constructor = ConeBufferGeometry;
32640
32641/**
32642 * @author benaadams / https://twitter.com/ben_a_adams
32643 * @author Mugen87 / https://github.com/Mugen87
32644 * @author hughes
32645 */
32646
32647// CircleGeometry
32648
32649function CircleGeometry( radius, segments, thetaStart, thetaLength ) {
32650
32651	Geometry.call( this );
32652
32653	this.type = 'CircleGeometry';
32654
32655	this.parameters = {
32656		radius: radius,
32657		segments: segments,
32658		thetaStart: thetaStart,
32659		thetaLength: thetaLength
32660	};
32661
32662	this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );
32663	this.mergeVertices();
32664
32665}
32666
32667CircleGeometry.prototype = Object.create( Geometry.prototype );
32668CircleGeometry.prototype.constructor = CircleGeometry;
32669
32670// CircleBufferGeometry
32671
32672function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {
32673
32674	BufferGeometry.call( this );
32675
32676	this.type = 'CircleBufferGeometry';
32677
32678	this.parameters = {
32679		radius: radius,
32680		segments: segments,
32681		thetaStart: thetaStart,
32682		thetaLength: thetaLength
32683	};
32684
32685	radius = radius || 1;
32686	segments = segments !== undefined ? Math.max( 3, segments ) : 8;
32687
32688	thetaStart = thetaStart !== undefined ? thetaStart : 0;
32689	thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
32690
32691	// buffers
32692
32693	var indices = [];
32694	var vertices = [];
32695	var normals = [];
32696	var uvs = [];
32697
32698	// helper variables
32699
32700	var i, s;
32701	var vertex = new Vector3();
32702	var uv = new Vector2();
32703
32704	// center point
32705
32706	vertices.push( 0, 0, 0 );
32707	normals.push( 0, 0, 1 );
32708	uvs.push( 0.5, 0.5 );
32709
32710	for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {
32711
32712		var segment = thetaStart + s / segments * thetaLength;
32713
32714		// vertex
32715
32716		vertex.x = radius * Math.cos( segment );
32717		vertex.y = radius * Math.sin( segment );
32718
32719		vertices.push( vertex.x, vertex.y, vertex.z );
32720
32721		// normal
32722
32723		normals.push( 0, 0, 1 );
32724
32725		// uvs
32726
32727		uv.x = ( vertices[ i ] / radius + 1 ) / 2;
32728		uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
32729
32730		uvs.push( uv.x, uv.y );
32731
32732	}
32733
32734	// indices
32735
32736	for ( i = 1; i <= segments; i ++ ) {
32737
32738		indices.push( i, i + 1, 0 );
32739
32740	}
32741
32742	// build geometry
32743
32744	this.setIndex( indices );
32745	this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
32746	this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
32747	this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
32748
32749}
32750
32751CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
32752CircleBufferGeometry.prototype.constructor = CircleBufferGeometry;
32753
32754var Geometries = /*#__PURE__*/Object.freeze({
32755	__proto__: null,
32756	WireframeGeometry: WireframeGeometry,
32757	ParametricGeometry: ParametricGeometry,
32758	ParametricBufferGeometry: ParametricBufferGeometry,
32759	TetrahedronGeometry: TetrahedronGeometry,
32760	TetrahedronBufferGeometry: TetrahedronBufferGeometry,
32761	OctahedronGeometry: OctahedronGeometry,
32762	OctahedronBufferGeometry: OctahedronBufferGeometry,
32763	IcosahedronGeometry: IcosahedronGeometry,
32764	IcosahedronBufferGeometry: IcosahedronBufferGeometry,
32765	DodecahedronGeometry: DodecahedronGeometry,
32766	DodecahedronBufferGeometry: DodecahedronBufferGeometry,
32767	PolyhedronGeometry: PolyhedronGeometry,
32768	PolyhedronBufferGeometry: PolyhedronBufferGeometry,
32769	TubeGeometry: TubeGeometry,
32770	TubeBufferGeometry: TubeBufferGeometry,
32771	TorusKnotGeometry: TorusKnotGeometry,
32772	TorusKnotBufferGeometry: TorusKnotBufferGeometry,
32773	TorusGeometry: TorusGeometry,
32774	TorusBufferGeometry: TorusBufferGeometry,
32775	TextGeometry: TextGeometry,
32776	TextBufferGeometry: TextBufferGeometry,
32777	SphereGeometry: SphereGeometry,
32778	SphereBufferGeometry: SphereBufferGeometry,
32779	RingGeometry: RingGeometry,
32780	RingBufferGeometry: RingBufferGeometry,
32781	PlaneGeometry: PlaneGeometry,
32782	PlaneBufferGeometry: PlaneBufferGeometry,
32783	LatheGeometry: LatheGeometry,
32784	LatheBufferGeometry: LatheBufferGeometry,
32785	ShapeGeometry: ShapeGeometry,
32786	ShapeBufferGeometry: ShapeBufferGeometry,
32787	ExtrudeGeometry: ExtrudeGeometry,
32788	ExtrudeBufferGeometry: ExtrudeBufferGeometry,
32789	EdgesGeometry: EdgesGeometry,
32790	ConeGeometry: ConeGeometry,
32791	ConeBufferGeometry: ConeBufferGeometry,
32792	CylinderGeometry: CylinderGeometry,
32793	CylinderBufferGeometry: CylinderBufferGeometry,
32794	CircleGeometry: CircleGeometry,
32795	CircleBufferGeometry: CircleBufferGeometry,
32796	BoxGeometry: BoxGeometry,
32797	BoxBufferGeometry: BoxBufferGeometry
32798});
32799
32800/**
32801 * @author mrdoob / http://mrdoob.com/
32802 *
32803 * parameters = {
32804 *  color: <THREE.Color>
32805 * }
32806 */
32807
32808function ShadowMaterial( parameters ) {
32809
32810	Material.call( this );
32811
32812	this.type = 'ShadowMaterial';
32813
32814	this.color = new Color( 0x000000 );
32815	this.transparent = true;
32816
32817	this.setValues( parameters );
32818
32819}
32820
32821ShadowMaterial.prototype = Object.create( Material.prototype );
32822ShadowMaterial.prototype.constructor = ShadowMaterial;
32823
vendor: 11,188 bytes, lines 32824-33310
32824ShadowMaterial.prototype.isShadowMaterial = true;
32825
32826ShadowMaterial.prototype.copy = function ( source ) {
32827
32828	Material.prototype.copy.call( this, source );
32829
32830	this.color.copy( source.color );
32831
32832	return this;
32833
32834};
32835
32836/**
32837 * @author mrdoob / http://mrdoob.com/
32838 */
32839
32840function RawShaderMaterial( parameters ) {
32841
32842	ShaderMaterial.call( this, parameters );
32843
32844	this.type = 'RawShaderMaterial';
32845
32846}
32847
32848RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );
32849RawShaderMaterial.prototype.constructor = RawShaderMaterial;
32850
32851RawShaderMaterial.prototype.isRawShaderMaterial = true;
32852
32853/**
32854 * @author WestLangley / http://github.com/WestLangley
32855 *
32856 * parameters = {
32857 *  color: <hex>,
32858 *  roughness: <float>,
32859 *  metalness: <float>,
32860 *  opacity: <float>,
32861 *
32862 *  map: new THREE.Texture( <Image> ),
32863 *
32864 *  lightMap: new THREE.Texture( <Image> ),
32865 *  lightMapIntensity: <float>
32866 *
32867 *  aoMap: new THREE.Texture( <Image> ),
32868 *  aoMapIntensity: <float>
32869 *
32870 *  emissive: <hex>,
32871 *  emissiveIntensity: <float>
32872 *  emissiveMap: new THREE.Texture( <Image> ),
32873 *
32874 *  bumpMap: new THREE.Texture( <Image> ),
32875 *  bumpScale: <float>,
32876 *
32877 *  normalMap: new THREE.Texture( <Image> ),
32878 *  normalMapType: THREE.TangentSpaceNormalMap,
32879 *  normalScale: <Vector2>,
32880 *
32881 *  displacementMap: new THREE.Texture( <Image> ),
32882 *  displacementScale: <float>,
32883 *  displacementBias: <float>,
32884 *
32885 *  roughnessMap: new THREE.Texture( <Image> ),
32886 *
32887 *  metalnessMap: new THREE.Texture( <Image> ),
32888 *
32889 *  alphaMap: new THREE.Texture( <Image> ),
32890 *
32891 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
32892 *  envMapIntensity: <float>
32893 *
32894 *  refractionRatio: <float>,
32895 *
32896 *  wireframe: <boolean>,
32897 *  wireframeLinewidth: <float>,
32898 *
32899 *  skinning: <bool>,
32900 *  morphTargets: <bool>,
32901 *  morphNormals: <bool>
32902 * }
32903 */
32904
32905function MeshStandardMaterial( parameters ) {
32906
32907	Material.call( this );
32908
32909	this.defines = { 'STANDARD': '' };
32910
32911	this.type = 'MeshStandardMaterial';
32912
32913	this.color = new Color( 0xffffff ); // diffuse
32914	this.roughness = 1.0;
32915	this.metalness = 0.0;
32916
32917	this.map = null;
32918
32919	this.lightMap = null;
32920	this.lightMapIntensity = 1.0;
32921
32922	this.aoMap = null;
32923	this.aoMapIntensity = 1.0;
32924
32925	this.emissive = new Color( 0x000000 );
32926	this.emissiveIntensity = 1.0;
32927	this.emissiveMap = null;
32928
32929	this.bumpMap = null;
32930	this.bumpScale = 1;
32931
32932	this.normalMap = null;
32933	this.normalMapType = TangentSpaceNormalMap;
32934	this.normalScale = new Vector2( 1, 1 );
32935
32936	this.displacementMap = null;
32937	this.displacementScale = 1;
32938	this.displacementBias = 0;
32939
32940	this.roughnessMap = null;
32941
32942	this.metalnessMap = null;
32943
32944	this.alphaMap = null;
32945
32946	this.envMap = null;
32947	this.envMapIntensity = 1.0;
32948
32949	this.refractionRatio = 0.98;
32950
32951	this.wireframe = false;
32952	this.wireframeLinewidth = 1;
32953	this.wireframeLinecap = 'round';
32954	this.wireframeLinejoin = 'round';
32955
32956	this.skinning = false;
32957	this.morphTargets = false;
32958	this.morphNormals = false;
32959
32960	this.vertexTangents = false;
32961
32962	this.setValues( parameters );
32963
32964}
32965
32966MeshStandardMaterial.prototype = Object.create( Material.prototype );
32967MeshStandardMaterial.prototype.constructor = MeshStandardMaterial;
32968
32969MeshStandardMaterial.prototype.isMeshStandardMaterial = true;
32970
32971MeshStandardMaterial.prototype.copy = function ( source ) {
32972
32973	Material.prototype.copy.call( this, source );
32974
32975	this.defines = { 'STANDARD': '' };
32976
32977	this.color.copy( source.color );
32978	this.roughness = source.roughness;
32979	this.metalness = source.metalness;
32980
32981	this.map = source.map;
32982
32983	this.lightMap = source.lightMap;
32984	this.lightMapIntensity = source.lightMapIntensity;
32985
32986	this.aoMap = source.aoMap;
32987	this.aoMapIntensity = source.aoMapIntensity;
32988
32989	this.emissive.copy( source.emissive );
32990	this.emissiveMap = source.emissiveMap;
32991	this.emissiveIntensity = source.emissiveIntensity;
32992
32993	this.bumpMap = source.bumpMap;
32994	this.bumpScale = source.bumpScale;
32995
32996	this.normalMap = source.normalMap;
32997	this.normalMapType = source.normalMapType;
32998	this.normalScale.copy( source.normalScale );
32999
33000	this.displacementMap = source.displacementMap;
33001	this.displacementScale = source.displacementScale;
33002	this.displacementBias = source.displacementBias;
33003
33004	this.roughnessMap = source.roughnessMap;
33005
33006	this.metalnessMap = source.metalnessMap;
33007
33008	this.alphaMap = source.alphaMap;
33009
33010	this.envMap = source.envMap;
33011	this.envMapIntensity = source.envMapIntensity;
33012
33013	this.refractionRatio = source.refractionRatio;
33014
33015	this.wireframe = source.wireframe;
33016	this.wireframeLinewidth = source.wireframeLinewidth;
33017	this.wireframeLinecap = source.wireframeLinecap;
33018	this.wireframeLinejoin = source.wireframeLinejoin;
33019
33020	this.skinning = source.skinning;
33021	this.morphTargets = source.morphTargets;
33022	this.morphNormals = source.morphNormals;
33023
33024	this.vertexTangents = source.vertexTangents;
33025
33026	return this;
33027
33028};
33029
33030/**
33031 * @author WestLangley / http://github.com/WestLangley
33032 *
33033 * parameters = {
33034 *  clearcoat: <float>,
33035 *  clearcoatMap: new THREE.Texture( <Image> ),
33036 *  clearcoatRoughness: <float>,
33037 *  clearcoatRoughnessMap: new THREE.Texture( <Image> ),
33038 *  clearcoatNormalScale: <Vector2>,
33039 *  clearcoatNormalMap: new THREE.Texture( <Image> ),
33040 *
33041 *  reflectivity: <float>,
33042 *
33043 *  sheen: <Color>,
33044 *
33045 *  transparency: <float>
33046 * }
33047 */
33048
33049function MeshPhysicalMaterial( parameters ) {
33050
33051	MeshStandardMaterial.call( this );
33052
33053	this.defines = {
33054
33055		'STANDARD': '',
33056		'PHYSICAL': ''
33057
33058	};
33059
33060	this.type = 'MeshPhysicalMaterial';
33061
33062	this.clearcoat = 0.0;
33063	this.clearcoatMap = null;
33064	this.clearcoatRoughness = 0.0;
33065	this.clearcoatRoughnessMap = null;
33066	this.clearcoatNormalScale = new Vector2( 1, 1 );
33067	this.clearcoatNormalMap = null;
33068
33069	this.reflectivity = 0.5; // maps to F0 = 0.04
33070
33071	this.sheen = null; // null will disable sheen bsdf
33072
33073	this.transparency = 0.0;
33074
33075	this.setValues( parameters );
33076
33077}
33078
33079MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );
33080MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;
33081
33082MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;
33083
33084MeshPhysicalMaterial.prototype.copy = function ( source ) {
33085
33086	MeshStandardMaterial.prototype.copy.call( this, source );
33087
33088	this.defines = {
33089
33090		'STANDARD': '',
33091		'PHYSICAL': ''
33092
33093	};
33094
33095	this.clearcoat = source.clearcoat;
33096	this.clearcoatMap = source.clearcoatMap;
33097	this.clearcoatRoughness = source.clearcoatRoughness;
33098	this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
33099	this.clearcoatNormalMap = source.clearcoatNormalMap;
33100	this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
33101
33102	this.reflectivity = source.reflectivity;
33103
33104	if ( source.sheen ) {
33105
33106		this.sheen = ( this.sheen || new Color() ).copy( source.sheen );
33107
33108	} else {
33109
33110		this.sheen = null;
33111
33112	}
33113
33114	this.transparency = source.transparency;
33115
33116	return this;
33117
33118};
33119
33120/**
33121 * @author mrdoob / http://mrdoob.com/
33122 * @author alteredq / http://alteredqualia.com/
33123 *
33124 * parameters = {
33125 *  color: <hex>,
33126 *  specular: <hex>,
33127 *  shininess: <float>,
33128 *  opacity: <float>,
33129 *
33130 *  map: new THREE.Texture( <Image> ),
33131 *
33132 *  lightMap: new THREE.Texture( <Image> ),
33133 *  lightMapIntensity: <float>
33134 *
33135 *  aoMap: new THREE.Texture( <Image> ),
33136 *  aoMapIntensity: <float>
33137 *
33138 *  emissive: <hex>,
33139 *  emissiveIntensity: <float>
33140 *  emissiveMap: new THREE.Texture( <Image> ),
33141 *
33142 *  bumpMap: new THREE.Texture( <Image> ),
33143 *  bumpScale: <float>,
33144 *
33145 *  normalMap: new THREE.Texture( <Image> ),
33146 *  normalMapType: THREE.TangentSpaceNormalMap,
33147 *  normalScale: <Vector2>,
33148 *
33149 *  displacementMap: new THREE.Texture( <Image> ),
33150 *  displacementScale: <float>,
33151 *  displacementBias: <float>,
33152 *
33153 *  specularMap: new THREE.Texture( <Image> ),
33154 *
33155 *  alphaMap: new THREE.Texture( <Image> ),
33156 *
33157 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
33158 *  combine: THREE.MultiplyOperation,
33159 *  reflectivity: <float>,
33160 *  refractionRatio: <float>,
33161 *
33162 *  wireframe: <boolean>,
33163 *  wireframeLinewidth: <float>,
33164 *
33165 *  skinning: <bool>,
33166 *  morphTargets: <bool>,
33167 *  morphNormals: <bool>
33168 * }
33169 */
33170
33171function MeshPhongMaterial( parameters ) {
33172
33173	Material.call( this );
33174
33175	this.type = 'MeshPhongMaterial';
33176
33177	this.color = new Color( 0xffffff ); // diffuse
33178	this.specular = new Color( 0x111111 );
33179	this.shininess = 30;
33180
33181	this.map = null;
33182
33183	this.lightMap = null;
33184	this.lightMapIntensity = 1.0;
33185
33186	this.aoMap = null;
33187	this.aoMapIntensity = 1.0;
33188
33189	this.emissive = new Color( 0x000000 );
33190	this.emissiveIntensity = 1.0;
33191	this.emissiveMap = null;
33192
33193	this.bumpMap = null;
33194	this.bumpScale = 1;
33195
33196	this.normalMap = null;
33197	this.normalMapType = TangentSpaceNormalMap;
33198	this.normalScale = new Vector2( 1, 1 );
33199
33200	this.displacementMap = null;
33201	this.displacementScale = 1;
33202	this.displacementBias = 0;
33203
33204	this.specularMap = null;
33205
33206	this.alphaMap = null;
33207
33208	this.envMap = null;
33209	this.combine = MultiplyOperation;
33210	this.reflectivity = 1;
33211	this.refractionRatio = 0.98;
33212
33213	this.wireframe = false;
33214	this.wireframeLinewidth = 1;
33215	this.wireframeLinecap = 'round';
33216	this.wireframeLinejoin = 'round';
33217
33218	this.skinning = false;
33219	this.morphTargets = false;
33220	this.morphNormals = false;
33221
33222	this.setValues( parameters );
33223
33224}
33225
33226MeshPhongMaterial.prototype = Object.create( Material.prototype );
33227MeshPhongMaterial.prototype.constructor = MeshPhongMaterial;
33228
33229MeshPhongMaterial.prototype.isMeshPhongMaterial = true;
33230
33231MeshPhongMaterial.prototype.copy = function ( source ) {
33232
33233	Material.prototype.copy.call( this, source );
33234
33235	this.color.copy( source.color );
33236	this.specular.copy( source.specular );
33237	this.shininess = source.shininess;
33238
33239	this.map = source.map;
33240
33241	this.lightMap = source.lightMap;
33242	this.lightMapIntensity = source.lightMapIntensity;
33243
33244	this.aoMap = source.aoMap;
33245	this.aoMapIntensity = source.aoMapIntensity;
33246
33247	this.emissive.copy( source.emissive );
33248	this.emissiveMap = source.emissiveMap;
33249	this.emissiveIntensity = source.emissiveIntensity;
33250
33251	this.bumpMap = source.bumpMap;
33252	this.bumpScale = source.bumpScale;
33253
33254	this.normalMap = source.normalMap;
33255	this.normalMapType = source.normalMapType;
33256	this.normalScale.copy( source.normalScale );
33257
33258	this.displacementMap = source.displacementMap;
33259	this.displacementScale = source.displacementScale;
33260	this.displacementBias = source.displacementBias;
33261
33262	this.specularMap = source.specularMap;
33263
33264	this.alphaMap = source.alphaMap;
33265
33266	this.envMap = source.envMap;
33267	this.combine = source.combine;
33268	this.reflectivity = source.reflectivity;
33269	this.refractionRatio = source.refractionRatio;
33270
33271	this.wireframe = source.wireframe;
33272	this.wireframeLinewidth = source.wireframeLinewidth;
33273	this.wireframeLinecap = source.wireframeLinecap;
33274	this.wireframeLinejoin = source.wireframeLinejoin;
33275
33276	this.skinning = source.skinning;
33277	this.morphTargets = source.morphTargets;
33278	this.morphNormals = source.morphNormals;
33279
33280	return this;
33281
33282};
33283
33284/**
33285 * @author takahirox / http://github.com/takahirox
33286 *
33287 * parameters = {
33288 *  color: <hex>,
33289 *  specular: <hex>,
33290 *  shininess: <float>,
33291 *
33292 *  map: new THREE.Texture( <Image> ),
33293 *  gradientMap: new THREE.Texture( <Image> ),
33294 *
33295 *  lightMap: new THREE.Texture( <Image> ),
33296 *  lightMapIntensity: <float>
33297 *
33298 *  aoMap: new THREE.Texture( <Image> ),
33299 *  aoMapIntensity: <float>
33300 *
33301 *  emissive: <hex>,
33302 *  emissiveIntensity: <float>
33303 *  emissiveMap: new THREE.Texture( <Image> ),
33304 *
33305 *  bumpMap: new THREE.Texture( <Image> ),
33306 *  bumpScale: <float>,
33307 *
33308 *  normalMap: new THREE.Texture( <Image> ),
33309 *  normalMapType: THREE.TangentSpaceNormalMap,
33310 *  normalScale: <Vector2>,
33311 *
33312 *  displacementMap: new THREE.Texture( <Image> ),
33313 *  displacementScale: <float>,
33314 *  displacementBias: <float>,
33315 *
33316 *  specularMap: new THREE.Texture( <Image> ),
33317 *
33318 *  alphaMap: new THREE.Texture( <Image> ),
33319 *
33320 *  wireframe: <boolean>,
33321 *  wireframeLinewidth: <float>,
33322 *
33323 *  skinning: <bool>,
33324 *  morphTargets: <bool>,
33325 *  morphNormals: <bool>
33326 * }
33327 */
33328
33329function MeshToonMaterial( parameters ) {
33330
33331	Material.call( this );
33332
33333	this.defines = { 'TOON': '' };
33334
33335	this.type = 'MeshToonMaterial';
33336
33337	this.color = new Color( 0xffffff );
33338	this.specular = new Color( 0x111111 );
33339	this.shininess = 30;
33340
33341	this.map = null;
33342	this.gradientMap = null;
33343
33344	this.lightMap = null;
33345	this.lightMapIntensity = 1.0;
33346
33347	this.aoMap = null;
33348	this.aoMapIntensity = 1.0;
33349
33350	this.emissive = new Color( 0x000000 );
33351	this.emissiveIntensity = 1.0;
33352	this.emissiveMap = null;
33353
33354	this.bumpMap = null;
33355	this.bumpScale = 1;
33356
33357	this.normalMap = null;
33358	this.normalMapType = TangentSpaceNormalMap;
33359	this.normalScale = new Vector2( 1, 1 );
33360
33361	this.displacementMap = null;
33362	this.displacementScale = 1;
33363	this.displacementBias = 0;
33364
33365	this.specularMap = null;
33366
33367	this.alphaMap = null;
33368
33369	this.wireframe = false;
33370	this.wireframeLinewidth = 1;
33371	this.wireframeLinecap = 'round';
33372	this.wireframeLinejoin = 'round';
33373
33374	this.skinning = false;
33375	this.morphTargets = false;
33376	this.morphNormals = false;
33377
33378	this.setValues( parameters );
33379
33380}
33381
33382MeshToonMaterial.prototype = Object.create( Material.prototype );
33383MeshToonMaterial.prototype.constructor = MeshToonMaterial;
33384
33385MeshToonMaterial.prototype.isMeshToonMaterial = true;
33386
33387MeshToonMaterial.prototype.copy = function ( source ) {
33388
33389	Material.prototype.copy.call( this, source );
33390
33391	this.color.copy( source.color );
33392	this.specular.copy( source.specular );
33393	this.shininess = source.shininess;
33394
33395	this.map = source.map;
33396	this.gradientMap = source.gradientMap;
33397
33398	this.lightMap = source.lightMap;
33399	this.lightMapIntensity = source.lightMapIntensity;
33400
33401	this.aoMap = source.aoMap;
33402	this.aoMapIntensity = source.aoMapIntensity;
33403
33404	this.emissive.copy( source.emissive );
33405	this.emissiveMap = source.emissiveMap;
33406	this.emissiveIntensity = source.emissiveIntensity;
33407
33408	this.bumpMap = source.bumpMap;
33409	this.bumpScale = source.bumpScale;
33410
33411	this.normalMap = source.normalMap;
33412	this.normalMapType = source.normalMapType;
33413	this.normalScale.copy( source.normalScale );
33414
33415	this.displacementMap = source.displacementMap;
33416	this.displacementScale = source.displacementScale;
33417	this.displacementBias = source.displacementBias;
33418
33419	this.specularMap = source.specularMap;
33420
33421	this.alphaMap = source.alphaMap;
33422
33423	this.wireframe = source.wireframe;
33424	this.wireframeLinewidth = source.wireframeLinewidth;
33425	this.wireframeLinecap = source.wireframeLinecap;
33426	this.wireframeLinejoin = source.wireframeLinejoin;
33427
33428	this.skinning = source.skinning;
33429	this.morphTargets = source.morphTargets;
33430	this.morphNormals = source.morphNormals;
33431
33432	return this;
33433
33434};
33435
33436/**
33437 * @author mrdoob / http://mrdoob.com/
33438 * @author WestLangley / http://github.com/WestLangley
33439 *
33440 * parameters = {
33441 *  opacity: <float>,
33442 *
33443 *  bumpMap: new THREE.Texture( <Image> ),
33444 *  bumpScale: <float>,
33445 *
33446 *  normalMap: new THREE.Texture( <Image> ),
33447 *  normalMapType: THREE.TangentSpaceNormalMap,
33448 *  normalScale: <Vector2>,
33449 *
33450 *  displacementMap: new THREE.Texture( <Image> ),
33451 *  displacementScale: <float>,
33452 *  displacementBias: <float>,
33453 *
33454 *  wireframe: <boolean>,
33455 *  wireframeLinewidth: <float>
33456 *
33457 *  skinning: <bool>,
33458 *  morphTargets: <bool>,
33459 *  morphNormals: <bool>
33460 * }
33461 */
33462
33463function MeshNormalMaterial( parameters ) {
33464
33465	Material.call( this );
33466
33467	this.type = 'MeshNormalMaterial';
33468
33469	this.bumpMap = null;
33470	this.bumpScale = 1;
33471
33472	this.normalMap = null;
33473	this.normalMapType = TangentSpaceNormalMap;
33474	this.normalScale = new Vector2( 1, 1 );
33475
33476	this.displacementMap = null;
33477	this.displacementScale = 1;
33478	this.displacementBias = 0;
33479
33480	this.wireframe = false;
33481	this.wireframeLinewidth = 1;
33482
33483	this.fog = false;
33484
33485	this.skinning = false;
33486	this.morphTargets = false;
33487	this.morphNormals = false;
33488
33489	this.setValues( parameters );
33490
33491}
33492
33493MeshNormalMaterial.prototype = Object.create( Material.prototype );
33494MeshNormalMaterial.prototype.constructor = MeshNormalMaterial;
33495
33496MeshNormalMaterial.prototype.isMeshNormalMaterial = true;
33497
33498MeshNormalMaterial.prototype.copy = function ( source ) {
33499
33500	Material.prototype.copy.call( this, source );
33501
33502	this.bumpMap = source.bumpMap;
33503	this.bumpScale = source.bumpScale;
33504
33505	this.normalMap = source.normalMap;
33506	this.normalMapType = source.normalMapType;
33507	this.normalScale.copy( source.normalScale );
33508
33509	this.displacementMap = source.displacementMap;
33510	this.displacementScale = source.displacementScale;
33511	this.displacementBias = source.displacementBias;
33512
33513	this.wireframe = source.wireframe;
33514	this.wireframeLinewidth = source.wireframeLinewidth;
33515
33516	this.skinning = source.skinning;
33517	this.morphTargets = source.morphTargets;
33518	this.morphNormals = source.morphNormals;
33519
33520	return this;
33521
33522};
33523
33524/**
33525 * @author mrdoob / http://mrdoob.com/
33526 * @author alteredq / http://alteredqualia.com/
33527 *
33528 * parameters = {
33529 *  color: <hex>,
33530 *  opacity: <float>,
33531 *
33532 *  map: new THREE.Texture( <Image> ),
33533 *
33534 *  lightMap: new THREE.Texture( <Image> ),
33535 *  lightMapIntensity: <float>
33536 *
33537 *  aoMap: new THREE.Texture( <Image> ),
33538 *  aoMapIntensity: <float>
33539 *
33540 *  emissive: <hex>,
33541 *  emissiveIntensity: <float>
33542 *  emissiveMap: new THREE.Texture( <Image> ),
33543 *
33544 *  specularMap: new THREE.Texture( <Image> ),
33545 *
33546 *  alphaMap: new THREE.Texture( <Image> ),
33547 *
33548 *  envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),
33549 *  combine: THREE.Multiply,
33550 *  reflectivity: <float>,
33551 *  refractionRatio: <float>,
33552 *
33553 *  wireframe: <boolean>,
33554 *  wireframeLinewidth: <float>,
33555 *
33556 *  skinning: <bool>,
33557 *  morphTargets: <bool>,
33558 *  morphNormals: <bool>
33559 * }
33560 */
33561
33562function MeshLambertMaterial( parameters ) {
33563
33564	Material.call( this );
33565
33566	this.type = 'MeshLambertMaterial';
33567
33568	this.color = new Color( 0xffffff ); // diffuse
33569
33570	this.map = null;
33571
33572	this.lightMap = null;
33573	this.lightMapIntensity = 1.0;
33574
33575	this.aoMap = null;
33576	this.aoMapIntensity = 1.0;
33577
33578	this.emissive = new Color( 0x000000 );
33579	this.emissiveIntensity = 1.0;
33580	this.emissiveMap = null;
33581
33582	this.specularMap = null;
33583
33584	this.alphaMap = null;
33585
33586	this.envMap = null;
33587	this.combine = MultiplyOperation;
33588	this.reflectivity = 1;
33589	this.refractionRatio = 0.98;
33590
33591	this.wireframe = false;
vendor: 5,982 bytes, lines 33592-33846
33592	this.wireframeLinewidth = 1;
33593	this.wireframeLinecap = 'round';
33594	this.wireframeLinejoin = 'round';
33595
33596	this.skinning = false;
33597	this.morphTargets = false;
33598	this.morphNormals = false;
33599
33600	this.setValues( parameters );
33601
33602}
33603
33604MeshLambertMaterial.prototype = Object.create( Material.prototype );
33605MeshLambertMaterial.prototype.constructor = MeshLambertMaterial;
33606
33607MeshLambertMaterial.prototype.isMeshLambertMaterial = true;
33608
33609MeshLambertMaterial.prototype.copy = function ( source ) {
33610
33611	Material.prototype.copy.call( this, source );
33612
33613	this.color.copy( source.color );
33614
33615	this.map = source.map;
33616
33617	this.lightMap = source.lightMap;
33618	this.lightMapIntensity = source.lightMapIntensity;
33619
33620	this.aoMap = source.aoMap;
33621	this.aoMapIntensity = source.aoMapIntensity;
33622
33623	this.emissive.copy( source.emissive );
33624	this.emissiveMap = source.emissiveMap;
33625	this.emissiveIntensity = source.emissiveIntensity;
33626
33627	this.specularMap = source.specularMap;
33628
33629	this.alphaMap = source.alphaMap;
33630
33631	this.envMap = source.envMap;
33632	this.combine = source.combine;
33633	this.reflectivity = source.reflectivity;
33634	this.refractionRatio = source.refractionRatio;
33635
33636	this.wireframe = source.wireframe;
33637	this.wireframeLinewidth = source.wireframeLinewidth;
33638	this.wireframeLinecap = source.wireframeLinecap;
33639	this.wireframeLinejoin = source.wireframeLinejoin;
33640
33641	this.skinning = source.skinning;
33642	this.morphTargets = source.morphTargets;
33643	this.morphNormals = source.morphNormals;
33644
33645	return this;
33646
33647};
33648
33649/**
33650 * @author WestLangley / http://github.com/WestLangley
33651 *
33652 * parameters = {
33653 *  color: <hex>,
33654 *  opacity: <float>,
33655 *
33656 *  matcap: new THREE.Texture( <Image> ),
33657 *
33658 *  map: new THREE.Texture( <Image> ),
33659 *
33660 *  bumpMap: new THREE.Texture( <Image> ),
33661 *  bumpScale: <float>,
33662 *
33663 *  normalMap: new THREE.Texture( <Image> ),
33664 *  normalMapType: THREE.TangentSpaceNormalMap,
33665 *  normalScale: <Vector2>,
33666 *
33667 *  displacementMap: new THREE.Texture( <Image> ),
33668 *  displacementScale: <float>,
33669 *  displacementBias: <float>,
33670 *
33671 *  alphaMap: new THREE.Texture( <Image> ),
33672 *
33673 *  skinning: <bool>,
33674 *  morphTargets: <bool>,
33675 *  morphNormals: <bool>
33676 * }
33677 */
33678
33679function MeshMatcapMaterial( parameters ) {
33680
33681	Material.call( this );
33682
33683	this.defines = { 'MATCAP': '' };
33684
33685	this.type = 'MeshMatcapMaterial';
33686
33687	this.color = new Color( 0xffffff ); // diffuse
33688
33689	this.matcap = null;
33690
33691	this.map = null;
33692
33693	this.bumpMap = null;
33694	this.bumpScale = 1;
33695
33696	this.normalMap = null;
33697	this.normalMapType = TangentSpaceNormalMap;
33698	this.normalScale = new Vector2( 1, 1 );
33699
33700	this.displacementMap = null;
33701	this.displacementScale = 1;
33702	this.displacementBias = 0;
33703
33704	this.alphaMap = null;
33705
33706	this.skinning = false;
33707	this.morphTargets = false;
33708	this.morphNormals = false;
33709
33710	this.setValues( parameters );
33711
33712}
33713
33714MeshMatcapMaterial.prototype = Object.create( Material.prototype );
33715MeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;
33716
33717MeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;
33718
33719MeshMatcapMaterial.prototype.copy = function ( source ) {
33720
33721	Material.prototype.copy.call( this, source );
33722
33723	this.defines = { 'MATCAP': '' };
33724
33725	this.color.copy( source.color );
33726
33727	this.matcap = source.matcap;
33728
33729	this.map = source.map;
33730
33731	this.bumpMap = source.bumpMap;
33732	this.bumpScale = source.bumpScale;
33733
33734	this.normalMap = source.normalMap;
33735	this.normalMapType = source.normalMapType;
33736	this.normalScale.copy( source.normalScale );
33737
33738	this.displacementMap = source.displacementMap;
33739	this.displacementScale = source.displacementScale;
33740	this.displacementBias = source.displacementBias;
33741
33742	this.alphaMap = source.alphaMap;
33743
33744	this.skinning = source.skinning;
33745	this.morphTargets = source.morphTargets;
33746	this.morphNormals = source.morphNormals;
33747
33748	return this;
33749
33750};
33751
33752/**
33753 * @author alteredq / http://alteredqualia.com/
33754 *
33755 * parameters = {
33756 *  color: <hex>,
33757 *  opacity: <float>,
33758 *
33759 *  linewidth: <float>,
33760 *
33761 *  scale: <float>,
33762 *  dashSize: <float>,
33763 *  gapSize: <float>
33764 * }
33765 */
33766
33767function LineDashedMaterial( parameters ) {
33768
33769	LineBasicMaterial.call( this );
33770
33771	this.type = 'LineDashedMaterial';
33772
33773	this.scale = 1;
33774	this.dashSize = 3;
33775	this.gapSize = 1;
33776
33777	this.setValues( parameters );
33778
33779}
33780
33781LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );
33782LineDashedMaterial.prototype.constructor = LineDashedMaterial;
33783
33784LineDashedMaterial.prototype.isLineDashedMaterial = true;
33785
33786LineDashedMaterial.prototype.copy = function ( source ) {
33787
33788	LineBasicMaterial.prototype.copy.call( this, source );
33789
33790	this.scale = source.scale;
33791	this.dashSize = source.dashSize;
33792	this.gapSize = source.gapSize;
33793
33794	return this;
33795
33796};
33797
33798var Materials = /*#__PURE__*/Object.freeze({
33799	__proto__: null,
33800	ShadowMaterial: ShadowMaterial,
33801	SpriteMaterial: SpriteMaterial,
33802	RawShaderMaterial: RawShaderMaterial,
33803	ShaderMaterial: ShaderMaterial,
33804	PointsMaterial: PointsMaterial,
33805	MeshPhysicalMaterial: MeshPhysicalMaterial,
33806	MeshStandardMaterial: MeshStandardMaterial,
33807	MeshPhongMaterial: MeshPhongMaterial,
33808	MeshToonMaterial: MeshToonMaterial,
33809	MeshNormalMaterial: MeshNormalMaterial,
33810	MeshLambertMaterial: MeshLambertMaterial,
33811	MeshDepthMaterial: MeshDepthMaterial,
33812	MeshDistanceMaterial: MeshDistanceMaterial,
33813	MeshBasicMaterial: MeshBasicMaterial,
33814	MeshMatcapMaterial: MeshMatcapMaterial,
33815	LineDashedMaterial: LineDashedMaterial,
33816	LineBasicMaterial: LineBasicMaterial,
33817	Material: Material
33818});
33819
33820/**
33821 * @author tschw
33822 * @author Ben Houston / http://clara.io/
33823 * @author David Sarno / http://lighthaus.us/
33824 */
33825
33826var AnimationUtils = {
33827
33828	// same as Array.prototype.slice, but also works on typed arrays
33829	arraySlice: function ( array, from, to ) {
33830
33831		if ( AnimationUtils.isTypedArray( array ) ) {
33832
33833			// in ios9 array.subarray(from, undefined) will return empty array
33834			// but array.subarray(from) or array.subarray(from, len) is correct
33835			return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
33836
33837		}
33838
33839		return array.slice( from, to );
33840
33841	},
33842
33843	// converts an array to a specific type
33844	convertArray: function ( array, type, forceClone ) {
33845
33846		if ( ! array || // let 'undefined' and 'null' pass
vendor: 5,877 bytes, lines 33847-34113
33847			! forceClone && array.constructor === type ) return array;
33848
33849		if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
33850
33851			return new type( array ); // create typed array
33852
33853		}
33854
33855		return Array.prototype.slice.call( array ); // create Array
33856
33857	},
33858
33859	isTypedArray: function ( object ) {
33860
33861		return ArrayBuffer.isView( object ) &&
33862			! ( object instanceof DataView );
33863
33864	},
33865
33866	// returns an array by which times and values can be sorted
33867	getKeyframeOrder: function ( times ) {
33868
33869		function compareTime( i, j ) {
33870
33871			return times[ i ] - times[ j ];
33872
33873		}
33874
33875		var n = times.length;
33876		var result = new Array( n );
33877		for ( var i = 0; i !== n; ++ i ) result[ i ] = i;
33878
33879		result.sort( compareTime );
33880
33881		return result;
33882
33883	},
33884
33885	// uses the array previously returned by 'getKeyframeOrder' to sort data
33886	sortedArray: function ( values, stride, order ) {
33887
33888		var nValues = values.length;
33889		var result = new values.constructor( nValues );
33890
33891		for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
33892
33893			var srcOffset = order[ i ] * stride;
33894
33895			for ( var j = 0; j !== stride; ++ j ) {
33896
33897				result[ dstOffset ++ ] = values[ srcOffset + j ];
33898
33899			}
33900
33901		}
33902
33903		return result;
33904
33905	},
33906
33907	// function for parsing AOS keyframe formats
33908	flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {
33909
33910		var i = 1, key = jsonKeys[ 0 ];
33911
33912		while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
33913
33914			key = jsonKeys[ i ++ ];
33915
33916		}
33917
33918		if ( key === undefined ) return; // no data
33919
33920		var value = key[ valuePropertyName ];
33921		if ( value === undefined ) return; // no data
33922
33923		if ( Array.isArray( value ) ) {
33924
33925			do {
33926
33927				value = key[ valuePropertyName ];
33928
33929				if ( value !== undefined ) {
33930
33931					times.push( key.time );
33932					values.push.apply( values, value ); // push all elements
33933
33934				}
33935
33936				key = jsonKeys[ i ++ ];
33937
33938			} while ( key !== undefined );
33939
33940		} else if ( value.toArray !== undefined ) {
33941
33942			// ...assume THREE.Math-ish
33943
33944			do {
33945
33946				value = key[ valuePropertyName ];
33947
33948				if ( value !== undefined ) {
33949
33950					times.push( key.time );
33951					value.toArray( values, values.length );
33952
33953				}
33954
33955				key = jsonKeys[ i ++ ];
33956
33957			} while ( key !== undefined );
33958
33959		} else {
33960
33961			// otherwise push as-is
33962
33963			do {
33964
33965				value = key[ valuePropertyName ];
33966
33967				if ( value !== undefined ) {
33968
33969					times.push( key.time );
33970					values.push( value );
33971
33972				}
33973
33974				key = jsonKeys[ i ++ ];
33975
33976			} while ( key !== undefined );
33977
33978		}
33979
33980	},
33981
33982	subclip: function ( sourceClip, name, startFrame, endFrame, fps ) {
33983
33984		fps = fps || 30;
33985
33986		var clip = sourceClip.clone();
33987
33988		clip.name = name;
33989
33990		var tracks = [];
33991
33992		for ( var i = 0; i < clip.tracks.length; ++ i ) {
33993
33994			var track = clip.tracks[ i ];
33995			var valueSize = track.getValueSize();
33996
33997			var times = [];
33998			var values = [];
33999
34000			for ( var j = 0; j < track.times.length; ++ j ) {
34001
34002				var frame = track.times[ j ] * fps;
34003
34004				if ( frame < startFrame || frame >= endFrame ) continue;
34005
34006				times.push( track.times[ j ] );
34007
34008				for ( var k = 0; k < valueSize; ++ k ) {
34009
34010					values.push( track.values[ j * valueSize + k ] );
34011
34012				}
34013
34014			}
34015
34016			if ( times.length === 0 ) continue;
34017
34018			track.times = AnimationUtils.convertArray( times, track.times.constructor );
34019			track.values = AnimationUtils.convertArray( values, track.values.constructor );
34020
34021			tracks.push( track );
34022
34023		}
34024
34025		clip.tracks = tracks;
34026
34027		// find minimum .times value across all tracks in the trimmed clip
34028
34029		var minStartTime = Infinity;
34030
34031		for ( var i = 0; i < clip.tracks.length; ++ i ) {
34032
34033			if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
34034
34035				minStartTime = clip.tracks[ i ].times[ 0 ];
34036
34037			}
34038
34039		}
34040
34041		// shift all tracks such that clip begins at t=0
34042
34043		for ( var i = 0; i < clip.tracks.length; ++ i ) {
34044
34045			clip.tracks[ i ].shift( - 1 * minStartTime );
34046
34047		}
34048
34049		clip.resetDuration();
34050
34051		return clip;
34052
34053	},
34054
34055	makeClipAdditive: function ( targetClip, referenceFrame, referenceClip, fps ) {
34056
34057		if ( referenceFrame === undefined ) referenceFrame = 0;
34058		if ( referenceClip === undefined ) referenceClip = targetClip;
34059		if ( fps === undefined || fps <= 0 ) fps = 30;
34060
34061		var numTracks = targetClip.tracks.length;
34062		var referenceTime = referenceFrame / fps;
34063
34064		// Make each track's values relative to the values at the reference frame
34065		for ( var i = 0; i < numTracks; ++ i ) {
34066
34067			var referenceTrack = referenceClip.tracks[ i ];
34068			var referenceTrackType = referenceTrack.ValueTypeName;
34069
34070			// Skip this track if it's non-numeric
34071			if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
34072
34073			// Find the track in the target clip whose name and type matches the reference track
34074			var targetTrack = targetClip.tracks.find( function ( track ) {
34075
34076				return track.name === referenceTrack.name
34077				&& track.ValueTypeName === referenceTrackType;
34078
34079			} );
34080
34081			if ( targetTrack === undefined ) continue;
34082
34083			var valueSize = referenceTrack.getValueSize();
34084			var lastIndex = referenceTrack.times.length - 1;
34085			var referenceValue;
34086
34087			// Find the value to subtract out of the track
34088			if ( referenceTime <= referenceTrack.times[ 0 ] ) {
34089
34090				// Reference frame is earlier than the first keyframe, so just use the first keyframe
34091				referenceValue = AnimationUtils.arraySlice( referenceTrack.values, 0, referenceTrack.valueSize );
34092
34093			} else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
34094
34095				// Reference frame is after the last keyframe, so just use the last keyframe
34096				var startIndex = lastIndex * valueSize;
34097				referenceValue = AnimationUtils.arraySlice( referenceTrack.values, startIndex );
34098
34099			} else {
34100
34101				// Interpolate to the reference value
34102				var interpolant = referenceTrack.createInterpolant();
34103				interpolant.evaluate( referenceTime );
34104				referenceValue = interpolant.resultBuffer;
34105
34106			}
34107
34108			// Conjugate the quaternion
34109			if ( referenceTrackType === 'quaternion' ) {
34110
34111				var referenceQuat = new Quaternion(
34112					referenceValue[ 0 ],
34113					referenceValue[ 1 ],
34114					referenceValue[ 2 ],
34115					referenceValue[ 3 ]
34116				).normalize().conjugate();
34117				referenceQuat.toArray( referenceValue );
34118
34119			}
34120
34121			// Subtract the reference value from all of the track values
34122
34123			var numTimes = targetTrack.times.length;
34124			for ( var j = 0; j < numTimes; ++ j ) {
34125
34126				var valueStart = j * valueSize;
34127
34128				if ( referenceTrackType === 'quaternion' ) {
34129
34130					// Multiply the conjugate for quaternion track types
34131					Quaternion.multiplyQuaternionsFlat(
34132						targetTrack.values,
34133						valueStart,
34134						referenceValue,
34135						0,
34136						targetTrack.values,
34137						valueStart
34138					);
34139
34140				} else {
34141
34142					// Subtract each value for all other numeric track types
34143					for ( var k = 0; k < valueSize; ++ k ) {
34144
34145						targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
34146
34147					}
34148
34149				}
34150
34151			}
34152
34153		}
34154
34155		targetClip.blendMode = AdditiveAnimationBlendMode;
34156
34157		return targetClip;
34158
34159	}
34160
34161};
34162
34163/**
34164 * Abstract base class of interpolants over parametric samples.
34165 *
34166 * The parameter domain is one dimensional, typically the time or a path
34167 * along a curve defined by the data.
34168 *
34169 * The sample values can have any dimensionality and derived classes may
34170 * apply special interpretations to the data.
34171 *
34172 * This class provides the interval seek in a Template Method, deferring
34173 * the actual interpolation to derived classes.
34174 *
34175 * Time complexity is O(1) for linear access crossing at most two points
34176 * and O(log N) for random access, where N is the number of positions.
34177 *
34178 * References:
34179 *
34180 * 		http://www.oodesign.com/template-method-pattern.html
34181 *
34182 * @author tschw
34183 */
34184
34185function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34186
34187	this.parameterPositions = parameterPositions;
34188	this._cachedIndex = 0;
34189
34190	this.resultBuffer = resultBuffer !== undefined ?
34191		resultBuffer : new sampleValues.constructor( sampleSize );
34192	this.sampleValues = sampleValues;
34193	this.valueSize = sampleSize;
34194
34195}
34196
34197Object.assign( Interpolant.prototype, {
34198
34199	evaluate: function ( t ) {
34200
34201		var pp = this.parameterPositions,
34202			i1 = this._cachedIndex,
34203
34204			t1 = pp[ i1 ],
34205			t0 = pp[ i1 - 1 ];
34206
34207		validate_interval: {
34208
34209			seek: {
34210
34211				var right;
34212
34213				linear_scan: {
34214
vendor: 48,911 bytes, lines 34215-36813
34215					//- See http://jsperf.com/comparison-to-undefined/3
34216					//- slower code:
34217					//-
34218					//- 				if ( t >= t1 || t1 === undefined ) {
34219					forward_scan: if ( ! ( t < t1 ) ) {
34220
34221						for ( var giveUpAt = i1 + 2; ; ) {
34222
34223							if ( t1 === undefined ) {
34224
34225								if ( t < t0 ) break forward_scan;
34226
34227								// after end
34228
34229								i1 = pp.length;
34230								this._cachedIndex = i1;
34231								return this.afterEnd_( i1 - 1, t, t0 );
34232
34233							}
34234
34235							if ( i1 === giveUpAt ) break; // this loop
34236
34237							t0 = t1;
34238							t1 = pp[ ++ i1 ];
34239
34240							if ( t < t1 ) {
34241
34242								// we have arrived at the sought interval
34243								break seek;
34244
34245							}
34246
34247						}
34248
34249						// prepare binary search on the right side of the index
34250						right = pp.length;
34251						break linear_scan;
34252
34253					}
34254
34255					//- slower code:
34256					//-					if ( t < t0 || t0 === undefined ) {
34257					if ( ! ( t >= t0 ) ) {
34258
34259						// looping?
34260
34261						var t1global = pp[ 1 ];
34262
34263						if ( t < t1global ) {
34264
34265							i1 = 2; // + 1, using the scan for the details
34266							t0 = t1global;
34267
34268						}
34269
34270						// linear reverse scan
34271
34272						for ( var giveUpAt = i1 - 2; ; ) {
34273
34274							if ( t0 === undefined ) {
34275
34276								// before start
34277
34278								this._cachedIndex = 0;
34279								return this.beforeStart_( 0, t, t1 );
34280
34281							}
34282
34283							if ( i1 === giveUpAt ) break; // this loop
34284
34285							t1 = t0;
34286							t0 = pp[ -- i1 - 1 ];
34287
34288							if ( t >= t0 ) {
34289
34290								// we have arrived at the sought interval
34291								break seek;
34292
34293							}
34294
34295						}
34296
34297						// prepare binary search on the left side of the index
34298						right = i1;
34299						i1 = 0;
34300						break linear_scan;
34301
34302					}
34303
34304					// the interval is valid
34305
34306					break validate_interval;
34307
34308				} // linear scan
34309
34310				// binary search
34311
34312				while ( i1 < right ) {
34313
34314					var mid = ( i1 + right ) >>> 1;
34315
34316					if ( t < pp[ mid ] ) {
34317
34318						right = mid;
34319
34320					} else {
34321
34322						i1 = mid + 1;
34323
34324					}
34325
34326				}
34327
34328				t1 = pp[ i1 ];
34329				t0 = pp[ i1 - 1 ];
34330
34331				// check boundary cases, again
34332
34333				if ( t0 === undefined ) {
34334
34335					this._cachedIndex = 0;
34336					return this.beforeStart_( 0, t, t1 );
34337
34338				}
34339
34340				if ( t1 === undefined ) {
34341
34342					i1 = pp.length;
34343					this._cachedIndex = i1;
34344					return this.afterEnd_( i1 - 1, t0, t );
34345
34346				}
34347
34348			} // seek
34349
34350			this._cachedIndex = i1;
34351
34352			this.intervalChanged_( i1, t0, t1 );
34353
34354		} // validate_interval
34355
34356		return this.interpolate_( i1, t0, t, t1 );
34357
34358	},
34359
34360	settings: null, // optional, subclass-specific settings structure
34361	// Note: The indirection allows central control of many interpolants.
34362
34363	// --- Protected interface
34364
34365	DefaultSettings_: {},
34366
34367	getSettings_: function () {
34368
34369		return this.settings || this.DefaultSettings_;
34370
34371	},
34372
34373	copySampleValue_: function ( index ) {
34374
34375		// copies a sample value to the result buffer
34376
34377		var result = this.resultBuffer,
34378			values = this.sampleValues,
34379			stride = this.valueSize,
34380			offset = index * stride;
34381
34382		for ( var i = 0; i !== stride; ++ i ) {
34383
34384			result[ i ] = values[ offset + i ];
34385
34386		}
34387
34388		return result;
34389
34390	},
34391
34392	// Template methods for derived classes:
34393
34394	interpolate_: function ( /* i1, t0, t, t1 */ ) {
34395
34396		throw new Error( 'call to abstract method' );
34397		// implementations shall return this.resultBuffer
34398
34399	},
34400
34401	intervalChanged_: function ( /* i1, t0, t1 */ ) {
34402
34403		// empty
34404
34405	}
34406
34407} );
34408
34409// DECLARE ALIAS AFTER assign prototype
34410Object.assign( Interpolant.prototype, {
34411
34412	//( 0, t, t0 ), returns this.resultBuffer
34413	beforeStart_: Interpolant.prototype.copySampleValue_,
34414
34415	//( N-1, tN-1, t ), returns this.resultBuffer
34416	afterEnd_: Interpolant.prototype.copySampleValue_,
34417
34418} );
34419
34420/**
34421 * Fast and simple cubic spline interpolant.
34422 *
34423 * It was derived from a Hermitian construction setting the first derivative
34424 * at each sample position to the linear slope between neighboring positions
34425 * over their parameter interval.
34426 *
34427 * @author tschw
34428 */
34429
34430function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34431
34432	Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34433
34434	this._weightPrev = - 0;
34435	this._offsetPrev = - 0;
34436	this._weightNext = - 0;
34437	this._offsetNext = - 0;
34438
34439}
34440
34441CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34442
34443	constructor: CubicInterpolant,
34444
34445	DefaultSettings_: {
34446
34447		endingStart: ZeroCurvatureEnding,
34448		endingEnd: ZeroCurvatureEnding
34449
34450	},
34451
34452	intervalChanged_: function ( i1, t0, t1 ) {
34453
34454		var pp = this.parameterPositions,
34455			iPrev = i1 - 2,
34456			iNext = i1 + 1,
34457
34458			tPrev = pp[ iPrev ],
34459			tNext = pp[ iNext ];
34460
34461		if ( tPrev === undefined ) {
34462
34463			switch ( this.getSettings_().endingStart ) {
34464
34465				case ZeroSlopeEnding:
34466
34467					// f'(t0) = 0
34468					iPrev = i1;
34469					tPrev = 2 * t0 - t1;
34470
34471					break;
34472
34473				case WrapAroundEnding:
34474
34475					// use the other end of the curve
34476					iPrev = pp.length - 2;
34477					tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
34478
34479					break;
34480
34481				default: // ZeroCurvatureEnding
34482
34483					// f''(t0) = 0 a.k.a. Natural Spline
34484					iPrev = i1;
34485					tPrev = t1;
34486
34487			}
34488
34489		}
34490
34491		if ( tNext === undefined ) {
34492
34493			switch ( this.getSettings_().endingEnd ) {
34494
34495				case ZeroSlopeEnding:
34496
34497					// f'(tN) = 0
34498					iNext = i1;
34499					tNext = 2 * t1 - t0;
34500
34501					break;
34502
34503				case WrapAroundEnding:
34504
34505					// use the other end of the curve
34506					iNext = 1;
34507					tNext = t1 + pp[ 1 ] - pp[ 0 ];
34508
34509					break;
34510
34511				default: // ZeroCurvatureEnding
34512
34513					// f''(tN) = 0, a.k.a. Natural Spline
34514					iNext = i1 - 1;
34515					tNext = t0;
34516
34517			}
34518
34519		}
34520
34521		var halfDt = ( t1 - t0 ) * 0.5,
34522			stride = this.valueSize;
34523
34524		this._weightPrev = halfDt / ( t0 - tPrev );
34525		this._weightNext = halfDt / ( tNext - t1 );
34526		this._offsetPrev = iPrev * stride;
34527		this._offsetNext = iNext * stride;
34528
34529	},
34530
34531	interpolate_: function ( i1, t0, t, t1 ) {
34532
34533		var result = this.resultBuffer,
34534			values = this.sampleValues,
34535			stride = this.valueSize,
34536
34537			o1 = i1 * stride,		o0 = o1 - stride,
34538			oP = this._offsetPrev, 	oN = this._offsetNext,
34539			wP = this._weightPrev,	wN = this._weightNext,
34540
34541			p = ( t - t0 ) / ( t1 - t0 ),
34542			pp = p * p,
34543			ppp = pp * p;
34544
34545		// evaluate polynomials
34546
34547		var sP = - wP * ppp + 2 * wP * pp - wP * p;
34548		var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
34549		var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
34550		var sN = wN * ppp - wN * pp;
34551
34552		// combine data linearly
34553
34554		for ( var i = 0; i !== stride; ++ i ) {
34555
34556			result[ i ] =
34557					sP * values[ oP + i ] +
34558					s0 * values[ o0 + i ] +
34559					s1 * values[ o1 + i ] +
34560					sN * values[ oN + i ];
34561
34562		}
34563
34564		return result;
34565
34566	}
34567
34568} );
34569
34570/**
34571 * @author tschw
34572 */
34573
34574function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34575
34576	Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34577
34578}
34579
34580LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34581
34582	constructor: LinearInterpolant,
34583
34584	interpolate_: function ( i1, t0, t, t1 ) {
34585
34586		var result = this.resultBuffer,
34587			values = this.sampleValues,
34588			stride = this.valueSize,
34589
34590			offset1 = i1 * stride,
34591			offset0 = offset1 - stride,
34592
34593			weight1 = ( t - t0 ) / ( t1 - t0 ),
34594			weight0 = 1 - weight1;
34595
34596		for ( var i = 0; i !== stride; ++ i ) {
34597
34598			result[ i ] =
34599					values[ offset0 + i ] * weight0 +
34600					values[ offset1 + i ] * weight1;
34601
34602		}
34603
34604		return result;
34605
34606	}
34607
34608} );
34609
34610/**
34611 *
34612 * Interpolant that evaluates to the sample value at the position preceeding
34613 * the parameter.
34614 *
34615 * @author tschw
34616 */
34617
34618function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
34619
34620	Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
34621
34622}
34623
34624DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
34625
34626	constructor: DiscreteInterpolant,
34627
34628	interpolate_: function ( i1 /*, t0, t, t1 */ ) {
34629
34630		return this.copySampleValue_( i1 - 1 );
34631
34632	}
34633
34634} );
34635
34636/**
34637 *
34638 * A timed sequence of keyframes for a specific property.
34639 *
34640 *
34641 * @author Ben Houston / http://clara.io/
34642 * @author David Sarno / http://lighthaus.us/
34643 * @author tschw
34644 */
34645
34646function KeyframeTrack( name, times, values, interpolation ) {
34647
34648	if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
34649	if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
34650
34651	this.name = name;
34652
34653	this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
34654	this.values = AnimationUtils.convertArray( values, this.ValueBufferType );
34655
34656	this.setInterpolation( interpolation || this.DefaultInterpolation );
34657
34658}
34659
34660// Static methods
34661
34662Object.assign( KeyframeTrack, {
34663
34664	// Serialization (in static context, because of constructor invocation
34665	// and automatic invocation of .toJSON):
34666
34667	toJSON: function ( track ) {
34668
34669		var trackType = track.constructor;
34670
34671		var json;
34672
34673		// derived classes can define a static toJSON method
34674		if ( trackType.toJSON !== undefined ) {
34675
34676			json = trackType.toJSON( track );
34677
34678		} else {
34679
34680			// by default, we assume the data can be serialized as-is
34681			json = {
34682
34683				'name': track.name,
34684				'times': AnimationUtils.convertArray( track.times, Array ),
34685				'values': AnimationUtils.convertArray( track.values, Array )
34686
34687			};
34688
34689			var interpolation = track.getInterpolation();
34690
34691			if ( interpolation !== track.DefaultInterpolation ) {
34692
34693				json.interpolation = interpolation;
34694
34695			}
34696
34697		}
34698
34699		json.type = track.ValueTypeName; // mandatory
34700
34701		return json;
34702
34703	}
34704
34705} );
34706
34707Object.assign( KeyframeTrack.prototype, {
34708
34709	constructor: KeyframeTrack,
34710
34711	TimeBufferType: Float32Array,
34712
34713	ValueBufferType: Float32Array,
34714
34715	DefaultInterpolation: InterpolateLinear,
34716
34717	InterpolantFactoryMethodDiscrete: function ( result ) {
34718
34719		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
34720
34721	},
34722
34723	InterpolantFactoryMethodLinear: function ( result ) {
34724
34725		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
34726
34727	},
34728
34729	InterpolantFactoryMethodSmooth: function ( result ) {
34730
34731		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
34732
34733	},
34734
34735	setInterpolation: function ( interpolation ) {
34736
34737		var factoryMethod;
34738
34739		switch ( interpolation ) {
34740
34741			case InterpolateDiscrete:
34742
34743				factoryMethod = this.InterpolantFactoryMethodDiscrete;
34744
34745				break;
34746
34747			case InterpolateLinear:
34748
34749				factoryMethod = this.InterpolantFactoryMethodLinear;
34750
34751				break;
34752
34753			case InterpolateSmooth:
34754
34755				factoryMethod = this.InterpolantFactoryMethodSmooth;
34756
34757				break;
34758
34759		}
34760
34761		if ( factoryMethod === undefined ) {
34762
34763			var message = "unsupported interpolation for " +
34764				this.ValueTypeName + " keyframe track named " + this.name;
34765
34766			if ( this.createInterpolant === undefined ) {
34767
34768				// fall back to default, unless the default itself is messed up
34769				if ( interpolation !== this.DefaultInterpolation ) {
34770
34771					this.setInterpolation( this.DefaultInterpolation );
34772
34773				} else {
34774
34775					throw new Error( message ); // fatal, in this case
34776
34777				}
34778
34779			}
34780
34781			console.warn( 'THREE.KeyframeTrack:', message );
34782			return this;
34783
34784		}
34785
34786		this.createInterpolant = factoryMethod;
34787
34788		return this;
34789
34790	},
34791
34792	getInterpolation: function () {
34793
34794		switch ( this.createInterpolant ) {
34795
34796			case this.InterpolantFactoryMethodDiscrete:
34797
34798				return InterpolateDiscrete;
34799
34800			case this.InterpolantFactoryMethodLinear:
34801
34802				return InterpolateLinear;
34803
34804			case this.InterpolantFactoryMethodSmooth:
34805
34806				return InterpolateSmooth;
34807
34808		}
34809
34810	},
34811
34812	getValueSize: function () {
34813
34814		return this.values.length / this.times.length;
34815
34816	},
34817
34818	// move all keyframes either forwards or backwards in time
34819	shift: function ( timeOffset ) {
34820
34821		if ( timeOffset !== 0.0 ) {
34822
34823			var times = this.times;
34824
34825			for ( var i = 0, n = times.length; i !== n; ++ i ) {
34826
34827				times[ i ] += timeOffset;
34828
34829			}
34830
34831		}
34832
34833		return this;
34834
34835	},
34836
34837	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
34838	scale: function ( timeScale ) {
34839
34840		if ( timeScale !== 1.0 ) {
34841
34842			var times = this.times;
34843
34844			for ( var i = 0, n = times.length; i !== n; ++ i ) {
34845
34846				times[ i ] *= timeScale;
34847
34848			}
34849
34850		}
34851
34852		return this;
34853
34854	},
34855
34856	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
34857	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
34858	trim: function ( startTime, endTime ) {
34859
34860		var times = this.times,
34861			nKeys = times.length,
34862			from = 0,
34863			to = nKeys - 1;
34864
34865		while ( from !== nKeys && times[ from ] < startTime ) {
34866
34867			++ from;
34868
34869		}
34870
34871		while ( to !== - 1 && times[ to ] > endTime ) {
34872
34873			-- to;
34874
34875		}
34876
34877		++ to; // inclusive -> exclusive bound
34878
34879		if ( from !== 0 || to !== nKeys ) {
34880
34881			// empty tracks are forbidden, so keep at least one keyframe
34882			if ( from >= to ) {
34883
34884				to = Math.max( to, 1 );
34885				from = to - 1;
34886
34887			}
34888
34889			var stride = this.getValueSize();
34890			this.times = AnimationUtils.arraySlice( times, from, to );
34891			this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );
34892
34893		}
34894
34895		return this;
34896
34897	},
34898
34899	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
34900	validate: function () {
34901
34902		var valid = true;
34903
34904		var valueSize = this.getValueSize();
34905		if ( valueSize - Math.floor( valueSize ) !== 0 ) {
34906
34907			console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
34908			valid = false;
34909
34910		}
34911
34912		var times = this.times,
34913			values = this.values,
34914
34915			nKeys = times.length;
34916
34917		if ( nKeys === 0 ) {
34918
34919			console.error( 'THREE.KeyframeTrack: Track is empty.', this );
34920			valid = false;
34921
34922		}
34923
34924		var prevTime = null;
34925
34926		for ( var i = 0; i !== nKeys; i ++ ) {
34927
34928			var currTime = times[ i ];
34929
34930			if ( typeof currTime === 'number' && isNaN( currTime ) ) {
34931
34932				console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
34933				valid = false;
34934				break;
34935
34936			}
34937
34938			if ( prevTime !== null && prevTime > currTime ) {
34939
34940				console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
34941				valid = false;
34942				break;
34943
34944			}
34945
34946			prevTime = currTime;
34947
34948		}
34949
34950		if ( values !== undefined ) {
34951
34952			if ( AnimationUtils.isTypedArray( values ) ) {
34953
34954				for ( var i = 0, n = values.length; i !== n; ++ i ) {
34955
34956					var value = values[ i ];
34957
34958					if ( isNaN( value ) ) {
34959
34960						console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
34961						valid = false;
34962						break;
34963
34964					}
34965
34966				}
34967
34968			}
34969
34970		}
34971
34972		return valid;
34973
34974	},
34975
34976	// removes equivalent sequential keys as common in morph target sequences
34977	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
34978	optimize: function () {
34979
34980		// times or values may be shared with other tracks, so overwriting is unsafe
34981		var times = AnimationUtils.arraySlice( this.times ),
34982			values = AnimationUtils.arraySlice( this.values ),
34983			stride = this.getValueSize(),
34984
34985			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
34986
34987			writeIndex = 1,
34988			lastIndex = times.length - 1;
34989
34990		for ( var i = 1; i < lastIndex; ++ i ) {
34991
34992			var keep = false;
34993
34994			var time = times[ i ];
34995			var timeNext = times[ i + 1 ];
34996
34997			// remove adjacent keyframes scheduled at the same time
34998
34999			if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {
35000
35001				if ( ! smoothInterpolation ) {
35002
35003					// remove unnecessary keyframes same as their neighbors
35004
35005					var offset = i * stride,
35006						offsetP = offset - stride,
35007						offsetN = offset + stride;
35008
35009					for ( var j = 0; j !== stride; ++ j ) {
35010
35011						var value = values[ offset + j ];
35012
35013						if ( value !== values[ offsetP + j ] ||
35014							value !== values[ offsetN + j ] ) {
35015
35016							keep = true;
35017							break;
35018
35019						}
35020
35021					}
35022
35023				} else {
35024
35025					keep = true;
35026
35027				}
35028
35029			}
35030
35031			// in-place compaction
35032
35033			if ( keep ) {
35034
35035				if ( i !== writeIndex ) {
35036
35037					times[ writeIndex ] = times[ i ];
35038
35039					var readOffset = i * stride,
35040						writeOffset = writeIndex * stride;
35041
35042					for ( var j = 0; j !== stride; ++ j ) {
35043
35044						values[ writeOffset + j ] = values[ readOffset + j ];
35045
35046					}
35047
35048				}
35049
35050				++ writeIndex;
35051
35052			}
35053
35054		}
35055
35056		// flush last keyframe (compaction looks ahead)
35057
35058		if ( lastIndex > 0 ) {
35059
35060			times[ writeIndex ] = times[ lastIndex ];
35061
35062			for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
35063
35064				values[ writeOffset + j ] = values[ readOffset + j ];
35065
35066			}
35067
35068			++ writeIndex;
35069
35070		}
35071
35072		if ( writeIndex !== times.length ) {
35073
35074			this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
35075			this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );
35076
35077		} else {
35078
35079			this.times = times;
35080			this.values = values;
35081
35082		}
35083
35084		return this;
35085
35086	},
35087
35088	clone: function () {
35089
35090		var times = AnimationUtils.arraySlice( this.times, 0 );
35091		var values = AnimationUtils.arraySlice( this.values, 0 );
35092
35093		var TypedKeyframeTrack = this.constructor;
35094		var track = new TypedKeyframeTrack( this.name, times, values );
35095
35096		// Interpolant argument to constructor is not saved, so copy the factory method directly.
35097		track.createInterpolant = this.createInterpolant;
35098
35099		return track;
35100
35101	}
35102
35103} );
35104
35105/**
35106 *
35107 * A Track of Boolean keyframe values.
35108 *
35109 *
35110 * @author Ben Houston / http://clara.io/
35111 * @author David Sarno / http://lighthaus.us/
35112 * @author tschw
35113 */
35114
35115function BooleanKeyframeTrack( name, times, values ) {
35116
35117	KeyframeTrack.call( this, name, times, values );
35118
35119}
35120
35121BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35122
35123	constructor: BooleanKeyframeTrack,
35124
35125	ValueTypeName: 'bool',
35126	ValueBufferType: Array,
35127
35128	DefaultInterpolation: InterpolateDiscrete,
35129
35130	InterpolantFactoryMethodLinear: undefined,
35131	InterpolantFactoryMethodSmooth: undefined
35132
35133	// Note: Actually this track could have a optimized / compressed
35134	// representation of a single value and a custom interpolant that
35135	// computes "firstValue ^ isOdd( index )".
35136
35137} );
35138
35139/**
35140 *
35141 * A Track of keyframe values that represent color.
35142 *
35143 *
35144 * @author Ben Houston / http://clara.io/
35145 * @author David Sarno / http://lighthaus.us/
35146 * @author tschw
35147 */
35148
35149function ColorKeyframeTrack( name, times, values, interpolation ) {
35150
35151	KeyframeTrack.call( this, name, times, values, interpolation );
35152
35153}
35154
35155ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35156
35157	constructor: ColorKeyframeTrack,
35158
35159	ValueTypeName: 'color'
35160
35161	// ValueBufferType is inherited
35162
35163	// DefaultInterpolation is inherited
35164
35165	// Note: Very basic implementation and nothing special yet.
35166	// However, this is the place for color space parameterization.
35167
35168} );
35169
35170/**
35171 *
35172 * A Track of numeric keyframe values.
35173 *
35174 * @author Ben Houston / http://clara.io/
35175 * @author David Sarno / http://lighthaus.us/
35176 * @author tschw
35177 */
35178
35179function NumberKeyframeTrack( name, times, values, interpolation ) {
35180
35181	KeyframeTrack.call( this, name, times, values, interpolation );
35182
35183}
35184
35185NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35186
35187	constructor: NumberKeyframeTrack,
35188
35189	ValueTypeName: 'number'
35190
35191	// ValueBufferType is inherited
35192
35193	// DefaultInterpolation is inherited
35194
35195} );
35196
35197/**
35198 * Spherical linear unit quaternion interpolant.
35199 *
35200 * @author tschw
35201 */
35202
35203function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
35204
35205	Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
35206
35207}
35208
35209QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {
35210
35211	constructor: QuaternionLinearInterpolant,
35212
35213	interpolate_: function ( i1, t0, t, t1 ) {
35214
35215		var result = this.resultBuffer,
35216			values = this.sampleValues,
35217			stride = this.valueSize,
35218
35219			offset = i1 * stride,
35220
35221			alpha = ( t - t0 ) / ( t1 - t0 );
35222
35223		for ( var end = offset + stride; offset !== end; offset += 4 ) {
35224
35225			Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
35226
35227		}
35228
35229		return result;
35230
35231	}
35232
35233} );
35234
35235/**
35236 *
35237 * A Track of quaternion keyframe values.
35238 *
35239 * @author Ben Houston / http://clara.io/
35240 * @author David Sarno / http://lighthaus.us/
35241 * @author tschw
35242 */
35243
35244function QuaternionKeyframeTrack( name, times, values, interpolation ) {
35245
35246	KeyframeTrack.call( this, name, times, values, interpolation );
35247
35248}
35249
35250QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35251
35252	constructor: QuaternionKeyframeTrack,
35253
35254	ValueTypeName: 'quaternion',
35255
35256	// ValueBufferType is inherited
35257
35258	DefaultInterpolation: InterpolateLinear,
35259
35260	InterpolantFactoryMethodLinear: function ( result ) {
35261
35262		return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
35263
35264	},
35265
35266	InterpolantFactoryMethodSmooth: undefined // not yet implemented
35267
35268} );
35269
35270/**
35271 *
35272 * A Track that interpolates Strings
35273 *
35274 *
35275 * @author Ben Houston / http://clara.io/
35276 * @author David Sarno / http://lighthaus.us/
35277 * @author tschw
35278 */
35279
35280function StringKeyframeTrack( name, times, values, interpolation ) {
35281
35282	KeyframeTrack.call( this, name, times, values, interpolation );
35283
35284}
35285
35286StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35287
35288	constructor: StringKeyframeTrack,
35289
35290	ValueTypeName: 'string',
35291	ValueBufferType: Array,
35292
35293	DefaultInterpolation: InterpolateDiscrete,
35294
35295	InterpolantFactoryMethodLinear: undefined,
35296
35297	InterpolantFactoryMethodSmooth: undefined
35298
35299} );
35300
35301/**
35302 *
35303 * A Track of vectored keyframe values.
35304 *
35305 *
35306 * @author Ben Houston / http://clara.io/
35307 * @author David Sarno / http://lighthaus.us/
35308 * @author tschw
35309 */
35310
35311function VectorKeyframeTrack( name, times, values, interpolation ) {
35312
35313	KeyframeTrack.call( this, name, times, values, interpolation );
35314
35315}
35316
35317VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {
35318
35319	constructor: VectorKeyframeTrack,
35320
35321	ValueTypeName: 'vector'
35322
35323	// ValueBufferType is inherited
35324
35325	// DefaultInterpolation is inherited
35326
35327} );
35328
35329/**
35330 *
35331 * Reusable set of Tracks that represent an animation.
35332 *
35333 * @author Ben Houston / http://clara.io/
35334 * @author David Sarno / http://lighthaus.us/
35335 */
35336
35337function AnimationClip( name, duration, tracks, blendMode ) {
35338
35339	this.name = name;
35340	this.tracks = tracks;
35341	this.duration = ( duration !== undefined ) ? duration : - 1;
35342	this.blendMode = ( blendMode !== undefined ) ? blendMode : NormalAnimationBlendMode;
35343
35344	this.uuid = MathUtils.generateUUID();
35345
35346	// this means it should figure out its duration by scanning the tracks
35347	if ( this.duration < 0 ) {
35348
35349		this.resetDuration();
35350
35351	}
35352
35353}
35354
35355function getTrackTypeForValueTypeName( typeName ) {
35356
35357	switch ( typeName.toLowerCase() ) {
35358
35359		case 'scalar':
35360		case 'double':
35361		case 'float':
35362		case 'number':
35363		case 'integer':
35364
35365			return NumberKeyframeTrack;
35366
35367		case 'vector':
35368		case 'vector2':
35369		case 'vector3':
35370		case 'vector4':
35371
35372			return VectorKeyframeTrack;
35373
35374		case 'color':
35375
35376			return ColorKeyframeTrack;
35377
35378		case 'quaternion':
35379
35380			return QuaternionKeyframeTrack;
35381
35382		case 'bool':
35383		case 'boolean':
35384
35385			return BooleanKeyframeTrack;
35386
35387		case 'string':
35388
35389			return StringKeyframeTrack;
35390
35391	}
35392
35393	throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
35394
35395}
35396
35397function parseKeyframeTrack( json ) {
35398
35399	if ( json.type === undefined ) {
35400
35401		throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
35402
35403	}
35404
35405	var trackType = getTrackTypeForValueTypeName( json.type );
35406
35407	if ( json.times === undefined ) {
35408
35409		var times = [], values = [];
35410
35411		AnimationUtils.flattenJSON( json.keys, times, values, 'value' );
35412
35413		json.times = times;
35414		json.values = values;
35415
35416	}
35417
35418	// derived classes can define a static parse method
35419	if ( trackType.parse !== undefined ) {
35420
35421		return trackType.parse( json );
35422
35423	} else {
35424
35425		// by default, we assume a constructor compatible with the base
35426		return new trackType( json.name, json.times, json.values, json.interpolation );
35427
35428	}
35429
35430}
35431
35432Object.assign( AnimationClip, {
35433
35434	parse: function ( json ) {
35435
35436		var tracks = [],
35437			jsonTracks = json.tracks,
35438			frameTime = 1.0 / ( json.fps || 1.0 );
35439
35440		for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {
35441
35442			tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
35443
35444		}
35445
35446		return new AnimationClip( json.name, json.duration, tracks, json.blendMode );
35447
35448	},
35449
35450	toJSON: function ( clip ) {
35451
35452		var tracks = [],
35453			clipTracks = clip.tracks;
35454
35455		var json = {
35456
35457			'name': clip.name,
35458			'duration': clip.duration,
35459			'tracks': tracks,
35460			'uuid': clip.uuid,
35461			'blendMode': clip.blendMode
35462
35463		};
35464
35465		for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {
35466
35467			tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
35468
35469		}
35470
35471		return json;
35472
35473	},
35474
35475	CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {
35476
35477		var numMorphTargets = morphTargetSequence.length;
35478		var tracks = [];
35479
35480		for ( var i = 0; i < numMorphTargets; i ++ ) {
35481
35482			var times = [];
35483			var values = [];
35484
35485			times.push(
35486				( i + numMorphTargets - 1 ) % numMorphTargets,
35487				i,
35488				( i + 1 ) % numMorphTargets );
35489
35490			values.push( 0, 1, 0 );
35491
35492			var order = AnimationUtils.getKeyframeOrder( times );
35493			times = AnimationUtils.sortedArray( times, 1, order );
35494			values = AnimationUtils.sortedArray( values, 1, order );
35495
35496			// if there is a key at the first frame, duplicate it as the
35497			// last frame as well for perfect loop.
35498			if ( ! noLoop && times[ 0 ] === 0 ) {
35499
35500				times.push( numMorphTargets );
35501				values.push( values[ 0 ] );
35502
35503			}
35504
35505			tracks.push(
35506				new NumberKeyframeTrack(
35507					'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
35508					times, values
35509				).scale( 1.0 / fps ) );
35510
35511		}
35512
35513		return new AnimationClip( name, - 1, tracks );
35514
35515	},
35516
35517	findByName: function ( objectOrClipArray, name ) {
35518
35519		var clipArray = objectOrClipArray;
35520
35521		if ( ! Array.isArray( objectOrClipArray ) ) {
35522
35523			var o = objectOrClipArray;
35524			clipArray = o.geometry && o.geometry.animations || o.animations;
35525
35526		}
35527
35528		for ( var i = 0; i < clipArray.length; i ++ ) {
35529
35530			if ( clipArray[ i ].name === name ) {
35531
35532				return clipArray[ i ];
35533
35534			}
35535
35536		}
35537
35538		return null;
35539
35540	},
35541
35542	CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {
35543
35544		var animationToMorphTargets = {};
35545
35546		// tested with https://regex101.com/ on trick sequences
35547		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
35548		var pattern = /^([\w-]*?)([\d]+)$/;
35549
35550		// sort morph target names into animation groups based
35551		// patterns like Walk_001, Walk_002, Run_001, Run_002
35552		for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
35553
35554			var morphTarget = morphTargets[ i ];
35555			var parts = morphTarget.name.match( pattern );
35556
35557			if ( parts && parts.length > 1 ) {
35558
35559				var name = parts[ 1 ];
35560
35561				var animationMorphTargets = animationToMorphTargets[ name ];
35562				if ( ! animationMorphTargets ) {
35563
35564					animationToMorphTargets[ name ] = animationMorphTargets = [];
35565
35566				}
35567
35568				animationMorphTargets.push( morphTarget );
35569
35570			}
35571
35572		}
35573
35574		var clips = [];
35575
35576		for ( var name in animationToMorphTargets ) {
35577
35578			clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
35579
35580		}
35581
35582		return clips;
35583
35584	},
35585
35586	// parse the animation.hierarchy format
35587	parseAnimation: function ( animation, bones ) {
35588
35589		if ( ! animation ) {
35590
35591			console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
35592			return null;
35593
35594		}
35595
35596		var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
35597
35598			// only return track if there are actually keys.
35599			if ( animationKeys.length !== 0 ) {
35600
35601				var times = [];
35602				var values = [];
35603
35604				AnimationUtils.flattenJSON( animationKeys, times, values, propertyName );
35605
35606				// empty keys are filtered out, so check again
35607				if ( times.length !== 0 ) {
35608
35609					destTracks.push( new trackType( trackName, times, values ) );
35610
35611				}
35612
35613			}
35614
35615		};
35616
35617		var tracks = [];
35618
35619		var clipName = animation.name || 'default';
35620		// automatic length determination in AnimationClip.
35621		var duration = animation.length || - 1;
35622		var fps = animation.fps || 30;
35623		var blendMode = animation.blendMode;
35624
35625		var hierarchyTracks = animation.hierarchy || [];
35626
35627		for ( var h = 0; h < hierarchyTracks.length; h ++ ) {
35628
35629			var animationKeys = hierarchyTracks[ h ].keys;
35630
35631			// skip empty tracks
35632			if ( ! animationKeys || animationKeys.length === 0 ) continue;
35633
35634			// process morph targets
35635			if ( animationKeys[ 0 ].morphTargets ) {
35636
35637				// figure out all morph targets used in this track
35638				var morphTargetNames = {};
35639
35640				for ( var k = 0; k < animationKeys.length; k ++ ) {
35641
35642					if ( animationKeys[ k ].morphTargets ) {
35643
35644						for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
35645
35646							morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
35647
35648						}
35649
35650					}
35651
35652				}
35653
35654				// create a track for each morph target with all zero
35655				// morphTargetInfluences except for the keys in which
35656				// the morphTarget is named.
35657				for ( var morphTargetName in morphTargetNames ) {
35658
35659					var times = [];
35660					var values = [];
35661
35662					for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
35663
35664						var animationKey = animationKeys[ k ];
35665
35666						times.push( animationKey.time );
35667						values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
35668
35669					}
35670
35671					tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
35672
35673				}
35674
35675				duration = morphTargetNames.length * ( fps || 1.0 );
35676
35677			} else {
35678
35679				// ...assume skeletal animation
35680
35681				var boneName = '.bones[' + bones[ h ].name + ']';
35682
35683				addNonemptyTrack(
35684					VectorKeyframeTrack, boneName + '.position',
35685					animationKeys, 'pos', tracks );
35686
35687				addNonemptyTrack(
35688					QuaternionKeyframeTrack, boneName + '.quaternion',
35689					animationKeys, 'rot', tracks );
35690
35691				addNonemptyTrack(
35692					VectorKeyframeTrack, boneName + '.scale',
35693					animationKeys, 'scl', tracks );
35694
35695			}
35696
35697		}
35698
35699		if ( tracks.length === 0 ) {
35700
35701			return null;
35702
35703		}
35704
35705		var clip = new AnimationClip( clipName, duration, tracks, blendMode );
35706
35707		return clip;
35708
35709	}
35710
35711} );
35712
35713Object.assign( AnimationClip.prototype, {
35714
35715	resetDuration: function () {
35716
35717		var tracks = this.tracks, duration = 0;
35718
35719		for ( var i = 0, n = tracks.length; i !== n; ++ i ) {
35720
35721			var track = this.tracks[ i ];
35722
35723			duration = Math.max( duration, track.times[ track.times.length - 1 ] );
35724
35725		}
35726
35727		this.duration = duration;
35728
35729		return this;
35730
35731	},
35732
35733	trim: function () {
35734
35735		for ( var i = 0; i < this.tracks.length; i ++ ) {
35736
35737			this.tracks[ i ].trim( 0, this.duration );
35738
35739		}
35740
35741		return this;
35742
35743	},
35744
35745	validate: function () {
35746
35747		var valid = true;
35748
35749		for ( var i = 0; i < this.tracks.length; i ++ ) {
35750
35751			valid = valid && this.tracks[ i ].validate();
35752
35753		}
35754
35755		return valid;
35756
35757	},
35758
35759	optimize: function () {
35760
35761		for ( var i = 0; i < this.tracks.length; i ++ ) {
35762
35763			this.tracks[ i ].optimize();
35764
35765		}
35766
35767		return this;
35768
35769	},
35770
35771	clone: function () {
35772
35773		var tracks = [];
35774
35775		for ( var i = 0; i < this.tracks.length; i ++ ) {
35776
35777			tracks.push( this.tracks[ i ].clone() );
35778
35779		}
35780
35781		return new AnimationClip( this.name, this.duration, tracks, this.blendMode );
35782
35783	}
35784
35785} );
35786
35787/**
35788 * @author mrdoob / http://mrdoob.com/
35789 */
35790
35791var Cache = {
35792
35793	enabled: false,
35794
35795	files: {},
35796
35797	add: function ( key, file ) {
35798
35799		if ( this.enabled === false ) return;
35800
35801		// console.log( 'THREE.Cache', 'Adding key:', key );
35802
35803		this.files[ key ] = file;
35804
35805	},
35806
35807	get: function ( key ) {
35808
35809		if ( this.enabled === false ) return;
35810
35811		// console.log( 'THREE.Cache', 'Checking key:', key );
35812
35813		return this.files[ key ];
35814
35815	},
35816
35817	remove: function ( key ) {
35818
35819		delete this.files[ key ];
35820
35821	},
35822
35823	clear: function () {
35824
35825		this.files = {};
35826
35827	}
35828
35829};
35830
35831/**
35832 * @author mrdoob / http://mrdoob.com/
35833 */
35834
35835function LoadingManager( onLoad, onProgress, onError ) {
35836
35837	var scope = this;
35838
35839	var isLoading = false;
35840	var itemsLoaded = 0;
35841	var itemsTotal = 0;
35842	var urlModifier = undefined;
35843	var handlers = [];
35844
35845	// Refer to #5689 for the reason why we don't set .onStart
35846	// in the constructor
35847
35848	this.onStart = undefined;
35849	this.onLoad = onLoad;
35850	this.onProgress = onProgress;
35851	this.onError = onError;
35852
35853	this.itemStart = function ( url ) {
35854
35855		itemsTotal ++;
35856
35857		if ( isLoading === false ) {
35858
35859			if ( scope.onStart !== undefined ) {
35860
35861				scope.onStart( url, itemsLoaded, itemsTotal );
35862
35863			}
35864
35865		}
35866
35867		isLoading = true;
35868
35869	};
35870
35871	this.itemEnd = function ( url ) {
35872
35873		itemsLoaded ++;
35874
35875		if ( scope.onProgress !== undefined ) {
35876
35877			scope.onProgress( url, itemsLoaded, itemsTotal );
35878
35879		}
35880
35881		if ( itemsLoaded === itemsTotal ) {
35882
35883			isLoading = false;
35884
35885			if ( scope.onLoad !== undefined ) {
35886
35887				scope.onLoad();
35888
35889			}
35890
35891		}
35892
35893	};
35894
35895	this.itemError = function ( url ) {
35896
35897		if ( scope.onError !== undefined ) {
35898
35899			scope.onError( url );
35900
35901		}
35902
35903	};
35904
35905	this.resolveURL = function ( url ) {
35906
35907		if ( urlModifier ) {
35908
35909			return urlModifier( url );
35910
35911		}
35912
35913		return url;
35914
35915	};
35916
35917	this.setURLModifier = function ( transform ) {
35918
35919		urlModifier = transform;
35920
35921		return this;
35922
35923	};
35924
35925	this.addHandler = function ( regex, loader ) {
35926
35927		handlers.push( regex, loader );
35928
35929		return this;
35930
35931	};
35932
35933	this.removeHandler = function ( regex ) {
35934
35935		var index = handlers.indexOf( regex );
35936
35937		if ( index !== - 1 ) {
35938
35939			handlers.splice( index, 2 );
35940
35941		}
35942
35943		return this;
35944
35945	};
35946
35947	this.getHandler = function ( file ) {
35948
35949		for ( var i = 0, l = handlers.length; i < l; i += 2 ) {
35950
35951			var regex = handlers[ i ];
35952			var loader = handlers[ i + 1 ];
35953
35954			if ( regex.global ) regex.lastIndex = 0; // see #17920
35955
35956			if ( regex.test( file ) ) {
35957
35958				return loader;
35959
35960			}
35961
35962		}
35963
35964		return null;
35965
35966	};
35967
35968}
35969
35970var DefaultLoadingManager = new LoadingManager();
35971
35972/**
35973 * @author alteredq / http://alteredqualia.com/
35974 */
35975
35976function Loader( manager ) {
35977
35978	this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
35979
35980	this.crossOrigin = 'anonymous';
35981	this.path = '';
35982	this.resourcePath = '';
35983
35984}
35985
35986Object.assign( Loader.prototype, {
35987
35988	load: function ( /* url, onLoad, onProgress, onError */ ) {},
35989
35990	loadAsync: function ( url, onProgress ) {
35991
35992		var scope = this;
35993
35994		return new Promise( function ( resolve, reject ) {
35995
35996			scope.load( url, resolve, onProgress, reject );
35997
35998		} );
35999
36000	},
36001
36002	parse: function ( /* data */ ) {},
36003
36004	setCrossOrigin: function ( crossOrigin ) {
36005
36006		this.crossOrigin = crossOrigin;
36007		return this;
36008
36009	},
36010
36011	setPath: function ( path ) {
36012
36013		this.path = path;
36014		return this;
36015
36016	},
36017
36018	setResourcePath: function ( resourcePath ) {
36019
36020		this.resourcePath = resourcePath;
36021		return this;
36022
36023	}
36024
36025} );
36026
36027/**
36028 * @author mrdoob / http://mrdoob.com/
36029 */
36030
36031var loading = {};
36032
36033function FileLoader( manager ) {
36034
36035	Loader.call( this, manager );
36036
36037}
36038
36039FileLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36040
36041	constructor: FileLoader,
36042
36043	load: function ( url, onLoad, onProgress, onError ) {
36044
36045		if ( url === undefined ) url = '';
36046
36047		if ( this.path !== undefined ) url = this.path + url;
36048
36049		url = this.manager.resolveURL( url );
36050
36051		var scope = this;
36052
36053		var cached = Cache.get( url );
36054
36055		if ( cached !== undefined ) {
36056
36057			scope.manager.itemStart( url );
36058
36059			setTimeout( function () {
36060
36061				if ( onLoad ) onLoad( cached );
36062
36063				scope.manager.itemEnd( url );
36064
36065			}, 0 );
36066
36067			return cached;
36068
36069		}
36070
36071		// Check if request is duplicate
36072
36073		if ( loading[ url ] !== undefined ) {
36074
36075			loading[ url ].push( {
36076
36077				onLoad: onLoad,
36078				onProgress: onProgress,
36079				onError: onError
36080
36081			} );
36082
36083			return;
36084
36085		}
36086
36087		// Check for data: URI
36088		var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;
36089		var dataUriRegexResult = url.match( dataUriRegex );
36090
36091		// Safari can not handle Data URIs through XMLHttpRequest so process manually
36092		if ( dataUriRegexResult ) {
36093
36094			var mimeType = dataUriRegexResult[ 1 ];
36095			var isBase64 = !! dataUriRegexResult[ 2 ];
36096			var data = dataUriRegexResult[ 3 ];
36097
36098			data = decodeURIComponent( data );
36099
36100			if ( isBase64 ) data = atob( data );
36101
36102			try {
36103
36104				var response;
36105				var responseType = ( this.responseType || '' ).toLowerCase();
36106
36107				switch ( responseType ) {
36108
36109					case 'arraybuffer':
36110					case 'blob':
36111
36112						var view = new Uint8Array( data.length );
36113
36114						for ( var i = 0; i < data.length; i ++ ) {
36115
36116							view[ i ] = data.charCodeAt( i );
36117
36118						}
36119
36120						if ( responseType === 'blob' ) {
36121
36122							response = new Blob( [ view.buffer ], { type: mimeType } );
36123
36124						} else {
36125
36126							response = view.buffer;
36127
36128						}
36129
36130						break;
36131
36132					case 'document':
36133
36134						var parser = new DOMParser();
36135						response = parser.parseFromString( data, mimeType );
36136
36137						break;
36138
36139					case 'json':
36140
36141						response = JSON.parse( data );
36142
36143						break;
36144
36145					default: // 'text' or other
36146
36147						response = data;
36148
36149						break;
36150
36151				}
36152
36153				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
36154				setTimeout( function () {
36155
36156					if ( onLoad ) onLoad( response );
36157
36158					scope.manager.itemEnd( url );
36159
36160				}, 0 );
36161
36162			} catch ( error ) {
36163
36164				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
36165				setTimeout( function () {
36166
36167					if ( onError ) onError( error );
36168
36169					scope.manager.itemError( url );
36170					scope.manager.itemEnd( url );
36171
36172				}, 0 );
36173
36174			}
36175
36176		} else {
36177
36178			// Initialise array for duplicate requests
36179
36180			loading[ url ] = [];
36181
36182			loading[ url ].push( {
36183
36184				onLoad: onLoad,
36185				onProgress: onProgress,
36186				onError: onError
36187
36188			} );
36189
36190			var request = new XMLHttpRequest();
36191
36192			request.open( 'GET', url, true );
36193
36194			request.addEventListener( 'load', function ( event ) {
36195
36196				var response = this.response;
36197
36198				var callbacks = loading[ url ];
36199
36200				delete loading[ url ];
36201
36202				if ( this.status === 200 || this.status === 0 ) {
36203
36204					// Some browsers return HTTP Status 0 when using non-http protocol
36205					// e.g. 'file://' or 'data://'. Handle as success.
36206
36207					if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
36208
36209					// Add to cache only on HTTP success, so that we do not cache
36210					// error response bodies as proper responses to requests.
36211					Cache.add( url, response );
36212
36213					for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
36214
36215						var callback = callbacks[ i ];
36216						if ( callback.onLoad ) callback.onLoad( response );
36217
36218					}
36219
36220					scope.manager.itemEnd( url );
36221
36222				} else {
36223
36224					for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
36225
36226						var callback = callbacks[ i ];
36227						if ( callback.onError ) callback.onError( event );
36228
36229					}
36230
36231					scope.manager.itemError( url );
36232					scope.manager.itemEnd( url );
36233
36234				}
36235
36236			}, false );
36237
36238			request.addEventListener( 'progress', function ( event ) {
36239
36240				var callbacks = loading[ url ];
36241
36242				for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
36243
36244					var callback = callbacks[ i ];
36245					if ( callback.onProgress ) callback.onProgress( event );
36246
36247				}
36248
36249			}, false );
36250
36251			request.addEventListener( 'error', function ( event ) {
36252
36253				var callbacks = loading[ url ];
36254
36255				delete loading[ url ];
36256
36257				for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
36258
36259					var callback = callbacks[ i ];
36260					if ( callback.onError ) callback.onError( event );
36261
36262				}
36263
36264				scope.manager.itemError( url );
36265				scope.manager.itemEnd( url );
36266
36267			}, false );
36268
36269			request.addEventListener( 'abort', function ( event ) {
36270
36271				var callbacks = loading[ url ];
36272
36273				delete loading[ url ];
36274
36275				for ( var i = 0, il = callbacks.length; i < il; i ++ ) {
36276
36277					var callback = callbacks[ i ];
36278					if ( callback.onError ) callback.onError( event );
36279
36280				}
36281
36282				scope.manager.itemError( url );
36283				scope.manager.itemEnd( url );
36284
36285			}, false );
36286
36287			if ( this.responseType !== undefined ) request.responseType = this.responseType;
36288			if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
36289
36290			if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' );
36291
36292			for ( var header in this.requestHeader ) {
36293
36294				request.setRequestHeader( header, this.requestHeader[ header ] );
36295
36296			}
36297
36298			request.send( null );
36299
36300		}
36301
36302		scope.manager.itemStart( url );
36303
36304		return request;
36305
36306	},
36307
36308	setResponseType: function ( value ) {
36309
36310		this.responseType = value;
36311		return this;
36312
36313	},
36314
36315	setWithCredentials: function ( value ) {
36316
36317		this.withCredentials = value;
36318		return this;
36319
36320	},
36321
36322	setMimeType: function ( value ) {
36323
36324		this.mimeType = value;
36325		return this;
36326
36327	},
36328
36329	setRequestHeader: function ( value ) {
36330
36331		this.requestHeader = value;
36332		return this;
36333
36334	}
36335
36336} );
36337
36338/**
36339 * @author bhouston / http://clara.io/
36340 */
36341
36342function AnimationLoader( manager ) {
36343
36344	Loader.call( this, manager );
36345
36346}
36347
36348AnimationLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36349
36350	constructor: AnimationLoader,
36351
36352	load: function ( url, onLoad, onProgress, onError ) {
36353
36354		var scope = this;
36355
36356		var loader = new FileLoader( scope.manager );
36357		loader.setPath( scope.path );
36358		loader.load( url, function ( text ) {
36359
36360			onLoad( scope.parse( JSON.parse( text ) ) );
36361
36362		}, onProgress, onError );
36363
36364	},
36365
36366	parse: function ( json ) {
36367
36368		var animations = [];
36369
36370		for ( var i = 0; i < json.length; i ++ ) {
36371
36372			var clip = AnimationClip.parse( json[ i ] );
36373
36374			animations.push( clip );
36375
36376		}
36377
36378		return animations;
36379
36380	}
36381
36382} );
36383
36384/**
36385 * @author mrdoob / http://mrdoob.com/
36386 *
36387 * Abstract Base class to block based textures loader (dds, pvr, ...)
36388 *
36389 * Sub classes have to implement the parse() method which will be used in load().
36390 */
36391
36392function CompressedTextureLoader( manager ) {
36393
36394	Loader.call( this, manager );
36395
36396}
36397
36398CompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36399
36400	constructor: CompressedTextureLoader,
36401
36402	load: function ( url, onLoad, onProgress, onError ) {
36403
36404		var scope = this;
36405
36406		var images = [];
36407
36408		var texture = new CompressedTexture();
36409		texture.image = images;
36410
36411		var loader = new FileLoader( this.manager );
36412		loader.setPath( this.path );
36413		loader.setResponseType( 'arraybuffer' );
36414
36415		function loadTexture( i ) {
36416
36417			loader.load( url[ i ], function ( buffer ) {
36418
36419				var texDatas = scope.parse( buffer, true );
36420
36421				images[ i ] = {
36422					width: texDatas.width,
36423					height: texDatas.height,
36424					format: texDatas.format,
36425					mipmaps: texDatas.mipmaps
36426				};
36427
36428				loaded += 1;
36429
36430				if ( loaded === 6 ) {
36431
36432					if ( texDatas.mipmapCount === 1 )
36433						texture.minFilter = LinearFilter;
36434
36435					texture.format = texDatas.format;
36436					texture.needsUpdate = true;
36437
36438					if ( onLoad ) onLoad( texture );
36439
36440				}
36441
36442			}, onProgress, onError );
36443
36444		}
36445
36446		if ( Array.isArray( url ) ) {
36447
36448			var loaded = 0;
36449
36450			for ( var i = 0, il = url.length; i < il; ++ i ) {
36451
36452				loadTexture( i );
36453
36454			}
36455
36456		} else {
36457
36458			// compressed cubemap texture stored in a single DDS file
36459
36460			loader.load( url, function ( buffer ) {
36461
36462				var texDatas = scope.parse( buffer, true );
36463
36464				if ( texDatas.isCubemap ) {
36465
36466					var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
36467
36468					for ( var f = 0; f < faces; f ++ ) {
36469
36470						images[ f ] = { mipmaps: [] };
36471
36472						for ( var i = 0; i < texDatas.mipmapCount; i ++ ) {
36473
36474							images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
36475							images[ f ].format = texDatas.format;
36476							images[ f ].width = texDatas.width;
36477							images[ f ].height = texDatas.height;
36478
36479						}
36480
36481					}
36482
36483				} else {
36484
36485					texture.image.width = texDatas.width;
36486					texture.image.height = texDatas.height;
36487					texture.mipmaps = texDatas.mipmaps;
36488
36489				}
36490
36491				if ( texDatas.mipmapCount === 1 ) {
36492
36493					texture.minFilter = LinearFilter;
36494
36495				}
36496
36497				texture.format = texDatas.format;
36498				texture.needsUpdate = true;
36499
36500				if ( onLoad ) onLoad( texture );
36501
36502			}, onProgress, onError );
36503
36504		}
36505
36506		return texture;
36507
36508	}
36509
36510} );
36511
36512/**
36513 * @author Nikos M. / https://github.com/foo123/
36514 *
36515 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
36516 *
36517 * Sub classes have to implement the parse() method which will be used in load().
36518 */
36519
36520function DataTextureLoader( manager ) {
36521
36522	Loader.call( this, manager );
36523
36524}
36525
36526DataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36527
36528	constructor: DataTextureLoader,
36529
36530	load: function ( url, onLoad, onProgress, onError ) {
36531
36532		var scope = this;
36533
36534		var texture = new DataTexture();
36535
36536		var loader = new FileLoader( this.manager );
36537		loader.setResponseType( 'arraybuffer' );
36538		loader.setPath( this.path );
36539		loader.load( url, function ( buffer ) {
36540
36541			var texData = scope.parse( buffer );
36542
36543			if ( ! texData ) return;
36544
36545			if ( texData.image !== undefined ) {
36546
36547				texture.image = texData.image;
36548
36549			} else if ( texData.data !== undefined ) {
36550
36551				texture.image.width = texData.width;
36552				texture.image.height = texData.height;
36553				texture.image.data = texData.data;
36554
36555			}
36556
36557			texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
36558			texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
36559
36560			texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
36561			texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
36562
36563			texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
36564
36565			if ( texData.format !== undefined ) {
36566
36567				texture.format = texData.format;
36568
36569			}
36570
36571			if ( texData.type !== undefined ) {
36572
36573				texture.type = texData.type;
36574
36575			}
36576
36577			if ( texData.mipmaps !== undefined ) {
36578
36579				texture.mipmaps = texData.mipmaps;
36580				texture.minFilter = LinearMipmapLinearFilter; // presumably...
36581
36582			}
36583
36584			if ( texData.mipmapCount === 1 ) {
36585
36586				texture.minFilter = LinearFilter;
36587
36588			}
36589
36590			texture.needsUpdate = true;
36591
36592			if ( onLoad ) onLoad( texture, texData );
36593
36594		}, onProgress, onError );
36595
36596
36597		return texture;
36598
36599	}
36600
36601} );
36602
36603/**
36604 * @author mrdoob / http://mrdoob.com/
36605 */
36606
36607function ImageLoader( manager ) {
36608
36609	Loader.call( this, manager );
36610
36611}
36612
36613ImageLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36614
36615	constructor: ImageLoader,
36616
36617	load: function ( url, onLoad, onProgress, onError ) {
36618
36619		if ( this.path !== undefined ) url = this.path + url;
36620
36621		url = this.manager.resolveURL( url );
36622
36623		var scope = this;
36624
36625		var cached = Cache.get( url );
36626
36627		if ( cached !== undefined ) {
36628
36629			scope.manager.itemStart( url );
36630
36631			setTimeout( function () {
36632
36633				if ( onLoad ) onLoad( cached );
36634
36635				scope.manager.itemEnd( url );
36636
36637			}, 0 );
36638
36639			return cached;
36640
36641		}
36642
36643		var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );
36644
36645		function onImageLoad() {
36646
36647			image.removeEventListener( 'load', onImageLoad, false );
36648			image.removeEventListener( 'error', onImageError, false );
36649
36650			Cache.add( url, this );
36651
36652			if ( onLoad ) onLoad( this );
36653
36654			scope.manager.itemEnd( url );
36655
36656		}
36657
36658		function onImageError( event ) {
36659
36660			image.removeEventListener( 'load', onImageLoad, false );
36661			image.removeEventListener( 'error', onImageError, false );
36662
36663			if ( onError ) onError( event );
36664
36665			scope.manager.itemError( url );
36666			scope.manager.itemEnd( url );
36667
36668		}
36669
36670		image.addEventListener( 'load', onImageLoad, false );
36671		image.addEventListener( 'error', onImageError, false );
36672
36673		if ( url.substr( 0, 5 ) !== 'data:' ) {
36674
36675			if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
36676
36677		}
36678
36679		scope.manager.itemStart( url );
36680
36681		image.src = url;
36682
36683		return image;
36684
36685	}
36686
36687} );
36688
36689/**
36690 * @author mrdoob / http://mrdoob.com/
36691 */
36692
36693
36694function CubeTextureLoader( manager ) {
36695
36696	Loader.call( this, manager );
36697
36698}
36699
36700CubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36701
36702	constructor: CubeTextureLoader,
36703
36704	load: function ( urls, onLoad, onProgress, onError ) {
36705
36706		var texture = new CubeTexture();
36707
36708		var loader = new ImageLoader( this.manager );
36709		loader.setCrossOrigin( this.crossOrigin );
36710		loader.setPath( this.path );
36711
36712		var loaded = 0;
36713
36714		function loadTexture( i ) {
36715
36716			loader.load( urls[ i ], function ( image ) {
36717
36718				texture.images[ i ] = image;
36719
36720				loaded ++;
36721
36722				if ( loaded === 6 ) {
36723
36724					texture.needsUpdate = true;
36725
36726					if ( onLoad ) onLoad( texture );
36727
36728				}
36729
36730			}, undefined, onError );
36731
36732		}
36733
36734		for ( var i = 0; i < urls.length; ++ i ) {
36735
36736			loadTexture( i );
36737
36738		}
36739
36740		return texture;
36741
36742	}
36743
36744} );
36745
36746/**
36747 * @author mrdoob / http://mrdoob.com/
36748 */
36749
36750function TextureLoader( manager ) {
36751
36752	Loader.call( this, manager );
36753
36754}
36755
36756TextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
36757
36758	constructor: TextureLoader,
36759
36760	load: function ( url, onLoad, onProgress, onError ) {
36761
36762		var texture = new Texture();
36763
36764		var loader = new ImageLoader( this.manager );
36765		loader.setCrossOrigin( this.crossOrigin );
36766		loader.setPath( this.path );
36767
36768		loader.load( url, function ( image ) {
36769
36770			texture.image = image;
36771
36772			// JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.
36773			var isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0;
36774
36775			texture.format = isJPEG ? RGBFormat : RGBAFormat;
36776			texture.needsUpdate = true;
36777
36778			if ( onLoad !== undefined ) {
36779
36780				onLoad( texture );
36781
36782			}
36783
36784		}, onProgress, onError );
36785
36786		return texture;
36787
36788	}
36789
36790} );
36791
36792/**
36793 * @author zz85 / http://www.lab4games.net/zz85/blog
36794 * Extensible curve object
36795 *
36796 * Some common of curve methods:
36797 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
36798 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
36799 * .getPoints(), .getSpacedPoints()
36800 * .getLength()
36801 * .updateArcLengths()
36802 *
36803 * This following curves inherit from THREE.Curve:
36804 *
36805 * -- 2D curves --
36806 * THREE.ArcCurve
36807 * THREE.CubicBezierCurve
36808 * THREE.EllipseCurve
36809 * THREE.LineCurve
36810 * THREE.QuadraticBezierCurve
36811 * THREE.SplineCurve
36812 *
36813 * -- 3D curves --
36814 * THREE.CatmullRomCurve3
36815 * THREE.CubicBezierCurve3
36816 * THREE.LineCurve3
36817 * THREE.QuadraticBezierCurve3
36818 *
36819 * A series of curves can be represented as a THREE.CurvePath.
36820 *
36821 **/
36822
36823/**************************************************************
36824 *	Abstract Curve base class
36825 **************************************************************/
36826
36827function Curve() {
36828
36829	this.type = 'Curve';
36830
36831	this.arcLengthDivisions = 200;
36832
36833}
36834
36835Object.assign( Curve.prototype, {
36836
36837	// Virtual base class method to overwrite and implement in subclasses
36838	//	- t [0 .. 1]
36839
36840	getPoint: function ( /* t, optionalTarget */ ) {
36841
36842		console.warn( 'THREE.Curve: .getPoint() not implemented.' );
36843		return null;
36844
36845	},
36846
36847	// Get point at relative position in curve according to arc length
36848	// - u [0 .. 1]
36849
36850	getPointAt: function ( u, optionalTarget ) {
36851
36852		var t = this.getUtoTmapping( u );
36853		return this.getPoint( t, optionalTarget );
36854
36855	},
36856
36857	// Get sequence of points using getPoint( t )
36858
36859	getPoints: function ( divisions ) {
36860
36861		if ( divisions === undefined ) divisions = 5;
36862
36863		var points = [];
36864
36865		for ( var d = 0; d <= divisions; d ++ ) {
36866
36867			points.push( this.getPoint( d / divisions ) );
36868
36869		}
36870
36871		return points;
36872
36873	},
36874
36875	// Get sequence of points using getPointAt( u )
36876
36877	getSpacedPoints: function ( divisions ) {
36878
36879		if ( divisions === undefined ) divisions = 5;
36880
36881		var points = [];
36882
36883		for ( var d = 0; d <= divisions; d ++ ) {
36884
36885			points.push( this.getPointAt( d / divisions ) );
36886
36887		}
36888
36889		return points;
36890
36891	},
36892
36893	// Get total curve arc length
36894
36895	getLength: function () {
36896
36897		var lengths = this.getLengths();
36898		return lengths[ lengths.length - 1 ];
36899
36900	},
36901
36902	// Get list of cumulative segment lengths
36903
36904	getLengths: function ( divisions ) {
36905
36906		if ( divisions === undefined ) divisions = this.arcLengthDivisions;
36907
36908		if ( this.cacheArcLengths &&
36909			( this.cacheArcLengths.length === divisions + 1 ) &&
36910			! this.needsUpdate ) {
36911
36912			return this.cacheArcLengths;
36913
36914		}
36915
36916		this.needsUpdate = false;
36917
36918		var cache = [];
36919		var current, last = this.getPoint( 0 );
36920		var p, sum = 0;
36921
36922		cache.push( 0 );
36923
36924		for ( p = 1; p <= divisions; p ++ ) {
36925
36926			current = this.getPoint( p / divisions );
36927			sum += current.distanceTo( last );
36928			cache.push( sum );
36929			last = current;
36930
36931		}
36932
36933		this.cacheArcLengths = cache;
36934
36935		return cache; // { sums: cache, sum: sum }; Sum is in the last element.
36936
36937	},
36938
36939	updateArcLengths: function () {
36940
36941		this.needsUpdate = true;
36942		this.getLengths();
36943
36944	},
36945
36946	// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
36947
36948	getUtoTmapping: function ( u, distance ) {
36949
36950		var arcLengths = this.getLengths();
36951
36952		var i = 0, il = arcLengths.length;
36953
36954		var targetArcLength; // The targeted u distance value to get
36955
36956		if ( distance ) {
36957
36958			targetArcLength = distance;
36959
36960		} else {
36961
36962			targetArcLength = u * arcLengths[ il - 1 ];
36963
36964		}
36965
36966		// binary search for the index with largest value smaller than target u distance
36967
36968		var low = 0, high = il - 1, comparison;
36969
36970		while ( low <= high ) {
36971
36972			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
36973
36974			comparison = arcLengths[ i ] - targetArcLength;
36975
36976			if ( comparison < 0 ) {
36977
36978				low = i + 1;
36979
36980			} else if ( comparison > 0 ) {
36981
36982				high = i - 1;
36983
36984			} else {
36985
36986				high = i;
36987				break;
36988
36989				// DONE
36990
36991			}
36992
36993		}
36994
36995		i = high;
36996
36997		if ( arcLengths[ i ] === targetArcLength ) {
36998
36999			return i / ( il - 1 );
37000
37001		}
37002
37003		// we could get finer grain at lengths, or use simple interpolation between two points
37004
37005		var lengthBefore = arcLengths[ i ];
37006		var lengthAfter = arcLengths[ i + 1 ];
37007
37008		var segmentLength = lengthAfter - lengthBefore;
37009
37010		// determine where we are between the 'before' and 'after' points
37011
37012		var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
37013
37014		// add that fractional amount to t
37015
37016		var t = ( i + segmentFraction ) / ( il - 1 );
37017
37018		return t;
37019
37020	},
37021
37022	// Returns a unit vector tangent at t
37023	// In case any sub curve does not implement its tangent derivation,
37024	// 2 points a small delta apart will be used to find its gradient
37025	// which seems to give a reasonable approximation
37026
37027	getTangent: function ( t, optionalTarget ) {
37028
37029		var delta = 0.0001;
37030		var t1 = t - delta;
37031		var t2 = t + delta;
37032
37033		// Capping in case of danger
37034
37035		if ( t1 < 0 ) t1 = 0;
37036		if ( t2 > 1 ) t2 = 1;
37037
37038		var pt1 = this.getPoint( t1 );
37039		var pt2 = this.getPoint( t2 );
37040
37041		var tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
37042
37043		tangent.copy( pt2 ).sub( pt1 ).normalize();
37044
37045		return tangent;
37046
37047	},
vendor: 36,522 bytes, lines 37048-38953
37048
37049	getTangentAt: function ( u, optionalTarget ) {
37050
37051		var t = this.getUtoTmapping( u );
37052		return this.getTangent( t, optionalTarget );
37053
37054	},
37055
37056	computeFrenetFrames: function ( segments, closed ) {
37057
37058		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
37059
37060		var normal = new Vector3();
37061
37062		var tangents = [];
37063		var normals = [];
37064		var binormals = [];
37065
37066		var vec = new Vector3();
37067		var mat = new Matrix4();
37068
37069		var i, u, theta;
37070
37071		// compute the tangent vectors for each segment on the curve
37072
37073		for ( i = 0; i <= segments; i ++ ) {
37074
37075			u = i / segments;
37076
37077			tangents[ i ] = this.getTangentAt( u, new Vector3() );
37078			tangents[ i ].normalize();
37079
37080		}
37081
37082		// select an initial normal vector perpendicular to the first tangent vector,
37083		// and in the direction of the minimum tangent xyz component
37084
37085		normals[ 0 ] = new Vector3();
37086		binormals[ 0 ] = new Vector3();
37087		var min = Number.MAX_VALUE;
37088		var tx = Math.abs( tangents[ 0 ].x );
37089		var ty = Math.abs( tangents[ 0 ].y );
37090		var tz = Math.abs( tangents[ 0 ].z );
37091
37092		if ( tx <= min ) {
37093
37094			min = tx;
37095			normal.set( 1, 0, 0 );
37096
37097		}
37098
37099		if ( ty <= min ) {
37100
37101			min = ty;
37102			normal.set( 0, 1, 0 );
37103
37104		}
37105
37106		if ( tz <= min ) {
37107
37108			normal.set( 0, 0, 1 );
37109
37110		}
37111
37112		vec.crossVectors( tangents[ 0 ], normal ).normalize();
37113
37114		normals[ 0 ].crossVectors( tangents[ 0 ], vec );
37115		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
37116
37117
37118		// compute the slowly-varying normal and binormal vectors for each segment on the curve
37119
37120		for ( i = 1; i <= segments; i ++ ) {
37121
37122			normals[ i ] = normals[ i - 1 ].clone();
37123
37124			binormals[ i ] = binormals[ i - 1 ].clone();
37125
37126			vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
37127
37128			if ( vec.length() > Number.EPSILON ) {
37129
37130				vec.normalize();
37131
37132				theta = Math.acos( MathUtils.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
37133
37134				normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
37135
37136			}
37137
37138			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
37139
37140		}
37141
37142		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
37143
37144		if ( closed === true ) {
37145
37146			theta = Math.acos( MathUtils.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
37147			theta /= segments;
37148
37149			if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
37150
37151				theta = - theta;
37152
37153			}
37154
37155			for ( i = 1; i <= segments; i ++ ) {
37156
37157				// twist a little...
37158				normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
37159				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
37160
37161			}
37162
37163		}
37164
37165		return {
37166			tangents: tangents,
37167			normals: normals,
37168			binormals: binormals
37169		};
37170
37171	},
37172
37173	clone: function () {
37174
37175		return new this.constructor().copy( this );
37176
37177	},
37178
37179	copy: function ( source ) {
37180
37181		this.arcLengthDivisions = source.arcLengthDivisions;
37182
37183		return this;
37184
37185	},
37186
37187	toJSON: function () {
37188
37189		var data = {
37190			metadata: {
37191				version: 4.5,
37192				type: 'Curve',
37193				generator: 'Curve.toJSON'
37194			}
37195		};
37196
37197		data.arcLengthDivisions = this.arcLengthDivisions;
37198		data.type = this.type;
37199
37200		return data;
37201
37202	},
37203
37204	fromJSON: function ( json ) {
37205
37206		this.arcLengthDivisions = json.arcLengthDivisions;
37207
37208		return this;
37209
37210	}
37211
37212} );
37213
37214function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
37215
37216	Curve.call( this );
37217
37218	this.type = 'EllipseCurve';
37219
37220	this.aX = aX || 0;
37221	this.aY = aY || 0;
37222
37223	this.xRadius = xRadius || 1;
37224	this.yRadius = yRadius || 1;
37225
37226	this.aStartAngle = aStartAngle || 0;
37227	this.aEndAngle = aEndAngle || 2 * Math.PI;
37228
37229	this.aClockwise = aClockwise || false;
37230
37231	this.aRotation = aRotation || 0;
37232
37233}
37234
37235EllipseCurve.prototype = Object.create( Curve.prototype );
37236EllipseCurve.prototype.constructor = EllipseCurve;
37237
37238EllipseCurve.prototype.isEllipseCurve = true;
37239
37240EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {
37241
37242	var point = optionalTarget || new Vector2();
37243
37244	var twoPi = Math.PI * 2;
37245	var deltaAngle = this.aEndAngle - this.aStartAngle;
37246	var samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
37247
37248	// ensures that deltaAngle is 0 .. 2 PI
37249	while ( deltaAngle < 0 ) deltaAngle += twoPi;
37250	while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
37251
37252	if ( deltaAngle < Number.EPSILON ) {
37253
37254		if ( samePoints ) {
37255
37256			deltaAngle = 0;
37257
37258		} else {
37259
37260			deltaAngle = twoPi;
37261
37262		}
37263
37264	}
37265
37266	if ( this.aClockwise === true && ! samePoints ) {
37267
37268		if ( deltaAngle === twoPi ) {
37269
37270			deltaAngle = - twoPi;
37271
37272		} else {
37273
37274			deltaAngle = deltaAngle - twoPi;
37275
37276		}
37277
37278	}
37279
37280	var angle = this.aStartAngle + t * deltaAngle;
37281	var x = this.aX + this.xRadius * Math.cos( angle );
37282	var y = this.aY + this.yRadius * Math.sin( angle );
37283
37284	if ( this.aRotation !== 0 ) {
37285
37286		var cos = Math.cos( this.aRotation );
37287		var sin = Math.sin( this.aRotation );
37288
37289		var tx = x - this.aX;
37290		var ty = y - this.aY;
37291
37292		// Rotate the point about the center of the ellipse.
37293		x = tx * cos - ty * sin + this.aX;
37294		y = tx * sin + ty * cos + this.aY;
37295
37296	}
37297
37298	return point.set( x, y );
37299
37300};
37301
37302EllipseCurve.prototype.copy = function ( source ) {
37303
37304	Curve.prototype.copy.call( this, source );
37305
37306	this.aX = source.aX;
37307	this.aY = source.aY;
37308
37309	this.xRadius = source.xRadius;
37310	this.yRadius = source.yRadius;
37311
37312	this.aStartAngle = source.aStartAngle;
37313	this.aEndAngle = source.aEndAngle;
37314
37315	this.aClockwise = source.aClockwise;
37316
37317	this.aRotation = source.aRotation;
37318
37319	return this;
37320
37321};
37322
37323
37324EllipseCurve.prototype.toJSON = function () {
37325
37326	var data = Curve.prototype.toJSON.call( this );
37327
37328	data.aX = this.aX;
37329	data.aY = this.aY;
37330
37331	data.xRadius = this.xRadius;
37332	data.yRadius = this.yRadius;
37333
37334	data.aStartAngle = this.aStartAngle;
37335	data.aEndAngle = this.aEndAngle;
37336
37337	data.aClockwise = this.aClockwise;
37338
37339	data.aRotation = this.aRotation;
37340
37341	return data;
37342
37343};
37344
37345EllipseCurve.prototype.fromJSON = function ( json ) {
37346
37347	Curve.prototype.fromJSON.call( this, json );
37348
37349	this.aX = json.aX;
37350	this.aY = json.aY;
37351
37352	this.xRadius = json.xRadius;
37353	this.yRadius = json.yRadius;
37354
37355	this.aStartAngle = json.aStartAngle;
37356	this.aEndAngle = json.aEndAngle;
37357
37358	this.aClockwise = json.aClockwise;
37359
37360	this.aRotation = json.aRotation;
37361
37362	return this;
37363
37364};
37365
37366function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
37367
37368	EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
37369
37370	this.type = 'ArcCurve';
37371
37372}
37373
37374ArcCurve.prototype = Object.create( EllipseCurve.prototype );
37375ArcCurve.prototype.constructor = ArcCurve;
37376
37377ArcCurve.prototype.isArcCurve = true;
37378
37379/**
37380 * @author zz85 https://github.com/zz85
37381 *
37382 * Centripetal CatmullRom Curve - which is useful for avoiding
37383 * cusps and self-intersections in non-uniform catmull rom curves.
37384 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
37385 *
37386 * curve.type accepts centripetal(default), chordal and catmullrom
37387 * curve.tension is used for catmullrom which defaults to 0.5
37388 */
37389
37390
37391/*
37392Based on an optimized c++ solution in
37393 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
37394 - http://ideone.com/NoEbVM
37395
37396This CubicPoly class could be used for reusing some variables and calculations,
37397but for three.js curve use, it could be possible inlined and flatten into a single function call
37398which can be placed in CurveUtils.
37399*/
37400
37401function CubicPoly() {
37402
37403	var c0 = 0, c1 = 0, c2 = 0, c3 = 0;
37404
37405	/*
37406	 * Compute coefficients for a cubic polynomial
37407	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
37408	 * such that
37409	 *   p(0) = x0, p(1) = x1
37410	 *  and
37411	 *   p'(0) = t0, p'(1) = t1.
37412	 */
37413	function init( x0, x1, t0, t1 ) {
37414
37415		c0 = x0;
37416		c1 = t0;
37417		c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
37418		c3 = 2 * x0 - 2 * x1 + t0 + t1;
37419
37420	}
37421
37422	return {
37423
37424		initCatmullRom: function ( x0, x1, x2, x3, tension ) {
37425
37426			init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
37427
37428		},
37429
37430		initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
37431
37432			// compute tangents when parameterized in [t1,t2]
37433			var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
37434			var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
37435
37436			// rescale tangents for parametrization in [0,1]
37437			t1 *= dt1;
37438			t2 *= dt1;
37439
37440			init( x1, x2, t1, t2 );
37441
37442		},
37443
37444		calc: function ( t ) {
37445
37446			var t2 = t * t;
37447			var t3 = t2 * t;
37448			return c0 + c1 * t + c2 * t2 + c3 * t3;
37449
37450		}
37451
37452	};
37453
37454}
37455
37456//
37457
37458var tmp = new Vector3();
37459var px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();
37460
37461function CatmullRomCurve3( points, closed, curveType, tension ) {
37462
37463	Curve.call( this );
37464
37465	this.type = 'CatmullRomCurve3';
37466
37467	this.points = points || [];
37468	this.closed = closed || false;
37469	this.curveType = curveType || 'centripetal';
37470	this.tension = tension || 0.5;
37471
37472}
37473
37474CatmullRomCurve3.prototype = Object.create( Curve.prototype );
37475CatmullRomCurve3.prototype.constructor = CatmullRomCurve3;
37476
37477CatmullRomCurve3.prototype.isCatmullRomCurve3 = true;
37478
37479CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) {
37480
37481	var point = optionalTarget || new Vector3();
37482
37483	var points = this.points;
37484	var l = points.length;
37485
37486	var p = ( l - ( this.closed ? 0 : 1 ) ) * t;
37487	var intPoint = Math.floor( p );
37488	var weight = p - intPoint;
37489
37490	if ( this.closed ) {
37491
37492		intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
37493
37494	} else if ( weight === 0 && intPoint === l - 1 ) {
37495
37496		intPoint = l - 2;
37497		weight = 1;
37498
37499	}
37500
37501	var p0, p1, p2, p3; // 4 points
37502
37503	if ( this.closed || intPoint > 0 ) {
37504
37505		p0 = points[ ( intPoint - 1 ) % l ];
37506
37507	} else {
37508
37509		// extrapolate first point
37510		tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
37511		p0 = tmp;
37512
37513	}
37514
37515	p1 = points[ intPoint % l ];
37516	p2 = points[ ( intPoint + 1 ) % l ];
37517
37518	if ( this.closed || intPoint + 2 < l ) {
37519
37520		p3 = points[ ( intPoint + 2 ) % l ];
37521
37522	} else {
37523
37524		// extrapolate last point
37525		tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
37526		p3 = tmp;
37527
37528	}
37529
37530	if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
37531
37532		// init Centripetal / Chordal Catmull-Rom
37533		var pow = this.curveType === 'chordal' ? 0.5 : 0.25;
37534		var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
37535		var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
37536		var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
37537
37538		// safety check for repeated points
37539		if ( dt1 < 1e-4 ) dt1 = 1.0;
37540		if ( dt0 < 1e-4 ) dt0 = dt1;
37541		if ( dt2 < 1e-4 ) dt2 = dt1;
37542
37543		px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
37544		py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
37545		pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
37546
37547	} else if ( this.curveType === 'catmullrom' ) {
37548
37549		px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
37550		py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
37551		pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
37552
37553	}
37554
37555	point.set(
37556		px.calc( weight ),
37557		py.calc( weight ),
37558		pz.calc( weight )
37559	);
37560
37561	return point;
37562
37563};
37564
37565CatmullRomCurve3.prototype.copy = function ( source ) {
37566
37567	Curve.prototype.copy.call( this, source );
37568
37569	this.points = [];
37570
37571	for ( var i = 0, l = source.points.length; i < l; i ++ ) {
37572
37573		var point = source.points[ i ];
37574
37575		this.points.push( point.clone() );
37576
37577	}
37578
37579	this.closed = source.closed;
37580	this.curveType = source.curveType;
37581	this.tension = source.tension;
37582
37583	return this;
37584
37585};
37586
37587CatmullRomCurve3.prototype.toJSON = function () {
37588
37589	var data = Curve.prototype.toJSON.call( this );
37590
37591	data.points = [];
37592
37593	for ( var i = 0, l = this.points.length; i < l; i ++ ) {
37594
37595		var point = this.points[ i ];
37596		data.points.push( point.toArray() );
37597
37598	}
37599
37600	data.closed = this.closed;
37601	data.curveType = this.curveType;
37602	data.tension = this.tension;
37603
37604	return data;
37605
37606};
37607
37608CatmullRomCurve3.prototype.fromJSON = function ( json ) {
37609
37610	Curve.prototype.fromJSON.call( this, json );
37611
37612	this.points = [];
37613
37614	for ( var i = 0, l = json.points.length; i < l; i ++ ) {
37615
37616		var point = json.points[ i ];
37617		this.points.push( new Vector3().fromArray( point ) );
37618
37619	}
37620
37621	this.closed = json.closed;
37622	this.curveType = json.curveType;
37623	this.tension = json.tension;
37624
37625	return this;
37626
37627};
37628
37629/**
37630 * @author zz85 / http://www.lab4games.net/zz85/blog
37631 *
37632 * Bezier Curves formulas obtained from
37633 * http://en.wikipedia.org/wiki/Bézier_curve
37634 */
37635
37636function CatmullRom( t, p0, p1, p2, p3 ) {
37637
37638	var v0 = ( p2 - p0 ) * 0.5;
37639	var v1 = ( p3 - p1 ) * 0.5;
37640	var t2 = t * t;
37641	var t3 = t * t2;
37642	return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
37643
37644}
37645
37646//
37647
37648function QuadraticBezierP0( t, p ) {
37649
37650	var k = 1 - t;
37651	return k * k * p;
37652
37653}
37654
37655function QuadraticBezierP1( t, p ) {
37656
37657	return 2 * ( 1 - t ) * t * p;
37658
37659}
37660
37661function QuadraticBezierP2( t, p ) {
37662
37663	return t * t * p;
37664
37665}
37666
37667function QuadraticBezier( t, p0, p1, p2 ) {
37668
37669	return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
37670		QuadraticBezierP2( t, p2 );
37671
37672}
37673
37674//
37675
37676function CubicBezierP0( t, p ) {
37677
37678	var k = 1 - t;
37679	return k * k * k * p;
37680
37681}
37682
37683function CubicBezierP1( t, p ) {
37684
37685	var k = 1 - t;
37686	return 3 * k * k * t * p;
37687
37688}
37689
37690function CubicBezierP2( t, p ) {
37691
37692	return 3 * ( 1 - t ) * t * t * p;
37693
37694}
37695
37696function CubicBezierP3( t, p ) {
37697
37698	return t * t * t * p;
37699
37700}
37701
37702function CubicBezier( t, p0, p1, p2, p3 ) {
37703
37704	return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
37705		CubicBezierP3( t, p3 );
37706
37707}
37708
37709function CubicBezierCurve( v0, v1, v2, v3 ) {
37710
37711	Curve.call( this );
37712
37713	this.type = 'CubicBezierCurve';
37714
37715	this.v0 = v0 || new Vector2();
37716	this.v1 = v1 || new Vector2();
37717	this.v2 = v2 || new Vector2();
37718	this.v3 = v3 || new Vector2();
37719
37720}
37721
37722CubicBezierCurve.prototype = Object.create( Curve.prototype );
37723CubicBezierCurve.prototype.constructor = CubicBezierCurve;
37724
37725CubicBezierCurve.prototype.isCubicBezierCurve = true;
37726
37727CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
37728
37729	var point = optionalTarget || new Vector2();
37730
37731	var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
37732
37733	point.set(
37734		CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
37735		CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
37736	);
37737
37738	return point;
37739
37740};
37741
37742CubicBezierCurve.prototype.copy = function ( source ) {
37743
37744	Curve.prototype.copy.call( this, source );
37745
37746	this.v0.copy( source.v0 );
37747	this.v1.copy( source.v1 );
37748	this.v2.copy( source.v2 );
37749	this.v3.copy( source.v3 );
37750
37751	return this;
37752
37753};
37754
37755CubicBezierCurve.prototype.toJSON = function () {
37756
37757	var data = Curve.prototype.toJSON.call( this );
37758
37759	data.v0 = this.v0.toArray();
37760	data.v1 = this.v1.toArray();
37761	data.v2 = this.v2.toArray();
37762	data.v3 = this.v3.toArray();
37763
37764	return data;
37765
37766};
37767
37768CubicBezierCurve.prototype.fromJSON = function ( json ) {
37769
37770	Curve.prototype.fromJSON.call( this, json );
37771
37772	this.v0.fromArray( json.v0 );
37773	this.v1.fromArray( json.v1 );
37774	this.v2.fromArray( json.v2 );
37775	this.v3.fromArray( json.v3 );
37776
37777	return this;
37778
37779};
37780
37781function CubicBezierCurve3( v0, v1, v2, v3 ) {
37782
37783	Curve.call( this );
37784
37785	this.type = 'CubicBezierCurve3';
37786
37787	this.v0 = v0 || new Vector3();
37788	this.v1 = v1 || new Vector3();
37789	this.v2 = v2 || new Vector3();
37790	this.v3 = v3 || new Vector3();
37791
37792}
37793
37794CubicBezierCurve3.prototype = Object.create( Curve.prototype );
37795CubicBezierCurve3.prototype.constructor = CubicBezierCurve3;
37796
37797CubicBezierCurve3.prototype.isCubicBezierCurve3 = true;
37798
37799CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
37800
37801	var point = optionalTarget || new Vector3();
37802
37803	var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
37804
37805	point.set(
37806		CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
37807		CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
37808		CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
37809	);
37810
37811	return point;
37812
37813};
37814
37815CubicBezierCurve3.prototype.copy = function ( source ) {
37816
37817	Curve.prototype.copy.call( this, source );
37818
37819	this.v0.copy( source.v0 );
37820	this.v1.copy( source.v1 );
37821	this.v2.copy( source.v2 );
37822	this.v3.copy( source.v3 );
37823
37824	return this;
37825
37826};
37827
37828CubicBezierCurve3.prototype.toJSON = function () {
37829
37830	var data = Curve.prototype.toJSON.call( this );
37831
37832	data.v0 = this.v0.toArray();
37833	data.v1 = this.v1.toArray();
37834	data.v2 = this.v2.toArray();
37835	data.v3 = this.v3.toArray();
37836
37837	return data;
37838
37839};
37840
37841CubicBezierCurve3.prototype.fromJSON = function ( json ) {
37842
37843	Curve.prototype.fromJSON.call( this, json );
37844
37845	this.v0.fromArray( json.v0 );
37846	this.v1.fromArray( json.v1 );
37847	this.v2.fromArray( json.v2 );
37848	this.v3.fromArray( json.v3 );
37849
37850	return this;
37851
37852};
37853
37854function LineCurve( v1, v2 ) {
37855
37856	Curve.call( this );
37857
37858	this.type = 'LineCurve';
37859
37860	this.v1 = v1 || new Vector2();
37861	this.v2 = v2 || new Vector2();
37862
37863}
37864
37865LineCurve.prototype = Object.create( Curve.prototype );
37866LineCurve.prototype.constructor = LineCurve;
37867
37868LineCurve.prototype.isLineCurve = true;
37869
37870LineCurve.prototype.getPoint = function ( t, optionalTarget ) {
37871
37872	var point = optionalTarget || new Vector2();
37873
37874	if ( t === 1 ) {
37875
37876		point.copy( this.v2 );
37877
37878	} else {
37879
37880		point.copy( this.v2 ).sub( this.v1 );
37881		point.multiplyScalar( t ).add( this.v1 );
37882
37883	}
37884
37885	return point;
37886
37887};
37888
37889// Line curve is linear, so we can overwrite default getPointAt
37890
37891LineCurve.prototype.getPointAt = function ( u, optionalTarget ) {
37892
37893	return this.getPoint( u, optionalTarget );
37894
37895};
37896
37897LineCurve.prototype.getTangent = function ( t, optionalTarget ) {
37898
37899	var tangent = optionalTarget || new Vector2();
37900
37901	var tangent = tangent.copy( this.v2 ).sub( this.v1 ).normalize();
37902
37903	return tangent;
37904
37905};
37906
37907LineCurve.prototype.copy = function ( source ) {
37908
37909	Curve.prototype.copy.call( this, source );
37910
37911	this.v1.copy( source.v1 );
37912	this.v2.copy( source.v2 );
37913
37914	return this;
37915
37916};
37917
37918LineCurve.prototype.toJSON = function () {
37919
37920	var data = Curve.prototype.toJSON.call( this );
37921
37922	data.v1 = this.v1.toArray();
37923	data.v2 = this.v2.toArray();
37924
37925	return data;
37926
37927};
37928
37929LineCurve.prototype.fromJSON = function ( json ) {
37930
37931	Curve.prototype.fromJSON.call( this, json );
37932
37933	this.v1.fromArray( json.v1 );
37934	this.v2.fromArray( json.v2 );
37935
37936	return this;
37937
37938};
37939
37940function LineCurve3( v1, v2 ) {
37941
37942	Curve.call( this );
37943
37944	this.type = 'LineCurve3';
37945
37946	this.v1 = v1 || new Vector3();
37947	this.v2 = v2 || new Vector3();
37948
37949}
37950
37951LineCurve3.prototype = Object.create( Curve.prototype );
37952LineCurve3.prototype.constructor = LineCurve3;
37953
37954LineCurve3.prototype.isLineCurve3 = true;
37955
37956LineCurve3.prototype.getPoint = function ( t, optionalTarget ) {
37957
37958	var point = optionalTarget || new Vector3();
37959
37960	if ( t === 1 ) {
37961
37962		point.copy( this.v2 );
37963
37964	} else {
37965
37966		point.copy( this.v2 ).sub( this.v1 );
37967		point.multiplyScalar( t ).add( this.v1 );
37968
37969	}
37970
37971	return point;
37972
37973};
37974
37975// Line curve is linear, so we can overwrite default getPointAt
37976
37977LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {
37978
37979	return this.getPoint( u, optionalTarget );
37980
37981};
37982
37983LineCurve3.prototype.copy = function ( source ) {
37984
37985	Curve.prototype.copy.call( this, source );
37986
37987	this.v1.copy( source.v1 );
37988	this.v2.copy( source.v2 );
37989
37990	return this;
37991
37992};
37993
37994LineCurve3.prototype.toJSON = function () {
37995
37996	var data = Curve.prototype.toJSON.call( this );
37997
37998	data.v1 = this.v1.toArray();
37999	data.v2 = this.v2.toArray();
38000
38001	return data;
38002
38003};
38004
38005LineCurve3.prototype.fromJSON = function ( json ) {
38006
38007	Curve.prototype.fromJSON.call( this, json );
38008
38009	this.v1.fromArray( json.v1 );
38010	this.v2.fromArray( json.v2 );
38011
38012	return this;
38013
38014};
38015
38016function QuadraticBezierCurve( v0, v1, v2 ) {
38017
38018	Curve.call( this );
38019
38020	this.type = 'QuadraticBezierCurve';
38021
38022	this.v0 = v0 || new Vector2();
38023	this.v1 = v1 || new Vector2();
38024	this.v2 = v2 || new Vector2();
38025
38026}
38027
38028QuadraticBezierCurve.prototype = Object.create( Curve.prototype );
38029QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;
38030
38031QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;
38032
38033QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {
38034
38035	var point = optionalTarget || new Vector2();
38036
38037	var v0 = this.v0, v1 = this.v1, v2 = this.v2;
38038
38039	point.set(
38040		QuadraticBezier( t, v0.x, v1.x, v2.x ),
38041		QuadraticBezier( t, v0.y, v1.y, v2.y )
38042	);
38043
38044	return point;
38045
38046};
38047
38048QuadraticBezierCurve.prototype.copy = function ( source ) {
38049
38050	Curve.prototype.copy.call( this, source );
38051
38052	this.v0.copy( source.v0 );
38053	this.v1.copy( source.v1 );
38054	this.v2.copy( source.v2 );
38055
38056	return this;
38057
38058};
38059
38060QuadraticBezierCurve.prototype.toJSON = function () {
38061
38062	var data = Curve.prototype.toJSON.call( this );
38063
38064	data.v0 = this.v0.toArray();
38065	data.v1 = this.v1.toArray();
38066	data.v2 = this.v2.toArray();
38067
38068	return data;
38069
38070};
38071
38072QuadraticBezierCurve.prototype.fromJSON = function ( json ) {
38073
38074	Curve.prototype.fromJSON.call( this, json );
38075
38076	this.v0.fromArray( json.v0 );
38077	this.v1.fromArray( json.v1 );
38078	this.v2.fromArray( json.v2 );
38079
38080	return this;
38081
38082};
38083
38084function QuadraticBezierCurve3( v0, v1, v2 ) {
38085
38086	Curve.call( this );
38087
38088	this.type = 'QuadraticBezierCurve3';
38089
38090	this.v0 = v0 || new Vector3();
38091	this.v1 = v1 || new Vector3();
38092	this.v2 = v2 || new Vector3();
38093
38094}
38095
38096QuadraticBezierCurve3.prototype = Object.create( Curve.prototype );
38097QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;
38098
38099QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;
38100
38101QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {
38102
38103	var point = optionalTarget || new Vector3();
38104
38105	var v0 = this.v0, v1 = this.v1, v2 = this.v2;
38106
38107	point.set(
38108		QuadraticBezier( t, v0.x, v1.x, v2.x ),
38109		QuadraticBezier( t, v0.y, v1.y, v2.y ),
38110		QuadraticBezier( t, v0.z, v1.z, v2.z )
38111	);
38112
38113	return point;
38114
38115};
38116
38117QuadraticBezierCurve3.prototype.copy = function ( source ) {
38118
38119	Curve.prototype.copy.call( this, source );
38120
38121	this.v0.copy( source.v0 );
38122	this.v1.copy( source.v1 );
38123	this.v2.copy( source.v2 );
38124
38125	return this;
38126
38127};
38128
38129QuadraticBezierCurve3.prototype.toJSON = function () {
38130
38131	var data = Curve.prototype.toJSON.call( this );
38132
38133	data.v0 = this.v0.toArray();
38134	data.v1 = this.v1.toArray();
38135	data.v2 = this.v2.toArray();
38136
38137	return data;
38138
38139};
38140
38141QuadraticBezierCurve3.prototype.fromJSON = function ( json ) {
38142
38143	Curve.prototype.fromJSON.call( this, json );
38144
38145	this.v0.fromArray( json.v0 );
38146	this.v1.fromArray( json.v1 );
38147	this.v2.fromArray( json.v2 );
38148
38149	return this;
38150
38151};
38152
38153function SplineCurve( points /* array of Vector2 */ ) {
38154
38155	Curve.call( this );
38156
38157	this.type = 'SplineCurve';
38158
38159	this.points = points || [];
38160
38161}
38162
38163SplineCurve.prototype = Object.create( Curve.prototype );
38164SplineCurve.prototype.constructor = SplineCurve;
38165
38166SplineCurve.prototype.isSplineCurve = true;
38167
38168SplineCurve.prototype.getPoint = function ( t, optionalTarget ) {
38169
38170	var point = optionalTarget || new Vector2();
38171
38172	var points = this.points;
38173	var p = ( points.length - 1 ) * t;
38174
38175	var intPoint = Math.floor( p );
38176	var weight = p - intPoint;
38177
38178	var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
38179	var p1 = points[ intPoint ];
38180	var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
38181	var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
38182
38183	point.set(
38184		CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
38185		CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
38186	);
38187
38188	return point;
38189
38190};
38191
38192SplineCurve.prototype.copy = function ( source ) {
38193
38194	Curve.prototype.copy.call( this, source );
38195
38196	this.points = [];
38197
38198	for ( var i = 0, l = source.points.length; i < l; i ++ ) {
38199
38200		var point = source.points[ i ];
38201
38202		this.points.push( point.clone() );
38203
38204	}
38205
38206	return this;
38207
38208};
38209
38210SplineCurve.prototype.toJSON = function () {
38211
38212	var data = Curve.prototype.toJSON.call( this );
38213
38214	data.points = [];
38215
38216	for ( var i = 0, l = this.points.length; i < l; i ++ ) {
38217
38218		var point = this.points[ i ];
38219		data.points.push( point.toArray() );
38220
38221	}
38222
38223	return data;
38224
38225};
38226
38227SplineCurve.prototype.fromJSON = function ( json ) {
38228
38229	Curve.prototype.fromJSON.call( this, json );
38230
38231	this.points = [];
38232
38233	for ( var i = 0, l = json.points.length; i < l; i ++ ) {
38234
38235		var point = json.points[ i ];
38236		this.points.push( new Vector2().fromArray( point ) );
38237
38238	}
38239
38240	return this;
38241
38242};
38243
38244var Curves = /*#__PURE__*/Object.freeze({
38245	__proto__: null,
38246	ArcCurve: ArcCurve,
38247	CatmullRomCurve3: CatmullRomCurve3,
38248	CubicBezierCurve: CubicBezierCurve,
38249	CubicBezierCurve3: CubicBezierCurve3,
38250	EllipseCurve: EllipseCurve,
38251	LineCurve: LineCurve,
38252	LineCurve3: LineCurve3,
38253	QuadraticBezierCurve: QuadraticBezierCurve,
38254	QuadraticBezierCurve3: QuadraticBezierCurve3,
38255	SplineCurve: SplineCurve
38256});
38257
38258/**
38259 * @author zz85 / http://www.lab4games.net/zz85/blog
38260 *
38261 **/
38262
38263/**************************************************************
38264 *	Curved Path - a curve path is simply a array of connected
38265 *  curves, but retains the api of a curve
38266 **************************************************************/
38267
38268function CurvePath() {
38269
38270	Curve.call( this );
38271
38272	this.type = 'CurvePath';
38273
38274	this.curves = [];
38275	this.autoClose = false; // Automatically closes the path
38276
38277}
38278
38279CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
38280
38281	constructor: CurvePath,
38282
38283	add: function ( curve ) {
38284
38285		this.curves.push( curve );
38286
38287	},
38288
38289	closePath: function () {
38290
38291		// Add a line curve if start and end of lines are not connected
38292		var startPoint = this.curves[ 0 ].getPoint( 0 );
38293		var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
38294
38295		if ( ! startPoint.equals( endPoint ) ) {
38296
38297			this.curves.push( new LineCurve( endPoint, startPoint ) );
38298
38299		}
38300
38301	},
38302
38303	// To get accurate point with reference to
38304	// entire path distance at time t,
38305	// following has to be done:
38306
38307	// 1. Length of each sub path have to be known
38308	// 2. Locate and identify type of curve
38309	// 3. Get t for the curve
38310	// 4. Return curve.getPointAt(t')
38311
38312	getPoint: function ( t ) {
38313
38314		var d = t * this.getLength();
38315		var curveLengths = this.getCurveLengths();
38316		var i = 0;
38317
38318		// To think about boundaries points.
38319
38320		while ( i < curveLengths.length ) {
38321
38322			if ( curveLengths[ i ] >= d ) {
38323
38324				var diff = curveLengths[ i ] - d;
38325				var curve = this.curves[ i ];
38326
38327				var segmentLength = curve.getLength();
38328				var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
38329
38330				return curve.getPointAt( u );
38331
38332			}
38333
38334			i ++;
38335
38336		}
38337
38338		return null;
38339
38340		// loop where sum != 0, sum > d , sum+1 <d
38341
38342	},
38343
38344	// We cannot use the default THREE.Curve getPoint() with getLength() because in
38345	// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
38346	// getPoint() depends on getLength
38347
38348	getLength: function () {
38349
38350		var lens = this.getCurveLengths();
38351		return lens[ lens.length - 1 ];
38352
38353	},
38354
38355	// cacheLengths must be recalculated.
38356	updateArcLengths: function () {
38357
38358		this.needsUpdate = true;
38359		this.cacheLengths = null;
38360		this.getCurveLengths();
38361
38362	},
38363
38364	// Compute lengths and cache them
38365	// We cannot overwrite getLengths() because UtoT mapping uses it.
38366
38367	getCurveLengths: function () {
38368
38369		// We use cache values if curves and cache array are same length
38370
38371		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
38372
38373			return this.cacheLengths;
38374
38375		}
38376
38377		// Get length of sub-curve
38378		// Push sums into cached array
38379
38380		var lengths = [], sums = 0;
38381
38382		for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
38383
38384			sums += this.curves[ i ].getLength();
38385			lengths.push( sums );
38386
38387		}
38388
38389		this.cacheLengths = lengths;
38390
38391		return lengths;
38392
38393	},
38394
38395	getSpacedPoints: function ( divisions ) {
38396
38397		if ( divisions === undefined ) divisions = 40;
38398
38399		var points = [];
38400
38401		for ( var i = 0; i <= divisions; i ++ ) {
38402
38403			points.push( this.getPoint( i / divisions ) );
38404
38405		}
38406
38407		if ( this.autoClose ) {
38408
38409			points.push( points[ 0 ] );
38410
38411		}
38412
38413		return points;
38414
38415	},
38416
38417	getPoints: function ( divisions ) {
38418
38419		divisions = divisions || 12;
38420
38421		var points = [], last;
38422
38423		for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {
38424
38425			var curve = curves[ i ];
38426			var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
38427				: ( curve && ( curve.isLineCurve || curve.isLineCurve3 ) ) ? 1
38428					: ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
38429						: divisions;
38430
38431			var pts = curve.getPoints( resolution );
38432
38433			for ( var j = 0; j < pts.length; j ++ ) {
38434
38435				var point = pts[ j ];
38436
38437				if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
38438
38439				points.push( point );
38440				last = point;
38441
38442			}
38443
38444		}
38445
38446		if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
38447
38448			points.push( points[ 0 ] );
38449
38450		}
38451
38452		return points;
38453
38454	},
38455
38456	copy: function ( source ) {
38457
38458		Curve.prototype.copy.call( this, source );
38459
38460		this.curves = [];
38461
38462		for ( var i = 0, l = source.curves.length; i < l; i ++ ) {
38463
38464			var curve = source.curves[ i ];
38465
38466			this.curves.push( curve.clone() );
38467
38468		}
38469
38470		this.autoClose = source.autoClose;
38471
38472		return this;
38473
38474	},
38475
38476	toJSON: function () {
38477
38478		var data = Curve.prototype.toJSON.call( this );
38479
38480		data.autoClose = this.autoClose;
38481		data.curves = [];
38482
38483		for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
38484
38485			var curve = this.curves[ i ];
38486			data.curves.push( curve.toJSON() );
38487
38488		}
38489
38490		return data;
38491
38492	},
38493
38494	fromJSON: function ( json ) {
38495
38496		Curve.prototype.fromJSON.call( this, json );
38497
38498		this.autoClose = json.autoClose;
38499		this.curves = [];
38500
38501		for ( var i = 0, l = json.curves.length; i < l; i ++ ) {
38502
38503			var curve = json.curves[ i ];
38504			this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
38505
38506		}
38507
38508		return this;
38509
38510	}
38511
38512} );
38513
38514/**
38515 * @author zz85 / http://www.lab4games.net/zz85/blog
38516 * Creates free form 2d path using series of points, lines or curves.
38517 **/
38518
38519function Path( points ) {
38520
38521	CurvePath.call( this );
38522
38523	this.type = 'Path';
38524
38525	this.currentPoint = new Vector2();
38526
38527	if ( points ) {
38528
38529		this.setFromPoints( points );
38530
38531	}
38532
38533}
38534
38535Path.prototype = Object.assign( Object.create( CurvePath.prototype ), {
38536
38537	constructor: Path,
38538
38539	setFromPoints: function ( points ) {
38540
38541		this.moveTo( points[ 0 ].x, points[ 0 ].y );
38542
38543		for ( var i = 1, l = points.length; i < l; i ++ ) {
38544
38545			this.lineTo( points[ i ].x, points[ i ].y );
38546
38547		}
38548
38549		return this;
38550
38551	},
38552
38553	moveTo: function ( x, y ) {
38554
38555		this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
38556
38557		return this;
38558
38559	},
38560
38561	lineTo: function ( x, y ) {
38562
38563		var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
38564		this.curves.push( curve );
38565
38566		this.currentPoint.set( x, y );
38567
38568		return this;
38569
38570	},
38571
38572	quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
38573
38574		var curve = new QuadraticBezierCurve(
38575			this.currentPoint.clone(),
38576			new Vector2( aCPx, aCPy ),
38577			new Vector2( aX, aY )
38578		);
38579
38580		this.curves.push( curve );
38581
38582		this.currentPoint.set( aX, aY );
38583
38584		return this;
38585
38586	},
38587
38588	bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
38589
38590		var curve = new CubicBezierCurve(
38591			this.currentPoint.clone(),
38592			new Vector2( aCP1x, aCP1y ),
38593			new Vector2( aCP2x, aCP2y ),
38594			new Vector2( aX, aY )
38595		);
38596
38597		this.curves.push( curve );
38598
38599		this.currentPoint.set( aX, aY );
38600
38601		return this;
38602
38603	},
38604
38605	splineThru: function ( pts /*Array of Vector*/ ) {
38606
38607		var npts = [ this.currentPoint.clone() ].concat( pts );
38608
38609		var curve = new SplineCurve( npts );
38610		this.curves.push( curve );
38611
38612		this.currentPoint.copy( pts[ pts.length - 1 ] );
38613
38614		return this;
38615
38616	},
38617
38618	arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
38619
38620		var x0 = this.currentPoint.x;
38621		var y0 = this.currentPoint.y;
38622
38623		this.absarc( aX + x0, aY + y0, aRadius,
38624			aStartAngle, aEndAngle, aClockwise );
38625
38626		return this;
38627
38628	},
38629
38630	absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
38631
38632		this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
38633
38634		return this;
38635
38636	},
38637
38638	ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
38639
38640		var x0 = this.currentPoint.x;
38641		var y0 = this.currentPoint.y;
38642
38643		this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
38644
38645		return this;
38646
38647	},
38648
38649	absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
38650
38651		var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
38652
38653		if ( this.curves.length > 0 ) {
38654
38655			// if a previous curve is present, attempt to join
38656			var firstPoint = curve.getPoint( 0 );
38657
38658			if ( ! firstPoint.equals( this.currentPoint ) ) {
38659
38660				this.lineTo( firstPoint.x, firstPoint.y );
38661
38662			}
38663
38664		}
38665
38666		this.curves.push( curve );
38667
38668		var lastPoint = curve.getPoint( 1 );
38669		this.currentPoint.copy( lastPoint );
38670
38671		return this;
38672
38673	},
38674
38675	copy: function ( source ) {
38676
38677		CurvePath.prototype.copy.call( this, source );
38678
38679		this.currentPoint.copy( source.currentPoint );
38680
38681		return this;
38682
38683	},
38684
38685	toJSON: function () {
38686
38687		var data = CurvePath.prototype.toJSON.call( this );
38688
38689		data.currentPoint = this.currentPoint.toArray();
38690
38691		return data;
38692
38693	},
38694
38695	fromJSON: function ( json ) {
38696
38697		CurvePath.prototype.fromJSON.call( this, json );
38698
38699		this.currentPoint.fromArray( json.currentPoint );
38700
38701		return this;
38702
38703	}
38704
38705} );
38706
38707/**
38708 * @author zz85 / http://www.lab4games.net/zz85/blog
38709 * Defines a 2d shape plane using paths.
38710 **/
38711
38712// STEP 1 Create a path.
38713// STEP 2 Turn path into shape.
38714// STEP 3 ExtrudeGeometry takes in Shape/Shapes
38715// STEP 3a - Extract points from each shape, turn to vertices
38716// STEP 3b - Triangulate each shape, add faces.
38717
38718function Shape( points ) {
38719
38720	Path.call( this, points );
38721
38722	this.uuid = MathUtils.generateUUID();
38723
38724	this.type = 'Shape';
38725
38726	this.holes = [];
38727
38728}
38729
38730Shape.prototype = Object.assign( Object.create( Path.prototype ), {
38731
38732	constructor: Shape,
38733
38734	getPointsHoles: function ( divisions ) {
38735
38736		var holesPts = [];
38737
38738		for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
38739
38740			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
38741
38742		}
38743
38744		return holesPts;
38745
38746	},
38747
38748	// get points of shape and holes (keypoints based on segments parameter)
38749
38750	extractPoints: function ( divisions ) {
38751
38752		return {
38753
38754			shape: this.getPoints( divisions ),
38755			holes: this.getPointsHoles( divisions )
38756
38757		};
38758
38759	},
38760
38761	copy: function ( source ) {
38762
38763		Path.prototype.copy.call( this, source );
38764
38765		this.holes = [];
38766
38767		for ( var i = 0, l = source.holes.length; i < l; i ++ ) {
38768
38769			var hole = source.holes[ i ];
38770
38771			this.holes.push( hole.clone() );
38772
38773		}
38774
38775		return this;
38776
38777	},
38778
38779	toJSON: function () {
38780
38781		var data = Path.prototype.toJSON.call( this );
38782
38783		data.uuid = this.uuid;
38784		data.holes = [];
38785
38786		for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
38787
38788			var hole = this.holes[ i ];
38789			data.holes.push( hole.toJSON() );
38790
38791		}
38792
38793		return data;
38794
38795	},
38796
38797	fromJSON: function ( json ) {
38798
38799		Path.prototype.fromJSON.call( this, json );
38800
38801		this.uuid = json.uuid;
38802		this.holes = [];
38803
38804		for ( var i = 0, l = json.holes.length; i < l; i ++ ) {
38805
38806			var hole = json.holes[ i ];
38807			this.holes.push( new Path().fromJSON( hole ) );
38808
38809		}
38810
38811		return this;
38812
38813	}
38814
38815} );
38816
38817/**
38818 * @author mrdoob / http://mrdoob.com/
38819 * @author alteredq / http://alteredqualia.com/
38820 */
38821
38822function Light( color, intensity ) {
38823
38824	Object3D.call( this );
38825
38826	this.type = 'Light';
38827
38828	this.color = new Color( color );
38829	this.intensity = intensity !== undefined ? intensity : 1;
38830
38831	this.receiveShadow = undefined;
38832
38833}
38834
38835Light.prototype = Object.assign( Object.create( Object3D.prototype ), {
38836
38837	constructor: Light,
38838
38839	isLight: true,
38840
38841	copy: function ( source ) {
38842
38843		Object3D.prototype.copy.call( this, source );
38844
38845		this.color.copy( source.color );
38846		this.intensity = source.intensity;
38847
38848		return this;
38849
38850	},
38851
38852	toJSON: function ( meta ) {
38853
38854		var data = Object3D.prototype.toJSON.call( this, meta );
38855
38856		data.object.color = this.color.getHex();
38857		data.object.intensity = this.intensity;
38858
38859		if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
38860
38861		if ( this.distance !== undefined ) data.object.distance = this.distance;
38862		if ( this.angle !== undefined ) data.object.angle = this.angle;
38863		if ( this.decay !== undefined ) data.object.decay = this.decay;
38864		if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
38865
38866		if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
38867
38868		return data;
38869
38870	}
38871
38872} );
38873
38874/**
38875 * @author alteredq / http://alteredqualia.com/
38876 */
38877
38878function HemisphereLight( skyColor, groundColor, intensity ) {
38879
38880	Light.call( this, skyColor, intensity );
38881
38882	this.type = 'HemisphereLight';
38883
38884	this.castShadow = undefined;
38885
38886	this.position.copy( Object3D.DefaultUp );
38887	this.updateMatrix();
38888
38889	this.groundColor = new Color( groundColor );
38890
38891}
38892
38893HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {
38894
38895	constructor: HemisphereLight,
38896
38897	isHemisphereLight: true,
38898
38899	copy: function ( source ) {
38900
38901		Light.prototype.copy.call( this, source );
38902
38903		this.groundColor.copy( source.groundColor );
38904
38905		return this;
38906
38907	}
38908
38909} );
38910
38911/**
38912 * @author mrdoob / http://mrdoob.com/
38913 */
38914
38915function LightShadow( camera ) {
38916
38917	this.camera = camera;
38918
38919	this.bias = 0;
38920	this.radius = 1;
38921
38922	this.mapSize = new Vector2( 512, 512 );
38923
38924	this.map = null;
38925	this.mapPass = null;
38926	this.matrix = new Matrix4();
38927
38928	this._frustum = new Frustum();
38929	this._frameExtents = new Vector2( 1, 1 );
38930
38931	this._viewportCount = 1;
38932
38933	this._viewports = [
38934
38935		new Vector4( 0, 0, 1, 1 )
38936
38937	];
38938
38939}
38940
38941Object.assign( LightShadow.prototype, {
38942
38943	_projScreenMatrix: new Matrix4(),
38944
38945	_lightPositionWorld: new Vector3(),
38946
38947	_lookTarget: new Vector3(),
38948
38949	getViewportCount: function () {
38950
38951		return this._viewportCount;
38952
38953	},
vendor: 6,365 bytes, lines 38954-39232
38954
38955	getFrustum: function () {
38956
38957		return this._frustum;
38958
38959	},
38960
38961	updateMatrices: function ( light ) {
38962
38963		var shadowCamera = this.camera,
38964			shadowMatrix = this.matrix,
38965			projScreenMatrix = this._projScreenMatrix,
38966			lookTarget = this._lookTarget,
38967			lightPositionWorld = this._lightPositionWorld;
38968
38969		lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
38970		shadowCamera.position.copy( lightPositionWorld );
38971
38972		lookTarget.setFromMatrixPosition( light.target.matrixWorld );
38973		shadowCamera.lookAt( lookTarget );
38974		shadowCamera.updateMatrixWorld();
38975
38976		projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
38977		this._frustum.setFromProjectionMatrix( projScreenMatrix );
38978
38979		shadowMatrix.set(
38980			0.5, 0.0, 0.0, 0.5,
38981			0.0, 0.5, 0.0, 0.5,
38982			0.0, 0.0, 0.5, 0.5,
38983			0.0, 0.0, 0.0, 1.0
38984		);
38985
38986		shadowMatrix.multiply( shadowCamera.projectionMatrix );
38987		shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
38988
38989	},
38990
38991	getViewport: function ( viewportIndex ) {
38992
38993		return this._viewports[ viewportIndex ];
38994
38995	},
38996
38997	getFrameExtents: function () {
38998
38999		return this._frameExtents;
39000
39001	},
39002
39003	copy: function ( source ) {
39004
39005		this.camera = source.camera.clone();
39006
39007		this.bias = source.bias;
39008		this.radius = source.radius;
39009
39010		this.mapSize.copy( source.mapSize );
39011
39012		return this;
39013
39014	},
39015
39016	clone: function () {
39017
39018		return new this.constructor().copy( this );
39019
39020	},
39021
39022	toJSON: function () {
39023
39024		var object = {};
39025
39026		if ( this.bias !== 0 ) object.bias = this.bias;
39027		if ( this.radius !== 1 ) object.radius = this.radius;
39028		if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
39029
39030		object.camera = this.camera.toJSON( false ).object;
39031		delete object.camera.matrix;
39032
39033		return object;
39034
39035	}
39036
39037} );
39038
39039/**
39040 * @author mrdoob / http://mrdoob.com/
39041 */
39042
39043function SpotLightShadow() {
39044
39045	LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );
39046
39047}
39048
39049SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39050
39051	constructor: SpotLightShadow,
39052
39053	isSpotLightShadow: true,
39054
39055	updateMatrices: function ( light ) {
39056
39057		var camera = this.camera;
39058
39059		var fov = MathUtils.RAD2DEG * 2 * light.angle;
39060		var aspect = this.mapSize.width / this.mapSize.height;
39061		var far = light.distance || camera.far;
39062
39063		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
39064
39065			camera.fov = fov;
39066			camera.aspect = aspect;
39067			camera.far = far;
39068			camera.updateProjectionMatrix();
39069
39070		}
39071
39072		LightShadow.prototype.updateMatrices.call( this, light );
39073
39074	}
39075
39076} );
39077
39078/**
39079 * @author alteredq / http://alteredqualia.com/
39080 */
39081
39082function SpotLight( color, intensity, distance, angle, penumbra, decay ) {
39083
39084	Light.call( this, color, intensity );
39085
39086	this.type = 'SpotLight';
39087
39088	this.position.copy( Object3D.DefaultUp );
39089	this.updateMatrix();
39090
39091	this.target = new Object3D();
39092
39093	Object.defineProperty( this, 'power', {
39094		get: function () {
39095
39096			// intensity = power per solid angle.
39097			// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39098			return this.intensity * Math.PI;
39099
39100		},
39101		set: function ( power ) {
39102
39103			// intensity = power per solid angle.
39104			// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39105			this.intensity = power / Math.PI;
39106
39107		}
39108	} );
39109
39110	this.distance = ( distance !== undefined ) ? distance : 0;
39111	this.angle = ( angle !== undefined ) ? angle : Math.PI / 3;
39112	this.penumbra = ( penumbra !== undefined ) ? penumbra : 0;
39113	this.decay = ( decay !== undefined ) ? decay : 1;	// for physically correct lights, should be 2.
39114
39115	this.shadow = new SpotLightShadow();
39116
39117}
39118
39119SpotLight.prototype = Object.assign( Object.create( Light.prototype ), {
39120
39121	constructor: SpotLight,
39122
39123	isSpotLight: true,
39124
39125	copy: function ( source ) {
39126
39127		Light.prototype.copy.call( this, source );
39128
39129		this.distance = source.distance;
39130		this.angle = source.angle;
39131		this.penumbra = source.penumbra;
39132		this.decay = source.decay;
39133
39134		this.target = source.target.clone();
39135
39136		this.shadow = source.shadow.clone();
39137
39138		return this;
39139
39140	}
39141
39142} );
39143
39144function PointLightShadow() {
39145
39146	LightShadow.call( this, new PerspectiveCamera( 90, 1, 0.5, 500 ) );
39147
39148	this._frameExtents = new Vector2( 4, 2 );
39149
39150	this._viewportCount = 6;
39151
39152	this._viewports = [
39153		// These viewports map a cube-map onto a 2D texture with the
39154		// following orientation:
39155		//
39156		//  xzXZ
39157		//   y Y
39158		//
39159		// X - Positive x direction
39160		// x - Negative x direction
39161		// Y - Positive y direction
39162		// y - Negative y direction
39163		// Z - Positive z direction
39164		// z - Negative z direction
39165
39166		// positive X
39167		new Vector4( 2, 1, 1, 1 ),
39168		// negative X
39169		new Vector4( 0, 1, 1, 1 ),
39170		// positive Z
39171		new Vector4( 3, 1, 1, 1 ),
39172		// negative Z
39173		new Vector4( 1, 1, 1, 1 ),
39174		// positive Y
39175		new Vector4( 3, 0, 1, 1 ),
39176		// negative Y
39177		new Vector4( 1, 0, 1, 1 )
39178	];
39179
39180	this._cubeDirections = [
39181		new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
39182		new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
39183	];
39184
39185	this._cubeUps = [
39186		new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
39187		new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),	new Vector3( 0, 0, - 1 )
39188	];
39189
39190}
39191
39192PointLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39193
39194	constructor: PointLightShadow,
39195
39196	isPointLightShadow: true,
39197
39198	updateMatrices: function ( light, viewportIndex ) {
39199
39200		if ( viewportIndex === undefined ) viewportIndex = 0;
39201
39202		var camera = this.camera,
39203			shadowMatrix = this.matrix,
39204			lightPositionWorld = this._lightPositionWorld,
39205			lookTarget = this._lookTarget,
39206			projScreenMatrix = this._projScreenMatrix;
39207
39208		lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
39209		camera.position.copy( lightPositionWorld );
39210
39211		lookTarget.copy( camera.position );
39212		lookTarget.add( this._cubeDirections[ viewportIndex ] );
39213		camera.up.copy( this._cubeUps[ viewportIndex ] );
39214		camera.lookAt( lookTarget );
39215		camera.updateMatrixWorld();
39216
39217		shadowMatrix.makeTranslation( - lightPositionWorld.x, - lightPositionWorld.y, - lightPositionWorld.z );
39218
39219		projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
39220		this._frustum.setFromProjectionMatrix( projScreenMatrix );
39221
39222	}
39223
39224} );
39225
39226/**
39227 * @author mrdoob / http://mrdoob.com/
39228 */
39229
39230
39231function PointLight( color, intensity, distance, decay ) {
39232
39233	Light.call( this, color, intensity );
39234
39235	this.type = 'PointLight';
39236
39237	Object.defineProperty( this, 'power', {
39238		get: function () {
39239
39240			// intensity = power per solid angle.
39241			// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39242			return this.intensity * 4 * Math.PI;
39243
39244		},
39245		set: function ( power ) {
39246
39247			// intensity = power per solid angle.
39248			// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
39249			this.intensity = power / ( 4 * Math.PI );
39250
39251		}
39252	} );
39253
39254	this.distance = ( distance !== undefined ) ? distance : 0;
39255	this.decay = ( decay !== undefined ) ? decay : 1;	// for physically correct lights, should be 2.
39256
39257	this.shadow = new PointLightShadow();
39258
39259}
39260
39261PointLight.prototype = Object.assign( Object.create( Light.prototype ), {
39262
39263	constructor: PointLight,
39264
39265	isPointLight: true,
39266
39267	copy: function ( source ) {
39268
39269		Light.prototype.copy.call( this, source );
39270
39271		this.distance = source.distance;
39272		this.decay = source.decay;
39273
39274		this.shadow = source.shadow.clone();
39275
39276		return this;
39277
39278	}
39279
39280} );
39281
39282/**
39283 * @author alteredq / http://alteredqualia.com/
39284 * @author arose / http://github.com/arose
39285 */
39286
39287function OrthographicCamera( left, right, top, bottom, near, far ) {
39288
39289	Camera.call( this );
39290
39291	this.type = 'OrthographicCamera';
39292
39293	this.zoom = 1;
39294	this.view = null;
39295
39296	this.left = ( left !== undefined ) ? left : - 1;
39297	this.right = ( right !== undefined ) ? right : 1;
39298	this.top = ( top !== undefined ) ? top : 1;
39299	this.bottom = ( bottom !== undefined ) ? bottom : - 1;
39300
39301	this.near = ( near !== undefined ) ? near : 0.1;
39302	this.far = ( far !== undefined ) ? far : 2000;
39303
39304	this.updateProjectionMatrix();
39305
39306}
39307
39308OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {
39309
39310	constructor: OrthographicCamera,
39311
39312	isOrthographicCamera: true,
39313
39314	copy: function ( source, recursive ) {
39315
39316		Camera.prototype.copy.call( this, source, recursive );
39317
39318		this.left = source.left;
39319		this.right = source.right;
39320		this.top = source.top;
39321		this.bottom = source.bottom;
39322		this.near = source.near;
39323		this.far = source.far;
39324
39325		this.zoom = source.zoom;
39326		this.view = source.view === null ? null : Object.assign( {}, source.view );
39327
39328		return this;
39329
39330	},
39331
39332	setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {
39333
39334		if ( this.view === null ) {
39335
39336			this.view = {
39337				enabled: true,
39338				fullWidth: 1,
39339				fullHeight: 1,
39340				offsetX: 0,
39341				offsetY: 0,
39342				width: 1,
39343				height: 1
39344			};
39345
39346		}
39347
39348		this.view.enabled = true;
39349		this.view.fullWidth = fullWidth;
39350		this.view.fullHeight = fullHeight;
39351		this.view.offsetX = x;
39352		this.view.offsetY = y;
39353		this.view.width = width;
39354		this.view.height = height;
39355
39356		this.updateProjectionMatrix();
39357
39358	},
39359
39360	clearViewOffset: function () {
39361
39362		if ( this.view !== null ) {
39363
39364			this.view.enabled = false;
39365
39366		}
39367
39368		this.updateProjectionMatrix();
39369
39370	},
39371
39372	updateProjectionMatrix: function () {
39373
39374		var dx = ( this.right - this.left ) / ( 2 * this.zoom );
39375		var dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
39376		var cx = ( this.right + this.left ) / 2;
39377		var cy = ( this.top + this.bottom ) / 2;
39378
39379		var left = cx - dx;
39380		var right = cx + dx;
39381		var top = cy + dy;
39382		var bottom = cy - dy;
39383
39384		if ( this.view !== null && this.view.enabled ) {
39385
39386			var scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
39387			var scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
39388
39389			left += scaleW * this.view.offsetX;
39390			right = left + scaleW * this.view.width;
39391			top -= scaleH * this.view.offsetY;
39392			bottom = top - scaleH * this.view.height;
39393
39394		}
39395
39396		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
39397
39398		this.projectionMatrixInverse.getInverse( this.projectionMatrix );
39399
39400	},
39401
39402	toJSON: function ( meta ) {
39403
39404		var data = Object3D.prototype.toJSON.call( this, meta );
39405
39406		data.object.zoom = this.zoom;
39407		data.object.left = this.left;
39408		data.object.right = this.right;
39409		data.object.top = this.top;
39410		data.object.bottom = this.bottom;
39411		data.object.near = this.near;
39412		data.object.far = this.far;
39413
39414		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
39415
39416		return data;
39417
39418	}
39419
39420} );
39421
39422/**
39423 * @author mrdoob / http://mrdoob.com/
39424 */
39425
39426function DirectionalLightShadow() {
39427
39428	LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
39429
39430}
39431
39432DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {
39433
39434	constructor: DirectionalLightShadow,
39435
39436	isDirectionalLightShadow: true,
39437
39438	updateMatrices: function ( light ) {
39439
39440		LightShadow.prototype.updateMatrices.call( this, light );
39441
39442	}
39443
39444} );
39445
39446/**
39447 * @author mrdoob / http://mrdoob.com/
39448 * @author alteredq / http://alteredqualia.com/
39449 */
39450
39451function DirectionalLight( color, intensity ) {
39452
39453	Light.call( this, color, intensity );
39454
39455	this.type = 'DirectionalLight';
39456
39457	this.position.copy( Object3D.DefaultUp );
39458	this.updateMatrix();
39459
39460	this.target = new Object3D();
39461
39462	this.shadow = new DirectionalLightShadow();
39463
39464}
39465
39466DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {
39467
39468	constructor: DirectionalLight,
39469
39470	isDirectionalLight: true,
39471
39472	copy: function ( source ) {
39473
39474		Light.prototype.copy.call( this, source );
39475
39476		this.target = source.target.clone();
39477
39478		this.shadow = source.shadow.clone();
39479
39480		return this;
39481
39482	}
39483
39484} );
39485
39486/**
39487 * @author mrdoob / http://mrdoob.com/
39488 */
39489
39490function AmbientLight( color, intensity ) {
39491
39492	Light.call( this, color, intensity );
39493
39494	this.type = 'AmbientLight';
39495
39496	this.castShadow = undefined;
39497
39498}
39499
39500AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {
39501
39502	constructor: AmbientLight,
39503
39504	isAmbientLight: true
39505
39506} );
39507
39508/**
39509 * @author abelnation / http://github.com/abelnation
39510 */
39511
39512function RectAreaLight( color, intensity, width, height ) {
39513
39514	Light.call( this, color, intensity );
39515
39516	this.type = 'RectAreaLight';
39517
39518	this.width = ( width !== undefined ) ? width : 10;
39519	this.height = ( height !== undefined ) ? height : 10;
39520
39521}
39522
39523RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
39524
39525	constructor: RectAreaLight,
39526
39527	isRectAreaLight: true,
39528
39529	copy: function ( source ) {
39530
39531		Light.prototype.copy.call( this, source );
39532
39533		this.width = source.width;
39534		this.height = source.height;
39535
39536		return this;
39537
39538	},
39539
39540	toJSON: function ( meta ) {
39541
39542		var data = Light.prototype.toJSON.call( this, meta );
39543
39544		data.object.width = this.width;
39545		data.object.height = this.height;
39546
39547		return data;
39548
39549	}
39550
39551} );
39552
39553/**
39554 * @author bhouston / http://clara.io
39555 * @author WestLangley / http://github.com/WestLangley
39556 *
39557 * Primary reference:
39558 *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
39559 *
39560 * Secondary reference:
39561 *   https://www.ppsloan.org/publications/StupidSH36.pdf
39562 */
39563
39564// 3-band SH defined by 9 coefficients
39565
39566function SphericalHarmonics3() {
39567
39568	this.coefficients = [];
39569
39570	for ( var i = 0; i < 9; i ++ ) {
39571
39572		this.coefficients.push( new Vector3() );
39573
39574	}
39575
39576}
39577
39578Object.assign( SphericalHarmonics3.prototype, {
39579
39580	isSphericalHarmonics3: true,
39581
39582	set: function ( coefficients ) {
39583
39584		for ( var i = 0; i < 9; i ++ ) {
39585
39586			this.coefficients[ i ].copy( coefficients[ i ] );
39587
39588		}
39589
39590		return this;
39591
39592	},
39593
39594	zero: function () {
39595
39596		for ( var i = 0; i < 9; i ++ ) {
39597
39598			this.coefficients[ i ].set( 0, 0, 0 );
39599
39600		}
39601
39602		return this;
39603
39604	},
39605
39606	// get the radiance in the direction of the normal
39607	// target is a Vector3
39608	getAt: function ( normal, target ) {
39609
39610		// normal is assumed to be unit length
39611
39612		var x = normal.x, y = normal.y, z = normal.z;
39613
39614		var coeff = this.coefficients;
39615
39616		// band 0
39617		target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
39618
39619		// band 1
39620		target.addScaledVector( coeff[ 1 ], 0.488603 * y );
39621		target.addScaledVector( coeff[ 2 ], 0.488603 * z );
39622		target.addScaledVector( coeff[ 3 ], 0.488603 * x );
39623
39624		// band 2
39625		target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
39626		target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
39627		target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
39628		target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
39629		target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
39630
39631		return target;
39632
39633	},
39634
39635	// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
39636	// target is a Vector3
39637	// https://graphics.stanford.edu/papers/envmap/envmap.pdf
39638	getIrradianceAt: function ( normal, target ) {
39639
39640		// normal is assumed to be unit length
39641
39642		var x = normal.x, y = normal.y, z = normal.z;
39643
39644		var coeff = this.coefficients;
39645
39646		// band 0
39647		target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
39648
39649		// band 1
39650		target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
39651		target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
39652		target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
39653
39654		// band 2
39655		target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
39656		target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
39657		target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
39658		target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
39659		target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
39660
39661		return target;
39662
39663	},
39664
39665	add: function ( sh ) {
39666
39667		for ( var i = 0; i < 9; i ++ ) {
39668
39669			this.coefficients[ i ].add( sh.coefficients[ i ] );
39670
39671		}
39672
39673		return this;
39674
39675	},
39676
39677	addScaledSH: function ( sh, s ) {
39678
39679		for ( var i = 0; i < 9; i ++ ) {
39680
39681			this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
39682
39683		}
39684
39685		return this;
39686
39687	},
39688
39689	scale: function ( s ) {
39690
39691		for ( var i = 0; i < 9; i ++ ) {
39692
39693			this.coefficients[ i ].multiplyScalar( s );
39694
39695		}
39696
39697		return this;
39698
39699	},
39700
39701	lerp: function ( sh, alpha ) {
39702
39703		for ( var i = 0; i < 9; i ++ ) {
39704
39705			this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
39706
39707		}
39708
39709		return this;
39710
39711	},
39712
39713	equals: function ( sh ) {
39714
39715		for ( var i = 0; i < 9; i ++ ) {
39716
39717			if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
39718
39719				return false;
39720
39721			}
39722
39723		}
39724
39725		return true;
39726
39727	},
39728
39729	copy: function ( sh ) {
39730
39731		return this.set( sh.coefficients );
39732
39733	},
39734
39735	clone: function () {
39736
39737		return new this.constructor().copy( this );
39738
39739	},
39740
39741	fromArray: function ( array, offset ) {
39742
39743		if ( offset === undefined ) offset = 0;
39744
39745		var coefficients = this.coefficients;
39746
39747		for ( var i = 0; i < 9; i ++ ) {
39748
39749			coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
39750
39751		}
39752
39753		return this;
39754
39755	},
39756
39757	toArray: function ( array, offset ) {
39758
39759		if ( array === undefined ) array = [];
39760		if ( offset === undefined ) offset = 0;
39761
39762		var coefficients = this.coefficients;
39763
39764		for ( var i = 0; i < 9; i ++ ) {
39765
39766			coefficients[ i ].toArray( array, offset + ( i * 3 ) );
39767
39768		}
39769
39770		return array;
39771
39772	}
39773
39774} );
39775
39776Object.assign( SphericalHarmonics3, {
39777
39778	// evaluate the basis functions
39779	// shBasis is an Array[ 9 ]
39780	getBasisAt: function ( normal, shBasis ) {
39781
39782		// normal is assumed to be unit length
39783
39784		var x = normal.x, y = normal.y, z = normal.z;
39785
39786		// band 0
39787		shBasis[ 0 ] = 0.282095;
39788
39789		// band 1
39790		shBasis[ 1 ] = 0.488603 * y;
39791		shBasis[ 2 ] = 0.488603 * z;
39792		shBasis[ 3 ] = 0.488603 * x;
39793
39794		// band 2
39795		shBasis[ 4 ] = 1.092548 * x * y;
39796		shBasis[ 5 ] = 1.092548 * y * z;
39797		shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
39798		shBasis[ 7 ] = 1.092548 * x * z;
39799		shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
39800
39801	}
39802
39803} );
39804
39805/**
39806 * @author WestLangley / http://github.com/WestLangley
39807 *
39808 * A LightProbe is a source of indirect-diffuse light
39809 */
39810
39811function LightProbe( sh, intensity ) {
39812
39813	Light.call( this, undefined, intensity );
39814
39815	this.type = 'LightProbe';
39816
39817	this.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();
39818
39819}
39820
39821LightProbe.prototype = Object.assign( Object.create( Light.prototype ), {
39822
39823	constructor: LightProbe,
39824
39825	isLightProbe: true,
39826
39827	copy: function ( source ) {
39828
39829		Light.prototype.copy.call( this, source );
39830
39831		this.sh.copy( source.sh );
39832
39833		return this;
39834
39835	},
39836
39837	fromJSON: function ( json ) {
39838
39839		this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
39840		this.sh.fromArray( json.sh );
39841
39842		return this;
39843
39844	},
39845
39846	toJSON: function ( meta ) {
39847
39848		var data = Light.prototype.toJSON.call( this, meta );
39849
39850		data.object.sh = this.sh.toArray();
39851
39852		return data;
39853
39854	}
39855
39856} );
39857
39858/**
39859 * @author mrdoob / http://mrdoob.com/
39860 */
39861
39862function MaterialLoader( manager ) {
39863
39864	Loader.call( this, manager );
39865
39866	this.textures = {};
39867
39868}
39869
39870MaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
39871
39872	constructor: MaterialLoader,
39873
39874	load: function ( url, onLoad, onProgress, onError ) {
39875
39876		var scope = this;
39877
39878		var loader = new FileLoader( scope.manager );
39879		loader.setPath( scope.path );
39880		loader.load( url, function ( text ) {
39881
39882			onLoad( scope.parse( JSON.parse( text ) ) );
39883
39884		}, onProgress, onError );
39885
39886	},
39887
39888	parse: function ( json ) {
39889
39890		var textures = this.textures;
39891
39892		function getTexture( name ) {
39893
39894			if ( textures[ name ] === undefined ) {
39895
39896				console.warn( 'THREE.MaterialLoader: Undefined texture', name );
39897
39898			}
39899
39900			return textures[ name ];
39901
39902		}
39903
39904		var material = new Materials[ json.type ]();
39905
39906		if ( json.uuid !== undefined ) material.uuid = json.uuid;
39907		if ( json.name !== undefined ) material.name = json.name;
39908		if ( json.color !== undefined ) material.color.setHex( json.color );
39909		if ( json.roughness !== undefined ) material.roughness = json.roughness;
39910		if ( json.metalness !== undefined ) material.metalness = json.metalness;
39911		if ( json.sheen !== undefined ) material.sheen = new Color().setHex( json.sheen );
39912		if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive );
39913		if ( json.specular !== undefined ) material.specular.setHex( json.specular );
39914		if ( json.shininess !== undefined ) material.shininess = json.shininess;
39915		if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
39916		if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
39917		if ( json.fog !== undefined ) material.fog = json.fog;
39918		if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
39919		if ( json.blending !== undefined ) material.blending = json.blending;
39920		if ( json.combine !== undefined ) material.combine = json.combine;
39921		if ( json.side !== undefined ) material.side = json.side;
39922		if ( json.opacity !== undefined ) material.opacity = json.opacity;
39923		if ( json.transparent !== undefined ) material.transparent = json.transparent;
39924		if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
39925		if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
39926		if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
39927		if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
39928
39929		if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
39930		if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
39931		if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
39932		if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
39933		if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
vendor: 8,815 bytes, lines 39934-40232
39934		if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
39935		if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
39936		if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
39937
39938		if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
39939		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
39940		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
39941		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
39942
39943		if ( json.rotation !== undefined ) material.rotation = json.rotation;
39944
39945		if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
39946		if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
39947		if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
39948		if ( json.scale !== undefined ) material.scale = json.scale;
39949
39950		if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
39951		if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
39952		if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
39953
39954		if ( json.skinning !== undefined ) material.skinning = json.skinning;
39955		if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
39956		if ( json.morphNormals !== undefined ) material.morphNormals = json.morphNormals;
39957		if ( json.dithering !== undefined ) material.dithering = json.dithering;
39958
39959		if ( json.vertexTangents !== undefined ) material.vertexTangents = json.vertexTangents;
39960
39961		if ( json.visible !== undefined ) material.visible = json.visible;
39962
39963		if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
39964
39965		if ( json.userData !== undefined ) material.userData = json.userData;
39966
39967		if ( json.vertexColors !== undefined ) {
39968
39969			if ( typeof json.vertexColors === 'number' ) {
39970
39971				material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
39972
39973			} else {
39974
39975				material.vertexColors = json.vertexColors;
39976
39977			}
39978
39979		}
39980
39981		// Shader Material
39982
39983		if ( json.uniforms !== undefined ) {
39984
39985			for ( var name in json.uniforms ) {
39986
39987				var uniform = json.uniforms[ name ];
39988
39989				material.uniforms[ name ] = {};
39990
39991				switch ( uniform.type ) {
39992
39993					case 't':
39994						material.uniforms[ name ].value = getTexture( uniform.value );
39995						break;
39996
39997					case 'c':
39998						material.uniforms[ name ].value = new Color().setHex( uniform.value );
39999						break;
40000
40001					case 'v2':
40002						material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
40003						break;
40004
40005					case 'v3':
40006						material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
40007						break;
40008
40009					case 'v4':
40010						material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
40011						break;
40012
40013					case 'm3':
40014						material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
40015
40016					case 'm4':
40017						material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
40018						break;
40019
40020					default:
40021						material.uniforms[ name ].value = uniform.value;
40022
40023				}
40024
40025			}
40026
40027		}
40028
40029		if ( json.defines !== undefined ) material.defines = json.defines;
40030		if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
40031		if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
40032
40033		if ( json.extensions !== undefined ) {
40034
40035			for ( var key in json.extensions ) {
40036
40037				material.extensions[ key ] = json.extensions[ key ];
40038
40039			}
40040
40041		}
40042
40043		// Deprecated
40044
40045		if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading
40046
40047		// for PointsMaterial
40048
40049		if ( json.size !== undefined ) material.size = json.size;
40050		if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
40051
40052		// maps
40053
40054		if ( json.map !== undefined ) material.map = getTexture( json.map );
40055		if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
40056
40057		if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
40058
40059		if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
40060		if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
40061
40062		if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
40063		if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
40064		if ( json.normalScale !== undefined ) {
40065
40066			var normalScale = json.normalScale;
40067
40068			if ( Array.isArray( normalScale ) === false ) {
40069
40070				// Blender exporter used to export a scalar. See #7459
40071
40072				normalScale = [ normalScale, normalScale ];
40073
40074			}
40075
40076			material.normalScale = new Vector2().fromArray( normalScale );
40077
40078		}
40079
40080		if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
40081		if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
40082		if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
40083
40084		if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
40085		if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
40086
40087		if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
40088		if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
40089
40090		if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
40091
40092		if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
40093		if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
40094
40095		if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
40096		if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
40097
40098		if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
40099		if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
40100
40101		if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
40102		if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
40103
40104		if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
40105
40106		if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
40107		if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
40108		if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
40109		if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
40110
40111		return material;
40112
40113	},
40114
40115	setTextures: function ( value ) {
40116
40117		this.textures = value;
40118		return this;
40119
40120	}
40121
40122} );
40123
40124/**
40125 * @author Don McCurdy / https://www.donmccurdy.com
40126 */
40127
40128var LoaderUtils = {
40129
40130	decodeText: function ( array ) {
40131
40132		if ( typeof TextDecoder !== 'undefined' ) {
40133
40134			return new TextDecoder().decode( array );
40135
40136		}
40137
40138		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
40139		// throws a "maximum call stack size exceeded" error for large arrays.
40140
40141		var s = '';
40142
40143		for ( var i = 0, il = array.length; i < il; i ++ ) {
40144
40145			// Implicitly assumes little-endian.
40146			s += String.fromCharCode( array[ i ] );
40147
40148		}
40149
40150		try {
40151
40152			// merges multi-byte utf-8 characters.
40153
40154			return decodeURIComponent( escape( s ) );
40155
40156		} catch ( e ) { // see #16358
40157
40158			return s;
40159
40160		}
40161
40162	},
40163
40164	extractUrlBase: function ( url ) {
40165
40166		var index = url.lastIndexOf( '/' );
40167
40168		if ( index === - 1 ) return './';
40169
40170		return url.substr( 0, index + 1 );
40171
40172	}
40173
40174};
40175
40176/**
40177 * @author benaadams / https://twitter.com/ben_a_adams
40178 */
40179
40180function InstancedBufferGeometry() {
40181
40182	BufferGeometry.call( this );
40183
40184	this.type = 'InstancedBufferGeometry';
40185	this.maxInstancedCount = undefined;
40186
40187}
40188
40189InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {
40190
40191	constructor: InstancedBufferGeometry,
40192
40193	isInstancedBufferGeometry: true,
40194
40195	copy: function ( source ) {
40196
40197		BufferGeometry.prototype.copy.call( this, source );
40198
40199		this.maxInstancedCount = source.maxInstancedCount;
40200
40201		return this;
40202
40203	},
40204
40205	clone: function () {
40206
40207		return new this.constructor().copy( this );
40208
40209	},
40210
40211	toJSON: function () {
40212
40213		var data = BufferGeometry.prototype.toJSON.call( this );
40214
40215		data.maxInstancedCount = this.maxInstancedCount;
40216
40217		data.isInstancedBufferGeometry = true;
40218
40219		return data;
40220
40221	}
40222
40223} );
40224
40225/**
40226 * @author benaadams / https://twitter.com/ben_a_adams
40227 */
40228
40229function InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {
40230
40231	if ( typeof ( normalized ) === 'number' ) {
40232
40233		meshPerAttribute = normalized;
40234
40235		normalized = false;
40236
40237		console.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );
40238
40239	}
40240
40241	BufferAttribute.call( this, array, itemSize, normalized );
40242
40243	this.meshPerAttribute = meshPerAttribute || 1;
40244
40245}
40246
40247InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {
40248
40249	constructor: InstancedBufferAttribute,
40250
40251	isInstancedBufferAttribute: true,
40252
40253	copy: function ( source ) {
40254
40255		BufferAttribute.prototype.copy.call( this, source );
40256
40257		this.meshPerAttribute = source.meshPerAttribute;
40258
40259		return this;
40260
40261	},
40262
40263	toJSON: function ()	{
40264
40265		var data = BufferAttribute.prototype.toJSON.call( this );
40266
40267		data.meshPerAttribute = this.meshPerAttribute;
40268
40269		data.isInstancedBufferAttribute = true;
40270
40271		return data;
40272
40273	}
40274
40275} );
40276
40277/**
40278 * @author mrdoob / http://mrdoob.com/
40279 */
40280
40281function BufferGeometryLoader( manager ) {
40282
40283	Loader.call( this, manager );
40284
40285}
40286
40287BufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40288
40289	constructor: BufferGeometryLoader,
40290
40291	load: function ( url, onLoad, onProgress, onError ) {
40292
40293		var scope = this;
40294
40295		var loader = new FileLoader( scope.manager );
40296		loader.setPath( scope.path );
40297		loader.load( url, function ( text ) {
40298
40299			onLoad( scope.parse( JSON.parse( text ) ) );
40300
40301		}, onProgress, onError );
40302
40303	},
40304
40305	parse: function ( json ) {
40306
40307		var geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
40308
40309		var index = json.data.index;
40310
40311		if ( index !== undefined ) {
40312
40313			var typedArray = new TYPED_ARRAYS[ index.type ]( index.array );
40314			geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
40315
40316		}
40317
40318		var attributes = json.data.attributes;
40319
40320		for ( var key in attributes ) {
40321
40322			var attribute = attributes[ key ];
40323			var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
40324			var bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
40325			var bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
40326			if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
40327			geometry.setAttribute( key, bufferAttribute );
40328
40329		}
40330
40331		var morphAttributes = json.data.morphAttributes;
40332
40333		if ( morphAttributes ) {
40334
40335			for ( var key in morphAttributes ) {
40336
40337				var attributeArray = morphAttributes[ key ];
40338
40339				var array = [];
40340
40341				for ( var i = 0, il = attributeArray.length; i < il; i ++ ) {
40342
40343					var attribute = attributeArray[ i ];
40344					var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );
40345
40346					var bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
40347					if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
40348					array.push( bufferAttribute );
40349
40350				}
40351
40352				geometry.morphAttributes[ key ] = array;
40353
40354			}
40355
40356		}
40357
40358		var morphTargetsRelative = json.data.morphTargetsRelative;
40359
40360		if ( morphTargetsRelative ) {
40361
40362			geometry.morphTargetsRelative = true;
40363
40364		}
40365
40366		var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
40367
40368		if ( groups !== undefined ) {
40369
40370			for ( var i = 0, n = groups.length; i !== n; ++ i ) {
40371
40372				var group = groups[ i ];
40373
40374				geometry.addGroup( group.start, group.count, group.materialIndex );
40375
40376			}
40377
40378		}
40379
40380		var boundingSphere = json.data.boundingSphere;
40381
40382		if ( boundingSphere !== undefined ) {
40383
40384			var center = new Vector3();
40385
40386			if ( boundingSphere.center !== undefined ) {
40387
40388				center.fromArray( boundingSphere.center );
40389
40390			}
40391
40392			geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
40393
40394		}
40395
40396		if ( json.name ) geometry.name = json.name;
40397		if ( json.userData ) geometry.userData = json.userData;
40398
40399		return geometry;
40400
40401	}
40402
40403} );
40404
40405var TYPED_ARRAYS = {
40406	Int8Array: Int8Array,
40407	Uint8Array: Uint8Array,
40408	// Workaround for IE11 pre KB2929437. See #11440
40409	Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,
40410	Int16Array: Int16Array,
40411	Uint16Array: Uint16Array,
40412	Int32Array: Int32Array,
40413	Uint32Array: Uint32Array,
40414	Float32Array: Float32Array,
40415	Float64Array: Float64Array
40416};
40417
40418/**
40419 * @author mrdoob / http://mrdoob.com/
40420 */
40421
40422function ObjectLoader( manager ) {
40423
40424	Loader.call( this, manager );
40425
40426}
40427
40428ObjectLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
40429
40430	constructor: ObjectLoader,
40431
40432	load: function ( url, onLoad, onProgress, onError ) {
40433
40434		var scope = this;
40435
40436		var path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
40437		this.resourcePath = this.resourcePath || path;
40438
40439		var loader = new FileLoader( scope.manager );
40440		loader.setPath( this.path );
40441		loader.load( url, function ( text ) {
40442
40443			var json = null;
40444
40445			try {
40446
40447				json = JSON.parse( text );
40448
40449			} catch ( error ) {
40450
40451				if ( onError !== undefined ) onError( error );
40452
40453				console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
40454
40455				return;
40456
40457			}
40458
40459			var metadata = json.metadata;
40460
40461			if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
40462
40463				console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
40464				return;
40465
40466			}
40467
40468			scope.parse( json, onLoad );
40469
40470		}, onProgress, onError );
40471
40472	},
40473
40474	parse: function ( json, onLoad ) {
40475
40476		var shapes = this.parseShape( json.shapes );
40477		var geometries = this.parseGeometries( json.geometries, shapes );
40478
40479		var images = this.parseImages( json.images, function () {
40480
40481			if ( onLoad !== undefined ) onLoad( object );
40482
40483		} );
40484
40485		var textures = this.parseTextures( json.textures, images );
40486		var materials = this.parseMaterials( json.materials, textures );
40487
40488		var object = this.parseObject( json.object, geometries, materials );
40489
40490		if ( json.animations ) {
40491
40492			object.animations = this.parseAnimations( json.animations );
40493
40494		}
40495
40496		if ( json.images === undefined || json.images.length === 0 ) {
40497
40498			if ( onLoad !== undefined ) onLoad( object );
40499
40500		}
40501
40502		return object;
40503
40504	},
40505
40506	parseShape: function ( json ) {
40507
40508		var shapes = {};
40509
40510		if ( json !== undefined ) {
40511
40512			for ( var i = 0, l = json.length; i < l; i ++ ) {
40513
40514				var shape = new Shape().fromJSON( json[ i ] );
40515
40516				shapes[ shape.uuid ] = shape;
40517
40518			}
40519
40520		}
40521
40522		return shapes;
40523
40524	},
40525
40526	parseGeometries: function ( json, shapes ) {
40527
40528		var geometries = {};
40529
40530		if ( json !== undefined ) {
40531
40532			var bufferGeometryLoader = new BufferGeometryLoader();
40533
40534			for ( var i = 0, l = json.length; i < l; i ++ ) {
40535
40536				var geometry;
40537				var data = json[ i ];
40538
40539				switch ( data.type ) {
40540
40541					case 'PlaneGeometry':
40542					case 'PlaneBufferGeometry':
40543
40544						geometry = new Geometries[ data.type ](
40545							data.width,
40546							data.height,
40547							data.widthSegments,
40548							data.heightSegments
40549						);
40550
40551						break;
40552
40553					case 'BoxGeometry':
40554					case 'BoxBufferGeometry':
40555					case 'CubeGeometry': // backwards compatible
40556
40557						geometry = new Geometries[ data.type ](
40558							data.width,
40559							data.height,
40560							data.depth,
40561							data.widthSegments,
40562							data.heightSegments,
40563							data.depthSegments
40564						);
40565
40566						break;
40567
40568					case 'CircleGeometry':
40569					case 'CircleBufferGeometry':
40570
40571						geometry = new Geometries[ data.type ](
40572							data.radius,
40573							data.segments,
40574							data.thetaStart,
40575							data.thetaLength
40576						);
40577
40578						break;
40579
40580					case 'CylinderGeometry':
40581					case 'CylinderBufferGeometry':
40582
40583						geometry = new Geometries[ data.type ](
40584							data.radiusTop,
40585							data.radiusBottom,
40586							data.height,
40587							data.radialSegments,
40588							data.heightSegments,
40589							data.openEnded,
40590							data.thetaStart,
40591							data.thetaLength
40592						);
40593
40594						break;
40595
40596					case 'ConeGeometry':
40597					case 'ConeBufferGeometry':
40598
40599						geometry = new Geometries[ data.type ](
40600							data.radius,
40601							data.height,
40602							data.radialSegments,
40603							data.heightSegments,
40604							data.openEnded,
40605							data.thetaStart,
40606							data.thetaLength
40607						);
40608
40609						break;
40610
40611					case 'SphereGeometry':
40612					case 'SphereBufferGeometry':
40613
40614						geometry = new Geometries[ data.type ](
40615							data.radius,
40616							data.widthSegments,
40617							data.heightSegments,
40618							data.phiStart,
40619							data.phiLength,
40620							data.thetaStart,
40621							data.thetaLength
40622						);
40623
40624						break;
40625
40626					case 'DodecahedronGeometry':
40627					case 'DodecahedronBufferGeometry':
40628					case 'IcosahedronGeometry':
40629					case 'IcosahedronBufferGeometry':
40630					case 'OctahedronGeometry':
40631					case 'OctahedronBufferGeometry':
40632					case 'TetrahedronGeometry':
40633					case 'TetrahedronBufferGeometry':
40634
40635						geometry = new Geometries[ data.type ](
40636							data.radius,
40637							data.detail
40638						);
40639
40640						break;
40641
40642					case 'RingGeometry':
40643					case 'RingBufferGeometry':
40644
40645						geometry = new Geometries[ data.type ](
40646							data.innerRadius,
40647							data.outerRadius,
40648							data.thetaSegments,
40649							data.phiSegments,
40650							data.thetaStart,
40651							data.thetaLength
40652						);
40653
40654						break;
40655
40656					case 'TorusGeometry':
40657					case 'TorusBufferGeometry':
40658
40659						geometry = new Geometries[ data.type ](
40660							data.radius,
40661							data.tube,
40662							data.radialSegments,
40663							data.tubularSegments,
40664							data.arc
40665						);
40666
40667						break;
40668
40669					case 'TorusKnotGeometry':
40670					case 'TorusKnotBufferGeometry':
40671
40672						geometry = new Geometries[ data.type ](
40673							data.radius,
40674							data.tube,
40675							data.tubularSegments,
40676							data.radialSegments,
40677							data.p,
40678							data.q
40679						);
40680
40681						break;
40682
40683					case 'TubeGeometry':
40684					case 'TubeBufferGeometry':
40685
40686						// This only works for built-in curves (e.g. CatmullRomCurve3).
40687						// User defined curves or instances of CurvePath will not be deserialized.
40688						geometry = new Geometries[ data.type ](
40689							new Curves[ data.path.type ]().fromJSON( data.path ),
40690							data.tubularSegments,
40691							data.radius,
40692							data.radialSegments,
40693							data.closed
40694						);
40695
40696						break;
40697
40698					case 'LatheGeometry':
40699					case 'LatheBufferGeometry':
40700
40701						geometry = new Geometries[ data.type ](
40702							data.points,
40703							data.segments,
40704							data.phiStart,
40705							data.phiLength
40706						);
40707
40708						break;
40709
40710					case 'PolyhedronGeometry':
40711					case 'PolyhedronBufferGeometry':
40712
40713						geometry = new Geometries[ data.type ](
40714							data.vertices,
40715							data.indices,
40716							data.radius,
40717							data.details
40718						);
40719
40720						break;
40721
40722					case 'ShapeGeometry':
40723					case 'ShapeBufferGeometry':
40724
40725						var geometryShapes = [];
40726
40727						for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
40728
40729							var shape = shapes[ data.shapes[ j ] ];
40730
40731							geometryShapes.push( shape );
40732
40733						}
40734
40735						geometry = new Geometries[ data.type ](
40736							geometryShapes,
40737							data.curveSegments
40738						);
40739
40740						break;
40741
40742
40743					case 'ExtrudeGeometry':
40744					case 'ExtrudeBufferGeometry':
40745
40746						var geometryShapes = [];
40747
40748						for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {
40749
40750							var shape = shapes[ data.shapes[ j ] ];
40751
40752							geometryShapes.push( shape );
40753
40754						}
40755
40756						var extrudePath = data.options.extrudePath;
40757
40758						if ( extrudePath !== undefined ) {
40759
40760							data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
40761
40762						}
40763
40764						geometry = new Geometries[ data.type ](
40765							geometryShapes,
40766							data.options
40767						);
40768
40769						break;
40770
40771					case 'BufferGeometry':
40772					case 'InstancedBufferGeometry':
40773
40774						geometry = bufferGeometryLoader.parse( data );
40775
40776						break;
40777
40778					case 'Geometry':
40779
40780						console.error( 'THREE.ObjectLoader: Loading "Geometry" is not supported anymore.' );
40781
40782						break;
40783
40784					default:
40785
40786						console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' );
40787
40788						continue;
40789
40790				}
40791
40792				geometry.uuid = data.uuid;
40793
40794				if ( data.name !== undefined ) geometry.name = data.name;
40795				if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData;
40796
40797				geometries[ data.uuid ] = geometry;
40798
40799			}
40800
40801		}
40802
40803		return geometries;
40804
40805	},
40806
40807	parseMaterials: function ( json, textures ) {
40808
40809		var cache = {}; // MultiMaterial
40810		var materials = {};
40811
40812		if ( json !== undefined ) {
40813
40814			var loader = new MaterialLoader();
40815			loader.setTextures( textures );
40816
40817			for ( var i = 0, l = json.length; i < l; i ++ ) {
40818
40819				var data = json[ i ];
40820
40821				if ( data.type === 'MultiMaterial' ) {
40822
40823					// Deprecated
40824
40825					var array = [];
40826
40827					for ( var j = 0; j < data.materials.length; j ++ ) {
40828
40829						var material = data.materials[ j ];
40830
40831						if ( cache[ material.uuid ] === undefined ) {
40832
40833							cache[ material.uuid ] = loader.parse( material );
40834
40835						}
40836
40837						array.push( cache[ material.uuid ] );
40838
40839					}
40840
40841					materials[ data.uuid ] = array;
40842
40843				} else {
40844
40845					if ( cache[ data.uuid ] === undefined ) {
40846
40847						cache[ data.uuid ] = loader.parse( data );
40848
40849					}
40850
40851					materials[ data.uuid ] = cache[ data.uuid ];
40852
40853				}
40854
40855			}
40856
40857		}
40858
40859		return materials;
40860
40861	},
40862
40863	parseAnimations: function ( json ) {
40864
40865		var animations = [];
40866
40867		for ( var i = 0; i < json.length; i ++ ) {
40868
40869			var data = json[ i ];
40870
40871			var clip = AnimationClip.parse( data );
40872
40873			if ( data.uuid !== undefined ) clip.uuid = data.uuid;
40874
40875			animations.push( clip );
40876
40877		}
40878
40879		return animations;
40880
40881	},
40882
40883	parseImages: function ( json, onLoad ) {
40884
40885		var scope = this;
40886		var images = {};
40887
40888		function loadImage( url ) {
40889
40890			scope.manager.itemStart( url );
40891
40892			return loader.load( url, function () {
40893
40894				scope.manager.itemEnd( url );
40895
40896			}, undefined, function () {
40897
40898				scope.manager.itemError( url );
40899				scope.manager.itemEnd( url );
40900
40901			} );
40902
40903		}
40904
40905		if ( json !== undefined && json.length > 0 ) {
40906
40907			var manager = new LoadingManager( onLoad );
40908
40909			var loader = new ImageLoader( manager );
40910			loader.setCrossOrigin( this.crossOrigin );
40911
40912			for ( var i = 0, il = json.length; i < il; i ++ ) {
40913
40914				var image = json[ i ];
40915				var url = image.url;
40916
40917				if ( Array.isArray( url ) ) {
40918
40919					// load array of images e.g CubeTexture
40920
40921					images[ image.uuid ] = [];
40922
40923					for ( var j = 0, jl = url.length; j < jl; j ++ ) {
40924
40925						var currentUrl = url[ j ];
40926
40927						var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;
40928
40929						images[ image.uuid ].push( loadImage( path ) );
40930
40931					}
40932
40933				} else {
40934
40935					// load single image
40936
40937					var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;
40938
40939					images[ image.uuid ] = loadImage( path );
40940
40941				}
40942
40943			}
40944
40945		}
40946
40947		return images;
40948
40949	},
40950
40951	parseTextures: function ( json, images ) {
40952
40953		function parseConstant( value, type ) {
40954
40955			if ( typeof value === 'number' ) return value;
40956
40957			console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
40958
40959			return type[ value ];
40960
40961		}
40962
40963		var textures = {};
40964
40965		if ( json !== undefined ) {
40966
40967			for ( var i = 0, l = json.length; i < l; i ++ ) {
40968
40969				var data = json[ i ];
40970
40971				if ( data.image === undefined ) {
40972
40973					console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
40974
40975				}
40976
40977				if ( images[ data.image ] === undefined ) {
40978
40979					console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
40980
40981				}
40982
40983				var texture;
40984
40985				if ( Array.isArray( images[ data.image ] ) ) {
40986
40987					texture = new CubeTexture( images[ data.image ] );
40988
40989				} else {
40990
40991					texture = new Texture( images[ data.image ] );
40992
40993				}
40994
40995				texture.needsUpdate = true;
40996
40997				texture.uuid = data.uuid;
40998
40999				if ( data.name !== undefined ) texture.name = data.name;
41000
41001				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
41002
41003				if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
41004				if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
41005				if ( data.center !== undefined ) texture.center.fromArray( data.center );
41006				if ( data.rotation !== undefined ) texture.rotation = data.rotation;
41007
41008				if ( data.wrap !== undefined ) {
41009
41010					texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
41011					texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
41012
41013				}
41014
41015				if ( data.format !== undefined ) texture.format = data.format;
41016				if ( data.type !== undefined ) texture.type = data.type;
41017				if ( data.encoding !== undefined ) texture.encoding = data.encoding;
41018
41019				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
41020				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
41021				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
41022
41023				if ( data.flipY !== undefined ) texture.flipY = data.flipY;
41024
41025				if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
41026				if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
41027
41028				textures[ data.uuid ] = texture;
41029
41030			}
41031
41032		}
41033
41034		return textures;
41035
41036	},
41037
41038	parseObject: function ( data, geometries, materials ) {
41039
41040		var object;
41041
41042		function getGeometry( name ) {
41043
41044			if ( geometries[ name ] === undefined ) {
41045
41046				console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
41047
41048			}
41049
41050			return geometries[ name ];
41051
41052		}
41053
41054		function getMaterial( name ) {
41055
41056			if ( name === undefined ) return undefined;
41057
41058			if ( Array.isArray( name ) ) {
41059
41060				var array = [];
41061
41062				for ( var i = 0, l = name.length; i < l; i ++ ) {
41063
41064					var uuid = name[ i ];
41065
41066					if ( materials[ uuid ] === undefined ) {
41067
41068						console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
41069
41070					}
41071
41072					array.push( materials[ uuid ] );
41073
41074				}
41075
41076				return array;
41077
41078			}
41079
41080			if ( materials[ name ] === undefined ) {
41081
41082				console.warn( 'THREE.ObjectLoader: Undefined material', name );
41083
41084			}
41085
41086			return materials[ name ];
41087
41088		}
41089
41090		switch ( data.type ) {
41091
41092			case 'Scene':
41093
41094				object = new Scene();
41095
41096				if ( data.background !== undefined ) {
41097
41098					if ( Number.isInteger( data.background ) ) {
41099
41100						object.background = new Color( data.background );
41101
41102					}
41103
41104				}
41105
41106				if ( data.fog !== undefined ) {
41107
41108					if ( data.fog.type === 'Fog' ) {
41109
41110						object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
41111
41112					} else if ( data.fog.type === 'FogExp2' ) {
41113
41114						object.fog = new FogExp2( data.fog.color, data.fog.density );
41115
41116					}
41117
41118				}
41119
41120				break;
41121
41122			case 'PerspectiveCamera':
41123
41124				object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
41125
41126				if ( data.focus !== undefined ) object.focus = data.focus;
41127				if ( data.zoom !== undefined ) object.zoom = data.zoom;
41128				if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
41129				if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
41130				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
41131
41132				break;
41133
41134			case 'OrthographicCamera':
41135
41136				object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
41137
41138				if ( data.zoom !== undefined ) object.zoom = data.zoom;
41139				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
41140
41141				break;
41142
41143			case 'AmbientLight':
41144
41145				object = new AmbientLight( data.color, data.intensity );
41146
41147				break;
41148
41149			case 'DirectionalLight':
41150
41151				object = new DirectionalLight( data.color, data.intensity );
41152
41153				break;
41154
41155			case 'PointLight':
41156
41157				object = new PointLight( data.color, data.intensity, data.distance, data.decay );
41158
41159				break;
41160
41161			case 'RectAreaLight':
41162
41163				object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
41164
41165				break;
41166
41167			case 'SpotLight':
41168
41169				object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
41170
41171				break;
41172
41173			case 'HemisphereLight':
41174
41175				object = new HemisphereLight( data.color, data.groundColor, data.intensity );
41176
41177				break;
41178
41179			case 'LightProbe':
41180
41181				object = new LightProbe().fromJSON( data );
41182
41183				break;
41184
41185			case 'SkinnedMesh':
41186
41187				console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );
41188
41189			case 'Mesh':
41190
41191				var geometry = getGeometry( data.geometry );
41192				var material = getMaterial( data.material );
41193
41194				object = new Mesh( geometry, material );
41195
41196				break;
41197
41198			case 'InstancedMesh':
41199
41200				var geometry = getGeometry( data.geometry );
41201				var material = getMaterial( data.material );
41202				var count = data.count;
41203				var instanceMatrix = data.instanceMatrix;
41204
41205				object = new InstancedMesh( geometry, material, count );
41206				object.instanceMatrix = new BufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
41207
41208				break;
41209
41210			case 'LOD':
41211
41212				object = new LOD();
41213
41214				break;
41215
41216			case 'Line':
41217
41218				object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );
41219
41220				break;
41221
41222			case 'LineLoop':
41223
41224				object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
41225
41226				break;
41227
41228			case 'LineSegments':
41229
41230				object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
41231
41232				break;
41233
41234			case 'PointCloud':
41235			case 'Points':
41236
41237				object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
41238
41239				break;
41240
41241			case 'Sprite':
41242
41243				object = new Sprite( getMaterial( data.material ) );
41244
41245				break;
41246
41247			case 'Group':
41248
41249				object = new Group();
41250
41251				break;
41252
41253			default:
41254
41255				object = new Object3D();
41256
41257		}
41258
41259		object.uuid = data.uuid;
41260
41261		if ( data.name !== undefined ) object.name = data.name;
41262
41263		if ( data.matrix !== undefined ) {
41264
41265			object.matrix.fromArray( data.matrix );
41266
41267			if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
41268			if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
41269
41270		} else {
41271
41272			if ( data.position !== undefined ) object.position.fromArray( data.position );
41273			if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
41274			if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
41275			if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
41276
41277		}
41278
41279		if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
41280		if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
41281
41282		if ( data.shadow ) {
41283
41284			if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
41285			if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
41286			if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
41287			if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
41288
41289		}
41290
41291		if ( data.visible !== undefined ) object.visible = data.visible;
41292		if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
41293		if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
41294		if ( data.userData !== undefined ) object.userData = data.userData;
41295		if ( data.layers !== undefined ) object.layers.mask = data.layers;
41296
41297		if ( data.children !== undefined ) {
41298
41299			var children = data.children;
41300
41301			for ( var i = 0; i < children.length; i ++ ) {
41302
41303				object.add( this.parseObject( children[ i ], geometries, materials ) );
41304
41305			}
41306
41307		}
41308
41309		if ( data.type === 'LOD' ) {
41310
41311			if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
41312
41313			var levels = data.levels;
41314
41315			for ( var l = 0; l < levels.length; l ++ ) {
41316
41317				var level = levels[ l ];
41318				var child = object.getObjectByProperty( 'uuid', level.object );
41319
41320				if ( child !== undefined ) {
41321
41322					object.addLevel( child, level.distance );
41323
41324				}
41325
41326			}
41327
41328		}
41329
41330		return object;
41331
41332	}
41333
41334} );
41335
41336var TEXTURE_MAPPING = {
41337	UVMapping: UVMapping,
41338	CubeReflectionMapping: CubeReflectionMapping,
41339	CubeRefractionMapping: CubeRefractionMapping,
41340	EquirectangularReflectionMapping: EquirectangularReflectionMapping,
41341	EquirectangularRefractionMapping: EquirectangularRefractionMapping,
41342	SphericalReflectionMapping: SphericalReflectionMapping,
41343	CubeUVReflectionMapping: CubeUVReflectionMapping,
41344	CubeUVRefractionMapping: CubeUVRefractionMapping
41345};
41346
41347var TEXTURE_WRAPPING = {
41348	RepeatWrapping: RepeatWrapping,
41349	ClampToEdgeWrapping: ClampToEdgeWrapping,
41350	MirroredRepeatWrapping: MirroredRepeatWrapping
41351};
41352
41353var TEXTURE_FILTER = {
41354	NearestFilter: NearestFilter,
41355	NearestMipmapNearestFilter: NearestMipmapNearestFilter,
41356	NearestMipmapLinearFilter: NearestMipmapLinearFilter,
41357	LinearFilter: LinearFilter,
41358	LinearMipmapNearestFilter: LinearMipmapNearestFilter,
41359	LinearMipmapLinearFilter: LinearMipmapLinearFilter
41360};
41361
41362/**
41363 * @author thespite / http://clicktorelease.com/
41364 */
41365
41366
41367function ImageBitmapLoader( manager ) {
41368
41369	if ( typeof createImageBitmap === 'undefined' ) {
41370
41371		console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
41372
41373	}
41374
41375	if ( typeof fetch === 'undefined' ) {
41376
41377		console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
41378
41379	}
41380
41381	Loader.call( this, manager );
41382
41383	this.options = undefined;
41384
41385}
41386
41387ImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
41388
41389	constructor: ImageBitmapLoader,
41390
41391	setOptions: function setOptions( options ) {
41392
41393		this.options = options;
41394
41395		return this;
41396
41397	},
41398
41399	load: function ( url, onLoad, onProgress, onError ) {
41400
41401		if ( url === undefined ) url = '';
41402
41403		if ( this.path !== undefined ) url = this.path + url;
41404
41405		url = this.manager.resolveURL( url );
41406
41407		var scope = this;
41408
41409		var cached = Cache.get( url );
41410
41411		if ( cached !== undefined ) {
41412
41413			scope.manager.itemStart( url );
41414
41415			setTimeout( function () {
41416
41417				if ( onLoad ) onLoad( cached );
41418
41419				scope.manager.itemEnd( url );
41420
41421			}, 0 );
41422
41423			return cached;
41424
41425		}
41426
41427		fetch( url ).then( function ( res ) {
41428
41429			return res.blob();
41430
41431		} ).then( function ( blob ) {
41432
41433			if ( scope.options === undefined ) {
41434
41435				// Workaround for FireFox. It causes an error if you pass options.
41436				return createImageBitmap( blob );
41437
41438			} else {
41439
41440				return createImageBitmap( blob, scope.options );
41441
41442			}
41443
41444		} ).then( function ( imageBitmap ) {
41445
41446			Cache.add( url, imageBitmap );
41447
41448			if ( onLoad ) onLoad( imageBitmap );
41449
41450			scope.manager.itemEnd( url );
41451
41452		} ).catch( function ( e ) {
41453
41454			if ( onError ) onError( e );
41455
41456			scope.manager.itemError( url );
41457			scope.manager.itemEnd( url );
41458
41459		} );
41460
41461		scope.manager.itemStart( url );
41462
41463	}
41464
41465} );
41466
41467/**
41468 * @author zz85 / http://www.lab4games.net/zz85/blog
41469 * minimal class for proxing functions to Path. Replaces old "extractSubpaths()"
41470 **/
41471
41472function ShapePath() {
41473
41474	this.type = 'ShapePath';
41475
41476	this.color = new Color();
41477
41478	this.subPaths = [];
41479	this.currentPath = null;
41480
41481}
41482
41483Object.assign( ShapePath.prototype, {
41484
41485	moveTo: function ( x, y ) {
41486
41487		this.currentPath = new Path();
41488		this.subPaths.push( this.currentPath );
41489		this.currentPath.moveTo( x, y );
41490
41491		return this;
41492
41493	},
41494
41495	lineTo: function ( x, y ) {
41496
41497		this.currentPath.lineTo( x, y );
41498
41499		return this;
41500
41501	},
41502
41503	quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
41504
41505		this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
41506
41507		return this;
41508
41509	},
41510
41511	bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
41512
41513		this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
41514
41515		return this;
41516
41517	},
41518
41519	splineThru: function ( pts ) {
41520
41521		this.currentPath.splineThru( pts );
41522
41523		return this;
41524
41525	},
41526
41527	toShapes: function ( isCCW, noHoles ) {
41528
41529		function toShapesNoHoles( inSubpaths ) {
41530
41531			var shapes = [];
41532
41533			for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
41534
41535				var tmpPath = inSubpaths[ i ];
41536
41537				var tmpShape = new Shape();
41538				tmpShape.curves = tmpPath.curves;
41539
41540				shapes.push( tmpShape );
41541
41542			}
41543
41544			return shapes;
41545
41546		}
41547
41548		function isPointInsidePolygon( inPt, inPolygon ) {
41549
41550			var polyLen = inPolygon.length;
41551
41552			// inPt on polygon contour => immediate success    or
41553			// toggling of inside/outside at every single! intersection point of an edge
41554			//  with the horizontal line through inPt, left of inPt
41555			//  not counting lowerY endpoints of edges and whole edges on that line
41556			var inside = false;
vendor: 11,468 bytes, lines 41557-42131
41557			for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
41558
41559				var edgeLowPt = inPolygon[ p ];
41560				var edgeHighPt = inPolygon[ q ];
41561
41562				var edgeDx = edgeHighPt.x - edgeLowPt.x;
41563				var edgeDy = edgeHighPt.y - edgeLowPt.y;
41564
41565				if ( Math.abs( edgeDy ) > Number.EPSILON ) {
41566
41567					// not parallel
41568					if ( edgeDy < 0 ) {
41569
41570						edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
41571						edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
41572
41573					}
41574
41575					if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) 		continue;
41576
41577					if ( inPt.y === edgeLowPt.y ) {
41578
41579						if ( inPt.x === edgeLowPt.x )		return	true;		// inPt is on contour ?
41580						// continue;				// no intersection or edgeLowPt => doesn't count !!!
41581
41582					} else {
41583
41584						var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
41585						if ( perpEdge === 0 )				return	true;		// inPt is on contour ?
41586						if ( perpEdge < 0 ) 				continue;
41587						inside = ! inside;		// true intersection left of inPt
41588
41589					}
41590
41591				} else {
41592
41593					// parallel or collinear
41594					if ( inPt.y !== edgeLowPt.y ) 		continue;			// parallel
41595					// edge lies on the same horizontal line as inPt
41596					if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
41597						 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )		return	true;	// inPt: Point on contour !
41598					// continue;
41599
41600				}
41601
41602			}
41603
41604			return	inside;
41605
41606		}
41607
41608		var isClockWise = ShapeUtils.isClockWise;
41609
41610		var subPaths = this.subPaths;
41611		if ( subPaths.length === 0 ) return [];
41612
41613		if ( noHoles === true )	return	toShapesNoHoles( subPaths );
41614
41615
41616		var solid, tmpPath, tmpShape, shapes = [];
41617
41618		if ( subPaths.length === 1 ) {
41619
41620			tmpPath = subPaths[ 0 ];
41621			tmpShape = new Shape();
41622			tmpShape.curves = tmpPath.curves;
41623			shapes.push( tmpShape );
41624			return shapes;
41625
41626		}
41627
41628		var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
41629		holesFirst = isCCW ? ! holesFirst : holesFirst;
41630
41631		// console.log("Holes first", holesFirst);
41632
41633		var betterShapeHoles = [];
41634		var newShapes = [];
41635		var newShapeHoles = [];
41636		var mainIdx = 0;
41637		var tmpPoints;
41638
41639		newShapes[ mainIdx ] = undefined;
41640		newShapeHoles[ mainIdx ] = [];
41641
41642		for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
41643
41644			tmpPath = subPaths[ i ];
41645			tmpPoints = tmpPath.getPoints();
41646			solid = isClockWise( tmpPoints );
41647			solid = isCCW ? ! solid : solid;
41648
41649			if ( solid ) {
41650
41651				if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )	mainIdx ++;
41652
41653				newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
41654				newShapes[ mainIdx ].s.curves = tmpPath.curves;
41655
41656				if ( holesFirst )	mainIdx ++;
41657				newShapeHoles[ mainIdx ] = [];
41658
41659				//console.log('cw', i);
41660
41661			} else {
41662
41663				newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
41664
41665				//console.log('ccw', i);
41666
41667			}
41668
41669		}
41670
41671		// only Holes? -> probably all Shapes with wrong orientation
41672		if ( ! newShapes[ 0 ] )	return	toShapesNoHoles( subPaths );
41673
41674
41675		if ( newShapes.length > 1 ) {
41676
41677			var ambiguous = false;
41678			var toChange = [];
41679
41680			for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
41681
41682				betterShapeHoles[ sIdx ] = [];
41683
41684			}
41685
41686			for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
41687
41688				var sho = newShapeHoles[ sIdx ];
41689
41690				for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
41691
41692					var ho = sho[ hIdx ];
41693					var hole_unassigned = true;
41694
41695					for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
41696
41697						if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
41698
41699							if ( sIdx !== s2Idx )	toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
41700							if ( hole_unassigned ) {
41701
41702								hole_unassigned = false;
41703								betterShapeHoles[ s2Idx ].push( ho );
41704
41705							} else {
41706
41707								ambiguous = true;
41708
41709							}
41710
41711						}
41712
41713					}
41714
41715					if ( hole_unassigned ) {
41716
41717						betterShapeHoles[ sIdx ].push( ho );
41718
41719					}
41720
41721				}
41722
41723			}
41724			// console.log("ambiguous: ", ambiguous);
41725
41726			if ( toChange.length > 0 ) {
41727
41728				// console.log("to change: ", toChange);
41729				if ( ! ambiguous )	newShapeHoles = betterShapeHoles;
41730
41731			}
41732
41733		}
41734
41735		var tmpHoles;
41736
41737		for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
41738
41739			tmpShape = newShapes[ i ].s;
41740			shapes.push( tmpShape );
41741			tmpHoles = newShapeHoles[ i ];
41742
41743			for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
41744
41745				tmpShape.holes.push( tmpHoles[ j ].h );
41746
41747			}
41748
41749		}
41750
41751		//console.log("shape", shapes);
41752
41753		return shapes;
41754
41755	}
41756
41757} );
41758
41759/**
41760 * @author zz85 / http://www.lab4games.net/zz85/blog
41761 * @author mrdoob / http://mrdoob.com/
41762 */
41763
41764
41765function Font( data ) {
41766
41767	this.type = 'Font';
41768
41769	this.data = data;
41770
41771}
41772
41773Object.assign( Font.prototype, {
41774
41775	isFont: true,
41776
41777	generateShapes: function ( text, size ) {
41778
41779		if ( size === undefined ) size = 100;
41780
41781		var shapes = [];
41782		var paths = createPaths( text, size, this.data );
41783
41784		for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
41785
41786			Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
41787
41788		}
41789
41790		return shapes;
41791
41792	}
41793
41794} );
41795
41796function createPaths( text, size, data ) {
41797
41798	var chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // workaround for IE11, see #13988
41799	var scale = size / data.resolution;
41800	var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
41801
41802	var paths = [];
41803
41804	var offsetX = 0, offsetY = 0;
41805
41806	for ( var i = 0; i < chars.length; i ++ ) {
41807
41808		var char = chars[ i ];
41809
41810		if ( char === '\n' ) {
41811
41812			offsetX = 0;
41813			offsetY -= line_height;
41814
41815		} else {
41816
41817			var ret = createPath( char, scale, offsetX, offsetY, data );
41818			offsetX += ret.offsetX;
41819			paths.push( ret.path );
41820
41821		}
41822
41823	}
41824
41825	return paths;
41826
41827}
41828
41829function createPath( char, scale, offsetX, offsetY, data ) {
41830
41831	var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
41832
41833	if ( ! glyph ) {
41834
41835		console.error( 'THREE.Font: character "' + char + '" does not exists in font family ' + data.familyName + '.' );
41836
41837		return;
41838
41839	}
41840
41841	var path = new ShapePath();
41842
41843	var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;
41844
41845	if ( glyph.o ) {
41846
41847		var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
41848
41849		for ( var i = 0, l = outline.length; i < l; ) {
41850
41851			var action = outline[ i ++ ];
41852
41853			switch ( action ) {
41854
41855				case 'm': // moveTo
41856
41857					x = outline[ i ++ ] * scale + offsetX;
41858					y = outline[ i ++ ] * scale + offsetY;
41859
41860					path.moveTo( x, y );
41861
41862					break;
41863
41864				case 'l': // lineTo
41865
41866					x = outline[ i ++ ] * scale + offsetX;
41867					y = outline[ i ++ ] * scale + offsetY;
41868
41869					path.lineTo( x, y );
41870
41871					break;
41872
41873				case 'q': // quadraticCurveTo
41874
41875					cpx = outline[ i ++ ] * scale + offsetX;
41876					cpy = outline[ i ++ ] * scale + offsetY;
41877					cpx1 = outline[ i ++ ] * scale + offsetX;
41878					cpy1 = outline[ i ++ ] * scale + offsetY;
41879
41880					path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
41881
41882					break;
41883
41884				case 'b': // bezierCurveTo
41885
41886					cpx = outline[ i ++ ] * scale + offsetX;
41887					cpy = outline[ i ++ ] * scale + offsetY;
41888					cpx1 = outline[ i ++ ] * scale + offsetX;
41889					cpy1 = outline[ i ++ ] * scale + offsetY;
41890					cpx2 = outline[ i ++ ] * scale + offsetX;
41891					cpy2 = outline[ i ++ ] * scale + offsetY;
41892
41893					path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
41894
41895					break;
41896
41897			}
41898
41899		}
41900
41901	}
41902
41903	return { offsetX: glyph.ha * scale, path: path };
41904
41905}
41906
41907/**
41908 * @author mrdoob / http://mrdoob.com/
41909 */
41910
41911function FontLoader( manager ) {
41912
41913	Loader.call( this, manager );
41914
41915}
41916
41917FontLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
41918
41919	constructor: FontLoader,
41920
41921	load: function ( url, onLoad, onProgress, onError ) {
41922
41923		var scope = this;
41924
41925		var loader = new FileLoader( this.manager );
41926		loader.setPath( this.path );
41927		loader.load( url, function ( text ) {
41928
41929			var json;
41930
41931			try {
41932
41933				json = JSON.parse( text );
41934
41935			} catch ( e ) {
41936
41937				console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
41938				json = JSON.parse( text.substring( 65, text.length - 2 ) );
41939
41940			}
41941
41942			var font = scope.parse( json );
41943
41944			if ( onLoad ) onLoad( font );
41945
41946		}, onProgress, onError );
41947
41948	},
41949
41950	parse: function ( json ) {
41951
41952		return new Font( json );
41953
41954	}
41955
41956} );
41957
41958/**
41959 * @author mrdoob / http://mrdoob.com/
41960 */
41961
41962var _context;
41963
41964var AudioContext = {
41965
41966	getContext: function () {
41967
41968		if ( _context === undefined ) {
41969
41970			_context = new ( window.AudioContext || window.webkitAudioContext )();
41971
41972		}
41973
41974		return _context;
41975
41976	},
41977
41978	setContext: function ( value ) {
41979
41980		_context = value;
41981
41982	}
41983
41984};
41985
41986/**
41987 * @author Reece Aaron Lecrivain / http://reecenotes.com/
41988 */
41989
41990function AudioLoader( manager ) {
41991
41992	Loader.call( this, manager );
41993
41994}
41995
41996AudioLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
41997
41998	constructor: AudioLoader,
41999
42000	load: function ( url, onLoad, onProgress, onError ) {
42001
42002		var loader = new FileLoader( this.manager );
42003		loader.setResponseType( 'arraybuffer' );
42004		loader.setPath( this.path );
42005		loader.load( url, function ( buffer ) {
42006
42007			// Create a copy of the buffer. The `decodeAudioData` method
42008			// detaches the buffer when complete, preventing reuse.
42009			var bufferCopy = buffer.slice( 0 );
42010
42011			var context = AudioContext.getContext();
42012			context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
42013
42014				onLoad( audioBuffer );
42015
42016			} );
42017
42018		}, onProgress, onError );
42019
42020	}
42021
42022} );
42023
42024/**
42025 * @author WestLangley / http://github.com/WestLangley
42026 */
42027
42028function HemisphereLightProbe( skyColor, groundColor, intensity ) {
42029
42030	LightProbe.call( this, undefined, intensity );
42031
42032	var color1 = new Color().set( skyColor );
42033	var color2 = new Color().set( groundColor );
42034
42035	var sky = new Vector3( color1.r, color1.g, color1.b );
42036	var ground = new Vector3( color2.r, color2.g, color2.b );
42037
42038	// without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
42039	var c0 = Math.sqrt( Math.PI );
42040	var c1 = c0 * Math.sqrt( 0.75 );
42041
42042	this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
42043	this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
42044
42045}
42046
42047HemisphereLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
42048
42049	constructor: HemisphereLightProbe,
42050
42051	isHemisphereLightProbe: true,
42052
42053	copy: function ( source ) { // modifying colors not currently supported
42054
42055		LightProbe.prototype.copy.call( this, source );
42056
42057		return this;
42058
42059	},
42060
42061	toJSON: function ( meta ) {
42062
42063		var data = LightProbe.prototype.toJSON.call( this, meta );
42064
42065		// data.sh = this.sh.toArray(); // todo
42066
42067		return data;
42068
42069	}
42070
42071} );
42072
42073/**
42074 * @author WestLangley / http://github.com/WestLangley
42075 */
42076
42077function AmbientLightProbe( color, intensity ) {
42078
42079	LightProbe.call( this, undefined, intensity );
42080
42081	var color1 = new Color().set( color );
42082
42083	// without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
42084	this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
42085
42086}
42087
42088AmbientLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {
42089
42090	constructor: AmbientLightProbe,
42091
42092	isAmbientLightProbe: true,
42093
42094	copy: function ( source ) { // modifying color not currently supported
42095
42096		LightProbe.prototype.copy.call( this, source );
42097
42098		return this;
42099
42100	},
42101
42102	toJSON: function ( meta ) {
42103
42104		var data = LightProbe.prototype.toJSON.call( this, meta );
42105
42106		// data.sh = this.sh.toArray(); // todo
42107
42108		return data;
42109
42110	}
42111
42112} );
42113
42114var _eyeRight = new Matrix4();
42115var _eyeLeft = new Matrix4();
42116
42117/**
42118 * @author mrdoob / http://mrdoob.com/
42119 */
42120
42121function StereoCamera() {
42122
42123	this.type = 'StereoCamera';
42124
42125	this.aspect = 1;
42126
42127	this.eyeSep = 0.064;
42128
42129	this.cameraL = new PerspectiveCamera();
42130	this.cameraL.layers.enable( 1 );
42131	this.cameraL.matrixAutoUpdate = false;
42132
42133	this.cameraR = new PerspectiveCamera();
42134	this.cameraR.layers.enable( 2 );
42135	this.cameraR.matrixAutoUpdate = false;
42136
42137	this._cache = {
42138		focus: null,
42139		fov: null,
42140		aspect: null,
42141		near: null,
42142		far: null,
42143		zoom: null,
42144		eyeSep: null
42145	};
42146
42147}
42148
42149Object.assign( StereoCamera.prototype, {
42150
42151	update: function ( camera ) {
42152
42153		var cache = this._cache;
42154
42155		var needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
42156			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
42157			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
42158
42159		if ( needsUpdate ) {
42160
42161			cache.focus = camera.focus;
42162			cache.fov = camera.fov;
42163			cache.aspect = camera.aspect * this.aspect;
42164			cache.near = camera.near;
42165			cache.far = camera.far;
42166			cache.zoom = camera.zoom;
42167			cache.eyeSep = this.eyeSep;
42168
42169			// Off-axis stereoscopic effect based on
42170			// http://paulbourke.net/stereographics/stereorender/
42171
42172			var projectionMatrix = camera.projectionMatrix.clone();
42173			var eyeSepHalf = cache.eyeSep / 2;
42174			var eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
42175			var ymax = ( cache.near * Math.tan( MathUtils.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
42176			var xmin, xmax;
42177
42178			// translate xOffset
42179
42180			_eyeLeft.elements[ 12 ] = - eyeSepHalf;
42181			_eyeRight.elements[ 12 ] = eyeSepHalf;
42182
42183			// for left eye
42184
42185			xmin = - ymax * cache.aspect + eyeSepOnProjection;
42186			xmax = ymax * cache.aspect + eyeSepOnProjection;
42187
42188			projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
42189			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
42190
42191			this.cameraL.projectionMatrix.copy( projectionMatrix );
42192
42193			// for right eye
42194
42195			xmin = - ymax * cache.aspect - eyeSepOnProjection;
42196			xmax = ymax * cache.aspect - eyeSepOnProjection;
42197
42198			projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
42199			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
42200
42201			this.cameraR.projectionMatrix.copy( projectionMatrix );
42202
42203		}
42204
42205		this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
42206		this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
42207
42208	}
42209
42210} );
42211
42212/**
42213 * @author alteredq / http://alteredqualia.com/
42214 */
42215
42216function Clock( autoStart ) {
42217
42218	this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
42219
42220	this.startTime = 0;
42221	this.oldTime = 0;
42222	this.elapsedTime = 0;
42223
42224	this.running = false;
42225
42226}
42227
42228Object.assign( Clock.prototype, {
42229
42230	start: function () {
42231
42232		this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
42233
42234		this.oldTime = this.startTime;
42235		this.elapsedTime = 0;
42236		this.running = true;
42237
42238	},
42239
42240	stop: function () {
42241
42242		this.getElapsedTime();
42243		this.running = false;
42244		this.autoStart = false;
42245
42246	},
42247
42248	getElapsedTime: function () {
42249
42250		this.getDelta();
42251		return this.elapsedTime;
42252
42253	},
42254
42255	getDelta: function () {
42256
42257		var diff = 0;
42258
42259		if ( this.autoStart && ! this.running ) {
42260
42261			this.start();
42262			return 0;
42263
42264		}
42265
42266		if ( this.running ) {
42267
42268			var newTime = ( typeof performance === 'undefined' ? Date : performance ).now();
42269
42270			diff = ( newTime - this.oldTime ) / 1000;
42271			this.oldTime = newTime;
42272
42273			this.elapsedTime += diff;
42274
42275		}
42276
42277		return diff;
42278
42279	}
42280
42281} );
42282
42283/**
42284 * @author mrdoob / http://mrdoob.com/
42285 */
42286
42287var _position$2 = new Vector3();
42288var _quaternion$3 = new Quaternion();
42289var _scale$1 = new Vector3();
42290var _orientation = new Vector3();
42291
42292function AudioListener() {
42293
42294	Object3D.call( this );
42295
42296	this.type = 'AudioListener';
42297
42298	this.context = AudioContext.getContext();
42299
42300	this.gain = this.context.createGain();
42301	this.gain.connect( this.context.destination );
42302
42303	this.filter = null;
42304
42305	this.timeDelta = 0;
42306
42307	// private
42308
42309	this._clock = new Clock();
42310
42311}
42312
42313AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
42314
42315	constructor: AudioListener,
42316
42317	getInput: function () {
42318
42319		return this.gain;
42320
42321	},
42322
42323	removeFilter: function ( ) {
42324
42325		if ( this.filter !== null ) {
42326
42327			this.gain.disconnect( this.filter );
42328			this.filter.disconnect( this.context.destination );
42329			this.gain.connect( this.context.destination );
42330			this.filter = null;
42331
42332		}
42333
42334		return this;
42335
42336	},
42337
42338	getFilter: function () {
42339
42340		return this.filter;
42341
42342	},
42343
42344	setFilter: function ( value ) {
42345
42346		if ( this.filter !== null ) {
42347
42348			this.gain.disconnect( this.filter );
42349			this.filter.disconnect( this.context.destination );
42350
42351		} else {
42352
42353			this.gain.disconnect( this.context.destination );
42354
42355		}
42356
42357		this.filter = value;
42358		this.gain.connect( this.filter );
42359		this.filter.connect( this.context.destination );
42360
42361		return this;
42362
42363	},
42364
42365	getMasterVolume: function () {
42366
42367		return this.gain.gain.value;
42368
42369	},
42370
42371	setMasterVolume: function ( value ) {
42372
42373		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
42374
42375		return this;
42376
42377	},
42378
42379	updateMatrixWorld: function ( force ) {
42380
42381		Object3D.prototype.updateMatrixWorld.call( this, force );
42382
42383		var listener = this.context.listener;
42384		var up = this.up;
42385
42386		this.timeDelta = this._clock.getDelta();
42387
42388		this.matrixWorld.decompose( _position$2, _quaternion$3, _scale$1 );
42389
42390		_orientation.set( 0, 0, - 1 ).applyQuaternion( _quaternion$3 );
42391
42392		if ( listener.positionX ) {
42393
42394			// code path for Chrome (see #14393)
42395
42396			var endTime = this.context.currentTime + this.timeDelta;
42397
42398			listener.positionX.linearRampToValueAtTime( _position$2.x, endTime );
42399			listener.positionY.linearRampToValueAtTime( _position$2.y, endTime );
42400			listener.positionZ.linearRampToValueAtTime( _position$2.z, endTime );
42401			listener.forwardX.linearRampToValueAtTime( _orientation.x, endTime );
42402			listener.forwardY.linearRampToValueAtTime( _orientation.y, endTime );
42403			listener.forwardZ.linearRampToValueAtTime( _orientation.z, endTime );
42404			listener.upX.linearRampToValueAtTime( up.x, endTime );
42405			listener.upY.linearRampToValueAtTime( up.y, endTime );
42406			listener.upZ.linearRampToValueAtTime( up.z, endTime );
42407
42408		} else {
42409
42410			listener.setPosition( _position$2.x, _position$2.y, _position$2.z );
42411			listener.setOrientation( _orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z );
42412
42413		}
42414
42415	}
42416
42417} );
42418
42419/**
42420 * @author mrdoob / http://mrdoob.com/
42421 * @author Reece Aaron Lecrivain / http://reecenotes.com/
42422 */
42423
42424function Audio( listener ) {
42425
42426	Object3D.call( this );
42427
42428	this.type = 'Audio';
42429
42430	this.listener = listener;
42431	this.context = listener.context;
42432
42433	this.gain = this.context.createGain();
42434	this.gain.connect( listener.getInput() );
42435
42436	this.autoplay = false;
42437
42438	this.buffer = null;
42439	this.detune = 0;
42440	this.loop = false;
42441	this.loopStart = 0;
42442	this.loopEnd = 0;
42443	this.offset = 0;
42444	this.duration = undefined;
42445	this.playbackRate = 1;
42446	this.isPlaying = false;
42447	this.hasPlaybackControl = true;
42448	this.sourceType = 'empty';
42449
42450	this._startedAt = 0;
42451	this._progress = 0;
42452
42453	this.filters = [];
42454
42455}
42456
42457Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
42458
42459	constructor: Audio,
42460
42461	getOutput: function () {
42462
42463		return this.gain;
42464
42465	},
42466
42467	setNodeSource: function ( audioNode ) {
42468
42469		this.hasPlaybackControl = false;
42470		this.sourceType = 'audioNode';
42471		this.source = audioNode;
42472		this.connect();
42473
42474		return this;
42475
42476	},
42477
42478	setMediaElementSource: function ( mediaElement ) {
42479
42480		this.hasPlaybackControl = false;
42481		this.sourceType = 'mediaNode';
42482		this.source = this.context.createMediaElementSource( mediaElement );
42483		this.connect();
42484
42485		return this;
42486
42487	},
42488
42489	setMediaStreamSource: function ( mediaStream ) {
42490
42491		this.hasPlaybackControl = false;
42492		this.sourceType = 'mediaStreamNode';
42493		this.source = this.context.createMediaStreamSource( mediaStream );
42494		this.connect();
42495
42496		return this;
42497
42498	},
42499
42500	setBuffer: function ( audioBuffer ) {
42501
42502		this.buffer = audioBuffer;
42503		this.sourceType = 'buffer';
42504
42505		if ( this.autoplay ) this.play();
42506
42507		return this;
42508
42509	},
42510
42511	play: function ( delay ) {
42512
42513		if ( delay === undefined ) delay = 0;
42514
42515		if ( this.isPlaying === true ) {
42516
42517			console.warn( 'THREE.Audio: Audio is already playing.' );
42518			return;
42519
42520		}
42521
42522		if ( this.hasPlaybackControl === false ) {
42523
42524			console.warn( 'THREE.Audio: this Audio has no playback control.' );
42525			return;
42526
42527		}
42528
42529		this._startedAt = this.context.currentTime + delay;
42530
42531		var source = this.context.createBufferSource();
42532		source.buffer = this.buffer;
42533		source.loop = this.loop;
42534		source.loopStart = this.loopStart;
42535		source.loopEnd = this.loopEnd;
42536		source.onended = this.onEnded.bind( this );
42537		source.start( this._startedAt, this._progress + this.offset, this.duration );
42538
42539		this.isPlaying = true;
42540
42541		this.source = source;
42542
42543		this.setDetune( this.detune );
42544		this.setPlaybackRate( this.playbackRate );
42545
42546		return this.connect();
42547
42548	},
42549
42550	pause: function () {
42551
42552		if ( this.hasPlaybackControl === false ) {
42553
42554			console.warn( 'THREE.Audio: this Audio has no playback control.' );
42555			return;
42556
42557		}
42558
42559		if ( this.isPlaying === true ) {
42560
42561			// update current progress
42562
42563			this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
42564
42565			if ( this.loop === true ) {
42566
42567				// ensure _progress does not exceed duration with looped audios
42568
42569				this._progress = this._progress % ( this.duration || this.buffer.duration );
42570
42571			}
42572
42573			this.source.stop();
42574			this.source.onended = null;
42575
42576			this.isPlaying = false;
42577
42578		}
42579
42580		return this;
42581
42582	},
42583
42584	stop: function () {
42585
42586		if ( this.hasPlaybackControl === false ) {
42587
42588			console.warn( 'THREE.Audio: this Audio has no playback control.' );
42589			return;
42590
42591		}
42592
42593		this._progress = 0;
42594
42595		this.source.stop();
42596		this.source.onended = null;
42597		this.isPlaying = false;
42598
42599		return this;
42600
42601	},
42602
42603	connect: function () {
42604
42605		if ( this.filters.length > 0 ) {
42606
42607			this.source.connect( this.filters[ 0 ] );
42608
42609			for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
42610
42611				this.filters[ i - 1 ].connect( this.filters[ i ] );
42612
42613			}
42614
42615			this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
42616
42617		} else {
42618
42619			this.source.connect( this.getOutput() );
42620
42621		}
42622
42623		return this;
42624
42625	},
42626
42627	disconnect: function () {
42628
42629		if ( this.filters.length > 0 ) {
42630
42631			this.source.disconnect( this.filters[ 0 ] );
42632
42633			for ( var i = 1, l = this.filters.length; i < l; i ++ ) {
42634
42635				this.filters[ i - 1 ].disconnect( this.filters[ i ] );
42636
42637			}
42638
42639			this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
42640
42641		} else {
42642
42643			this.source.disconnect( this.getOutput() );
42644
42645		}
42646
42647		return this;
42648
42649	},
42650
42651	getFilters: function () {
42652
42653		return this.filters;
42654
42655	},
42656
42657	setFilters: function ( value ) {
42658
42659		if ( ! value ) value = [];
42660
42661		if ( this.isPlaying === true ) {
42662
42663			this.disconnect();
42664			this.filters = value;
42665			this.connect();
42666
42667		} else {
42668
42669			this.filters = value;
42670
42671		}
42672
42673		return this;
42674
42675	},
42676
42677	setDetune: function ( value ) {
42678
42679		this.detune = value;
42680
42681		if ( this.source.detune === undefined ) return; // only set detune when available
42682
42683		if ( this.isPlaying === true ) {
42684
42685			this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
42686
42687		}
42688
42689		return this;
42690
42691	},
42692
42693	getDetune: function () {
42694
42695		return this.detune;
42696
42697	},
42698
42699	getFilter: function () {
42700
42701		return this.getFilters()[ 0 ];
42702
42703	},
42704
42705	setFilter: function ( filter ) {
42706
42707		return this.setFilters( filter ? [ filter ] : [] );
42708
42709	},
42710
42711	setPlaybackRate: function ( value ) {
42712
42713		if ( this.hasPlaybackControl === false ) {
42714
42715			console.warn( 'THREE.Audio: this Audio has no playback control.' );
42716			return;
42717
42718		}
42719
42720		this.playbackRate = value;
42721
42722		if ( this.isPlaying === true ) {
42723
42724			this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
42725
42726		}
42727
42728		return this;
42729
42730	},
42731
42732	getPlaybackRate: function () {
42733
42734		return this.playbackRate;
42735
42736	},
42737
42738	onEnded: function () {
42739
42740		this.isPlaying = false;
42741
42742	},
42743
42744	getLoop: function () {
42745
42746		if ( this.hasPlaybackControl === false ) {
42747
42748			console.warn( 'THREE.Audio: this Audio has no playback control.' );
42749			return false;
42750
42751		}
42752
42753		return this.loop;
42754
42755	},
42756
42757	setLoop: function ( value ) {
42758
42759		if ( this.hasPlaybackControl === false ) {
42760
42761			console.warn( 'THREE.Audio: this Audio has no playback control.' );
42762			return;
42763
42764		}
42765
42766		this.loop = value;
42767
42768		if ( this.isPlaying === true ) {
42769
42770			this.source.loop = this.loop;
42771
42772		}
42773
42774		return this;
42775
42776	},
42777
42778	setLoopStart: function ( value ) {
42779
42780		this.loopStart = value;
42781
42782		return this;
42783
42784	},
42785
42786	setLoopEnd: function ( value ) {
42787
42788		this.loopEnd = value;
42789
42790		return this;
42791
42792	},
42793
42794	getVolume: function () {
42795
42796		return this.gain.gain.value;
42797
42798	},
42799
42800	setVolume: function ( value ) {
42801
42802		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
42803
42804		return this;
42805
42806	}
42807
42808} );
42809
42810/**
42811 * @author mrdoob / http://mrdoob.com/
42812 */
42813
42814var _position$3 = new Vector3();
42815var _quaternion$4 = new Quaternion();
42816var _scale$2 = new Vector3();
42817var _orientation$1 = new Vector3();
42818
42819function PositionalAudio( listener ) {
42820
42821	Audio.call( this, listener );
42822
42823	this.panner = this.context.createPanner();
42824	this.panner.panningModel = 'HRTF';
42825	this.panner.connect( this.gain );
42826
42827}
42828
42829PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
42830
42831	constructor: PositionalAudio,
42832
42833	getOutput: function () {
42834
42835		return this.panner;
42836
42837	},
42838
42839	getRefDistance: function () {
42840
42841		return this.panner.refDistance;
42842
42843	},
42844
42845	setRefDistance: function ( value ) {
42846
42847		this.panner.refDistance = value;
42848
42849		return this;
42850
42851	},
42852
42853	getRolloffFactor: function () {
42854
42855		return this.panner.rolloffFactor;
42856
42857	},
42858
42859	setRolloffFactor: function ( value ) {
42860
42861		this.panner.rolloffFactor = value;
42862
42863		return this;
42864
42865	},
42866
42867	getDistanceModel: function () {
42868
42869		return this.panner.distanceModel;
42870
42871	},
42872
42873	setDistanceModel: function ( value ) {
42874
42875		this.panner.distanceModel = value;
42876
42877		return this;
42878
42879	},
42880
42881	getMaxDistance: function () {
42882
42883		return this.panner.maxDistance;
42884
42885	},
42886
42887	setMaxDistance: function ( value ) {
42888
42889		this.panner.maxDistance = value;
42890
42891		return this;
42892
42893	},
42894
42895	setDirectionalCone: function ( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
42896
42897		this.panner.coneInnerAngle = coneInnerAngle;
42898		this.panner.coneOuterAngle = coneOuterAngle;
42899		this.panner.coneOuterGain = coneOuterGain;
42900
42901		return this;
42902
42903	},
42904
42905	updateMatrixWorld: function ( force ) {
42906
42907		Object3D.prototype.updateMatrixWorld.call( this, force );
42908
42909		if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
42910
42911		this.matrixWorld.decompose( _position$3, _quaternion$4, _scale$2 );
42912
42913		_orientation$1.set( 0, 0, 1 ).applyQuaternion( _quaternion$4 );
42914
42915		var panner = this.panner;
42916
42917		if ( panner.positionX ) {
42918
42919			// code path for Chrome and Firefox (see #14393)
42920
42921			var endTime = this.context.currentTime + this.listener.timeDelta;
42922
42923			panner.positionX.linearRampToValueAtTime( _position$3.x, endTime );
42924			panner.positionY.linearRampToValueAtTime( _position$3.y, endTime );
42925			panner.positionZ.linearRampToValueAtTime( _position$3.z, endTime );
42926			panner.orientationX.linearRampToValueAtTime( _orientation$1.x, endTime );
42927			panner.orientationY.linearRampToValueAtTime( _orientation$1.y, endTime );
42928			panner.orientationZ.linearRampToValueAtTime( _orientation$1.z, endTime );
42929
42930		} else {
42931
42932			panner.setPosition( _position$3.x, _position$3.y, _position$3.z );
42933			panner.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z );
42934
42935		}
42936
42937	}
42938
42939} );
42940
42941/**
42942 * @author mrdoob / http://mrdoob.com/
42943 */
42944
42945function AudioAnalyser( audio, fftSize ) {
42946
42947	this.analyser = audio.context.createAnalyser();
42948	this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
42949
42950	this.data = new Uint8Array( this.analyser.frequencyBinCount );
42951
42952	audio.getOutput().connect( this.analyser );
42953
42954}
42955
42956Object.assign( AudioAnalyser.prototype, {
42957
42958	getFrequencyData: function () {
42959
42960		this.analyser.getByteFrequencyData( this.data );
42961
42962		return this.data;
42963
42964	},
42965
42966	getAverageFrequency: function () {
42967
42968		var value = 0, data = this.getFrequencyData();
42969
42970		for ( var i = 0; i < data.length; i ++ ) {
42971
42972			value += data[ i ];
42973
42974		}
42975
42976		return value / data.length;
42977
42978	}
42979
42980} );
42981
42982/**
42983 *
42984 * Buffered scene graph property that allows weighted accumulation.
42985 *
42986 *
42987 * @author Ben Houston / http://clara.io/
42988 * @author David Sarno / http://lighthaus.us/
42989 * @author tschw
42990 */
42991
42992function PropertyMixer( binding, typeName, valueSize ) {
42993
42994	this.binding = binding;
42995	this.valueSize = valueSize;
42996
42997	var mixFunction,
42998		mixFunctionAdditive,
42999		setIdentity;
43000
43001	// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
43002	//
43003	// interpolators can use .buffer as their .result
43004	// the data then goes to 'incoming'
43005	//
43006	// 'accu0' and 'accu1' are used frame-interleaved for
43007	// the cumulative result and are compared to detect
43008	// changes
43009	//
43010	// 'orig' stores the original state of the property
43011	//
43012	// 'add' is used for additive cumulative results
43013	//
vendor: 22,486 bytes, lines 43014-44023
43014	// 'work' is optional and is only present for quaternion types. It is used
43015	// to store intermediate quaternion multiplication results
43016
43017	switch ( typeName ) {
43018
43019		case 'quaternion':
43020			mixFunction = this._slerp;
43021			mixFunctionAdditive = this._slerpAdditive;
43022			setIdentity = this._setAdditiveIdentityQuaternion;
43023
43024			this.buffer = new Float64Array( valueSize * 6 );
43025			this._workIndex = 5;
43026			break;
43027
43028		case 'string':
43029		case 'bool':
43030			mixFunction = this._select;
43031
43032			// Use the regular mix function and for additive on these types,
43033			// additive is not relevant for non-numeric types
43034			mixFunctionAdditive = this._select;
43035
43036			setIdentity = this._setAdditiveIdentityOther;
43037
43038			this.buffer = new Array( valueSize * 5 );
43039			break;
43040
43041		default:
43042			mixFunction = this._lerp;
43043			mixFunctionAdditive = this._lerpAdditive;
43044			setIdentity = this._setAdditiveIdentityNumeric;
43045
43046			this.buffer = new Float64Array( valueSize * 5 );
43047
43048	}
43049
43050	this._mixBufferRegion = mixFunction;
43051	this._mixBufferRegionAdditive = mixFunctionAdditive;
43052	this._setIdentity = setIdentity;
43053	this._origIndex = 3;
43054	this._addIndex = 4;
43055
43056	this.cumulativeWeight = 0;
43057	this.cumulativeWeightAdditive = 0;
43058
43059	this.useCount = 0;
43060	this.referenceCount = 0;
43061
43062}
43063
43064Object.assign( PropertyMixer.prototype, {
43065
43066	// accumulate data in the 'incoming' region into 'accu<i>'
43067	accumulate: function ( accuIndex, weight ) {
43068
43069		// note: happily accumulating nothing when weight = 0, the caller knows
43070		// the weight and shouldn't have made the call in the first place
43071
43072		var buffer = this.buffer,
43073			stride = this.valueSize,
43074			offset = accuIndex * stride + stride,
43075
43076			currentWeight = this.cumulativeWeight;
43077
43078		if ( currentWeight === 0 ) {
43079
43080			// accuN := incoming * weight
43081
43082			for ( var i = 0; i !== stride; ++ i ) {
43083
43084				buffer[ offset + i ] = buffer[ i ];
43085
43086			}
43087
43088			currentWeight = weight;
43089
43090		} else {
43091
43092			// accuN := accuN + incoming * weight
43093
43094			currentWeight += weight;
43095			var mix = weight / currentWeight;
43096			this._mixBufferRegion( buffer, offset, 0, mix, stride );
43097
43098		}
43099
43100		this.cumulativeWeight = currentWeight;
43101
43102	},
43103
43104	// accumulate data in the 'incoming' region into 'add'
43105	accumulateAdditive: function ( weight ) {
43106
43107		var buffer = this.buffer,
43108			stride = this.valueSize,
43109			offset = stride * this._addIndex;
43110
43111		if ( this.cumulativeWeightAdditive === 0 ) {
43112
43113			// add = identity
43114
43115			this._setIdentity();
43116
43117		}
43118
43119		// add := add + incoming * weight
43120
43121		this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
43122		this.cumulativeWeightAdditive += weight;
43123
43124	},
43125
43126	// apply the state of 'accu<i>' to the binding when accus differ
43127	apply: function ( accuIndex ) {
43128
43129		var stride = this.valueSize,
43130			buffer = this.buffer,
43131			offset = accuIndex * stride + stride,
43132
43133			weight = this.cumulativeWeight,
43134			weightAdditive = this.cumulativeWeightAdditive,
43135
43136			binding = this.binding;
43137
43138		this.cumulativeWeight = 0;
43139		this.cumulativeWeightAdditive = 0;
43140
43141		if ( weight < 1 ) {
43142
43143			// accuN := accuN + original * ( 1 - cumulativeWeight )
43144
43145			var originalValueOffset = stride * this._origIndex;
43146
43147			this._mixBufferRegion(
43148				buffer, offset, originalValueOffset, 1 - weight, stride );
43149
43150		}
43151
43152		if ( weightAdditive > 0 ) {
43153
43154			// accuN := accuN + additive accuN
43155
43156			this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
43157
43158		}
43159
43160		for ( var i = stride, e = stride + stride; i !== e; ++ i ) {
43161
43162			if ( buffer[ i ] !== buffer[ i + stride ] ) {
43163
43164				// value has changed -> update scene graph
43165
43166				binding.setValue( buffer, offset );
43167				break;
43168
43169			}
43170
43171		}
43172
43173	},
43174
43175	// remember the state of the bound property and copy it to both accus
43176	saveOriginalState: function () {
43177
43178		var binding = this.binding;
43179
43180		var buffer = this.buffer,
43181			stride = this.valueSize,
43182
43183			originalValueOffset = stride * this._origIndex;
43184
43185		binding.getValue( buffer, originalValueOffset );
43186
43187		// accu[0..1] := orig -- initially detect changes against the original
43188		for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {
43189
43190			buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
43191
43192		}
43193
43194		// Add to identity for additive
43195		this._setIdentity();
43196
43197		this.cumulativeWeight = 0;
43198		this.cumulativeWeightAdditive = 0;
43199
43200	},
43201
43202	// apply the state previously taken via 'saveOriginalState' to the binding
43203	restoreOriginalState: function () {
43204
43205		var originalValueOffset = this.valueSize * 3;
43206		this.binding.setValue( this.buffer, originalValueOffset );
43207
43208	},
43209
43210	_setAdditiveIdentityNumeric: function () {
43211
43212		var startIndex = this._addIndex * this.valueSize;
43213
43214		this.buffer.fill( 0, startIndex, startIndex + this.valueSize );
43215
43216	},
43217
43218	_setAdditiveIdentityQuaternion: function () {
43219
43220		this._setAdditiveIdentityNumeric();
43221		this.buffer[ this._addIndex * 4 + 3 ] = 1;
43222
43223	},
43224
43225	_setAdditiveIdentityOther: function () {
43226
43227		var startIndex = this._origIndex * this.valueSize;
43228		var targetIndex = this._addIndex * this.valueSize;
43229
43230		this.buffer.copyWithin( targetIndex, startIndex, this.valueSize );
43231
43232	},
43233
43234
43235	// mix functions
43236
43237	_select: function ( buffer, dstOffset, srcOffset, t, stride ) {
43238
43239		if ( t >= 0.5 ) {
43240
43241			for ( var i = 0; i !== stride; ++ i ) {
43242
43243				buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
43244
43245			}
43246
43247		}
43248
43249	},
43250
43251	_slerp: function ( buffer, dstOffset, srcOffset, t ) {
43252
43253		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
43254
43255	},
43256
43257	_slerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
43258
43259		var workOffset = this._workIndex * stride;
43260
43261		// Store result in intermediate buffer offset
43262		Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
43263
43264		// Slerp to the intermediate result
43265		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
43266
43267	},
43268
43269	_lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {
43270
43271		var s = 1 - t;
43272
43273		for ( var i = 0; i !== stride; ++ i ) {
43274
43275			var j = dstOffset + i;
43276
43277			buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
43278
43279		}
43280
43281	},
43282
43283	_lerpAdditive: function ( buffer, dstOffset, srcOffset, t, stride ) {
43284
43285		for ( var i = 0; i !== stride; ++ i ) {
43286
43287			var j = dstOffset + i;
43288
43289			buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
43290
43291		}
43292
43293	}
43294
43295} );
43296
43297/**
43298 *
43299 * A reference to a real property in the scene graph.
43300 *
43301 *
43302 * @author Ben Houston / http://clara.io/
43303 * @author David Sarno / http://lighthaus.us/
43304 * @author tschw
43305 */
43306
43307// Characters [].:/ are reserved for track binding syntax.
43308var _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
43309var _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
43310
43311// Attempts to allow node names from any language. ES5's `\w` regexp matches
43312// only latin characters, and the unicode \p{L} is not yet supported. So
43313// instead, we exclude reserved characters and match everything else.
43314var _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
43315var _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
43316
43317// Parent directories, delimited by '/' or ':'. Currently unused, but must
43318// be matched to parse the rest of the track name.
43319var _directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
43320
43321// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
43322var _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
43323
43324// Object on target node, and accessor. May not contain reserved
43325// characters. Accessor may contain any character except closing bracket.
43326var _objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
43327
43328// Property and accessor. May not contain reserved characters. Accessor may
43329// contain any non-bracket characters.
43330var _propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
43331
43332var _trackRe = new RegExp( ''
43333	+ '^'
43334	+ _directoryRe
43335	+ _nodeRe
43336	+ _objectRe
43337	+ _propertyRe
43338	+ '$'
43339);
43340
43341var _supportedObjectNames = [ 'material', 'materials', 'bones' ];
43342
43343function Composite( targetGroup, path, optionalParsedPath ) {
43344
43345	var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
43346
43347	this._targetGroup = targetGroup;
43348	this._bindings = targetGroup.subscribe_( path, parsedPath );
43349
43350}
43351
43352Object.assign( Composite.prototype, {
43353
43354	getValue: function ( array, offset ) {
43355
43356		this.bind(); // bind all binding
43357
43358		var firstValidIndex = this._targetGroup.nCachedObjects_,
43359			binding = this._bindings[ firstValidIndex ];
43360
43361		// and only call .getValue on the first
43362		if ( binding !== undefined ) binding.getValue( array, offset );
43363
43364	},
43365
43366	setValue: function ( array, offset ) {
43367
43368		var bindings = this._bindings;
43369
43370		for ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
43371
43372			bindings[ i ].setValue( array, offset );
43373
43374		}
43375
43376	},
43377
43378	bind: function () {
43379
43380		var bindings = this._bindings;
43381
43382		for ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
43383
43384			bindings[ i ].bind();
43385
43386		}
43387
43388	},
43389
43390	unbind: function () {
43391
43392		var bindings = this._bindings;
43393
43394		for ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
43395
43396			bindings[ i ].unbind();
43397
43398		}
43399
43400	}
43401
43402} );
43403
43404
43405function PropertyBinding( rootNode, path, parsedPath ) {
43406
43407	this.path = path;
43408	this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
43409
43410	this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;
43411
43412	this.rootNode = rootNode;
43413
43414}
43415
43416Object.assign( PropertyBinding, {
43417
43418	Composite: Composite,
43419
43420	create: function ( root, path, parsedPath ) {
43421
43422		if ( ! ( root && root.isAnimationObjectGroup ) ) {
43423
43424			return new PropertyBinding( root, path, parsedPath );
43425
43426		} else {
43427
43428			return new PropertyBinding.Composite( root, path, parsedPath );
43429
43430		}
43431
43432	},
43433
43434	/**
43435	 * Replaces spaces with underscores and removes unsupported characters from
43436	 * node names, to ensure compatibility with parseTrackName().
43437	 *
43438	 * @param {string} name Node name to be sanitized.
43439	 * @return {string}
43440	 */
43441	sanitizeNodeName: function ( name ) {
43442
43443		return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
43444
43445	},
43446
43447	parseTrackName: function ( trackName ) {
43448
43449		var matches = _trackRe.exec( trackName );
43450
43451		if ( ! matches ) {
43452
43453			throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
43454
43455		}
43456
43457		var results = {
43458			// directoryName: matches[ 1 ], // (tschw) currently unused
43459			nodeName: matches[ 2 ],
43460			objectName: matches[ 3 ],
43461			objectIndex: matches[ 4 ],
43462			propertyName: matches[ 5 ], // required
43463			propertyIndex: matches[ 6 ]
43464		};
43465
43466		var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
43467
43468		if ( lastDot !== undefined && lastDot !== - 1 ) {
43469
43470			var objectName = results.nodeName.substring( lastDot + 1 );
43471
43472			// Object names must be checked against a whitelist. Otherwise, there
43473			// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
43474			// 'bar' could be the objectName, or part of a nodeName (which can
43475			// include '.' characters).
43476			if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
43477
43478				results.nodeName = results.nodeName.substring( 0, lastDot );
43479				results.objectName = objectName;
43480
43481			}
43482
43483		}
43484
43485		if ( results.propertyName === null || results.propertyName.length === 0 ) {
43486
43487			throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
43488
43489		}
43490
43491		return results;
43492
43493	},
43494
43495	findNode: function ( root, nodeName ) {
43496
43497		if ( ! nodeName || nodeName === "" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
43498
43499			return root;
43500
43501		}
43502
43503		// search into skeleton bones.
43504		if ( root.skeleton ) {
43505
43506			var bone = root.skeleton.getBoneByName( nodeName );
43507
43508			if ( bone !== undefined ) {
43509
43510				return bone;
43511
43512			}
43513
43514		}
43515
43516		// search into node subtree.
43517		if ( root.children ) {
43518
43519			var searchNodeSubtree = function ( children ) {
43520
43521				for ( var i = 0; i < children.length; i ++ ) {
43522
43523					var childNode = children[ i ];
43524
43525					if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
43526
43527						return childNode;
43528
43529					}
43530
43531					var result = searchNodeSubtree( childNode.children );
43532
43533					if ( result ) return result;
43534
43535				}
43536
43537				return null;
43538
43539			};
43540
43541			var subTreeNode = searchNodeSubtree( root.children );
43542
43543			if ( subTreeNode ) {
43544
43545				return subTreeNode;
43546
43547			}
43548
43549		}
43550
43551		return null;
43552
43553	}
43554
43555} );
43556
43557Object.assign( PropertyBinding.prototype, { // prototype, continued
43558
43559	// these are used to "bind" a nonexistent property
43560	_getValue_unavailable: function () {},
43561	_setValue_unavailable: function () {},
43562
43563	BindingType: {
43564		Direct: 0,
43565		EntireArray: 1,
43566		ArrayElement: 2,
43567		HasFromToArray: 3
43568	},
43569
43570	Versioning: {
43571		None: 0,
43572		NeedsUpdate: 1,
43573		MatrixWorldNeedsUpdate: 2
43574	},
43575
43576	GetterByBindingType: [
43577
43578		function getValue_direct( buffer, offset ) {
43579
43580			buffer[ offset ] = this.node[ this.propertyName ];
43581
43582		},
43583
43584		function getValue_array( buffer, offset ) {
43585
43586			var source = this.resolvedProperty;
43587
43588			for ( var i = 0, n = source.length; i !== n; ++ i ) {
43589
43590				buffer[ offset ++ ] = source[ i ];
43591
43592			}
43593
43594		},
43595
43596		function getValue_arrayElement( buffer, offset ) {
43597
43598			buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
43599
43600		},
43601
43602		function getValue_toArray( buffer, offset ) {
43603
43604			this.resolvedProperty.toArray( buffer, offset );
43605
43606		}
43607
43608	],
43609
43610	SetterByBindingTypeAndVersioning: [
43611
43612		[
43613			// Direct
43614
43615			function setValue_direct( buffer, offset ) {
43616
43617				this.targetObject[ this.propertyName ] = buffer[ offset ];
43618
43619			},
43620
43621			function setValue_direct_setNeedsUpdate( buffer, offset ) {
43622
43623				this.targetObject[ this.propertyName ] = buffer[ offset ];
43624				this.targetObject.needsUpdate = true;
43625
43626			},
43627
43628			function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
43629
43630				this.targetObject[ this.propertyName ] = buffer[ offset ];
43631				this.targetObject.matrixWorldNeedsUpdate = true;
43632
43633			}
43634
43635		], [
43636
43637			// EntireArray
43638
43639			function setValue_array( buffer, offset ) {
43640
43641				var dest = this.resolvedProperty;
43642
43643				for ( var i = 0, n = dest.length; i !== n; ++ i ) {
43644
43645					dest[ i ] = buffer[ offset ++ ];
43646
43647				}
43648
43649			},
43650
43651			function setValue_array_setNeedsUpdate( buffer, offset ) {
43652
43653				var dest = this.resolvedProperty;
43654
43655				for ( var i = 0, n = dest.length; i !== n; ++ i ) {
43656
43657					dest[ i ] = buffer[ offset ++ ];
43658
43659				}
43660
43661				this.targetObject.needsUpdate = true;
43662
43663			},
43664
43665			function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
43666
43667				var dest = this.resolvedProperty;
43668
43669				for ( var i = 0, n = dest.length; i !== n; ++ i ) {
43670
43671					dest[ i ] = buffer[ offset ++ ];
43672
43673				}
43674
43675				this.targetObject.matrixWorldNeedsUpdate = true;
43676
43677			}
43678
43679		], [
43680
43681			// ArrayElement
43682
43683			function setValue_arrayElement( buffer, offset ) {
43684
43685				this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
43686
43687			},
43688
43689			function setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
43690
43691				this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
43692				this.targetObject.needsUpdate = true;
43693
43694			},
43695
43696			function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
43697
43698				this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
43699				this.targetObject.matrixWorldNeedsUpdate = true;
43700
43701			}
43702
43703		], [
43704
43705			// HasToFromArray
43706
43707			function setValue_fromArray( buffer, offset ) {
43708
43709				this.resolvedProperty.fromArray( buffer, offset );
43710
43711			},
43712
43713			function setValue_fromArray_setNeedsUpdate( buffer, offset ) {
43714
43715				this.resolvedProperty.fromArray( buffer, offset );
43716				this.targetObject.needsUpdate = true;
43717
43718			},
43719
43720			function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
43721
43722				this.resolvedProperty.fromArray( buffer, offset );
43723				this.targetObject.matrixWorldNeedsUpdate = true;
43724
43725			}
43726
43727		]
43728
43729	],
43730
43731	getValue: function getValue_unbound( targetArray, offset ) {
43732
43733		this.bind();
43734		this.getValue( targetArray, offset );
43735
43736		// Note: This class uses a State pattern on a per-method basis:
43737		// 'bind' sets 'this.getValue' / 'setValue' and shadows the
43738		// prototype version of these methods with one that represents
43739		// the bound state. When the property is not found, the methods
43740		// become no-ops.
43741
43742	},
43743
43744	setValue: function getValue_unbound( sourceArray, offset ) {
43745
43746		this.bind();
43747		this.setValue( sourceArray, offset );
43748
43749	},
43750
43751	// create getter / setter pair for a property in the scene graph
43752	bind: function () {
43753
43754		var targetObject = this.node,
43755			parsedPath = this.parsedPath,
43756
43757			objectName = parsedPath.objectName,
43758			propertyName = parsedPath.propertyName,
43759			propertyIndex = parsedPath.propertyIndex;
43760
43761		if ( ! targetObject ) {
43762
43763			targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;
43764
43765			this.node = targetObject;
43766
43767		}
43768
43769		// set fail state so we can just 'return' on error
43770		this.getValue = this._getValue_unavailable;
43771		this.setValue = this._setValue_unavailable;
43772
43773		// ensure there is a value node
43774		if ( ! targetObject ) {
43775
43776			console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
43777			return;
43778
43779		}
43780
43781		if ( objectName ) {
43782
43783			var objectIndex = parsedPath.objectIndex;
43784
43785			// special cases were we need to reach deeper into the hierarchy to get the face materials....
43786			switch ( objectName ) {
43787
43788				case 'materials':
43789
43790					if ( ! targetObject.material ) {
43791
43792						console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
43793						return;
43794
43795					}
43796
43797					if ( ! targetObject.material.materials ) {
43798
43799						console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
43800						return;
43801
43802					}
43803
43804					targetObject = targetObject.material.materials;
43805
43806					break;
43807
43808				case 'bones':
43809
43810					if ( ! targetObject.skeleton ) {
43811
43812						console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
43813						return;
43814
43815					}
43816
43817					// potential future optimization: skip this if propertyIndex is already an integer
43818					// and convert the integer string to a true integer.
43819
43820					targetObject = targetObject.skeleton.bones;
43821
43822					// support resolving morphTarget names into indices.
43823					for ( var i = 0; i < targetObject.length; i ++ ) {
43824
43825						if ( targetObject[ i ].name === objectIndex ) {
43826
43827							objectIndex = i;
43828							break;
43829
43830						}
43831
43832					}
43833
43834					break;
43835
43836				default:
43837
43838					if ( targetObject[ objectName ] === undefined ) {
43839
43840						console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
43841						return;
43842
43843					}
43844
43845					targetObject = targetObject[ objectName ];
43846
43847			}
43848
43849
43850			if ( objectIndex !== undefined ) {
43851
43852				if ( targetObject[ objectIndex ] === undefined ) {
43853
43854					console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
43855					return;
43856
43857				}
43858
43859				targetObject = targetObject[ objectIndex ];
43860
43861			}
43862
43863		}
43864
43865		// resolve property
43866		var nodeProperty = targetObject[ propertyName ];
43867
43868		if ( nodeProperty === undefined ) {
43869
43870			var nodeName = parsedPath.nodeName;
43871
43872			console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
43873				'.' + propertyName + ' but it wasn\'t found.', targetObject );
43874			return;
43875
43876		}
43877
43878		// determine versioning scheme
43879		var versioning = this.Versioning.None;
43880
43881		this.targetObject = targetObject;
43882
43883		if ( targetObject.needsUpdate !== undefined ) { // material
43884
43885			versioning = this.Versioning.NeedsUpdate;
43886
43887		} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
43888
43889			versioning = this.Versioning.MatrixWorldNeedsUpdate;
43890
43891		}
43892
43893		// determine how the property gets bound
43894		var bindingType = this.BindingType.Direct;
43895
43896		if ( propertyIndex !== undefined ) {
43897
43898			// access a sub element of the property array (only primitives are supported right now)
43899
43900			if ( propertyName === "morphTargetInfluences" ) {
43901
43902				// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
43903
43904				// support resolving morphTarget names into indices.
43905				if ( ! targetObject.geometry ) {
43906
43907					console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
43908					return;
43909
43910				}
43911
43912				if ( targetObject.geometry.isBufferGeometry ) {
43913
43914					if ( ! targetObject.geometry.morphAttributes ) {
43915
43916						console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
43917						return;
43918
43919					}
43920
43921					for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {
43922
43923						if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {
43924
43925							propertyIndex = i;
43926							break;
43927
43928						}
43929
43930					}
43931
43932
43933				} else {
43934
43935					if ( ! targetObject.geometry.morphTargets ) {
43936
43937						console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );
43938						return;
43939
43940					}
43941
43942					for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {
43943
43944						if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {
43945
43946							propertyIndex = i;
43947							break;
43948
43949						}
43950
43951					}
43952
43953				}
43954
43955			}
43956
43957			bindingType = this.BindingType.ArrayElement;
43958
43959			this.resolvedProperty = nodeProperty;
43960			this.propertyIndex = propertyIndex;
43961
43962		} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
43963
43964			// must use copy for Object3D.Euler/Quaternion
43965
43966			bindingType = this.BindingType.HasFromToArray;
43967
43968			this.resolvedProperty = nodeProperty;
43969
43970		} else if ( Array.isArray( nodeProperty ) ) {
43971
43972			bindingType = this.BindingType.EntireArray;
43973
43974			this.resolvedProperty = nodeProperty;
43975
43976		} else {
43977
43978			this.propertyName = propertyName;
43979
43980		}
43981
43982		// select getter / setter
43983		this.getValue = this.GetterByBindingType[ bindingType ];
43984		this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
43985
43986	},
43987
43988	unbind: function () {
43989
43990		this.node = null;
43991
43992		// back to the prototype version of getValue / setValue
43993		// note: avoiding to mutate the shape of 'this' via 'delete'
43994		this.getValue = this._getValue_unbound;
43995		this.setValue = this._setValue_unbound;
43996
43997	}
43998
43999} );
44000
44001// DECLARE ALIAS AFTER assign prototype
44002Object.assign( PropertyBinding.prototype, {
44003
44004	// initial state of these methods that calls 'bind'
44005	_getValue_unbound: PropertyBinding.prototype.getValue,
44006	_setValue_unbound: PropertyBinding.prototype.setValue,
44007
44008} );
44009
44010/**
44011 *
44012 * A group of objects that receives a shared animation state.
44013 *
44014 * Usage:
44015 *
44016 *  - Add objects you would otherwise pass as 'root' to the
44017 *    constructor or the .clipAction method of AnimationMixer.
44018 *
44019 *  - Instead pass this object as 'root'.
44020 *
44021 *  - You can also add and remove objects later when the mixer
44022 *    is running.
44023 *
44024 * Note:
44025 *
44026 *    Objects of this class appear as one object to the mixer,
44027 *    so cache control of the individual objects must be done
44028 *    on the group.
44029 *
44030 * Limitation:
44031 *
44032 *  - The animated properties must be compatible among the
44033 *    all objects in the group.
44034 *
44035 *  - A single property can either be controlled through a
44036 *    target group or directly, but not both.
44037 *
44038 * @author tschw
44039 */
44040
44041function AnimationObjectGroup() {
44042
44043	this.uuid = MathUtils.generateUUID();
44044
44045	// cached objects followed by the active ones
44046	this._objects = Array.prototype.slice.call( arguments );
44047
44048	this.nCachedObjects_ = 0; // threshold
44049	// note: read by PropertyBinding.Composite
44050
44051	var indices = {};
44052	this._indicesByUUID = indices; // for bookkeeping
44053
44054	for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
44055
44056		indices[ arguments[ i ].uuid ] = i;
44057
44058	}
44059
44060	this._paths = []; // inside: string
44061	this._parsedPaths = []; // inside: { we don't care, here }
44062	this._bindings = []; // inside: Array< PropertyBinding >
44063	this._bindingsIndicesByPath = {}; // inside: indices in these arrays
44064
44065	var scope = this;
44066
44067	this.stats = {
44068
44069		objects: {
44070			get total() {
44071
44072				return scope._objects.length;
44073
44074			},
44075			get inUse() {
44076
44077				return this.total - scope.nCachedObjects_;
44078
44079			}
44080		},
44081		get bindingsPerObject() {
44082
44083			return scope._bindings.length;
44084
44085		}
44086
44087	};
44088
44089}
44090
44091Object.assign( AnimationObjectGroup.prototype, {
44092
44093	isAnimationObjectGroup: true,
44094
44095	add: function () {
44096
44097		var objects = this._objects,
44098			nObjects = objects.length,
44099			nCachedObjects = this.nCachedObjects_,
44100			indicesByUUID = this._indicesByUUID,
44101			paths = this._paths,
44102			parsedPaths = this._parsedPaths,
44103			bindings = this._bindings,
44104			nBindings = bindings.length,
44105			knownObject = undefined;
44106
44107		for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
44108
44109			var object = arguments[ i ],
44110				uuid = object.uuid,
44111				index = indicesByUUID[ uuid ];
44112
44113			if ( index === undefined ) {
44114
44115				// unknown object -> add it to the ACTIVE region
44116
44117				index = nObjects ++;
44118				indicesByUUID[ uuid ] = index;
44119				objects.push( object );
44120
44121				// accounting is done, now do the same for all bindings
44122
44123				for ( var j = 0, m = nBindings; j !== m; ++ j ) {
44124
44125					bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
44126
44127				}
44128
44129			} else if ( index < nCachedObjects ) {
44130
44131				knownObject = objects[ index ];
44132
44133				// move existing object to the ACTIVE region
44134
44135				var firstActiveIndex = -- nCachedObjects,
44136					lastCachedObject = objects[ firstActiveIndex ];
44137
44138				indicesByUUID[ lastCachedObject.uuid ] = index;
44139				objects[ index ] = lastCachedObject;
44140
44141				indicesByUUID[ uuid ] = firstActiveIndex;
44142				objects[ firstActiveIndex ] = object;
44143
44144				// accounting is done, now do the same for all bindings
44145
44146				for ( var j = 0, m = nBindings; j !== m; ++ j ) {
44147
44148					var bindingsForPath = bindings[ j ],
44149						lastCached = bindingsForPath[ firstActiveIndex ],
44150						binding = bindingsForPath[ index ];
44151
44152					bindingsForPath[ index ] = lastCached;
44153
44154					if ( binding === undefined ) {
44155
44156						// since we do not bother to create new bindings
44157						// for objects that are cached, the binding may
44158						// or may not exist
44159
44160						binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
44161
44162					}
44163
44164					bindingsForPath[ firstActiveIndex ] = binding;
44165
44166				}
44167
44168			} else if ( objects[ index ] !== knownObject ) {
44169
44170				console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
44171					'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
44172
44173			} // else the object is already where we want it to be
44174
44175		} // for arguments
44176
44177		this.nCachedObjects_ = nCachedObjects;
44178
44179	},
44180
44181	remove: function () {
44182
44183		var objects = this._objects,
44184			nCachedObjects = this.nCachedObjects_,
44185			indicesByUUID = this._indicesByUUID,
44186			bindings = this._bindings,
44187			nBindings = bindings.length;
44188
44189		for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
44190
44191			var object = arguments[ i ],
44192				uuid = object.uuid,
44193				index = indicesByUUID[ uuid ];
44194
44195			if ( index !== undefined && index >= nCachedObjects ) {
44196
44197				// move existing object into the CACHED region
44198
44199				var lastCachedIndex = nCachedObjects ++,
44200					firstActiveObject = objects[ lastCachedIndex ];
44201
44202				indicesByUUID[ firstActiveObject.uuid ] = index;
44203				objects[ index ] = firstActiveObject;
44204
44205				indicesByUUID[ uuid ] = lastCachedIndex;
44206				objects[ lastCachedIndex ] = object;
44207
44208				// accounting is done, now do the same for all bindings
44209
44210				for ( var j = 0, m = nBindings; j !== m; ++ j ) {
44211
vendor: 6,456 bytes, lines 44212-44485
44212					var bindingsForPath = bindings[ j ],
44213						firstActive = bindingsForPath[ lastCachedIndex ],
44214						binding = bindingsForPath[ index ];
44215
44216					bindingsForPath[ index ] = firstActive;
44217					bindingsForPath[ lastCachedIndex ] = binding;
44218
44219				}
44220
44221			}
44222
44223		} // for arguments
44224
44225		this.nCachedObjects_ = nCachedObjects;
44226
44227	},
44228
44229	// remove & forget
44230	uncache: function () {
44231
44232		var objects = this._objects,
44233			nObjects = objects.length,
44234			nCachedObjects = this.nCachedObjects_,
44235			indicesByUUID = this._indicesByUUID,
44236			bindings = this._bindings,
44237			nBindings = bindings.length;
44238
44239		for ( var i = 0, n = arguments.length; i !== n; ++ i ) {
44240
44241			var object = arguments[ i ],
44242				uuid = object.uuid,
44243				index = indicesByUUID[ uuid ];
44244
44245			if ( index !== undefined ) {
44246
44247				delete indicesByUUID[ uuid ];
44248
44249				if ( index < nCachedObjects ) {
44250
44251					// object is cached, shrink the CACHED region
44252
44253					var firstActiveIndex = -- nCachedObjects,
44254						lastCachedObject = objects[ firstActiveIndex ],
44255						lastIndex = -- nObjects,
44256						lastObject = objects[ lastIndex ];
44257
44258					// last cached object takes this object's place
44259					indicesByUUID[ lastCachedObject.uuid ] = index;
44260					objects[ index ] = lastCachedObject;
44261
44262					// last object goes to the activated slot and pop
44263					indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
44264					objects[ firstActiveIndex ] = lastObject;
44265					objects.pop();
44266
44267					// accounting is done, now do the same for all bindings
44268
44269					for ( var j = 0, m = nBindings; j !== m; ++ j ) {
44270
44271						var bindingsForPath = bindings[ j ],
44272							lastCached = bindingsForPath[ firstActiveIndex ],
44273							last = bindingsForPath[ lastIndex ];
44274
44275						bindingsForPath[ index ] = lastCached;
44276						bindingsForPath[ firstActiveIndex ] = last;
44277						bindingsForPath.pop();
44278
44279					}
44280
44281				} else {
44282
44283					// object is active, just swap with the last and pop
44284
44285					var lastIndex = -- nObjects,
44286						lastObject = objects[ lastIndex ];
44287
44288					indicesByUUID[ lastObject.uuid ] = index;
44289					objects[ index ] = lastObject;
44290					objects.pop();
44291
44292					// accounting is done, now do the same for all bindings
44293
44294					for ( var j = 0, m = nBindings; j !== m; ++ j ) {
44295
44296						var bindingsForPath = bindings[ j ];
44297
44298						bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
44299						bindingsForPath.pop();
44300
44301					}
44302
44303				} // cached or active
44304
44305			} // if object is known
44306
44307		} // for arguments
44308
44309		this.nCachedObjects_ = nCachedObjects;
44310
44311	},
44312
44313	// Internal interface used by befriended PropertyBinding.Composite:
44314
44315	subscribe_: function ( path, parsedPath ) {
44316
44317		// returns an array of bindings for the given path that is changed
44318		// according to the contained objects in the group
44319
44320		var indicesByPath = this._bindingsIndicesByPath,
44321			index = indicesByPath[ path ],
44322			bindings = this._bindings;
44323
44324		if ( index !== undefined ) return bindings[ index ];
44325
44326		var paths = this._paths,
44327			parsedPaths = this._parsedPaths,
44328			objects = this._objects,
44329			nObjects = objects.length,
44330			nCachedObjects = this.nCachedObjects_,
44331			bindingsForPath = new Array( nObjects );
44332
44333		index = bindings.length;
44334
44335		indicesByPath[ path ] = index;
44336
44337		paths.push( path );
44338		parsedPaths.push( parsedPath );
44339		bindings.push( bindingsForPath );
44340
44341		for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
44342
44343			var object = objects[ i ];
44344			bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
44345
44346		}
44347
44348		return bindingsForPath;
44349
44350	},
44351
44352	unsubscribe_: function ( path ) {
44353
44354		// tells the group to forget about a property path and no longer
44355		// update the array previously obtained with 'subscribe_'
44356
44357		var indicesByPath = this._bindingsIndicesByPath,
44358			index = indicesByPath[ path ];
44359
44360		if ( index !== undefined ) {
44361
44362			var paths = this._paths,
44363				parsedPaths = this._parsedPaths,
44364				bindings = this._bindings,
44365				lastBindingsIndex = bindings.length - 1,
44366				lastBindings = bindings[ lastBindingsIndex ],
44367				lastBindingsPath = path[ lastBindingsIndex ];
44368
44369			indicesByPath[ lastBindingsPath ] = index;
44370
44371			bindings[ index ] = lastBindings;
44372			bindings.pop();
44373
44374			parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
44375			parsedPaths.pop();
44376
44377			paths[ index ] = paths[ lastBindingsIndex ];
44378			paths.pop();
44379
44380		}
44381
44382	}
44383
44384} );
44385
44386/**
44387 *
44388 * Action provided by AnimationMixer for scheduling clip playback on specific
44389 * objects.
44390 *
44391 * @author Ben Houston / http://clara.io/
44392 * @author David Sarno / http://lighthaus.us/
44393 * @author tschw
44394 *
44395 */
44396
44397function AnimationAction( mixer, clip, localRoot, blendMode ) {
44398
44399	this._mixer = mixer;
44400	this._clip = clip;
44401	this._localRoot = localRoot || null;
44402	this.blendMode = blendMode || clip.blendMode;
44403
44404	var tracks = clip.tracks,
44405		nTracks = tracks.length,
44406		interpolants = new Array( nTracks );
44407
44408	var interpolantSettings = {
44409		endingStart: ZeroCurvatureEnding,
44410		endingEnd: ZeroCurvatureEnding
44411	};
44412
44413	for ( var i = 0; i !== nTracks; ++ i ) {
44414
44415		var interpolant = tracks[ i ].createInterpolant( null );
44416		interpolants[ i ] = interpolant;
44417		interpolant.settings = interpolantSettings;
44418
44419	}
44420
44421	this._interpolantSettings = interpolantSettings;
44422
44423	this._interpolants = interpolants; // bound by the mixer
44424
44425	// inside: PropertyMixer (managed by the mixer)
44426	this._propertyBindings = new Array( nTracks );
44427
44428	this._cacheIndex = null; // for the memory manager
44429	this._byClipCacheIndex = null; // for the memory manager
44430
44431	this._timeScaleInterpolant = null;
44432	this._weightInterpolant = null;
44433
44434	this.loop = LoopRepeat;
44435	this._loopCount = - 1;
44436
44437	// global mixer time when the action is to be started
44438	// it's set back to 'null' upon start of the action
44439	this._startTime = null;
44440
44441	// scaled local time of the action
44442	// gets clamped or wrapped to 0..clip.duration according to loop
44443	this.time = 0;
44444
44445	this.timeScale = 1;
44446	this._effectiveTimeScale = 1;
44447
44448	this.weight = 1;
44449	this._effectiveWeight = 1;
44450
44451	this.repetitions = Infinity; // no. of repetitions when looping
44452
44453	this.paused = false; // true -> zero effective time scale
44454	this.enabled = true; // false -> zero effective weight
44455
44456	this.clampWhenFinished = false;// keep feeding the last frame?
44457
44458	this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
44459	this.zeroSlopeAtEnd = true;// clips for start, loop and end
44460
44461}
44462
44463Object.assign( AnimationAction.prototype, {
44464
44465	// State & Scheduling
44466
44467	play: function () {
44468
44469		this._mixer._activateAction( this );
44470
44471		return this;
44472
44473	},
44474
44475	stop: function () {
44476
44477		this._mixer._deactivateAction( this );
44478
44479		return this.reset();
44480
44481	},
44482
44483	reset: function () {
44484
44485		this.paused = false;
vendor: 4,176 bytes, lines 44486-44709
44486		this.enabled = true;
44487
44488		this.time = 0; // restart clip
44489		this._loopCount = - 1;// forget previous loops
44490		this._startTime = null;// forget scheduling
44491
44492		return this.stopFading().stopWarping();
44493
44494	},
44495
44496	isRunning: function () {
44497
44498		return this.enabled && ! this.paused && this.timeScale !== 0 &&
44499			this._startTime === null && this._mixer._isActiveAction( this );
44500
44501	},
44502
44503	// return true when play has been called
44504	isScheduled: function () {
44505
44506		return this._mixer._isActiveAction( this );
44507
44508	},
44509
44510	startAt: function ( time ) {
44511
44512		this._startTime = time;
44513
44514		return this;
44515
44516	},
44517
44518	setLoop: function ( mode, repetitions ) {
44519
44520		this.loop = mode;
44521		this.repetitions = repetitions;
44522
44523		return this;
44524
44525	},
44526
44527	// Weight
44528
44529	// set the weight stopping any scheduled fading
44530	// although .enabled = false yields an effective weight of zero, this
44531	// method does *not* change .enabled, because it would be confusing
44532	setEffectiveWeight: function ( weight ) {
44533
44534		this.weight = weight;
44535
44536		// note: same logic as when updated at runtime
44537		this._effectiveWeight = this.enabled ? weight : 0;
44538
44539		return this.stopFading();
44540
44541	},
44542
44543	// return the weight considering fading and .enabled
44544	getEffectiveWeight: function () {
44545
44546		return this._effectiveWeight;
44547
44548	},
44549
44550	fadeIn: function ( duration ) {
44551
44552		return this._scheduleFading( duration, 0, 1 );
44553
44554	},
44555
44556	fadeOut: function ( duration ) {
44557
44558		return this._scheduleFading( duration, 1, 0 );
44559
44560	},
44561
44562	crossFadeFrom: function ( fadeOutAction, duration, warp ) {
44563
44564		fadeOutAction.fadeOut( duration );
44565		this.fadeIn( duration );
44566
44567		if ( warp ) {
44568
44569			var fadeInDuration = this._clip.duration,
44570				fadeOutDuration = fadeOutAction._clip.duration,
44571
44572				startEndRatio = fadeOutDuration / fadeInDuration,
44573				endStartRatio = fadeInDuration / fadeOutDuration;
44574
44575			fadeOutAction.warp( 1.0, startEndRatio, duration );
44576			this.warp( endStartRatio, 1.0, duration );
44577
44578		}
44579
44580		return this;
44581
44582	},
44583
44584	crossFadeTo: function ( fadeInAction, duration, warp ) {
44585
44586		return fadeInAction.crossFadeFrom( this, duration, warp );
44587
44588	},
44589
44590	stopFading: function () {
44591
44592		var weightInterpolant = this._weightInterpolant;
44593
44594		if ( weightInterpolant !== null ) {
44595
44596			this._weightInterpolant = null;
44597			this._mixer._takeBackControlInterpolant( weightInterpolant );
44598
44599		}
44600
44601		return this;
44602
44603	},
44604
44605	// Time Scale Control
44606
44607	// set the time scale stopping any scheduled warping
44608	// although .paused = true yields an effective time scale of zero, this
44609	// method does *not* change .paused, because it would be confusing
44610	setEffectiveTimeScale: function ( timeScale ) {
44611
44612		this.timeScale = timeScale;
44613		this._effectiveTimeScale = this.paused ? 0 : timeScale;
44614
44615		return this.stopWarping();
44616
44617	},
44618
44619	// return the time scale considering warping and .paused
44620	getEffectiveTimeScale: function () {
44621
44622		return this._effectiveTimeScale;
44623
44624	},
44625
44626	setDuration: function ( duration ) {
44627
44628		this.timeScale = this._clip.duration / duration;
44629
44630		return this.stopWarping();
44631
44632	},
44633
44634	syncWith: function ( action ) {
44635
44636		this.time = action.time;
44637		this.timeScale = action.timeScale;
44638
44639		return this.stopWarping();
44640
44641	},
44642
44643	halt: function ( duration ) {
44644
44645		return this.warp( this._effectiveTimeScale, 0, duration );
44646
44647	},
44648
44649	warp: function ( startTimeScale, endTimeScale, duration ) {
44650
44651		var mixer = this._mixer, now = mixer.time,
44652			interpolant = this._timeScaleInterpolant,
44653
44654			timeScale = this.timeScale;
44655
44656		if ( interpolant === null ) {
44657
44658			interpolant = mixer._lendControlInterpolant();
44659			this._timeScaleInterpolant = interpolant;
44660
44661		}
44662
44663		var times = interpolant.parameterPositions,
44664			values = interpolant.sampleValues;
44665
44666		times[ 0 ] = now;
44667		times[ 1 ] = now + duration;
44668
44669		values[ 0 ] = startTimeScale / timeScale;
44670		values[ 1 ] = endTimeScale / timeScale;
44671
44672		return this;
44673
44674	},
44675
44676	stopWarping: function () {
44677
44678		var timeScaleInterpolant = this._timeScaleInterpolant;
44679
44680		if ( timeScaleInterpolant !== null ) {
44681
44682			this._timeScaleInterpolant = null;
44683			this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
44684
44685		}
44686
44687		return this;
44688
44689	},
44690
44691	// Object Accessors
44692
44693	getMixer: function () {
44694
44695		return this._mixer;
44696
44697	},
44698
44699	getClip: function () {
44700
44701		return this._clip;
44702
44703	},
44704
44705	getRoot: function () {
44706
44707		return this._localRoot || this._mixer._root;
44708
44709	},
vendor: 17,748 bytes, lines 44710-45610
44710
44711	// Interna
44712
44713	_update: function ( time, deltaTime, timeDirection, accuIndex ) {
44714
44715		// called by the mixer
44716
44717		if ( ! this.enabled ) {
44718
44719			// call ._updateWeight() to update ._effectiveWeight
44720
44721			this._updateWeight( time );
44722			return;
44723
44724		}
44725
44726		var startTime = this._startTime;
44727
44728		if ( startTime !== null ) {
44729
44730			// check for scheduled start of action
44731
44732			var timeRunning = ( time - startTime ) * timeDirection;
44733			if ( timeRunning < 0 || timeDirection === 0 ) {
44734
44735				return; // yet to come / don't decide when delta = 0
44736
44737			}
44738
44739			// start
44740
44741			this._startTime = null; // unschedule
44742			deltaTime = timeDirection * timeRunning;
44743
44744		}
44745
44746		// apply time scale and advance time
44747
44748		deltaTime *= this._updateTimeScale( time );
44749		var clipTime = this._updateTime( deltaTime );
44750
44751		// note: _updateTime may disable the action resulting in
44752		// an effective weight of 0
44753
44754		var weight = this._updateWeight( time );
44755
44756		if ( weight > 0 ) {
44757
44758			var interpolants = this._interpolants;
44759			var propertyMixers = this._propertyBindings;
44760
44761			switch ( this.blendMode ) {
44762
44763				case AdditiveAnimationBlendMode:
44764
44765					for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
44766
44767						interpolants[ j ].evaluate( clipTime );
44768						propertyMixers[ j ].accumulateAdditive( weight );
44769
44770					}
44771
44772					break;
44773
44774				case NormalAnimationBlendMode:
44775				default:
44776
44777					for ( var j = 0, m = interpolants.length; j !== m; ++ j ) {
44778
44779						interpolants[ j ].evaluate( clipTime );
44780						propertyMixers[ j ].accumulate( accuIndex, weight );
44781
44782					}
44783
44784			}
44785
44786		}
44787
44788	},
44789
44790	_updateWeight: function ( time ) {
44791
44792		var weight = 0;
44793
44794		if ( this.enabled ) {
44795
44796			weight = this.weight;
44797			var interpolant = this._weightInterpolant;
44798
44799			if ( interpolant !== null ) {
44800
44801				var interpolantValue = interpolant.evaluate( time )[ 0 ];
44802
44803				weight *= interpolantValue;
44804
44805				if ( time > interpolant.parameterPositions[ 1 ] ) {
44806
44807					this.stopFading();
44808
44809					if ( interpolantValue === 0 ) {
44810
44811						// faded out, disable
44812						this.enabled = false;
44813
44814					}
44815
44816				}
44817
44818			}
44819
44820		}
44821
44822		this._effectiveWeight = weight;
44823		return weight;
44824
44825	},
44826
44827	_updateTimeScale: function ( time ) {
44828
44829		var timeScale = 0;
44830
44831		if ( ! this.paused ) {
44832
44833			timeScale = this.timeScale;
44834
44835			var interpolant = this._timeScaleInterpolant;
44836
44837			if ( interpolant !== null ) {
44838
44839				var interpolantValue = interpolant.evaluate( time )[ 0 ];
44840
44841				timeScale *= interpolantValue;
44842
44843				if ( time > interpolant.parameterPositions[ 1 ] ) {
44844
44845					this.stopWarping();
44846
44847					if ( timeScale === 0 ) {
44848
44849						// motion has halted, pause
44850						this.paused = true;
44851
44852					} else {
44853
44854						// warp done - apply final time scale
44855						this.timeScale = timeScale;
44856
44857					}
44858
44859				}
44860
44861			}
44862
44863		}
44864
44865		this._effectiveTimeScale = timeScale;
44866		return timeScale;
44867
44868	},
44869
44870	_updateTime: function ( deltaTime ) {
44871
44872		var time = this.time + deltaTime;
44873		var duration = this._clip.duration;
44874		var loop = this.loop;
44875		var loopCount = this._loopCount;
44876
44877		var pingPong = ( loop === LoopPingPong );
44878
44879		if ( deltaTime === 0 ) {
44880
44881			if ( loopCount === - 1 ) return time;
44882
44883			return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
44884
44885		}
44886
44887		if ( loop === LoopOnce ) {
44888
44889			if ( loopCount === - 1 ) {
44890
44891				// just started
44892
44893				this._loopCount = 0;
44894				this._setEndings( true, true, false );
44895
44896			}
44897
44898			handle_stop: {
44899
44900				if ( time >= duration ) {
44901
44902					time = duration;
44903
44904				} else if ( time < 0 ) {
44905
44906					time = 0;
44907
44908				} else {
44909
44910					this.time = time;
44911
44912					break handle_stop;
44913
44914				}
44915
44916				if ( this.clampWhenFinished ) this.paused = true;
44917				else this.enabled = false;
44918
44919				this.time = time;
44920
44921				this._mixer.dispatchEvent( {
44922					type: 'finished', action: this,
44923					direction: deltaTime < 0 ? - 1 : 1
44924				} );
44925
44926			}
44927
44928		} else { // repetitive Repeat or PingPong
44929
44930			if ( loopCount === - 1 ) {
44931
44932				// just started
44933
44934				if ( deltaTime >= 0 ) {
44935
44936					loopCount = 0;
44937
44938					this._setEndings( true, this.repetitions === 0, pingPong );
44939
44940				} else {
44941
44942					// when looping in reverse direction, the initial
44943					// transition through zero counts as a repetition,
44944					// so leave loopCount at -1
44945
44946					this._setEndings( this.repetitions === 0, true, pingPong );
44947
44948				}
44949
44950			}
44951
44952			if ( time >= duration || time < 0 ) {
44953
44954				// wrap around
44955
44956				var loopDelta = Math.floor( time / duration ); // signed
44957				time -= duration * loopDelta;
44958
44959				loopCount += Math.abs( loopDelta );
44960
44961				var pending = this.repetitions - loopCount;
44962
44963				if ( pending <= 0 ) {
44964
44965					// have to stop (switch state, clamp time, fire event)
44966
44967					if ( this.clampWhenFinished ) this.paused = true;
44968					else this.enabled = false;
44969
44970					time = deltaTime > 0 ? duration : 0;
44971
44972					this.time = time;
44973
44974					this._mixer.dispatchEvent( {
44975						type: 'finished', action: this,
44976						direction: deltaTime > 0 ? 1 : - 1
44977					} );
44978
44979				} else {
44980
44981					// keep running
44982
44983					if ( pending === 1 ) {
44984
44985						// entering the last round
44986
44987						var atStart = deltaTime < 0;
44988						this._setEndings( atStart, ! atStart, pingPong );
44989
44990					} else {
44991
44992						this._setEndings( false, false, pingPong );
44993
44994					}
44995
44996					this._loopCount = loopCount;
44997
44998					this.time = time;
44999
45000					this._mixer.dispatchEvent( {
45001						type: 'loop', action: this, loopDelta: loopDelta
45002					} );
45003
45004				}
45005
45006			} else {
45007
45008				this.time = time;
45009
45010			}
45011
45012			if ( pingPong && ( loopCount & 1 ) === 1 ) {
45013
45014				// invert time for the "pong round"
45015
45016				return duration - time;
45017
45018			}
45019
45020		}
45021
45022		return time;
45023
45024	},
45025
45026	_setEndings: function ( atStart, atEnd, pingPong ) {
45027
45028		var settings = this._interpolantSettings;
45029
45030		if ( pingPong ) {
45031
45032			settings.endingStart = ZeroSlopeEnding;
45033			settings.endingEnd = ZeroSlopeEnding;
45034
45035		} else {
45036
45037			// assuming for LoopOnce atStart == atEnd == true
45038
45039			if ( atStart ) {
45040
45041				settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
45042
45043			} else {
45044
45045				settings.endingStart = WrapAroundEnding;
45046
45047			}
45048
45049			if ( atEnd ) {
45050
45051				settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
45052
45053			} else {
45054
45055				settings.endingEnd 	 = WrapAroundEnding;
45056
45057			}
45058
45059		}
45060
45061	},
45062
45063	_scheduleFading: function ( duration, weightNow, weightThen ) {
45064
45065		var mixer = this._mixer, now = mixer.time,
45066			interpolant = this._weightInterpolant;
45067
45068		if ( interpolant === null ) {
45069
45070			interpolant = mixer._lendControlInterpolant();
45071			this._weightInterpolant = interpolant;
45072
45073		}
45074
45075		var times = interpolant.parameterPositions,
45076			values = interpolant.sampleValues;
45077
45078		times[ 0 ] = now;
45079		values[ 0 ] = weightNow;
45080		times[ 1 ] = now + duration;
45081		values[ 1 ] = weightThen;
45082
45083		return this;
45084
45085	}
45086
45087} );
45088
45089/**
45090 *
45091 * Player for AnimationClips.
45092 *
45093 *
45094 * @author Ben Houston / http://clara.io/
45095 * @author David Sarno / http://lighthaus.us/
45096 * @author tschw
45097 */
45098
45099function AnimationMixer( root ) {
45100
45101	this._root = root;
45102	this._initMemoryManager();
45103	this._accuIndex = 0;
45104
45105	this.time = 0;
45106
45107	this.timeScale = 1.0;
45108
45109}
45110
45111AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
45112
45113	constructor: AnimationMixer,
45114
45115	_bindAction: function ( action, prototypeAction ) {
45116
45117		var root = action._localRoot || this._root,
45118			tracks = action._clip.tracks,
45119			nTracks = tracks.length,
45120			bindings = action._propertyBindings,
45121			interpolants = action._interpolants,
45122			rootUuid = root.uuid,
45123			bindingsByRoot = this._bindingsByRootAndName,
45124			bindingsByName = bindingsByRoot[ rootUuid ];
45125
45126		if ( bindingsByName === undefined ) {
45127
45128			bindingsByName = {};
45129			bindingsByRoot[ rootUuid ] = bindingsByName;
45130
45131		}
45132
45133		for ( var i = 0; i !== nTracks; ++ i ) {
45134
45135			var track = tracks[ i ],
45136				trackName = track.name,
45137				binding = bindingsByName[ trackName ];
45138
45139			if ( binding !== undefined ) {
45140
45141				bindings[ i ] = binding;
45142
45143			} else {
45144
45145				binding = bindings[ i ];
45146
45147				if ( binding !== undefined ) {
45148
45149					// existing binding, make sure the cache knows
45150
45151					if ( binding._cacheIndex === null ) {
45152
45153						++ binding.referenceCount;
45154						this._addInactiveBinding( binding, rootUuid, trackName );
45155
45156					}
45157
45158					continue;
45159
45160				}
45161
45162				var path = prototypeAction && prototypeAction.
45163					_propertyBindings[ i ].binding.parsedPath;
45164
45165				binding = new PropertyMixer(
45166					PropertyBinding.create( root, trackName, path ),
45167					track.ValueTypeName, track.getValueSize() );
45168
45169				++ binding.referenceCount;
45170				this._addInactiveBinding( binding, rootUuid, trackName );
45171
45172				bindings[ i ] = binding;
45173
45174			}
45175
45176			interpolants[ i ].resultBuffer = binding.buffer;
45177
45178		}
45179
45180	},
45181
45182	_activateAction: function ( action ) {
45183
45184		if ( ! this._isActiveAction( action ) ) {
45185
45186			if ( action._cacheIndex === null ) {
45187
45188				// this action has been forgotten by the cache, but the user
45189				// appears to be still using it -> rebind
45190
45191				var rootUuid = ( action._localRoot || this._root ).uuid,
45192					clipUuid = action._clip.uuid,
45193					actionsForClip = this._actionsByClip[ clipUuid ];
45194
45195				this._bindAction( action,
45196					actionsForClip && actionsForClip.knownActions[ 0 ] );
45197
45198				this._addInactiveAction( action, clipUuid, rootUuid );
45199
45200			}
45201
45202			var bindings = action._propertyBindings;
45203
45204			// increment reference counts / sort out state
45205			for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
45206
45207				var binding = bindings[ i ];
45208
45209				if ( binding.useCount ++ === 0 ) {
45210
45211					this._lendBinding( binding );
45212					binding.saveOriginalState();
45213
45214				}
45215
45216			}
45217
45218			this._lendAction( action );
45219
45220		}
45221
45222	},
45223
45224	_deactivateAction: function ( action ) {
45225
45226		if ( this._isActiveAction( action ) ) {
45227
45228			var bindings = action._propertyBindings;
45229
45230			// decrement reference counts / sort out state
45231			for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
45232
45233				var binding = bindings[ i ];
45234
45235				if ( -- binding.useCount === 0 ) {
45236
45237					binding.restoreOriginalState();
45238					this._takeBackBinding( binding );
45239
45240				}
45241
45242			}
45243
45244			this._takeBackAction( action );
45245
45246		}
45247
45248	},
45249
45250	// Memory manager
45251
45252	_initMemoryManager: function () {
45253
45254		this._actions = []; // 'nActiveActions' followed by inactive ones
45255		this._nActiveActions = 0;
45256
45257		this._actionsByClip = {};
45258		// inside:
45259		// {
45260		// 	knownActions: Array< AnimationAction > - used as prototypes
45261		// 	actionByRoot: AnimationAction - lookup
45262		// }
45263
45264
45265		this._bindings = []; // 'nActiveBindings' followed by inactive ones
45266		this._nActiveBindings = 0;
45267
45268		this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
45269
45270
45271		this._controlInterpolants = []; // same game as above
45272		this._nActiveControlInterpolants = 0;
45273
45274		var scope = this;
45275
45276		this.stats = {
45277
45278			actions: {
45279				get total() {
45280
45281					return scope._actions.length;
45282
45283				},
45284				get inUse() {
45285
45286					return scope._nActiveActions;
45287
45288				}
45289			},
45290			bindings: {
45291				get total() {
45292
45293					return scope._bindings.length;
45294
45295				},
45296				get inUse() {
45297
45298					return scope._nActiveBindings;
45299
45300				}
45301			},
45302			controlInterpolants: {
45303				get total() {
45304
45305					return scope._controlInterpolants.length;
45306
45307				},
45308				get inUse() {
45309
45310					return scope._nActiveControlInterpolants;
45311
45312				}
45313			}
45314
45315		};
45316
45317	},
45318
45319	// Memory management for AnimationAction objects
45320
45321	_isActiveAction: function ( action ) {
45322
45323		var index = action._cacheIndex;
45324		return index !== null && index < this._nActiveActions;
45325
45326	},
45327
45328	_addInactiveAction: function ( action, clipUuid, rootUuid ) {
45329
45330		var actions = this._actions,
45331			actionsByClip = this._actionsByClip,
45332			actionsForClip = actionsByClip[ clipUuid ];
45333
45334		if ( actionsForClip === undefined ) {
45335
45336			actionsForClip = {
45337
45338				knownActions: [ action ],
45339				actionByRoot: {}
45340
45341			};
45342
45343			action._byClipCacheIndex = 0;
45344
45345			actionsByClip[ clipUuid ] = actionsForClip;
45346
45347		} else {
45348
45349			var knownActions = actionsForClip.knownActions;
45350
45351			action._byClipCacheIndex = knownActions.length;
45352			knownActions.push( action );
45353
45354		}
45355
45356		action._cacheIndex = actions.length;
45357		actions.push( action );
45358
45359		actionsForClip.actionByRoot[ rootUuid ] = action;
45360
45361	},
45362
45363	_removeInactiveAction: function ( action ) {
45364
45365		var actions = this._actions,
45366			lastInactiveAction = actions[ actions.length - 1 ],
45367			cacheIndex = action._cacheIndex;
45368
45369		lastInactiveAction._cacheIndex = cacheIndex;
45370		actions[ cacheIndex ] = lastInactiveAction;
45371		actions.pop();
45372
45373		action._cacheIndex = null;
45374
45375
45376		var clipUuid = action._clip.uuid,
45377			actionsByClip = this._actionsByClip,
45378			actionsForClip = actionsByClip[ clipUuid ],
45379			knownActionsForClip = actionsForClip.knownActions,
45380
45381			lastKnownAction =
45382				knownActionsForClip[ knownActionsForClip.length - 1 ],
45383
45384			byClipCacheIndex = action._byClipCacheIndex;
45385
45386		lastKnownAction._byClipCacheIndex = byClipCacheIndex;
45387		knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
45388		knownActionsForClip.pop();
45389
45390		action._byClipCacheIndex = null;
45391
45392
45393		var actionByRoot = actionsForClip.actionByRoot,
45394			rootUuid = ( action._localRoot || this._root ).uuid;
45395
45396		delete actionByRoot[ rootUuid ];
45397
45398		if ( knownActionsForClip.length === 0 ) {
45399
45400			delete actionsByClip[ clipUuid ];
45401
45402		}
45403
45404		this._removeInactiveBindingsForAction( action );
45405
45406	},
45407
45408	_removeInactiveBindingsForAction: function ( action ) {
45409
45410		var bindings = action._propertyBindings;
45411		for ( var i = 0, n = bindings.length; i !== n; ++ i ) {
45412
45413			var binding = bindings[ i ];
45414
45415			if ( -- binding.referenceCount === 0 ) {
45416
45417				this._removeInactiveBinding( binding );
45418
45419			}
45420
45421		}
45422
45423	},
45424
45425	_lendAction: function ( action ) {
45426
45427		// [ active actions |  inactive actions  ]
45428		// [  active actions >| inactive actions ]
45429		//                 s        a
45430		//                  <-swap->
45431		//                 a        s
45432
45433		var actions = this._actions,
45434			prevIndex = action._cacheIndex,
45435
45436			lastActiveIndex = this._nActiveActions ++,
45437
45438			firstInactiveAction = actions[ lastActiveIndex ];
45439
45440		action._cacheIndex = lastActiveIndex;
45441		actions[ lastActiveIndex ] = action;
45442
45443		firstInactiveAction._cacheIndex = prevIndex;
45444		actions[ prevIndex ] = firstInactiveAction;
45445
45446	},
45447
45448	_takeBackAction: function ( action ) {
45449
45450		// [  active actions  | inactive actions ]
45451		// [ active actions |< inactive actions  ]
45452		//        a        s
45453		//         <-swap->
45454		//        s        a
45455
45456		var actions = this._actions,
45457			prevIndex = action._cacheIndex,
45458
45459			firstInactiveIndex = -- this._nActiveActions,
45460
45461			lastActiveAction = actions[ firstInactiveIndex ];
45462
45463		action._cacheIndex = firstInactiveIndex;
45464		actions[ firstInactiveIndex ] = action;
45465
45466		lastActiveAction._cacheIndex = prevIndex;
45467		actions[ prevIndex ] = lastActiveAction;
45468
45469	},
45470
45471	// Memory management for PropertyMixer objects
45472
45473	_addInactiveBinding: function ( binding, rootUuid, trackName ) {
45474
45475		var bindingsByRoot = this._bindingsByRootAndName,
45476			bindingByName = bindingsByRoot[ rootUuid ],
45477
45478			bindings = this._bindings;
45479
45480		if ( bindingByName === undefined ) {
45481
45482			bindingByName = {};
45483			bindingsByRoot[ rootUuid ] = bindingByName;
45484
45485		}
45486
45487		bindingByName[ trackName ] = binding;
45488
45489		binding._cacheIndex = bindings.length;
45490		bindings.push( binding );
45491
45492	},
45493
45494	_removeInactiveBinding: function ( binding ) {
45495
45496		var bindings = this._bindings,
45497			propBinding = binding.binding,
45498			rootUuid = propBinding.rootNode.uuid,
45499			trackName = propBinding.path,
45500			bindingsByRoot = this._bindingsByRootAndName,
45501			bindingByName = bindingsByRoot[ rootUuid ],
45502
45503			lastInactiveBinding = bindings[ bindings.length - 1 ],
45504			cacheIndex = binding._cacheIndex;
45505
45506		lastInactiveBinding._cacheIndex = cacheIndex;
45507		bindings[ cacheIndex ] = lastInactiveBinding;
45508		bindings.pop();
45509
45510		delete bindingByName[ trackName ];
45511
45512		if ( Object.keys( bindingByName ).length === 0 ) {
45513
45514			delete bindingsByRoot[ rootUuid ];
45515
45516		}
45517
45518	},
45519
45520	_lendBinding: function ( binding ) {
45521
45522		var bindings = this._bindings,
45523			prevIndex = binding._cacheIndex,
45524
45525			lastActiveIndex = this._nActiveBindings ++,
45526
45527			firstInactiveBinding = bindings[ lastActiveIndex ];
45528
45529		binding._cacheIndex = lastActiveIndex;
45530		bindings[ lastActiveIndex ] = binding;
45531
45532		firstInactiveBinding._cacheIndex = prevIndex;
45533		bindings[ prevIndex ] = firstInactiveBinding;
45534
45535	},
45536
45537	_takeBackBinding: function ( binding ) {
45538
45539		var bindings = this._bindings,
45540			prevIndex = binding._cacheIndex,
45541
45542			firstInactiveIndex = -- this._nActiveBindings,
45543
45544			lastActiveBinding = bindings[ firstInactiveIndex ];
45545
45546		binding._cacheIndex = firstInactiveIndex;
45547		bindings[ firstInactiveIndex ] = binding;
45548
45549		lastActiveBinding._cacheIndex = prevIndex;
45550		bindings[ prevIndex ] = lastActiveBinding;
45551
45552	},
45553
45554
45555	// Memory management of Interpolants for weight and time scale
45556
45557	_lendControlInterpolant: function () {
45558
45559		var interpolants = this._controlInterpolants,
45560			lastActiveIndex = this._nActiveControlInterpolants ++,
45561			interpolant = interpolants[ lastActiveIndex ];
45562
45563		if ( interpolant === undefined ) {
45564
45565			interpolant = new LinearInterpolant(
45566				new Float32Array( 2 ), new Float32Array( 2 ),
45567				1, this._controlInterpolantsResultBuffer );
45568
45569			interpolant.__cacheIndex = lastActiveIndex;
45570			interpolants[ lastActiveIndex ] = interpolant;
45571
45572		}
45573
45574		return interpolant;
45575
45576	},
45577
45578	_takeBackControlInterpolant: function ( interpolant ) {
45579
45580		var interpolants = this._controlInterpolants,
45581			prevIndex = interpolant.__cacheIndex,
45582
45583			firstInactiveIndex = -- this._nActiveControlInterpolants,
45584
45585			lastActiveInterpolant = interpolants[ firstInactiveIndex ];
45586
45587		interpolant.__cacheIndex = firstInactiveIndex;
45588		interpolants[ firstInactiveIndex ] = interpolant;
45589
45590		lastActiveInterpolant.__cacheIndex = prevIndex;
45591		interpolants[ prevIndex ] = lastActiveInterpolant;
45592
45593	},
45594
45595	_controlInterpolantsResultBuffer: new Float32Array( 1 ),
45596
45597	// return an action for a clip optionally using a custom root target
45598	// object (this method allocates a lot of dynamic memory in case a
45599	// previously unknown clip/root combination is specified)
45600	clipAction: function ( clip, optionalRoot, blendMode ) {
45601
45602		var root = optionalRoot || this._root,
45603			rootUuid = root.uuid,
45604
45605			clipObject = typeof clip === 'string' ?
45606				AnimationClip.findByName( root, clip ) : clip,
45607
45608			clipUuid = clipObject !== null ? clipObject.uuid : clip,
45609
45610			actionsForClip = this._actionsByClip[ clipUuid ],
45611			prototypeAction = null;
45612
45613		if ( blendMode === undefined ) {
45614
45615			if ( clipObject !== null ) {
45616
45617				blendMode = clipObject.blendMode;
45618
45619			} else {
45620
45621				blendMode = NormalAnimationBlendMode;
45622
45623			}
45624
45625		}
45626
45627		if ( actionsForClip !== undefined ) {
45628
45629			var existingAction =
45630					actionsForClip.actionByRoot[ rootUuid ];
45631
45632			if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
45633
45634				return existingAction;
45635
45636			}
45637
45638			// we know the clip, so we don't have to parse all
45639			// the bindings again but can just copy
45640			prototypeAction = actionsForClip.knownActions[ 0 ];
45641
45642			// also, take the clip from the prototype action
45643			if ( clipObject === null )
45644				clipObject = prototypeAction._clip;
45645
45646		}
45647
45648		// clip must be known when specified via string
45649		if ( clipObject === null ) return null;
45650
45651		// allocate all resources required to run it
45652		var newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
45653
45654		this._bindAction( newAction, prototypeAction );
45655
45656		// and make the action known to the memory manager
45657		this._addInactiveAction( newAction, clipUuid, rootUuid );
45658
45659		return newAction;
45660
45661	},
45662
45663	// get an existing action
45664	existingAction: function ( clip, optionalRoot ) {
45665
45666		var root = optionalRoot || this._root,
45667			rootUuid = root.uuid,
45668
45669			clipObject = typeof clip === 'string' ?
45670				AnimationClip.findByName( root, clip ) : clip,
45671
45672			clipUuid = clipObject ? clipObject.uuid : clip,
45673
45674			actionsForClip = this._actionsByClip[ clipUuid ];
45675
45676		if ( actionsForClip !== undefined ) {
45677
45678			return actionsForClip.actionByRoot[ rootUuid ] || null;
45679
45680		}
45681
45682		return null;
45683
45684	},
45685
45686	// deactivates all previously scheduled actions
45687	stopAllAction: function () {
45688
45689		var actions = this._actions,
45690			nActions = this._nActiveActions,
45691			bindings = this._bindings,
45692			nBindings = this._nActiveBindings;
45693
45694		this._nActiveActions = 0;
45695		this._nActiveBindings = 0;
45696
45697		for ( var i = 0; i !== nActions; ++ i ) {
45698
45699			actions[ i ].reset();
45700
45701		}
45702
45703		for ( var i = 0; i !== nBindings; ++ i ) {
45704
45705			bindings[ i ].useCount = 0;
45706
45707		}
45708
45709		return this;
45710
45711	},
45712
45713	// advance the time and update apply the animation
45714	update: function ( deltaTime ) {
45715
45716		deltaTime *= this.timeScale;
45717
45718		var actions = this._actions,
45719			nActions = this._nActiveActions,
45720
45721			time = this.time += deltaTime,
45722			timeDirection = Math.sign( deltaTime ),
45723
45724			accuIndex = this._accuIndex ^= 1;
45725
45726		// run active actions
45727
45728		for ( var i = 0; i !== nActions; ++ i ) {
45729
45730			var action = actions[ i ];
45731
45732			action._update( time, deltaTime, timeDirection, accuIndex );
45733
45734		}
45735
45736		// update scene graph
45737
45738		var bindings = this._bindings,
45739			nBindings = this._nActiveBindings;
45740
45741		for ( var i = 0; i !== nBindings; ++ i ) {
45742
45743			bindings[ i ].apply( accuIndex );
45744
45745		}
45746
45747		return this;
45748
45749	},
45750
45751	// Allows you to seek to a specific time in an animation.
45752	setTime: function ( timeInSeconds ) {
45753
45754		this.time = 0; // Zero out time attribute for AnimationMixer object;
45755		for ( var i = 0; i < this._actions.length; i ++ ) {
45756
45757			this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
45758
45759		}
45760
45761		return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
45762
45763	},
45764
45765	// return this mixer's root target object
45766	getRoot: function () {
45767
45768		return this._root;
45769
45770	},
vendor: 4,901 bytes, lines 45771-46005
45771
45772	// free all resources specific to a particular clip
45773	uncacheClip: function ( clip ) {
45774
45775		var actions = this._actions,
45776			clipUuid = clip.uuid,
45777			actionsByClip = this._actionsByClip,
45778			actionsForClip = actionsByClip[ clipUuid ];
45779
45780		if ( actionsForClip !== undefined ) {
45781
45782			// note: just calling _removeInactiveAction would mess up the
45783			// iteration state and also require updating the state we can
45784			// just throw away
45785
45786			var actionsToRemove = actionsForClip.knownActions;
45787
45788			for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
45789
45790				var action = actionsToRemove[ i ];
45791
45792				this._deactivateAction( action );
45793
45794				var cacheIndex = action._cacheIndex,
45795					lastInactiveAction = actions[ actions.length - 1 ];
45796
45797				action._cacheIndex = null;
45798				action._byClipCacheIndex = null;
45799
45800				lastInactiveAction._cacheIndex = cacheIndex;
45801				actions[ cacheIndex ] = lastInactiveAction;
45802				actions.pop();
45803
45804				this._removeInactiveBindingsForAction( action );
45805
45806			}
45807
45808			delete actionsByClip[ clipUuid ];
45809
45810		}
45811
45812	},
45813
45814	// free all resources specific to a particular root target object
45815	uncacheRoot: function ( root ) {
45816
45817		var rootUuid = root.uuid,
45818			actionsByClip = this._actionsByClip;
45819
45820		for ( var clipUuid in actionsByClip ) {
45821
45822			var actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
45823				action = actionByRoot[ rootUuid ];
45824
45825			if ( action !== undefined ) {
45826
45827				this._deactivateAction( action );
45828				this._removeInactiveAction( action );
45829
45830			}
45831
45832		}
45833
45834		var bindingsByRoot = this._bindingsByRootAndName,
45835			bindingByName = bindingsByRoot[ rootUuid ];
45836
45837		if ( bindingByName !== undefined ) {
45838
45839			for ( var trackName in bindingByName ) {
45840
45841				var binding = bindingByName[ trackName ];
45842				binding.restoreOriginalState();
45843				this._removeInactiveBinding( binding );
45844
45845			}
45846
45847		}
45848
45849	},
45850
45851	// remove a targeted clip from the cache
45852	uncacheAction: function ( clip, optionalRoot ) {
45853
45854		var action = this.existingAction( clip, optionalRoot );
45855
45856		if ( action !== null ) {
45857
45858			this._deactivateAction( action );
45859			this._removeInactiveAction( action );
45860
45861		}
45862
45863	}
45864
45865} );
45866
45867/**
45868 * @author mrdoob / http://mrdoob.com/
45869 */
45870
45871function Uniform( value ) {
45872
45873	if ( typeof value === 'string' ) {
45874
45875		console.warn( 'THREE.Uniform: Type parameter is no longer needed.' );
45876		value = arguments[ 1 ];
45877
45878	}
45879
45880	this.value = value;
45881
45882}
45883
45884Uniform.prototype.clone = function () {
45885
45886	return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
45887
45888};
45889
45890/**
45891 * @author benaadams / https://twitter.com/ben_a_adams
45892 */
45893
45894function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {
45895
45896	InterleavedBuffer.call( this, array, stride );
45897
45898	this.meshPerAttribute = meshPerAttribute || 1;
45899
45900}
45901
45902InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {
45903
45904	constructor: InstancedInterleavedBuffer,
45905
45906	isInstancedInterleavedBuffer: true,
45907
45908	copy: function ( source ) {
45909
45910		InterleavedBuffer.prototype.copy.call( this, source );
45911
45912		this.meshPerAttribute = source.meshPerAttribute;
45913
45914		return this;
45915
45916	}
45917
45918} );
45919
45920/**
45921 * @author mrdoob / http://mrdoob.com/
45922 * @author bhouston / http://clara.io/
45923 * @author stephomi / http://stephaneginier.com/
45924 */
45925
45926function Raycaster( origin, direction, near, far ) {
45927
45928	this.ray = new Ray( origin, direction );
45929	// direction is assumed to be normalized (for accurate distance calculations)
45930
45931	this.near = near || 0;
45932	this.far = far || Infinity;
45933	this.camera = null;
45934	this.layers = new Layers();
45935
45936	this.params = {
45937		Mesh: {},
45938		Line: { threshold: 1 },
45939		LOD: {},
45940		Points: { threshold: 1 },
45941		Sprite: {}
45942	};
45943
45944	Object.defineProperties( this.params, {
45945		PointCloud: {
45946			get: function () {
45947
45948				console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );
45949				return this.Points;
45950
45951			}
45952		}
45953	} );
45954
45955}
45956
45957function ascSort( a, b ) {
45958
45959	return a.distance - b.distance;
45960
45961}
45962
45963function intersectObject( object, raycaster, intersects, recursive ) {
45964
45965	if ( object.layers.test( raycaster.layers ) ) {
45966
45967		object.raycast( raycaster, intersects );
45968
45969	}
45970
45971	if ( recursive === true ) {
45972
45973		var children = object.children;
45974
45975		for ( var i = 0, l = children.length; i < l; i ++ ) {
45976
45977			intersectObject( children[ i ], raycaster, intersects, true );
45978
45979		}
45980
45981	}
45982
45983}
45984
45985Object.assign( Raycaster.prototype, {
45986
45987	set: function ( origin, direction ) {
45988
45989		// direction is assumed to be normalized (for accurate distance calculations)
45990
45991		this.ray.set( origin, direction );
45992
45993	},
45994
45995	setFromCamera: function ( coords, camera ) {
45996
45997		if ( ( camera && camera.isPerspectiveCamera ) ) {
45998
45999			this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
46000			this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
46001			this.camera = camera;
46002
46003		} else if ( ( camera && camera.isOrthographicCamera ) ) {
46004
46005			this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera );
46005 // set origin in plane of camera
46006			this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
46007			this.camera = camera;
46008
46009		} else {
46010
46011			console.error( 'THREE.Raycaster: Unsupported camera type.' );
46012
46013		}
46014
46015	},
46016
46017	intersectObject: function ( object, recursive, optionalTarget ) {
46018
46019		var intersects = optionalTarget || [];
46020
46021		intersectObject( object, this, intersects, recursive );
46022
46023		intersects.sort( ascSort );
46024
46025		return intersects;
46026
46027	},
46028
46029	intersectObjects: function ( objects, recursive, optionalTarget ) {
46030
46031		var intersects = optionalTarget || [];
46032
46033		if ( Array.isArray( objects ) === false ) {
46034
46035			console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );
46036			return intersects;
46037
46038		}
46039
46040		for ( var i = 0, l = objects.length; i < l; i ++ ) {
46041
46042			intersectObject( objects[ i ], this, intersects, recursive );
46043
46044		}
46045
46046		intersects.sort( ascSort );
46047
46048		return intersects;
46049
46050	}
46051
46052} );
46053
46054/**
46055 * @author bhouston / http://clara.io
46056 * @author WestLangley / http://github.com/WestLangley
46057 *
46058 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
46059 *
46060 * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
46061 * The azimuthal angle (theta) is measured from the positive z-axis.
46062 */
46063
46064function Spherical( radius, phi, theta ) {
46065
46066	this.radius = ( radius !== undefined ) ? radius : 1.0;
46067	this.phi = ( phi !== undefined ) ? phi : 0; // polar angle
46068	this.theta = ( theta !== undefined ) ? theta : 0; // azimuthal angle
46069
46070	return this;
46071
46072}
46073
46074Object.assign( Spherical.prototype, {
46075
46076	set: function ( radius, phi, theta ) {
46077
46078		this.radius = radius;
46079		this.phi = phi;
46080		this.theta = theta;
46081
46082		return this;
46083
46084	},
46085
46086	clone: function () {
46087
46088		return new this.constructor().copy( this );
46089
46090	},
46091
46092	copy: function ( other ) {
46093
46094		this.radius = other.radius;
46095		this.phi = other.phi;
46096		this.theta = other.theta;
46097
46098		return this;
46099
46100	},
46101
46102	// restrict phi to be betwee EPS and PI-EPS
46103	makeSafe: function () {
46104
46105		var EPS = 0.000001;
46106		this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
46107
46108		return this;
46109
46110	},
46111
46112	setFromVector3: function ( v ) {
46113
46114		return this.setFromCartesianCoords( v.x, v.y, v.z );
46115
46116	},
46117
46118	setFromCartesianCoords: function ( x, y, z ) {
46119
46120		this.radius = Math.sqrt( x * x + y * y + z * z );
46121
46122		if ( this.radius === 0 ) {
46123
46124			this.theta = 0;
46125			this.phi = 0;
46126
46127		} else {
46128
46129			this.theta = Math.atan2( x, z );
46130			this.phi = Math.acos( MathUtils.clamp( y / this.radius, - 1, 1 ) );
46131
46132		}
46133
46134		return this;
46135
46136	}
46137
46138} );
46139
46140/**
46141 * @author Mugen87 / https://github.com/Mugen87
46142 *
46143 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
46144 *
46145 */
46146
46147function Cylindrical( radius, theta, y ) {
46148
46149	this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane
46150	this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
46151	this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane
46152
46153	return this;
46154
46155}
46156
46157Object.assign( Cylindrical.prototype, {
46158
46159	set: function ( radius, theta, y ) {
46160
46161		this.radius = radius;
46162		this.theta = theta;
46163		this.y = y;
46164
46165		return this;
46166
46167	},
46168
46169	clone: function () {
46170
46171		return new this.constructor().copy( this );
46172
46173	},
46174
46175	copy: function ( other ) {
46176
46177		this.radius = other.radius;
46178		this.theta = other.theta;
46179		this.y = other.y;
46180
46181		return this;
46182
46183	},
46184
46185	setFromVector3: function ( v ) {
46186
46187		return this.setFromCartesianCoords( v.x, v.y, v.z );
46188
46189	},
46190
46191	setFromCartesianCoords: function ( x, y, z ) {
46192
46193		this.radius = Math.sqrt( x * x + z * z );
46194		this.theta = Math.atan2( x, z );
46195		this.y = y;
46196
46197		return this;
46198
46199	}
46200
46201} );
46202
46203/**
46204 * @author bhouston / http://clara.io
46205 */
46206
46207var _vector$7 = new Vector2();
46208
46209function Box2( min, max ) {
46210
46211	this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );
46212	this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );
46213
46214}
46215
46216Object.assign( Box2.prototype, {
46217
46218	set: function ( min, max ) {
46219
46220		this.min.copy( min );
46221		this.max.copy( max );
46222
46223		return this;
46224
46225	},
46226
46227	setFromPoints: function ( points ) {
46228
46229		this.makeEmpty();
46230
46231		for ( var i = 0, il = points.length; i < il; i ++ ) {
46232
46233			this.expandByPoint( points[ i ] );
46234
46235		}
46236
46237		return this;
46238
46239	},
46240
46241	setFromCenterAndSize: function ( center, size ) {
46242
46243		var halfSize = _vector$7.copy( size ).multiplyScalar( 0.5 );
46244		this.min.copy( center ).sub( halfSize );
46245		this.max.copy( center ).add( halfSize );
46246
46247		return this;
46248
46249	},
46250
46251	clone: function () {
46252
46253		return new this.constructor().copy( this );
46254
46255	},
46256
46257	copy: function ( box ) {
46258
46259		this.min.copy( box.min );
46260		this.max.copy( box.max );
46261
46262		return this;
46263
46264	},
46265
46266	makeEmpty: function () {
46267
46268		this.min.x = this.min.y = + Infinity;
46269		this.max.x = this.max.y = - Infinity;
46270
46271		return this;
46272
46273	},
46274
46275	isEmpty: function () {
46276
46277		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
46278
46279		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
46280
46281	},
46282
46283	getCenter: function ( target ) {
46284
46285		if ( target === undefined ) {
46286
46287			console.warn( 'THREE.Box2: .getCenter() target is now required' );
46288			target = new Vector2();
46289
46290		}
46291
46292		return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
46293
46294	},
46295
46296	getSize: function ( target ) {
46297
46298		if ( target === undefined ) {
46299
46300			console.warn( 'THREE.Box2: .getSize() target is now required' );
46301			target = new Vector2();
46302
46303		}
46304
46305		return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
46306
46307	},
46308
46309	expandByPoint: function ( point ) {
46310
46311		this.min.min( point );
46312		this.max.max( point );
46313
46314		return this;
46315
46316	},
46317
46318	expandByVector: function ( vector ) {
46319
46320		this.min.sub( vector );
46321		this.max.add( vector );
46322
46323		return this;
46324
46325	},
46326
46327	expandByScalar: function ( scalar ) {
46328
46329		this.min.addScalar( - scalar );
46330		this.max.addScalar( scalar );
46331
46332		return this;
46333
46334	},
46335
46336	containsPoint: function ( point ) {
46337
46338		return point.x < this.min.x || point.x > this.max.x ||
46339			point.y < this.min.y || point.y > this.max.y ? false : true;
46340
46341	},
46342
46343	containsBox: function ( box ) {
46344
46345		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
46346			this.min.y <= box.min.y && box.max.y <= this.max.y;
46347
46348	},
46349
46350	getParameter: function ( point, target ) {
46351
46352		// This can potentially have a divide by zero if the box
46353		// has a size dimension of 0.
46354
46355		if ( target === undefined ) {
46356
46357			console.warn( 'THREE.Box2: .getParameter() target is now required' );
46358			target = new Vector2();
46359
46360		}
46361
46362		return target.set(
46363			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
46364			( point.y - this.min.y ) / ( this.max.y - this.min.y )
46365		);
46366
46367	},
46368
46369	intersectsBox: function ( box ) {
46370
46371		// using 4 splitting planes to rule out intersections
46372
46373		return box.max.x < this.min.x || box.min.x > this.max.x ||
46374			box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
46375
46376	},
46377
46378	clampPoint: function ( point, target ) {
46379
46380		if ( target === undefined ) {
46381
46382			console.warn( 'THREE.Box2: .clampPoint() target is now required' );
46383			target = new Vector2();
46384
46385		}
46386
46387		return target.copy( point ).clamp( this.min, this.max );
46388
46389	},
46390
46391	distanceToPoint: function ( point ) {
46392
46393		var clampedPoint = _vector$7.copy( point ).clamp( this.min, this.max );
46394		return clampedPoint.sub( point ).length();
46395
46396	},
46397
46398	intersect: function ( box ) {
46399
46400		this.min.max( box.min );
46401		this.max.min( box.max );
46402
46403		return this;
46404
46405	},
46406
46407	union: function ( box ) {
46408
46409		this.min.min( box.min );
46410		this.max.max( box.max );
46411
46412		return this;
46413
46414	},
46415
46416	translate: function ( offset ) {
46417
46418		this.min.add( offset );
46419		this.max.add( offset );
46420
46421		return this;
46422
46423	},
46424
46425	equals: function ( box ) {
46426
46427		return box.min.equals( this.min ) && box.max.equals( this.max );
46428
46429	}
46430
46431} );
46432
46433/**
46434 * @author bhouston / http://clara.io
46435 */
46436
46437var _startP = new Vector3();
46438var _startEnd = new Vector3();
46439
46440function Line3( start, end ) {
46441
46442	this.start = ( start !== undefined ) ? start : new Vector3();
46443	this.end = ( end !== undefined ) ? end : new Vector3();
46444
46445}
46446
46447Object.assign( Line3.prototype, {
46448
46449	set: function ( start, end ) {
46450
46451		this.start.copy( start );
46452		this.end.copy( end );
46453
46454		return this;
46455
46456	},
46457
46458	clone: function () {
46459
46460		return new this.constructor().copy( this );
46461
46462	},
46463
46464	copy: function ( line ) {
46465
46466		this.start.copy( line.start );
46467		this.end.copy( line.end );
46468
46469		return this;
46470
46471	},
46472
46473	getCenter: function ( target ) {
46474
46475		if ( target === undefined ) {
46476
46477			console.warn( 'THREE.Line3: .getCenter() target is now required' );
46478			target = new Vector3();
46479
46480		}
46481
46482		return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
46483
46484	},
46485
46486	delta: function ( target ) {
46487
46488		if ( target === undefined ) {
46489
46490			console.warn( 'THREE.Line3: .delta() target is now required' );
46491			target = new Vector3();
46492
46493		}
46494
46495		return target.subVectors( this.end, this.start );
46496
46497	},
46498
46499	distanceSq: function () {
46500
46501		return this.start.distanceToSquared( this.end );
46502
46503	},
46504
46505	distance: function () {
46506
46507		return this.start.distanceTo( this.end );
46508
46509	},
46510
46511	at: function ( t, target ) {
46512
46513		if ( target === undefined ) {
46514
46515			console.warn( 'THREE.Line3: .at() target is now required' );
46516			target = new Vector3();
46517
46518		}
46519
46520		return this.delta( target ).multiplyScalar( t ).add( this.start );
46521
46522	},
46523
46524	closestPointToPointParameter: function ( point, clampToLine ) {
46525
46526		_startP.subVectors( point, this.start );
46527		_startEnd.subVectors( this.end, this.start );
46528
46529		var startEnd2 = _startEnd.dot( _startEnd );
46530		var startEnd_startP = _startEnd.dot( _startP );
46531
46532		var t = startEnd_startP / startEnd2;
46533
46534		if ( clampToLine ) {
46535
46536			t = MathUtils.clamp( t, 0, 1 );
46537
46538		}
46539
46540		return t;
46541
46542	},
46543
46544	closestPointToPoint: function ( point, clampToLine, target ) {
46545
46546		var t = this.closestPointToPointParameter( point, clampToLine );
46547
46548		if ( target === undefined ) {
46549
46550			console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );
46551			target = new Vector3();
46552
46553		}
46554
46555		return this.delta( target ).multiplyScalar( t ).add( this.start );
46556
46557	},
46558
46559	applyMatrix4: function ( matrix ) {
46560
46561		this.start.applyMatrix4( matrix );
46562		this.end.applyMatrix4( matrix );
46563
46564		return this;
46565
46566	},
46567
46568	equals: function ( line ) {
46569
46570		return line.start.equals( this.start ) && line.end.equals( this.end );
46571
46572	}
46573
46574} );
46575
46576/**
46577 * @author alteredq / http://alteredqualia.com/
46578 */
46579
46580function ImmediateRenderObject( material ) {
46581
46582	Object3D.call( this );
46583
46584	this.material = material;
46585	this.render = function ( /* renderCallback */ ) {};
46586
46587}
46588
46589ImmediateRenderObject.prototype = Object.create( Object3D.prototype );
46590ImmediateRenderObject.prototype.constructor = ImmediateRenderObject;
46591
46592ImmediateRenderObject.prototype.isImmediateRenderObject = true;
46593
46594/**
46595 * @author alteredq / http://alteredqualia.com/
46596 * @author mrdoob / http://mrdoob.com/
46597 * @author WestLangley / http://github.com/WestLangley
46598 */
46599
46600var _vector$8 = new Vector3();
46601
46602function SpotLightHelper( light, color ) {
46603
46604	Object3D.call( this );
46605
46606	this.light = light;
46607	this.light.updateMatrixWorld();
46608
46609	this.matrix = light.matrixWorld;
46610	this.matrixAutoUpdate = false;
46611
46612	this.color = color;
46613
46614	var geometry = new BufferGeometry();
46615
46616	var positions = [
46617		0, 0, 0, 	0, 0, 1,
46618		0, 0, 0, 	1, 0, 1,
46619		0, 0, 0,	- 1, 0, 1,
46620		0, 0, 0, 	0, 1, 1,
46621		0, 0, 0, 	0, - 1, 1
46622	];
46623
46624	for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
46625
46626		var p1 = ( i / l ) * Math.PI * 2;
46627		var p2 = ( j / l ) * Math.PI * 2;
46628
46629		positions.push(
46630			Math.cos( p1 ), Math.sin( p1 ), 1,
46631			Math.cos( p2 ), Math.sin( p2 ), 1
46632		);
46633
46634	}
46635
46636	geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
46637
46638	var material = new LineBasicMaterial( { fog: false, toneMapped: false } );
46639
46640	this.cone = new LineSegments( geometry, material );
46641	this.add( this.cone );
46642
46643	this.update();
46644
46645}
46646
46647SpotLightHelper.prototype = Object.create( Object3D.prototype );
46648SpotLightHelper.prototype.constructor = SpotLightHelper;
46649
46650SpotLightHelper.prototype.dispose = function () {
46651
46652	this.cone.geometry.dispose();
46653	this.cone.material.dispose();
46654
46655};
46656
46657SpotLightHelper.prototype.update = function () {
46658
46659	this.light.updateMatrixWorld();
46660
46661	var coneLength = this.light.distance ? this.light.distance : 1000;
46662	var coneWidth = coneLength * Math.tan( this.light.angle );
46663
46664	this.cone.scale.set( coneWidth, coneWidth, coneLength );
46665
46666	_vector$8.setFromMatrixPosition( this.light.target.matrixWorld );
46667
46668	this.cone.lookAt( _vector$8 );
46669
46670	if ( this.color !== undefined ) {
46671
46672		this.cone.material.color.set( this.color );
46673
46674	} else {
46675
46676		this.cone.material.color.copy( this.light.color );
46677
46678	}
46679
46680};
46681
46682/**
46683 * @author Sean Griffin / http://twitter.com/sgrif
46684 * @author Michael Guerrero / http://realitymeltdown.com
46685 * @author mrdoob / http://mrdoob.com/
46686 * @author ikerr / http://verold.com
46687 * @author Mugen87 / https://github.com/Mugen87
46688 */
46689
46690var _vector$9 = new Vector3();
46691var _boneMatrix = new Matrix4();
46692var _matrixWorldInv = new Matrix4();
46693
46694function getBoneList( object ) {
46695
46696	var boneList = [];
46697
46698	if ( object && object.isBone ) {
46699
46700		boneList.push( object );
46701
46702	}
46703
46704	for ( var i = 0; i < object.children.length; i ++ ) {
46705
46706		boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
46707
46708	}
46709
46710	return boneList;
46711
46712}
46713
46714function SkeletonHelper( object ) {
46715
46716	var bones = getBoneList( object );
46717
46718	var geometry = new BufferGeometry();
46719
46720	var vertices = [];
46721	var colors = [];
46722
46723	var color1 = new Color( 0, 0, 1 );
46724	var color2 = new Color( 0, 1, 0 );
46725
46726	for ( var i = 0; i < bones.length; i ++ ) {
46727
46728		var bone = bones[ i ];
46729
46730		if ( bone.parent && bone.parent.isBone ) {
46731
46732			vertices.push( 0, 0, 0 );
46733			vertices.push( 0, 0, 0 );
46734			colors.push( color1.r, color1.g, color1.b );
46735			colors.push( color2.r, color2.g, color2.b );
46736
46737		}
46738
46739	}
46740
46741	geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
46742	geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
46743
46744	var material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
46745
46746	LineSegments.call( this, geometry, material );
46747
46748	this.type = 'SkeletonHelper';
46749
46750	this.root = object;
46751	this.bones = bones;
46752
46753	this.matrix = object.matrixWorld;
46754	this.matrixAutoUpdate = false;
46755
46756}
46757
46758SkeletonHelper.prototype = Object.create( LineSegments.prototype );
46759SkeletonHelper.prototype.constructor = SkeletonHelper;
46760
46761SkeletonHelper.prototype.isSkeletonHelper = true;
46762
46763SkeletonHelper.prototype.updateMatrixWorld = function ( force ) {
46764
46765	var bones = this.bones;
46766
46767	var geometry = this.geometry;
46768	var position = geometry.getAttribute( 'position' );
46769
46770	_matrixWorldInv.getInverse( this.root.matrixWorld );
46771
46772	for ( var i = 0, j = 0; i < bones.length; i ++ ) {
46773
46774		var bone = bones[ i ];
46775
46776		if ( bone.parent && bone.parent.isBone ) {
46777
46778			_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
46779			_vector$9.setFromMatrixPosition( _boneMatrix );
46780			position.setXYZ( j, _vector$9.x, _vector$9.y, _vector$9.z );
46781
46782			_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
46783			_vector$9.setFromMatrixPosition( _boneMatrix );
46784			position.setXYZ( j + 1, _vector$9.x, _vector$9.y, _vector$9.z );
46785
46786			j += 2;
46787
46788		}
46789
46790	}
46791
46792	geometry.getAttribute( 'position' ).needsUpdate = true;
46793
46794	Object3D.prototype.updateMatrixWorld.call( this, force );
46795
46796};
46797
46798/**
46799 * @author alteredq / http://alteredqualia.com/
46800 * @author mrdoob / http://mrdoob.com/
46801 */
46802
46803function PointLightHelper( light, sphereSize, color ) {
46804
46805	this.light = light;
46806	this.light.updateMatrixWorld();
46807
46808	this.color = color;
46809
46810	var geometry = new SphereBufferGeometry( sphereSize, 4, 2 );
46811	var material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
46812
46813	Mesh.call( this, geometry, material );
46814
46815	this.type = 'PointLightHelper';
46816
46817	this.matrix = this.light.matrixWorld;
46818	this.matrixAutoUpdate = false;
46819
46820	this.update();
46821
46822
46823	/*
46824	var distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );
46825	var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
46826
46827	this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
46828	this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
46829
46830	var d = light.distance;
46831
46832	if ( d === 0.0 ) {
46833
46834		this.lightDistance.visible = false;
46835
46836	} else {
46837
46838		this.lightDistance.scale.set( d, d, d );
46839
46840	}
46841
46842	this.add( this.lightDistance );
46843	*/
46844
46845}
46846
46847PointLightHelper.prototype = Object.create( Mesh.prototype );
46848PointLightHelper.prototype.constructor = PointLightHelper;
46849
46850PointLightHelper.prototype.dispose = function () {
46851
46852	this.geometry.dispose();
46853	this.material.dispose();
46854
46855};
46856
46857PointLightHelper.prototype.update = function () {
46858
46859	if ( this.color !== undefined ) {
46860
46861		this.material.color.set( this.color );
46862
46863	} else {
46864
46865		this.material.color.copy( this.light.color );
46866
46867	}
46868
46869	/*
46870	var d = this.light.distance;
46871
46872	if ( d === 0.0 ) {
46873
46874		this.lightDistance.visible = false;
46875
46876	} else {
46877
46878		this.lightDistance.visible = true;
46879		this.lightDistance.scale.set( d, d, d );
46880
46881	}
46882	*/
46883
46884};
46885
46886/**
46887 * @author alteredq / http://alteredqualia.com/
46888 * @author mrdoob / http://mrdoob.com/
46889 * @author Mugen87 / https://github.com/Mugen87
46890 */
46891
46892var _vector$a = new Vector3();
46893var _color1 = new Color();
46894var _color2 = new Color();
46895
46896function HemisphereLightHelper( light, size, color ) {
46897
46898	Object3D.call( this );
46899
46900	this.light = light;
46901	this.light.updateMatrixWorld();
46902
46903	this.matrix = light.matrixWorld;
46904	this.matrixAutoUpdate = false;
46905
46906	this.color = color;
46907
46908	var geometry = new OctahedronBufferGeometry( size );
46909	geometry.rotateY( Math.PI * 0.5 );
46910
46911	this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
46912	if ( this.color === undefined ) this.material.vertexColors = true;
46913
46914	var position = geometry.getAttribute( 'position' );
46915	var colors = new Float32Array( position.count * 3 );
46916
46917	geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
46918
46919	this.add( new Mesh( geometry, this.material ) );
46920
46921	this.update();
46922
46923}
46924
46925HemisphereLightHelper.prototype = Object.create( Object3D.prototype );
46926HemisphereLightHelper.prototype.constructor = HemisphereLightHelper;
46927
46928HemisphereLightHelper.prototype.dispose = function () {
46929
46930	this.children[ 0 ].geometry.dispose();
46931	this.children[ 0 ].material.dispose();
46932
46933};
46934
46935HemisphereLightHelper.prototype.update = function () {
46936
46937	var mesh = this.children[ 0 ];
46938
46939	if ( this.color !== undefined ) {
46940
46941		this.material.color.set( this.color );
46942
46943	} else {
46944
46945		var colors = mesh.geometry.getAttribute( 'color' );
46946
46947		_color1.copy( this.light.color );
46948		_color2.copy( this.light.groundColor );
46949
46950		for ( var i = 0, l = colors.count; i < l; i ++ ) {
46951
46952			var color = ( i < ( l / 2 ) ) ? _color1 : _color2;
46953
46954			colors.setXYZ( i, color.r, color.g, color.b );
46955
46956		}
46957
46958		colors.needsUpdate = true;
46959
46960	}
46961
46962	mesh.lookAt( _vector$a.setFromMatrixPosition( this.light.matrixWorld ).negate() );
46963
46964};
46965
46966/**
46967 * @author mrdoob / http://mrdoob.com/
46968 */
46969
46970function GridHelper( size, divisions, color1, color2 ) {
46971
46972	size = size || 10;
46973	divisions = divisions || 10;
46974	color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
46975	color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
46976
46977	var center = divisions / 2;
46978	var step = size / divisions;
46979	var halfSize = size / 2;
46980
46981	var vertices = [], colors = [];
46982
46983	for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
46984
46985		vertices.push( - halfSize, 0, k, halfSize, 0, k );
46986		vertices.push( k, 0, - halfSize, k, 0, halfSize );
46987
46988		var color = i === center ? color1 : color2;
46989
46990		color.toArray( colors, j ); j += 3;
46991		color.toArray( colors, j ); j += 3;
46992		color.toArray( colors, j ); j += 3;
46993		color.toArray( colors, j ); j += 3;
46994
46995	}
46996
46997	var geometry = new BufferGeometry();
46998	geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
46999	geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47000
47001	var material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
47002
47003	LineSegments.call( this, geometry, material );
47004
47005	this.type = 'GridHelper';
47006
47007}
47008
47009GridHelper.prototype = Object.assign( Object.create( LineSegments.prototype ), {
47010
47011	constructor: GridHelper,
47012
47013	copy: function ( source ) {
47014
47015		LineSegments.prototype.copy.call( this, source );
47016
47017		this.geometry.copy( source.geometry );
47018		this.material.copy( source.material );
47019
47020		return this;
47021
47022	},
47023
47024	clone: function () {
47025
47026		return new this.constructor().copy( this );
47027
47028	}
47029
47030} );
47031
47032/**
47033 * @author mrdoob / http://mrdoob.com/
47034 * @author Mugen87 / http://github.com/Mugen87
47035 * @author Hectate / http://www.github.com/Hectate
47036 */
47037
47038function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {
47039
47040	radius = radius || 10;
47041	radials = radials || 16;
47042	circles = circles || 8;
47043	divisions = divisions || 64;
47044	color1 = new Color( color1 !== undefined ? color1 : 0x444444 );
47045	color2 = new Color( color2 !== undefined ? color2 : 0x888888 );
47046
47047	var vertices = [];
47048	var colors = [];
47049
47050	var x, z;
47051	var v, i, j, r, color;
47052
47053	// create the radials
47054
47055	for ( i = 0; i <= radials; i ++ ) {
47056
47057		v = ( i / radials ) * ( Math.PI * 2 );
47058
47059		x = Math.sin( v ) * radius;
47060		z = Math.cos( v ) * radius;
47061
47062		vertices.push( 0, 0, 0 );
47063		vertices.push( x, 0, z );
47064
47065		color = ( i & 1 ) ? color1 : color2;
47066
47067		colors.push( color.r, color.g, color.b );
47068		colors.push( color.r, color.g, color.b );
47069
47070	}
47071
47072	// create the circles
47073
47074	for ( i = 0; i <= circles; i ++ ) {
47075
47076		color = ( i & 1 ) ? color1 : color2;
47077
47078		r = radius - ( radius / circles * i );
47079
47080		for ( j = 0; j < divisions; j ++ ) {
47081
47082			// first vertex
47083
47084			v = ( j / divisions ) * ( Math.PI * 2 );
47085
47086			x = Math.sin( v ) * r;
47087			z = Math.cos( v ) * r;
47088
47089			vertices.push( x, 0, z );
47090			colors.push( color.r, color.g, color.b );
47091
47092			// second vertex
47093
47094			v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
47095
47096			x = Math.sin( v ) * r;
47097			z = Math.cos( v ) * r;
47098
47099			vertices.push( x, 0, z );
47100			colors.push( color.r, color.g, color.b );
47101
47102		}
47103
47104	}
47105
47106	var geometry = new BufferGeometry();
47107	geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
47108	geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47109
47110	var material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
47111
47112	LineSegments.call( this, geometry, material );
47113
47114	this.type = 'PolarGridHelper';
47115
47116}
47117
47118PolarGridHelper.prototype = Object.create( LineSegments.prototype );
47119PolarGridHelper.prototype.constructor = PolarGridHelper;
47120
47121/**
47122 * @author alteredq / http://alteredqualia.com/
47123 * @author mrdoob / http://mrdoob.com/
47124 * @author WestLangley / http://github.com/WestLangley
47125 */
47126
47127var _v1$5 = new Vector3();
47128var _v2$3 = new Vector3();
47129var _v3$1 = new Vector3();
47130
47131function DirectionalLightHelper( light, size, color ) {
47132
47133	Object3D.call( this );
47134
47135	this.light = light;
47136	this.light.updateMatrixWorld();
47137
47138	this.matrix = light.matrixWorld;
47139	this.matrixAutoUpdate = false;
47140
47141	this.color = color;
47142
47143	if ( size === undefined ) size = 1;
47144
47145	var geometry = new BufferGeometry();
47146	geometry.setAttribute( 'position', new Float32BufferAttribute( [
47147		- size, size, 0,
47148		size, size, 0,
47149		size, - size, 0,
47150		- size, - size, 0,
47151		- size, size, 0
47152	], 3 ) );
47153
47154	var material = new LineBasicMaterial( { fog: false, toneMapped: false } );
47155
47156	this.lightPlane = new Line( geometry, material );
47157	this.add( this.lightPlane );
47158
47159	geometry = new BufferGeometry();
47160	geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
47161
47162	this.targetLine = new Line( geometry, material );
47163	this.add( this.targetLine );
47164
47165	this.update();
47166
47167}
47168
47169DirectionalLightHelper.prototype = Object.create( Object3D.prototype );
47170DirectionalLightHelper.prototype.constructor = DirectionalLightHelper;
47171
47172DirectionalLightHelper.prototype.dispose = function () {
47173
47174	this.lightPlane.geometry.dispose();
47175	this.lightPlane.material.dispose();
47176	this.targetLine.geometry.dispose();
47177	this.targetLine.material.dispose();
47178
47179};
47180
47181DirectionalLightHelper.prototype.update = function () {
47182
47183	_v1$5.setFromMatrixPosition( this.light.matrixWorld );
47184	_v2$3.setFromMatrixPosition( this.light.target.matrixWorld );
47185	_v3$1.subVectors( _v2$3, _v1$5 );
47186
47187	this.lightPlane.lookAt( _v2$3 );
47188
47189	if ( this.color !== undefined ) {
47190
47191		this.lightPlane.material.color.set( this.color );
47192		this.targetLine.material.color.set( this.color );
47193
47194	} else {
47195
47196		this.lightPlane.material.color.copy( this.light.color );
47197		this.targetLine.material.color.copy( this.light.color );
47198
47199	}
47200
47201	this.targetLine.lookAt( _v2$3 );
47202	this.targetLine.scale.z = _v3$1.length();
47203
47204};
47205
47206/**
47207 * @author alteredq / http://alteredqualia.com/
47208 * @author Mugen87 / https://github.com/Mugen87
47209 *
47210 *	- shows frustum, line of sight and up of the camera
47211 *	- suitable for fast updates
47212 * 	- based on frustum visualization in lightgl.js shadowmap example
47213 *		http://evanw.github.com/lightgl.js/tests/shadowmap.html
47214 */
47215
47216var _vector$b = new Vector3();
47217var _camera = new Camera();
47218
47219function CameraHelper( camera ) {
47220
47221	var geometry = new BufferGeometry();
47222	var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
47223
47224	var vertices = [];
47225	var colors = [];
47226
47227	var pointMap = {};
47228
47229	// colors
47230
47231	var colorFrustum = new Color( 0xffaa00 );
47232	var colorCone = new Color( 0xff0000 );
47233	var colorUp = new Color( 0x00aaff );
47234	var colorTarget = new Color( 0xffffff );
47235	var colorCross = new Color( 0x333333 );
47236
47237	// near
47238
47239	addLine( 'n1', 'n2', colorFrustum );
47240	addLine( 'n2', 'n4', colorFrustum );
47241	addLine( 'n4', 'n3', colorFrustum );
47242	addLine( 'n3', 'n1', colorFrustum );
47243
47244	// far
47245
47246	addLine( 'f1', 'f2', colorFrustum );
47247	addLine( 'f2', 'f4', colorFrustum );
47248	addLine( 'f4', 'f3', colorFrustum );
47249	addLine( 'f3', 'f1', colorFrustum );
47250
47251	// sides
47252
47253	addLine( 'n1', 'f1', colorFrustum );
47254	addLine( 'n2', 'f2', colorFrustum );
47255	addLine( 'n3', 'f3', colorFrustum );
47256	addLine( 'n4', 'f4', colorFrustum );
47257
47258	// cone
47259
47260	addLine( 'p', 'n1', colorCone );
47261	addLine( 'p', 'n2', colorCone );
47262	addLine( 'p', 'n3', colorCone );
47263	addLine( 'p', 'n4', colorCone );
47264
47265	// up
47266
47267	addLine( 'u1', 'u2', colorUp );
47268	addLine( 'u2', 'u3', colorUp );
47269	addLine( 'u3', 'u1', colorUp );
47270
47271	// target
47272
47273	addLine( 'c', 't', colorTarget );
47274	addLine( 'p', 'c', colorCross );
47275
47276	// cross
47277
47278	addLine( 'cn1', 'cn2', colorCross );
47279	addLine( 'cn3', 'cn4', colorCross );
47280
47281	addLine( 'cf1', 'cf2', colorCross );
47282	addLine( 'cf3', 'cf4', colorCross );
47283
47284	function addLine( a, b, color ) {
47285
47286		addPoint( a, color );
47287		addPoint( b, color );
47288
47289	}
47290
47291	function addPoint( id, color ) {
47292
47293		vertices.push( 0, 0, 0 );
47294		colors.push( color.r, color.g, color.b );
47295
47296		if ( pointMap[ id ] === undefined ) {
47297
47298			pointMap[ id ] = [];
47299
47300		}
47301
47302		pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
47303
47304	}
47305
47306	geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
47307	geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47308
47309	LineSegments.call( this, geometry, material );
47310
47311	this.type = 'CameraHelper';
47312
47313	this.camera = camera;
47314	if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
47315
47316	this.matrix = camera.matrixWorld;
47317	this.matrixAutoUpdate = false;
47318
47319	this.pointMap = pointMap;
47320
47321	this.update();
47322
47323}
47324
47325CameraHelper.prototype = Object.create( LineSegments.prototype );
47326CameraHelper.prototype.constructor = CameraHelper;
47327
47328CameraHelper.prototype.update = function () {
47329
47330	var geometry = this.geometry;
47331	var pointMap = this.pointMap;
47332
47333	var w = 1, h = 1;
47334
47335	// we need just camera projection matrix inverse
47336	// world matrix must be identity
47337
47338	_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
47339
47340	// center / target
47341
47342	setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
47343	setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
47344
47345	// near
47346
47347	setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
47348	setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
47349	setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
47350	setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
47351
47352	// far
47353
47354	setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
47355	setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
47356	setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
47357	setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
47358
47359	// up
47360
47361	setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
47362	setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
47363	setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
47364
47365	// cross
47366
47367	setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
47368	setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
47369	setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
47370	setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
47371
47372	setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
47373	setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
47374	setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
47375	setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
47376
47377	geometry.getAttribute( 'position' ).needsUpdate = true;
47378
47379};
47380
47381function setPoint( point, pointMap, geometry, camera, x, y, z ) {
47382
47383	_vector$b.set( x, y, z ).unproject( camera );
47384
47385	var points = pointMap[ point ];
47386
47387	if ( points !== undefined ) {
47388
47389		var position = geometry.getAttribute( 'position' );
47390
47391		for ( var i = 0, l = points.length; i < l; i ++ ) {
47392
47393			position.setXYZ( points[ i ], _vector$b.x, _vector$b.y, _vector$b.z );
47394
47395		}
47396
47397	}
47398
47399}
47400
47401/**
47402 * @author mrdoob / http://mrdoob.com/
47403 * @author Mugen87 / http://github.com/Mugen87
47404 */
47405
47406var _box$3 = new Box3();
47407
47408function BoxHelper( object, color ) {
47409
47410	this.object = object;
47411
47412	if ( color === undefined ) color = 0xffff00;
47413
47414	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 ] );
47415	var positions = new Float32Array( 8 * 3 );
47416
47417	var geometry = new BufferGeometry();
47418	geometry.setIndex( new BufferAttribute( indices, 1 ) );
47419	geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
47420
47421	LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
47422
47423	this.type = 'BoxHelper';
47424
47425	this.matrixAutoUpdate = false;
47426
47427	this.update();
47428
47429}
47430
47431BoxHelper.prototype = Object.create( LineSegments.prototype );
47432BoxHelper.prototype.constructor = BoxHelper;
47433
47434BoxHelper.prototype.update = function ( object ) {
47435
47436	if ( object !== undefined ) {
47437
47438		console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
47439
47440	}
47441
47442	if ( this.object !== undefined ) {
47443
47444		_box$3.setFromObject( this.object );
47445
47446	}
47447
47448	if ( _box$3.isEmpty() ) return;
47449
47450	var min = _box$3.min;
47451	var max = _box$3.max;
47452
47453	/*
47454	  5____4
47455	1/___0/|
47456	| 6__|_7
47457	2/___3/
47458
47459	0: max.x, max.y, max.z
47460	1: min.x, max.y, max.z
47461	2: min.x, min.y, max.z
47462	3: max.x, min.y, max.z
47463	4: max.x, max.y, min.z
47464	5: min.x, max.y, min.z
47465	6: min.x, min.y, min.z
47466	7: max.x, min.y, min.z
47467	*/
47468
47469	var position = this.geometry.attributes.position;
47470	var array = position.array;
47471
47472	array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
47473	array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
47474	array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
47475	array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
47476	array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
47477	array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
47478	array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
47479	array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
47480
47481	position.needsUpdate = true;
47482
47483	this.geometry.computeBoundingSphere();
47484
47485
47486};
47487
47488BoxHelper.prototype.setFromObject = function ( object ) {
47489
47490	this.object = object;
47491	this.update();
47492
47493	return this;
47494
47495};
47496
47497BoxHelper.prototype.copy = function ( source ) {
47498
47499	LineSegments.prototype.copy.call( this, source );
47500
47501	this.object = source.object;
47502
47503	return this;
47504
47505};
47506
47507BoxHelper.prototype.clone = function () {
47508
47509	return new this.constructor().copy( this );
47510
47511};
47512
47513/**
47514 * @author WestLangley / http://github.com/WestLangley
47515 */
47516
47517function Box3Helper( box, color ) {
47518
47519	this.type = 'Box3Helper';
47520
47521	this.box = box;
47522
47523	color = color || 0xffff00;
47524
47525	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 ] );
47526
47527	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 ];
47528
47529	var geometry = new BufferGeometry();
47530
47531	geometry.setIndex( new BufferAttribute( indices, 1 ) );
47532
47533	geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
47534
47535	LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
47536
47537	this.type = 'Box3Helper';
47538
47539	this.geometry.computeBoundingSphere();
47540
47541}
47542
47543Box3Helper.prototype = Object.create( LineSegments.prototype );
47544Box3Helper.prototype.constructor = Box3Helper;
47545
47546Box3Helper.prototype.updateMatrixWorld = function ( force ) {
47547
47548	var box = this.box;
47549
47550	if ( box.isEmpty() ) return;
47551
47552	box.getCenter( this.position );
47553
47554	box.getSize( this.scale );
47555
47556	this.scale.multiplyScalar( 0.5 );
47557
47558	Object3D.prototype.updateMatrixWorld.call( this, force );
47559
47560};
47561
47562/**
47563 * @author WestLangley / http://github.com/WestLangley
47564 */
47565
47566function PlaneHelper( plane, size, hex ) {
47567
47568	this.plane = plane;
47569
47570	this.size = ( size === undefined ) ? 1 : size;
47571
47572	var color = ( hex !== undefined ) ? hex : 0xffff00;
47573
47574	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 ];
47575
47576	var geometry = new BufferGeometry();
47577	geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
47578	geometry.computeBoundingSphere();
47579
47580	Line.call( this, geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
47581
47582	this.type = 'PlaneHelper';
47583
47584	//
47585
47586	var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];
47587
47588	var geometry2 = new BufferGeometry();
47589	geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
47590	geometry2.computeBoundingSphere();
47591
47592	this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
47593
47594}
47595
47596PlaneHelper.prototype = Object.create( Line.prototype );
47597PlaneHelper.prototype.constructor = PlaneHelper;
47598
47599PlaneHelper.prototype.updateMatrixWorld = function ( force ) {
47600
47601	var scale = - this.plane.constant;
47602
47603	if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter
47604
47605	this.scale.set( 0.5 * this.size, 0.5 * this.size, scale );
47606
47607	this.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here
47608
47609	this.lookAt( this.plane.normal );
47610
47611	Object3D.prototype.updateMatrixWorld.call( this, force );
47612
47613};
47614
47615/**
47616 * @author WestLangley / http://github.com/WestLangley
47617 * @author zz85 / http://github.com/zz85
47618 * @author bhouston / http://clara.io
47619 *
47620 * Creates an arrow for visualizing directions
47621 *
47622 * Parameters:
47623 *  dir - Vector3
47624 *  origin - Vector3
47625 *  length - Number
47626 *  color - color in hex value
47627 *  headLength - Number
47628 *  headWidth - Number
47629 */
47630
47631var _axis = new Vector3();
47632var _lineGeometry, _coneGeometry;
47633
47634function ArrowHelper( dir, origin, length, color, headLength, headWidth ) {
47635
47636	// dir is assumed to be normalized
47637
47638	Object3D.call( this );
47639
47640	this.type = 'ArrowHelper';
47641
47642	if ( dir === undefined ) dir = new Vector3( 0, 0, 1 );
47643	if ( origin === undefined ) origin = new Vector3( 0, 0, 0 );
47644	if ( length === undefined ) length = 1;
47645	if ( color === undefined ) color = 0xffff00;
47646	if ( headLength === undefined ) headLength = 0.2 * length;
47647	if ( headWidth === undefined ) headWidth = 0.2 * headLength;
47648
47649	if ( _lineGeometry === undefined ) {
47650
47651		_lineGeometry = new BufferGeometry();
47652		_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
47653
47654		_coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );
47655		_coneGeometry.translate( 0, - 0.5, 0 );
47656
47657	}
47658
47659	this.position.copy( origin );
47660
47661	this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
47662	this.line.matrixAutoUpdate = false;
47663	this.add( this.line );
47664
47665	this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
47666	this.cone.matrixAutoUpdate = false;
47667	this.add( this.cone );
47668
47669	this.setDirection( dir );
47670	this.setLength( length, headLength, headWidth );
47671
47672}
47673
47674ArrowHelper.prototype = Object.create( Object3D.prototype );
47675ArrowHelper.prototype.constructor = ArrowHelper;
47676
47677ArrowHelper.prototype.setDirection = function ( dir ) {
47678
47679	// dir is assumed to be normalized
47680
47681	if ( dir.y > 0.99999 ) {
47682
47683		this.quaternion.set( 0, 0, 0, 1 );
47684
47685	} else if ( dir.y < - 0.99999 ) {
47686
47687		this.quaternion.set( 1, 0, 0, 0 );
47688
47689	} else {
47690
47691		_axis.set( dir.z, 0, - dir.x ).normalize();
47692
47693		var radians = Math.acos( dir.y );
47694
47695		this.quaternion.setFromAxisAngle( _axis, radians );
47696
47697	}
47698
47699};
47700
47701ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
47702
47703	if ( headLength === undefined ) headLength = 0.2 * length;
47704	if ( headWidth === undefined ) headWidth = 0.2 * headLength;
47705
47706	this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
47707	this.line.updateMatrix();
47708
47709	this.cone.scale.set( headWidth, headLength, headWidth );
47710	this.cone.position.y = length;
47711	this.cone.updateMatrix();
47712
47713};
47714
47715ArrowHelper.prototype.setColor = function ( color ) {
47716
47717	this.line.material.color.set( color );
47718	this.cone.material.color.set( color );
47719
47720};
47721
47722ArrowHelper.prototype.copy = function ( source ) {
47723
47724	Object3D.prototype.copy.call( this, source, false );
47725
47726	this.line.copy( source.line );
47727	this.cone.copy( source.cone );
47728
47729	return this;
47730
47731};
47732
47733ArrowHelper.prototype.clone = function () {
47734
47735	return new this.constructor().copy( this );
47736
47737};
47738
47739/**
47740 * @author sroucheray / http://sroucheray.org/
47741 * @author mrdoob / http://mrdoob.com/
47742 */
47743
47744function AxesHelper( size ) {
47745
47746	size = size || 1;
47747
47748	var vertices = [
47749		0, 0, 0,	size, 0, 0,
47750		0, 0, 0,	0, size, 0,
47751		0, 0, 0,	0, 0, size
47752	];
47753
47754	var colors = [
47755		1, 0, 0,	1, 0.6, 0,
47756		0, 1, 0,	0.6, 1, 0,
47757		0, 0, 1,	0, 0.6, 1
47758	];
47759
47760	var geometry = new BufferGeometry();
47761	geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
47762	geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
47763
47764	var material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
47765
47766	LineSegments.call( this, geometry, material );
47767
47768	this.type = 'AxesHelper';
47769
47770}
47771
47772AxesHelper.prototype = Object.create( LineSegments.prototype );
47773AxesHelper.prototype.constructor = AxesHelper;
47774
47775/**
47776 * @author Emmett Lalish / elalish
47777 *
47778 * This class generates a Prefiltered, Mipmapped Radiance Environment Map
47779 * (PMREM) from a cubeMap environment texture. This allows different levels of
47780 * blur to be quickly accessed based on material roughness. It is packed into a
47781 * special CubeUV format that allows us to perform custom interpolation so that
47782 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
47783 * chain, it only goes down to the LOD_MIN level (above), and then creates extra
47784 * even more filtered 'mips' at the same LOD_MIN resolution, associated with
47785 * higher roughness levels. In this way we maintain resolution to smoothly
47786 * interpolate diffuse lighting while limiting sampling computation.
47787 */
47788
47789var LOD_MIN = 4;
47790var LOD_MAX = 8;
47791var SIZE_MAX = Math.pow( 2, LOD_MAX );
47792
47793// The standard deviations (radians) associated with the extra mips. These are
47794// chosen to approximate a Trowbridge-Reitz distribution function times the
47795// geometric shadowing function. These sigma values squared must match the
47796// variance #defines in cube_uv_reflection_fragment.glsl.js.
47797var EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
47798
47799var TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
47800
47801// The maximum length of the blur for loop. Smaller sigmas will use fewer
47802// samples and exit early, but not recompile the shader.
47803var MAX_SAMPLES = 20;
47804
47805var ENCODINGS = {
47806	[ LinearEncoding ]: 0,
47807	[ sRGBEncoding ]: 1,
47808	[ RGBEEncoding ]: 2,
47809	[ RGBM7Encoding ]: 3,
47810	[ RGBM16Encoding ]: 4,
47811	[ RGBDEncoding ]: 5,
47812	[ GammaEncoding ]: 6
47813};
47814
47815var _flatCamera = new OrthographicCamera();
47816var { _lodPlanes, _sizeLods, _sigmas } = _createPlanes();
47817var _oldTarget = null;
47818
47819// Golden Ratio
47820var PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
47821var INV_PHI = 1 / PHI;
47822
47823// Vertices of a dodecahedron (except the opposites, which represent the
47824// same axis), used as axis directions evenly spread on a sphere.
47825var _axisDirections = [
47826	new Vector3( 1, 1, 1 ),
47827	new Vector3( - 1, 1, 1 ),
47828	new Vector3( 1, 1, - 1 ),
47829	new Vector3( - 1, 1, - 1 ),
47830	new Vector3( 0, PHI, INV_PHI ),
47831	new Vector3( 0, PHI, - INV_PHI ),
47832	new Vector3( INV_PHI, 0, PHI ),
47833	new Vector3( - INV_PHI, 0, PHI ),
47834	new Vector3( PHI, INV_PHI, 0 ),
47835	new Vector3( - PHI, INV_PHI, 0 ) ];
47836
47837function PMREMGenerator( renderer ) {
47838
47839	this._renderer = renderer;
47840	this._pingPongRenderTarget = null;
47841
47842	this._blurMaterial = _getBlurShader( MAX_SAMPLES );
47843	this._equirectShader = null;
47844	this._cubemapShader = null;
47845
47846	this._compileMaterial( this._blurMaterial );
47847
47848}
47849
47850PMREMGenerator.prototype = {
47851
47852	constructor: PMREMGenerator,
47853
47854	/**
47855	 * Generates a PMREM from a supplied Scene, which can be faster than using an
47856	 * image if networking bandwidth is low. Optional sigma specifies a blur radius
47857	 * in radians to be applied to the scene before PMREM generation. Optional near
47858	 * and far planes ensure the scene is rendered in its entirety (the cubeCamera
47859	 * is placed at the origin).
47860	 */
47861	fromScene: function ( scene, sigma = 0, near = 0.1, far = 100 ) {
47862
47863		_oldTarget = this._renderer.getRenderTarget();
47864		var cubeUVRenderTarget = this._allocateTargets();
47865
47866		this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
47867		if ( sigma > 0 ) {
47868
47869			this._blur( cubeUVRenderTarget, 0, 0, sigma );
47870
47871		}
47872
47873		this._applyPMREM( cubeUVRenderTarget );
47874		this._cleanup( cubeUVRenderTarget );
47875
47876		return cubeUVRenderTarget;
47877
47878	},
47879
47880	/**
47881	 * Generates a PMREM from an equirectangular texture, which can be either LDR
47882	 * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512),
47883	 * as this matches best with the 256 x 256 cubemap output.
47884	 */
47885	fromEquirectangular: function ( equirectangular ) {
47886
47887		equirectangular.magFilter = NearestFilter;
47888		equirectangular.minFilter = NearestFilter;
47889		equirectangular.generateMipmaps = false;
47890
47891		return this.fromCubemap( equirectangular );
47892
47893	},
47894
47895	/**
47896	 * Generates a PMREM from an cubemap texture, which can be either LDR
47897	 * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
47898	 * as this matches best with the 256 x 256 cubemap output.
47899	 */
47900	fromCubemap: function ( cubemap ) {
47901
47902		_oldTarget = this._renderer.getRenderTarget();
47903		var cubeUVRenderTarget = this._allocateTargets( cubemap );
47904		this._textureToCubeUV( cubemap, cubeUVRenderTarget );
47905		this._applyPMREM( cubeUVRenderTarget );
47906		this._cleanup( cubeUVRenderTarget );
47907
47908		return cubeUVRenderTarget;
47909
47910	},
47911
47912	/**
47913	 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
47914	 * your texture's network fetch for increased concurrency.
47915	 */
47916	compileCubemapShader: function () {
47917
47918		if ( this._cubemapShader === null ) {
47919
47920			this._cubemapShader = _getCubemapShader();
47921			this._compileMaterial( this._cubemapShader );
47922
47923		}
47924
47925	},
47926
47927	/**
47928	 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
47929	 * your texture's network fetch for increased concurrency.
47930	 */
47931	compileEquirectangularShader: function () {
47932
47933		if ( this._equirectShader === null ) {
47934
47935			this._equirectShader = _getEquirectShader();
47936			this._compileMaterial( this._equirectShader );
47937
47938		}
47939
47940	},
47941
47942	/**
47943	 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
47944	 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
47945	 * one of them will cause any others to also become unusable.
47946	 */
47947	dispose: function () {
47948
47949		this._blurMaterial.dispose();
47950
47951		if ( this._cubemapShader !== null ) this._cubemapShader.dispose();
47952		if ( this._equirectShader !== null ) this._equirectShader.dispose();
47953
47954		for ( var i = 0; i < _lodPlanes.length; i ++ ) {
47955
47956			_lodPlanes[ i ].dispose();
47957
47958		}
47959
47960	},
47961
47962	// private interface
47963
47964	_cleanup: function ( outputTarget ) {
47965
47966		this._pingPongRenderTarget.dispose();
47967		this._renderer.setRenderTarget( _oldTarget );
47968		outputTarget.scissorTest = false;
47969		// reset viewport and scissor
47970		outputTarget.setSize( outputTarget.width, outputTarget.height );
47971
47972	},
47973
47974	_allocateTargets: function ( equirectangular ) {
47975
47976		var params = {
47977			magFilter: NearestFilter,
47978			minFilter: NearestFilter,
47979			generateMipmaps: false,
47980			type: UnsignedByteType,
47981			format: RGBEFormat,
47982			encoding: _isLDR( equirectangular ) ? equirectangular.encoding : RGBEEncoding,
47983			depthBuffer: false,
47984			stencilBuffer: false
47985		};
47986
47987		var cubeUVRenderTarget = _createRenderTarget( params );
47988		cubeUVRenderTarget.depthBuffer = equirectangular ? false : true;
47989		this._pingPongRenderTarget = _createRenderTarget( params );
47990		return cubeUVRenderTarget;
47991
47992	},
47993
47994	_compileMaterial: function ( material ) {
47995
47996		var tmpScene = new Scene();
47997		tmpScene.add( new Mesh( _lodPlanes[ 0 ], material ) );
47998		this._renderer.compile( tmpScene, _flatCamera );
47999
48000	},
48001
48002	_sceneToCubeUV: function ( scene, near, far, cubeUVRenderTarget ) {
48003
48004		var fov = 90;
48005		var aspect = 1;
48006		var cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
48007		var upSign = [ 1, 1, 1, 1, - 1, 1 ];
48008		var forwardSign = [ 1, 1, - 1, - 1, - 1, 1 ];
48009		var renderer = this._renderer;
48010
48011		var outputEncoding = renderer.outputEncoding;
48012		var toneMapping = renderer.toneMapping;
48013		var toneMappingExposure = renderer.toneMappingExposure;
48014		var clearColor = renderer.getClearColor();
48015		var clearAlpha = renderer.getClearAlpha();
48016
48017		renderer.toneMapping = LinearToneMapping;
48018		renderer.toneMappingExposure = 1.0;
48019		renderer.outputEncoding = LinearEncoding;
48020		scene.scale.z *= - 1;
48021
48022		var background = scene.background;
48023		if ( background && background.isColor ) {
48024
48025			background.convertSRGBToLinear();
48026			// Convert linear to RGBE
48027			var maxComponent = Math.max( background.r, background.g, background.b );
48028			var fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
48029			background = background.multiplyScalar( Math.pow( 2.0, - fExp ) );
48030			var alpha = ( fExp + 128.0 ) / 255.0;
vendor: 9,285 bytes, lines 48031-48400
48031			renderer.setClearColor( background, alpha );
48032			scene.background = null;
48033
48034		}
48035
48036		for ( var i = 0; i < 6; i ++ ) {
48037
48038			var col = i % 3;
48039			if ( col == 0 ) {
48040
48041				cubeCamera.up.set( 0, upSign[ i ], 0 );
48042				cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
48043
48044			} else if ( col == 1 ) {
48045
48046				cubeCamera.up.set( 0, 0, upSign[ i ] );
48047				cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
48048
48049			} else {
48050
48051				cubeCamera.up.set( 0, upSign[ i ], 0 );
48052				cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
48053
48054			}
48055
48056			_setViewport( cubeUVRenderTarget,
48057				col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
48058			renderer.setRenderTarget( cubeUVRenderTarget );
48059			renderer.render( scene, cubeCamera );
48060
48061		}
48062
48063		renderer.toneMapping = toneMapping;
48064		renderer.toneMappingExposure = toneMappingExposure;
48065		renderer.outputEncoding = outputEncoding;
48066		renderer.setClearColor( clearColor, clearAlpha );
48067		scene.scale.z *= - 1;
48068
48069	},
48070
48071	_textureToCubeUV: function ( texture, cubeUVRenderTarget ) {
48072
48073		var scene = new Scene();
48074		var renderer = this._renderer;
48075
48076		if ( texture.isCubeTexture ) {
48077
48078			if ( this._cubemapShader == null ) {
48079
48080				this._cubemapShader = _getCubemapShader();
48081
48082			}
48083
48084		} else {
48085
48086			if ( this._equirectShader == null ) {
48087
48088				this._equirectShader = _getEquirectShader();
48089
48090			}
48091
48092		}
48093
48094		var material = texture.isCubeTexture ? this._cubemapShader : this._equirectShader;
48095		scene.add( new Mesh( _lodPlanes[ 0 ], material ) );
48096
48097		var uniforms = material.uniforms;
48098
48099		uniforms[ 'envMap' ].value = texture;
48100
48101		if ( ! texture.isCubeTexture ) {
48102
48103			uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
48104
48105		}
48106
48107		uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ];
48108		uniforms[ 'outputEncoding' ].value = ENCODINGS[ cubeUVRenderTarget.texture.encoding ];
48109
48110		_setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
48111
48112		renderer.setRenderTarget( cubeUVRenderTarget );
48113		renderer.render( scene, _flatCamera );
48114
48115	},
48116
48117	_applyPMREM: function ( cubeUVRenderTarget ) {
48118
48119		var renderer = this._renderer;
48120		var autoClear = renderer.autoClear;
48121		renderer.autoClear = false;
48122
48123		for ( var i = 1; i < TOTAL_LODS; i ++ ) {
48124
48125			var sigma = Math.sqrt( _sigmas[ i ] * _sigmas[ i ] - _sigmas[ i - 1 ] * _sigmas[ i - 1 ] );
48126
48127			var poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ];
48128
48129			this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
48130
48131		}
48132
48133		renderer.autoClear = autoClear;
48134
48135	},
48136
48137	/**
48138	 * This is a two-pass Gaussian blur for a cubemap. Normally this is done
48139	 * vertically and horizontally, but this breaks down on a cube. Here we apply
48140	 * the blur latitudinally (around the poles), and then longitudinally (towards
48141	 * the poles) to approximate the orthogonally-separable blur. It is least
48142	 * accurate at the poles, but still does a decent job.
48143	 */
48144	_blur: function ( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
48145
48146		var pingPongRenderTarget = this._pingPongRenderTarget;
48147
48148		this._halfBlur(
48149			cubeUVRenderTarget,
48150			pingPongRenderTarget,
48151			lodIn,
48152			lodOut,
48153			sigma,
48154			'latitudinal',
48155			poleAxis );
48156
48157		this._halfBlur(
48158			pingPongRenderTarget,
48159			cubeUVRenderTarget,
48160			lodOut,
48161			lodOut,
48162			sigma,
48163			'longitudinal',
48164			poleAxis );
48165
48166	},
48167
48168	_halfBlur: function ( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
48169
48170		var renderer = this._renderer;
48171		var blurMaterial = this._blurMaterial;
48172
48173		if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
48174
48175			console.error(
48176				'blur direction must be either latitudinal or longitudinal!' );
48177
48178		}
48179
48180		// Number of standard deviations at which to cut off the discrete approximation.
48181		var STANDARD_DEVIATIONS = 3;
48182
48183		var blurScene = new Scene();
48184		blurScene.add( new Mesh( _lodPlanes[ lodOut ], blurMaterial ) );
48185		var blurUniforms = blurMaterial.uniforms;
48186
48187		var pixels = _sizeLods[ lodIn ] - 1;
48188		var radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
48189		var sigmaPixels = sigmaRadians / radiansPerPixel;
48190		var samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
48191
48192		if ( samples > MAX_SAMPLES ) {
48193
48194			console.warn( `sigmaRadians, ${
48195				sigmaRadians}, is too large and will clip, as it requested ${
48196				samples} samples when the maximum is set to ${MAX_SAMPLES}` );
48197
48198		}
48199
48200		var weights = [];
48201		var sum = 0;
48202
48203		for ( var i = 0; i < MAX_SAMPLES; ++ i ) {
48204
48205			var x = i / sigmaPixels;
48206			var weight = Math.exp( - x * x / 2 );
48207			weights.push( weight );
48208
48209			if ( i == 0 ) {
48210
48211				sum += weight;
48212
48213			} else if ( i < samples ) {
48214
48215				sum += 2 * weight;
48216
48217			}
48218
48219		}
48220
48221		for ( var i = 0; i < weights.length; i ++ ) {
48222
48223			weights[ i ] = weights[ i ] / sum;
48224
48225		}
48226
48227		blurUniforms[ 'envMap' ].value = targetIn.texture;
48228		blurUniforms[ 'samples' ].value = samples;
48229		blurUniforms[ 'weights' ].value = weights;
48230		blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
48231
48232		if ( poleAxis ) {
48233
48234			blurUniforms[ 'poleAxis' ].value = poleAxis;
48235
48236		}
48237
48238		blurUniforms[ 'dTheta' ].value = radiansPerPixel;
48239		blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn;
48240		blurUniforms[ 'inputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
48241		blurUniforms[ 'outputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
48242
48243		var outputSize = _sizeLods[ lodOut ];
48244		var x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize );
48245		var y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
48246
48247		_setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
48248		renderer.setRenderTarget( targetOut );
48249		renderer.render( blurScene, _flatCamera );
48250
48251	}
48252
48253};
48254
48255function _isLDR( texture ) {
48256
48257	if ( texture === undefined || texture.type !== UnsignedByteType ) return false;
48258
48259	return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding;
48260
48261}
48262
48263function _createPlanes() {
48264
48265	var _lodPlanes = [];
48266	var _sizeLods = [];
48267	var _sigmas = [];
48268
48269	var lod = LOD_MAX;
48270
48271	for ( var i = 0; i < TOTAL_LODS; i ++ ) {
48272
48273		var sizeLod = Math.pow( 2, lod );
48274		_sizeLods.push( sizeLod );
48275		var sigma = 1.0 / sizeLod;
48276
48277		if ( i > LOD_MAX - LOD_MIN ) {
48278
48279			sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
48280
48281		} else if ( i == 0 ) {
48282
48283			sigma = 0;
48284
48285		}
48286
48287		_sigmas.push( sigma );
48288
48289		var texelSize = 1.0 / ( sizeLod - 1 );
48290		var min = - texelSize / 2;
48291		var max = 1 + texelSize / 2;
48292		var uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
48293
48294		var cubeFaces = 6;
48295		var vertices = 6;
48296		var positionSize = 3;
48297		var uvSize = 2;
48298		var faceIndexSize = 1;
48299
48300		var position = new Float32Array( positionSize * vertices * cubeFaces );
48301		var uv = new Float32Array( uvSize * vertices * cubeFaces );
48302		var faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
48303
48304		for ( var face = 0; face < cubeFaces; face ++ ) {
48305
48306			var x = ( face % 3 ) * 2 / 3 - 1;
48307			var y = face > 2 ? 0 : - 1;
48308			var coordinates = [
48309				x, y, 0,
48310				x + 2 / 3, y, 0,
48311				x + 2 / 3, y + 1, 0,
48312				x, y, 0,
48313				x + 2 / 3, y + 1, 0,
48314				x, y + 1, 0
48315			];
48316			position.set( coordinates, positionSize * vertices * face );
48317			uv.set( uv1, uvSize * vertices * face );
48318			var fill = [ face, face, face, face, face, face ];
48319			faceIndex.set( fill, faceIndexSize * vertices * face );
48320
48321		}
48322
48323		var planes = new BufferGeometry();
48324		planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
48325		planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
48326		planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
48327		_lodPlanes.push( planes );
48328
48329		if ( lod > LOD_MIN ) {
48330
48331			lod --;
48332
48333		}
48334
48335	}
48336
48337	return { _lodPlanes, _sizeLods, _sigmas };
48338
48339}
48340
48341function _createRenderTarget( params ) {
48342
48343	var cubeUVRenderTarget = new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
48344	cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
48345	cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
48346	cubeUVRenderTarget.scissorTest = true;
48347	return cubeUVRenderTarget;
48348
48349}
48350
48351function _setViewport( target, x, y, width, height ) {
48352
48353	target.viewport.set( x, y, width, height );
48354	target.scissor.set( x, y, width, height );
48355
48356}
48357
48358function _getBlurShader( maxSamples ) {
48359
48360	var weights = new Float32Array( maxSamples );
48361	var poleAxis = new Vector3( 0, 1, 0 );
48362	var shaderMaterial = new RawShaderMaterial( {
48363
48364		defines: { 'n': maxSamples },
48365
48366		uniforms: {
48367			'envMap': { value: null },
48368			'samples': { value: 1 },
48369			'weights': { value: weights },
48370			'latitudinal': { value: false },
48371			'dTheta': { value: 0 },
48372			'mipInt': { value: 0 },
48373			'poleAxis': { value: poleAxis },
48374			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
48375			'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
48376		},
48377
48378		vertexShader: _getCommonVertexShader(),
48379
48380		fragmentShader: `
48381precision mediump float;
48382precision mediump int;
48383varying vec3 vOutputDirection;
48384uniform sampler2D envMap;
48385uniform int samples;
48386uniform float weights[n];
48387uniform bool latitudinal;
48388uniform float dTheta;
48389uniform float mipInt;
48390uniform vec3 poleAxis;
48391
48392${_getEncodings()}
48393
48394#define ENVMAP_TYPE_CUBE_UV
48395#include <cube_uv_reflection_fragment>
48396
48397vec3 getSample(float theta, vec3 axis) {
48398	float cosTheta = cos(theta);
48399	// Rodrigues' axis-angle rotation
48400	vec3 sampleDirection = vOutputDirection * cosTheta
48401		+ cross(axis, vOutputDirection) * sin(theta)
48402		+ axis * dot(axis, vOutputDirection) * (1.0 - cosTheta);
48403	return bilinearCubeUV(envMap, sampleDirection, mipInt);
48404}
48405
48406void main() {
48407	vec3 axis = latitudinal ? poleAxis : cross(poleAxis, vOutputDirection);
48408	if (all(equal(axis, vec3(0.0))))
48409		axis = vec3(vOutputDirection.z, 0.0, - vOutputDirection.x);
48410	axis = normalize(axis);
48411	gl_FragColor = vec4(0.0);
48412	gl_FragColor.rgb += weights[0] * getSample(0.0, axis);
48413	for (int i = 1; i < n; i++) {
48414		if (i >= samples)
48415			break;
48416		float theta = dTheta * float(i);
48417		gl_FragColor.rgb += weights[i] * getSample(-1.0 * theta, axis);
48418		gl_FragColor.rgb += weights[i] * getSample(theta, axis);
48419	}
48420	gl_FragColor = linearToOutputTexel(gl_FragColor);
48421}
48422		`,
48423
48424		blending: NoBlending,
48425		depthTest: false,
48426		depthWrite: false
48427
48428	} );
48429
48430	shaderMaterial.type = 'SphericalGaussianBlur';
48431
48432	return shaderMaterial;
48433
48434}
48435
48436function _getEquirectShader() {
48437
48438	var texelSize = new Vector2( 1, 1 );
48439	var shaderMaterial = new RawShaderMaterial( {
48440
48441		uniforms: {
48442			'envMap': { value: null },
48443			'texelSize': { value: texelSize },
48444			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
48445			'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
48446		},
48447
48448		vertexShader: _getCommonVertexShader(),
48449
48450		fragmentShader: `
48451precision mediump float;
48452precision mediump int;
48453varying vec3 vOutputDirection;
48454uniform sampler2D envMap;
48455uniform vec2 texelSize;
48456
48457${_getEncodings()}
48458
48459#define RECIPROCAL_PI 0.31830988618
48460#define RECIPROCAL_PI2 0.15915494
48461
48462void main() {
48463	gl_FragColor = vec4(0.0);
48464	vec3 outputDirection = normalize(vOutputDirection);
48465	vec2 uv;
48466	uv.y = asin(clamp(outputDirection.y, -1.0, 1.0)) * RECIPROCAL_PI + 0.5;
48467	uv.x = atan(outputDirection.z, outputDirection.x) * RECIPROCAL_PI2 + 0.5;
48468	vec2 f = fract(uv / texelSize - 0.5);
48469	uv -= f * texelSize;
48470	vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
48471	uv.x += texelSize.x;
48472	vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
48473	uv.y += texelSize.y;
48474	vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
48475	uv.x -= texelSize.x;
48476	vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
48477	vec3 tm = mix(tl, tr, f.x);
48478	vec3 bm = mix(bl, br, f.x);
48479	gl_FragColor.rgb = mix(tm, bm, f.y);
48480	gl_FragColor = linearToOutputTexel(gl_FragColor);
48481}
48482		`,
48483
48484		blending: NoBlending,
48485		depthTest: false,
48486		depthWrite: false
48487
48488	} );
48489
48490	shaderMaterial.type = 'EquirectangularToCubeUV';
48491
48492	return shaderMaterial;
48493
48494}
48495
48496function _getCubemapShader() {
48497
48498	var shaderMaterial = new RawShaderMaterial( {
48499
48500		uniforms: {
48501			'envMap': { value: null },
48502			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
48503			'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
48504		},
48505
48506		vertexShader: _getCommonVertexShader(),
48507
48508		fragmentShader: `
48509precision mediump float;
48510precision mediump int;
48511varying vec3 vOutputDirection;
48512uniform samplerCube envMap;
48513
48514${_getEncodings()}
48515
48516void main() {
48517	gl_FragColor = vec4(0.0);
48518	gl_FragColor.rgb = envMapTexelToLinear(textureCube(envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ))).rgb;
48519	gl_FragColor = linearToOutputTexel(gl_FragColor);
48520}
48521		`,
48522
48523		blending: NoBlending,
48524		depthTest: false,
48525		depthWrite: false
48526
48527	} );
48528
48529	shaderMaterial.type = 'CubemapToCubeUV';
48530
48531	return shaderMaterial;
48532
48533}
48534
48535function _getCommonVertexShader() {
48536
48537	return `
48538precision mediump float;
48539precision mediump int;
48540attribute vec3 position;
48541attribute vec2 uv;
48542attribute float faceIndex;
48543varying vec3 vOutputDirection;
48544vec3 getDirection(vec2 uv, float face) {
48545	uv = 2.0 * uv - 1.0;
48546	vec3 direction = vec3(uv, 1.0);
48547	if (face == 0.0) {
48548		direction = direction.zyx;
48549		direction.z *= -1.0;
48550	} else if (face == 1.0) {
48551		direction = direction.xzy;
48552		direction.z *= -1.0;
48553	} else if (face == 3.0) {
48554		direction = direction.zyx;
48555		direction.x *= -1.0;
48556	} else if (face == 4.0) {
48557		direction = direction.xzy;
48558		direction.y *= -1.0;
48559	} else if (face == 5.0) {
48560		direction.xz *= -1.0;
48561	}
48562	return direction;
48563}
48564void main() {
48565	vOutputDirection = getDirection(uv, faceIndex);
48566	gl_Position = vec4( position, 1.0 );
48567}
48568	`;
48569
48570}
48571
48572function _getEncodings() {
48573
48574	return `
48575uniform int inputEncoding;
48576uniform int outputEncoding;
48577
48578#include <encodings_pars_fragment>
48579
48580vec4 inputTexelToLinear(vec4 value){
48581	if(inputEncoding == 0){
48582		return value;
48583	}else if(inputEncoding == 1){
48584		return sRGBToLinear(value);
48585	}else if(inputEncoding == 2){
48586		return RGBEToLinear(value);
48587	}else if(inputEncoding == 3){
48588		return RGBMToLinear(value, 7.0);
48589	}else if(inputEncoding == 4){
48590		return RGBMToLinear(value, 16.0);
48591	}else if(inputEncoding == 5){
48592		return RGBDToLinear(value, 256.0);
48593	}else{
48594		return GammaToLinear(value, 2.2);
48595	}
48596}
48597
48598vec4 linearToOutputTexel(vec4 value){
48599	if(outputEncoding == 0){
48600		return value;
48601	}else if(outputEncoding == 1){
48602		return LinearTosRGB(value);
48603	}else if(outputEncoding == 2){
48604		return LinearToRGBE(value);
48605	}else if(outputEncoding == 3){
48606		return LinearToRGBM(value, 7.0);
48607	}else if(outputEncoding == 4){
48608		return LinearToRGBM(value, 16.0);
48609	}else if(outputEncoding == 5){
48610		return LinearToRGBD(value, 256.0);
48611	}else{
48612		return LinearToGamma(value, 2.2);
48613	}
48614}
48615
48616vec4 envMapTexelToLinear(vec4 color) {
48617	return inputTexelToLinear(color);
48618}
48619	`;
48620
48621}
48622
48623/**
48624 * @author mrdoob / http://mrdoob.com/
48625 */
48626
48627function Face4( a, b, c, d, normal, color, materialIndex ) {
48628
48629	console.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );
48630	return new Face3( a, b, c, normal, color, materialIndex );
48631
48632}
48633
48634var LineStrip = 0;
48635var LinePieces = 1;
48636var NoColors = 0;
48637var FaceColors = 1;
48638var VertexColors = 2;
48639
48640function MeshFaceMaterial( materials ) {
48641
48642	console.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );
48643	return materials;
48644
48645}
48646
48647function MultiMaterial( materials ) {
48648
48649	if ( materials === undefined ) materials = [];
48650
48651	console.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );
48652	materials.isMultiMaterial = true;
48653	materials.materials = materials;
48654	materials.clone = function () {
48655
48656		return materials.slice();
48657
48658	};
48659
48660	return materials;
48661
48662}
48663
48664function PointCloud( geometry, material ) {
48665
48666	console.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );
48667	return new Points( geometry, material );
48668
48669}
48670
48671function Particle( material ) {
48672
48673	console.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );
48674	return new Sprite( material );
48675
48676}
48677
48678function ParticleSystem( geometry, material ) {
48679
48680	console.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );
48681	return new Points( geometry, material );
48682
48683}
48684
48685function PointCloudMaterial( parameters ) {
48686
48687	console.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );
48688	return new PointsMaterial( parameters );
48689
48690}
48691
48692function ParticleBasicMaterial( parameters ) {
48693
48694	console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );
48695	return new PointsMaterial( parameters );
48696
48697}
48698
48699function ParticleSystemMaterial( parameters ) {
48700
48701	console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );
48702	return new PointsMaterial( parameters );
48703
48704}
48705
48706function Vertex( x, y, z ) {
48707
48708	console.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );
48709	return new Vector3( x, y, z );
48710
48711}
48712
48713//
48714
48715function DynamicBufferAttribute( array, itemSize ) {
48716
48717	console.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setUsage( THREE.DynamicDrawUsage ) instead.' );
48718	return new BufferAttribute( array, itemSize ).setUsage( DynamicDrawUsage );
48719
48720}
48721
48722function Int8Attribute( array, itemSize ) {
48723
48724	console.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );
48725	return new Int8BufferAttribute( array, itemSize );
48726
48727}
48728
48729function Uint8Attribute( array, itemSize ) {
48730
48731	console.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );
48732	return new Uint8BufferAttribute( array, itemSize );
48733
48734}
48735
48736function Uint8ClampedAttribute( array, itemSize ) {
48737
48738	console.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );
48739	return new Uint8ClampedBufferAttribute( array, itemSize );
48740
48741}
48742
48743function Int16Attribute( array, itemSize ) {
48744
48745	console.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );
48746	return new Int16BufferAttribute( array, itemSize );
48747
48748}
48749
48750function Uint16Attribute( array, itemSize ) {
48751
48752	console.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );
48753	return new Uint16BufferAttribute( array, itemSize );
48754
48755}
48756
48757function Int32Attribute( array, itemSize ) {
48758
48759	console.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );
48760	return new Int32BufferAttribute( array, itemSize );
48761
48762}
48763
48764function Uint32Attribute( array, itemSize ) {
48765
48766	console.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );
48767	return new Uint32BufferAttribute( array, itemSize );
48768
48769}
48770
48771function Float32Attribute( array, itemSize ) {
48772
48773	console.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );
48774	return new Float32BufferAttribute( array, itemSize );
48775
48776}
48777
48778function Float64Attribute( array, itemSize ) {
48779
48780	console.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );
48781	return new Float64BufferAttribute( array, itemSize );
48782
48783}
48784
48785//
48786
48787Curve.create = function ( construct, getPoint ) {
48788
48789	console.log( 'THREE.Curve.create() has been deprecated' );
48790
48791	construct.prototype = Object.create( Curve.prototype );
48792	construct.prototype.constructor = construct;
48793	construct.prototype.getPoint = getPoint;
48794
48795	return construct;
48796
48797};
48798
48799//
48800
48801Object.assign( CurvePath.prototype, {
48802
48803	createPointsGeometry: function ( divisions ) {
48804
48805		console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
48806
48807		// generate geometry from path points (for Line or Points objects)
48808
48809		var pts = this.getPoints( divisions );
48810		return this.createGeometry( pts );
48811
48812	},
48813
48814	createSpacedPointsGeometry: function ( divisions ) {
48815
48816		console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
48817
48818		// generate geometry from equidistant sampling along the path
48819
48820		var pts = this.getSpacedPoints( divisions );
48821		return this.createGeometry( pts );
48822
48823	},
48824
48825	createGeometry: function ( points ) {
48826
48827		console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );
48828
48829		var geometry = new Geometry();
48830
48831		for ( var i = 0, l = points.length; i < l; i ++ ) {
48832
48833			var point = points[ i ];
48834			geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );
48835
48836		}
48837
48838		return geometry;
48839
48840	}
48841
48842} );
48843
48844//
48845
48846Object.assign( Path.prototype, {
48847
48848	fromPoints: function ( points ) {
48849
48850		console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );
48851		return this.setFromPoints( points );
48852
48853	}
48854
48855} );
48856
48857//
48858
48859function ClosedSplineCurve3( points ) {
48860
48861	console.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
48862
48863	CatmullRomCurve3.call( this, points );
48864	this.type = 'catmullrom';
48865	this.closed = true;
48866
48867}
48868
48869ClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
48870
48871//
48872
48873function SplineCurve3( points ) {
48874
48875	console.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );
48876
48877	CatmullRomCurve3.call( this, points );
48878	this.type = 'catmullrom';
48879
48880}
48881
48882SplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );
48883
48884//
48885
48886function Spline( points ) {
48887
48888	console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );
48889
48890	CatmullRomCurve3.call( this, points );
48891	this.type = 'catmullrom';
48892
48893}
48894
48895Spline.prototype = Object.create( CatmullRomCurve3.prototype );
48896
48897Object.assign( Spline.prototype, {
48898
48899	initFromArray: function ( /* a */ ) {
48900
48901		console.error( 'THREE.Spline: .initFromArray() has been removed.' );
48902
48903	},
48904	getControlPointsArray: function ( /* optionalTarget */ ) {
48905
48906		console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );
48907
48908	},
48909	reparametrizeByArcLength: function ( /* samplingCoef */ ) {
48910
48911		console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );
48912
48913	}
48914
48915} );
48916
48917//
48918
48919function AxisHelper( size ) {
48920
48921	console.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );
48922	return new AxesHelper( size );
48923
48924}
48925
48926function BoundingBoxHelper( object, color ) {
48927
48928	console.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );
48929	return new BoxHelper( object, color );
48930
48931}
48932
48933function EdgesHelper( object, hex ) {
48934
48935	console.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );
48936	return new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
48937
48938}
48939
48940GridHelper.prototype.setColors = function () {
48941
48942	console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );
48943
48944};
48945
48946SkeletonHelper.prototype.update = function () {
48947
48948	console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );
48949
48950};
48951
48952function WireframeHelper( object, hex ) {
48953
48954	console.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );
48955	return new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );
48956
48957}
48958
48959//
48960
48961Object.assign( Loader.prototype, {
48962
48963	extractUrlBase: function ( url ) {
48964
48965		console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );
48966		return LoaderUtils.extractUrlBase( url );
48967
48968	}
48969
48970} );
48971
48972Loader.Handlers = {
48973
48974	add: function ( /* regex, loader */ ) {
48975
48976		console.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );
48977
48978	},
48979
48980	get: function ( /* file */ ) {
48981
48982		console.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );
48983
48984	}
48985
48986};
48987
48988function XHRLoader( manager ) {
48989
48990	console.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );
48991	return new FileLoader( manager );
48992
48993}
48994
48995function BinaryTextureLoader( manager ) {
48996
48997	console.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );
48998	return new DataTextureLoader( manager );
48999
49000}
49001
49002Object.assign( ObjectLoader.prototype, {
49003
49004	setTexturePath: function ( value ) {
49005
49006		console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
49007		return this.setResourcePath( value );
49008
49009	}
49010
49011} );
49012
49013//
49014
49015Object.assign( Box2.prototype, {
49016
49017	center: function ( optionalTarget ) {
49018
49019		console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );
49020		return this.getCenter( optionalTarget );
49021
49022	},
49023	empty: function () {
49024
49025		console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );
49026		return this.isEmpty();
49027
49028	},
49029	isIntersectionBox: function ( box ) {
49030
49031		console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );
49032		return this.intersectsBox( box );
49033
49034	},
49035	size: function ( optionalTarget ) {
49036
49037		console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );
49038		return this.getSize( optionalTarget );
49039
49040	}
49041} );
49042
49043Object.assign( Box3.prototype, {
49044
49045	center: function ( optionalTarget ) {
49046
49047		console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );
49048		return this.getCenter( optionalTarget );
49049
49050	},
49051	empty: function () {
49052
49053		console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );
49054		return this.isEmpty();
49055
49056	},
49057	isIntersectionBox: function ( box ) {
49058
49059		console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );
49060		return this.intersectsBox( box );
49061
49062	},
49063	isIntersectionSphere: function ( sphere ) {
49064
49065		console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
49066		return this.intersectsSphere( sphere );
49067
49068	},
49069	size: function ( optionalTarget ) {
49070
49071		console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );
49072		return this.getSize( optionalTarget );
49073
49074	}
49075} );
49076
49077Object.assign( Sphere.prototype, {
49078
49079	empty: function () {
49080
49081		console.warn( 'THREE.Sphere: .empty() has been renamed to .isEmpty().' );
49082		return this.isEmpty();
49083
49084	},
49085
49086} );
49087
49088Frustum.prototype.setFromMatrix = function ( m ) {
49089
49090	console.warn( 'THREE.Frustum: .setFromMatrix() has been renamed to .setFromProjectionMatrix().' );
49091	return this.setFromProjectionMatrix( m );
49092
49093};
49094
49095Line3.prototype.center = function ( optionalTarget ) {
49096
49097	console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );
49098	return this.getCenter( optionalTarget );
49099
49100};
49101
49102Object.assign( MathUtils, {
49103
49104	random16: function () {
49105
49106		console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );
49107		return Math.random();
49108
49109	},
49110
49111	nearestPowerOfTwo: function ( value ) {
49112
49113		console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );
49114		return MathUtils.floorPowerOfTwo( value );
49115
49116	},
49117
49118	nextPowerOfTwo: function ( value ) {
49119
49120		console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );
49121		return MathUtils.ceilPowerOfTwo( value );
49122
49123	}
49124
49125} );
49126
49127Object.assign( Matrix3.prototype, {
49128
49129	flattenToArrayOffset: function ( array, offset ) {
49130
49131		console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
49132		return this.toArray( array, offset );
49133
49134	},
49135	multiplyVector3: function ( vector ) {
49136
vendor: 1,651 bytes, lines 49137-49192
49137		console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );
49138		return vector.applyMatrix3( this );
49139
49140	},
49141	multiplyVector3Array: function ( /* a */ ) {
49142
49143		console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );
49144
49145	},
49146	applyToBufferAttribute: function ( attribute ) {
49147
49148		console.warn( 'THREE.Matrix3: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix3( matrix ) instead.' );
49149		return attribute.applyMatrix3( this );
49150
49151	},
49152	applyToVector3Array: function ( /* array, offset, length */ ) {
49153
49154		console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );
49155
49156	}
49157
49158} );
49159
49160Object.assign( Matrix4.prototype, {
49161
49162	extractPosition: function ( m ) {
49163
49164		console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );
49165		return this.copyPosition( m );
49166
49167	},
49168	flattenToArrayOffset: function ( array, offset ) {
49169
49170		console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." );
49171		return this.toArray( array, offset );
49172
49173	},
49174	getPosition: function () {
49175
49176		console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
49177		return new Vector3().setFromMatrixColumn( this, 3 );
49178
49179	},
49180	setRotationFromQuaternion: function ( q ) {
49181
49182		console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );
49183		return this.makeRotationFromQuaternion( q );
49184
49185	},
49186	multiplyToArray: function () {
49187
49188		console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );
49189
49190	},
49191	multiplyVector3: function ( vector ) {
49192
49193		console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
49194		return vector.applyMatrix4( this );
49195
49196	},
49197	multiplyVector4: function ( vector ) {
49198
49199		console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
49200		return vector.applyMatrix4( this );
49201
49202	},
49203	multiplyVector3Array: function ( /* a */ ) {
49204
49205		console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );
49206
49207	},
49208	rotateAxis: function ( v ) {
49209
49210		console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );
49211		v.transformDirection( this );
49212
49213	},
49214	crossVector: function ( vector ) {
49215
49216		console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );
49217		return vector.applyMatrix4( this );
49218
49219	},
49220	translate: function () {
49221
49222		console.error( 'THREE.Matrix4: .translate() has been removed.' );
49223
49224	},
49225	rotateX: function () {
49226
49227		console.error( 'THREE.Matrix4: .rotateX() has been removed.' );
49228
49229	},
49230	rotateY: function () {
49231
49232		console.error( 'THREE.Matrix4: .rotateY() has been removed.' );
49233
49234	},
49235	rotateZ: function () {
49236
49237		console.error( 'THREE.Matrix4: .rotateZ() has been removed.' );
49238
49239	},
49240	rotateByAxis: function () {
49241
49242		console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );
49243
49244	},
49245	applyToBufferAttribute: function ( attribute ) {
49246
49247		console.warn( 'THREE.Matrix4: .applyToBufferAttribute() has been removed. Use attribute.applyMatrix4( matrix ) instead.' );
49248		return attribute.applyMatrix4( this );
49249
49250	},
49251	applyToVector3Array: function ( /* array, offset, length */ ) {
49252
49253		console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );
49254
49255	},
49256	makeFrustum: function ( left, right, bottom, top, near, far ) {
49257
49258		console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );
49259		return this.makePerspective( left, right, top, bottom, near, far );
49260
49261	}
49262
49263} );
49264
49265Plane.prototype.isIntersectionLine = function ( line ) {
49266
49267	console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );
49268	return this.intersectsLine( line );
49269
49270};
49271
49272Quaternion.prototype.multiplyVector3 = function ( vector ) {
49273
vendor: 28,316 bytes, lines 49274-50459
49274	console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );
49275	return vector.applyQuaternion( this );
49276
49277};
49278
49279Object.assign( Ray.prototype, {
49280
49281	isIntersectionBox: function ( box ) {
49282
49283		console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );
49284		return this.intersectsBox( box );
49285
49286	},
49287	isIntersectionPlane: function ( plane ) {
49288
49289		console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );
49290		return this.intersectsPlane( plane );
49291
49292	},
49293	isIntersectionSphere: function ( sphere ) {
49294
49295		console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );
49296		return this.intersectsSphere( sphere );
49297
49298	}
49299
49300} );
49301
49302Object.assign( Triangle.prototype, {
49303
49304	area: function () {
49305
49306		console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );
49307		return this.getArea();
49308
49309	},
49310	barycoordFromPoint: function ( point, target ) {
49311
49312		console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
49313		return this.getBarycoord( point, target );
49314
49315	},
49316	midpoint: function ( target ) {
49317
49318		console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );
49319		return this.getMidpoint( target );
49320
49321	},
49322	normal: function ( target ) {
49323
49324		console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
49325		return this.getNormal( target );
49326
49327	},
49328	plane: function ( target ) {
49329
49330		console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );
49331		return this.getPlane( target );
49332
49333	}
49334
49335} );
49336
49337Object.assign( Triangle, {
49338
49339	barycoordFromPoint: function ( point, a, b, c, target ) {
49340
49341		console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );
49342		return Triangle.getBarycoord( point, a, b, c, target );
49343
49344	},
49345	normal: function ( a, b, c, target ) {
49346
49347		console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );
49348		return Triangle.getNormal( a, b, c, target );
49349
49350	}
49351
49352} );
49353
49354Object.assign( Shape.prototype, {
49355
49356	extractAllPoints: function ( divisions ) {
49357
49358		console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );
49359		return this.extractPoints( divisions );
49360
49361	},
49362	extrude: function ( options ) {
49363
49364		console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );
49365		return new ExtrudeGeometry( this, options );
49366
49367	},
49368	makeGeometry: function ( options ) {
49369
49370		console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );
49371		return new ShapeGeometry( this, options );
49372
49373	}
49374
49375} );
49376
49377Object.assign( Vector2.prototype, {
49378
49379	fromAttribute: function ( attribute, index, offset ) {
49380
49381		console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );
49382		return this.fromBufferAttribute( attribute, index, offset );
49383
49384	},
49385	distanceToManhattan: function ( v ) {
49386
49387		console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
49388		return this.manhattanDistanceTo( v );
49389
49390	},
49391	lengthManhattan: function () {
49392
49393		console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );
49394		return this.manhattanLength();
49395
49396	}
49397
49398} );
49399
49400Object.assign( Vector3.prototype, {
49401
49402	setEulerFromRotationMatrix: function () {
49403
49404		console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );
49405
49406	},
49407	setEulerFromQuaternion: function () {
49408
49409		console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );
49410
49411	},
49412	getPositionFromMatrix: function ( m ) {
49413
49414		console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );
49415		return this.setFromMatrixPosition( m );
49416
49417	},
49418	getScaleFromMatrix: function ( m ) {
49419
49420		console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );
49421		return this.setFromMatrixScale( m );
49422
49423	},
49424	getColumnFromMatrix: function ( index, matrix ) {
49425
49426		console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );
49427		return this.setFromMatrixColumn( matrix, index );
49428
49429	},
49430	applyProjection: function ( m ) {
49431
49432		console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );
49433		return this.applyMatrix4( m );
49434
49435	},
49436	fromAttribute: function ( attribute, index, offset ) {
49437
49438		console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );
49439		return this.fromBufferAttribute( attribute, index, offset );
49440
49441	},
49442	distanceToManhattan: function ( v ) {
49443
49444		console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );
49445		return this.manhattanDistanceTo( v );
49446
49447	},
49448	lengthManhattan: function () {
49449
49450		console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );
49451		return this.manhattanLength();
49452
49453	}
49454
49455} );
49456
49457Object.assign( Vector4.prototype, {
49458
49459	fromAttribute: function ( attribute, index, offset ) {
49460
49461		console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );
49462		return this.fromBufferAttribute( attribute, index, offset );
49463
49464	},
49465	lengthManhattan: function () {
49466
49467		console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );
49468		return this.manhattanLength();
49469
49470	}
49471
49472} );
49473
49474//
49475
49476Object.assign( Geometry.prototype, {
49477
49478	computeTangents: function () {
49479
49480		console.error( 'THREE.Geometry: .computeTangents() has been removed.' );
49481
49482	},
49483	computeLineDistances: function () {
49484
49485		console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );
49486
49487	},
49488	applyMatrix: function ( matrix ) {
49489
49490		console.warn( 'THREE.Geometry: .applyMatrix() has been renamed to .applyMatrix4().' );
49491		return this.applyMatrix4( matrix );
49492
49493	}
49494
49495} );
49496
49497Object.assign( Object3D.prototype, {
49498
49499	getChildByName: function ( name ) {
49500
49501		console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );
49502		return this.getObjectByName( name );
49503
49504	},
49505	renderDepth: function () {
49506
49507		console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );
49508
49509	},
49510	translate: function ( distance, axis ) {
49511
49512		console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );
49513		return this.translateOnAxis( axis, distance );
49514
49515	},
49516	getWorldRotation: function () {
49517
49518		console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );
49519
49520	},
49521	applyMatrix: function ( matrix ) {
49522
49523		console.warn( 'THREE.Object3D: .applyMatrix() has been renamed to .applyMatrix4().' );
49524		return this.applyMatrix4( matrix );
49525
49526	}
49527
49528} );
49529
49530Object.defineProperties( Object3D.prototype, {
49531
49532	eulerOrder: {
49533		get: function () {
49534
49535			console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
49536			return this.rotation.order;
49537
49538		},
49539		set: function ( value ) {
49540
49541			console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
49542			this.rotation.order = value;
49543
49544		}
49545	},
49546	useQuaternion: {
49547		get: function () {
49548
49549			console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
49550
49551		},
49552		set: function () {
49553
49554			console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );
49555
49556		}
49557	}
49558
49559} );
49560
49561Object.assign( Mesh.prototype, {
49562
49563	setDrawMode: function () {
49564
49565		console.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
49566
49567	},
49568
49569} );
49570
49571Object.defineProperties( Mesh.prototype, {
49572
49573	drawMode: {
49574		get: function () {
49575
49576			console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );
49577			return TrianglesDrawMode;
49578
49579		},
49580		set: function () {
49581
49582			console.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );
49583
49584		}
49585	}
49586
49587} );
49588
49589Object.defineProperties( LOD.prototype, {
49590
49591	objects: {
49592		get: function () {
49593
49594			console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
49595			return this.levels;
49596
49597		}
49598	}
49599
49600} );
49601
49602Object.defineProperty( Skeleton.prototype, 'useVertexTexture', {
49603
49604	get: function () {
49605
49606		console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
49607
49608	},
49609	set: function () {
49610
49611		console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );
49612
49613	}
49614
49615} );
49616
49617SkinnedMesh.prototype.initBones = function () {
49618
49619	console.error( 'THREE.SkinnedMesh: initBones() has been removed.' );
49620
49621};
49622
49623Object.defineProperty( Curve.prototype, '__arcLengthDivisions', {
49624
49625	get: function () {
49626
49627		console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
49628		return this.arcLengthDivisions;
49629
49630	},
49631	set: function ( value ) {
49632
49633		console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );
49634		this.arcLengthDivisions = value;
49635
49636	}
49637
49638} );
49639
49640//
49641
49642PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {
49643
49644	console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " +
49645			"Use .setFocalLength and .filmGauge for a photographic setup." );
49646
49647	if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
49648	this.setFocalLength( focalLength );
49649
49650};
49651
49652//
49653
49654Object.defineProperties( Light.prototype, {
49655	onlyShadow: {
49656		set: function () {
49657
49658			console.warn( 'THREE.Light: .onlyShadow has been removed.' );
49659
49660		}
49661	},
49662	shadowCameraFov: {
49663		set: function ( value ) {
49664
49665			console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );
49666			this.shadow.camera.fov = value;
49667
49668		}
49669	},
49670	shadowCameraLeft: {
49671		set: function ( value ) {
49672
49673			console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );
49674			this.shadow.camera.left = value;
49675
49676		}
49677	},
49678	shadowCameraRight: {
49679		set: function ( value ) {
49680
49681			console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );
49682			this.shadow.camera.right = value;
49683
49684		}
49685	},
49686	shadowCameraTop: {
49687		set: function ( value ) {
49688
49689			console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );
49690			this.shadow.camera.top = value;
49691
49692		}
49693	},
49694	shadowCameraBottom: {
49695		set: function ( value ) {
49696
49697			console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );
49698			this.shadow.camera.bottom = value;
49699
49700		}
49701	},
49702	shadowCameraNear: {
49703		set: function ( value ) {
49704
49705			console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );
49706			this.shadow.camera.near = value;
49707
49708		}
49709	},
49710	shadowCameraFar: {
49711		set: function ( value ) {
49712
49713			console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );
49714			this.shadow.camera.far = value;
49715
49716		}
49717	},
49718	shadowCameraVisible: {
49719		set: function () {
49720
49721			console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );
49722
49723		}
49724	},
49725	shadowBias: {
49726		set: function ( value ) {
49727
49728			console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );
49729			this.shadow.bias = value;
49730
49731		}
49732	},
49733	shadowDarkness: {
49734		set: function () {
49735
49736			console.warn( 'THREE.Light: .shadowDarkness has been removed.' );
49737
49738		}
49739	},
49740	shadowMapWidth: {
49741		set: function ( value ) {
49742
49743			console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );
49744			this.shadow.mapSize.width = value;
49745
49746		}
49747	},
49748	shadowMapHeight: {
49749		set: function ( value ) {
49750
49751			console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );
49752			this.shadow.mapSize.height = value;
49753
49754		}
49755	}
49756} );
49757
49758//
49759
49760Object.defineProperties( BufferAttribute.prototype, {
49761
49762	length: {
49763		get: function () {
49764
49765			console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );
49766			return this.array.length;
49767
49768		}
49769	},
49770	dynamic: {
49771		get: function () {
49772
49773			console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
49774			return this.usage === DynamicDrawUsage;
49775
49776		},
49777		set: function ( /* value */ ) {
49778
49779			console.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );
49780			this.setUsage( DynamicDrawUsage );
49781
49782		}
49783	}
49784
49785} );
49786
49787Object.assign( BufferAttribute.prototype, {
49788	setDynamic: function ( value ) {
49789
49790		console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
49791		this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
49792		return this;
49793
49794	},
49795	copyIndicesArray: function ( /* indices */ ) {
49796
49797		console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );
49798
49799	},
49800	setArray: function ( /* array */ ) {
49801
49802		console.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
49803
49804	}
49805} );
49806
49807Object.assign( BufferGeometry.prototype, {
49808
49809	addIndex: function ( index ) {
49810
49811		console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );
49812		this.setIndex( index );
49813
49814	},
49815	addAttribute: function ( name, attribute ) {
49816
49817		console.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );
49818
49819		if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {
49820
49821			console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );
49822
49823			return this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );
49824
49825		}
49826
49827		if ( name === 'index' ) {
49828
49829			console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
49830			this.setIndex( attribute );
49831
49832			return this;
49833
49834		}
49835
49836		return this.setAttribute( name, attribute );
49837
49838	},
49839	addDrawCall: function ( start, count, indexOffset ) {
49840
49841		if ( indexOffset !== undefined ) {
49842
49843			console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );
49844
49845		}
49846
49847		console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );
49848		this.addGroup( start, count );
49849
49850	},
49851	clearDrawCalls: function () {
49852
49853		console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );
49854		this.clearGroups();
49855
49856	},
49857	computeTangents: function () {
49858
49859		console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );
49860
49861	},
49862	computeOffsets: function () {
49863
49864		console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );
49865
49866	},
49867	removeAttribute: function ( name ) {
49868
49869		console.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );
49870
49871		return this.deleteAttribute( name );
49872
49873	},
49874	applyMatrix: function ( matrix ) {
49875
49876		console.warn( 'THREE.BufferGeometry: .applyMatrix() has been renamed to .applyMatrix4().' );
49877		return this.applyMatrix4( matrix );
49878
49879	}
49880
49881} );
49882
49883Object.defineProperties( BufferGeometry.prototype, {
49884
49885	drawcalls: {
49886		get: function () {
49887
49888			console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );
49889			return this.groups;
49890
49891		}
49892	},
49893	offsets: {
49894		get: function () {
49895
49896			console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );
49897			return this.groups;
49898
49899		}
49900	}
49901
49902} );
49903
49904Object.defineProperties( Raycaster.prototype, {
49905
49906	linePrecision: {
49907		get: function () {
49908
49909			console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
49910			return this.params.Line.threshold;
49911
49912		},
49913		set: function ( value ) {
49914
49915			console.warn( 'THREE.Raycaster: .linePrecision has been deprecated. Use .params.Line.threshold instead.' );
49916			this.params.Line.threshold = value;
49917
49918		}
49919	}
49920
49921} );
49922
49923Object.defineProperties( InterleavedBuffer.prototype, {
49924
49925	dynamic: {
49926		get: function () {
49927
49928			console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
49929			return this.usage === DynamicDrawUsage;
49930
49931		},
49932		set: function ( value ) {
49933
49934			console.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );
49935			this.setUsage( value );
49936
49937		}
49938	}
49939
49940} );
49941
49942Object.assign( InterleavedBuffer.prototype, {
49943	setDynamic: function ( value ) {
49944
49945		console.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );
49946		this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
49947		return this;
49948
49949	},
49950	setArray: function ( /* array */ ) {
49951
49952		console.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );
49953
49954	}
49955} );
49956
49957//
49958
49959Object.assign( ExtrudeBufferGeometry.prototype, {
49960
49961	getArrays: function () {
49962
49963		console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );
49964
49965	},
49966
49967	addShapeList: function () {
49968
49969		console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );
49970
49971	},
49972
49973	addShape: function () {
49974
49975		console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );
49976
49977	}
49978
49979} );
49980
49981//
49982
49983Object.defineProperties( Uniform.prototype, {
49984
49985	dynamic: {
49986		set: function () {
49987
49988			console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );
49989
49990		}
49991	},
49992	onUpdate: {
49993		value: function () {
49994
49995			console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );
49996			return this;
49997
49998		}
49999	}
50000
50001} );
50002
50003//
50004
50005Object.defineProperties( Material.prototype, {
50006
50007	wrapAround: {
50008		get: function () {
50009
50010			console.warn( 'THREE.Material: .wrapAround has been removed.' );
50011
50012		},
50013		set: function () {
50014
50015			console.warn( 'THREE.Material: .wrapAround has been removed.' );
50016
50017		}
50018	},
50019
50020	overdraw: {
50021		get: function () {
50022
50023			console.warn( 'THREE.Material: .overdraw has been removed.' );
50024
50025		},
50026		set: function () {
50027
50028			console.warn( 'THREE.Material: .overdraw has been removed.' );
50029
50030		}
50031	},
50032
50033	wrapRGB: {
50034		get: function () {
50035
50036			console.warn( 'THREE.Material: .wrapRGB has been removed.' );
50037			return new Color();
50038
50039		}
50040	},
50041
50042	shading: {
50043		get: function () {
50044
50045			console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
50046
50047		},
50048		set: function ( value ) {
50049
50050			console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
50051			this.flatShading = ( value === FlatShading );
50052
50053		}
50054	},
50055
50056	stencilMask: {
50057		get: function () {
50058
50059			console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
50060			return this.stencilFuncMask;
50061
50062		},
50063		set: function ( value ) {
50064
50065			console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
50066			this.stencilFuncMask = value;
50067
50068		}
50069	}
50070
50071} );
50072
50073Object.defineProperties( MeshPhongMaterial.prototype, {
50074
50075	metal: {
50076		get: function () {
50077
50078			console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );
50079			return false;
50080
50081		},
50082		set: function () {
50083
50084			console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );
50085
50086		}
50087	}
50088
50089} );
50090
50091Object.defineProperties( ShaderMaterial.prototype, {
50092
50093	derivatives: {
50094		get: function () {
50095
50096			console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
50097			return this.extensions.derivatives;
50098
50099		},
50100		set: function ( value ) {
50101
50102			console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );
50103			this.extensions.derivatives = value;
50104
50105		}
50106	}
50107
50108} );
50109
50110//
50111
50112Object.assign( WebGLRenderer.prototype, {
50113
50114	clearTarget: function ( renderTarget, color, depth, stencil ) {
50115
50116		console.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );
50117		this.setRenderTarget( renderTarget );
50118		this.clear( color, depth, stencil );
50119
50120	},
50121	animate: function ( callback ) {
50122
50123		console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );
50124		this.setAnimationLoop( callback );
50125
50126	},
50127	getCurrentRenderTarget: function () {
50128
50129		console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );
50130		return this.getRenderTarget();
50131
50132	},
50133	getMaxAnisotropy: function () {
50134
50135		console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );
50136		return this.capabilities.getMaxAnisotropy();
50137
50138	},
50139	getPrecision: function () {
50140
50141		console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );
50142		return this.capabilities.precision;
50143
50144	},
50145	resetGLState: function () {
50146
50147		console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );
50148		return this.state.reset();
50149
50150	},
50151	supportsFloatTextures: function () {
50152
50153		console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' );
50154		return this.extensions.get( 'OES_texture_float' );
50155
50156	},
50157	supportsHalfFloatTextures: function () {
50158
50159		console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' );
50160		return this.extensions.get( 'OES_texture_half_float' );
50161
50162	},
50163	supportsStandardDerivatives: function () {
50164
50165		console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' );
50166		return this.extensions.get( 'OES_standard_derivatives' );
50167
50168	},
50169	supportsCompressedTextureS3TC: function () {
50170
50171		console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' );
50172		return this.extensions.get( 'WEBGL_compressed_texture_s3tc' );
50173
50174	},
50175	supportsCompressedTexturePVRTC: function () {
50176
50177		console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' );
50178		return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );
50179
50180	},
50181	supportsBlendMinMax: function () {
50182
50183		console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' );
50184		return this.extensions.get( 'EXT_blend_minmax' );
50185
50186	},
50187	supportsVertexTextures: function () {
50188
50189		console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );
50190		return this.capabilities.vertexTextures;
50191
50192	},
50193	supportsInstancedArrays: function () {
50194
50195		console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' );
50196		return this.extensions.get( 'ANGLE_instanced_arrays' );
50197
50198	},
50199	enableScissorTest: function ( boolean ) {
50200
50201		console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );
50202		this.setScissorTest( boolean );
50203
50204	},
50205	initMaterial: function () {
50206
50207		console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
50208
50209	},
50210	addPrePlugin: function () {
50211
50212		console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
50213
50214	},
50215	addPostPlugin: function () {
50216
50217		console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
50218
50219	},
50220	updateShadowMap: function () {
50221
50222		console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
50223
50224	},
50225	setFaceCulling: function () {
50226
50227		console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );
50228
50229	},
50230	allocTextureUnit: function () {
50231
50232		console.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );
50233
50234	},
50235	setTexture: function () {
50236
50237		console.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );
50238
50239	},
50240	setTexture2D: function () {
50241
50242		console.warn( 'THREE.WebGLRenderer: .setTexture2D() has been removed.' );
50243
50244	},
50245	setTextureCube: function () {
50246
50247		console.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );
50248
50249	},
50250	getActiveMipMapLevel: function () {
50251
50252		console.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );
50253		return this.getActiveMipmapLevel();
50254
50255	}
50256
50257} );
50258
50259Object.defineProperties( WebGLRenderer.prototype, {
50260
50261	shadowMapEnabled: {
50262		get: function () {
50263
50264			return this.shadowMap.enabled;
50265
50266		},
50267		set: function ( value ) {
50268
50269			console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
50270			this.shadowMap.enabled = value;
50271
50272		}
50273	},
50274	shadowMapType: {
50275		get: function () {
50276
50277			return this.shadowMap.type;
50278
50279		},
50280		set: function ( value ) {
50281
50282			console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
50283			this.shadowMap.type = value;
50284
50285		}
50286	},
50287	shadowMapCullFace: {
50288		get: function () {
50289
50290			console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
50291			return undefined;
50292
50293		},
50294		set: function ( /* value */ ) {
50295
50296			console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );
50297
50298		}
50299	},
50300	context: {
50301		get: function () {
50302
50303			console.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );
50304			return this.getContext();
50305
50306		}
50307	},
50308	vr: {
50309		get: function () {
50310
50311			console.warn( 'THREE.WebGLRenderer: .vr has been renamed to .xr' );
50312			return this.xr;
50313
50314		}
50315	},
50316	gammaInput: {
50317		get: function () {
50318
50319			console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
50320			return false;
50321
50322		},
50323		set: function () {
50324
50325			console.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Set the encoding for textures via Texture.encoding instead.' );
50326
50327		}
50328	},
50329	gammaOutput: {
50330		get: function () {
50331
50332			console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
50333			return false;
50334
50335		},
50336		set: function ( value ) {
50337
50338			console.warn( 'THREE.WebGLRenderer: .gammaOutput has been removed. Set WebGLRenderer.outputEncoding instead.' );
50339			this.outputEncoding = ( value === true ) ? sRGBEncoding : LinearEncoding;
50340
50341		}
50342	}
50343
50344} );
50345
50346Object.defineProperties( WebGLShadowMap.prototype, {
50347
50348	cullFace: {
50349		get: function () {
50350
50351			console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
50352			return undefined;
50353
50354		},
50355		set: function ( /* cullFace */ ) {
50356
50357			console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );
50358
50359		}
50360	},
50361	renderReverseSided: {
50362		get: function () {
50363
50364			console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
50365			return undefined;
50366
50367		},
50368		set: function () {
50369
50370			console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );
50371
50372		}
50373	},
50374	renderSingleSided: {
50375		get: function () {
50376
50377			console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
50378			return undefined;
50379
50380		},
50381		set: function () {
50382
50383			console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );
50384
50385		}
50386	}
50387
50388} );
50389
50390function WebGLRenderTargetCube( width, height, options ) {
50391
50392	console.warn( 'THREE.WebGLRenderTargetCube( width, height, options ) is now WebGLCubeRenderTarget( size, options ).' );
50393	return new WebGLCubeRenderTarget( width, options );
50394
50395}
50396
50397//
50398
50399Object.defineProperties( WebGLRenderTarget.prototype, {
50400
50401	wrapS: {
50402		get: function () {
50403
50404			console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
50405			return this.texture.wrapS;
50406
50407		},
50408		set: function ( value ) {
50409
50410			console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
50411			this.texture.wrapS = value;
50412
50413		}
50414	},
50415	wrapT: {
50416		get: function () {
50417
50418			console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
50419			return this.texture.wrapT;
50420
50421		},
50422		set: function ( value ) {
50423
50424			console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
50425			this.texture.wrapT = value;
50426
50427		}
50428	},
50429	magFilter: {
50430		get: function () {
50431
50432			console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
50433			return this.texture.magFilter;
50434
50435		},
50436		set: function ( value ) {
50437
50438			console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
50439			this.texture.magFilter = value;
50440
50441		}
50442	},
50443	minFilter: {
50444		get: function () {
50445
50446			console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
50447			return this.texture.minFilter;
50448
50449		},
50450		set: function ( value ) {
50451
50452			console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
50453			this.texture.minFilter = value;
50454
50455		}
50456	},
50457	anisotropy: {
50458		get: function () {
50459
vendor: 2,617 bytes, lines 50460-50584
50460			console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
50461			return this.texture.anisotropy;
50462
50463		},
50464		set: function ( value ) {
50465
50466			console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
50467			this.texture.anisotropy = value;
50468
50469		}
50470	},
50471	offset: {
50472		get: function () {
50473
50474			console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
50475			return this.texture.offset;
50476
50477		},
50478		set: function ( value ) {
50479
50480			console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
50481			this.texture.offset = value;
50482
50483		}
50484	},
50485	repeat: {
50486		get: function () {
50487
50488			console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
50489			return this.texture.repeat;
50490
50491		},
50492		set: function ( value ) {
50493
50494			console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
50495			this.texture.repeat = value;
50496
50497		}
50498	},
50499	format: {
50500		get: function () {
50501
50502			console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
50503			return this.texture.format;
50504
50505		},
50506		set: function ( value ) {
50507
50508			console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
50509			this.texture.format = value;
50510
50511		}
50512	},
50513	type: {
50514		get: function () {
50515
50516			console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
50517			return this.texture.type;
50518
50519		},
50520		set: function ( value ) {
50521
50522			console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
50523			this.texture.type = value;
50524
50525		}
50526	},
50527	generateMipmaps: {
50528		get: function () {
50529
50530			console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
50531			return this.texture.generateMipmaps;
50532
50533		},
50534		set: function ( value ) {
50535
50536			console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
50537			this.texture.generateMipmaps = value;
50538
50539		}
50540	}
50541
50542} );
50543
50544//
50545
50546Object.defineProperties( Audio.prototype, {
50547
50548	load: {
50549		value: function ( file ) {
50550
50551			console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );
50552			var scope = this;
50553			var audioLoader = new AudioLoader();
50554			audioLoader.load( file, function ( buffer ) {
50555
50556				scope.setBuffer( buffer );
50557
50558			} );
50559			return this;
50560
50561		}
50562	},
50563	startTime: {
50564		set: function () {
50565
50566			console.warn( 'THREE.Audio: .startTime is now .play( delay ).' );
50567
50568		}
50569	}
50570
50571} );
50572
50573AudioAnalyser.prototype.getData = function () {
50574
50575	console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );
50576	return this.getFrequencyData();
50577
50578};
50579
50580//
50581
50582CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {
50583
50584	console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update(
50584).' );
50585	return this.update( renderer, scene );
50586
50587};
50588
50589//
50590
50591var GeometryUtils = {
50592
50593	merge: function ( geometry1, geometry2, materialIndexOffset ) {
50594
50595		console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
50596		var matrix;
50597
50598		if ( geometry2.isMesh ) {
50599
50600			geometry2.matrixAutoUpdate && geometry2.updateMatrix();
50601
50602			matrix = geometry2.matrix;
50603			geometry2 = geometry2.geometry;
50604
50605		}
50606
50607		geometry1.merge( geometry2, matrix, materialIndexOffset );
50608
50609	},
50610
50611	center: function ( geometry ) {
50612
50613		console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
50614		return geometry.center();
50615
50616	}
50617
50618};
50619
50620ImageUtils.crossOrigin = undefined;
50621
50622ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {
50623
50624	console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );
50625
50626	var loader = new TextureLoader();
50627	loader.setCrossOrigin( this.crossOrigin );
50628
50629	var texture = loader.load( url, onLoad, undefined, onError );
50630
50631	if ( mapping ) texture.mapping = mapping;
50632
50633	return texture;
50634
50635};
50636
50637ImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {
50638
50639	console.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );
50640
50641	var loader = new CubeTextureLoader();
50642	loader.setCrossOrigin( this.crossOrigin );
50643
50644	var texture = loader.load( urls, onLoad, undefined, onError );
50645
50646	if ( mapping ) texture.mapping = mapping;
50647
50648	return texture;
50649
50650};
50651
50652ImageUtils.loadCompressedTexture = function () {
50653
50654	console.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );
50655
50656};
50657
50658ImageUtils.loadCompressedTextureCube = function () {
50659
50660	console.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );
50661
50662};
50663
50664//
50665
50666function CanvasRenderer() {
50667
50668	console.error( 'THREE.CanvasRenderer has been removed' );
50669
50670}
50671
50672//
50673
50674function JSONLoader() {
50675
50676	console.error( 'THREE.JSONLoader has been removed.' );
50677
50678}
50679
50680//
50681
50682var SceneUtils = {
50683
50684	createMultiMaterialObject: function ( /* geometry, materials */ ) {
50685
50686		console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
50687
50688	},
50689
50690	detach: function ( /* child, parent, scene */ ) {
50691
50692		console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
50693
50694	},
50695
50696	attach: function ( /* child, scene, parent */ ) {
50697
50698		console.error( 'THREE.SceneUtils has been moved to /examples/jsm/utils/SceneUtils.js' );
50699
50700	}
50701
50702};
50703
50704//
50705
50706function LensFlare() {
50707
50708	console.error( 'THREE.LensFlare has been moved to /examples/jsm/objects/Lensflare.js' );
50709
50710}
50711
50712if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
50713
50714	/* eslint-disable no-undef */
50715	__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
50716		revision: REVISION,
50717	} } ) );
50718	/* eslint-enable no-undef */
50719
50720}
50721
50722export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, AxisHelper, BackSide, BasicDepthPacking, BasicShadowMap, BinaryTextureLoader, Bone, BooleanKeyframeTrack, BoundingBoxHelper, Box2, Box3, Box3Helper, BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasRenderer, CanvasTexture, CatmullRomCurve3, CineonToneMapping, CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, ClosedSplineCurve3, Color, ColorKeyframeTrack, CompressedTexture, CompressedTextureLoader, ConeBufferGeometry, ConeGeometry, CubeCamera, BoxGeometry as CubeGeometry, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubeUVRefractionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CylinderBufferGeometry, CylinderGeometry, Cylindrical, DataTexture, DataTexture2DArray, DataTexture3D, DataTextureLoader, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DirectionalLightShadow, DiscreteInterpolant, DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicBufferAttribute, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EdgesHelper, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeBufferGeometry, ExtrudeGeometry, Face3, Face4, FaceColors, FileLoader, FlatShading, Float32Attribute, Float32BufferAttribute, Float64Attribute, Float64BufferAttribute, FloatType, Fog, FogExp2, Font, FontLoader, FrontFaceDirectionCCW, FrontFaceDirectionCW, FrontSide, Frustum, GammaEncoding, Geometry, GeometryUtils, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, ImmediateRenderObject, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16Attribute, Int16BufferAttribute, Int32Attribute, Int32BufferAttribute, Int8Attribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, JSONLoader, KeepStencilOp, KeyframeTrack, LOD, LatheBufferGeometry, LatheGeometry, Layers, LensFlare, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightShadow, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LinePieces, LineSegments, LineStrip, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LogLuvEncoding, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils as Math, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiMaterial, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColors, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, Orthogra
50722phicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, ParametricBufferGeometry, ParametricGeometry, Particle, ParticleBasicMaterial, ParticleSystem, ParticleSystemMaterial, Path, PerspectiveCamera, Plane, PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointCloud, PointCloudMaterial, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDEncoding, RGBEEncoding, RGBEFormat, RGBFormat, RGBIntegerFormat, RGBM16Encoding, RGBM7Encoding, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingBufferGeometry, RingGeometry, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, Scene, SceneUtils, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SmoothShading, Sphere, SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, SphericalReflectionMapping, Spline, SplineCurve, SplineCurve3, SpotLight, SpotLightHelper, SpotLightShadow, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronBufferGeometry, TetrahedronGeometry, TextBufferGeometry, TextGeometry, Texture, TextureLoader, TorusBufferGeometry, TorusGeometry, TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeBufferGeometry, TubeGeometry, UVMapping, Uint16Attribute, Uint16BufferAttribute, Uint32Attribute, Uint32BufferAttribute, Uint8Attribute, Uint8BufferAttribute, Uint8ClampedAttribute, Uint8ClampedBufferAttribute, Uncharted2ToneMapping, Uniform, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShort565Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, Vertex, VertexColors, VideoTexture, WebGLCubeRenderTarget, WebGLMultisampleRenderTarget, WebGLRenderTarget, WebGLRenderTargetCube, WebGLRenderer, WebGLUtils, WireframeGeometry, WireframeHelper, WrapAroundEnding, XHRLoader, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, sRGBEncoding };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.