PageSourceSearch

https://register-any-point.github.io/js/three.module.js

js register-any-point.github.io collected 2026-10-03 09:49:59 UTC 1,178,889 bytes, 50,441 lines download raw bytes

1/**
2 * @license
3 * Copyright 2010-2023 Three.js Authors
4 * SPDX-License-Identifier: MIT
5 */
6const REVISION = '150';
7const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
8const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
9const CullFaceNone = 0;
10const CullFaceBack = 1;
11const CullFaceFront = 2;
12const CullFaceFrontBack = 3;
13const BasicShadowMap = 0;
14const PCFShadowMap = 1;
15const PCFSoftShadowMap = 2;
16const VSMShadowMap = 3;
17const FrontSide = 0;
18const BackSide = 1;
19const DoubleSide = 2;
20const TwoPassDoubleSide = 2; // r149
21const NoBlending = 0;
22const NormalBlending = 1;
23const AdditiveBlending = 2;
24const SubtractiveBlending = 3;
25const MultiplyBlending = 4;
26const CustomBlending = 5;
27const AddEquation = 100;
28const SubtractEquation = 101;
29const ReverseSubtractEquation = 102;
30const MinEquation = 103;
31const MaxEquation = 104;
32const ZeroFactor = 200;
33const OneFactor = 201;
34const SrcColorFactor = 202;
35const OneMinusSrcColorFactor = 203;
36const SrcAlphaFactor = 204;
37const OneMinusSrcAlphaFactor = 205;
38const DstAlphaFactor = 206;
39const OneMinusDstAlphaFactor = 207;
40const DstColorFactor = 208;
41const OneMinusDstColorFactor = 209;
42const SrcAlphaSaturateFactor = 210;
43const NeverDepth = 0;
44const AlwaysDepth = 1;
45const LessDepth = 2;
46const LessEqualDepth = 3;
47const EqualDepth = 4;
48const GreaterEqualDepth = 5;
49const GreaterDepth = 6;
50const NotEqualDepth = 7;
51const MultiplyOperation = 0;
52const MixOperation = 1;
53const AddOperation = 2;
54const NoToneMapping = 0;
55const LinearToneMapping = 1;
56const ReinhardToneMapping = 2;
57const CineonToneMapping = 3;
58const ACESFilmicToneMapping = 4;
59const CustomToneMapping = 5;
60
61const UVMapping = 300;
62const CubeReflectionMapping = 301;
63const CubeRefractionMapping = 302;
64const EquirectangularReflectionMapping = 303;
65const EquirectangularRefractionMapping = 304;
66const CubeUVReflectionMapping = 306;
67const RepeatWrapping = 1000;
68const ClampToEdgeWrapping = 1001;
69const MirroredRepeatWrapping = 1002;
70const NearestFilter = 1003;
71const NearestMipmapNearestFilter = 1004;
72const NearestMipMapNearestFilter = 1004;
73const NearestMipmapLinearFilter = 1005;
74const NearestMipMapLinearFilter = 1005;
75const LinearFilter = 1006;
76const LinearMipmapNearestFilter = 1007;
77const LinearMipMapNearestFilter = 1007;
78const LinearMipmapLinearFilter = 1008;
79const LinearMipMapLinearFilter = 1008;
80const UnsignedByteType = 1009;
81const ByteType = 1010;
82const ShortType = 1011;
83const UnsignedShortType = 1012;
84const IntType = 1013;
85const UnsignedIntType = 1014;
86const FloatType = 1015;
87const HalfFloatType = 1016;
88const UnsignedShort4444Type = 1017;
89const UnsignedShort5551Type = 1018;
90const UnsignedInt248Type = 1020;
91const AlphaFormat = 1021;
92const RGBAFormat = 1023;
93const LuminanceFormat = 1024;
94const LuminanceAlphaFormat = 1025;
95const DepthFormat = 1026;
96const DepthStencilFormat = 1027;
97const RedFormat = 1028;
98const RedIntegerFormat = 1029;
99const RGFormat = 1030;
100const RGIntegerFormat = 1031;
101const RGBAIntegerFormat = 1033;
102
103const RGB_S3TC_DXT1_Format = 33776;
104const RGBA_S3TC_DXT1_Format = 33777;
105const RGBA_S3TC_DXT3_Format = 33778;
106const RGBA_S3TC_DXT5_Format = 33779;
107const RGB_PVRTC_4BPPV1_Format = 35840;
108const RGB_PVRTC_2BPPV1_Format = 35841;
109const RGBA_PVRTC_4BPPV1_Format = 35842;
110const RGBA_PVRTC_2BPPV1_Format = 35843;
111const RGB_ETC1_Format = 36196;
112const RGB_ETC2_Format = 37492;
113const RGBA_ETC2_EAC_Format = 37496;
114const RGBA_ASTC_4x4_Format = 37808;
115const RGBA_ASTC_5x4_Format = 37809;
116const RGBA_ASTC_5x5_Format = 37810;
117const RGBA_ASTC_6x5_Format = 37811;
118const RGBA_ASTC_6x6_Format = 37812;
119const RGBA_ASTC_8x5_Format = 37813;
120const RGBA_ASTC_8x6_Format = 37814;
121const RGBA_ASTC_8x8_Format = 37815;
122const RGBA_ASTC_10x5_Format = 37816;
123const RGBA_ASTC_10x6_Format = 37817;
124const RGBA_ASTC_10x8_Format = 37818;
125const RGBA_ASTC_10x10_Format = 37819;
126const RGBA_ASTC_12x10_Format = 37820;
127const RGBA_ASTC_12x12_Format = 37821;
128const RGBA_BPTC_Format = 36492;
129const RED_RGTC1_Format = 36283;
130const SIGNED_RED_RGTC1_Format = 36284;
131const RED_GREEN_RGTC2_Format = 36285;
132const SIGNED_RED_GREEN_RGTC2_Format = 36286;
133const LoopOnce = 2200;
134const LoopRepeat = 2201;
135const LoopPingPong = 2202;
136const InterpolateDiscrete = 2300;
137const InterpolateLinear = 2301;
138const InterpolateSmooth = 2302;
139const ZeroCurvatureEnding = 2400;
140const ZeroSlopeEnding = 2401;
141const WrapAroundEnding = 2402;
142const NormalAnimationBlendMode = 2500;
143const AdditiveAnimationBlendMode = 2501;
144const TrianglesDrawMode = 0;
145const TriangleStripDrawMode = 1;
146const TriangleFanDrawMode = 2;
147const LinearEncoding = 3000;
148const sRGBEncoding = 3001;
149const BasicDepthPacking = 3200;
150const RGBADepthPacking = 3201;
151const TangentSpaceNormalMap = 0;
152const ObjectSpaceNormalMap = 1;
153
154// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU n
vendor: 6,946 bytes, lines 154-403
154ames where available.
155const NoColorSpace = '';
156const SRGBColorSpace = 'srgb';
157const LinearSRGBColorSpace = 'srgb-linear';
158const DisplayP3ColorSpace = 'display-p3';
159
160const ZeroStencilOp = 0;
161const KeepStencilOp = 7680;
162const ReplaceStencilOp = 7681;
163const IncrementStencilOp = 7682;
164const DecrementStencilOp = 7683;
165const IncrementWrapStencilOp = 34055;
166const DecrementWrapStencilOp = 34056;
167const InvertStencilOp = 5386;
168
169const NeverStencilFunc = 512;
170const LessStencilFunc = 513;
171const EqualStencilFunc = 514;
172const LessEqualStencilFunc = 515;
173const GreaterStencilFunc = 516;
174const NotEqualStencilFunc = 517;
175const GreaterEqualStencilFunc = 518;
176const AlwaysStencilFunc = 519;
177
178const StaticDrawUsage = 35044;
179const DynamicDrawUsage = 35048;
180const StreamDrawUsage = 35040;
181const StaticReadUsage = 35045;
182const DynamicReadUsage = 35049;
183const StreamReadUsage = 35041;
184const StaticCopyUsage = 35046;
185const DynamicCopyUsage = 35050;
186const StreamCopyUsage = 35042;
187
188const GLSL1 = '100';
189const GLSL3 = '300 es';
190
191const _SRGBAFormat = 1035; // fallback for WebGL 1
192
193/**
194 * https://github.com/mrdoob/eventdispatcher.js/
195 */
196
197class EventDispatcher {
198
199	addEventListener( type, listener ) {
200
201		if ( this._listeners === undefined ) this._listeners = {};
202
203		const listeners = this._listeners;
204
205		if ( listeners[ type ] === undefined ) {
206
207			listeners[ type ] = [];
208
209		}
210
211		if ( listeners[ type ].indexOf( listener ) === - 1 ) {
212
213			listeners[ type ].push( listener );
214
215		}
216
217	}
218
219	hasEventListener( type, listener ) {
220
221		if ( this._listeners === undefined ) return false;
222
223		const listeners = this._listeners;
224
225		return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
226
227	}
228
229	removeEventListener( type, listener ) {
230
231		if ( this._listeners === undefined ) return;
232
233		const listeners = this._listeners;
234		const listenerArray = listeners[ type ];
235
236		if ( listenerArray !== undefined ) {
237
238			const index = listenerArray.indexOf( listener );
239
240			if ( index !== - 1 ) {
241
242				listenerArray.splice( index, 1 );
243
244			}
245
246		}
247
248	}
249
250	dispatchEvent( event ) {
251
252		if ( this._listeners === undefined ) return;
253
254		const listeners = this._listeners;
255		const listenerArray = listeners[ event.type ];
256
257		if ( listenerArray !== undefined ) {
258
259			event.target = this;
260
261			// Make a copy, in case listeners are removed while iterating.
262			const array = listenerArray.slice( 0 );
263
264			for ( let i = 0, l = array.length; i < l; i ++ ) {
265
266				array[ i ].call( this, event );
267
268			}
269
270			event.target = null;
271
272		}
273
274	}
275
276}
277
278const _lut = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff' ];
279
280let _seed = 1234567;
281
282
283const DEG2RAD = Math.PI / 180;
284const RAD2DEG = 180 / Math.PI;
285
286// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
287function generateUUID() {
288
289	const d0 = Math.random() * 0xffffffff | 0;
290	const d1 = Math.random() * 0xffffffff | 0;
291	const d2 = Math.random() * 0xffffffff | 0;
292	const d3 = Math.random() * 0xffffffff | 0;
293	const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
294			_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
295			_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
296			_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
297
298	// .toLowerCase() here flattens concatenated strings to save heap memory space.
299	return uuid.toLowerCase();
300
301}
302
303function clamp( value, min, max ) {
304
305	return Math.max( min, Math.min( max, value ) );
306
307}
308
309// compute euclidean modulo of m % n
310// https://en.wikipedia.org/wiki/Modulo_operation
311function euclideanModulo( n, m ) {
312
313	return ( ( n % m ) + m ) % m;
314
315}
316
317// Linear mapping from range <a1, a2> to range <b1, b2>
318function mapLinear( x, a1, a2, b1, b2 ) {
319
320	return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
321
322}
323
324// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
325function inverseLerp( x, y, value ) {
326
327	if ( x !== y ) {
328
329		return ( value - x ) / ( y - x );
330
331	} else {
332
333		return 0;
334
335	}
336
337}
338
339// https://en.wikipedia.org/wiki/Linear_interpolation
340function lerp( x, y, t ) {
341
342	return ( 1 - t ) * x + t * y;
343
344}
345
346// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
347function damp( x, y, lambda, dt ) {
348
349	return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
350
351}
352
353// https://www.desmos.com/calculator/vcsjnyz7x4
354function pingpong( x, length = 1 ) {
355
356	return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
357
358}
359
360// http://en.wikipedia.org/wiki/Smoothstep
361function smoothstep( x, min, max ) {
362
363	if ( x <= min ) return 0;
364	if ( x >= max ) return 1;
365
366	x = ( x - min ) / ( max - min );
367
368	return x * x * ( 3 - 2 * x );
369
370}
371
372function smootherstep( x, min, max ) {
373
374	if ( x <= min ) return 0;
375	if ( x >= max ) return 1;
376
377	x = ( x - min ) / ( max - min );
378
379	return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
380
381}
382
383// Random integer from <low, high> interval
384function randInt( low, high ) {
385
386	return low + Math.floor( Math.random() * ( high - low + 1 ) );
387
388}
389
390// Random float from <low, high> interval
391function randFloat( low, high ) {
392
393	return low + Math.random() * ( high - low );
394
395}
396
397// Random float from <-range/2, range/2> interval
398function randFloatSpread( range ) {
399
400	return range * ( 0.5 - Math.random() );
401
402}
403
vendor: 8,542 bytes, lines 404-1028
404// Deterministic pseudo-random float in the interval [ 0, 1 ]
405function seededRandom( s ) {
406
407	if ( s !== undefined ) _seed = s;
408
409	// Mulberry32 generator
410
411	let t = _seed += 0x6D2B79F5;
412
413	t = Math.imul( t ^ t >>> 15, t | 1 );
414
415	t ^= t + Math.imul( t ^ t >>> 7, t | 61 );
416
417	return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296;
418
419}
420
421function degToRad( degrees ) {
422
423	return degrees * DEG2RAD;
424
425}
426
427function radToDeg( radians ) {
428
429	return radians * RAD2DEG;
430
431}
432
433function isPowerOfTwo( value ) {
434
435	return ( value & ( value - 1 ) ) === 0 && value !== 0;
436
437}
438
439function ceilPowerOfTwo( value ) {
440
441	return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
442
443}
444
445function floorPowerOfTwo( value ) {
446
447	return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
448
449}
450
451function setQuaternionFromProperEuler( q, a, b, c, order ) {
452
453	// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
454
455	// rotations are applied to the axes in the order specified by 'order'
456	// rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
457	// angles are in radians
458
459	const cos = Math.cos;
460	const sin = Math.sin;
461
462	const c2 = cos( b / 2 );
463	const s2 = sin( b / 2 );
464
465	const c13 = cos( ( a + c ) / 2 );
466	const s13 = sin( ( a + c ) / 2 );
467
468	const c1_3 = cos( ( a - c ) / 2 );
469	const s1_3 = sin( ( a - c ) / 2 );
470
471	const c3_1 = cos( ( c - a ) / 2 );
472	const s3_1 = sin( ( c - a ) / 2 );
473
474	switch ( order ) {
475
476		case 'XYX':
477			q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
478			break;
479
480		case 'YZY':
481			q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
482			break;
483
484		case 'ZXZ':
485			q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
486			break;
487
488		case 'XZX':
489			q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
490			break;
491
492		case 'YXY':
493			q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
494			break;
495
496		case 'ZYZ':
497			q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
498			break;
499
500		default:
501			console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
502
503	}
504
505}
506
507function denormalize( value, array ) {
508
509	switch ( array.constructor ) {
510
511		case Float32Array:
512
513			return value;
514
515		case Uint16Array:
516
517			return value / 65535.0;
518
519		case Uint8Array:
520
521			return value / 255.0;
522
523		case Int16Array:
524
525			return Math.max( value / 32767.0, - 1.0 );
526
527		case Int8Array:
528
529			return Math.max( value / 127.0, - 1.0 );
530
531		default:
532
533			throw new Error( 'Invalid component type.' );
534
535	}
536
537}
538
539function normalize( value, array ) {
540
541	switch ( array.constructor ) {
542
543		case Float32Array:
544
545			return value;
546
547		case Uint16Array:
548
549			return Math.round( value * 65535.0 );
550
551		case Uint8Array:
552
553			return Math.round( value * 255.0 );
554
555		case Int16Array:
556
557			return Math.round( value * 32767.0 );
558
559		case Int8Array:
560
561			return Math.round( value * 127.0 );
562
563		default:
564
565			throw new Error( 'Invalid component type.' );
566
567	}
568
569}
570
571const MathUtils = {
572	DEG2RAD: DEG2RAD,
573	RAD2DEG: RAD2DEG,
574	generateUUID: generateUUID,
575	clamp: clamp,
576	euclideanModulo: euclideanModulo,
577	mapLinear: mapLinear,
578	inverseLerp: inverseLerp,
579	lerp: lerp,
580	damp: damp,
581	pingpong: pingpong,
582	smoothstep: smoothstep,
583	smootherstep: smootherstep,
584	randInt: randInt,
585	randFloat: randFloat,
586	randFloatSpread: randFloatSpread,
587	seededRandom: seededRandom,
588	degToRad: degToRad,
589	radToDeg: radToDeg,
590	isPowerOfTwo: isPowerOfTwo,
591	ceilPowerOfTwo: ceilPowerOfTwo,
592	floorPowerOfTwo: floorPowerOfTwo,
593	setQuaternionFromProperEuler: setQuaternionFromProperEuler,
594	normalize: normalize,
595	denormalize: denormalize
596};
597
598class Vector2 {
599
600	constructor( x = 0, y = 0 ) {
601
602		Vector2.prototype.isVector2 = true;
603
604		this.x = x;
605		this.y = y;
606
607	}
608
609	get width() {
610
611		return this.x;
612
613	}
614
615	set width( value ) {
616
617		this.x = value;
618
619	}
620
621	get height() {
622
623		return this.y;
624
625	}
626
627	set height( value ) {
628
629		this.y = value;
630
631	}
632
633	set( x, y ) {
634
635		this.x = x;
636		this.y = y;
637
638		return this;
639
640	}
641
642	setScalar( scalar ) {
643
644		this.x = scalar;
645		this.y = scalar;
646
647		return this;
648
649	}
650
651	setX( x ) {
652
653		this.x = x;
654
655		return this;
656
657	}
658
659	setY( y ) {
660
661		this.y = y;
662
663		return this;
664
665	}
666
667	setComponent( index, value ) {
668
669		switch ( index ) {
670
671			case 0: this.x = value; break;
672			case 1: this.y = value; break;
673			default: throw new Error( 'index is out of range: ' + index );
674
675		}
676
677		return this;
678
679	}
680
681	getComponent( index ) {
682
683		switch ( index ) {
684
685			case 0: return this.x;
686			case 1: return this.y;
687			default: throw new Error( 'index is out of range: ' + index );
688
689		}
690
691	}
692
693	clone() {
694
695		return new this.constructor( this.x, this.y );
696
697	}
698
699	copy( v ) {
700
701		this.x = v.x;
702		this.y = v.y;
703
704		return this;
705
706	}
707
708	add( v ) {
709
710		this.x += v.x;
711		this.y += v.y;
712
713		return this;
714
715	}
716
717	addScalar( s ) {
718
719		this.x += s;
720		this.y += s;
721
722		return this;
723
724	}
725
726	addVectors( a, b ) {
727
728		this.x = a.x + b.x;
729		this.y = a.y + b.y;
730
731		return this;
732
733	}
734
735	addScaledVector( v, s ) {
736
737		this.x += v.x * s;
738		this.y += v.y * s;
739
740		return this;
741
742	}
743
744	sub( v ) {
745
746		this.x -= v.x;
747		this.y -= v.y;
748
749		return this;
750
751	}
752
753	subScalar( s ) {
754
755		this.x -= s;
756		this.y -= s;
757
758		return this;
759
760	}
761
762	subVectors( a, b ) {
763
764		this.x = a.x - b.x;
765		this.y = a.y - b.y;
766
767		return this;
768
769	}
770
771	multiply( v ) {
772
773		this.x *= v.x;
774		this.y *= v.y;
775
776		return this;
777
778	}
779
780	multiplyScalar( scalar ) {
781
782		this.x *= scalar;
783		this.y *= scalar;
784
785		return this;
786
787	}
788
789	divide( v ) {
790
791		this.x /= v.x;
792		this.y /= v.y;
793
794		return this;
795
796	}
797
798	divideScalar( scalar ) {
799
800		return this.multiplyScalar( 1 / scalar );
801
802	}
803
804	applyMatrix3( m ) {
805
806		const x = this.x, y = this.y;
807		const e = m.elements;
808
809		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
810		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
811
812		return this;
813
814	}
815
816	min( v ) {
817
818		this.x = Math.min( this.x, v.x );
819		this.y = Math.min( this.y, v.y );
820
821		return this;
822
823	}
824
825	max( v ) {
826
827		this.x = Math.max( this.x, v.x );
828		this.y = Math.max( this.y, v.y );
829
830		return this;
831
832	}
833
834	clamp( min, max ) {
835
836		// assumes min < max, componentwise
837
838		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
839		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
840
841		return this;
842
843	}
844
845	clampScalar( minVal, maxVal ) {
846
847		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
848		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
849
850		return this;
851
852	}
853
854	clampLength( min, max ) {
855
856		const length = this.length();
857
858		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
859
860	}
861
862	floor() {
863
864		this.x = Math.floor( this.x );
865		this.y = Math.floor( this.y );
866
867		return this;
868
869	}
870
871	ceil() {
872
873		this.x = Math.ceil( this.x );
874		this.y = Math.ceil( this.y );
875
876		return this;
877
878	}
879
880	round() {
881
882		this.x = Math.round( this.x );
883		this.y = Math.round( this.y );
884
885		return this;
886
887	}
888
889	roundToZero() {
890
891		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
892		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
893
894		return this;
895
896	}
897
898	negate() {
899
900		this.x = - this.x;
901		this.y = - this.y;
902
903		return this;
904
905	}
906
907	dot( v ) {
908
909		return this.x * v.x + this.y * v.y;
910
911	}
912
913	cross( v ) {
914
915		return this.x * v.y - this.y * v.x;
916
917	}
918
919	lengthSq() {
920
921		return this.x * this.x + this.y * this.y;
922
923	}
924
925	length() {
926
927		return Math.sqrt( this.x * this.x + this.y * this.y );
928
929	}
930
931	manhattanLength() {
932
933		return Math.abs( this.x ) + Math.abs( this.y );
934
935	}
936
937	normalize() {
938
939		return this.divideScalar( this.length() || 1 );
940
941	}
942
943	angle() {
944
945		// computes the angle in radians with respect to the positive x-axis
946
947		const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
948
949		return angle;
950
951	}
952
953	distanceTo( v ) {
954
955		return Math.sqrt( this.distanceToSquared( v ) );
956
957	}
958
959	distanceToSquared( v ) {
960
961		const dx = this.x - v.x, dy = this.y - v.y;
962		return dx * dx + dy * dy;
963
964	}
965
966	manhattanDistanceTo( v ) {
967
968		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
969
970	}
971
972	setLength( length ) {
973
974		return this.normalize().multiplyScalar( length );
975
976	}
977
978	lerp( v, alpha ) {
979
980		this.x += ( v.x - this.x ) * alpha;
981		this.y += ( v.y - this.y ) * alpha;
982
983		return this;
984
985	}
986
987	lerpVectors( v1, v2, alpha ) {
988
989		this.x = v1.x + ( v2.x - v1.x ) * alpha;
990		this.y = v1.y + ( v2.y - v1.y ) * alpha;
991
992		return this;
993
994	}
995
996	equals( v ) {
997
998		return ( ( v.x === this.x ) && ( v.y === this.y ) );
999
1000	}
1001
1002	fromArray( array, offset = 0 ) {
1003
1004		this.x = array[ offset ];
1005		this.y = array[ offset + 1 ];
1006
1007		return this;
1008
1009	}
1010
1011	toArray( array = [], offset = 0 ) {
1012
1013		array[ offset ] = this.x;
1014		array[ offset + 1 ] = this.y;
1015
1016		return array;
1017
1018	}
1019
1020	fromBufferAttribute( attribute, index ) {
1021
1022		this.x = attribute.getX( index );
1023		this.y = attribute.getY( index );
1024
1025		return this;
1026
1027	}
1028
vendor: 4,496 bytes, lines 1029-1284
1029	rotateAround( center, angle ) {
1030
1031		const c = Math.cos( angle ), s = Math.sin( angle );
1032
1033		const x = this.x - center.x;
1034		const y = this.y - center.y;
1035
1036		this.x = x * c - y * s + center.x;
1037		this.y = x * s + y * c + center.y;
1038
1039		return this;
1040
1041	}
1042
1043	random() {
1044
1045		this.x = Math.random();
1046		this.y = Math.random();
1047
1048		return this;
1049
1050	}
1051
1052	*[ Symbol.iterator ]() {
1053
1054		yield this.x;
1055		yield this.y;
1056
1057	}
1058
1059}
1060
1061class Matrix3 {
1062
1063	constructor() {
1064
1065		Matrix3.prototype.isMatrix3 = true;
1066
1067		this.elements = [
1068
1069			1, 0, 0,
1070			0, 1, 0,
1071			0, 0, 1
1072
1073		];
1074
1075	}
1076
1077	set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1078
1079		const te = this.elements;
1080
1081		te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
1082		te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
1083		te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
1084
1085		return this;
1086
1087	}
1088
1089	identity() {
1090
1091		this.set(
1092
1093			1, 0, 0,
1094			0, 1, 0,
1095			0, 0, 1
1096
1097		);
1098
1099		return this;
1100
1101	}
1102
1103	copy( m ) {
1104
1105		const te = this.elements;
1106		const me = m.elements;
1107
1108		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
1109		te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
1110		te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
1111
1112		return this;
1113
1114	}
1115
1116	extractBasis( xAxis, yAxis, zAxis ) {
1117
1118		xAxis.setFromMatrix3Column( this, 0 );
1119		yAxis.setFromMatrix3Column( this, 1 );
1120		zAxis.setFromMatrix3Column( this, 2 );
1121
1122		return this;
1123
1124	}
1125
1126	setFromMatrix4( m ) {
1127
1128		const me = m.elements;
1129
1130		this.set(
1131
1132			me[ 0 ], me[ 4 ], me[ 8 ],
1133			me[ 1 ], me[ 5 ], me[ 9 ],
1134			me[ 2 ], me[ 6 ], me[ 10 ]
1135
1136		);
1137
1138		return this;
1139
1140	}
1141
1142	multiply( m ) {
1143
1144		return this.multiplyMatrices( this, m );
1145
1146	}
1147
1148	premultiply( m ) {
1149
1150		return this.multiplyMatrices( m, this );
1151
1152	}
1153
1154	multiplyMatrices( a, b ) {
1155
1156		const ae = a.elements;
1157		const be = b.elements;
1158		const te = this.elements;
1159
1160		const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
1161		const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
1162		const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
1163
1164		const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
1165		const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
1166		const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
1167
1168		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
1169		te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
1170		te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
1171
1172		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
1173		te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
1174		te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
1175
1176		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
1177		te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
1178		te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
1179
1180		return this;
1181
1182	}
1183
1184	multiplyScalar( s ) {
1185
1186		const te = this.elements;
1187
1188		te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
1189		te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
1190		te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
1191
1192		return this;
1193
1194	}
1195
1196	determinant() {
1197
1198		const te = this.elements;
1199
1200		const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
1201			d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
1202			g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
1203
1204		return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
1205
1206	}
1207
1208	invert() {
1209
1210		const te = this.elements,
1211
1212			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
1213			n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
1214			n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
1215
1216			t11 = n33 * n22 - n32 * n23,
1217			t12 = n32 * n13 - n33 * n12,
1218			t13 = n23 * n12 - n22 * n13,
1219
1220			det = n11 * t11 + n21 * t12 + n31 * t13;
1221
1222		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1223
1224		const detInv = 1 / det;
1225
1226		te[ 0 ] = t11 * detInv;
1227		te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
1228		te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
1229
1230		te[ 3 ] = t12 * detInv;
1231		te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
1232		te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
1233
1234		te[ 6 ] = t13 * detInv;
1235		te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
1236		te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
1237
1238		return this;
1239
1240	}
1241
1242	transpose() {
1243
1244		let tmp;
1245		const m = this.elements;
1246
1247		tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
1248		tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
1249		tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
1250
1251		return this;
1252
1253	}
1254
1255	getNormalMatrix( matrix4 ) {
1256
1257		return this.setFromMatrix4( matrix4 ).invert().transpose();
1258
1259	}
1260
1261	transposeIntoArray( r ) {
1262
1263		const m = this.elements;
1264
1265		r[ 0 ] = m[ 0 ];
1266		r[ 1 ] = m[ 3 ];
1267		r[ 2 ] = m[ 6 ];
1268		r[ 3 ] = m[ 1 ];
1269		r[ 4 ] = m[ 4 ];
1270		r[ 5 ] = m[ 7 ];
1271		r[ 6 ] = m[ 2 ];
1272		r[ 7 ] = m[ 5 ];
1273		r[ 8 ] = m[ 8 ];
1274
1275		return this;
1276
1277	}
1278
1279	setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
1280
1281		const c = Math.cos( rotation );
1282		const s = Math.sin( rotation );
1283
1284		this.set(
vendor: 16,384 bytes, lines 1285-2286
1285			sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
1286			- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
1287			0, 0, 1
1288		);
1289
1290		return this;
1291
1292	}
1293
1294	//
1295
1296	scale( sx, sy ) {
1297
1298		this.premultiply( _m3.makeScale( sx, sy ) );
1299
1300		return this;
1301
1302	}
1303
1304	rotate( theta ) {
1305
1306		this.premultiply( _m3.makeRotation( - theta ) );
1307
1308		return this;
1309
1310	}
1311
1312	translate( tx, ty ) {
1313
1314		this.premultiply( _m3.makeTranslation( tx, ty ) );
1315
1316		return this;
1317
1318	}
1319
1320	// for 2D Transforms
1321
1322	makeTranslation( x, y ) {
1323
1324		this.set(
1325
1326			1, 0, x,
1327			0, 1, y,
1328			0, 0, 1
1329
1330		);
1331
1332		return this;
1333
1334	}
1335
1336	makeRotation( theta ) {
1337
1338		// counterclockwise
1339
1340		const c = Math.cos( theta );
1341		const s = Math.sin( theta );
1342
1343		this.set(
1344
1345			c, - s, 0,
1346			s, c, 0,
1347			0, 0, 1
1348
1349		);
1350
1351		return this;
1352
1353	}
1354
1355	makeScale( x, y ) {
1356
1357		this.set(
1358
1359			x, 0, 0,
1360			0, y, 0,
1361			0, 0, 1
1362
1363		);
1364
1365		return this;
1366
1367	}
1368
1369	//
1370
1371	equals( matrix ) {
1372
1373		const te = this.elements;
1374		const me = matrix.elements;
1375
1376		for ( let i = 0; i < 9; i ++ ) {
1377
1378			if ( te[ i ] !== me[ i ] ) return false;
1379
1380		}
1381
1382		return true;
1383
1384	}
1385
1386	fromArray( array, offset = 0 ) {
1387
1388		for ( let i = 0; i < 9; i ++ ) {
1389
1390			this.elements[ i ] = array[ i + offset ];
1391
1392		}
1393
1394		return this;
1395
1396	}
1397
1398	toArray( array = [], offset = 0 ) {
1399
1400		const te = this.elements;
1401
1402		array[ offset ] = te[ 0 ];
1403		array[ offset + 1 ] = te[ 1 ];
1404		array[ offset + 2 ] = te[ 2 ];
1405
1406		array[ offset + 3 ] = te[ 3 ];
1407		array[ offset + 4 ] = te[ 4 ];
1408		array[ offset + 5 ] = te[ 5 ];
1409
1410		array[ offset + 6 ] = te[ 6 ];
1411		array[ offset + 7 ] = te[ 7 ];
1412		array[ offset + 8 ] = te[ 8 ];
1413
1414		return array;
1415
1416	}
1417
1418	clone() {
1419
1420		return new this.constructor().fromArray( this.elements );
1421
1422	}
1423
1424}
1425
1426const _m3 = /*@__PURE__*/ new Matrix3();
1427
1428function arrayNeedsUint32( array ) {
1429
1430	// assumes larger values usually on last
1431
1432	for ( let i = array.length - 1; i >= 0; -- i ) {
1433
1434		if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
1435
1436	}
1437
1438	return false;
1439
1440}
1441
1442const TYPED_ARRAYS = {
1443	Int8Array: Int8Array,
1444	Uint8Array: Uint8Array,
1445	Uint8ClampedArray: Uint8ClampedArray,
1446	Int16Array: Int16Array,
1447	Uint16Array: Uint16Array,
1448	Int32Array: Int32Array,
1449	Uint32Array: Uint32Array,
1450	Float32Array: Float32Array,
1451	Float64Array: Float64Array
1452};
1453
1454function getTypedArray( type, buffer ) {
1455
1456	return new TYPED_ARRAYS[ type ]( buffer );
1457
1458}
1459
1460function createElementNS( name ) {
1461
1462	return document.createElementNS( 'http://www.w3.org/1999/xhtml', name );
1463
1464}
1465
1466class Quaternion {
1467
1468	constructor( x = 0, y = 0, z = 0, w = 1 ) {
1469
1470		this.isQuaternion = true;
1471
1472		this._x = x;
1473		this._y = y;
1474		this._z = z;
1475		this._w = w;
1476
1477	}
1478
1479	static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
1480
1481		// fuzz-free, array-based Quaternion SLERP operation
1482
1483		let x0 = src0[ srcOffset0 + 0 ],
1484			y0 = src0[ srcOffset0 + 1 ],
1485			z0 = src0[ srcOffset0 + 2 ],
1486			w0 = src0[ srcOffset0 + 3 ];
1487
1488		const x1 = src1[ srcOffset1 + 0 ],
1489			y1 = src1[ srcOffset1 + 1 ],
1490			z1 = src1[ srcOffset1 + 2 ],
1491			w1 = src1[ srcOffset1 + 3 ];
1492
1493		if ( t === 0 ) {
1494
1495			dst[ dstOffset + 0 ] = x0;
1496			dst[ dstOffset + 1 ] = y0;
1497			dst[ dstOffset + 2 ] = z0;
1498			dst[ dstOffset + 3 ] = w0;
1499			return;
1500
1501		}
1502
1503		if ( t === 1 ) {
1504
1505			dst[ dstOffset + 0 ] = x1;
1506			dst[ dstOffset + 1 ] = y1;
1507			dst[ dstOffset + 2 ] = z1;
1508			dst[ dstOffset + 3 ] = w1;
1509			return;
1510
1511		}
1512
1513		if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
1514
1515			let s = 1 - t;
1516			const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
1517				dir = ( cos >= 0 ? 1 : - 1 ),
1518				sqrSin = 1 - cos * cos;
1519
1520			// Skip the Slerp for tiny steps to avoid numeric problems:
1521			if ( sqrSin > Number.EPSILON ) {
1522
1523				const sin = Math.sqrt( sqrSin ),
1524					len = Math.atan2( sin, cos * dir );
1525
1526				s = Math.sin( s * len ) / sin;
1527				t = Math.sin( t * len ) / sin;
1528
1529			}
1530
1531			const tDir = t * dir;
1532
1533			x0 = x0 * s + x1 * tDir;
1534			y0 = y0 * s + y1 * tDir;
1535			z0 = z0 * s + z1 * tDir;
1536			w0 = w0 * s + w1 * tDir;
1537
1538			// Normalize in case we just did a lerp:
1539			if ( s === 1 - t ) {
1540
1541				const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
1542
1543				x0 *= f;
1544				y0 *= f;
1545				z0 *= f;
1546				w0 *= f;
1547
1548			}
1549
1550		}
1551
1552		dst[ dstOffset ] = x0;
1553		dst[ dstOffset + 1 ] = y0;
1554		dst[ dstOffset + 2 ] = z0;
1555		dst[ dstOffset + 3 ] = w0;
1556
1557	}
1558
1559	static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
1560
1561		const x0 = src0[ srcOffset0 ];
1562		const y0 = src0[ srcOffset0 + 1 ];
1563		const z0 = src0[ srcOffset0 + 2 ];
1564		const w0 = src0[ srcOffset0 + 3 ];
1565
1566		const x1 = src1[ srcOffset1 ];
1567		const y1 = src1[ srcOffset1 + 1 ];
1568		const z1 = src1[ srcOffset1 + 2 ];
1569		const w1 = src1[ srcOffset1 + 3 ];
1570
1571		dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
1572		dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
1573		dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
1574		dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
1575
1576		return dst;
1577
1578	}
1579
1580	get x() {
1581
1582		return this._x;
1583
1584	}
1585
1586	set x( value ) {
1587
1588		this._x = value;
1589		this._onChangeCallback();
1590
1591	}
1592
1593	get y() {
1594
1595		return this._y;
1596
1597	}
1598
1599	set y( value ) {
1600
1601		this._y = value;
1602		this._onChangeCallback();
1603
1604	}
1605
1606	get z() {
1607
1608		return this._z;
1609
1610	}
1611
1612	set z( value ) {
1613
1614		this._z = value;
1615		this._onChangeCallback();
1616
1617	}
1618
1619	get w() {
1620
1621		return this._w;
1622
1623	}
1624
1625	set w( value ) {
1626
1627		this._w = value;
1628		this._onChangeCallback();
1629
1630	}
1631
1632	set( x, y, z, w ) {
1633
1634		this._x = x;
1635		this._y = y;
1636		this._z = z;
1637		this._w = w;
1638
1639		this._onChangeCallback();
1640
1641		return this;
1642
1643	}
1644
1645	clone() {
1646
1647		return new this.constructor( this._x, this._y, this._z, this._w );
1648
1649	}
1650
1651	copy( quaternion ) {
1652
1653		this._x = quaternion.x;
1654		this._y = quaternion.y;
1655		this._z = quaternion.z;
1656		this._w = quaternion.w;
1657
1658		this._onChangeCallback();
1659
1660		return this;
1661
1662	}
1663
1664	setFromEuler( euler, update ) {
1665
1666		const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
1667
1668		// http://www.mathworks.com/matlabcentral/fileexchange/
1669		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
1670		//	content/SpinCalc.m
1671
1672		const cos = Math.cos;
1673		const sin = Math.sin;
1674
1675		const c1 = cos( x / 2 );
1676		const c2 = cos( y / 2 );
1677		const c3 = cos( z / 2 );
1678
1679		const s1 = sin( x / 2 );
1680		const s2 = sin( y / 2 );
1681		const s3 = sin( z / 2 );
1682
1683		switch ( order ) {
1684
1685			case 'XYZ':
1686				this._x = s1 * c2 * c3 + c1 * s2 * s3;
1687				this._y = c1 * s2 * c3 - s1 * c2 * s3;
1688				this._z = c1 * c2 * s3 + s1 * s2 * c3;
1689				this._w = c1 * c2 * c3 - s1 * s2 * s3;
1690				break;
1691
1692			case 'YXZ':
1693				this._x = s1 * c2 * c3 + c1 * s2 * s3;
1694				this._y = c1 * s2 * c3 - s1 * c2 * s3;
1695				this._z = c1 * c2 * s3 - s1 * s2 * c3;
1696				this._w = c1 * c2 * c3 + s1 * s2 * s3;
1697				break;
1698
1699			case 'ZXY':
1700				this._x = s1 * c2 * c3 - c1 * s2 * s3;
1701				this._y = c1 * s2 * c3 + s1 * c2 * s3;
1702				this._z = c1 * c2 * s3 + s1 * s2 * c3;
1703				this._w = c1 * c2 * c3 - s1 * s2 * s3;
1704				break;
1705
1706			case 'ZYX':
1707				this._x = s1 * c2 * c3 - c1 * s2 * s3;
1708				this._y = c1 * s2 * c3 + s1 * c2 * s3;
1709				this._z = c1 * c2 * s3 - s1 * s2 * c3;
1710				this._w = c1 * c2 * c3 + s1 * s2 * s3;
1711				break;
1712
1713			case 'YZX':
1714				this._x = s1 * c2 * c3 + c1 * s2 * s3;
1715				this._y = c1 * s2 * c3 + s1 * c2 * s3;
1716				this._z = c1 * c2 * s3 - s1 * s2 * c3;
1717				this._w = c1 * c2 * c3 - s1 * s2 * s3;
1718				break;
1719
1720			case 'XZY':
1721				this._x = s1 * c2 * c3 - c1 * s2 * s3;
1722				this._y = c1 * s2 * c3 - s1 * c2 * s3;
1723				this._z = c1 * c2 * s3 + s1 * s2 * c3;
1724				this._w = c1 * c2 * c3 + s1 * s2 * s3;
1725				break;
1726
1727			default:
1728				console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
1729
1730		}
1731
1732		if ( update !== false ) this._onChangeCallback();
1733
1734		return this;
1735
1736	}
1737
1738	setFromAxisAngle( axis, angle ) {
1739
1740		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
1741
1742		// assumes axis is normalized
1743
1744		const halfAngle = angle / 2, s = Math.sin( halfAngle );
1745
1746		this._x = axis.x * s;
1747		this._y = axis.y * s;
1748		this._z = axis.z * s;
1749		this._w = Math.cos( halfAngle );
1750
1751		this._onChangeCallback();
1752
1753		return this;
1754
1755	}
1756
1757	setFromRotationMatrix( m ) {
1758
1759		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
1760
1761		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
1762
1763		const te = m.elements,
1764
1765			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
1766			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
1767			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
1768
1769			trace = m11 + m22 + m33;
1770
1771		if ( trace > 0 ) {
1772
1773			const s = 0.5 / Math.sqrt( trace + 1.0 );
1774
1775			this._w = 0.25 / s;
1776			this._x = ( m32 - m23 ) * s;
1777			this._y = ( m13 - m31 ) * s;
1778			this._z = ( m21 - m12 ) * s;
1779
1780		} else if ( m11 > m22 && m11 > m33 ) {
1781
1782			const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
1783
1784			this._w = ( m32 - m23 ) / s;
1785			this._x = 0.25 * s;
1786			this._y = ( m12 + m21 ) / s;
1787			this._z = ( m13 + m31 ) / s;
1788
1789		} else if ( m22 > m33 ) {
1790
1791			const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
1792
1793			this._w = ( m13 - m31 ) / s;
1794			this._x = ( m12 + m21 ) / s;
1795			this._y = 0.25 * s;
1796			this._z = ( m23 + m32 ) / s;
1797
1798		} else {
1799
1800			const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
1801
1802			this._w = ( m21 - m12 ) / s;
1803			this._x = ( m13 + m31 ) / s;
1804			this._y = ( m23 + m32 ) / s;
1805			this._z = 0.25 * s;
1806
1807		}
1808
1809		this._onChangeCallback();
1810
1811		return this;
1812
1813	}
1814
1815	setFromUnitVectors( vFrom, vTo ) {
1816
1817		// assumes direction vectors vFrom and vTo are normalized
1818
1819		let r = vFrom.dot( vTo ) + 1;
1820
1821		if ( r < Number.EPSILON ) {
1822
1823			// vFrom and vTo point in opposite directions
1824
1825			r = 0;
1826
1827			if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
1828
1829				this._x = - vFrom.y;
1830				this._y = vFrom.x;
1831				this._z = 0;
1832				this._w = r;
1833
1834			} else {
1835
1836				this._x = 0;
1837				this._y = - vFrom.z;
1838				this._z = vFrom.y;
1839				this._w = r;
1840
1841			}
1842
1843		} else {
1844
1845			// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
1846
1847			this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
1848			this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
1849			this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
1850			this._w = r;
1851
1852		}
1853
1854		return this.normalize();
1855
1856	}
1857
1858	angleTo( q ) {
1859
1860		return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) );
1861
1862	}
1863
1864	rotateTowards( q, step ) {
1865
1866		const angle = this.angleTo( q );
1867
1868		if ( angle === 0 ) return this;
1869
1870		const t = Math.min( 1, step / angle );
1871
1872		this.slerp( q, t );
1873
1874		return this;
1875
1876	}
1877
1878	identity() {
1879
1880		return this.set( 0, 0, 0, 1 );
1881
1882	}
1883
1884	invert() {
1885
1886		// quaternion is assumed to have unit length
1887
1888		return this.conjugate();
1889
1890	}
1891
1892	conjugate() {
1893
1894		this._x *= - 1;
1895		this._y *= - 1;
1896		this._z *= - 1;
1897
1898		this._onChangeCallback();
1899
1900		return this;
1901
1902	}
1903
1904	dot( v ) {
1905
1906		return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
1907
1908	}
1909
1910	lengthSq() {
1911
1912		return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
1913
1914	}
1915
1916	length() {
1917
1918		return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
1919
1920	}
1921
1922	normalize() {
1923
1924		let l = this.length();
1925
1926		if ( l === 0 ) {
1927
1928			this._x = 0;
1929			this._y = 0;
1930			this._z = 0;
1931			this._w = 1;
1932
1933		} else {
1934
1935			l = 1 / l;
1936
1937			this._x = this._x * l;
1938			this._y = this._y * l;
1939			this._z = this._z * l;
1940			this._w = this._w * l;
1941
1942		}
1943
1944		this._onChangeCallback();
1945
1946		return this;
1947
1948	}
1949
1950	multiply( q ) {
1951
1952		return this.multiplyQuaternions( this, q );
1953
1954	}
1955
1956	premultiply( q ) {
1957
1958		return this.multiplyQuaternions( q, this );
1959
1960	}
1961
1962	multiplyQuaternions( a, b ) {
1963
1964		// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
1965
1966		const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
1967		const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
1968
1969		this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
1970		this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
1971		this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
1972		this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
1973
1974		this._onChangeCallback();
1975
1976		return this;
1977
1978	}
1979
1980	slerp( qb, t ) {
1981
1982		if ( t === 0 ) return this;
1983		if ( t === 1 ) return this.copy( qb );
1984
1985		const x = this._x, y = this._y, z = this._z, w = this._w;
1986
1987		// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
1988
1989		let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
1990
1991		if ( cosHalfTheta < 0 ) {
1992
1993			this._w = - qb._w;
1994			this._x = - qb._x;
1995			this._y = - qb._y;
1996			this._z = - qb._z;
1997
1998			cosHalfTheta = - cosHalfTheta;
1999
2000		} else {
2001
2002			this.copy( qb );
2003
2004		}
2005
2006		if ( cosHalfTheta >= 1.0 ) {
2007
2008			this._w = w;
2009			this._x = x;
2010			this._y = y;
2011			this._z = z;
2012
2013			return this;
2014
2015		}
2016
2017		const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
2018
2019		if ( sqrSinHalfTheta <= Number.EPSILON ) {
2020
2021			const s = 1 - t;
2022			this._w = s * w + t * this._w;
2023			this._x = s * x + t * this._x;
2024			this._y = s * y + t * this._y;
2025			this._z = s * z + t * this._z;
2026
2027			this.normalize();
2028			this._onChangeCallback();
2029
2030			return this;
2031
2032		}
2033
2034		const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
2035		const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
2036		const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
2037			ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
2038
2039		this._w = ( w * ratioA + this._w * ratioB );
2040		this._x = ( x * ratioA + this._x * ratioB );
2041		this._y = ( y * ratioA + this._y * ratioB );
2042		this._z = ( z * ratioA + this._z * ratioB );
2043
2044		this._onChangeCallback();
2045
2046		return this;
2047
2048	}
2049
2050	slerpQuaternions( qa, qb, t ) {
2051
2052		return this.copy( qa ).slerp( qb, t );
2053
2054	}
2055
2056	random() {
2057
2058		// Derived from http://planning.cs.uiuc.edu/node198.html
2059		// Note, this source uses w, x, y, z ordering,
2060		// so we swap the order below.
2061
2062		const u1 = Math.random();
2063		const sqrt1u1 = Math.sqrt( 1 - u1 );
2064		const sqrtu1 = Math.sqrt( u1 );
2065
2066		const u2 = 2 * Math.PI * Math.random();
2067
2068		const u3 = 2 * Math.PI * Math.random();
2069
2070		return this.set(
2071			sqrt1u1 * Math.cos( u2 ),
2072			sqrtu1 * Math.sin( u3 ),
2073			sqrtu1 * Math.cos( u3 ),
2074			sqrt1u1 * Math.sin( u2 ),
2075		);
2076
2077	}
2078
2079	equals( quaternion ) {
2080
2081		return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
2082
2083	}
2084
2085	fromArray( array, offset = 0 ) {
2086
2087		this._x = array[ offset ];
2088		this._y = array[ offset + 1 ];
2089		this._z = array[ offset + 2 ];
2090		this._w = array[ offset + 3 ];
2091
2092		this._onChangeCallback();
2093
2094		return this;
2095
2096	}
2097
2098	toArray( array = [], offset = 0 ) {
2099
2100		array[ offset ] = this._x;
2101		array[ offset + 1 ] = this._y;
2102		array[ offset + 2 ] = this._z;
2103		array[ offset + 3 ] = this._w;
2104
2105		return array;
2106
2107	}
2108
2109	fromBufferAttribute( attribute, index ) {
2110
2111		this._x = attribute.getX( index );
2112		this._y = attribute.getY( index );
2113		this._z = attribute.getZ( index );
2114		this._w = attribute.getW( index );
2115
2116		return this;
2117
2118	}
2119
2120	_onChange( callback ) {
2121
2122		this._onChangeCallback = callback;
2123
2124		return this;
2125
2126	}
2127
2128	_onChangeCallback() {}
2129
2130	*[ Symbol.iterator ]() {
2131
2132		yield this._x;
2133		yield this._y;
2134		yield this._z;
2135		yield this._w;
2136
2137	}
2138
2139}
2140
2141class Vector3 {
2142
2143	constructor( x = 0, y = 0, z = 0 ) {
2144
2145		Vector3.prototype.isVector3 = true;
2146
2147		this.x = x;
2148		this.y = y;
2149		this.z = z;
2150
2151	}
2152
2153	set( x, y, z ) {
2154
2155		if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
2156
2157		this.x = x;
2158		this.y = y;
2159		this.z = z;
2160
2161		return this;
2162
2163	}
2164
2165	setScalar( scalar ) {
2166
2167		this.x = scalar;
2168		this.y = scalar;
2169		this.z = scalar;
2170
2171		return this;
2172
2173	}
2174
2175	setX( x ) {
2176
2177		this.x = x;
2178
2179		return this;
2180
2181	}
2182
2183	setY( y ) {
2184
2185		this.y = y;
2186
2187		return this;
2188
2189	}
2190
2191	setZ( z ) {
2192
2193		this.z = z;
2194
2195		return this;
2196
2197	}
2198
2199	setComponent( index, value ) {
2200
2201		switch ( index ) {
2202
2203			case 0: this.x = value; break;
2204			case 1: this.y = value; break;
2205			case 2: this.z = value; break;
2206			default: throw new Error( 'index is out of range: ' + index );
2207
2208		}
2209
2210		return this;
2211
2212	}
2213
2214	getComponent( index ) {
2215
2216		switch ( index ) {
2217
2218			case 0: return this.x;
2219			case 1: return this.y;
2220			case 2: return this.z;
2221			default: throw new Error( 'index is out of range: ' + index );
2222
2223		}
2224
2225	}
2226
2227	clone() {
2228
2229		return new this.constructor( this.x, this.y, this.z );
2230
2231	}
2232
2233	copy( v ) {
2234
2235		this.x = v.x;
2236		this.y = v.y;
2237		this.z = v.z;
2238
2239		return this;
2240
2241	}
2242
2243	add( v ) {
2244
2245		this.x += v.x;
2246		this.y += v.y;
2247		this.z += v.z;
2248
2249		return this;
2250
2251	}
2252
2253	addScalar( s ) {
2254
2255		this.x += s;
2256		this.y += s;
2257		this.z += s;
2258
2259		return this;
2260
2261	}
2262
2263	addVectors( a, b ) {
2264
2265		this.x = a.x + b.x;
2266		this.y = a.y + b.y;
2267		this.z = a.z + b.z;
2268
2269		return this;
2270
2271	}
2272
2273	addScaledVector( v, s ) {
2274
2275		this.x += v.x * s;
2276		this.y += v.y * s;
2277		this.z += v.z * s;
2278
2279		return this;
2280
2281	}
2282
2283	sub( v ) {
2284
2285		this.x -= v.x;
2286		t
vendor: 7,286 bytes, lines 2286-2720
2286his.y -= v.y;
2287		this.z -= v.z;
2288
2289		return this;
2290
2291	}
2292
2293	subScalar( s ) {
2294
2295		this.x -= s;
2296		this.y -= s;
2297		this.z -= s;
2298
2299		return this;
2300
2301	}
2302
2303	subVectors( a, b ) {
2304
2305		this.x = a.x - b.x;
2306		this.y = a.y - b.y;
2307		this.z = a.z - b.z;
2308
2309		return this;
2310
2311	}
2312
2313	multiply( v ) {
2314
2315		this.x *= v.x;
2316		this.y *= v.y;
2317		this.z *= v.z;
2318
2319		return this;
2320
2321	}
2322
2323	multiplyScalar( scalar ) {
2324
2325		this.x *= scalar;
2326		this.y *= scalar;
2327		this.z *= scalar;
2328
2329		return this;
2330
2331	}
2332
2333	multiplyVectors( a, b ) {
2334
2335		this.x = a.x * b.x;
2336		this.y = a.y * b.y;
2337		this.z = a.z * b.z;
2338
2339		return this;
2340
2341	}
2342
2343	applyEuler( euler ) {
2344
2345		return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) );
2346
2347	}
2348
2349	applyAxisAngle( axis, angle ) {
2350
2351		return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) );
2352
2353	}
2354
2355	applyMatrix3( m ) {
2356
2357		const x = this.x, y = this.y, z = this.z;
2358		const e = m.elements;
2359
2360		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
2361		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
2362		this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
2363
2364		return this;
2365
2366	}
2367
2368	applyNormalMatrix( m ) {
2369
2370		return this.applyMatrix3( m ).normalize();
2371
2372	}
2373
2374	applyMatrix4( m ) {
2375
2376		const x = this.x, y = this.y, z = this.z;
2377		const e = m.elements;
2378
2379		const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
2380
2381		this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
2382		this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
2383		this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
2384
2385		return this;
2386
2387	}
2388
2389	applyQuaternion( q ) {
2390
2391		const x = this.x, y = this.y, z = this.z;
2392		const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
2393
2394		// calculate quat * vector
2395
2396		const ix = qw * x + qy * z - qz * y;
2397		const iy = qw * y + qz * x - qx * z;
2398		const iz = qw * z + qx * y - qy * x;
2399		const iw = - qx * x - qy * y - qz * z;
2400
2401		// calculate result * inverse quat
2402
2403		this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
2404		this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
2405		this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
2406
2407		return this;
2408
2409	}
2410
2411	project( camera ) {
2412
2413		return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
2414
2415	}
2416
2417	unproject( camera ) {
2418
2419		return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
2420
2421	}
2422
2423	transformDirection( m ) {
2424
2425		// input: THREE.Matrix4 affine matrix
2426		// vector interpreted as a direction
2427
2428		const x = this.x, y = this.y, z = this.z;
2429		const e = m.elements;
2430
2431		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
2432		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
2433		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
2434
2435		return this.normalize();
2436
2437	}
2438
2439	divide( v ) {
2440
2441		this.x /= v.x;
2442		this.y /= v.y;
2443		this.z /= v.z;
2444
2445		return this;
2446
2447	}
2448
2449	divideScalar( scalar ) {
2450
2451		return this.multiplyScalar( 1 / scalar );
2452
2453	}
2454
2455	min( v ) {
2456
2457		this.x = Math.min( this.x, v.x );
2458		this.y = Math.min( this.y, v.y );
2459		this.z = Math.min( this.z, v.z );
2460
2461		return this;
2462
2463	}
2464
2465	max( v ) {
2466
2467		this.x = Math.max( this.x, v.x );
2468		this.y = Math.max( this.y, v.y );
2469		this.z = Math.max( this.z, v.z );
2470
2471		return this;
2472
2473	}
2474
2475	clamp( min, max ) {
2476
2477		// assumes min < max, componentwise
2478
2479		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2480		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2481		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2482
2483		return this;
2484
2485	}
2486
2487	clampScalar( minVal, maxVal ) {
2488
2489		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
2490		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
2491		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
2492
2493		return this;
2494
2495	}
2496
2497	clampLength( min, max ) {
2498
2499		const length = this.length();
2500
2501		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2502
2503	}
2504
2505	floor() {
2506
2507		this.x = Math.floor( this.x );
2508		this.y = Math.floor( this.y );
2509		this.z = Math.floor( this.z );
2510
2511		return this;
2512
2513	}
2514
2515	ceil() {
2516
2517		this.x = Math.ceil( this.x );
2518		this.y = Math.ceil( this.y );
2519		this.z = Math.ceil( this.z );
2520
2521		return this;
2522
2523	}
2524
2525	round() {
2526
2527		this.x = Math.round( this.x );
2528		this.y = Math.round( this.y );
2529		this.z = Math.round( this.z );
2530
2531		return this;
2532
2533	}
2534
2535	roundToZero() {
2536
2537		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
2538		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
2539		this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
2540
2541		return this;
2542
2543	}
2544
2545	negate() {
2546
2547		this.x = - this.x;
2548		this.y = - this.y;
2549		this.z = - this.z;
2550
2551		return this;
2552
2553	}
2554
2555	dot( v ) {
2556
2557		return this.x * v.x + this.y * v.y + this.z * v.z;
2558
2559	}
2560
2561	// TODO lengthSquared?
2562
2563	lengthSq() {
2564
2565		return this.x * this.x + this.y * this.y + this.z * this.z;
2566
2567	}
2568
2569	length() {
2570
2571		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
2572
2573	}
2574
2575	manhattanLength() {
2576
2577		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
2578
2579	}
2580
2581	normalize() {
2582
2583		return this.divideScalar( this.length() || 1 );
2584
2585	}
2586
2587	setLength( length ) {
2588
2589		return this.normalize().multiplyScalar( length );
2590
2591	}
2592
2593	lerp( v, alpha ) {
2594
2595		this.x += ( v.x - this.x ) * alpha;
2596		this.y += ( v.y - this.y ) * alpha;
2597		this.z += ( v.z - this.z ) * alpha;
2598
2599		return this;
2600
2601	}
2602
2603	lerpVectors( v1, v2, alpha ) {
2604
2605		this.x = v1.x + ( v2.x - v1.x ) * alpha;
2606		this.y = v1.y + ( v2.y - v1.y ) * alpha;
2607		this.z = v1.z + ( v2.z - v1.z ) * alpha;
2608
2609		return this;
2610
2611	}
2612
2613	cross( v ) {
2614
2615		return this.crossVectors( this, v );
2616
2617	}
2618
2619	crossVectors( a, b ) {
2620
2621		const ax = a.x, ay = a.y, az = a.z;
2622		const bx = b.x, by = b.y, bz = b.z;
2623
2624		this.x = ay * bz - az * by;
2625		this.y = az * bx - ax * bz;
2626		this.z = ax * by - ay * bx;
2627
2628		return this;
2629
2630	}
2631
2632	projectOnVector( v ) {
2633
2634		const denominator = v.lengthSq();
2635
2636		if ( denominator === 0 ) return this.set( 0, 0, 0 );
2637
2638		const scalar = v.dot( this ) / denominator;
2639
2640		return this.copy( v ).multiplyScalar( scalar );
2641
2642	}
2643
2644	projectOnPlane( planeNormal ) {
2645
2646		_vector$d.copy( this ).projectOnVector( planeNormal );
2647
2648		return this.sub( _vector$d );
2649
2650	}
2651
2652	reflect( normal ) {
2653
2654		// reflect incident vector off plane orthogonal to normal
2655		// normal is assumed to have unit length
2656
2657		return this.sub( _vector$d.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
2658
2659	}
2660
2661	angleTo( v ) {
2662
2663		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
2664
2665		if ( denominator === 0 ) return Math.PI / 2;
2666
2667		const theta = this.dot( v ) / denominator;
2668
2669		// clamp, to handle numerical problems
2670
2671		return Math.acos( clamp( theta, - 1, 1 ) );
2672
2673	}
2674
2675	distanceTo( v ) {
2676
2677		return Math.sqrt( this.distanceToSquared( v ) );
2678
2679	}
2680
2681	distanceToSquared( v ) {
2682
2683		const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
2684
2685		return dx * dx + dy * dy + dz * dz;
2686
2687	}
2688
2689	manhattanDistanceTo( v ) {
2690
2691		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
2692
2693	}
2694
2695	setFromSpherical( s ) {
2696
2697		return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
2698
2699	}
2700
2701	setFromSphericalCoords( radius, phi, theta ) {
2702
2703		const sinPhiRadius = Math.sin( phi ) * radius;
2704
2705		this.x = sinPhiRadius * Math.sin( theta );
2706		this.y = Math.cos( phi ) * radius;
2707		this.z = sinPhiRadius * Math.cos( theta );
2708
2709		return this;
2710
2711	}
2712
2713	setFromCylindrical( c ) {
2714
2715		return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
2716
2717	}
2718
2719	setFromCylindricalCoords( radius, theta, y ) {
2720
2721		this.x = radius * Math.sin( theta );
2722		this.y = y;
2723		this.z = radius * Math.cos( theta );
2724
2725		return this;
2726
2727	}
2728
2729	setFromMatrixPosition( m ) {
2730
2731		const e = m.elements;
2732
2733		this.x = e[ 12 ];
2734		this.y = e[ 13 ];
2735		this.z = e[ 14 ];
2736
2737		return this;
2738
2739	}
2740
2741	setFromMatrixScale( m ) {
2742
2743		const sx = this.setFromMatrixColumn( m, 0 ).length();
2744		const sy = this.setFromMatrixColumn( m, 1 ).length();
2745		const sz = this.setFromMatrixColumn( m, 2 ).length();
2746
2747		this.x = sx;
2748		this.y = sy;
2749		this.z = sz;
2750
2751		return this;
2752
2753	}
2754
2755	setFromMatrixColumn( m, index ) {
2756
2757		return this.fromArray( m.elements, index * 4 );
2758
2759	}
2760
2761	setFromMatrix3Column( m, index ) {
2762
2763		return this.fromArray( m.elements, index * 3 );
2764
2765	}
2766
2767	setFromEuler( e ) {
2768
2769		this.x = e._x;
2770		this.y = e._y;
2771		this.z = e._z;
2772
2773		return this;
2774
2775	}
2776
2777	equals( v ) {
2778
2779		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
2780
2781	}
2782
2783	fromArray( array, offset = 0 ) {
2784
2785		this.x = array[ offset ];
2786		this.y = array[ offset + 1 ];
2787		this.z = array[ offset + 2 ];
2788
2789		return this;
2790
2791	}
2792
2793	toArray( array = [], offset = 0 ) {
2794
2795		array[ offset ] = this.x;
2796		array[ offset + 1 ] = this.y;
2797		array[ offset + 2 ] = this.z;
2798
2799		return array;
2800
2801	}
2802
2803	fromBufferAttribute( attribute, index ) {
2804
2805		this.x = attribute.getX( index );
2806		this.y = attribute.getY( index );
2807		this.z = attribute.getZ( index );
2808
2809		return this;
2810
2811	}
2812
2813	random() {
2814
2815		this.x = Math.random();
2816		this.y = Math.random();
2817		this.z = Math.random();
2818
2819		return this;
2820
2821	}
2822
2823	randomDirection() {
2824
2825		// Derived from https://mathworld.wolfram.com/SpherePointPicking.html
2826
2827		const u = ( Math.random() - 0.5 ) * 2;
2828		const t = Math.random() * Math.PI * 2;
2829		const f = Math.sqrt( 1 - u ** 2 );
2830
2831		this.x = f * Math.cos( t );
2832		this.y = f * Math.sin( t );
2833		this.z = u;
2834
2835		return this;
2836
2837	}
2838
2839	*[ Symbol.iterator ]() {
2840
2841		yield this.x;
2842		yield this.y;
2843		yield this.z;
2844
2845	}
2846
2847}
2848
2849const _vector$d = /*@__PURE__*/ new Vector3();
2850const _quaternion$4 = /*@__PURE__*/ new Quaternion();
2851
2852function SRGBToLinear( c ) {
2853
2854	return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
2855
2856}
2857
2858function LinearToSRGB( c ) {
2859
2860	return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
2861
2862}
2863
2864
2865/**
2866 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping
2867 * or clipping. Based on W3C specifications for sRGB and Display P3,
2868 * and ICC specifications for the D50 connection space. Values in/out
2869 * are _linear_ sRGB and _linear_ Display P3.
2870 *
2871 * Note that both sRGB and Display P3 use the sRGB transfer functions.
2872 *
2873 * Reference:
2874 * - http://www.russellcottrell.com/photo/matrixCalculator.htm
2875 */
2876
2877const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = new Matrix3().fromArray( [
2878	0.8224621, 0.0331941, 0.0170827,
2879	0.1775380, 0.9668058, 0.0723974,
2880	- 0.0000001, 0.0000001, 0.9105199
2881] );
2882
2883const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = new Matrix3().fromArray( [
2884	1.2249401, - 0.0420569, - 0.0196376,
2885	- 0.2249404, 1.0420571, - 0.0786361,
2886	0.0000001, 0.0000000, 1.0982735
2887] );
2888
2889const _vector$c = new Vector3();
2890
2891function DisplayP3ToLinearSRGB( color ) {
2892
2893	color.convertSRGBToLinear();
2894
2895	_vector$c.set( color.r, color.g, color.b ).applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB );
2896
2897	return color.setRGB( _vector$c.x, _vector$c.y, _vector$c.z );
2898
2899}
2900
2901function LinearSRGBToDisplayP3( color ) {
2902
2903	_vector$c.set( color.r, color.g, color.b ).applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 );
2904
2905	return color.setRGB( _vector$c.x, _vector$c.y, _vector$c.z ).convertLinearToSRGB();
2906
2907}
2908
2909// Conversions from <source> to Linear-sRGB reference space.
2910const TO_LINEAR = {
2911	[ LinearSRGBColorSpace ]: ( color ) => color,
2912	[ SRGBColorSpace ]: ( color ) => color.convertSRGBToLinear(),
2913	[ DisplayP3ColorSpace ]: DisplayP3ToLinearSRGB,
2914};
2915
2916// Conversions to <target> from Linear-sRGB reference space.
2917const FROM_LINEAR = {
2918	[ LinearSRGBColorSpace ]: ( color ) => color,
2919	[ SRGBColorSpace ]: ( color ) => color.convertLinearToSRGB(),
2920	[ DisplayP3ColorSpace ]: LinearSRGBToDisplayP3,
2921};
2922
2923const ColorManagement = {
2924
2925	enabled: false,
2926
2927	get legacyMode() {
2928
2929		console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' );
2930
2931		return ! this.enabled;
2932
2933	},
2934
2935	set legacyMode( legacyMode ) {
2936
2937		console.warn( 'THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150.' );
2938
2939		this.enabled = ! legacyMode;
2940
2941	},
2942
2943	get workingColorSpace() {
2944
2945		return LinearSRGBColorSpace;
2946
2947	},
2948
2949	set workingColorSpace( colorSpace ) {
2950
2951		console.warn( 'THREE.ColorManagement: .workingColorSpace is readonly.' );
2952
2953	},
2954
2955	convert: function ( color, sourceColorSpace, targetColorSpace ) {
2956
2957		if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) {
2958
2959			return color;
2960
2961		}
2962
2963		const sourceToLinear = TO_LINEAR[ sourceColorSpace ];
2964		const targetFromLinear = FROM_LINEAR[ targetColorSpace ];
2965
2966		if ( sourceToLinear === undefined || targetFromLinear === undefined ) {
2967
2968			throw new Error( `Unsupported color space conversion, "${ sourceColorSpace }" to "${ targetColorSpace }".` );
2969
2970		}
2971
2972		return targetFromLinear( sourceToLinear( color ) );
2973
2974	},
2975
2976	fromWorkingColorSpace: function ( color, targetColorSpace ) {
2977
2978		return this.convert( color, this.workingColorSpace, targetColorSpace );
2979
2980	},
2981
2982	toWorkingColorSpace: function ( color, sourceColorSpace ) {
2983
2984		return this.convert( color, sourceColorSpace, this.workingColorSpace );
2985
2986	},
2987
2988};
2989
2990let _canvas;
2991
2992class ImageUtils {
2993
2994	static getDataURL( image ) {
2995
2996		if ( /^data:/i.test( image.src ) ) {
2997
2998			return image.src;
2999
3000		}
3001
3002		if ( typeof HTMLCanvasElement == 'undefined' ) {
3003
3004			return image.src;
3005
3006		}
3007
3008		let canvas;
3009
3010		if ( image instanceof HTMLCanvasElement ) {
3011
3012			canvas = image;
3013
3014		} else {
3015
vendor: 19,905 bytes, lines 3016-4174
3016			if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' );
3017
3018			_canvas.width = image.width;
3019			_canvas.height = image.height;
3020
3021			const context = _canvas.getContext( '2d' );
3022
3023			if ( image instanceof ImageData ) {
3024
3025				context.putImageData( image, 0, 0 );
3026
3027			} else {
3028
3029				context.drawImage( image, 0, 0, image.width, image.height );
3030
3031			}
3032
3033			canvas = _canvas;
3034
3035		}
3036
3037		if ( canvas.width > 2048 || canvas.height > 2048 ) {
3038
3039			console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image );
3040
3041			return canvas.toDataURL( 'image/jpeg', 0.6 );
3042
3043		} else {
3044
3045			return canvas.toDataURL( 'image/png' );
3046
3047		}
3048
3049	}
3050
3051	static sRGBToLinear( image ) {
3052
3053		if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
3054			( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
3055			( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
3056
3057			const canvas = createElementNS( 'canvas' );
3058
3059			canvas.width = image.width;
3060			canvas.height = image.height;
3061
3062			const context = canvas.getContext( '2d' );
3063			context.drawImage( image, 0, 0, image.width, image.height );
3064
3065			const imageData = context.getImageData( 0, 0, image.width, image.height );
3066			const data = imageData.data;
3067
3068			for ( let i = 0; i < data.length; i ++ ) {
3069
3070				data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;
3071
3072			}
3073
3074			context.putImageData( imageData, 0, 0 );
3075
3076			return canvas;
3077
3078		} else if ( image.data ) {
3079
3080			const data = image.data.slice( 0 );
3081
3082			for ( let i = 0; i < data.length; i ++ ) {
3083
3084				if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {
3085
3086					data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );
3087
3088				} else {
3089
3090					// assuming float
3091
3092					data[ i ] = SRGBToLinear( data[ i ] );
3093
3094				}
3095
3096			}
3097
3098			return {
3099				data: data,
3100				width: image.width,
3101				height: image.height
3102			};
3103
3104		} else {
3105
3106			console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
3107			return image;
3108
3109		}
3110
3111	}
3112
3113}
3114
3115class Source {
3116
3117	constructor( data = null ) {
3118
3119		this.isSource = true;
3120
3121		this.uuid = generateUUID();
3122
3123		this.data = data;
3124
3125		this.version = 0;
3126
3127	}
3128
3129	set needsUpdate( value ) {
3130
3131		if ( value === true ) this.version ++;
3132
3133	}
3134
3135	toJSON( meta ) {
3136
3137		const isRootObject = ( meta === undefined || typeof meta === 'string' );
3138
3139		if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) {
3140
3141			return meta.images[ this.uuid ];
3142
3143		}
3144
3145		const output = {
3146			uuid: this.uuid,
3147			url: ''
3148		};
3149
3150		const data = this.data;
3151
3152		if ( data !== null ) {
3153
3154			let url;
3155
3156			if ( Array.isArray( data ) ) {
3157
3158				// cube texture
3159
3160				url = [];
3161
3162				for ( let i = 0, l = data.length; i < l; i ++ ) {
3163
3164					if ( data[ i ].isDataTexture ) {
3165
3166						url.push( serializeImage( data[ i ].image ) );
3167
3168					} else {
3169
3170						url.push( serializeImage( data[ i ] ) );
3171
3172					}
3173
3174				}
3175
3176			} else {
3177
3178				// texture
3179
3180				url = serializeImage( data );
3181
3182			}
3183
3184			output.url = url;
3185
3186		}
3187
3188		if ( ! isRootObject ) {
3189
3190			meta.images[ this.uuid ] = output;
3191
3192		}
3193
3194		return output;
3195
3196	}
3197
3198}
3199
3200function serializeImage( image ) {
3201
3202	if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
3203		( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
3204		( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
3205
3206		// default images
3207
3208		return ImageUtils.getDataURL( image );
3209
3210	} else {
3211
3212		if ( image.data ) {
3213
3214			// images of DataTexture
3215
3216			return {
3217				data: Array.from( image.data ),
3218				width: image.width,
3219				height: image.height,
3220				type: image.data.constructor.name
3221			};
3222
3223		} else {
3224
3225			console.warn( 'THREE.Texture: Unable to serialize Texture.' );
3226			return {};
3227
3228		}
3229
3230	}
3231
3232}
3233
3234let textureId = 0;
3235
3236class Texture extends EventDispatcher {
3237
3238	constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, encoding = LinearEncoding ) {
3239
3240		super();
3241
3242		this.isTexture = true;
3243
3244		Object.defineProperty( this, 'id', { value: textureId ++ } );
3245
3246		this.uuid = generateUUID();
3247
3248		this.name = '';
3249
3250		this.source = new Source( image );
3251		this.mipmaps = [];
3252
3253		this.mapping = mapping;
3254
3255		this.wrapS = wrapS;
3256		this.wrapT = wrapT;
3257
3258		this.magFilter = magFilter;
3259		this.minFilter = minFilter;
3260
3261		this.anisotropy = anisotropy;
3262
3263		this.format = format;
3264		this.internalFormat = null;
3265		this.type = type;
3266
3267		this.offset = new Vector2( 0, 0 );
3268		this.repeat = new Vector2( 1, 1 );
3269		this.center = new Vector2( 0, 0 );
3270		this.rotation = 0;
3271
3272		this.matrixAutoUpdate = true;
3273		this.matrix = new Matrix3();
3274
3275		this.generateMipmaps = true;
3276		this.premultiplyAlpha = false;
3277		this.flipY = true;
3278		this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
3279
3280		// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.
3281		//
3282		// Also changing the encoding after already used by a Material will not automatically make the Material
3283		// update. You need to explicitly call Material.needsUpdate to trigger it to recompile.
3284		this.encoding = encoding;
3285
3286		this.userData = {};
3287
3288		this.version = 0;
3289		this.onUpdate = null;
3290
3291		this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not
3292		this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures)
3293
3294	}
3295
3296	get image() {
3297
3298		return this.source.data;
3299
3300	}
3301
3302	set image( value = null ) {
3303
3304		this.source.data = value;
3305
3306	}
3307
3308	updateMatrix() {
3309
3310		this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
3311
3312	}
3313
3314	clone() {
3315
3316		return new this.constructor().copy( this );
3317
3318	}
3319
3320	copy( source ) {
3321
3322		this.name = source.name;
3323
3324		this.source = source.source;
3325		this.mipmaps = source.mipmaps.slice( 0 );
3326
3327		this.mapping = source.mapping;
3328
3329		this.wrapS = source.wrapS;
3330		this.wrapT = source.wrapT;
3331
3332		this.magFilter = source.magFilter;
3333		this.minFilter = source.minFilter;
3334
3335		this.anisotropy = source.anisotropy;
3336
3337		this.format = source.format;
3338		this.internalFormat = source.internalFormat;
3339		this.type = source.type;
3340
3341		this.offset.copy( source.offset );
3342		this.repeat.copy( source.repeat );
3343		this.center.copy( source.center );
3344		this.rotation = source.rotation;
3345
3346		this.matrixAutoUpdate = source.matrixAutoUpdate;
3347		this.matrix.copy( source.matrix );
3348
3349		this.generateMipmaps = source.generateMipmaps;
3350		this.premultiplyAlpha = source.premultiplyAlpha;
3351		this.flipY = source.flipY;
3352		this.unpackAlignment = source.unpackAlignment;
3353		this.encoding = source.encoding;
3354
3355		this.userData = JSON.parse( JSON.stringify( source.userData ) );
3356
3357		this.needsUpdate = true;
3358
3359		return this;
3360
3361	}
3362
3363	toJSON( meta ) {
3364
3365		const isRootObject = ( meta === undefined || typeof meta === 'string' );
3366
3367		if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
3368
3369			return meta.textures[ this.uuid ];
3370
3371		}
3372
3373		const output = {
3374
3375			metadata: {
3376				version: 4.5,
3377				type: 'Texture',
3378				generator: 'Texture.toJSON'
3379			},
3380
3381			uuid: this.uuid,
3382			name: this.name,
3383
3384			image: this.source.toJSON( meta ).uuid,
3385
3386			mapping: this.mapping,
3387
3388			repeat: [ this.repeat.x, this.repeat.y ],
3389			offset: [ this.offset.x, this.offset.y ],
3390			center: [ this.center.x, this.center.y ],
3391			rotation: this.rotation,
3392
3393			wrap: [ this.wrapS, this.wrapT ],
3394
3395			format: this.format,
3396			internalFormat: this.internalFormat,
3397			type: this.type,
3398			encoding: this.encoding,
3399
3400			minFilter: this.minFilter,
3401			magFilter: this.magFilter,
3402			anisotropy: this.anisotropy,
3403
3404			flipY: this.flipY,
3405
3406			generateMipmaps: this.generateMipmaps,
3407			premultiplyAlpha: this.premultiplyAlpha,
3408			unpackAlignment: this.unpackAlignment
3409
3410		};
3411
3412		if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData;
3413
3414		if ( ! isRootObject ) {
3415
3416			meta.textures[ this.uuid ] = output;
3417
3418		}
3419
3420		return output;
3421
3422	}
3423
3424	dispose() {
3425
3426		this.dispatchEvent( { type: 'dispose' } );
3427
3428	}
3429
3430	transformUv( uv ) {
3431
3432		if ( this.mapping !== UVMapping ) return uv;
3433
3434		uv.applyMatrix3( this.matrix );
3435
3436		if ( uv.x < 0 || uv.x > 1 ) {
3437
3438			switch ( this.wrapS ) {
3439
3440				case RepeatWrapping:
3441
3442					uv.x = uv.x - Math.floor( uv.x );
3443					break;
3444
3445				case ClampToEdgeWrapping:
3446
3447					uv.x = uv.x < 0 ? 0 : 1;
3448					break;
3449
3450				case MirroredRepeatWrapping:
3451
3452					if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
3453
3454						uv.x = Math.ceil( uv.x ) - uv.x;
3455
3456					} else {
3457
3458						uv.x = uv.x - Math.floor( uv.x );
3459
3460					}
3461
3462					break;
3463
3464			}
3465
3466		}
3467
3468		if ( uv.y < 0 || uv.y > 1 ) {
3469
3470			switch ( this.wrapT ) {
3471
3472				case RepeatWrapping:
3473
3474					uv.y = uv.y - Math.floor( uv.y );
3475					break;
3476
3477				case ClampToEdgeWrapping:
3478
3479					uv.y = uv.y < 0 ? 0 : 1;
3480					break;
3481
3482				case MirroredRepeatWrapping:
3483
3484					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
3485
3486						uv.y = Math.ceil( uv.y ) - uv.y;
3487
3488					} else {
3489
3490						uv.y = uv.y - Math.floor( uv.y );
3491
3492					}
3493
3494					break;
3495
3496			}
3497
3498		}
3499
3500		if ( this.flipY ) {
3501
3502			uv.y = 1 - uv.y;
3503
3504		}
3505
3506		return uv;
3507
3508	}
3509
3510	set needsUpdate( value ) {
3511
3512		if ( value === true ) {
3513
3514			this.version ++;
3515			this.source.needsUpdate = true;
3516
3517		}
3518
3519	}
3520
3521}
3522
3523Texture.DEFAULT_IMAGE = null;
3524Texture.DEFAULT_MAPPING = UVMapping;
3525Texture.DEFAULT_ANISOTROPY = 1;
3526
3527class Vector4 {
3528
3529	constructor( x = 0, y = 0, z = 0, w = 1 ) {
3530
3531		Vector4.prototype.isVector4 = true;
3532
3533		this.x = x;
3534		this.y = y;
3535		this.z = z;
3536		this.w = w;
3537
3538	}
3539
3540	get width() {
3541
3542		return this.z;
3543
3544	}
3545
3546	set width( value ) {
3547
3548		this.z = value;
3549
3550	}
3551
3552	get height() {
3553
3554		return this.w;
3555
3556	}
3557
3558	set height( value ) {
3559
3560		this.w = value;
3561
3562	}
3563
3564	set( x, y, z, w ) {
3565
3566		this.x = x;
3567		this.y = y;
3568		this.z = z;
3569		this.w = w;
3570
3571		return this;
3572
3573	}
3574
3575	setScalar( scalar ) {
3576
3577		this.x = scalar;
3578		this.y = scalar;
3579		this.z = scalar;
3580		this.w = scalar;
3581
3582		return this;
3583
3584	}
3585
3586	setX( x ) {
3587
3588		this.x = x;
3589
3590		return this;
3591
3592	}
3593
3594	setY( y ) {
3595
3596		this.y = y;
3597
3598		return this;
3599
3600	}
3601
3602	setZ( z ) {
3603
3604		this.z = z;
3605
3606		return this;
3607
3608	}
3609
3610	setW( w ) {
3611
3612		this.w = w;
3613
3614		return this;
3615
3616	}
3617
3618	setComponent( index, value ) {
3619
3620		switch ( index ) {
3621
3622			case 0: this.x = value; break;
3623			case 1: this.y = value; break;
3624			case 2: this.z = value; break;
3625			case 3: this.w = value; break;
3626			default: throw new Error( 'index is out of range: ' + index );
3627
3628		}
3629
3630		return this;
3631
3632	}
3633
3634	getComponent( index ) {
3635
3636		switch ( index ) {
3637
3638			case 0: return this.x;
3639			case 1: return this.y;
3640			case 2: return this.z;
3641			case 3: return this.w;
3642			default: throw new Error( 'index is out of range: ' + index );
3643
3644		}
3645
3646	}
3647
3648	clone() {
3649
3650		return new this.constructor( this.x, this.y, this.z, this.w );
3651
3652	}
3653
3654	copy( v ) {
3655
3656		this.x = v.x;
3657		this.y = v.y;
3658		this.z = v.z;
3659		this.w = ( v.w !== undefined ) ? v.w : 1;
3660
3661		return this;
3662
3663	}
3664
3665	add( v ) {
3666
3667		this.x += v.x;
3668		this.y += v.y;
3669		this.z += v.z;
3670		this.w += v.w;
3671
3672		return this;
3673
3674	}
3675
3676	addScalar( s ) {
3677
3678		this.x += s;
3679		this.y += s;
3680		this.z += s;
3681		this.w += s;
3682
3683		return this;
3684
3685	}
3686
3687	addVectors( a, b ) {
3688
3689		this.x = a.x + b.x;
3690		this.y = a.y + b.y;
3691		this.z = a.z + b.z;
3692		this.w = a.w + b.w;
3693
3694		return this;
3695
3696	}
3697
3698	addScaledVector( v, s ) {
3699
3700		this.x += v.x * s;
3701		this.y += v.y * s;
3702		this.z += v.z * s;
3703		this.w += v.w * s;
3704
3705		return this;
3706
3707	}
3708
3709	sub( v ) {
3710
3711		this.x -= v.x;
3712		this.y -= v.y;
3713		this.z -= v.z;
3714		this.w -= v.w;
3715
3716		return this;
3717
3718	}
3719
3720	subScalar( s ) {
3721
3722		this.x -= s;
3723		this.y -= s;
3724		this.z -= s;
3725		this.w -= s;
3726
3727		return this;
3728
3729	}
3730
3731	subVectors( a, b ) {
3732
3733		this.x = a.x - b.x;
3734		this.y = a.y - b.y;
3735		this.z = a.z - b.z;
3736		this.w = a.w - b.w;
3737
3738		return this;
3739
3740	}
3741
3742	multiply( v ) {
3743
3744		this.x *= v.x;
3745		this.y *= v.y;
3746		this.z *= v.z;
3747		this.w *= v.w;
3748
3749		return this;
3750
3751	}
3752
3753	multiplyScalar( scalar ) {
3754
3755		this.x *= scalar;
3756		this.y *= scalar;
3757		this.z *= scalar;
3758		this.w *= scalar;
3759
3760		return this;
3761
3762	}
3763
3764	applyMatrix4( m ) {
3765
3766		const x = this.x, y = this.y, z = this.z, w = this.w;
3767		const e = m.elements;
3768
3769		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
3770		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
3771		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
3772		this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
3773
3774		return this;
3775
3776	}
3777
3778	divideScalar( scalar ) {
3779
3780		return this.multiplyScalar( 1 / scalar );
3781
3782	}
3783
3784	setAxisAngleFromQuaternion( q ) {
3785
3786		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
3787
3788		// q is assumed to be normalized
3789
3790		this.w = 2 * Math.acos( q.w );
3791
3792		const s = Math.sqrt( 1 - q.w * q.w );
3793
3794		if ( s < 0.0001 ) {
3795
3796			this.x = 1;
3797			this.y = 0;
3798			this.z = 0;
3799
3800		} else {
3801
3802			this.x = q.x / s;
3803			this.y = q.y / s;
3804			this.z = q.z / s;
3805
3806		}
3807
3808		return this;
3809
3810	}
3811
3812	setAxisAngleFromRotationMatrix( m ) {
3813
3814		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
3815
3816		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
3817
3818		let angle, x, y, z; // variables for result
3819		const epsilon = 0.01,		// margin to allow for rounding errors
3820			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
3821
3822			te = m.elements,
3823
3824			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
3825			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
3826			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
3827
3828		if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
3829		     ( Math.abs( m13 - m31 ) < epsilon ) &&
3830		     ( Math.abs( m23 - m32 ) < epsilon ) ) {
3831
3832			// singularity found
3833			// first check for identity matrix which must have +1 for all terms
3834			// in leading diagonal and zero in other terms
3835
3836			if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
3837			     ( Math.abs( m13 + m31 ) < epsilon2 ) &&
3838			     ( Math.abs( m23 + m32 ) < epsilon2 ) &&
3839			     ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
3840
3841				// this singularity is identity matrix so angle = 0
3842
3843				this.set( 1, 0, 0, 0 );
3844
3845				return this; // zero angle, arbitrary axis
3846
3847			}
3848
3849			// otherwise this singularity is angle = 180
3850
3851			angle = Math.PI;
3852
3853			const xx = ( m11 + 1 ) / 2;
3854			const yy = ( m22 + 1 ) / 2;
3855			const zz = ( m33 + 1 ) / 2;
3856			const xy = ( m12 + m21 ) / 4;
3857			const xz = ( m13 + m31 ) / 4;
3858			const yz = ( m23 + m32 ) / 4;
3859
3860			if ( ( xx > yy ) && ( xx > zz ) ) {
3861
3862				// m11 is the largest diagonal term
3863
3864				if ( xx < epsilon ) {
3865
3866					x = 0;
3867					y = 0.707106781;
3868					z = 0.707106781;
3869
3870				} else {
3871
3872					x = Math.sqrt( xx );
3873					y = xy / x;
3874					z = xz / x;
3875
3876				}
3877
3878			} else if ( yy > zz ) {
3879
3880				// m22 is the largest diagonal term
3881
3882				if ( yy < epsilon ) {
3883
3884					x = 0.707106781;
3885					y = 0;
3886					z = 0.707106781;
3887
3888				} else {
3889
3890					y = Math.sqrt( yy );
3891					x = xy / y;
3892					z = yz / y;
3893
3894				}
3895
3896			} else {
3897
3898				// m33 is the largest diagonal term so base result on this
3899
3900				if ( zz < epsilon ) {
3901
3902					x = 0.707106781;
3903					y = 0.707106781;
3904					z = 0;
3905
3906				} else {
3907
3908					z = Math.sqrt( zz );
3909					x = xz / z;
3910					y = yz / z;
3911
3912				}
3913
3914			}
3915
3916			this.set( x, y, z, angle );
3917
3918			return this; // return 180 deg rotation
3919
3920		}
3921
3922		// as we have reached here there are no singularities so we can handle normally
3923
3924		let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
3925			( m13 - m31 ) * ( m13 - m31 ) +
3926			( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
3927
3928		if ( Math.abs( s ) < 0.001 ) s = 1;
3929
3930		// prevent divide by zero, should not happen if matrix is orthogonal and should be
3931		// caught by singularity test above, but I've left it in just in case
3932
3933		this.x = ( m32 - m23 ) / s;
3934		this.y = ( m13 - m31 ) / s;
3935		this.z = ( m21 - m12 ) / s;
3936		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
3937
3938		return this;
3939
3940	}
3941
3942	min( v ) {
3943
3944		this.x = Math.min( this.x, v.x );
3945		this.y = Math.min( this.y, v.y );
3946		this.z = Math.min( this.z, v.z );
3947		this.w = Math.min( this.w, v.w );
3948
3949		return this;
3950
3951	}
3952
3953	max( v ) {
3954
3955		this.x = Math.max( this.x, v.x );
3956		this.y = Math.max( this.y, v.y );
3957		this.z = Math.max( this.z, v.z );
3958		this.w = Math.max( this.w, v.w );
3959
3960		return this;
3961
3962	}
3963
3964	clamp( min, max ) {
3965
3966		// assumes min < max, componentwise
3967
3968		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
3969		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
3970		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
3971		this.w = Math.max( min.w, Math.min( max.w, this.w ) );
3972
3973		return this;
3974
3975	}
3976
3977	clampScalar( minVal, maxVal ) {
3978
3979		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
3980		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
3981		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
3982		this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
3983
3984		return this;
3985
3986	}
3987
3988	clampLength( min, max ) {
3989
3990		const length = this.length();
3991
3992		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
3993
3994	}
3995
3996	floor() {
3997
3998		this.x = Math.floor( this.x );
3999		this.y = Math.floor( this.y );
4000		this.z = Math.floor( this.z );
4001		this.w = Math.floor( this.w );
4002
4003		return this;
4004
4005	}
4006
4007	ceil() {
4008
4009		this.x = Math.ceil( this.x );
4010		this.y = Math.ceil( this.y );
4011		this.z = Math.ceil( this.z );
4012		this.w = Math.ceil( this.w );
4013
4014		return this;
4015
4016	}
4017
4018	round() {
4019
4020		this.x = Math.round( this.x );
4021		this.y = Math.round( this.y );
4022		this.z = Math.round( this.z );
4023		this.w = Math.round( this.w );
4024
4025		return this;
4026
4027	}
4028
4029	roundToZero() {
4030
4031		this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
4032		this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
4033		this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
4034		this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
4035
4036		return this;
4037
4038	}
4039
4040	negate() {
4041
4042		this.x = - this.x;
4043		this.y = - this.y;
4044		this.z = - this.z;
4045		this.w = - this.w;
4046
4047		return this;
4048
4049	}
4050
4051	dot( v ) {
4052
4053		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
4054
4055	}
4056
4057	lengthSq() {
4058
4059		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
4060
4061	}
4062
4063	length() {
4064
4065		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
4066
4067	}
4068
4069	manhattanLength() {
4070
4071		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
4072
4073	}
4074
4075	normalize() {
4076
4077		return this.divideScalar( this.length() || 1 );
4078
4079	}
4080
4081	setLength( length ) {
4082
4083		return this.normalize().multiplyScalar( length );
4084
4085	}
4086
4087	lerp( v, alpha ) {
4088
4089		this.x += ( v.x - this.x ) * alpha;
4090		this.y += ( v.y - this.y ) * alpha;
4091		this.z += ( v.z - this.z ) * alpha;
4092		this.w += ( v.w - this.w ) * alpha;
4093
4094		return this;
4095
4096	}
4097
4098	lerpVectors( v1, v2, alpha ) {
4099
4100		this.x = v1.x + ( v2.x - v1.x ) * alpha;
4101		this.y = v1.y + ( v2.y - v1.y ) * alpha;
4102		this.z = v1.z + ( v2.z - v1.z ) * alpha;
4103		this.w = v1.w + ( v2.w - v1.w ) * alpha;
4104
4105		return this;
4106
4107	}
4108
4109	equals( v ) {
4110
4111		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
4112
4113	}
4114
4115	fromArray( array, offset = 0 ) {
4116
4117		this.x = array[ offset ];
4118		this.y = array[ offset + 1 ];
4119		this.z = array[ offset + 2 ];
4120		this.w = array[ offset + 3 ];
4121
4122		return this;
4123
4124	}
4125
4126	toArray( array = [], offset = 0 ) {
4127
4128		array[ offset ] = this.x;
4129		array[ offset + 1 ] = this.y;
4130		array[ offset + 2 ] = this.z;
4131		array[ offset + 3 ] = this.w;
4132
4133		return array;
4134
4135	}
4136
4137	fromBufferAttribute( attribute, index ) {
4138
4139		this.x = attribute.getX( index );
4140		this.y = attribute.getY( index );
4141		this.z = attribute.getZ( index );
4142		this.w = attribute.getW( index );
4143
4144		return this;
4145
4146	}
4147
4148	random() {
4149
4150		this.x = Math.random();
4151		this.y = Math.random();
4152		this.z = Math.random();
4153		this.w = Math.random();
4154
4155		return this;
4156
4157	}
4158
4159	*[ Symbol.iterator ]() {
4160
4161		yield this.x;
4162		yield this.y;
4163		yield this.z;
4164		yield this.w;
4165
4166	}
4167
4168}
4169
4170/*
4171 In options, we can specify:
4172 * Texture parameters for an auto-generated target texture
4173 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
4174*/
4175class WebGLRenderTarget extends EventDispatcher {
4176
4177	constructor( width = 1, height = 1, options = {} ) {
4178
4179		super();
4180
4181		this.isWebGLRenderTarget = true;
4182
4183		this.width = width;
4184		this.height = height;
4185		this.depth = 1;
4186
4187		this.scissor = new Vector4( 0, 0, width, height );
4188		this.scissorTest = false;
4189
4190		this.viewport = new Vector4( 0, 0, width, height );
4191
4192		const image = { width: width, height: height, depth: 1 };
4193
4194		this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
4195		this.texture.isRenderTargetTexture = true;
4196
4197		this.texture.flipY = false;
4198		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
4199		this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null;
4200		this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
4201
4202		this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
4203		this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
4204
4205		this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
4206
4207		this.samples = options.samples !== undefined ? options.samples : 0;
4208
4209	}
4210
4211	setSize( width, height, depth = 1 ) {
4212
4213		if ( this.width !== width || this.height !== height || this.depth !== depth ) {
4214
4215			this.width = width;
4216			this.height = height;
4217			this.depth = depth;
4218
4219			this.texture.image.width = width;
4220			this.texture.image.height = height;
4221			this.texture.image.depth = depth;
4222
4223			this.dispose();
4224
4225		}
4226
4227		this.viewport.set( 0, 0, width, height );
4228		this.scissor.set( 0, 0, width, height );
4229
4230	}
4231
4232	clone() {
4233
4234		return new this.constructor().copy( this );
4235
4236	}
4237
4238	copy( source ) {
4239
4240		this.width = source.width;
4241		this.height = source.height;
4242		this.depth = source.depth;
4243
4244		this.viewport.copy( source.viewport );
4245
4246		this.texture = source.texture.clone();
4247		this.texture.isRenderTargetTexture = true;
4248
4249		// ensure image object is not shared, see #20328
4250
4251		const image = Object.assign( {}, source.texture.image );
4252		this.texture.source = new Source( image );
4253
4254		this.depthBuffer = source.depthBuffer;
4255		this.stencilBuffer = source.stencilBuffer;
4256
4257		if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
4258
4259		this.samples = source.samples;
4260
4261		return this;
4262
4263	}
4264
4265	dispose() {
4266
4267		this.dispatchEvent( { type: 'dispose' } );
4268
4269	}
4270
4271}
4272
4273class DataArrayTexture extends Texture {
4274
4275	constructor( data = null, width = 1, height = 1, depth = 1 ) {
4276
4277		super( null );
4278
4279		this.isDataArrayTexture = true;
4280
4281		this.image = { data, width, height, depth };
4282
4283		this.magFilter = NearestFilter;
4284		this.minFilter = NearestFilter;
4285
4286		this.wrapR = ClampToEdgeWrapping;
4287
4288		this.generateMipmaps = false;
4289		this.flipY = false;
4290		this.unpackAlignment = 1;
4291
4292	}
4293
4294}
4295
4296class WebGLArrayRenderTarget extends WebGLRenderTarget {
4297
4298	constructor( width = 1, height = 1, depth = 1 ) {
4299
4300		super( width, height );
4301
4302		this.isWebGLArrayRenderTarget = true;
4303
4304		this.depth = depth;
4305
4306		this.texture = new DataArrayTexture( null, width, height, depth );
4307
4308		this.texture.isRenderTargetTexture = true;
4309
4310	}
4311
4312}
4313
4314class Data3DTexture extends Texture {
4315
4316	constructor( data = null, width = 1, height = 1, depth = 1 ) {
4317
4318		// We're going to add .setXXX() methods for setting properties later.
4319		// Users can still set in DataTexture3D directly.
4320		//
4321		//	const texture = new THREE.DataTexture3D( data, width, height, depth );
4322		// 	texture.anisotropy = 16;
4323		//
4324		// See #14839
4325
4326		super( null );
4327
4328		this.isData3DTexture = true;
4329
4330		this.image = { data, width, height, depth };
4331
4332		this.magFilter = NearestFilter;
4333		this.minFilter = NearestFilter;
4334
4335		this.wrapR = ClampToEdgeWrapping;
4336
4337		this.generateMipmaps = false;
4338		this.flipY = false;
4339		this.unpackAlignment = 1;
4340
4341	}
4342
4343}
4344
4345class WebGL3DRenderTarget extends WebGLRenderTarget {
4346
4347	constructor( width = 1, height = 1, depth = 1 ) {
4348
4349		super( width, height );
4350
4351		this.isWebGL3DRenderTarget = true;
4352
4353		this.depth = depth;
4354
4355		this.texture = new Data3DTexture( null, width, height, depth );
4356
4357		this.texture.isRenderTargetTexture = true;
4358
4359	}
4360
4361}
4362
4363class WebGLMultipleRenderTargets extends WebGLRenderTarget {
4364
4365	constructor( width = 1, height = 1, count = 1, options = {} ) {
4366
4367		super( width, height, options );
4368
vendor: 4,588 bytes, lines 4369-4633
4369		this.isWebGLMultipleRenderTargets = true;
4370
4371		const texture = this.texture;
4372
4373		this.texture = [];
4374
4375		for ( let i = 0; i < count; i ++ ) {
4376
4377			this.texture[ i ] = texture.clone();
4378			this.texture[ i ].isRenderTargetTexture = true;
4379
4380		}
4381
4382	}
4383
4384	setSize( width, height, depth = 1 ) {
4385
4386		if ( this.width !== width || this.height !== height || this.depth !== depth ) {
4387
4388			this.width = width;
4389			this.height = height;
4390			this.depth = depth;
4391
4392			for ( let i = 0, il = this.texture.length; i < il; i ++ ) {
4393
4394				this.texture[ i ].image.width = width;
4395				this.texture[ i ].image.height = height;
4396				this.texture[ i ].image.depth = depth;
4397
4398			}
4399
4400			this.dispose();
4401
4402		}
4403
4404		this.viewport.set( 0, 0, width, height );
4405		this.scissor.set( 0, 0, width, height );
4406
4407		return this;
4408
4409	}
4410
4411	copy( source ) {
4412
4413		this.dispose();
4414
4415		this.width = source.width;
4416		this.height = source.height;
4417		this.depth = source.depth;
4418
4419		this.viewport.set( 0, 0, this.width, this.height );
4420		this.scissor.set( 0, 0, this.width, this.height );
4421
4422		this.depthBuffer = source.depthBuffer;
4423		this.stencilBuffer = source.stencilBuffer;
4424
4425		if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
4426
4427		this.texture.length = 0;
4428
4429		for ( let i = 0, il = source.texture.length; i < il; i ++ ) {
4430
4431			this.texture[ i ] = source.texture[ i ].clone();
4432			this.texture[ i ].isRenderTargetTexture = true;
4433
4434		}
4435
4436		return this;
4437
4438	}
4439
4440}
4441
4442class Box3 {
4443
4444	constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) {
4445
4446		this.isBox3 = true;
4447
4448		this.min = min;
4449		this.max = max;
4450
4451	}
4452
4453	set( min, max ) {
4454
4455		this.min.copy( min );
4456		this.max.copy( max );
4457
4458		return this;
4459
4460	}
4461
4462	setFromArray( array ) {
4463
4464		let minX = + Infinity;
4465		let minY = + Infinity;
4466		let minZ = + Infinity;
4467
4468		let maxX = - Infinity;
4469		let maxY = - Infinity;
4470		let maxZ = - Infinity;
4471
4472		for ( let i = 0, l = array.length; i < l; i += 3 ) {
4473
4474			const x = array[ i ];
4475			const y = array[ i + 1 ];
4476			const z = array[ i + 2 ];
4477
4478			if ( x < minX ) minX = x;
4479			if ( y < minY ) minY = y;
4480			if ( z < minZ ) minZ = z;
4481
4482			if ( x > maxX ) maxX = x;
4483			if ( y > maxY ) maxY = y;
4484			if ( z > maxZ ) maxZ = z;
4485
4486		}
4487
4488		this.min.set( minX, minY, minZ );
4489		this.max.set( maxX, maxY, maxZ );
4490
4491		return this;
4492
4493	}
4494
4495	setFromBufferAttribute( attribute ) {
4496
4497		let minX = + Infinity;
4498		let minY = + Infinity;
4499		let minZ = + Infinity;
4500
4501		let maxX = - Infinity;
4502		let maxY = - Infinity;
4503		let maxZ = - Infinity;
4504
4505		for ( let i = 0, l = attribute.count; i < l; i ++ ) {
4506
4507			const x = attribute.getX( i );
4508			const y = attribute.getY( i );
4509			const z = attribute.getZ( i );
4510
4511			if ( x < minX ) minX = x;
4512			if ( y < minY ) minY = y;
4513			if ( z < minZ ) minZ = z;
4514
4515			if ( x > maxX ) maxX = x;
4516			if ( y > maxY ) maxY = y;
4517			if ( z > maxZ ) maxZ = z;
4518
4519		}
4520
4521		this.min.set( minX, minY, minZ );
4522		this.max.set( maxX, maxY, maxZ );
4523
4524		return this;
4525
4526	}
4527
4528	setFromPoints( points ) {
4529
4530		this.makeEmpty();
4531
4532		for ( let i = 0, il = points.length; i < il; i ++ ) {
4533
4534			this.expandByPoint( points[ i ] );
4535
4536		}
4537
4538		return this;
4539
4540	}
4541
4542	setFromCenterAndSize( center, size ) {
4543
4544		const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 );
4545
4546		this.min.copy( center ).sub( halfSize );
4547		this.max.copy( center ).add( halfSize );
4548
4549		return this;
4550
4551	}
4552
4553	setFromObject( object, precise = false ) {
4554
4555		this.makeEmpty();
4556
4557		return this.expandByObject( object, precise );
4558
4559	}
4560
4561	clone() {
4562
4563		return new this.constructor().copy( this );
4564
4565	}
4566
4567	copy( box ) {
4568
4569		this.min.copy( box.min );
4570		this.max.copy( box.max );
4571
4572		return this;
4573
4574	}
4575
4576	makeEmpty() {
4577
4578		this.min.x = this.min.y = this.min.z = + Infinity;
4579		this.max.x = this.max.y = this.max.z = - Infinity;
4580
4581		return this;
4582
4583	}
4584
4585	isEmpty() {
4586
4587		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4588
4589		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4590
4591	}
4592
4593	getCenter( target ) {
4594
4595		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4596
4597	}
4598
4599	getSize( target ) {
4600
4601		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
4602
4603	}
4604
4605	expandByPoint( point ) {
4606
4607		this.min.min( point );
4608		this.max.max( point );
4609
4610		return this;
4611
4612	}
4613
4614	expandByVector( vector ) {
4615
4616		this.min.sub( vector );
4617		this.max.add( vector );
4618
4619		return this;
4620
4621	}
4622
4623	expandByScalar( scalar ) {
4624
4625		this.min.addScalar( - scalar );
4626		this.max.addScalar( scalar );
4627
4628		return this;
4629
4630	}
4631
4632	expandByObject( object, precise = false ) {
4633
vendor: 12,498 bytes, lines 4634-5227
4634		// Computes the world-axis-aligned bounding box of an object (including its children),
4635		// accounting for both the object's, and children's, world transforms
4636
4637		object.updateWorldMatrix( false, false );
4638
4639		const geometry = object.geometry;
4640
4641		if ( geometry !== undefined ) {
4642
4643			if ( precise && geometry.attributes != undefined && geometry.attributes.position !== undefined ) {
4644
4645				const position = geometry.attributes.position;
4646				for ( let i = 0, l = position.count; i < l; i ++ ) {
4647
4648					_vector$b.fromBufferAttribute( position, i ).applyMatrix4( object.matrixWorld );
4649					this.expandByPoint( _vector$b );
4650
4651				}
4652
4653			} else {
4654
4655				if ( geometry.boundingBox === null ) {
4656
4657					geometry.computeBoundingBox();
4658
4659				}
4660
4661				_box$3.copy( geometry.boundingBox );
4662				_box$3.applyMatrix4( object.matrixWorld );
4663
4664				this.union( _box$3 );
4665
4666			}
4667
4668		}
4669
4670		const children = object.children;
4671
4672		for ( let i = 0, l = children.length; i < l; i ++ ) {
4673
4674			this.expandByObject( children[ i ], precise );
4675
4676		}
4677
4678		return this;
4679
4680	}
4681
4682	containsPoint( point ) {
4683
4684		return point.x < this.min.x || point.x > this.max.x ||
4685			point.y < this.min.y || point.y > this.max.y ||
4686			point.z < this.min.z || point.z > this.max.z ? false : true;
4687
4688	}
4689
4690	containsBox( box ) {
4691
4692		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4693			this.min.y <= box.min.y && box.max.y <= this.max.y &&
4694			this.min.z <= box.min.z && box.max.z <= this.max.z;
4695
4696	}
4697
4698	getParameter( point, target ) {
4699
4700		// This can potentially have a divide by zero if the box
4701		// has a size dimension of 0.
4702
4703		return target.set(
4704			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4705			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4706			( point.z - this.min.z ) / ( this.max.z - this.min.z )
4707		);
4708
4709	}
4710
4711	intersectsBox( box ) {
4712
4713		// using 6 splitting planes to rule out intersections.
4714		return box.max.x < this.min.x || box.min.x > this.max.x ||
4715			box.max.y < this.min.y || box.min.y > this.max.y ||
4716			box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
4717
4718	}
4719
4720	intersectsSphere( sphere ) {
4721
4722		// Find the point on the AABB closest to the sphere center.
4723		this.clampPoint( sphere.center, _vector$b );
4724
4725		// If that point is inside the sphere, the AABB and sphere intersect.
4726		return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
4727
4728	}
4729
4730	intersectsPlane( plane ) {
4731
4732		// We compute the minimum and maximum dot product values. If those values
4733		// are on the same side (back or front) of the plane, then there is no intersection.
4734
4735		let min, max;
4736
4737		if ( plane.normal.x > 0 ) {
4738
4739			min = plane.normal.x * this.min.x;
4740			max = plane.normal.x * this.max.x;
4741
4742		} else {
4743
4744			min = plane.normal.x * this.max.x;
4745			max = plane.normal.x * this.min.x;
4746
4747		}
4748
4749		if ( plane.normal.y > 0 ) {
4750
4751			min += plane.normal.y * this.min.y;
4752			max += plane.normal.y * this.max.y;
4753
4754		} else {
4755
4756			min += plane.normal.y * this.max.y;
4757			max += plane.normal.y * this.min.y;
4758
4759		}
4760
4761		if ( plane.normal.z > 0 ) {
4762
4763			min += plane.normal.z * this.min.z;
4764			max += plane.normal.z * this.max.z;
4765
4766		} else {
4767
4768			min += plane.normal.z * this.max.z;
4769			max += plane.normal.z * this.min.z;
4770
4771		}
4772
4773		return ( min <= - plane.constant && max >= - plane.constant );
4774
4775	}
4776
4777	intersectsTriangle( triangle ) {
4778
4779		if ( this.isEmpty() ) {
4780
4781			return false;
4782
4783		}
4784
4785		// compute box center and extents
4786		this.getCenter( _center );
4787		_extents.subVectors( this.max, _center );
4788
4789		// translate triangle to aabb origin
4790		_v0$2.subVectors( triangle.a, _center );
4791		_v1$7.subVectors( triangle.b, _center );
4792		_v2$4.subVectors( triangle.c, _center );
4793
4794		// compute edge vectors for triangle
4795		_f0.subVectors( _v1$7, _v0$2 );
4796		_f1.subVectors( _v2$4, _v1$7 );
4797		_f2.subVectors( _v0$2, _v2$4 );
4798
4799		// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
4800		// 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
4801		// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
4802		let axes = [
4803			0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
4804			_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
4805			- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
4806		];
4807		if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
4808
4809			return false;
4810
4811		}
4812
4813		// test 3 face normals from the aabb
4814		axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
4815		if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
4816
4817			return false;
4818
4819		}
4820
4821		// finally testing the face normal of the triangle
4822		// use already existing triangle edge vectors here
4823		_triangleNormal.crossVectors( _f0, _f1 );
4824		axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
4825
4826		return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents );
4827
4828	}
4829
4830	clampPoint( point, target ) {
4831
4832		return target.copy( point ).clamp( this.min, this.max );
4833
4834	}
4835
4836	distanceToPoint( point ) {
4837
4838		return this.clampPoint( point, _vector$b ).distanceTo( point );
4839
4840	}
4841
4842	getBoundingSphere( target ) {
4843
4844		if ( this.isEmpty() ) {
4845
4846			target.makeEmpty();
4847
4848		} else {
4849
4850			this.getCenter( target.center );
4851
4852			target.radius = this.getSize( _vector$b ).length() * 0.5;
4853
4854		}
4855
4856		return target;
4857
4858	}
4859
4860	intersect( box ) {
4861
4862		this.min.max( box.min );
4863		this.max.min( box.max );
4864
4865		// 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.
4866		if ( this.isEmpty() ) this.makeEmpty();
4867
4868		return this;
4869
4870	}
4871
4872	union( box ) {
4873
4874		this.min.min( box.min );
4875		this.max.max( box.max );
4876
4877		return this;
4878
4879	}
4880
4881	applyMatrix4( matrix ) {
4882
4883		// transform of empty box is an empty box.
4884		if ( this.isEmpty() ) return this;
4885
4886		// NOTE: I am using a binary pattern to specify all 2^3 combinations below
4887		_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
4888		_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
4889		_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
4890		_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
4891		_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
4892		_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
4893		_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
4894		_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
4895
4896		this.setFromPoints( _points );
4897
4898		return this;
4899
4900	}
4901
4902	translate( offset ) {
4903
4904		this.min.add( offset );
4905		this.max.add( offset );
4906
4907		return this;
4908
4909	}
4910
4911	equals( box ) {
4912
4913		return box.min.equals( this.min ) && box.max.equals( this.max );
4914
4915	}
4916
4917}
4918
4919const _points = [
4920	/*@__PURE__*/ new Vector3(),
4921	/*@__PURE__*/ new Vector3(),
4922	/*@__PURE__*/ new Vector3(),
4923	/*@__PURE__*/ new Vector3(),
4924	/*@__PURE__*/ new Vector3(),
4925	/*@__PURE__*/ new Vector3(),
4926	/*@__PURE__*/ new Vector3(),
4927	/*@__PURE__*/ new Vector3()
4928];
4929
4930const _vector$b = /*@__PURE__*/ new Vector3();
4931
4932const _box$3 = /*@__PURE__*/ new Box3();
4933
4934// triangle centered vertices
4935
4936const _v0$2 = /*@__PURE__*/ new Vector3();
4937const _v1$7 = /*@__PURE__*/ new Vector3();
4938const _v2$4 = /*@__PURE__*/ new Vector3();
4939
4940// triangle edge vectors
4941
4942const _f0 = /*@__PURE__*/ new Vector3();
4943const _f1 = /*@__PURE__*/ new Vector3();
4944const _f2 = /*@__PURE__*/ new Vector3();
4945
4946const _center = /*@__PURE__*/ new Vector3();
4947const _extents = /*@__PURE__*/ new Vector3();
4948const _triangleNormal = /*@__PURE__*/ new Vector3();
4949const _testAxis = /*@__PURE__*/ new Vector3();
4950
4951function satForAxes( axes, v0, v1, v2, extents ) {
4952
4953	for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
4954
4955		_testAxis.fromArray( axes, i );
4956		// project the aabb onto the separating axis
4957		const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
4958		// project all 3 vertices of the triangle onto the separating axis
4959		const p0 = v0.dot( _testAxis );
4960		const p1 = v1.dot( _testAxis );
4961		const p2 = v2.dot( _testAxis );
4962		// actual test, basically see if either of the most extreme of the triangle points intersects r
4963		if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
4964
4965			// points of the projected triangle are outside the projected half-length of the aabb
4966			// the axis is separating and we can exit
4967			return false;
4968
4969		}
4970
4971	}
4972
4973	return true;
4974
4975}
4976
4977const _box$2 = /*@__PURE__*/ new Box3();
4978const _v1$6 = /*@__PURE__*/ new Vector3();
4979const _v2$3 = /*@__PURE__*/ new Vector3();
4980
4981class Sphere {
4982
4983	constructor( center = new Vector3(), radius = - 1 ) {
4984
4985		this.center = center;
4986		this.radius = radius;
4987
4988	}
4989
4990	set( center, radius ) {
4991
4992		this.center.copy( center );
4993		this.radius = radius;
4994
4995		return this;
4996
4997	}
4998
4999	setFromPoints( points, optionalCenter ) {
5000
5001		const center = this.center;
5002
5003		if ( optionalCenter !== undefined ) {
5004
5005			center.copy( optionalCenter );
5006
5007		} else {
5008
5009			_box$2.setFromPoints( points ).getCenter( center );
5010
5011		}
5012
5013		let maxRadiusSq = 0;
5014
5015		for ( let i = 0, il = points.length; i < il; i ++ ) {
5016
5017			maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
5018
5019		}
5020
5021		this.radius = Math.sqrt( maxRadiusSq );
5022
5023		return this;
5024
5025	}
5026
5027	copy( sphere ) {
5028
5029		this.center.copy( sphere.center );
5030		this.radius = sphere.radius;
5031
5032		return this;
5033
5034	}
5035
5036	isEmpty() {
5037
5038		return ( this.radius < 0 );
5039
5040	}
5041
5042	makeEmpty() {
5043
5044		this.center.set( 0, 0, 0 );
5045		this.radius = - 1;
5046
5047		return this;
5048
5049	}
5050
5051	containsPoint( point ) {
5052
5053		return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
5054
5055	}
5056
5057	distanceToPoint( point ) {
5058
5059		return ( point.distanceTo( this.center ) - this.radius );
5060
5061	}
5062
5063	intersectsSphere( sphere ) {
5064
5065		const radiusSum = this.radius + sphere.radius;
5066
5067		return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
5068
5069	}
5070
5071	intersectsBox( box ) {
5072
5073		return box.intersectsSphere( this );
5074
5075	}
5076
5077	intersectsPlane( plane ) {
5078
5079		return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
5080
5081	}
5082
5083	clampPoint( point, target ) {
5084
5085		const deltaLengthSq = this.center.distanceToSquared( point );
5086
5087		target.copy( point );
5088
5089		if ( deltaLengthSq > ( this.radius * this.radius ) ) {
5090
5091			target.sub( this.center ).normalize();
5092			target.multiplyScalar( this.radius ).add( this.center );
5093
5094		}
5095
5096		return target;
5097
5098	}
5099
5100	getBoundingBox( target ) {
5101
5102		if ( this.isEmpty() ) {
5103
5104			// Empty sphere produces empty bounding box
5105			target.makeEmpty();
5106			return target;
5107
5108		}
5109
5110		target.set( this.center, this.center );
5111		target.expandByScalar( this.radius );
5112
5113		return target;
5114
5115	}
5116
5117	applyMatrix4( matrix ) {
5118
5119		this.center.applyMatrix4( matrix );
5120		this.radius = this.radius * matrix.getMaxScaleOnAxis();
5121
5122		return this;
5123
5124	}
5125
5126	translate( offset ) {
5127
5128		this.center.add( offset );
5129
5130		return this;
5131
5132	}
5133
5134	expandByPoint( point ) {
5135
5136		if ( this.isEmpty() ) {
5137
5138			this.center.copy( point );
5139
5140			this.radius = 0;
5141
5142			return this;
5143
5144		}
5145
5146		_v1$6.subVectors( point, this.center );
5147
5148		const lengthSq = _v1$6.lengthSq();
5149
5150		if ( lengthSq > ( this.radius * this.radius ) ) {
5151
5152			// calculate the minimal sphere
5153
5154			const length = Math.sqrt( lengthSq );
5155
5156			const delta = ( length - this.radius ) * 0.5;
5157
5158			this.center.addScaledVector( _v1$6, delta / length );
5159
5160			this.radius += delta;
5161
5162		}
5163
5164		return this;
5165
5166	}
5167
5168	union( sphere ) {
5169
5170		if ( sphere.isEmpty() ) {
5171
5172			return this;
5173
5174		}
5175
5176		if ( this.isEmpty() ) {
5177
5178			this.copy( sphere );
5179
5180			return this;
5181
5182		}
5183
5184		if ( this.center.equals( sphere.center ) === true ) {
5185
5186			 this.radius = Math.max( this.radius, sphere.radius );
5187
5188		} else {
5189
5190			_v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius );
5191
5192			this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) );
5193
5194			this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) );
5195
5196		}
5197
5198		return this;
5199
5200	}
5201
5202	equals( sphere ) {
5203
5204		return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
5205
5206	}
5207
5208	clone() {
5209
5210		return new this.constructor().copy( this );
5211
5212	}
5213
5214}
5215
5216const _vector$a = /*@__PURE__*/ new Vector3();
5217const _segCenter = /*@__PURE__*/ new Vector3();
5218const _segDir = /*@__PURE__*/ new Vector3();
5219const _diff = /*@__PURE__*/ new Vector3();
5220
5221const _edge1 = /*@__PURE__*/ new Vector3();
5222const _edge2 = /*@__PURE__*/ new Vector3();
5223const _normal$1 = /*@__PURE__*/ new Vector3();
5224
5225class Ray {
5226
5227	constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 
vendor: 8,510 bytes, lines 5227-5633
52271 ) ) {
5228
5229		this.origin = origin;
5230		this.direction = direction;
5231
5232	}
5233
5234	set( origin, direction ) {
5235
5236		this.origin.copy( origin );
5237		this.direction.copy( direction );
5238
5239		return this;
5240
5241	}
5242
5243	copy( ray ) {
5244
5245		this.origin.copy( ray.origin );
5246		this.direction.copy( ray.direction );
5247
5248		return this;
5249
5250	}
5251
5252	at( t, target ) {
5253
5254		return target.copy( this.origin ).addScaledVector( this.direction, t );
5255
5256	}
5257
5258	lookAt( v ) {
5259
5260		this.direction.copy( v ).sub( this.origin ).normalize();
5261
5262		return this;
5263
5264	}
5265
5266	recast( t ) {
5267
5268		this.origin.copy( this.at( t, _vector$a ) );
5269
5270		return this;
5271
5272	}
5273
5274	closestPointToPoint( point, target ) {
5275
5276		target.subVectors( point, this.origin );
5277
5278		const directionDistance = target.dot( this.direction );
5279
5280		if ( directionDistance < 0 ) {
5281
5282			return target.copy( this.origin );
5283
5284		}
5285
5286		return target.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5287
5288	}
5289
5290	distanceToPoint( point ) {
5291
5292		return Math.sqrt( this.distanceSqToPoint( point ) );
5293
5294	}
5295
5296	distanceSqToPoint( point ) {
5297
5298		const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction );
5299
5300		// point behind the ray
5301
5302		if ( directionDistance < 0 ) {
5303
5304			return this.origin.distanceToSquared( point );
5305
5306		}
5307
5308		_vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5309
5310		return _vector$a.distanceToSquared( point );
5311
5312	}
5313
5314	distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
5315
5316		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
5317		// It returns the min distance between the ray and the segment
5318		// defined by v0 and v1
5319		// It can also set two optional targets :
5320		// - The closest point on the ray
5321		// - The closest point on the segment
5322
5323		_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
5324		_segDir.copy( v1 ).sub( v0 ).normalize();
5325		_diff.copy( this.origin ).sub( _segCenter );
5326
5327		const segExtent = v0.distanceTo( v1 ) * 0.5;
5328		const a01 = - this.direction.dot( _segDir );
5329		const b0 = _diff.dot( this.direction );
5330		const b1 = - _diff.dot( _segDir );
5331		const c = _diff.lengthSq();
5332		const det = Math.abs( 1 - a01 * a01 );
5333		let s0, s1, sqrDist, extDet;
5334
5335		if ( det > 0 ) {
5336
5337			// The ray and segment are not parallel.
5338
5339			s0 = a01 * b1 - b0;
5340			s1 = a01 * b0 - b1;
5341			extDet = segExtent * det;
5342
5343			if ( s0 >= 0 ) {
5344
5345				if ( s1 >= - extDet ) {
5346
5347					if ( s1 <= extDet ) {
5348
5349						// region 0
5350						// Minimum at interior points of ray and segment.
5351
5352						const invDet = 1 / det;
5353						s0 *= invDet;
5354						s1 *= invDet;
5355						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
5356
5357					} else {
5358
5359						// region 1
5360
5361						s1 = segExtent;
5362						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5363						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5364
5365					}
5366
5367				} else {
5368
5369					// region 5
5370
5371					s1 = - segExtent;
5372					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5373					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5374
5375				}
5376
5377			} else {
5378
5379				if ( s1 <= - extDet ) {
5380
5381					// region 4
5382
5383					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
5384					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5385					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5386
5387				} else if ( s1 <= extDet ) {
5388
5389					// region 3
5390
5391					s0 = 0;
5392					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
5393					sqrDist = s1 * ( s1 + 2 * b1 ) + c;
5394
5395				} else {
5396
5397					// region 2
5398
5399					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
5400					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5401					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5402
5403				}
5404
5405			}
5406
5407		} else {
5408
5409			// Ray and segment are parallel.
5410
5411			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
5412			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5413			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5414
5415		}
5416
5417		if ( optionalPointOnRay ) {
5418
5419			optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 );
5420
5421		}
5422
5423		if ( optionalPointOnSegment ) {
5424
5425			optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 );
5426
5427		}
5428
5429		return sqrDist;
5430
5431	}
5432
5433	intersectSphere( sphere, target ) {
5434
5435		_vector$a.subVectors( sphere.center, this.origin );
5436		const tca = _vector$a.dot( this.direction );
5437		const d2 = _vector$a.dot( _vector$a ) - tca * tca;
5438		const radius2 = sphere.radius * sphere.radius;
5439
5440		if ( d2 > radius2 ) return null;
5441
5442		const thc = Math.sqrt( radius2 - d2 );
5443
5444		// t0 = first intersect point - entrance on front of sphere
5445		const t0 = tca - thc;
5446
5447		// t1 = second intersect point - exit point on back of sphere
5448		const t1 = tca + thc;
5449
5450		// test to see if t1 is behind the ray - if so, return null
5451		if ( t1 < 0 ) return null;
5452
5453		// test to see if t0 is behind the ray:
5454		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
5455		// in order to always return an intersect point that is in front of the ray.
5456		if ( t0 < 0 ) return this.at( t1, target );
5457
5458		// else t0 is in front of the ray, so return the first collision point scaled by t0
5459		return this.at( t0, target );
5460
5461	}
5462
5463	intersectsSphere( sphere ) {
5464
5465		return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
5466
5467	}
5468
5469	distanceToPlane( plane ) {
5470
5471		const denominator = plane.normal.dot( this.direction );
5472
5473		if ( denominator === 0 ) {
5474
5475			// line is coplanar, return origin
5476			if ( plane.distanceToPoint( this.origin ) === 0 ) {
5477
5478				return 0;
5479
5480			}
5481
5482			// Null is preferable to undefined since undefined means.... it is undefined
5483
5484			return null;
5485
5486		}
5487
5488		const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
5489
5490		// Return if the ray never intersects the plane
5491
5492		return t >= 0 ? t : null;
5493
5494	}
5495
5496	intersectPlane( plane, target ) {
5497
5498		const t = this.distanceToPlane( plane );
5499
5500		if ( t === null ) {
5501
5502			return null;
5503
5504		}
5505
5506		return this.at( t, target );
5507
5508	}
5509
5510	intersectsPlane( plane ) {
5511
5512		// check if the ray lies on the plane first
5513
5514		const distToPoint = plane.distanceToPoint( this.origin );
5515
5516		if ( distToPoint === 0 ) {
5517
5518			return true;
5519
5520		}
5521
5522		const denominator = plane.normal.dot( this.direction );
5523
5524		if ( denominator * distToPoint < 0 ) {
5525
5526			return true;
5527
5528		}
5529
5530		// ray origin is behind the plane (and is pointing behind it)
5531
5532		return false;
5533
5534	}
5535
5536	intersectBox( box, target ) {
5537
5538		let tmin, tmax, tymin, tymax, tzmin, tzmax;
5539
5540		const invdirx = 1 / this.direction.x,
5541			invdiry = 1 / this.direction.y,
5542			invdirz = 1 / this.direction.z;
5543
5544		const origin = this.origin;
5545
5546		if ( invdirx >= 0 ) {
5547
5548			tmin = ( box.min.x - origin.x ) * invdirx;
5549			tmax = ( box.max.x - origin.x ) * invdirx;
5550
5551		} else {
5552
5553			tmin = ( box.max.x - origin.x ) * invdirx;
5554			tmax = ( box.min.x - origin.x ) * invdirx;
5555
5556		}
5557
5558		if ( invdiry >= 0 ) {
5559
5560			tymin = ( box.min.y - origin.y ) * invdiry;
5561			tymax = ( box.max.y - origin.y ) * invdiry;
5562
5563		} else {
5564
5565			tymin = ( box.max.y - origin.y ) * invdiry;
5566			tymax = ( box.min.y - origin.y ) * invdiry;
5567
5568		}
5569
5570		if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
5571
5572		if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin;
5573
5574		if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax;
5575
5576		if ( invdirz >= 0 ) {
5577
5578			tzmin = ( box.min.z - origin.z ) * invdirz;
5579			tzmax = ( box.max.z - origin.z ) * invdirz;
5580
5581		} else {
5582
5583			tzmin = ( box.max.z - origin.z ) * invdirz;
5584			tzmax = ( box.min.z - origin.z ) * invdirz;
5585
5586		}
5587
5588		if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
5589
5590		if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
5591
5592		if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
5593
5594		//return point closest to the ray (positive side)
5595
5596		if ( tmax < 0 ) return null;
5597
5598		return this.at( tmin >= 0 ? tmin : tmax, target );
5599
5600	}
5601
5602	intersectsBox( box ) {
5603
5604		return this.intersectBox( box, _vector$a ) !== null;
5605
5606	}
5607
5608	intersectTriangle( a, b, c, backfaceCulling, target ) {
5609
5610		// Compute the offset origin, edges, and normal.
5611
5612		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
5613
5614		_edge1.subVectors( b, a );
5615		_edge2.subVectors( c, a );
5616		_normal$1.crossVectors( _edge1, _edge2 );
5617
5618		// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
5619		// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
5620		//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
5621		//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
5622		//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
5623		let DdN = this.direction.dot( _normal$1 );
5624		let sign;
5625
5626		if ( DdN > 0 ) {
5627
5628			if ( backfaceCulling ) return null;
5629			sign = 1;
5630
5631		} else if ( DdN < 0 ) {
5632
5633			sign = -
5633 1;
5634			DdN = - DdN;
5635
5636		} else {
5637
5638			return null;
5639
5640		}
5641
5642		_diff.subVectors( this.origin, a );
5643		const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
5644
5645		// b1 < 0, no intersection
5646		if ( DdQxE2 < 0 ) {
5647
5648			return null;
5649
5650		}
5651
5652		const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
5653
5654		// b2 < 0, no intersection
5655		if ( DdE1xQ < 0 ) {
5656
5657			return null;
5658
5659		}
5660
5661		// b1+b2 > 1, no intersection
5662		if ( DdQxE2 + DdE1xQ > DdN ) {
5663
5664			return null;
5665
5666		}
5667
5668		// Line intersects triangle, check if ray does.
vendor: 661 bytes, lines 5669-5719
5669		const QdN = - sign * _diff.dot( _normal$1 );
5670
5671		// t < 0, no intersection
5672		if ( QdN < 0 ) {
5673
5674			return null;
5675
5676		}
5677
5678		// Ray intersects triangle.
5679		return this.at( QdN / DdN, target );
5680
5681	}
5682
5683	applyMatrix4( matrix4 ) {
5684
5685		this.origin.applyMatrix4( matrix4 );
5686		this.direction.transformDirection( matrix4 );
5687
5688		return this;
5689
5690	}
5691
5692	equals( ray ) {
5693
5694		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
5695
5696	}
5697
5698	clone() {
5699
5700		return new this.constructor().copy( this );
5701
5702	}
5703
5704}
5705
5706class Matrix4 {
5707
5708	constructor() {
5709
5710		Matrix4.prototype.isMatrix4 = true;
5711
5712		this.elements = [
5713
5714			1, 0, 0, 0,
5715			0, 1, 0, 0,
5716			0, 0, 1, 0,
5717			0, 0, 0, 1
5718
5719		];
vendor: 12,702 bytes, lines 5719-6260
5719
5720
5721	}
5722
5723	set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5724
5725		const te = this.elements;
5726
5727		te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
5728		te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
5729		te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
5730		te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
5731
5732		return this;
5733
5734	}
5735
5736	identity() {
5737
5738		this.set(
5739
5740			1, 0, 0, 0,
5741			0, 1, 0, 0,
5742			0, 0, 1, 0,
5743			0, 0, 0, 1
5744
5745		);
5746
5747		return this;
5748
5749	}
5750
5751	clone() {
5752
5753		return new Matrix4().fromArray( this.elements );
5754
5755	}
5756
5757	copy( m ) {
5758
5759		const te = this.elements;
5760		const me = m.elements;
5761
5762		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
5763		te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
5764		te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
5765		te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
5766
5767		return this;
5768
5769	}
5770
5771	copyPosition( m ) {
5772
5773		const te = this.elements, me = m.elements;
5774
5775		te[ 12 ] = me[ 12 ];
5776		te[ 13 ] = me[ 13 ];
5777		te[ 14 ] = me[ 14 ];
5778
5779		return this;
5780
5781	}
5782
5783	setFromMatrix3( m ) {
5784
5785		const me = m.elements;
5786
5787		this.set(
5788
5789			me[ 0 ], me[ 3 ], me[ 6 ], 0,
5790			me[ 1 ], me[ 4 ], me[ 7 ], 0,
5791			me[ 2 ], me[ 5 ], me[ 8 ], 0,
5792			0, 0, 0, 1
5793
5794		);
5795
5796		return this;
5797
5798	}
5799
5800	extractBasis( xAxis, yAxis, zAxis ) {
5801
5802		xAxis.setFromMatrixColumn( this, 0 );
5803		yAxis.setFromMatrixColumn( this, 1 );
5804		zAxis.setFromMatrixColumn( this, 2 );
5805
5806		return this;
5807
5808	}
5809
5810	makeBasis( xAxis, yAxis, zAxis ) {
5811
5812		this.set(
5813			xAxis.x, yAxis.x, zAxis.x, 0,
5814			xAxis.y, yAxis.y, zAxis.y, 0,
5815			xAxis.z, yAxis.z, zAxis.z, 0,
5816			0, 0, 0, 1
5817		);
5818
5819		return this;
5820
5821	}
5822
5823	extractRotation( m ) {
5824
5825		// this method does not support reflection matrices
5826
5827		const te = this.elements;
5828		const me = m.elements;
5829
5830		const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length();
5831		const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length();
5832		const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length();
5833
5834		te[ 0 ] = me[ 0 ] * scaleX;
5835		te[ 1 ] = me[ 1 ] * scaleX;
5836		te[ 2 ] = me[ 2 ] * scaleX;
5837		te[ 3 ] = 0;
5838
5839		te[ 4 ] = me[ 4 ] * scaleY;
5840		te[ 5 ] = me[ 5 ] * scaleY;
5841		te[ 6 ] = me[ 6 ] * scaleY;
5842		te[ 7 ] = 0;
5843
5844		te[ 8 ] = me[ 8 ] * scaleZ;
5845		te[ 9 ] = me[ 9 ] * scaleZ;
5846		te[ 10 ] = me[ 10 ] * scaleZ;
5847		te[ 11 ] = 0;
5848
5849		te[ 12 ] = 0;
5850		te[ 13 ] = 0;
5851		te[ 14 ] = 0;
5852		te[ 15 ] = 1;
5853
5854		return this;
5855
5856	}
5857
5858	makeRotationFromEuler( euler ) {
5859
5860		const te = this.elements;
5861
5862		const x = euler.x, y = euler.y, z = euler.z;
5863		const a = Math.cos( x ), b = Math.sin( x );
5864		const c = Math.cos( y ), d = Math.sin( y );
5865		const e = Math.cos( z ), f = Math.sin( z );
5866
5867		if ( euler.order === 'XYZ' ) {
5868
5869			const ae = a * e, af = a * f, be = b * e, bf = b * f;
5870
5871			te[ 0 ] = c * e;
5872			te[ 4 ] = - c * f;
5873			te[ 8 ] = d;
5874
5875			te[ 1 ] = af + be * d;
5876			te[ 5 ] = ae - bf * d;
5877			te[ 9 ] = - b * c;
5878
5879			te[ 2 ] = bf - ae * d;
5880			te[ 6 ] = be + af * d;
5881			te[ 10 ] = a * c;
5882
5883		} else if ( euler.order === 'YXZ' ) {
5884
5885			const ce = c * e, cf = c * f, de = d * e, df = d * f;
5886
5887			te[ 0 ] = ce + df * b;
5888			te[ 4 ] = de * b - cf;
5889			te[ 8 ] = a * d;
5890
5891			te[ 1 ] = a * f;
5892			te[ 5 ] = a * e;
5893			te[ 9 ] = - b;
5894
5895			te[ 2 ] = cf * b - de;
5896			te[ 6 ] = df + ce * b;
5897			te[ 10 ] = a * c;
5898
5899		} else if ( euler.order === 'ZXY' ) {
5900
5901			const ce = c * e, cf = c * f, de = d * e, df = d * f;
5902
5903			te[ 0 ] = ce - df * b;
5904			te[ 4 ] = - a * f;
5905			te[ 8 ] = de + cf * b;
5906
5907			te[ 1 ] = cf + de * b;
5908			te[ 5 ] = a * e;
5909			te[ 9 ] = df - ce * b;
5910
5911			te[ 2 ] = - a * d;
5912			te[ 6 ] = b;
5913			te[ 10 ] = a * c;
5914
5915		} else if ( euler.order === 'ZYX' ) {
5916
5917			const ae = a * e, af = a * f, be = b * e, bf = b * f;
5918
5919			te[ 0 ] = c * e;
5920			te[ 4 ] = be * d - af;
5921			te[ 8 ] = ae * d + bf;
5922
5923			te[ 1 ] = c * f;
5924			te[ 5 ] = bf * d + ae;
5925			te[ 9 ] = af * d - be;
5926
5927			te[ 2 ] = - d;
5928			te[ 6 ] = b * c;
5929			te[ 10 ] = a * c;
5930
5931		} else if ( euler.order === 'YZX' ) {
5932
5933			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5934
5935			te[ 0 ] = c * e;
5936			te[ 4 ] = bd - ac * f;
5937			te[ 8 ] = bc * f + ad;
5938
5939			te[ 1 ] = f;
5940			te[ 5 ] = a * e;
5941			te[ 9 ] = - b * e;
5942
5943			te[ 2 ] = - d * e;
5944			te[ 6 ] = ad * f + bc;
5945			te[ 10 ] = ac - bd * f;
5946
5947		} else if ( euler.order === 'XZY' ) {
5948
5949			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
5950
5951			te[ 0 ] = c * e;
5952			te[ 4 ] = - f;
5953			te[ 8 ] = d * e;
5954
5955			te[ 1 ] = ac * f + bd;
5956			te[ 5 ] = a * e;
5957			te[ 9 ] = ad * f - bc;
5958
5959			te[ 2 ] = bc * f - ad;
5960			te[ 6 ] = b * e;
5961			te[ 10 ] = bd * f + ac;
5962
5963		}
5964
5965		// bottom row
5966		te[ 3 ] = 0;
5967		te[ 7 ] = 0;
5968		te[ 11 ] = 0;
5969
5970		// last column
5971		te[ 12 ] = 0;
5972		te[ 13 ] = 0;
5973		te[ 14 ] = 0;
5974		te[ 15 ] = 1;
5975
5976		return this;
5977
5978	}
5979
5980	makeRotationFromQuaternion( q ) {
5981
5982		return this.compose( _zero, q, _one );
5983
5984	}
5985
5986	lookAt( eye, target, up ) {
5987
5988		const te = this.elements;
5989
5990		_z.subVectors( eye, target );
5991
5992		if ( _z.lengthSq() === 0 ) {
5993
5994			// eye and target are in the same position
5995
5996			_z.z = 1;
5997
5998		}
5999
6000		_z.normalize();
6001		_x.crossVectors( up, _z );
6002
6003		if ( _x.lengthSq() === 0 ) {
6004
6005			// up and z are parallel
6006
6007			if ( Math.abs( up.z ) === 1 ) {
6008
6009				_z.x += 0.0001;
6010
6011			} else {
6012
6013				_z.z += 0.0001;
6014
6015			}
6016
6017			_z.normalize();
6018			_x.crossVectors( up, _z );
6019
6020		}
6021
6022		_x.normalize();
6023		_y.crossVectors( _z, _x );
6024
6025		te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
6026		te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
6027		te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
6028
6029		return this;
6030
6031	}
6032
6033	multiply( m ) {
6034
6035		return this.multiplyMatrices( this, m );
6036
6037	}
6038
6039	premultiply( m ) {
6040
6041		return this.multiplyMatrices( m, this );
6042
6043	}
6044
6045	multiplyMatrices( a, b ) {
6046
6047		const ae = a.elements;
6048		const be = b.elements;
6049		const te = this.elements;
6050
6051		const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
6052		const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
6053		const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
6054		const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
6055
6056		const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
6057		const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
6058		const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
6059		const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
6060
6061		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
6062		te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
6063		te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
6064		te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
6065
6066		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
6067		te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
6068		te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
6069		te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
6070
6071		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
6072		te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
6073		te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
6074		te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
6075
6076		te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
6077		te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
6078		te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
6079		te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
6080
6081		return this;
6082
6083	}
6084
6085	multiplyScalar( s ) {
6086
6087		const te = this.elements;
6088
6089		te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
6090		te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
6091		te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
6092		te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
6093
6094		return this;
6095
6096	}
6097
6098	determinant() {
6099
6100		const te = this.elements;
6101
6102		const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
6103		const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
6104		const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
6105		const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
6106
6107		//TODO: make this more efficient
6108		//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
6109
6110		return (
6111			n41 * (
6112				+ n14 * n23 * n32
6113				 - n13 * n24 * n32
6114				 - n14 * n22 * n33
6115				 + n12 * n24 * n33
6116				 + n13 * n22 * n34
6117				 - n12 * n23 * n34
6118			) +
6119			n42 * (
6120				+ n11 * n23 * n34
6121				 - n11 * n24 * n33
6122				 + n14 * n21 * n33
6123				 - n13 * n21 * n34
6124				 + n13 * n24 * n31
6125				 - n14 * n23 * n31
6126			) +
6127			n43 * (
6128				+ n11 * n24 * n32
6129				 - n11 * n22 * n34
6130				 - n14 * n21 * n32
6131				 + n12 * n21 * n34
6132				 + n14 * n22 * n31
6133				 - n12 * n24 * n31
6134			) +
6135			n44 * (
6136				- n13 * n22 * n31
6137				 - n11 * n23 * n32
6138				 + n11 * n22 * n33
6139				 + n13 * n21 * n32
6140				 - n12 * n21 * n33
6141				 + n12 * n23 * n31
6142			)
6143
6144		);
6145
6146	}
6147
6148	transpose() {
6149
6150		const te = this.elements;
6151		let tmp;
6152
6153		tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
6154		tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
6155		tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
6156
6157		tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
6158		tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
6159		tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
6160
6161		return this;
6162
6163	}
6164
6165	setPosition( x, y, z ) {
6166
6167		const te = this.elements;
6168
6169		if ( x.isVector3 ) {
6170
6171			te[ 12 ] = x.x;
6172			te[ 13 ] = x.y;
6173			te[ 14 ] = x.z;
6174
6175		} else {
6176
6177			te[ 12 ] = x;
6178			te[ 13 ] = y;
6179			te[ 14 ] = z;
6180
6181		}
6182
6183		return this;
6184
6185	}
6186
6187	invert() {
6188
6189		// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
6190		const te = this.elements,
6191
6192			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
6193			n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
6194			n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
6195			n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
6196
6197			t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
6198			t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
6199			t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
6200			t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
6201
6202		const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
6203
6204		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
6205
6206		const detInv = 1 / det;
6207
6208		te[ 0 ] = t11 * detInv;
6209		te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
6210		te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
6211		te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
6212
6213		te[ 4 ] = t12 * detInv;
6214		te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
6215		te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
6216		te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
6217
6218		te[ 8 ] = t13 * detInv;
6219		te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
6220		te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
6221		te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
6222
6223		te[ 12 ] = t14 * detInv;
6224		te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
6225		te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
6226		te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
6227
6228		return this;
6229
6230	}
6231
6232	scale( v ) {
6233
6234		const te = this.elements;
6235		const x = v.x, y = v.y, z = v.z;
6236
6237		te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
6238		te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
6239		te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
6240		te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
6241
6242		return this;
6243
6244	}
6245
6246	getMaxScaleOnAxis() {
6247
6248		const te = this.elements;
6249
6250		const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
6251		const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
6252		const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
6253
6254		return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
6255
6256	}
6257
6258	makeTranslation( x, y, z ) {
6259
6260		
vendor: 2,013 bytes, lines 6260-6398
6260this.set(
6261
6262			1, 0, 0, x,
6263			0, 1, 0, y,
6264			0, 0, 1, z,
6265			0, 0, 0, 1
6266
6267		);
6268
6269		return this;
6270
6271	}
6272
6273	makeRotationX( theta ) {
6274
6275		const c = Math.cos( theta ), s = Math.sin( theta );
6276
6277		this.set(
6278
6279			1, 0, 0, 0,
6280			0, c, - s, 0,
6281			0, s, c, 0,
6282			0, 0, 0, 1
6283
6284		);
6285
6286		return this;
6287
6288	}
6289
6290	makeRotationY( theta ) {
6291
6292		const c = Math.cos( theta ), s = Math.sin( theta );
6293
6294		this.set(
6295
6296			 c, 0, s, 0,
6297			 0, 1, 0, 0,
6298			- s, 0, c, 0,
6299			 0, 0, 0, 1
6300
6301		);
6302
6303		return this;
6304
6305	}
6306
6307	makeRotationZ( theta ) {
6308
6309		const c = Math.cos( theta ), s = Math.sin( theta );
6310
6311		this.set(
6312
6313			c, - s, 0, 0,
6314			s, c, 0, 0,
6315			0, 0, 1, 0,
6316			0, 0, 0, 1
6317
6318		);
6319
6320		return this;
6321
6322	}
6323
6324	makeRotationAxis( axis, angle ) {
6325
6326		// Based on http://www.gamedev.net/reference/articles/article1199.asp
6327
6328		const c = Math.cos( angle );
6329		const s = Math.sin( angle );
6330		const t = 1 - c;
6331		const x = axis.x, y = axis.y, z = axis.z;
6332		const tx = t * x, ty = t * y;
6333
6334		this.set(
6335
6336			tx * x + c, tx * y - s * z, tx * z + s * y, 0,
6337			tx * y + s * z, ty * y + c, ty * z - s * x, 0,
6338			tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
6339			0, 0, 0, 1
6340
6341		);
6342
6343		return this;
6344
6345	}
6346
6347	makeScale( x, y, z ) {
6348
6349		this.set(
6350
6351			x, 0, 0, 0,
6352			0, y, 0, 0,
6353			0, 0, z, 0,
6354			0, 0, 0, 1
6355
6356		);
6357
6358		return this;
6359
6360	}
6361
6362	makeShear( xy, xz, yx, yz, zx, zy ) {
6363
6364		this.set(
6365
6366			1, yx, zx, 0,
6367			xy, 1, zy, 0,
6368			xz, yz, 1, 0,
6369			0, 0, 0, 1
6370
6371		);
6372
6373		return this;
6374
6375	}
6376
6377	compose( position, quaternion, scale ) {
6378
6379		const te = this.elements;
6380
6381		const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
6382		const x2 = x + x,	y2 = y + y, z2 = z + z;
6383		const xx = x * x2, xy = x * y2, xz = x * z2;
6384		const yy = y * y2, yz = y * z2, zz = z * z2;
6385		const wx = w * x2, wy = w * y2, wz = w * z2;
6386
6387		const sx = scale.x, sy = scale.y, sz = scale.z;
6388
6389		te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
6390		te[ 1 ] = ( xy + wz ) * sx;
6391		te[ 2 ] = ( xz - wy ) * sx;
6392		te[ 3 ] = 0;
6393
6394		te[ 4 ] = ( xy - wz ) * sy;
6395		te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
6396		te[ 6 ] = ( yz + wx ) * sy;
6397		te[ 7 ] = 0;
6398
vendor: 4,294 bytes, lines 6399-6620
6399		te[ 8 ] = ( xz + wy ) * sz;
6400		te[ 9 ] = ( yz - wx ) * sz;
6401		te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
6402		te[ 11 ] = 0;
6403
6404		te[ 12 ] = position.x;
6405		te[ 13 ] = position.y;
6406		te[ 14 ] = position.z;
6407		te[ 15 ] = 1;
6408
6409		return this;
6410
6411	}
6412
6413	decompose( position, quaternion, scale ) {
6414
6415		const te = this.elements;
6416
6417		let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
6418		const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
6419		const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
6420
6421		// if determine is negative, we need to invert one scale
6422		const det = this.determinant();
6423		if ( det < 0 ) sx = - sx;
6424
6425		position.x = te[ 12 ];
6426		position.y = te[ 13 ];
6427		position.z = te[ 14 ];
6428
6429		// scale the rotation part
6430		_m1$2.copy( this );
6431
6432		const invSX = 1 / sx;
6433		const invSY = 1 / sy;
6434		const invSZ = 1 / sz;
6435
6436		_m1$2.elements[ 0 ] *= invSX;
6437		_m1$2.elements[ 1 ] *= invSX;
6438		_m1$2.elements[ 2 ] *= invSX;
6439
6440		_m1$2.elements[ 4 ] *= invSY;
6441		_m1$2.elements[ 5 ] *= invSY;
6442		_m1$2.elements[ 6 ] *= invSY;
6443
6444		_m1$2.elements[ 8 ] *= invSZ;
6445		_m1$2.elements[ 9 ] *= invSZ;
6446		_m1$2.elements[ 10 ] *= invSZ;
6447
6448		quaternion.setFromRotationMatrix( _m1$2 );
6449
6450		scale.x = sx;
6451		scale.y = sy;
6452		scale.z = sz;
6453
6454		return this;
6455
6456	}
6457
6458	makePerspective( left, right, top, bottom, near, far ) {
6459
6460		const te = this.elements;
6461		const x = 2 * near / ( right - left );
6462		const y = 2 * near / ( top - bottom );
6463
6464		const a = ( right + left ) / ( right - left );
6465		const b = ( top + bottom ) / ( top - bottom );
6466		const c = - ( far + near ) / ( far - near );
6467		const d = - 2 * far * near / ( far - near );
6468
6469		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a;	te[ 12 ] = 0;
6470		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b;	te[ 13 ] = 0;
6471		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c;	te[ 14 ] = d;
6472		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
6473
6474		return this;
6475
6476	}
6477
6478	makeOrthographic( left, right, top, bottom, near, far ) {
6479
6480		const te = this.elements;
6481		const w = 1.0 / ( right - left );
6482		const h = 1.0 / ( top - bottom );
6483		const p = 1.0 / ( far - near );
6484
6485		const x = ( right + left ) * w;
6486		const y = ( top + bottom ) * h;
6487		const z = ( far + near ) * p;
6488
6489		te[ 0 ] = 2 * w;	te[ 4 ] = 0;	te[ 8 ] = 0;	te[ 12 ] = - x;
6490		te[ 1 ] = 0;	te[ 5 ] = 2 * h;	te[ 9 ] = 0;	te[ 13 ] = - y;
6491		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = - 2 * p;	te[ 14 ] = - z;
6492		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = 0;	te[ 15 ] = 1;
6493
6494		return this;
6495
6496	}
6497
6498	equals( matrix ) {
6499
6500		const te = this.elements;
6501		const me = matrix.elements;
6502
6503		for ( let i = 0; i < 16; i ++ ) {
6504
6505			if ( te[ i ] !== me[ i ] ) return false;
6506
6507		}
6508
6509		return true;
6510
6511	}
6512
6513	fromArray( array, offset = 0 ) {
6514
6515		for ( let i = 0; i < 16; i ++ ) {
6516
6517			this.elements[ i ] = array[ i + offset ];
6518
6519		}
6520
6521		return this;
6522
6523	}
6524
6525	toArray( array = [], offset = 0 ) {
6526
6527		const te = this.elements;
6528
6529		array[ offset ] = te[ 0 ];
6530		array[ offset + 1 ] = te[ 1 ];
6531		array[ offset + 2 ] = te[ 2 ];
6532		array[ offset + 3 ] = te[ 3 ];
6533
6534		array[ offset + 4 ] = te[ 4 ];
6535		array[ offset + 5 ] = te[ 5 ];
6536		array[ offset + 6 ] = te[ 6 ];
6537		array[ offset + 7 ] = te[ 7 ];
6538
6539		array[ offset + 8 ] = te[ 8 ];
6540		array[ offset + 9 ] = te[ 9 ];
6541		array[ offset + 10 ] = te[ 10 ];
6542		array[ offset + 11 ] = te[ 11 ];
6543
6544		array[ offset + 12 ] = te[ 12 ];
6545		array[ offset + 13 ] = te[ 13 ];
6546		array[ offset + 14 ] = te[ 14 ];
6547		array[ offset + 15 ] = te[ 15 ];
6548
6549		return array;
6550
6551	}
6552
6553}
6554
6555const _v1$5 = /*@__PURE__*/ new Vector3();
6556const _m1$2 = /*@__PURE__*/ new Matrix4();
6557const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
6558const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
6559const _x = /*@__PURE__*/ new Vector3();
6560const _y = /*@__PURE__*/ new Vector3();
6561const _z = /*@__PURE__*/ new Vector3();
6562
6563const _matrix$1 = /*@__PURE__*/ new Matrix4();
6564const _quaternion$3 = /*@__PURE__*/ new Quaternion();
6565
6566class Euler {
6567
6568	constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) {
6569
6570		this.isEuler = true;
6571
6572		this._x = x;
6573		this._y = y;
6574		this._z = z;
6575		this._order = order;
6576
6577	}
6578
6579	get x() {
6580
6581		return this._x;
6582
6583	}
6584
6585	set x( value ) {
6586
6587		this._x = value;
6588		this._onChangeCallback();
6589
6590	}
6591
6592	get y() {
6593
6594		return this._y;
6595
6596	}
6597
6598	set y( value ) {
6599
6600		this._y = value;
6601		this._onChangeCallback();
6602
6603	}
6604
6605	get z() {
6606
6607		return this._z;
6608
6609	}
6610
6611	set z( value ) {
6612
6613		this._z = value;
6614		this._onChangeCallback();
6615
6616	}
6617
6618	get order() {
6619
6620		return this._order;
vendor: 23,201 bytes, lines 6621-7937
6621
6622	}
6623
6624	set order( value ) {
6625
6626		this._order = value;
6627		this._onChangeCallback();
6628
6629	}
6630
6631	set( x, y, z, order = this._order ) {
6632
6633		this._x = x;
6634		this._y = y;
6635		this._z = z;
6636		this._order = order;
6637
6638		this._onChangeCallback();
6639
6640		return this;
6641
6642	}
6643
6644	clone() {
6645
6646		return new this.constructor( this._x, this._y, this._z, this._order );
6647
6648	}
6649
6650	copy( euler ) {
6651
6652		this._x = euler._x;
6653		this._y = euler._y;
6654		this._z = euler._z;
6655		this._order = euler._order;
6656
6657		this._onChangeCallback();
6658
6659		return this;
6660
6661	}
6662
6663	setFromRotationMatrix( m, order = this._order, update = true ) {
6664
6665		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6666
6667		const te = m.elements;
6668		const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
6669		const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
6670		const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
6671
6672		switch ( order ) {
6673
6674			case 'XYZ':
6675
6676				this._y = Math.asin( clamp( m13, - 1, 1 ) );
6677
6678				if ( Math.abs( m13 ) < 0.9999999 ) {
6679
6680					this._x = Math.atan2( - m23, m33 );
6681					this._z = Math.atan2( - m12, m11 );
6682
6683				} else {
6684
6685					this._x = Math.atan2( m32, m22 );
6686					this._z = 0;
6687
6688				}
6689
6690				break;
6691
6692			case 'YXZ':
6693
6694				this._x = Math.asin( - clamp( m23, - 1, 1 ) );
6695
6696				if ( Math.abs( m23 ) < 0.9999999 ) {
6697
6698					this._y = Math.atan2( m13, m33 );
6699					this._z = Math.atan2( m21, m22 );
6700
6701				} else {
6702
6703					this._y = Math.atan2( - m31, m11 );
6704					this._z = 0;
6705
6706				}
6707
6708				break;
6709
6710			case 'ZXY':
6711
6712				this._x = Math.asin( clamp( m32, - 1, 1 ) );
6713
6714				if ( Math.abs( m32 ) < 0.9999999 ) {
6715
6716					this._y = Math.atan2( - m31, m33 );
6717					this._z = Math.atan2( - m12, m22 );
6718
6719				} else {
6720
6721					this._y = 0;
6722					this._z = Math.atan2( m21, m11 );
6723
6724				}
6725
6726				break;
6727
6728			case 'ZYX':
6729
6730				this._y = Math.asin( - clamp( m31, - 1, 1 ) );
6731
6732				if ( Math.abs( m31 ) < 0.9999999 ) {
6733
6734					this._x = Math.atan2( m32, m33 );
6735					this._z = Math.atan2( m21, m11 );
6736
6737				} else {
6738
6739					this._x = 0;
6740					this._z = Math.atan2( - m12, m22 );
6741
6742				}
6743
6744				break;
6745
6746			case 'YZX':
6747
6748				this._z = Math.asin( clamp( m21, - 1, 1 ) );
6749
6750				if ( Math.abs( m21 ) < 0.9999999 ) {
6751
6752					this._x = Math.atan2( - m23, m22 );
6753					this._y = Math.atan2( - m31, m11 );
6754
6755				} else {
6756
6757					this._x = 0;
6758					this._y = Math.atan2( m13, m33 );
6759
6760				}
6761
6762				break;
6763
6764			case 'XZY':
6765
6766				this._z = Math.asin( - clamp( m12, - 1, 1 ) );
6767
6768				if ( Math.abs( m12 ) < 0.9999999 ) {
6769
6770					this._x = Math.atan2( m32, m22 );
6771					this._y = Math.atan2( m13, m11 );
6772
6773				} else {
6774
6775					this._x = Math.atan2( - m23, m33 );
6776					this._y = 0;
6777
6778				}
6779
6780				break;
6781
6782			default:
6783
6784				console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
6785
6786		}
6787
6788		this._order = order;
6789
6790		if ( update === true ) this._onChangeCallback();
6791
6792		return this;
6793
6794	}
6795
6796	setFromQuaternion( q, order, update ) {
6797
6798		_matrix$1.makeRotationFromQuaternion( q );
6799
6800		return this.setFromRotationMatrix( _matrix$1, order, update );
6801
6802	}
6803
6804	setFromVector3( v, order = this._order ) {
6805
6806		return this.set( v.x, v.y, v.z, order );
6807
6808	}
6809
6810	reorder( newOrder ) {
6811
6812		// WARNING: this discards revolution information -bhouston
6813
6814		_quaternion$3.setFromEuler( this );
6815
6816		return this.setFromQuaternion( _quaternion$3, newOrder );
6817
6818	}
6819
6820	equals( euler ) {
6821
6822		return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
6823
6824	}
6825
6826	fromArray( array ) {
6827
6828		this._x = array[ 0 ];
6829		this._y = array[ 1 ];
6830		this._z = array[ 2 ];
6831		if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
6832
6833		this._onChangeCallback();
6834
6835		return this;
6836
6837	}
6838
6839	toArray( array = [], offset = 0 ) {
6840
6841		array[ offset ] = this._x;
6842		array[ offset + 1 ] = this._y;
6843		array[ offset + 2 ] = this._z;
6844		array[ offset + 3 ] = this._order;
6845
6846		return array;
6847
6848	}
6849
6850	_onChange( callback ) {
6851
6852		this._onChangeCallback = callback;
6853
6854		return this;
6855
6856	}
6857
6858	_onChangeCallback() {}
6859
6860	*[ Symbol.iterator ]() {
6861
6862		yield this._x;
6863		yield this._y;
6864		yield this._z;
6865		yield this._order;
6866
6867	}
6868
6869}
6870
6871Euler.DEFAULT_ORDER = 'XYZ';
6872
6873class Layers {
6874
6875	constructor() {
6876
6877		this.mask = 1 | 0;
6878
6879	}
6880
6881	set( channel ) {
6882
6883		this.mask = ( 1 << channel | 0 ) >>> 0;
6884
6885	}
6886
6887	enable( channel ) {
6888
6889		this.mask |= 1 << channel | 0;
6890
6891	}
6892
6893	enableAll() {
6894
6895		this.mask = 0xffffffff | 0;
6896
6897	}
6898
6899	toggle( channel ) {
6900
6901		this.mask ^= 1 << channel | 0;
6902
6903	}
6904
6905	disable( channel ) {
6906
6907		this.mask &= ~ ( 1 << channel | 0 );
6908
6909	}
6910
6911	disableAll() {
6912
6913		this.mask = 0;
6914
6915	}
6916
6917	test( layers ) {
6918
6919		return ( this.mask & layers.mask ) !== 0;
6920
6921	}
6922
6923	isEnabled( channel ) {
6924
6925		return ( this.mask & ( 1 << channel | 0 ) ) !== 0;
6926
6927	}
6928
6929}
6930
6931let _object3DId = 0;
6932
6933const _v1$4 = /*@__PURE__*/ new Vector3();
6934const _q1 = /*@__PURE__*/ new Quaternion();
6935const _m1$1 = /*@__PURE__*/ new Matrix4();
6936const _target = /*@__PURE__*/ new Vector3();
6937
6938const _position$3 = /*@__PURE__*/ new Vector3();
6939const _scale$2 = /*@__PURE__*/ new Vector3();
6940const _quaternion$2 = /*@__PURE__*/ new Quaternion();
6941
6942const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
6943const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
6944const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
6945
6946const _addedEvent = { type: 'added' };
6947const _removedEvent = { type: 'removed' };
6948
6949class Object3D extends EventDispatcher {
6950
6951	constructor() {
6952
6953		super();
6954
6955		this.isObject3D = true;
6956
6957		Object.defineProperty( this, 'id', { value: _object3DId ++ } );
6958
6959		this.uuid = generateUUID();
6960
6961		this.name = '';
6962		this.type = 'Object3D';
6963
6964		this.parent = null;
6965		this.children = [];
6966
6967		this.up = Object3D.DEFAULT_UP.clone();
6968
6969		const position = new Vector3();
6970		const rotation = new Euler();
6971		const quaternion = new Quaternion();
6972		const scale = new Vector3( 1, 1, 1 );
6973
6974		function onRotationChange() {
6975
6976			quaternion.setFromEuler( rotation, false );
6977
6978		}
6979
6980		function onQuaternionChange() {
6981
6982			rotation.setFromQuaternion( quaternion, undefined, false );
6983
6984		}
6985
6986		rotation._onChange( onRotationChange );
6987		quaternion._onChange( onQuaternionChange );
6988
6989		Object.defineProperties( this, {
6990			position: {
6991				configurable: true,
6992				enumerable: true,
6993				value: position
6994			},
6995			rotation: {
6996				configurable: true,
6997				enumerable: true,
6998				value: rotation
6999			},
7000			quaternion: {
7001				configurable: true,
7002				enumerable: true,
7003				value: quaternion
7004			},
7005			scale: {
7006				configurable: true,
7007				enumerable: true,
7008				value: scale
7009			},
7010			modelViewMatrix: {
7011				value: new Matrix4()
7012			},
7013			normalMatrix: {
7014				value: new Matrix3()
7015			}
7016		} );
7017
7018		this.matrix = new Matrix4();
7019		this.matrixWorld = new Matrix4();
7020
7021		this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
7022		this.matrixWorldNeedsUpdate = false;
7023
7024		this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
7025
7026		this.layers = new Layers();
7027		this.visible = true;
7028
7029		this.castShadow = false;
7030		this.receiveShadow = false;
7031
7032		this.frustumCulled = true;
7033		this.renderOrder = 0;
7034
7035		this.animations = [];
7036
7037		this.userData = {};
7038
7039	}
7040
7041	onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
7042
7043	onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
7044
7045	applyMatrix4( matrix ) {
7046
7047		if ( this.matrixAutoUpdate ) this.updateMatrix();
7048
7049		this.matrix.premultiply( matrix );
7050
7051		this.matrix.decompose( this.position, this.quaternion, this.scale );
7052
7053	}
7054
7055	applyQuaternion( q ) {
7056
7057		this.quaternion.premultiply( q );
7058
7059		return this;
7060
7061	}
7062
7063	setRotationFromAxisAngle( axis, angle ) {
7064
7065		// assumes axis is normalized
7066
7067		this.quaternion.setFromAxisAngle( axis, angle );
7068
7069	}
7070
7071	setRotationFromEuler( euler ) {
7072
7073		this.quaternion.setFromEuler( euler, true );
7074
7075	}
7076
7077	setRotationFromMatrix( m ) {
7078
7079		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7080
7081		this.quaternion.setFromRotationMatrix( m );
7082
7083	}
7084
7085	setRotationFromQuaternion( q ) {
7086
7087		// assumes q is normalized
7088
7089		this.quaternion.copy( q );
7090
7091	}
7092
7093	rotateOnAxis( axis, angle ) {
7094
7095		// rotate object on axis in object space
7096		// axis is assumed to be normalized
7097
7098		_q1.setFromAxisAngle( axis, angle );
7099
7100		this.quaternion.multiply( _q1 );
7101
7102		return this;
7103
7104	}
7105
7106	rotateOnWorldAxis( axis, angle ) {
7107
7108		// rotate object on axis in world space
7109		// axis is assumed to be normalized
7110		// method assumes no rotated parent
7111
7112		_q1.setFromAxisAngle( axis, angle );
7113
7114		this.quaternion.premultiply( _q1 );
7115
7116		return this;
7117
7118	}
7119
7120	rotateX( angle ) {
7121
7122		return this.rotateOnAxis( _xAxis, angle );
7123
7124	}
7125
7126	rotateY( angle ) {
7127
7128		return this.rotateOnAxis( _yAxis, angle );
7129
7130	}
7131
7132	rotateZ( angle ) {
7133
7134		return this.rotateOnAxis( _zAxis, angle );
7135
7136	}
7137
7138	translateOnAxis( axis, distance ) {
7139
7140		// translate object by distance along axis in object space
7141		// axis is assumed to be normalized
7142
7143		_v1$4.copy( axis ).applyQuaternion( this.quaternion );
7144
7145		this.position.add( _v1$4.multiplyScalar( distance ) );
7146
7147		return this;
7148
7149	}
7150
7151	translateX( distance ) {
7152
7153		return this.translateOnAxis( _xAxis, distance );
7154
7155	}
7156
7157	translateY( distance ) {
7158
7159		return this.translateOnAxis( _yAxis, distance );
7160
7161	}
7162
7163	translateZ( distance ) {
7164
7165		return this.translateOnAxis( _zAxis, distance );
7166
7167	}
7168
7169	localToWorld( vector ) {
7170
7171		this.updateWorldMatrix( true, false );
7172
7173		return vector.applyMatrix4( this.matrixWorld );
7174
7175	}
7176
7177	worldToLocal( vector ) {
7178
7179		this.updateWorldMatrix( true, false );
7180
7181		return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
7182
7183	}
7184
7185	lookAt( x, y, z ) {
7186
7187		// This method does not support objects having non-uniformly-scaled parent(s)
7188
7189		if ( x.isVector3 ) {
7190
7191			_target.copy( x );
7192
7193		} else {
7194
7195			_target.set( x, y, z );
7196
7197		}
7198
7199		const parent = this.parent;
7200
7201		this.updateWorldMatrix( true, false );
7202
7203		_position$3.setFromMatrixPosition( this.matrixWorld );
7204
7205		if ( this.isCamera || this.isLight ) {
7206
7207			_m1$1.lookAt( _position$3, _target, this.up );
7208
7209		} else {
7210
7211			_m1$1.lookAt( _target, _position$3, this.up );
7212
7213		}
7214
7215		this.quaternion.setFromRotationMatrix( _m1$1 );
7216
7217		if ( parent ) {
7218
7219			_m1$1.extractRotation( parent.matrixWorld );
7220			_q1.setFromRotationMatrix( _m1$1 );
7221			this.quaternion.premultiply( _q1.invert() );
7222
7223		}
7224
7225	}
7226
7227	add( object ) {
7228
7229		if ( arguments.length > 1 ) {
7230
7231			for ( let i = 0; i < arguments.length; i ++ ) {
7232
7233				this.add( arguments[ i ] );
7234
7235			}
7236
7237			return this;
7238
7239		}
7240
7241		if ( object === this ) {
7242
7243			console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
7244			return this;
7245
7246		}
7247
7248		if ( object && object.isObject3D ) {
7249
7250			if ( object.parent !== null ) {
7251
7252				object.parent.remove( object );
7253
7254			}
7255
7256			object.parent = this;
7257			this.children.push( object );
7258
7259			object.dispatchEvent( _addedEvent );
7260
7261		} else {
7262
7263			console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
7264
7265		}
7266
7267		return this;
7268
7269	}
7270
7271	remove( object ) {
7272
7273		if ( arguments.length > 1 ) {
7274
7275			for ( let i = 0; i < arguments.length; i ++ ) {
7276
7277				this.remove( arguments[ i ] );
7278
7279			}
7280
7281			return this;
7282
7283		}
7284
7285		const index = this.children.indexOf( object );
7286
7287		if ( index !== - 1 ) {
7288
7289			object.parent = null;
7290			this.children.splice( index, 1 );
7291
7292			object.dispatchEvent( _removedEvent );
7293
7294		}
7295
7296		return this;
7297
7298	}
7299
7300	removeFromParent() {
7301
7302		const parent = this.parent;
7303
7304		if ( parent !== null ) {
7305
7306			parent.remove( this );
7307
7308		}
7309
7310		return this;
7311
7312	}
7313
7314	clear() {
7315
7316		for ( let i = 0; i < this.children.length; i ++ ) {
7317
7318			const object = this.children[ i ];
7319
7320			object.parent = null;
7321
7322			object.dispatchEvent( _removedEvent );
7323
7324		}
7325
7326		this.children.length = 0;
7327
7328		return this;
7329
7330
7331	}
7332
7333	attach( object ) {
7334
7335		// adds object as a child of this, while maintaining the object's world transform
7336
7337		// Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
7338
7339		this.updateWorldMatrix( true, false );
7340
7341		_m1$1.copy( this.matrixWorld ).invert();
7342
7343		if ( object.parent !== null ) {
7344
7345			object.parent.updateWorldMatrix( true, false );
7346
7347			_m1$1.multiply( object.parent.matrixWorld );
7348
7349		}
7350
7351		object.applyMatrix4( _m1$1 );
7352
7353		this.add( object );
7354
7355		object.updateWorldMatrix( false, true );
7356
7357		return this;
7358
7359	}
7360
7361	getObjectById( id ) {
7362
7363		return this.getObjectByProperty( 'id', id );
7364
7365	}
7366
7367	getObjectByName( name ) {
7368
7369		return this.getObjectByProperty( 'name', name );
7370
7371	}
7372
7373	getObjectByProperty( name, value ) {
7374
7375		if ( this[ name ] === value ) return this;
7376
7377		for ( let i = 0, l = this.children.length; i < l; i ++ ) {
7378
7379			const child = this.children[ i ];
7380			const object = child.getObjectByProperty( name, value );
7381
7382			if ( object !== undefined ) {
7383
7384				return object;
7385
7386			}
7387
7388		}
7389
7390		return undefined;
7391
7392	}
7393
7394	getObjectsByProperty( name, value ) {
7395
7396		let result = [];
7397
7398		if ( this[ name ] === value ) result.push( this );
7399
7400		for ( let i = 0, l = this.children.length; i < l; i ++ ) {
7401
7402			const childResult = this.children[ i ].getObjectsByProperty( name, value );
7403
7404			if ( childResult.length > 0 ) {
7405
7406				result = result.concat( childResult );
7407
7408			}
7409
7410		}
7411
7412		return result;
7413
7414	}
7415
7416	getWorldPosition( target ) {
7417
7418		this.updateWorldMatrix( true, false );
7419
7420		return target.setFromMatrixPosition( this.matrixWorld );
7421
7422	}
7423
7424	getWorldQuaternion( target ) {
7425
7426		this.updateWorldMatrix( true, false );
7427
7428		this.matrixWorld.decompose( _position$3, target, _scale$2 );
7429
7430		return target;
7431
7432	}
7433
7434	getWorldScale( target ) {
7435
7436		this.updateWorldMatrix( true, false );
7437
7438		this.matrixWorld.decompose( _position$3, _quaternion$2, target );
7439
7440		return target;
7441
7442	}
7443
7444	getWorldDirection( target ) {
7445
7446		this.updateWorldMatrix( true, false );
7447
7448		const e = this.matrixWorld.elements;
7449
7450		return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
7451
7452	}
7453
7454	raycast( /* raycaster, intersects */ ) {}
7455
7456	traverse( callback ) {
7457
7458		callback( this );
7459
7460		const children = this.children;
7461
7462		for ( let i = 0, l = children.length; i < l; i ++ ) {
7463
7464			children[ i ].traverse( callback );
7465
7466		}
7467
7468	}
7469
7470	traverseVisible( callback ) {
7471
7472		if ( this.visible === false ) return;
7473
7474		callback( this );
7475
7476		const children = this.children;
7477
7478		for ( let i = 0, l = children.length; i < l; i ++ ) {
7479
7480			children[ i ].traverseVisible( callback );
7481
7482		}
7483
7484	}
7485
7486	traverseAncestors( callback ) {
7487
7488		const parent = this.parent;
7489
7490		if ( parent !== null ) {
7491
7492			callback( parent );
7493
7494			parent.traverseAncestors( callback );
7495
7496		}
7497
7498	}
7499
7500	updateMatrix() {
7501
7502		this.matrix.compose( this.position, this.quaternion, this.scale );
7503
7504		this.matrixWorldNeedsUpdate = true;
7505
7506	}
7507
7508	updateMatrixWorld( force ) {
7509
7510		if ( this.matrixAutoUpdate ) this.updateMatrix();
7511
7512		if ( this.matrixWorldNeedsUpdate || force ) {
7513
7514			if ( this.parent === null ) {
7515
7516				this.matrixWorld.copy( this.matrix );
7517
7518			} else {
7519
7520				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
7521
7522			}
7523
7524			this.matrixWorldNeedsUpdate = false;
7525
7526			force = true;
7527
7528		}
7529
7530		// update children
7531
7532		const children = this.children;
7533
7534		for ( let i = 0, l = children.length; i < l; i ++ ) {
7535
7536			const child = children[ i ];
7537
7538			if ( child.matrixWorldAutoUpdate === true || force === true ) {
7539
7540				child.updateMatrixWorld( force );
7541
7542			}
7543
7544		}
7545
7546	}
7547
7548	updateWorldMatrix( updateParents, updateChildren ) {
7549
7550		const parent = this.parent;
7551
7552		if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) {
7553
7554			parent.updateWorldMatrix( true, false );
7555
7556		}
7557
7558		if ( this.matrixAutoUpdate ) this.updateMatrix();
7559
7560		if ( this.parent === null ) {
7561
7562			this.matrixWorld.copy( this.matrix );
7563
7564		} else {
7565
7566			this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
7567
7568		}
7569
7570		// update children
7571
7572		if ( updateChildren === true ) {
7573
7574			const children = this.children;
7575
7576			for ( let i = 0, l = children.length; i < l; i ++ ) {
7577
7578				const child = children[ i ];
7579
7580				if ( child.matrixWorldAutoUpdate === true ) {
7581
7582					child.updateWorldMatrix( false, true );
7583
7584				}
7585
7586			}
7587
7588		}
7589
7590	}
7591
7592	toJSON( meta ) {
7593
7594		// meta is a string when called from JSON.stringify
7595		const isRootObject = ( meta === undefined || typeof meta === 'string' );
7596
7597		const output = {};
7598
7599		// meta is a hash used to collect geometries, materials.
7600		// not providing it implies that this is the root object
7601		// being serialized.
7602		if ( isRootObject ) {
7603
7604			// initialize meta obj
7605			meta = {
7606				geometries: {},
7607				materials: {},
7608				textures: {},
7609				images: {},
7610				shapes: {},
7611				skeletons: {},
7612				animations: {},
7613				nodes: {}
7614			};
7615
7616			output.metadata = {
7617				version: 4.5,
7618				type: 'Object',
7619				generator: 'Object3D.toJSON'
7620			};
7621
7622		}
7623
7624		// standard Object3D serialization
7625
7626		const object = {};
7627
7628		object.uuid = this.uuid;
7629		object.type = this.type;
7630
7631		if ( this.name !== '' ) object.name = this.name;
7632		if ( this.castShadow === true ) object.castShadow = true;
7633		if ( this.receiveShadow === true ) object.receiveShadow = true;
7634		if ( this.visible === false ) object.visible = false;
7635		if ( this.frustumCulled === false ) object.frustumCulled = false;
7636		if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
7637		if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
7638
7639		object.layers = this.layers.mask;
7640		object.matrix = this.matrix.toArray();
7641
7642		if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
7643
7644		// object specific properties
7645
7646		if ( this.isInstancedMesh ) {
7647
7648			object.type = 'InstancedMesh';
7649			object.count = this.count;
7650			object.instanceMatrix = this.instanceMatrix.toJSON();
7651			if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
7652
7653		}
7654
7655		//
7656
7657		function serialize( library, element ) {
7658
7659			if ( library[ element.uuid ] === undefined ) {
7660
7661				library[ element.uuid ] = element.toJSON( meta );
7662
7663			}
7664
7665			return element.uuid;
7666
7667		}
7668
7669		if ( this.isScene ) {
7670
7671			if ( this.background ) {
7672
7673				if ( this.background.isColor ) {
7674
7675					object.background = this.background.toJSON();
7676
7677				} else if ( this.background.isTexture ) {
7678
7679					object.background = this.background.toJSON( meta ).uuid;
7680
7681				}
7682
7683			}
7684
7685			if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
7686
7687				object.environment = this.environment.toJSON( meta ).uuid;
7688
7689			}
7690
7691		} else if ( this.isMesh || this.isLine || this.isPoints ) {
7692
7693			object.geometry = serialize( meta.geometries, this.geometry );
7694
7695			const parameters = this.geometry.parameters;
7696
7697			if ( parameters !== undefined && parameters.shapes !== undefined ) {
7698
7699				const shapes = parameters.shapes;
7700
7701				if ( Array.isArray( shapes ) ) {
7702
7703					for ( let i = 0, l = shapes.length; i < l; i ++ ) {
7704
7705						const shape = shapes[ i ];
7706
7707						serialize( meta.shapes, shape );
7708
7709					}
7710
7711				} else {
7712
7713					serialize( meta.shapes, shapes );
7714
7715				}
7716
7717			}
7718
7719		}
7720
7721		if ( this.isSkinnedMesh ) {
7722
7723			object.bindMode = this.bindMode;
7724			object.bindMatrix = this.bindMatrix.toArray();
7725
7726			if ( this.skeleton !== undefined ) {
7727
7728				serialize( meta.skeletons, this.skeleton );
7729
7730				object.skeleton = this.skeleton.uuid;
7731
7732			}
7733
7734		}
7735
7736		if ( this.material !== undefined ) {
7737
7738			if ( Array.isArray( this.material ) ) {
7739
7740				const uuids = [];
7741
7742				for ( let i = 0, l = this.material.length; i < l; i ++ ) {
7743
7744					uuids.push( serialize( meta.materials, this.material[ i ] ) );
7745
7746				}
7747
7748				object.material = uuids;
7749
7750			} else {
7751
7752				object.material = serialize( meta.materials, this.material );
7753
7754			}
7755
7756		}
7757
7758		//
7759
7760		if ( this.children.length > 0 ) {
7761
7762			object.children = [];
7763
7764			for ( let i = 0; i < this.children.length; i ++ ) {
7765
7766				object.children.push( this.children[ i ].toJSON( meta ).object );
7767
7768			}
7769
7770		}
7771
7772		//
7773
7774		if ( this.animations.length > 0 ) {
7775
7776			object.animations = [];
7777
7778			for ( let i = 0; i < this.animations.length; i ++ ) {
7779
7780				const animation = this.animations[ i ];
7781
7782				object.animations.push( serialize( meta.animations, animation ) );
7783
7784			}
7785
7786		}
7787
7788		if ( isRootObject ) {
7789
7790			const geometries = extractFromCache( meta.geometries );
7791			const materials = extractFromCache( meta.materials );
7792			const textures = extractFromCache( meta.textures );
7793			const images = extractFromCache( meta.images );
7794			const shapes = extractFromCache( meta.shapes );
7795			const skeletons = extractFromCache( meta.skeletons );
7796			const animations = extractFromCache( meta.animations );
7797			const nodes = extractFromCache( meta.nodes );
7798
7799			if ( geometries.length > 0 ) output.geometries = geometries;
7800			if ( materials.length > 0 ) output.materials = materials;
7801			if ( textures.length > 0 ) output.textures = textures;
7802			if ( images.length > 0 ) output.images = images;
7803			if ( shapes.length > 0 ) output.shapes = shapes;
7804			if ( skeletons.length > 0 ) output.skeletons = skeletons;
7805			if ( animations.length > 0 ) output.animations = animations;
7806			if ( nodes.length > 0 ) output.nodes = nodes;
7807
7808		}
7809
7810		output.object = object;
7811
7812		return output;
7813
7814		// extract data from the cache hash
7815		// remove metadata on each item
7816		// and return as array
7817		function extractFromCache( cache ) {
7818
7819			const values = [];
7820			for ( const key in cache ) {
7821
7822				const data = cache[ key ];
7823				delete data.metadata;
7824				values.push( data );
7825
7826			}
7827
7828			return values;
7829
7830		}
7831
7832	}
7833
7834	clone( recursive ) {
7835
7836		return new this.constructor().copy( this, recursive );
7837
7838	}
7839
7840	copy( source, recursive = true ) {
7841
7842		this.name = source.name;
7843
7844		this.up.copy( source.up );
7845
7846		this.position.copy( source.position );
7847		this.rotation.order = source.rotation.order;
7848		this.quaternion.copy( source.quaternion );
7849		this.scale.copy( source.scale );
7850
7851		this.matrix.copy( source.matrix );
7852		this.matrixWorld.copy( source.matrixWorld );
7853
7854		this.matrixAutoUpdate = source.matrixAutoUpdate;
7855		this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
7856
7857		this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
7858
7859		this.layers.mask = source.layers.mask;
7860		this.visible = source.visible;
7861
7862		this.castShadow = source.castShadow;
7863		this.receiveShadow = source.receiveShadow;
7864
7865		this.frustumCulled = source.frustumCulled;
7866		this.renderOrder = source.renderOrder;
7867
7868		this.userData = JSON.parse( JSON.stringify( source.userData ) );
7869
7870		if ( recursive === true ) {
7871
7872			for ( let i = 0; i < source.children.length; i ++ ) {
7873
7874				const child = source.children[ i ];
7875				this.add( child.clone() );
7876
7877			}
7878
7879		}
7880
7881		return this;
7882
7883	}
7884
7885}
7886
7887Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
7888Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
7889Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
7890
7891const _v0$1 = /*@__PURE__*/ new Vector3();
7892const _v1$3 = /*@__PURE__*/ new Vector3();
7893const _v2$2 = /*@__PURE__*/ new Vector3();
7894const _v3$1 = /*@__PURE__*/ new Vector3();
7895
7896const _vab = /*@__PURE__*/ new Vector3();
7897const _vac = /*@__PURE__*/ new Vector3();
7898const _vbc = /*@__PURE__*/ new Vector3();
7899const _vap = /*@__PURE__*/ new Vector3();
7900const _vbp = /*@__PURE__*/ new Vector3();
7901const _vcp = /*@__PURE__*/ new Vector3();
7902
7903class Triangle {
7904
7905	constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) {
7906
7907		this.a = a;
7908		this.b = b;
7909		this.c = c;
7910
7911	}
7912
7913	static getNormal( a, b, c, target ) {
7914
7915		target.subVectors( c, b );
7916		_v0$1.subVectors( a, b );
7917		target.cross( _v0$1 );
7918
7919		const targetLengthSq = target.lengthSq();
7920		if ( targetLengthSq > 0 ) {
7921
7922			return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
7923
7924		}
7925
7926		return target.set( 0, 0, 0 );
7927
7928	}
7929
7930	// static/instance method to calculate barycentric coordinates
7931	// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
7932	static getBarycoord( point, a, b, c, target ) {
7933
7934		_v0$1.subVectors( c, a );
7935		_v1$3.subVectors( b, a );
7936		_v2$2.subVectors( point, a );
7937
vendor: 4,192 bytes, lines 7938-8140
7938		const dot00 = _v0$1.dot( _v0$1 );
7939		const dot01 = _v0$1.dot( _v1$3 );
7940		const dot02 = _v0$1.dot( _v2$2 );
7941		const dot11 = _v1$3.dot( _v1$3 );
7942		const dot12 = _v1$3.dot( _v2$2 );
7943
7944		const denom = ( dot00 * dot11 - dot01 * dot01 );
7945
7946		// collinear or singular triangle
7947		if ( denom === 0 ) {
7948
7949			// arbitrary location outside of triangle?
7950			// not sure if this is the best idea, maybe should be returning undefined
7951			return target.set( - 2, - 1, - 1 );
7952
7953		}
7954
7955		const invDenom = 1 / denom;
7956		const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
7957		const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
7958
7959		// barycentric coordinates must always sum to 1
7960		return target.set( 1 - u - v, v, u );
7961
7962	}
7963
7964	static containsPoint( point, a, b, c ) {
7965
7966		this.getBarycoord( point, a, b, c, _v3$1 );
7967
7968		return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 );
7969
7970	}
7971
7972	static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
7973
7974		this.getBarycoord( point, p1, p2, p3, _v3$1 );
7975
7976		target.set( 0, 0 );
7977		target.addScaledVector( uv1, _v3$1.x );
7978		target.addScaledVector( uv2, _v3$1.y );
7979		target.addScaledVector( uv3, _v3$1.z );
7980
7981		return target;
7982
7983	}
7984
7985	static isFrontFacing( a, b, c, direction ) {
7986
7987		_v0$1.subVectors( c, b );
7988		_v1$3.subVectors( a, b );
7989
7990		// strictly front facing
7991		return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
7992
7993	}
7994
7995	set( a, b, c ) {
7996
7997		this.a.copy( a );
7998		this.b.copy( b );
7999		this.c.copy( c );
8000
8001		return this;
8002
8003	}
8004
8005	setFromPointsAndIndices( points, i0, i1, i2 ) {
8006
8007		this.a.copy( points[ i0 ] );
8008		this.b.copy( points[ i1 ] );
8009		this.c.copy( points[ i2 ] );
8010
8011		return this;
8012
8013	}
8014
8015	setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
8016
8017		this.a.fromBufferAttribute( attribute, i0 );
8018		this.b.fromBufferAttribute( attribute, i1 );
8019		this.c.fromBufferAttribute( attribute, i2 );
8020
8021		return this;
8022
8023	}
8024
8025	clone() {
8026
8027		return new this.constructor().copy( this );
8028
8029	}
8030
8031	copy( triangle ) {
8032
8033		this.a.copy( triangle.a );
8034		this.b.copy( triangle.b );
8035		this.c.copy( triangle.c );
8036
8037		return this;
8038
8039	}
8040
8041	getArea() {
8042
8043		_v0$1.subVectors( this.c, this.b );
8044		_v1$3.subVectors( this.a, this.b );
8045
8046		return _v0$1.cross( _v1$3 ).length() * 0.5;
8047
8048	}
8049
8050	getMidpoint( target ) {
8051
8052		return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
8053
8054	}
8055
8056	getNormal( target ) {
8057
8058		return Triangle.getNormal( this.a, this.b, this.c, target );
8059
8060	}
8061
8062	getPlane( target ) {
8063
8064		return target.setFromCoplanarPoints( this.a, this.b, this.c );
8065
8066	}
8067
8068	getBarycoord( point, target ) {
8069
8070		return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
8071
8072	}
8073
8074	getUV( point, uv1, uv2, uv3, target ) {
8075
8076		return Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );
8077
8078	}
8079
8080	containsPoint( point ) {
8081
8082		return Triangle.containsPoint( point, this.a, this.b, this.c );
8083
8084	}
8085
8086	isFrontFacing( direction ) {
8087
8088		return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
8089
8090	}
8091
8092	intersectsBox( box ) {
8093
8094		return box.intersectsTriangle( this );
8095
8096	}
8097
8098	closestPointToPoint( p, target ) {
8099
8100		const a = this.a, b = this.b, c = this.c;
8101		let v, w;
8102
8103		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
8104		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
8105		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
8106		// basically, we're distinguishing which of the voronoi regions of the triangle
8107		// the point lies in with the minimum amount of redundant computation.
8108
8109		_vab.subVectors( b, a );
8110		_vac.subVectors( c, a );
8111		_vap.subVectors( p, a );
8112		const d1 = _vab.dot( _vap );
8113		const d2 = _vac.dot( _vap );
8114		if ( d1 <= 0 && d2 <= 0 ) {
8115
8116			// vertex region of A; barycentric coords (1, 0, 0)
8117			return target.copy( a );
8118
8119		}
8120
8121		_vbp.subVectors( p, b );
8122		const d3 = _vab.dot( _vbp );
8123		const d4 = _vac.dot( _vbp );
8124		if ( d3 >= 0 && d4 <= d3 ) {
8125
8126			// vertex region of B; barycentric coords (0, 1, 0)
8127			return target.copy( b );
8128
8129		}
8130
8131		const vc = d1 * d4 - d3 * d2;
8132		if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
8133
8134			v = d1 / ( d1 - d3 );
8135			// edge region of AB; barycentric coords (1-v, v, 0)
8136			return target.copy( a ).addScaledVector( _vab, v );
8137
8138		}
8139
8140		_vcp.subVectors( p, c );
vendor: 12,126 bytes, lines 8141-8540
8141		const d5 = _vab.dot( _vcp );
8142		const d6 = _vac.dot( _vcp );
8143		if ( d6 >= 0 && d5 <= d6 ) {
8144
8145			// vertex region of C; barycentric coords (0, 0, 1)
8146			return target.copy( c );
8147
8148		}
8149
8150		const vb = d5 * d2 - d1 * d6;
8151		if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
8152
8153			w = d2 / ( d2 - d6 );
8154			// edge region of AC; barycentric coords (1-w, 0, w)
8155			return target.copy( a ).addScaledVector( _vac, w );
8156
8157		}
8158
8159		const va = d3 * d6 - d5 * d4;
8160		if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
8161
8162			_vbc.subVectors( c, b );
8163			w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
8164			// edge region of BC; barycentric coords (0, 1-w, w)
8165			return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
8166
8167		}
8168
8169		// face region
8170		const denom = 1 / ( va + vb + vc );
8171		// u = va * denom
8172		v = vb * denom;
8173		w = vc * denom;
8174
8175		return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
8176
8177	}
8178
8179	equals( triangle ) {
8180
8181		return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
8182
8183	}
8184
8185}
8186
8187let materialId = 0;
8188
8189class Material extends EventDispatcher {
8190
8191	constructor() {
8192
8193		super();
8194
8195		this.isMaterial = true;
8196
8197		Object.defineProperty( this, 'id', { value: materialId ++ } );
8198
8199		this.uuid = generateUUID();
8200
8201		this.name = '';
8202		this.type = 'Material';
8203
8204		this.blending = NormalBlending;
8205		this.side = FrontSide;
8206		this.vertexColors = false;
8207
8208		this.opacity = 1;
8209		this.transparent = false;
8210
8211		this.blendSrc = SrcAlphaFactor;
8212		this.blendDst = OneMinusSrcAlphaFactor;
8213		this.blendEquation = AddEquation;
8214		this.blendSrcAlpha = null;
8215		this.blendDstAlpha = null;
8216		this.blendEquationAlpha = null;
8217
8218		this.depthFunc = LessEqualDepth;
8219		this.depthTest = true;
8220		this.depthWrite = true;
8221
8222		this.stencilWriteMask = 0xff;
8223		this.stencilFunc = AlwaysStencilFunc;
8224		this.stencilRef = 0;
8225		this.stencilFuncMask = 0xff;
8226		this.stencilFail = KeepStencilOp;
8227		this.stencilZFail = KeepStencilOp;
8228		this.stencilZPass = KeepStencilOp;
8229		this.stencilWrite = false;
8230
8231		this.clippingPlanes = null;
8232		this.clipIntersection = false;
8233		this.clipShadows = false;
8234
8235		this.shadowSide = null;
8236
8237		this.colorWrite = true;
8238
8239		this.precision = null; // override the renderer's default precision for this material
8240
8241		this.polygonOffset = false;
8242		this.polygonOffsetFactor = 0;
8243		this.polygonOffsetUnits = 0;
8244
8245		this.dithering = false;
8246
8247		this.alphaToCoverage = false;
8248		this.premultipliedAlpha = false;
8249		this.forceSinglePass = false;
8250
8251		this.visible = true;
8252
8253		this.toneMapped = true;
8254
8255		this.userData = {};
8256
8257		this.version = 0;
8258
8259		this._alphaTest = 0;
8260
8261	}
8262
8263	get alphaTest() {
8264
8265		return this._alphaTest;
8266
8267	}
8268
8269	set alphaTest( value ) {
8270
8271		if ( this._alphaTest > 0 !== value > 0 ) {
8272
8273			this.version ++;
8274
8275		}
8276
8277		this._alphaTest = value;
8278
8279	}
8280
8281	onBuild( /* shaderobject, renderer */ ) {}
8282
8283	onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {}
8284
8285	onBeforeCompile( /* shaderobject, renderer */ ) {}
8286
8287	customProgramCacheKey() {
8288
8289		return this.onBeforeCompile.toString();
8290
8291	}
8292
8293	setValues( values ) {
8294
8295		if ( values === undefined ) return;
8296
8297		for ( const key in values ) {
8298
8299			const newValue = values[ key ];
8300
8301			if ( newValue === undefined ) {
8302
8303				console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
8304				continue;
8305
8306			}
8307
8308			const currentValue = this[ key ];
8309
8310			if ( currentValue === undefined ) {
8311
8312				console.warn( 'THREE.' + this.type + ': \'' + key + '\' is not a property of this material.' );
8313				continue;
8314
8315			}
8316
8317			if ( currentValue && currentValue.isColor ) {
8318
8319				currentValue.set( newValue );
8320
8321			} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
8322
8323				currentValue.copy( newValue );
8324
8325			} else {
8326
8327				this[ key ] = newValue;
8328
8329			}
8330
8331		}
8332
8333	}
8334
8335	toJSON( meta ) {
8336
8337		const isRootObject = ( meta === undefined || typeof meta === 'string' );
8338
8339		if ( isRootObject ) {
8340
8341			meta = {
8342				textures: {},
8343				images: {}
8344			};
8345
8346		}
8347
8348		const data = {
8349			metadata: {
8350				version: 4.5,
8351				type: 'Material',
8352				generator: 'Material.toJSON'
8353			}
8354		};
8355
8356		// standard Material serialization
8357		data.uuid = this.uuid;
8358		data.type = this.type;
8359
8360		if ( this.name !== '' ) data.name = this.name;
8361
8362		if ( this.color && this.color.isColor ) data.color = this.color.getHex();
8363
8364		if ( this.roughness !== undefined ) data.roughness = this.roughness;
8365		if ( this.metalness !== undefined ) data.metalness = this.metalness;
8366
8367		if ( this.sheen !== undefined ) data.sheen = this.sheen;
8368		if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
8369		if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness;
8370		if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
8371		if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
8372
8373		if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
8374		if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity;
8375		if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
8376		if ( this.shininess !== undefined ) data.shininess = this.shininess;
8377		if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
8378		if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
8379
8380		if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
8381
8382			data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
8383
8384		}
8385
8386		if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
8387
8388			data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
8389
8390		}
8391
8392		if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
8393
8394			data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
8395			data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
8396
8397		}
8398
8399		if ( this.iridescence !== undefined ) data.iridescence = this.iridescence;
8400		if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR;
8401		if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
8402
8403		if ( this.iridescenceMap && this.iridescenceMap.isTexture ) {
8404
8405			data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid;
8406
8407		}
8408
8409		if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) {
8410
8411			data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid;
8412
8413		}
8414
8415		if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
8416		if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
8417		if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
8418
8419		if ( this.lightMap && this.lightMap.isTexture ) {
8420
8421			data.lightMap = this.lightMap.toJSON( meta ).uuid;
8422			data.lightMapIntensity = this.lightMapIntensity;
8423
8424		}
8425
8426		if ( this.aoMap && this.aoMap.isTexture ) {
8427
8428			data.aoMap = this.aoMap.toJSON( meta ).uuid;
8429			data.aoMapIntensity = this.aoMapIntensity;
8430
8431		}
8432
8433		if ( this.bumpMap && this.bumpMap.isTexture ) {
8434
8435			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
8436			data.bumpScale = this.bumpScale;
8437
8438		}
8439
8440		if ( this.normalMap && this.normalMap.isTexture ) {
8441
8442			data.normalMap = this.normalMap.toJSON( meta ).uuid;
8443			data.normalMapType = this.normalMapType;
8444			data.normalScale = this.normalScale.toArray();
8445
8446		}
8447
8448		if ( this.displacementMap && this.displacementMap.isTexture ) {
8449
8450			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
8451			data.displacementScale = this.displacementScale;
8452			data.displacementBias = this.displacementBias;
8453
8454		}
8455
8456		if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
8457		if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
8458
8459		if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
8460		if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
8461		if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
8462		if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
8463
8464		if ( this.envMap && this.envMap.isTexture ) {
8465
8466			data.envMap = this.envMap.toJSON( meta ).uuid;
8467
8468			if ( this.combine !== undefined ) data.combine = this.combine;
8469
8470		}
8471
8472		if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
8473		if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity;
8474		if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio;
8475
8476		if ( this.gradientMap && this.gradientMap.isTexture ) {
8477
8478			data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
8479
8480		}
8481
8482		if ( this.transmission !== undefined ) data.transmission = this.transmission;
8483		if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
8484		if ( this.thickness !== undefined ) data.thickness = this.thickness;
8485		if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
8486		if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance;
8487		if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
8488
8489		if ( this.size !== undefined ) data.size = this.size;
8490		if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide;
8491		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
8492
8493		if ( this.blending !== NormalBlending ) data.blending = this.blending;
8494		if ( this.side !== FrontSide ) data.side = this.side;
8495		if ( this.vertexColors ) data.vertexColors = true;
8496
8497		if ( this.opacity < 1 ) data.opacity = this.opacity;
8498		if ( this.transparent === true ) data.transparent = this.transparent;
8499
8500		data.depthFunc = this.depthFunc;
8501		data.depthTest = this.depthTest;
8502		data.depthWrite = this.depthWrite;
8503		data.colorWrite = this.colorWrite;
8504
8505		data.stencilWrite = this.stencilWrite;
8506		data.stencilWriteMask = this.stencilWriteMask;
8507		data.stencilFunc = this.stencilFunc;
8508		data.stencilRef = this.stencilRef;
8509		data.stencilFuncMask = this.stencilFuncMask;
8510		data.stencilFail = this.stencilFail;
8511		data.stencilZFail = this.stencilZFail;
8512		data.stencilZPass = this.stencilZPass;
8513
8514		// rotation (SpriteMaterial)
8515		if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation;
8516
8517		if ( this.polygonOffset === true ) data.polygonOffset = true;
8518		if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
8519		if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
8520
8521		if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth;
8522		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
8523		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
8524		if ( this.scale !== undefined ) data.scale = this.scale;
8525
8526		if ( this.dithering === true ) data.dithering = true;
8527
8528		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
8529		if ( this.alphaToCoverage === true ) data.alphaToCoverage = this.alphaToCoverage;
8530		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
8531		if ( this.forceSinglePass === true ) data.forceSinglePass = this.forceSinglePass;
8532
8533		if ( this.wireframe === true ) data.wireframe = this.wireframe;
8534		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
8535		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
8536		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
8537
8538		if ( this.flatShading === true ) data.flatShading = this.flatShading;
8539
8540		if ( this.visible === false ) data.visible = false;
vendor: 5,795 bytes, lines 8541-8697
8541
8542		if ( this.toneMapped === false ) data.toneMapped = false;
8543
8544		if ( this.fog === false ) data.fog = false;
8545
8546		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
8547
8548		// TODO: Copied from Object3D.toJSON
8549
8550		function extractFromCache( cache ) {
8551
8552			const values = [];
8553
8554			for ( const key in cache ) {
8555
8556				const data = cache[ key ];
8557				delete data.metadata;
8558				values.push( data );
8559
8560			}
8561
8562			return values;
8563
8564		}
8565
8566		if ( isRootObject ) {
8567
8568			const textures = extractFromCache( meta.textures );
8569			const images = extractFromCache( meta.images );
8570
8571			if ( textures.length > 0 ) data.textures = textures;
8572			if ( images.length > 0 ) data.images = images;
8573
8574		}
8575
8576		return data;
8577
8578	}
8579
8580	clone() {
8581
8582		return new this.constructor().copy( this );
8583
8584	}
8585
8586	copy( source ) {
8587
8588		this.name = source.name;
8589
8590		this.blending = source.blending;
8591		this.side = source.side;
8592		this.vertexColors = source.vertexColors;
8593
8594		this.opacity = source.opacity;
8595		this.transparent = source.transparent;
8596
8597		this.blendSrc = source.blendSrc;
8598		this.blendDst = source.blendDst;
8599		this.blendEquation = source.blendEquation;
8600		this.blendSrcAlpha = source.blendSrcAlpha;
8601		this.blendDstAlpha = source.blendDstAlpha;
8602		this.blendEquationAlpha = source.blendEquationAlpha;
8603
8604		this.depthFunc = source.depthFunc;
8605		this.depthTest = source.depthTest;
8606		this.depthWrite = source.depthWrite;
8607
8608		this.stencilWriteMask = source.stencilWriteMask;
8609		this.stencilFunc = source.stencilFunc;
8610		this.stencilRef = source.stencilRef;
8611		this.stencilFuncMask = source.stencilFuncMask;
8612		this.stencilFail = source.stencilFail;
8613		this.stencilZFail = source.stencilZFail;
8614		this.stencilZPass = source.stencilZPass;
8615		this.stencilWrite = source.stencilWrite;
8616
8617		const srcPlanes = source.clippingPlanes;
8618		let dstPlanes = null;
8619
8620		if ( srcPlanes !== null ) {
8621
8622			const n = srcPlanes.length;
8623			dstPlanes = new Array( n );
8624
8625			for ( let i = 0; i !== n; ++ i ) {
8626
8627				dstPlanes[ i ] = srcPlanes[ i ].clone();
8628
8629			}
8630
8631		}
8632
8633		this.clippingPlanes = dstPlanes;
8634		this.clipIntersection = source.clipIntersection;
8635		this.clipShadows = source.clipShadows;
8636
8637		this.shadowSide = source.shadowSide;
8638
8639		this.colorWrite = source.colorWrite;
8640
8641		this.precision = source.precision;
8642
8643		this.polygonOffset = source.polygonOffset;
8644		this.polygonOffsetFactor = source.polygonOffsetFactor;
8645		this.polygonOffsetUnits = source.polygonOffsetUnits;
8646
8647		this.dithering = source.dithering;
8648
8649		this.alphaTest = source.alphaTest;
8650		this.alphaToCoverage = source.alphaToCoverage;
8651		this.premultipliedAlpha = source.premultipliedAlpha;
8652		this.forceSinglePass = source.forceSinglePass;
8653
8654		this.visible = source.visible;
8655
8656		this.toneMapped = source.toneMapped;
8657
8658		this.userData = JSON.parse( JSON.stringify( source.userData ) );
8659
8660		return this;
8661
8662	}
8663
8664	dispose() {
8665
8666		this.dispatchEvent( { type: 'dispose' } );
8667
8668	}
8669
8670	set needsUpdate( value ) {
8671
8672		if ( value === true ) this.version ++;
8673
8674	}
8675
8676}
8677
8678const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
8679	'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
8680	'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
8681	'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
8682	'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
8683	'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
8684	'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
8685	'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
8686	'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
8687	'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
8688	'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
8689	'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
8690	'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
8691	'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
8692	'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
8693	'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
8694	'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
8695	'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
8696	'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
8697	'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
8698	'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
8699	'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
8700	'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
8701	'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
8702
8703const _hslA = { h: 0, s: 0, l: 0 };
8704const _hslB = { h: 0, s: 0, l: 0 };
8705
8706function hue2rgb( p, q, t ) {
8707
8708	if ( t < 0 ) t += 1;
8709	if ( t > 1 ) t -= 1;
8710	if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
8711	if ( t < 1 / 2 ) return q;
8712	if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
8713	return p;
8714
8715}
8716
8717class Color {
8718
8719	constructor( r, g, b ) {
8720
8721		this.isColor = true;
8722
8723		this.r = 1;
8724		this.g = 1;
8725		this.b = 1;
8726
8727		if ( g === undefined && b === undefined ) {
8728
8729			// r is THREE.Color, hex or string
8730			return this.set( r );
8731
8732		}
8733
8734		return this.setRGB( r, g, b );
8735
8736	}
8737
8738	set( value ) {
8739
8740		if ( value && value.isColor ) {
8741
8742			this.copy( value );
8743
8744		} else if ( typeof value === 'number' ) {
8745
8746			this.setHex( value );
8747
8748		} else if ( typeof value === 'string' ) {
8749
8750			this.setStyle( value );
8751
8752		}
8753
8754		return this;
8755
8756	}
8757
8758	setScalar( scalar ) {
8759
8760		this.r = scalar;
8761		this.g = scalar;
8762		this.b = scalar;
8763
8764		return this;
8765
8766	}
8767
8768	setHex( hex, colorSpace = SRGBColorSpace ) {
8769
8770		hex = Math.floor( hex );
8771
8772		this.r = ( hex >> 16 & 255 ) / 255;
8773		this.g = ( hex >> 8 & 255 ) / 255;
8774		this.b = ( hex & 255 ) / 255;
8775
8776		ColorManagement.toWorkingColorSpace( this, colorSpace );
8777
8778		return this;
8779
8780	}
8781
8782	setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) {
8783
8784		this.r = r;
8785		this.g = g;
8786		this.b = b;
8787
8788		ColorManagement.toWorkingColorSpace( this, colorSpace );
8789
8790		return this;
8791
8792	}
8793
8794	setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) {
8795
8796		// h,s,l ranges are in 0.0 - 1.0
8797		h = euclideanModulo( h, 1 );
8798		s = clamp( s, 0, 1 );
8799		l = clamp( l, 0, 1 );
8800
8801		if ( s === 0 ) {
8802
8803			this.r = this.g = this.b = l;
8804
8805		} else {
8806
8807			const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
8808			const q = ( 2 * l ) - p;
8809
8810			this.r = hue2rgb( q, p, h + 1 / 3 );
8811			this.g = hue2rgb( q, p, h );
8812			this.b = hue2rgb( q, p, h - 1 / 3 );
8813
8814		}
8815
8816		ColorManagement.toWorkingColorSpace( this, colorSpace );
8817
8818		return this;
8819
8820	}
8821
8822	setStyle( style, colorSpace = SRGBColorSpace ) {
8823
8824		function handleAlpha( string ) {
8825
8826			if ( string === undefined ) return;
8827
8828			if ( parseFloat( string ) < 1 ) {
8829
8830				console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
8831
8832			}
8833
8834		}
8835
8836
8837		let m;
8838
8839		if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) {
8840
8841			// rgb / hsl
8842
8843			let color;
8844			const name = m[ 1 ];
8845			const components = m[ 2 ];
8846
8847			switch ( name ) {
8848
8849				case 'rgb':
8850				case 'rgba':
8851
8852					if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8853
8854						// rgb(255,0,0) rgba(255,0,0,0.5)
8855						this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;
8856						this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;
8857						this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;
8858
8859						ColorManagement.toWorkingColorSpace( this, colorSpace );
8860
8861						handleAlpha( color[ 4 ] );
8862
8863						return this;
8864
8865					}
8866
8867					if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8868
8869						// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
8870						this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;
8871						this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;
8872						this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;
8873
8874						ColorManagement.toWorkingColorSpace( this, colorSpace );
8875
8876						handleAlpha( color[ 4 ] );
8877
8878						return this;
8879
8880					}
8881
8882					break;
8883
8884				case 'hsl':
8885				case 'hsla':
8886
8887					if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8888
8889						// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
8890						const h = parseFloat( color[ 1 ] ) / 360;
8891						const s = parseFloat( color[ 2 ] ) / 100;
8892						const l = parseFloat( color[ 3 ] ) / 100;
8893
8894						handleAlpha( color[ 4 ] );
8895
8896						return this.setHSL( h, s, l, colorSpace );
8897
8898					}
8899
8900					break;
8901
8902				default:
8903
8904					console.warn( 'THREE.Color: Unknown color model ' + style );
8905
8906			}
8907
8908		} else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
8909
8910			// hex color
8911
8912			const hex = m[ 1 ];
8913			const size = hex.length;
8914
8915			if ( size === 3 ) {
8916
8917				// #ff0
8918				this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
8919				this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
8920				this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
8921
vendor: 20,875 bytes, lines 8922-10186
8922				ColorManagement.toWorkingColorSpace( this, colorSpace );
8923
8924				return this;
8925
8926			} else if ( size === 6 ) {
8927
8928				// #ff0000
8929				this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
8930				this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
8931				this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
8932
8933				ColorManagement.toWorkingColorSpace( this, colorSpace );
8934
8935				return this;
8936
8937			} else {
8938
8939				console.warn( 'THREE.Color: Invalid hex color ' + style );
8940
8941			}
8942
8943		} else if ( style && style.length > 0 ) {
8944
8945			return this.setColorName( style, colorSpace );
8946
8947		}
8948
8949		return this;
8950
8951	}
8952
8953	setColorName( style, colorSpace = SRGBColorSpace ) {
8954
8955		// color keywords
8956		const hex = _colorKeywords[ style.toLowerCase() ];
8957
8958		if ( hex !== undefined ) {
8959
8960			// red
8961			this.setHex( hex, colorSpace );
8962
8963		} else {
8964
8965			// unknown color
8966			console.warn( 'THREE.Color: Unknown color ' + style );
8967
8968		}
8969
8970		return this;
8971
8972	}
8973
8974	clone() {
8975
8976		return new this.constructor( this.r, this.g, this.b );
8977
8978	}
8979
8980	copy( color ) {
8981
8982		this.r = color.r;
8983		this.g = color.g;
8984		this.b = color.b;
8985
8986		return this;
8987
8988	}
8989
8990	copySRGBToLinear( color ) {
8991
8992		this.r = SRGBToLinear( color.r );
8993		this.g = SRGBToLinear( color.g );
8994		this.b = SRGBToLinear( color.b );
8995
8996		return this;
8997
8998	}
8999
9000	copyLinearToSRGB( color ) {
9001
9002		this.r = LinearToSRGB( color.r );
9003		this.g = LinearToSRGB( color.g );
9004		this.b = LinearToSRGB( color.b );
9005
9006		return this;
9007
9008	}
9009
9010	convertSRGBToLinear() {
9011
9012		this.copySRGBToLinear( this );
9013
9014		return this;
9015
9016	}
9017
9018	convertLinearToSRGB() {
9019
9020		this.copyLinearToSRGB( this );
9021
9022		return this;
9023
9024	}
9025
9026	getHex( colorSpace = SRGBColorSpace ) {
9027
9028		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
9029
9030		return clamp( _color.r * 255, 0, 255 ) << 16 ^ clamp( _color.g * 255, 0, 255 ) << 8 ^ clamp( _color.b * 255, 0, 255 ) << 0;
9031
9032	}
9033
9034	getHexString( colorSpace = SRGBColorSpace ) {
9035
9036		return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 );
9037
9038	}
9039
9040	getHSL( target, colorSpace = ColorManagement.workingColorSpace ) {
9041
9042		// h,s,l ranges are in 0.0 - 1.0
9043
9044		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
9045
9046		const r = _color.r, g = _color.g, b = _color.b;
9047
9048		const max = Math.max( r, g, b );
9049		const min = Math.min( r, g, b );
9050
9051		let hue, saturation;
9052		const lightness = ( min + max ) / 2.0;
9053
9054		if ( min === max ) {
9055
9056			hue = 0;
9057			saturation = 0;
9058
9059		} else {
9060
9061			const delta = max - min;
9062
9063			saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
9064
9065			switch ( max ) {
9066
9067				case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
9068				case g: hue = ( b - r ) / delta + 2; break;
9069				case b: hue = ( r - g ) / delta + 4; break;
9070
9071			}
9072
9073			hue /= 6;
9074
9075		}
9076
9077		target.h = hue;
9078		target.s = saturation;
9079		target.l = lightness;
9080
9081		return target;
9082
9083	}
9084
9085	getRGB( target, colorSpace = ColorManagement.workingColorSpace ) {
9086
9087		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
9088
9089		target.r = _color.r;
9090		target.g = _color.g;
9091		target.b = _color.b;
9092
9093		return target;
9094
9095	}
9096
9097	getStyle( colorSpace = SRGBColorSpace ) {
9098
9099		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
9100
9101		const r = _color.r, g = _color.g, b = _color.b;
9102
9103		if ( colorSpace !== SRGBColorSpace ) {
9104
9105			// Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
9106			return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`;
9107
9108		}
9109
9110		return `rgb(${( r * 255 ) | 0},${( g * 255 ) | 0},${( b * 255 ) | 0})`;
9111
9112	}
9113
9114	offsetHSL( h, s, l ) {
9115
9116		this.getHSL( _hslA );
9117
9118		_hslA.h += h; _hslA.s += s; _hslA.l += l;
9119
9120		this.setHSL( _hslA.h, _hslA.s, _hslA.l );
9121
9122		return this;
9123
9124	}
9125
9126	add( color ) {
9127
9128		this.r += color.r;
9129		this.g += color.g;
9130		this.b += color.b;
9131
9132		return this;
9133
9134	}
9135
9136	addColors( color1, color2 ) {
9137
9138		this.r = color1.r + color2.r;
9139		this.g = color1.g + color2.g;
9140		this.b = color1.b + color2.b;
9141
9142		return this;
9143
9144	}
9145
9146	addScalar( s ) {
9147
9148		this.r += s;
9149		this.g += s;
9150		this.b += s;
9151
9152		return this;
9153
9154	}
9155
9156	sub( color ) {
9157
9158		this.r = Math.max( 0, this.r - color.r );
9159		this.g = Math.max( 0, this.g - color.g );
9160		this.b = Math.max( 0, this.b - color.b );
9161
9162		return this;
9163
9164	}
9165
9166	multiply( color ) {
9167
9168		this.r *= color.r;
9169		this.g *= color.g;
9170		this.b *= color.b;
9171
9172		return this;
9173
9174	}
9175
9176	multiplyScalar( s ) {
9177
9178		this.r *= s;
9179		this.g *= s;
9180		this.b *= s;
9181
9182		return this;
9183
9184	}
9185
9186	lerp( color, alpha ) {
9187
9188		this.r += ( color.r - this.r ) * alpha;
9189		this.g += ( color.g - this.g ) * alpha;
9190		this.b += ( color.b - this.b ) * alpha;
9191
9192		return this;
9193
9194	}
9195
9196	lerpColors( color1, color2, alpha ) {
9197
9198		this.r = color1.r + ( color2.r - color1.r ) * alpha;
9199		this.g = color1.g + ( color2.g - color1.g ) * alpha;
9200		this.b = color1.b + ( color2.b - color1.b ) * alpha;
9201
9202		return this;
9203
9204	}
9205
9206	lerpHSL( color, alpha ) {
9207
9208		this.getHSL( _hslA );
9209		color.getHSL( _hslB );
9210
9211		const h = lerp( _hslA.h, _hslB.h, alpha );
9212		const s = lerp( _hslA.s, _hslB.s, alpha );
9213		const l = lerp( _hslA.l, _hslB.l, alpha );
9214
9215		this.setHSL( h, s, l );
9216
9217		return this;
9218
9219	}
9220
9221	equals( c ) {
9222
9223		return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
9224
9225	}
9226
9227	fromArray( array, offset = 0 ) {
9228
9229		this.r = array[ offset ];
9230		this.g = array[ offset + 1 ];
9231		this.b = array[ offset + 2 ];
9232
9233		return this;
9234
9235	}
9236
9237	toArray( array = [], offset = 0 ) {
9238
9239		array[ offset ] = this.r;
9240		array[ offset + 1 ] = this.g;
9241		array[ offset + 2 ] = this.b;
9242
9243		return array;
9244
9245	}
9246
9247	fromBufferAttribute( attribute, index ) {
9248
9249		this.r = attribute.getX( index );
9250		this.g = attribute.getY( index );
9251		this.b = attribute.getZ( index );
9252
9253		return this;
9254
9255	}
9256
9257	toJSON() {
9258
9259		return this.getHex();
9260
9261	}
9262
9263	*[ Symbol.iterator ]() {
9264
9265		yield this.r;
9266		yield this.g;
9267		yield this.b;
9268
9269	}
9270
9271}
9272
9273const _color = new Color();
9274
9275Color.NAMES = _colorKeywords;
9276
9277class MeshBasicMaterial extends Material {
9278
9279	constructor( parameters ) {
9280
9281		super();
9282
9283		this.isMeshBasicMaterial = true;
9284
9285		this.type = 'MeshBasicMaterial';
9286
9287		this.color = new Color( 0xffffff ); // emissive
9288
9289		this.map = null;
9290
9291		this.lightMap = null;
9292		this.lightMapIntensity = 1.0;
9293
9294		this.aoMap = null;
9295		this.aoMapIntensity = 1.0;
9296
9297		this.specularMap = null;
9298
9299		this.alphaMap = null;
9300
9301		this.envMap = null;
9302		this.combine = MultiplyOperation;
9303		this.reflectivity = 1;
9304		this.refractionRatio = 0.98;
9305
9306		this.wireframe = false;
9307		this.wireframeLinewidth = 1;
9308		this.wireframeLinecap = 'round';
9309		this.wireframeLinejoin = 'round';
9310
9311		this.fog = true;
9312
9313		this.setValues( parameters );
9314
9315	}
9316
9317	copy( source ) {
9318
9319		super.copy( source );
9320
9321		this.color.copy( source.color );
9322
9323		this.map = source.map;
9324
9325		this.lightMap = source.lightMap;
9326		this.lightMapIntensity = source.lightMapIntensity;
9327
9328		this.aoMap = source.aoMap;
9329		this.aoMapIntensity = source.aoMapIntensity;
9330
9331		this.specularMap = source.specularMap;
9332
9333		this.alphaMap = source.alphaMap;
9334
9335		this.envMap = source.envMap;
9336		this.combine = source.combine;
9337		this.reflectivity = source.reflectivity;
9338		this.refractionRatio = source.refractionRatio;
9339
9340		this.wireframe = source.wireframe;
9341		this.wireframeLinewidth = source.wireframeLinewidth;
9342		this.wireframeLinecap = source.wireframeLinecap;
9343		this.wireframeLinejoin = source.wireframeLinejoin;
9344
9345		this.fog = source.fog;
9346
9347		return this;
9348
9349	}
9350
9351}
9352
9353const _vector$9 = /*@__PURE__*/ new Vector3();
9354const _vector2$1 = /*@__PURE__*/ new Vector2();
9355
9356class BufferAttribute {
9357
9358	constructor( array, itemSize, normalized = false ) {
9359
9360		if ( Array.isArray( array ) ) {
9361
9362			throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
9363
9364		}
9365
9366		this.isBufferAttribute = true;
9367
9368		this.name = '';
9369
9370		this.array = array;
9371		this.itemSize = itemSize;
9372		this.count = array !== undefined ? array.length / itemSize : 0;
9373		this.normalized = normalized;
9374
9375		this.usage = StaticDrawUsage;
9376		this.updateRange = { offset: 0, count: - 1 };
9377
9378		this.version = 0;
9379
9380	}
9381
9382	onUploadCallback() {}
9383
9384	set needsUpdate( value ) {
9385
9386		if ( value === true ) this.version ++;
9387
9388	}
9389
9390	setUsage( value ) {
9391
9392		this.usage = value;
9393
9394		return this;
9395
9396	}
9397
9398	copy( source ) {
9399
9400		this.name = source.name;
9401		this.array = new source.array.constructor( source.array );
9402		this.itemSize = source.itemSize;
9403		this.count = source.count;
9404		this.normalized = source.normalized;
9405
9406		this.usage = source.usage;
9407
9408		return this;
9409
9410	}
9411
9412	copyAt( index1, attribute, index2 ) {
9413
9414		index1 *= this.itemSize;
9415		index2 *= attribute.itemSize;
9416
9417		for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
9418
9419			this.array[ index1 + i ] = attribute.array[ index2 + i ];
9420
9421		}
9422
9423		return this;
9424
9425	}
9426
9427	copyArray( array ) {
9428
9429		this.array.set( array );
9430
9431		return this;
9432
9433	}
9434
9435	applyMatrix3( m ) {
9436
9437		if ( this.itemSize === 2 ) {
9438
9439			for ( let i = 0, l = this.count; i < l; i ++ ) {
9440
9441				_vector2$1.fromBufferAttribute( this, i );
9442				_vector2$1.applyMatrix3( m );
9443
9444				this.setXY( i, _vector2$1.x, _vector2$1.y );
9445
9446			}
9447
9448		} else if ( this.itemSize === 3 ) {
9449
9450			for ( let i = 0, l = this.count; i < l; i ++ ) {
9451
9452				_vector$9.fromBufferAttribute( this, i );
9453				_vector$9.applyMatrix3( m );
9454
9455				this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9456
9457			}
9458
9459		}
9460
9461		return this;
9462
9463	}
9464
9465	applyMatrix4( m ) {
9466
9467		for ( let i = 0, l = this.count; i < l; i ++ ) {
9468
9469			_vector$9.fromBufferAttribute( this, i );
9470
9471			_vector$9.applyMatrix4( m );
9472
9473			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9474
9475		}
9476
9477		return this;
9478
9479	}
9480
9481	applyNormalMatrix( m ) {
9482
9483		for ( let i = 0, l = this.count; i < l; i ++ ) {
9484
9485			_vector$9.fromBufferAttribute( this, i );
9486
9487			_vector$9.applyNormalMatrix( m );
9488
9489			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9490
9491		}
9492
9493		return this;
9494
9495	}
9496
9497	transformDirection( m ) {
9498
9499		for ( let i = 0, l = this.count; i < l; i ++ ) {
9500
9501			_vector$9.fromBufferAttribute( this, i );
9502
9503			_vector$9.transformDirection( m );
9504
9505			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9506
9507		}
9508
9509		return this;
9510
9511	}
9512
9513	set( value, offset = 0 ) {
9514
9515		// Matching BufferAttribute constructor, do not normalize the array.
9516		this.array.set( value, offset );
9517
9518		return this;
9519
9520	}
9521
9522	getX( index ) {
9523
9524		let x = this.array[ index * this.itemSize ];
9525
9526		if ( this.normalized ) x = denormalize( x, this.array );
9527
9528		return x;
9529
9530	}
9531
9532	setX( index, x ) {
9533
9534		if ( this.normalized ) x = normalize( x, this.array );
9535
9536		this.array[ index * this.itemSize ] = x;
9537
9538		return this;
9539
9540	}
9541
9542	getY( index ) {
9543
9544		let y = this.array[ index * this.itemSize + 1 ];
9545
9546		if ( this.normalized ) y = denormalize( y, this.array );
9547
9548		return y;
9549
9550	}
9551
9552	setY( index, y ) {
9553
9554		if ( this.normalized ) y = normalize( y, this.array );
9555
9556		this.array[ index * this.itemSize + 1 ] = y;
9557
9558		return this;
9559
9560	}
9561
9562	getZ( index ) {
9563
9564		let z = this.array[ index * this.itemSize + 2 ];
9565
9566		if ( this.normalized ) z = denormalize( z, this.array );
9567
9568		return z;
9569
9570	}
9571
9572	setZ( index, z ) {
9573
9574		if ( this.normalized ) z = normalize( z, this.array );
9575
9576		this.array[ index * this.itemSize + 2 ] = z;
9577
9578		return this;
9579
9580	}
9581
9582	getW( index ) {
9583
9584		let w = this.array[ index * this.itemSize + 3 ];
9585
9586		if ( this.normalized ) w = denormalize( w, this.array );
9587
9588		return w;
9589
9590	}
9591
9592	setW( index, w ) {
9593
9594		if ( this.normalized ) w = normalize( w, this.array );
9595
9596		this.array[ index * this.itemSize + 3 ] = w;
9597
9598		return this;
9599
9600	}
9601
9602	setXY( index, x, y ) {
9603
9604		index *= this.itemSize;
9605
9606		if ( this.normalized ) {
9607
9608			x = normalize( x, this.array );
9609			y = normalize( y, this.array );
9610
9611		}
9612
9613		this.array[ index + 0 ] = x;
9614		this.array[ index + 1 ] = y;
9615
9616		return this;
9617
9618	}
9619
9620	setXYZ( index, x, y, z ) {
9621
9622		index *= this.itemSize;
9623
9624		if ( this.normalized ) {
9625
9626			x = normalize( x, this.array );
9627			y = normalize( y, this.array );
9628			z = normalize( z, this.array );
9629
9630		}
9631
9632		this.array[ index + 0 ] = x;
9633		this.array[ index + 1 ] = y;
9634		this.array[ index + 2 ] = z;
9635
9636		return this;
9637
9638	}
9639
9640	setXYZW( index, x, y, z, w ) {
9641
9642		index *= this.itemSize;
9643
9644		if ( this.normalized ) {
9645
9646			x = normalize( x, this.array );
9647			y = normalize( y, this.array );
9648			z = normalize( z, this.array );
9649			w = normalize( w, this.array );
9650
9651		}
9652
9653		this.array[ index + 0 ] = x;
9654		this.array[ index + 1 ] = y;
9655		this.array[ index + 2 ] = z;
9656		this.array[ index + 3 ] = w;
9657
9658		return this;
9659
9660	}
9661
9662	onUpload( callback ) {
9663
9664		this.onUploadCallback = callback;
9665
9666		return this;
9667
9668	}
9669
9670	clone() {
9671
9672		return new this.constructor( this.array, this.itemSize ).copy( this );
9673
9674	}
9675
9676	toJSON() {
9677
9678		const data = {
9679			itemSize: this.itemSize,
9680			type: this.array.constructor.name,
9681			array: Array.from( this.array ),
9682			normalized: this.normalized
9683		};
9684
9685		if ( this.name !== '' ) data.name = this.name;
9686		if ( this.usage !== StaticDrawUsage ) data.usage = this.usage;
9687		if ( this.updateRange.offset !== 0 || this.updateRange.count !== - 1 ) data.updateRange = this.updateRange;
9688
9689		return data;
9690
9691	}
9692
9693	// @deprecated
9694
9695	copyColorsArray() {
9696
9697		console.error( 'THREE.BufferAttribute: copyColorsArray() was removed in r144.' );
9698
9699	}
9700
9701	copyVector2sArray() {
9702
9703		console.error( 'THREE.BufferAttribute: copyVector2sArray() was removed in r144.' );
9704
9705	}
9706
9707	copyVector3sArray() {
9708
9709		console.error( 'THREE.BufferAttribute: copyVector3sArray() was removed in r144.' );
9710
9711	}
9712
9713	copyVector4sArray() {
9714
9715		console.error( 'THREE.BufferAttribute: copyVector4sArray() was removed in r144.' );
9716
9717	}
9718
9719}
9720
9721//
9722
9723class Int8BufferAttribute extends BufferAttribute {
9724
9725	constructor( array, itemSize, normalized ) {
9726
9727		super( new Int8Array( array ), itemSize, normalized );
9728
9729	}
9730
9731}
9732
9733class Uint8BufferAttribute extends BufferAttribute {
9734
9735	constructor( array, itemSize, normalized ) {
9736
9737		super( new Uint8Array( array ), itemSize, normalized );
9738
9739	}
9740
9741}
9742
9743class Uint8ClampedBufferAttribute extends BufferAttribute {
9744
9745	constructor( array, itemSize, normalized ) {
9746
9747		super( new Uint8ClampedArray( array ), itemSize, normalized );
9748
9749	}
9750
9751}
9752
9753class Int16BufferAttribute extends BufferAttribute {
9754
9755	constructor( array, itemSize, normalized ) {
9756
9757		super( new Int16Array( array ), itemSize, normalized );
9758
9759	}
9760
9761}
9762
9763class Uint16BufferAttribute extends BufferAttribute {
9764
9765	constructor( array, itemSize, normalized ) {
9766
9767		super( new Uint16Array( array ), itemSize, normalized );
9768
9769	}
9770
9771}
9772
9773class Int32BufferAttribute extends BufferAttribute {
9774
9775	constructor( array, itemSize, normalized ) {
9776
9777		super( new Int32Array( array ), itemSize, normalized );
9778
9779	}
9780
9781}
9782
9783class Uint32BufferAttribute extends BufferAttribute {
9784
9785	constructor( array, itemSize, normalized ) {
9786
9787		super( new Uint32Array( array ), itemSize, normalized );
9788
9789	}
9790
9791}
9792
9793class Float16BufferAttribute extends BufferAttribute {
9794
9795	constructor( array, itemSize, normalized ) {
9796
9797		super( new Uint16Array( array ), itemSize, normalized );
9798
9799		this.isFloat16BufferAttribute = true;
9800
9801	}
9802
9803}
9804
9805
9806class Float32BufferAttribute extends BufferAttribute {
9807
9808	constructor( array, itemSize, normalized ) {
9809
9810		super( new Float32Array( array ), itemSize, normalized );
9811
9812	}
9813
9814}
9815
9816class Float64BufferAttribute extends BufferAttribute {
9817
9818	constructor( array, itemSize, normalized ) {
9819
9820		super( new Float64Array( array ), itemSize, normalized );
9821
9822	}
9823
9824}
9825
9826let _id$1 = 0;
9827
9828const _m1 = /*@__PURE__*/ new Matrix4();
9829const _obj = /*@__PURE__*/ new Object3D();
9830const _offset = /*@__PURE__*/ new Vector3();
9831const _box$1 = /*@__PURE__*/ new Box3();
9832const _boxMorphTargets = /*@__PURE__*/ new Box3();
9833const _vector$8 = /*@__PURE__*/ new Vector3();
9834
9835class BufferGeometry extends EventDispatcher {
9836
9837	constructor() {
9838
9839		super();
9840
9841		this.isBufferGeometry = true;
9842
9843		Object.defineProperty( this, 'id', { value: _id$1 ++ } );
9844
9845		this.uuid = generateUUID();
9846
9847		this.name = '';
9848		this.type = 'BufferGeometry';
9849
9850		this.index = null;
9851		this.attributes = {};
9852
9853		this.morphAttributes = {};
9854		this.morphTargetsRelative = false;
9855
9856		this.groups = [];
9857
9858		this.boundingBox = null;
9859		this.boundingSphere = null;
9860
9861		this.drawRange = { start: 0, count: Infinity };
9862
9863		this.userData = {};
9864
9865	}
9866
9867	getIndex() {
9868
9869		return this.index;
9870
9871	}
9872
9873	setIndex( index ) {
9874
9875		if ( Array.isArray( index ) ) {
9876
9877			this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
9878
9879		} else {
9880
9881			this.index = index;
9882
9883		}
9884
9885		return this;
9886
9887	}
9888
9889	getAttribute( name ) {
9890
9891		return this.attributes[ name ];
9892
9893	}
9894
9895	setAttribute( name, attribute ) {
9896
9897		this.attributes[ name ] = attribute;
9898
9899		return this;
9900
9901	}
9902
9903	deleteAttribute( name ) {
9904
9905		delete this.attributes[ name ];
9906
9907		return this;
9908
9909	}
9910
9911	hasAttribute( name ) {
9912
9913		return this.attributes[ name ] !== undefined;
9914
9915	}
9916
9917	addGroup( start, count, materialIndex = 0 ) {
9918
9919		this.groups.push( {
9920
9921			start: start,
9922			count: count,
9923			materialIndex: materialIndex
9924
9925		} );
9926
9927	}
9928
9929	clearGroups() {
9930
9931		this.groups = [];
9932
9933	}
9934
9935	setDrawRange( start, count ) {
9936
9937		this.drawRange.start = start;
9938		this.drawRange.count = count;
9939
9940	}
9941
9942	applyMatrix4( matrix ) {
9943
9944		const position = this.attributes.position;
9945
9946		if ( position !== undefined ) {
9947
9948			position.applyMatrix4( matrix );
9949
9950			position.needsUpdate = true;
9951
9952		}
9953
9954		const normal = this.attributes.normal;
9955
9956		if ( normal !== undefined ) {
9957
9958			const normalMatrix = new Matrix3().getNormalMatrix( matrix );
9959
9960			normal.applyNormalMatrix( normalMatrix );
9961
9962			normal.needsUpdate = true;
9963
9964		}
9965
9966		const tangent = this.attributes.tangent;
9967
9968		if ( tangent !== undefined ) {
9969
9970			tangent.transformDirection( matrix );
9971
9972			tangent.needsUpdate = true;
9973
9974		}
9975
9976		if ( this.boundingBox !== null ) {
9977
9978			this.computeBoundingBox();
9979
9980		}
9981
9982		if ( this.boundingSphere !== null ) {
9983
9984			this.computeBoundingSphere();
9985
9986		}
9987
9988		return this;
9989
9990	}
9991
9992	applyQuaternion( q ) {
9993
9994		_m1.makeRotationFromQuaternion( q );
9995
9996		this.applyMatrix4( _m1 );
9997
9998		return this;
9999
10000	}
10001
10002	rotateX( angle ) {
10003
10004		// rotate geometry around world x-axis
10005
10006		_m1.makeRotationX( angle );
10007
10008		this.applyMatrix4( _m1 );
10009
10010		return this;
10011
10012	}
10013
10014	rotateY( angle ) {
10015
10016		// rotate geometry around world y-axis
10017
10018		_m1.makeRotationY( angle );
10019
10020		this.applyMatrix4( _m1 );
10021
10022		return this;
10023
10024	}
10025
10026	rotateZ( angle ) {
10027
10028		// rotate geometry around world z-axis
10029
10030		_m1.makeRotationZ( angle );
10031
10032		this.applyMatrix4( _m1 );
10033
10034		return this;
10035
10036	}
10037
10038	translate( x, y, z ) {
10039
10040		// translate geometry
10041
10042		_m1.makeTranslation( x, y, z );
10043
10044		this.applyMatrix4( _m1 );
10045
10046		return this;
10047
10048	}
10049
10050	scale( x, y, z ) {
10051
10052		// scale geometry
10053
10054		_m1.makeScale( x, y, z );
10055
10056		this.applyMatrix4( _m1 );
10057
10058		return this;
10059
10060	}
10061
10062	lookAt( vector ) {
10063
10064		_obj.lookAt( vector );
10065
10066		_obj.updateMatrix();
10067
10068		this.applyMatrix4( _obj.matrix );
10069
10070		return this;
10071
10072	}
10073
10074	center() {
10075
10076		this.computeBoundingBox();
10077
10078		this.boundingBox.getCenter( _offset ).negate();
10079
10080		this.translate( _offset.x, _offset.y, _offset.z );
10081
10082		return this;
10083
10084	}
10085
10086	setFromPoints( points ) {
10087
10088		const position = [];
10089
10090		for ( let i = 0, l = points.length; i < l; i ++ ) {
10091
10092			const point = points[ i ];
10093			position.push( point.x, point.y, point.z || 0 );
10094
10095		}
10096
10097		this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
10098
10099		return this;
10100
10101	}
10102
10103	computeBoundingBox() {
10104
10105		if ( this.boundingBox === null ) {
10106
10107			this.boundingBox = new Box3();
10108
10109		}
10110
10111		const position = this.attributes.position;
10112		const morphAttributesPosition = this.morphAttributes.position;
10113
10114		if ( position && position.isGLBufferAttribute ) {
10115
10116			console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this );
10117
10118			this.boundingBox.set(
10119				new Vector3( - Infinity, - Infinity, - Infinity ),
10120				new Vector3( + Infinity, + Infinity, + Infinity )
10121			);
10122
10123			return;
10124
10125		}
10126
10127		if ( position !== undefined ) {
10128
10129			this.boundingBox.setFromBufferAttribute( position );
10130
10131			// process morph attributes if present
10132
10133			if ( morphAttributesPosition ) {
10134
10135				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10136
10137					const morphAttribute = morphAttributesPosition[ i ];
10138					_box$1.setFromBufferAttribute( morphAttribute );
10139
10140					if ( this.morphTargetsRelative ) {
10141
10142						_vector$8.addVectors( this.boundingBox.min, _box$1.min );
10143						this.boundingBox.expandByPoint( _vector$8 );
10144
10145						_vector$8.addVectors( this.boundingBox.max, _box$1.max );
10146						this.boundingBox.expandByPoint( _vector$8 );
10147
10148					} else {
10149
10150						this.boundingBox.expandByPoint( _box$1.min );
10151						this.boundingBox.expandByPoint( _box$1.max );
10152
10153					}
10154
10155				}
10156
10157			}
10158
10159		} else {
10160
10161			this.boundingBox.makeEmpty();
10162
10163		}
10164
10165		if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
10166
10167			console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
10168
10169		}
10170
10171	}
10172
10173	computeBoundingSphere() {
10174
10175		if ( this.boundingSphere === null ) {
10176
10177			this.boundingSphere = new Sphere();
10178
10179		}
10180
10181		const position = this.attributes.position;
10182		const morphAttributesPosition = this.morphAttributes.position;
10183
10184		if ( position && position.isGLBufferAttribute ) {
10185
10186			console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "fal
vendor: 5,873 bytes, lines 10186-10456
10186se".', this );
10187
10188			this.boundingSphere.set( new Vector3(), Infinity );
10189
10190			return;
10191
10192		}
10193
10194		if ( position ) {
10195
10196			// first, find the center of the bounding sphere
10197
10198			const center = this.boundingSphere.center;
10199
10200			_box$1.setFromBufferAttribute( position );
10201
10202			// process morph attributes if present
10203
10204			if ( morphAttributesPosition ) {
10205
10206				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10207
10208					const morphAttribute = morphAttributesPosition[ i ];
10209					_boxMorphTargets.setFromBufferAttribute( morphAttribute );
10210
10211					if ( this.morphTargetsRelative ) {
10212
10213						_vector$8.addVectors( _box$1.min, _boxMorphTargets.min );
10214						_box$1.expandByPoint( _vector$8 );
10215
10216						_vector$8.addVectors( _box$1.max, _boxMorphTargets.max );
10217						_box$1.expandByPoint( _vector$8 );
10218
10219					} else {
10220
10221						_box$1.expandByPoint( _boxMorphTargets.min );
10222						_box$1.expandByPoint( _boxMorphTargets.max );
10223
10224					}
10225
10226				}
10227
10228			}
10229
10230			_box$1.getCenter( center );
10231
10232			// second, try to find a boundingSphere with a radius smaller than the
10233			// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
10234
10235			let maxRadiusSq = 0;
10236
10237			for ( let i = 0, il = position.count; i < il; i ++ ) {
10238
10239				_vector$8.fromBufferAttribute( position, i );
10240
10241				maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10242
10243			}
10244
10245			// process morph attributes if present
10246
10247			if ( morphAttributesPosition ) {
10248
10249				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10250
10251					const morphAttribute = morphAttributesPosition[ i ];
10252					const morphTargetsRelative = this.morphTargetsRelative;
10253
10254					for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
10255
10256						_vector$8.fromBufferAttribute( morphAttribute, j );
10257
10258						if ( morphTargetsRelative ) {
10259
10260							_offset.fromBufferAttribute( position, j );
10261							_vector$8.add( _offset );
10262
10263						}
10264
10265						maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10266
10267					}
10268
10269				}
10270
10271			}
10272
10273			this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
10274
10275			if ( isNaN( this.boundingSphere.radius ) ) {
10276
10277				console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
10278
10279			}
10280
10281		}
10282
10283	}
10284
10285	computeTangents() {
10286
10287		const index = this.index;
10288		const attributes = this.attributes;
10289
10290		// based on http://www.terathon.com/code/tangent.html
10291		// (per vertex tangents)
10292
10293		if ( index === null ||
10294			 attributes.position === undefined ||
10295			 attributes.normal === undefined ||
10296			 attributes.uv === undefined ) {
10297
10298			console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
10299			return;
10300
10301		}
10302
10303		const indices = index.array;
10304		const positions = attributes.position.array;
10305		const normals = attributes.normal.array;
10306		const uvs = attributes.uv.array;
10307
10308		const nVertices = positions.length / 3;
10309
10310		if ( this.hasAttribute( 'tangent' ) === false ) {
10311
10312			this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
10313
10314		}
10315
10316		const tangents = this.getAttribute( 'tangent' ).array;
10317
10318		const tan1 = [], tan2 = [];
10319
10320		for ( let i = 0; i < nVertices; i ++ ) {
10321
10322			tan1[ i ] = new Vector3();
10323			tan2[ i ] = new Vector3();
10324
10325		}
10326
10327		const vA = new Vector3(),
10328			vB = new Vector3(),
10329			vC = new Vector3(),
10330
10331			uvA = new Vector2(),
10332			uvB = new Vector2(),
10333			uvC = new Vector2(),
10334
10335			sdir = new Vector3(),
10336			tdir = new Vector3();
10337
10338		function handleTriangle( a, b, c ) {
10339
10340			vA.fromArray( positions, a * 3 );
10341			vB.fromArray( positions, b * 3 );
10342			vC.fromArray( positions, c * 3 );
10343
10344			uvA.fromArray( uvs, a * 2 );
10345			uvB.fromArray( uvs, b * 2 );
10346			uvC.fromArray( uvs, c * 2 );
10347
10348			vB.sub( vA );
10349			vC.sub( vA );
10350
10351			uvB.sub( uvA );
10352			uvC.sub( uvA );
10353
10354			const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
10355
10356			// silently ignore degenerate uv triangles having coincident or colinear vertices
10357
10358			if ( ! isFinite( r ) ) return;
10359
10360			sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
10361			tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
10362
10363			tan1[ a ].add( sdir );
10364			tan1[ b ].add( sdir );
10365			tan1[ c ].add( sdir );
10366
10367			tan2[ a ].add( tdir );
10368			tan2[ b ].add( tdir );
10369			tan2[ c ].add( tdir );
10370
10371		}
10372
10373		let groups = this.groups;
10374
10375		if ( groups.length === 0 ) {
10376
10377			groups = [ {
10378				start: 0,
10379				count: indices.length
10380			} ];
10381
10382		}
10383
10384		for ( let i = 0, il = groups.length; i < il; ++ i ) {
10385
10386			const group = groups[ i ];
10387
10388			const start = group.start;
10389			const count = group.count;
10390
10391			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
10392
10393				handleTriangle(
10394					indices[ j + 0 ],
10395					indices[ j + 1 ],
10396					indices[ j + 2 ]
10397				);
10398
10399			}
10400
10401		}
10402
10403		const tmp = new Vector3(), tmp2 = new Vector3();
10404		const n = new Vector3(), n2 = new Vector3();
10405
10406		function handleVertex( v ) {
10407
10408			n.fromArray( normals, v * 3 );
10409			n2.copy( n );
10410
10411			const t = tan1[ v ];
10412
10413			// Gram-Schmidt orthogonalize
10414
10415			tmp.copy( t );
10416			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
10417
10418			// Calculate handedness
10419
10420			tmp2.crossVectors( n2, t );
10421			const test = tmp2.dot( tan2[ v ] );
10422			const w = ( test < 0.0 ) ? - 1.0 : 1.0;
10423
10424			tangents[ v * 4 ] = tmp.x;
10425			tangents[ v * 4 + 1 ] = tmp.y;
10426			tangents[ v * 4 + 2 ] = tmp.z;
10427			tangents[ v * 4 + 3 ] = w;
10428
10429		}
10430
10431		for ( let i = 0, il = groups.length; i < il; ++ i ) {
10432
10433			const group = groups[ i ];
10434
10435			const start = group.start;
10436			const count = group.count;
10437
10438			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
10439
10440				handleVertex( indices[ j + 0 ] );
10441				handleVertex( indices[ j + 1 ] );
10442				handleVertex( indices[ j + 2 ] );
10443
10444			}
10445
10446		}
10447
10448	}
10449
10450	computeVertexNormals() {
10451
10452		const index = this.index;
10453		const positionAttribute = this.getAttribute( 'position' );
10454
10455		if ( positionAttribute !== undefined ) {
10456
vendor: 12,723 bytes, lines 10457-11085
10457			let normalAttribute = this.getAttribute( 'normal' );
10458
10459			if ( normalAttribute === undefined ) {
10460
10461				normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
10462				this.setAttribute( 'normal', normalAttribute );
10463
10464			} else {
10465
10466				// reset existing normals to zero
10467
10468				for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
10469
10470					normalAttribute.setXYZ( i, 0, 0, 0 );
10471
10472				}
10473
10474			}
10475
10476			const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
10477			const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
10478			const cb = new Vector3(), ab = new Vector3();
10479
10480			// indexed elements
10481
10482			if ( index ) {
10483
10484				for ( let i = 0, il = index.count; i < il; i += 3 ) {
10485
10486					const vA = index.getX( i + 0 );
10487					const vB = index.getX( i + 1 );
10488					const vC = index.getX( i + 2 );
10489
10490					pA.fromBufferAttribute( positionAttribute, vA );
10491					pB.fromBufferAttribute( positionAttribute, vB );
10492					pC.fromBufferAttribute( positionAttribute, vC );
10493
10494					cb.subVectors( pC, pB );
10495					ab.subVectors( pA, pB );
10496					cb.cross( ab );
10497
10498					nA.fromBufferAttribute( normalAttribute, vA );
10499					nB.fromBufferAttribute( normalAttribute, vB );
10500					nC.fromBufferAttribute( normalAttribute, vC );
10501
10502					nA.add( cb );
10503					nB.add( cb );
10504					nC.add( cb );
10505
10506					normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
10507					normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
10508					normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
10509
10510				}
10511
10512			} else {
10513
10514				// non-indexed elements (unconnected triangle soup)
10515
10516				for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
10517
10518					pA.fromBufferAttribute( positionAttribute, i + 0 );
10519					pB.fromBufferAttribute( positionAttribute, i + 1 );
10520					pC.fromBufferAttribute( positionAttribute, i + 2 );
10521
10522					cb.subVectors( pC, pB );
10523					ab.subVectors( pA, pB );
10524					cb.cross( ab );
10525
10526					normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
10527					normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
10528					normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
10529
10530				}
10531
10532			}
10533
10534			this.normalizeNormals();
10535
10536			normalAttribute.needsUpdate = true;
10537
10538		}
10539
10540	}
10541
10542	// @deprecated since r144
10543
10544	merge() {
10545
10546		console.error( 'THREE.BufferGeometry.merge() has been removed. Use THREE.BufferGeometryUtils.mergeBufferGeometries() instead.' );
10547		return this;
10548
10549	}
10550
10551	normalizeNormals() {
10552
10553		const normals = this.attributes.normal;
10554
10555		for ( let i = 0, il = normals.count; i < il; i ++ ) {
10556
10557			_vector$8.fromBufferAttribute( normals, i );
10558
10559			_vector$8.normalize();
10560
10561			normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
10562
10563		}
10564
10565	}
10566
10567	toNonIndexed() {
10568
10569		function convertBufferAttribute( attribute, indices ) {
10570
10571			const array = attribute.array;
10572			const itemSize = attribute.itemSize;
10573			const normalized = attribute.normalized;
10574
10575			const array2 = new array.constructor( indices.length * itemSize );
10576
10577			let index = 0, index2 = 0;
10578
10579			for ( let i = 0, l = indices.length; i < l; i ++ ) {
10580
10581				if ( attribute.isInterleavedBufferAttribute ) {
10582
10583					index = indices[ i ] * attribute.data.stride + attribute.offset;
10584
10585				} else {
10586
10587					index = indices[ i ] * itemSize;
10588
10589				}
10590
10591				for ( let j = 0; j < itemSize; j ++ ) {
10592
10593					array2[ index2 ++ ] = array[ index ++ ];
10594
10595				}
10596
10597			}
10598
10599			return new BufferAttribute( array2, itemSize, normalized );
10600
10601		}
10602
10603		//
10604
10605		if ( this.index === null ) {
10606
10607			console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
10608			return this;
10609
10610		}
10611
10612		const geometry2 = new BufferGeometry();
10613
10614		const indices = this.index.array;
10615		const attributes = this.attributes;
10616
10617		// attributes
10618
10619		for ( const name in attributes ) {
10620
10621			const attribute = attributes[ name ];
10622
10623			const newAttribute = convertBufferAttribute( attribute, indices );
10624
10625			geometry2.setAttribute( name, newAttribute );
10626
10627		}
10628
10629		// morph attributes
10630
10631		const morphAttributes = this.morphAttributes;
10632
10633		for ( const name in morphAttributes ) {
10634
10635			const morphArray = [];
10636			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
10637
10638			for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
10639
10640				const attribute = morphAttribute[ i ];
10641
10642				const newAttribute = convertBufferAttribute( attribute, indices );
10643
10644				morphArray.push( newAttribute );
10645
10646			}
10647
10648			geometry2.morphAttributes[ name ] = morphArray;
10649
10650		}
10651
10652		geometry2.morphTargetsRelative = this.morphTargetsRelative;
10653
10654		// groups
10655
10656		const groups = this.groups;
10657
10658		for ( let i = 0, l = groups.length; i < l; i ++ ) {
10659
10660			const group = groups[ i ];
10661			geometry2.addGroup( group.start, group.count, group.materialIndex );
10662
10663		}
10664
10665		return geometry2;
10666
10667	}
10668
10669	toJSON() {
10670
10671		const data = {
10672			metadata: {
10673				version: 4.5,
10674				type: 'BufferGeometry',
10675				generator: 'BufferGeometry.toJSON'
10676			}
10677		};
10678
10679		// standard BufferGeometry serialization
10680
10681		data.uuid = this.uuid;
10682		data.type = this.type;
10683		if ( this.name !== '' ) data.name = this.name;
10684		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
10685
10686		if ( this.parameters !== undefined ) {
10687
10688			const parameters = this.parameters;
10689
10690			for ( const key in parameters ) {
10691
10692				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
10693
10694			}
10695
10696			return data;
10697
10698		}
10699
10700		// for simplicity the code assumes attributes are not shared across geometries, see #15811
10701
10702		data.data = { attributes: {} };
10703
10704		const index = this.index;
10705
10706		if ( index !== null ) {
10707
10708			data.data.index = {
10709				type: index.array.constructor.name,
10710				array: Array.prototype.slice.call( index.array )
10711			};
10712
10713		}
10714
10715		const attributes = this.attributes;
10716
10717		for ( const key in attributes ) {
10718
10719			const attribute = attributes[ key ];
10720
10721			data.data.attributes[ key ] = attribute.toJSON( data.data );
10722
10723		}
10724
10725		const morphAttributes = {};
10726		let hasMorphAttributes = false;
10727
10728		for ( const key in this.morphAttributes ) {
10729
10730			const attributeArray = this.morphAttributes[ key ];
10731
10732			const array = [];
10733
10734			for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
10735
10736				const attribute = attributeArray[ i ];
10737
10738				array.push( attribute.toJSON( data.data ) );
10739
10740			}
10741
10742			if ( array.length > 0 ) {
10743
10744				morphAttributes[ key ] = array;
10745
10746				hasMorphAttributes = true;
10747
10748			}
10749
10750		}
10751
10752		if ( hasMorphAttributes ) {
10753
10754			data.data.morphAttributes = morphAttributes;
10755			data.data.morphTargetsRelative = this.morphTargetsRelative;
10756
10757		}
10758
10759		const groups = this.groups;
10760
10761		if ( groups.length > 0 ) {
10762
10763			data.data.groups = JSON.parse( JSON.stringify( groups ) );
10764
10765		}
10766
10767		const boundingSphere = this.boundingSphere;
10768
10769		if ( boundingSphere !== null ) {
10770
10771			data.data.boundingSphere = {
10772				center: boundingSphere.center.toArray(),
10773				radius: boundingSphere.radius
10774			};
10775
10776		}
10777
10778		return data;
10779
10780	}
10781
10782	clone() {
10783
10784		return new this.constructor().copy( this );
10785
10786	}
10787
10788	copy( source ) {
10789
10790		// reset
10791
10792		this.index = null;
10793		this.attributes = {};
10794		this.morphAttributes = {};
10795		this.groups = [];
10796		this.boundingBox = null;
10797		this.boundingSphere = null;
10798
10799		// used for storing cloned, shared data
10800
10801		const data = {};
10802
10803		// name
10804
10805		this.name = source.name;
10806
10807		// index
10808
10809		const index = source.index;
10810
10811		if ( index !== null ) {
10812
10813			this.setIndex( index.clone( data ) );
10814
10815		}
10816
10817		// attributes
10818
10819		const attributes = source.attributes;
10820
10821		for ( const name in attributes ) {
10822
10823			const attribute = attributes[ name ];
10824			this.setAttribute( name, attribute.clone( data ) );
10825
10826		}
10827
10828		// morph attributes
10829
10830		const morphAttributes = source.morphAttributes;
10831
10832		for ( const name in morphAttributes ) {
10833
10834			const array = [];
10835			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
10836
10837			for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
10838
10839				array.push( morphAttribute[ i ].clone( data ) );
10840
10841			}
10842
10843			this.morphAttributes[ name ] = array;
10844
10845		}
10846
10847		this.morphTargetsRelative = source.morphTargetsRelative;
10848
10849		// groups
10850
10851		const groups = source.groups;
10852
10853		for ( let i = 0, l = groups.length; i < l; i ++ ) {
10854
10855			const group = groups[ i ];
10856			this.addGroup( group.start, group.count, group.materialIndex );
10857
10858		}
10859
10860		// bounding box
10861
10862		const boundingBox = source.boundingBox;
10863
10864		if ( boundingBox !== null ) {
10865
10866			this.boundingBox = boundingBox.clone();
10867
10868		}
10869
10870		// bounding sphere
10871
10872		const boundingSphere = source.boundingSphere;
10873
10874		if ( boundingSphere !== null ) {
10875
10876			this.boundingSphere = boundingSphere.clone();
10877
10878		}
10879
10880		// draw range
10881
10882		this.drawRange.start = source.drawRange.start;
10883		this.drawRange.count = source.drawRange.count;
10884
10885		// user data
10886
10887		this.userData = source.userData;
10888
10889		return this;
10890
10891	}
10892
10893	dispose() {
10894
10895		this.dispatchEvent( { type: 'dispose' } );
10896
10897	}
10898
10899}
10900
10901const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4();
10902const _ray$2 = /*@__PURE__*/ new Ray();
10903const _sphere$3 = /*@__PURE__*/ new Sphere();
10904const _sphereHitAt = /*@__PURE__*/ new Vector3();
10905
10906const _vA$1 = /*@__PURE__*/ new Vector3();
10907const _vB$1 = /*@__PURE__*/ new Vector3();
10908const _vC$1 = /*@__PURE__*/ new Vector3();
10909
10910const _tempA = /*@__PURE__*/ new Vector3();
10911const _morphA = /*@__PURE__*/ new Vector3();
10912
10913const _uvA$1 = /*@__PURE__*/ new Vector2();
10914const _uvB$1 = /*@__PURE__*/ new Vector2();
10915const _uvC$1 = /*@__PURE__*/ new Vector2();
10916
10917const _intersectionPoint = /*@__PURE__*/ new Vector3();
10918const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
10919
10920class Mesh extends Object3D {
10921
10922	constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
10923
10924		super();
10925
10926		this.isMesh = true;
10927
10928		this.type = 'Mesh';
10929
10930		this.geometry = geometry;
10931		this.material = material;
10932
10933		this.updateMorphTargets();
10934
10935	}
10936
10937	copy( source, recursive ) {
10938
10939		super.copy( source, recursive );
10940
10941		if ( source.morphTargetInfluences !== undefined ) {
10942
10943			this.morphTargetInfluences = source.morphTargetInfluences.slice();
10944
10945		}
10946
10947		if ( source.morphTargetDictionary !== undefined ) {
10948
10949			this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
10950
10951		}
10952
10953		this.material = source.material;
10954		this.geometry = source.geometry;
10955
10956		return this;
10957
10958	}
10959
10960	updateMorphTargets() {
10961
10962		const geometry = this.geometry;
10963
10964		const morphAttributes = geometry.morphAttributes;
10965		const keys = Object.keys( morphAttributes );
10966
10967		if ( keys.length > 0 ) {
10968
10969			const morphAttribute = morphAttributes[ keys[ 0 ] ];
10970
10971			if ( morphAttribute !== undefined ) {
10972
10973				this.morphTargetInfluences = [];
10974				this.morphTargetDictionary = {};
10975
10976				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
10977
10978					const name = morphAttribute[ m ].name || String( m );
10979
10980					this.morphTargetInfluences.push( 0 );
10981					this.morphTargetDictionary[ name ] = m;
10982
10983				}
10984
10985			}
10986
10987		}
10988
10989	}
10990
10991	getVertexPosition( index, target ) {
10992
10993		const geometry = this.geometry;
10994		const position = geometry.attributes.position;
10995		const morphPosition = geometry.morphAttributes.position;
10996		const morphTargetsRelative = geometry.morphTargetsRelative;
10997
10998		target.fromBufferAttribute( position, index );
10999
11000		const morphInfluences = this.morphTargetInfluences;
11001
11002		if ( morphPosition && morphInfluences ) {
11003
11004			_morphA.set( 0, 0, 0 );
11005
11006			for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
11007
11008				const influence = morphInfluences[ i ];
11009				const morphAttribute = morphPosition[ i ];
11010
11011				if ( influence === 0 ) continue;
11012
11013				_tempA.fromBufferAttribute( morphAttribute, index );
11014
11015				if ( morphTargetsRelative ) {
11016
11017					_morphA.addScaledVector( _tempA, influence );
11018
11019				} else {
11020
11021					_morphA.addScaledVector( _tempA.sub( target ), influence );
11022
11023				}
11024
11025			}
11026
11027			target.add( _morphA );
11028
11029		}
11030
11031		if ( this.isSkinnedMesh ) {
11032
11033			this.boneTransform( index, target );
11034
11035		}
11036
11037		return target;
11038
11039	}
11040
11041	raycast( raycaster, intersects ) {
11042
11043		const geometry = this.geometry;
11044		const material = this.material;
11045		const matrixWorld = this.matrixWorld;
11046
11047		if ( material === undefined ) return;
11048
11049		// Checking boundingSphere distance to ray
11050
11051		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
11052
11053		_sphere$3.copy( geometry.boundingSphere );
11054		_sphere$3.applyMatrix4( matrixWorld );
11055
11056		_ray$2.copy( raycaster.ray ).recast( raycaster.near );
11057
11058		if ( _sphere$3.containsPoint( _ray$2.origin ) === false ) {
11059
11060			if ( _ray$2.intersectSphere( _sphere$3, _sphereHitAt ) === null ) return;
11061
11062			if ( _ray$2.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return;
11063
11064		}
11065
11066		//
11067
11068		_inverseMatrix$2.copy( matrixWorld ).invert();
11069		_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
11070
11071		// Check boundingBox before continuing
11072
11073		if ( geometry.boundingBox !== null ) {
11074
11075			if ( _ray$2.intersectsBox( geometry.boundingBox ) === false ) return;
11076
11077		}
11078
11079		let intersection;
11080
11081		const index = geometry.index;
11082		const position = geometry.attributes.position;
11083		const uv = geometry.attributes.uv;
11084		const uv2 = geometry.attributes.uv2;
11085		const groups = geometry.groups;
vendor: 6,468 bytes, lines 11086-11338
11086		const drawRange = geometry.drawRange;
11087
11088		if ( index !== null ) {
11089
11090			// indexed buffer geometry
11091
11092			if ( Array.isArray( material ) ) {
11093
11094				for ( let i = 0, il = groups.length; i < il; i ++ ) {
11095
11096					const group = groups[ i ];
11097					const groupMaterial = material[ group.materialIndex ];
11098
11099					const start = Math.max( group.start, drawRange.start );
11100					const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11101
11102					for ( let j = start, jl = end; j < jl; j += 3 ) {
11103
11104						const a = index.getX( j );
11105						const b = index.getX( j + 1 );
11106						const c = index.getX( j + 2 );
11107
11108						intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c );
11109
11110						if ( intersection ) {
11111
11112							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
11113							intersection.face.materialIndex = group.materialIndex;
11114							intersects.push( intersection );
11115
11116						}
11117
11118					}
11119
11120				}
11121
11122			} else {
11123
11124				const start = Math.max( 0, drawRange.start );
11125				const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
11126
11127				for ( let i = start, il = end; i < il; i += 3 ) {
11128
11129					const a = index.getX( i );
11130					const b = index.getX( i + 1 );
11131					const c = index.getX( i + 2 );
11132
11133					intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c );
11134
11135					if ( intersection ) {
11136
11137						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
11138						intersects.push( intersection );
11139
11140					}
11141
11142				}
11143
11144			}
11145
11146		} else if ( position !== undefined ) {
11147
11148			// non-indexed buffer geometry
11149
11150			if ( Array.isArray( material ) ) {
11151
11152				for ( let i = 0, il = groups.length; i < il; i ++ ) {
11153
11154					const group = groups[ i ];
11155					const groupMaterial = material[ group.materialIndex ];
11156
11157					const start = Math.max( group.start, drawRange.start );
11158					const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11159
11160					for ( let j = start, jl = end; j < jl; j += 3 ) {
11161
11162						const a = j;
11163						const b = j + 1;
11164						const c = j + 2;
11165
11166						intersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray$2, uv, uv2, a, b, c );
11167
11168						if ( intersection ) {
11169
11170							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
11171							intersection.face.materialIndex = group.materialIndex;
11172							intersects.push( intersection );
11173
11174						}
11175
11176					}
11177
11178				}
11179
11180			} else {
11181
11182				const start = Math.max( 0, drawRange.start );
11183				const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
11184
11185				for ( let i = start, il = end; i < il; i += 3 ) {
11186
11187					const a = i;
11188					const b = i + 1;
11189					const c = i + 2;
11190
11191					intersection = checkBufferGeometryIntersection( this, material, raycaster, _ray$2, uv, uv2, a, b, c );
11192
11193					if ( intersection ) {
11194
11195						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
11196						intersects.push( intersection );
11197
11198					}
11199
11200				}
11201
11202			}
11203
11204		}
11205
11206	}
11207
11208}
11209
11210function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
11211
11212	let intersect;
11213
11214	if ( material.side === BackSide ) {
11215
11216		intersect = ray.intersectTriangle( pC, pB, pA, true, point );
11217
11218	} else {
11219
11220		intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point );
11221
11222	}
11223
11224	if ( intersect === null ) return null;
11225
11226	_intersectionPointWorld.copy( point );
11227	_intersectionPointWorld.applyMatrix4( object.matrixWorld );
11228
11229	const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
11230
11231	if ( distance < raycaster.near || distance > raycaster.far ) return null;
11232
11233	return {
11234		distance: distance,
11235		point: _intersectionPointWorld.clone(),
11236		object: object
11237	};
11238
11239}
11240
11241function checkBufferGeometryIntersection( object, material, raycaster, ray, uv, uv2, a, b, c ) {
11242
11243	object.getVertexPosition( a, _vA$1 );
11244	object.getVertexPosition( b, _vB$1 );
11245	object.getVertexPosition( c, _vC$1 );
11246
11247	const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint );
11248
11249	if ( intersection ) {
11250
11251		if ( uv ) {
11252
11253			_uvA$1.fromBufferAttribute( uv, a );
11254			_uvB$1.fromBufferAttribute( uv, b );
11255			_uvC$1.fromBufferAttribute( uv, c );
11256
11257			intersection.uv = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
11258
11259		}
11260
11261		if ( uv2 ) {
11262
11263			_uvA$1.fromBufferAttribute( uv2, a );
11264			_uvB$1.fromBufferAttribute( uv2, b );
11265			_uvC$1.fromBufferAttribute( uv2, c );
11266
11267			intersection.uv2 = Triangle.getUV( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
11268
11269		}
11270
11271		const face = {
11272			a: a,
11273			b: b,
11274			c: c,
11275			normal: new Vector3(),
11276			materialIndex: 0
11277		};
11278
11279		Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal );
11280
11281		intersection.face = face;
11282
11283	}
11284
11285	return intersection;
11286
11287}
11288
11289class BoxGeometry extends BufferGeometry {
11290
11291	constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
11292
11293		super();
11294
11295		this.type = 'BoxGeometry';
11296
11297		this.parameters = {
11298			width: width,
11299			height: height,
11300			depth: depth,
11301			widthSegments: widthSegments,
11302			heightSegments: heightSegments,
11303			depthSegments: depthSegments
11304		};
11305
11306		const scope = this;
11307
11308		// segments
11309
11310		widthSegments = Math.floor( widthSegments );
11311		heightSegments = Math.floor( heightSegments );
11312		depthSegments = Math.floor( depthSegments );
11313
11314		// buffers
11315
11316		const indices = [];
11317		const vertices = [];
11318		const normals = [];
11319		const uvs = [];
11320
11321		// helper variables
11322
11323		let numberOfVertices = 0;
11324		let groupStart = 0;
11325
11326		// build each side of the box geometry
11327
11328		buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
11329		buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
11330		buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
11331		buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
11332		buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
11333		buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
11334
11335		// build geometry
11336
11337		this.setIndex( indices );
11338		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,573 bytes, lines 11339-11579
11339		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
11340		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
11341
11342		function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
11343
11344			const segmentWidth = width / gridX;
11345			const segmentHeight = height / gridY;
11346
11347			const widthHalf = width / 2;
11348			const heightHalf = height / 2;
11349			const depthHalf = depth / 2;
11350
11351			const gridX1 = gridX + 1;
11352			const gridY1 = gridY + 1;
11353
11354			let vertexCounter = 0;
11355			let groupCount = 0;
11356
11357			const vector = new Vector3();
11358
11359			// generate vertices, normals and uvs
11360
11361			for ( let iy = 0; iy < gridY1; iy ++ ) {
11362
11363				const y = iy * segmentHeight - heightHalf;
11364
11365				for ( let ix = 0; ix < gridX1; ix ++ ) {
11366
11367					const x = ix * segmentWidth - widthHalf;
11368
11369					// set values to correct vector component
11370
11371					vector[ u ] = x * udir;
11372					vector[ v ] = y * vdir;
11373					vector[ w ] = depthHalf;
11374
11375					// now apply vector to vertex buffer
11376
11377					vertices.push( vector.x, vector.y, vector.z );
11378
11379					// set values to correct vector component
11380
11381					vector[ u ] = 0;
11382					vector[ v ] = 0;
11383					vector[ w ] = depth > 0 ? 1 : - 1;
11384
11385					// now apply vector to normal buffer
11386
11387					normals.push( vector.x, vector.y, vector.z );
11388
11389					// uvs
11390
11391					uvs.push( ix / gridX );
11392					uvs.push( 1 - ( iy / gridY ) );
11393
11394					// counters
11395
11396					vertexCounter += 1;
11397
11398				}
11399
11400			}
11401
11402			// indices
11403
11404			// 1. you need three indices to draw a single face
11405			// 2. a single segment consists of two faces
11406			// 3. so we need to generate six (2*3) indices per segment
11407
11408			for ( let iy = 0; iy < gridY; iy ++ ) {
11409
11410				for ( let ix = 0; ix < gridX; ix ++ ) {
11411
11412					const a = numberOfVertices + ix + gridX1 * iy;
11413					const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
11414					const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
11415					const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
11416
11417					// faces
11418
11419					indices.push( a, b, d );
11420					indices.push( b, c, d );
11421
11422					// increase counter
11423
11424					groupCount += 6;
11425
11426				}
11427
11428			}
11429
11430			// add a group to the geometry. this will ensure multi material support
11431
11432			scope.addGroup( groupStart, groupCount, materialIndex );
11433
11434			// calculate new start value for groups
11435
11436			groupStart += groupCount;
11437
11438			// update total number of vertices
11439
11440			numberOfVertices += vertexCounter;
11441
11442		}
11443
11444	}
11445
11446	copy( source ) {
11447
11448		super.copy( source );
11449
11450		this.parameters = Object.assign( {}, source.parameters );
11451
11452		return this;
11453
11454	}
11455
11456	static fromJSON( data ) {
11457
11458		return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
11459
11460	}
11461
11462}
11463
11464/**
11465 * Uniform Utilities
11466 */
11467
11468function cloneUniforms( src ) {
11469
11470	const dst = {};
11471
11472	for ( const u in src ) {
11473
11474		dst[ u ] = {};
11475
11476		for ( const p in src[ u ] ) {
11477
11478			const property = src[ u ][ p ];
11479
11480			if ( property && ( property.isColor ||
11481				property.isMatrix3 || property.isMatrix4 ||
11482				property.isVector2 || property.isVector3 || property.isVector4 ||
11483				property.isTexture || property.isQuaternion ) ) {
11484
11485				dst[ u ][ p ] = property.clone();
11486
11487			} else if ( Array.isArray( property ) ) {
11488
11489				dst[ u ][ p ] = property.slice();
11490
11491			} else {
11492
11493				dst[ u ][ p ] = property;
11494
11495			}
11496
11497		}
11498
11499	}
11500
11501	return dst;
11502
11503}
11504
11505function mergeUniforms( uniforms ) {
11506
11507	const merged = {};
11508
11509	for ( let u = 0; u < uniforms.length; u ++ ) {
11510
11511		const tmp = cloneUniforms( uniforms[ u ] );
11512
11513		for ( const p in tmp ) {
11514
11515			merged[ p ] = tmp[ p ];
11516
11517		}
11518
11519	}
11520
11521	return merged;
11522
11523}
11524
11525function cloneUniformsGroups( src ) {
11526
11527	const dst = [];
11528
11529	for ( let u = 0; u < src.length; u ++ ) {
11530
11531		dst.push( src[ u ].clone() );
11532
11533	}
11534
11535	return dst;
11536
11537}
11538
11539function getUnlitUniformColorSpace( renderer ) {
11540
11541	if ( renderer.getRenderTarget() === null ) {
11542
11543		// https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398
11544		return renderer.outputEncoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
11545
11546	}
11547
11548	return LinearSRGBColorSpace;
11549
11550}
11551
11552// Legacy
11553
11554const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
11555
11556var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
11557
11558var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
11559
11560class ShaderMaterial extends Material {
11561
11562	constructor( parameters ) {
11563
11564		super();
11565
11566		this.isShaderMaterial = true;
11567
11568		this.type = 'ShaderMaterial';
11569
11570		this.defines = {};
11571		this.uniforms = {};
11572		this.uniformsGroups = [];
11573
11574		this.vertexShader = default_vertex;
11575		this.fragmentShader = default_fragment;
11576
11577		this.linewidth = 1;
11578
11579		this.wireframe = false;
vendor: 4,992 bytes, lines 11580-11834
11580		this.wireframeLinewidth = 1;
11581
11582		this.fog = false; // set to use scene fog
11583		this.lights = false; // set to use scene lights
11584		this.clipping = false; // set to use user-defined clipping planes
11585
11586		this.extensions = {
11587			derivatives: false, // set to use derivatives
11588			fragDepth: false, // set to use fragment depth values
11589			drawBuffers: false, // set to use draw buffers
11590			shaderTextureLOD: false // set to use shader texture LOD
11591		};
11592
11593		// When rendered geometry doesn't include these attributes but the material does,
11594		// use these default values in WebGL. This avoids errors when buffer data is missing.
11595		this.defaultAttributeValues = {
11596			'color': [ 1, 1, 1 ],
11597			'uv': [ 0, 0 ],
11598			'uv2': [ 0, 0 ]
11599		};
11600
11601		this.index0AttributeName = undefined;
11602		this.uniformsNeedUpdate = false;
11603
11604		this.glslVersion = null;
11605
11606		if ( parameters !== undefined ) {
11607
11608			this.setValues( parameters );
11609
11610		}
11611
11612	}
11613
11614	copy( source ) {
11615
11616		super.copy( source );
11617
11618		this.fragmentShader = source.fragmentShader;
11619		this.vertexShader = source.vertexShader;
11620
11621		this.uniforms = cloneUniforms( source.uniforms );
11622		this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups );
11623
11624		this.defines = Object.assign( {}, source.defines );
11625
11626		this.wireframe = source.wireframe;
11627		this.wireframeLinewidth = source.wireframeLinewidth;
11628
11629		this.fog = source.fog;
11630		this.lights = source.lights;
11631		this.clipping = source.clipping;
11632
11633		this.extensions = Object.assign( {}, source.extensions );
11634
11635		this.glslVersion = source.glslVersion;
11636
11637		return this;
11638
11639	}
11640
11641	toJSON( meta ) {
11642
11643		const data = super.toJSON( meta );
11644
11645		data.glslVersion = this.glslVersion;
11646		data.uniforms = {};
11647
11648		for ( const name in this.uniforms ) {
11649
11650			const uniform = this.uniforms[ name ];
11651			const value = uniform.value;
11652
11653			if ( value && value.isTexture ) {
11654
11655				data.uniforms[ name ] = {
11656					type: 't',
11657					value: value.toJSON( meta ).uuid
11658				};
11659
11660			} else if ( value && value.isColor ) {
11661
11662				data.uniforms[ name ] = {
11663					type: 'c',
11664					value: value.getHex()
11665				};
11666
11667			} else if ( value && value.isVector2 ) {
11668
11669				data.uniforms[ name ] = {
11670					type: 'v2',
11671					value: value.toArray()
11672				};
11673
11674			} else if ( value && value.isVector3 ) {
11675
11676				data.uniforms[ name ] = {
11677					type: 'v3',
11678					value: value.toArray()
11679				};
11680
11681			} else if ( value && value.isVector4 ) {
11682
11683				data.uniforms[ name ] = {
11684					type: 'v4',
11685					value: value.toArray()
11686				};
11687
11688			} else if ( value && value.isMatrix3 ) {
11689
11690				data.uniforms[ name ] = {
11691					type: 'm3',
11692					value: value.toArray()
11693				};
11694
11695			} else if ( value && value.isMatrix4 ) {
11696
11697				data.uniforms[ name ] = {
11698					type: 'm4',
11699					value: value.toArray()
11700				};
11701
11702			} else {
11703
11704				data.uniforms[ name ] = {
11705					value: value
11706				};
11707
11708				// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
11709
11710			}
11711
11712		}
11713
11714		if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
11715
11716		data.vertexShader = this.vertexShader;
11717		data.fragmentShader = this.fragmentShader;
11718
11719		const extensions = {};
11720
11721		for ( const key in this.extensions ) {
11722
11723			if ( this.extensions[ key ] === true ) extensions[ key ] = true;
11724
11725		}
11726
11727		if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
11728
11729		return data;
11730
11731	}
11732
11733}
11734
11735class Camera extends Object3D {
11736
11737	constructor() {
11738
11739		super();
11740
11741		this.isCamera = true;
11742
11743		this.type = 'Camera';
11744
11745		this.matrixWorldInverse = new Matrix4();
11746
11747		this.projectionMatrix = new Matrix4();
11748		this.projectionMatrixInverse = new Matrix4();
11749
11750	}
11751
11752	copy( source, recursive ) {
11753
11754		super.copy( source, recursive );
11755
11756		this.matrixWorldInverse.copy( source.matrixWorldInverse );
11757
11758		this.projectionMatrix.copy( source.projectionMatrix );
11759		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
11760
11761		return this;
11762
11763	}
11764
11765	getWorldDirection( target ) {
11766
11767		this.updateWorldMatrix( true, false );
11768
11769		const e = this.matrixWorld.elements;
11770
11771		return target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();
11772
11773	}
11774
11775	updateMatrixWorld( force ) {
11776
11777		super.updateMatrixWorld( force );
11778
11779		this.matrixWorldInverse.copy( this.matrixWorld ).invert();
11780
11781	}
11782
11783	updateWorldMatrix( updateParents, updateChildren ) {
11784
11785		super.updateWorldMatrix( updateParents, updateChildren );
11786
11787		this.matrixWorldInverse.copy( this.matrixWorld ).invert();
11788
11789	}
11790
11791	clone() {
11792
11793		return new this.constructor().copy( this );
11794
11795	}
11796
11797}
11798
11799class PerspectiveCamera extends Camera {
11800
11801	constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
11802
11803		super();
11804
11805		this.isPerspectiveCamera = true;
11806
11807		this.type = 'PerspectiveCamera';
11808
11809		this.fov = fov;
11810		this.zoom = 1;
11811
11812		this.near = near;
11813		this.far = far;
11814		this.focus = 10;
11815
11816		this.aspect = aspect;
11817		this.view = null;
11818
11819		this.filmGauge = 35;	// width of the film (default in millimeters)
11820		this.filmOffset = 0;	// horizontal film offset (same unit as gauge)
11821
11822		this.updateProjectionMatrix();
11823
11824	}
11825
11826	copy( source, recursive ) {
11827
11828		super.copy( source, recursive );
11829
11830		this.fov = source.fov;
11831		this.zoom = source.zoom;
11832
11833		this.near = source.near;
11834		this.far = source.far;
vendor: 3,387 bytes, lines 11835-11980
11835		this.focus = source.focus;
11836
11837		this.aspect = source.aspect;
11838		this.view = source.view === null ? null : Object.assign( {}, source.view );
11839
11840		this.filmGauge = source.filmGauge;
11841		this.filmOffset = source.filmOffset;
11842
11843		return this;
11844
11845	}
11846
11847	/**
11848	 * Sets the FOV by focal length in respect to the current .filmGauge.
11849	 *
11850	 * The default film gauge is 35, so that the focal length can be specified for
11851	 * a 35mm (full frame) camera.
11852	 *
11853	 * Values for focal length and film gauge must have the same unit.
11854	 */
11855	setFocalLength( focalLength ) {
11856
11857		/** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
11858		const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
11859
11860		this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
11861		this.updateProjectionMatrix();
11862
11863	}
11864
11865	/**
11866	 * Calculates the focal length from the current .fov and .filmGauge.
11867	 */
11868	getFocalLength() {
11869
11870		const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
11871
11872		return 0.5 * this.getFilmHeight() / vExtentSlope;
11873
11874	}
11875
11876	getEffectiveFOV() {
11877
11878		return RAD2DEG * 2 * Math.atan(
11879			Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
11880
11881	}
11882
11883	getFilmWidth() {
11884
11885		// film not completely covered in portrait format (aspect < 1)
11886		return this.filmGauge * Math.min( this.aspect, 1 );
11887
11888	}
11889
11890	getFilmHeight() {
11891
11892		// film not completely covered in landscape format (aspect > 1)
11893		return this.filmGauge / Math.max( this.aspect, 1 );
11894
11895	}
11896
11897	/**
11898	 * Sets an offset in a larger frustum. This is useful for multi-window or
11899	 * multi-monitor/multi-machine setups.
11900	 *
11901	 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
11902	 * the monitors are in grid like this
11903	 *
11904	 *   +---+---+---+
11905	 *   | A | B | C |
11906	 *   +---+---+---+
11907	 *   | D | E | F |
11908	 *   +---+---+---+
11909	 *
11910	 * then for each monitor you would call it like this
11911	 *
11912	 *   const w = 1920;
11913	 *   const h = 1080;
11914	 *   const fullWidth = w * 3;
11915	 *   const fullHeight = h * 2;
11916	 *
11917	 *   --A--
11918	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
11919	 *   --B--
11920	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
11921	 *   --C--
11922	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
11923	 *   --D--
11924	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
11925	 *   --E--
11926	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
11927	 *   --F--
11928	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
11929	 *
11930	 *   Note there is no reason monitors have to be the same size or in a grid.
11931	 */
11932	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
11933
11934		this.aspect = fullWidth / fullHeight;
11935
11936		if ( this.view === null ) {
11937
11938			this.view = {
11939				enabled: true,
11940				fullWidth: 1,
11941				fullHeight: 1,
11942				offsetX: 0,
11943				offsetY: 0,
11944				width: 1,
11945				height: 1
11946			};
11947
11948		}
11949
11950		this.view.enabled = true;
11951		this.view.fullWidth = fullWidth;
11952		this.view.fullHeight = fullHeight;
11953		this.view.offsetX = x;
11954		this.view.offsetY = y;
11955		this.view.width = width;
11956		this.view.height = height;
11957
11958		this.updateProjectionMatrix();
11959
11960	}
11961
11962	clearViewOffset() {
11963
11964		if ( this.view !== null ) {
11965
11966			this.view.enabled = false;
11967
11968		}
11969
11970		this.updateProjectionMatrix();
11971
11972	}
11973
11974	updateProjectionMatrix() {
11975
11976		const near = this.near;
11977		let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
11978		let height = 2 * top;
11979		let width = this.aspect * height;
11980		let left = - 0.5 * width;
11981		const view = this.view;
11982
11983		if ( this.view !== null && this.view.enabled ) {
11984
11985			const fullWidth = view.fullWidth,
11986				fullHeight = view.fullHeight;
11987
11988			left += view.offsetX * width / fullWidth;
11989			top -= view.offsetY * height / fullHeight;
11990			width *= view.width / fullWidth;
11991			height *= view.height / fullHeight;
11992
11993		}
11994
11995		const skew = this.filmOffset;
11996		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
11997
11998		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );
11999
12000		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
12001
12002	}
12003
12004	toJSON( meta ) {
12005
12006		const data = super.toJSON( meta );
12007
12008		data.object.fov = this.fov;
12009		data.object.zoom = this.zoom;
12010
12011		data.object.near = this.near;
12012		data.object.far = this.far;
12013		data.object.focus = this.focus;
12014
12015		data.object.aspect = this.aspect;
12016
12017		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
12018
12019		data.object.filmGauge = this.filmGauge;
12020		data.object.filmOffset = this.filmOffset;
12021
12022		return data;
12023
12024	}
12025
12026}
12027
12028const fov = - 90; // negative fov is not an error
12029const aspect = 1;
12030
12031class CubeCamera extends Object3D {
12032
12033	constructor( near, far, renderTarget ) {
12034
12035		super();
12036
12037		this.type = 'CubeCamera';
12038
12039		this.renderTarget = renderTarget;
12040
12041		const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
12042		cameraPX.layers = this.layers;
12043		cameraPX.up.set( 0, 1, 0 );
12044		cameraPX.lookAt( 1, 0, 0 );
12045		this.add( cameraPX );
12046
12047		const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
12048		cameraNX.layers = this.layers;
12049		cameraNX.up.set( 0, 1, 0 );
12050		cameraNX.lookAt( - 1, 0, 0 );
12051		this.add( cameraNX );
12052
12053		const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
12054		cameraPY.layers = this.layers;
12055		cameraPY.up.set( 0, 0, - 1 );
12056		cameraPY.lookAt( 0, 1, 0 );
12057		this.add( cameraPY );
12058
12059		const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
12060		cameraNY.layers = this.layers;
12061		cameraNY.up.set( 0, 0, 1 );
12062		cameraNY.lookAt( 0, - 1, 0 );
12063		this.add( cameraNY );
12064
12065		const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
12066		cameraPZ.layers = this.layers;
12067		cameraPZ.up.set( 0, 1, 0 );
12068		cameraPZ.lookAt( 0, 0, 1 );
12069		this.add( cameraPZ );
12070
12071		const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
12072		cameraNZ.layers = this.layers;
12073		cameraNZ.up.set( 0, 1, 0 );
12074		cameraNZ.lookAt( 0, 0, - 1 );
12075		this.add( cameraNZ );
12076
12077	}
12078
12079	update( renderer, scene ) {
12080
12081		if ( this.parent === null ) this.updateMatrixWorld();
12082
12083		const renderTarget = this.renderTarget;
12084
12085		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
12086
12087		const currentRenderTarget = renderer.getRenderTarget();
12088
12089		const currentToneMapping = renderer.toneMapping;
12090		const currentXrEnabled = renderer.xr.enabled;
12091
12092		renderer.toneMapping = NoToneMapping;
12093		renderer.xr.enabled = false;
12094
12095		const generateMipmaps = renderTarget.texture.generateMipmaps;
12096
12097		renderTarget.texture.generateMipmaps = false;
12098
12099		renderer.setRenderTarget( renderTarget, 0 );
12100		renderer.render( scene, cameraPX );
12101
12102		renderer.setRenderTarget( renderTarget, 1 );
12103		renderer.render( scene, cameraNX );
12104
12105		renderer.setRenderTarget( renderTarget, 2 );
12106		renderer.render( scene, cameraPY );
12107
12108		renderer.setRenderTarget( renderTarget, 3 );
12109		renderer.render( scene, cameraNY );
12110
12111		renderer.setRenderTarget( renderTarget, 4 );
12112		renderer.render( scene, cameraPZ );
12113
12114		renderTarget.texture.generateMipmaps = generateMipmaps;
12115
12116		renderer.setRenderTarget( renderTarget, 5 );
12117		renderer.render( scene, cameraNZ );
12118
12119		renderer.setRenderTarget( currentRenderTarget );
12120
12121		renderer.toneMapping = currentToneMapping;
12122		renderer.xr.enabled = currentXrEnabled;
12123
12124		renderTarget.texture.needsPMREMUpdate = true;
12125
12126	}
12127
12128}
12129
12130class CubeTexture extends Texture {
12131
12132	constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {
12133
12134		images = images !== undefined ? images : [];
12135		mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
12136
12137		super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
12138
12139		this.isCubeTexture = true;
12140
12141		this.flipY = false;
vendor: 4,767 bytes, lines 12142-12361
12142
12143	}
12144
12145	get images() {
12146
12147		return this.image;
12148
12149	}
12150
12151	set images( value ) {
12152
12153		this.image = value;
12154
12155	}
12156
12157}
12158
12159class WebGLCubeRenderTarget extends WebGLRenderTarget {
12160
12161	constructor( size = 1, options = {} ) {
12162
12163		super( size, size, options );
12164
12165		this.isWebGLCubeRenderTarget = true;
12166
12167		const image = { width: size, height: size, depth: 1 };
12168		const images = [ image, image, image, image, image, image ];
12169
12170		this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
12171
12172		// By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
12173		// in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
12174		// in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
12175
12176		// three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
12177		// and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
12178		// as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
12179
12180		this.texture.isRenderTargetTexture = true;
12181
12182		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
12183		this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
12184
12185	}
12186
12187	fromEquirectangularTexture( renderer, texture ) {
12188
12189		this.texture.type = texture.type;
12190		this.texture.encoding = texture.encoding;
12191
12192		this.texture.generateMipmaps = texture.generateMipmaps;
12193		this.texture.minFilter = texture.minFilter;
12194		this.texture.magFilter = texture.magFilter;
12195
12196		const shader = {
12197
12198			uniforms: {
12199				tEquirect: { value: null },
12200			},
12201
12202			vertexShader: /* glsl */`
12203
12204				varying vec3 vWorldDirection;
12205
12206				vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
12207
12208					return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
12209
12210				}
12211
12212				void main() {
12213
12214					vWorldDirection = transformDirection( position, modelMatrix );
12215
12216					#include <begin_vertex>
12217					#include <project_vertex>
12218
12219				}
12220			`,
12221
12222			fragmentShader: /* glsl */`
12223
12224				uniform sampler2D tEquirect;
12225
12226				varying vec3 vWorldDirection;
12227
12228				#include <common>
12229
12230				void main() {
12231
12232					vec3 direction = normalize( vWorldDirection );
12233
12234					vec2 sampleUV = equirectUv( direction );
12235
12236					gl_FragColor = texture2D( tEquirect, sampleUV );
12237
12238				}
12239			`
12240		};
12241
12242		const geometry = new BoxGeometry( 5, 5, 5 );
12243
12244		const material = new ShaderMaterial( {
12245
12246			name: 'CubemapFromEquirect',
12247
12248			uniforms: cloneUniforms( shader.uniforms ),
12249			vertexShader: shader.vertexShader,
12250			fragmentShader: shader.fragmentShader,
12251			side: BackSide,
12252			blending: NoBlending
12253
12254		} );
12255
12256		material.uniforms.tEquirect.value = texture;
12257
12258		const mesh = new Mesh( geometry, material );
12259
12260		const currentMinFilter = texture.minFilter;
12261
12262		// Avoid blurred poles
12263		if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
12264
12265		const camera = new CubeCamera( 1, 10, this );
12266		camera.update( renderer, mesh );
12267
12268		texture.minFilter = currentMinFilter;
12269
12270		mesh.geometry.dispose();
12271		mesh.material.dispose();
12272
12273		return this;
12274
12275	}
12276
12277	clear( renderer, color, depth, stencil ) {
12278
12279		const currentRenderTarget = renderer.getRenderTarget();
12280
12281		for ( let i = 0; i < 6; i ++ ) {
12282
12283			renderer.setRenderTarget( this, i );
12284
12285			renderer.clear( color, depth, stencil );
12286
12287		}
12288
12289		renderer.setRenderTarget( currentRenderTarget );
12290
12291	}
12292
12293}
12294
12295const _vector1 = /*@__PURE__*/ new Vector3();
12296const _vector2 = /*@__PURE__*/ new Vector3();
12297const _normalMatrix = /*@__PURE__*/ new Matrix3();
12298
12299class Plane {
12300
12301	constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) {
12302
12303		this.isPlane = true;
12304
12305		// normal is assumed to be normalized
12306
12307		this.normal = normal;
12308		this.constant = constant;
12309
12310	}
12311
12312	set( normal, constant ) {
12313
12314		this.normal.copy( normal );
12315		this.constant = constant;
12316
12317		return this;
12318
12319	}
12320
12321	setComponents( x, y, z, w ) {
12322
12323		this.normal.set( x, y, z );
12324		this.constant = w;
12325
12326		return this;
12327
12328	}
12329
12330	setFromNormalAndCoplanarPoint( normal, point ) {
12331
12332		this.normal.copy( normal );
12333		this.constant = - point.dot( this.normal );
12334
12335		return this;
12336
12337	}
12338
12339	setFromCoplanarPoints( a, b, c ) {
12340
12341		const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
12342
12343		// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
12344
12345		this.setFromNormalAndCoplanarPoint( normal, a );
12346
12347		return this;
12348
12349	}
12350
12351	copy( plane ) {
12352
12353		this.normal.copy( plane.normal );
12354		this.constant = plane.constant;
12355
12356		return this;
12357
12358	}
12359
12360	normalize() {
12361
vendor: 4,441 bytes, lines 12362-12571
12362		// Note: will lead to a divide by zero if the plane is invalid.
12363
12364		const inverseNormalLength = 1.0 / this.normal.length();
12365		this.normal.multiplyScalar( inverseNormalLength );
12366		this.constant *= inverseNormalLength;
12367
12368		return this;
12369
12370	}
12371
12372	negate() {
12373
12374		this.constant *= - 1;
12375		this.normal.negate();
12376
12377		return this;
12378
12379	}
12380
12381	distanceToPoint( point ) {
12382
12383		return this.normal.dot( point ) + this.constant;
12384
12385	}
12386
12387	distanceToSphere( sphere ) {
12388
12389		return this.distanceToPoint( sphere.center ) - sphere.radius;
12390
12391	}
12392
12393	projectPoint( point, target ) {
12394
12395		return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) );
12396
12397	}
12398
12399	intersectLine( line, target ) {
12400
12401		const direction = line.delta( _vector1 );
12402
12403		const denominator = this.normal.dot( direction );
12404
12405		if ( denominator === 0 ) {
12406
12407			// line is coplanar, return origin
12408			if ( this.distanceToPoint( line.start ) === 0 ) {
12409
12410				return target.copy( line.start );
12411
12412			}
12413
12414			// Unsure if this is the correct method to handle this case.
12415			return null;
12416
12417		}
12418
12419		const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
12420
12421		if ( t < 0 || t > 1 ) {
12422
12423			return null;
12424
12425		}
12426
12427		return target.copy( line.start ).addScaledVector( direction, t );
12428
12429	}
12430
12431	intersectsLine( line ) {
12432
12433		// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
12434
12435		const startSign = this.distanceToPoint( line.start );
12436		const endSign = this.distanceToPoint( line.end );
12437
12438		return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
12439
12440	}
12441
12442	intersectsBox( box ) {
12443
12444		return box.intersectsPlane( this );
12445
12446	}
12447
12448	intersectsSphere( sphere ) {
12449
12450		return sphere.intersectsPlane( this );
12451
12452	}
12453
12454	coplanarPoint( target ) {
12455
12456		return target.copy( this.normal ).multiplyScalar( - this.constant );
12457
12458	}
12459
12460	applyMatrix4( matrix, optionalNormalMatrix ) {
12461
12462		const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
12463
12464		const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
12465
12466		const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
12467
12468		this.constant = - referencePoint.dot( normal );
12469
12470		return this;
12471
12472	}
12473
12474	translate( offset ) {
12475
12476		this.constant -= offset.dot( this.normal );
12477
12478		return this;
12479
12480	}
12481
12482	equals( plane ) {
12483
12484		return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
12485
12486	}
12487
12488	clone() {
12489
12490		return new this.constructor().copy( this );
12491
12492	}
12493
12494}
12495
12496const _sphere$2 = /*@__PURE__*/ new Sphere();
12497const _vector$7 = /*@__PURE__*/ new Vector3();
12498
12499class Frustum {
12500
12501	constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
12502
12503		this.planes = [ p0, p1, p2, p3, p4, p5 ];
12504
12505	}
12506
12507	set( p0, p1, p2, p3, p4, p5 ) {
12508
12509		const planes = this.planes;
12510
12511		planes[ 0 ].copy( p0 );
12512		planes[ 1 ].copy( p1 );
12513		planes[ 2 ].copy( p2 );
12514		planes[ 3 ].copy( p3 );
12515		planes[ 4 ].copy( p4 );
12516		planes[ 5 ].copy( p5 );
12517
12518		return this;
12519
12520	}
12521
12522	copy( frustum ) {
12523
12524		const planes = this.planes;
12525
12526		for ( let i = 0; i < 6; i ++ ) {
12527
12528			planes[ i ].copy( frustum.planes[ i ] );
12529
12530		}
12531
12532		return this;
12533
12534	}
12535
12536	setFromProjectionMatrix( m ) {
12537
12538		const planes = this.planes;
12539		const me = m.elements;
12540		const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
12541		const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
12542		const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
12543		const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
12544
12545		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
12546		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
12547		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
12548		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
12549		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
12550		planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
12551
12552		return this;
12553
12554	}
12555
12556	intersectsObject( object ) {
12557
12558		const geometry = object.geometry;
12559
12560		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
12561
12562		_sphere$2.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
12563
12564		return this.intersectsSphere( _sphere$2 );
12565
12566	}
12567
12568	intersectsSprite( sprite ) {
12569
12570		_sphere$2.center.set( 0, 0, 0 );
12571		_sphere$2.radius = 0.7071067811865476;
vendor: 5,575 bytes, lines 12572-12914
12572		_sphere$2.applyMatrix4( sprite.matrixWorld );
12573
12574		return this.intersectsSphere( _sphere$2 );
12575
12576	}
12577
12578	intersectsSphere( sphere ) {
12579
12580		const planes = this.planes;
12581		const center = sphere.center;
12582		const negRadius = - sphere.radius;
12583
12584		for ( let i = 0; i < 6; i ++ ) {
12585
12586			const distance = planes[ i ].distanceToPoint( center );
12587
12588			if ( distance < negRadius ) {
12589
12590				return false;
12591
12592			}
12593
12594		}
12595
12596		return true;
12597
12598	}
12599
12600	intersectsBox( box ) {
12601
12602		const planes = this.planes;
12603
12604		for ( let i = 0; i < 6; i ++ ) {
12605
12606			const plane = planes[ i ];
12607
12608			// corner at max distance
12609
12610			_vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x;
12611			_vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y;
12612			_vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z;
12613
12614			if ( plane.distanceToPoint( _vector$7 ) < 0 ) {
12615
12616				return false;
12617
12618			}
12619
12620		}
12621
12622		return true;
12623
12624	}
12625
12626	containsPoint( point ) {
12627
12628		const planes = this.planes;
12629
12630		for ( let i = 0; i < 6; i ++ ) {
12631
12632			if ( planes[ i ].distanceToPoint( point ) < 0 ) {
12633
12634				return false;
12635
12636			}
12637
12638		}
12639
12640		return true;
12641
12642	}
12643
12644	clone() {
12645
12646		return new this.constructor().copy( this );
12647
12648	}
12649
12650}
12651
12652function WebGLAnimation() {
12653
12654	let context = null;
12655	let isAnimating = false;
12656	let animationLoop = null;
12657	let requestId = null;
12658
12659	function onAnimationFrame( time, frame ) {
12660
12661		animationLoop( time, frame );
12662
12663		requestId = context.requestAnimationFrame( onAnimationFrame );
12664
12665	}
12666
12667	return {
12668
12669		start: function () {
12670
12671			if ( isAnimating === true ) return;
12672			if ( animationLoop === null ) return;
12673
12674			requestId = context.requestAnimationFrame( onAnimationFrame );
12675
12676			isAnimating = true;
12677
12678		},
12679
12680		stop: function () {
12681
12682			context.cancelAnimationFrame( requestId );
12683
12684			isAnimating = false;
12685
12686		},
12687
12688		setAnimationLoop: function ( callback ) {
12689
12690			animationLoop = callback;
12691
12692		},
12693
12694		setContext: function ( value ) {
12695
12696			context = value;
12697
12698		}
12699
12700	};
12701
12702}
12703
12704function WebGLAttributes( gl, capabilities ) {
12705
12706	const isWebGL2 = capabilities.isWebGL2;
12707
12708	const buffers = new WeakMap();
12709
12710	function createBuffer( attribute, bufferType ) {
12711
12712		const array = attribute.array;
12713		const usage = attribute.usage;
12714
12715		const buffer = gl.createBuffer();
12716
12717		gl.bindBuffer( bufferType, buffer );
12718		gl.bufferData( bufferType, array, usage );
12719
12720		attribute.onUploadCallback();
12721
12722		let type;
12723
12724		if ( array instanceof Float32Array ) {
12725
12726			type = 5126;
12727
12728		} else if ( array instanceof Uint16Array ) {
12729
12730			if ( attribute.isFloat16BufferAttribute ) {
12731
12732				if ( isWebGL2 ) {
12733
12734					type = 5131;
12735
12736				} else {
12737
12738					throw new Error( 'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
12739
12740				}
12741
12742			} else {
12743
12744				type = 5123;
12745
12746			}
12747
12748		} else if ( array instanceof Int16Array ) {
12749
12750			type = 5122;
12751
12752		} else if ( array instanceof Uint32Array ) {
12753
12754			type = 5125;
12755
12756		} else if ( array instanceof Int32Array ) {
12757
12758			type = 5124;
12759
12760		} else if ( array instanceof Int8Array ) {
12761
12762			type = 5120;
12763
12764		} else if ( array instanceof Uint8Array ) {
12765
12766			type = 5121;
12767
12768		} else if ( array instanceof Uint8ClampedArray ) {
12769
12770			type = 5121;
12771
12772		} else {
12773
12774			throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array );
12775
12776		}
12777
12778		return {
12779			buffer: buffer,
12780			type: type,
12781			bytesPerElement: array.BYTES_PER_ELEMENT,
12782			version: attribute.version
12783		};
12784
12785	}
12786
12787	function updateBuffer( buffer, attribute, bufferType ) {
12788
12789		const array = attribute.array;
12790		const updateRange = attribute.updateRange;
12791
12792		gl.bindBuffer( bufferType, buffer );
12793
12794		if ( updateRange.count === - 1 ) {
12795
12796			// Not using update ranges
12797
12798			gl.bufferSubData( bufferType, 0, array );
12799
12800		} else {
12801
12802			if ( isWebGL2 ) {
12803
12804				gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
12805					array, updateRange.offset, updateRange.count );
12806
12807			} else {
12808
12809				gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
12810					array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
12811
12812			}
12813
12814			updateRange.count = - 1; // reset range
12815
12816		}
12817
12818		attribute.onUploadCallback();
12819
12820	}
12821
12822	//
12823
12824	function get( attribute ) {
12825
12826		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12827
12828		return buffers.get( attribute );
12829
12830	}
12831
12832	function remove( attribute ) {
12833
12834		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12835
12836		const data = buffers.get( attribute );
12837
12838		if ( data ) {
12839
12840			gl.deleteBuffer( data.buffer );
12841
12842			buffers.delete( attribute );
12843
12844		}
12845
12846	}
12847
12848	function update( attribute, bufferType ) {
12849
12850		if ( attribute.isGLBufferAttribute ) {
12851
12852			const cached = buffers.get( attribute );
12853
12854			if ( ! cached || cached.version < attribute.version ) {
12855
12856				buffers.set( attribute, {
12857					buffer: attribute.buffer,
12858					type: attribute.type,
12859					bytesPerElement: attribute.elementSize,
12860					version: attribute.version
12861				} );
12862
12863			}
12864
12865			return;
12866
12867		}
12868
12869		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
12870
12871		const data = buffers.get( attribute );
12872
12873		if ( data === undefined ) {
12874
12875			buffers.set( attribute, createBuffer( attribute, bufferType ) );
12876
12877		} else if ( data.version < attribute.version ) {
12878
12879			updateBuffer( data.buffer, attribute, bufferType );
12880
12881			data.version = attribute.version;
12882
12883		}
12884
12885	}
12886
12887	return {
12888
12889		get: get,
12890		remove: remove,
12891		update: update
12892
12893	};
12894
12895}
12896
12897class PlaneGeometry extends BufferGeometry {
12898
12899	constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
12900
12901		super();
12902
12903		this.type = 'PlaneGeometry';
12904
12905		this.parameters = {
12906			width: width,
12907			height: height,
12908			widthSegments: widthSegments,
12909			heightSegments: heightSegments
12910		};
12911
12912		const width_half = width / 2;
12913		const height_half = height / 2;
12914
vendor: 4,135 bytes, lines 12915-13007
12915		const gridX = Math.floor( widthSegments );
12916		const gridY = Math.floor( heightSegments );
12917
12918		const gridX1 = gridX + 1;
12919		const gridY1 = gridY + 1;
12920
12921		const segment_width = width / gridX;
12922		const segment_height = height / gridY;
12923
12924		//
12925
12926		const indices = [];
12927		const vertices = [];
12928		const normals = [];
12929		const uvs = [];
12930
12931		for ( let iy = 0; iy < gridY1; iy ++ ) {
12932
12933			const y = iy * segment_height - height_half;
12934
12935			for ( let ix = 0; ix < gridX1; ix ++ ) {
12936
12937				const x = ix * segment_width - width_half;
12938
12939				vertices.push( x, - y, 0 );
12940
12941				normals.push( 0, 0, 1 );
12942
12943				uvs.push( ix / gridX );
12944				uvs.push( 1 - ( iy / gridY ) );
12945
12946			}
12947
12948		}
12949
12950		for ( let iy = 0; iy < gridY; iy ++ ) {
12951
12952			for ( let ix = 0; ix < gridX; ix ++ ) {
12953
12954				const a = ix + gridX1 * iy;
12955				const b = ix + gridX1 * ( iy + 1 );
12956				const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
12957				const d = ( ix + 1 ) + gridX1 * iy;
12958
12959				indices.push( a, b, d );
12960				indices.push( b, c, d );
12961
12962			}
12963
12964		}
12965
12966		this.setIndex( indices );
12967		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
12968		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
12969		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
12970
12971	}
12972
12973	copy( source ) {
12974
12975		super.copy( source );
12976
12977		this.parameters = Object.assign( {}, source.parameters );
12978
12979		return this;
12980
12981	}
12982
12983	static fromJSON( data ) {
12984
12985		return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
12986
12987	}
12988
12989}
12990
12991var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif";
12992
12993var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
12994
12995var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;\n#endif";
12996
12997var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif";
12998
12999var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif";
13000
13001var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
13002
13003var begin_vertex = "vec3 transformed = vec3( position );";
13004
13005var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
13006
13007var bsdfs = "vec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n    float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n    float x2 = x * x;\n    float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n    return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );
13007\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( V * D );\n}\n#ifdef USE_IRIDESCENCE\n\tvec3 BRDF_GGX_Iridescence( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 f0, const in float f90, const in float iridescence, const in vec3 iridescenceFresnel, const in float roughness ) {\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = mix( F_Schlick( f0, f90, dotVH ), iridescenceFresnel, iridescence );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\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 >
13007 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif";
13008
13009var iridescence_fragment = "#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660,  0.0556434,\n\t\t-1.5371385,  1.8760108, -0.2040259,\n\t\t-0.4985314,  0.0415560,  1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\t return vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );
13009\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat R21 = R12;\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif";
13010
13011var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = dFdx( surf_pos.xyz );\n\t\tvec3 vSigmaY = dFdy( surf_pos.xyz );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif";
13012
13013var 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";
13014
13015var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
13016
13017var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
13018
13019var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
13020
13021var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif";
13022
13023var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif";
13024
13025var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
13026
13027var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
13028
13029var common = "#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nfloat w0( float a ) {\n\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n}\nfloat w1( float a ) {\n\treturn ( 1.0 / 6.0 ) * ( a *  a * ( 3.0 * a - 6.0 ) + 4.0 );\n}\nfloat w2( float a ){\n    return ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n}\nfloat w3( float a ) {\n\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n}\nfloat g0( float a ) {\n\treturn w0( a ) + w1( a );\n}\nfloat g1( float a ) {\n\treturn w2( a ) + w3( a );\n}\nfloat h0( float a ) {\n\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n}\nfloat h1( float a ) {\n    return 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n}\nvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, vec2 fullSize, float lod ) {\n\tuv = uv * texelSize.zw + 0.5;\n\tvec2 iuv = floor( uv );\n    vec2 fuv = fract( uv );\n    float g0x = g0( fuv.x );\n    float g1x = g1( fuv.x );\n    float h0x = h0( fuv.x );\n    float h1x = h1( fuv.x );\n    float h0y = h0( fuv.y );\n    float h1y = h1( fuv.y );\n    vec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n    vec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n    vec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n    vec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n    \n    vec2 lodFudge = pow( 1.95, lod ) / fullSize;\n\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t   g1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n}\nvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\tvec2 fullSize = vec2( textureSize( sampler, 0 ) );\n\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), fullSize, floor( lod ) );\n\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), fullSize, ceil( lod ) );\n\treturn mix( fSample, cSample, fract( lod ) );\n}";
13030
13031var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_v0 0.339\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_v1 0.276\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_v4 0.046\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_v5 0.016\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_v6 0.0038\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif";
13032
13033var 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";
13034
13035var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
13036
13037var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + dis
13037placementBias );\n#endif";
13038
13039var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
13040
13041var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
13042
13043var encodings_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
13044
13045var encodings_pars_fragment = "vec4 LinearToLinear( in vec4 value ) {\n\treturn value;\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}";
13046
13047var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif";
13048
13049var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\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";
13050
13051var envmap_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\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";
13052
13053var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\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";
13054
13055var 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}
13055 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";
13056
13057var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif";
13058
13059var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif";
13060
13061var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
13062
13063var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif";
13064
13065var 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 vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}";
13066
13067var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif";
13068
13069var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
13070
13071var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;";
13072
13073var lights_lambert_pars_fragment = "varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in GeometricContext geometry, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert";
13074
13075var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}
13075\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif";
13076
13077var envmap_physical_pars_fragment = "#if defined( USE_ENVMAP )\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#if defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n#endif";
13078
13079var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
13080
13081var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon";
13082
13083var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
13084
13085var lights_phong_pars_fragment = "varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot
13085( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong";
13086
13087var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULARINTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vUv ).a;\n\t\t#endif\n\t\t#ifdef USE_SPECULARCOLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vUv ).rgb;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;
13087\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vUv ).a;\n\t#endif\n#endif";
13088
13089var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n};\nvec3 clearcoatSpecular = vec3( 0.0 );\nvec3 sheenSpecular = vec3( 0.0 );\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGAp
13089prox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecular += ccIrradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.clearcoatNormal, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * BRDF_Sheen( directLight.direction, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX_Iridescence( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness );\n\t#else\n\t\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometry.viewDir, geometry.normal, material.specularColor, material.specularF90, material.roughness );\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecular += clearcoatRadiance * EnvironmentBRDF( geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;
13089\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometry.normal, geometry.viewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
13090
13091var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef USE_CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometry.viewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( 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\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometry, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_L
13091IGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry.normal );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
13092
13093var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometry.normal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getIBLRadiance( geometry.viewDir, geometry.normal, material.roughness );\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
13094
13095var 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";
13096
13097var 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";
13098
13099var 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";
13100
13101var 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";
13102
13103var 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";
13104
13105var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif";
13106
13107var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
13108
13109var 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\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif";
13110
13111var 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";
13112
13113var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
13114
13115var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
13116
13117var morphcolor_vertex = "#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif";
13118
13119var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif";
13120
13121var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif";
13122
13123var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif";
13124
13125var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;";
13126
13127var normal_fragment_maps = "#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );
13127\n\t#else\n\t\tnormal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
13128
13129var normal_pars_fragment = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif";
13130
13131var normal_pars_vertex = "#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif";
13132
13133var normal_vertex = "#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif";
13134
13135var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );\n\t\treturn normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );\n\t}\n#endif";
13136
13137var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif";
13138
13139var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, faceDirection );\n\t#endif\n#endif";
13140
13141var 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";
13142
13143var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif";
13144
13145var output_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha + 0.1;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );";
13146
13147var 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}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\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}";
13148
13149var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
13150
13151var 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;";
13152
13153var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
13154
13155var 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";
13156
13157var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, v
vendor: 14,091 bytes, lines 13157-13171
13157Uv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
13158
13159var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
13160
13161var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif";
13162
13163var shadowmap_pars_vertex = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
13164
13165var shadowmap_vertex = "#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif";
13166
13167var 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, vSpotLightCoord[ 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}";
13168
13169var 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";
13170
13171var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\t
13171uniform int boneTextureSize;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tfloat j = i * 4.0;\n\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\ty = dy * ( y + 0.5 );\n\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\treturn bone;\n\t}\n#endif";
13172
13173var 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";
13174
13175var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif";
13176
13177var 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";
13178
13179var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
13180
13181var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
13182
13183var tonemapping_pars_fragment = "#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3(  1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108,  1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605,  1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
13184
13185var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmission = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmission.rgb, material.transmission );\n#endif";
13186
13187var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn radiance;\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance * radiance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor * diffuseColor, transmittedLight.a );\n\t}\n#endif";
13188
13189var uv_pars_fragment = "#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif";
13190
13191var 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";
13192
13193var uv_vertex = "#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif";
13194
13195var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif";
13196
13197var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif";
13198
13199var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif";
13200
13201var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_L
13201IGHT_COORDS > 0\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";
13202
13203const vertex$h = "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}";
13204
13205const fragment$h = "uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
13206
13207const vertex$g = "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}";
13208
13209const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
13210
13211const vertex$f = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
13212
13213const fragment$f = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
13214
13215const vertex$e = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}";
13216
13217const fragment$e = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}";
13218
13219const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}";
13220
13221const fragment$d = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}";
13222
13223const vertex$c = "varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
13224
13225const fragment$c = "uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n}";
13226
13227const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
13228
13229const fragment$b = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
13230
13231const vertex$a = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}";
13232
13233const fragment$a = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13234
13235const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
13236
13237const fragment$9 = "#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_lambert_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_lambert_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13238
13239const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
13240
13241const fragment$8 = "#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;
13241\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13242
13243const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}";
13244
13245const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}";
13246
13247const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
13248
13249const fragment$6 = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13250
13251const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}";
13252
13253const fragment$5 = 
vendor: 3,950 bytes, line 13253
13253"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULARINTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n\t#ifdef USE_SPECULARCOLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEENCOLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEENROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <bsdfs>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include <transmission_fragment>\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecular;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;\n\t#endif\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}"
vendor: 13,906 bytes, lines 13253-13449
13253;
13254
13255const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
13256
13257const fragment$4 = "#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_toon_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13258
13259const vertex$3 = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <morphcolor_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}";
13260
13261const fragment$3 = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
13262
13263const vertex$2 = "#include <common>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
13264
13265const fragment$2 = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <logdepthbuf_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\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}";
13266
13267const vertex$1 = "uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
13268
13269const fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <output_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}";
13270
13271const ShaderChunk = {
13272	alphamap_fragment: alphamap_fragment,
13273	alphamap_pars_fragment: alphamap_pars_fragment,
13274	alphatest_fragment: alphatest_fragment,
13275	alphatest_pars_fragment: alphatest_pars_fragment,
13276	aomap_fragment: aomap_fragment,
13277	aomap_pars_fragment: aomap_pars_fragment,
13278	begin_vertex: begin_vertex,
13279	beginnormal_vertex: beginnormal_vertex,
13280	bsdfs: bsdfs,
13281	iridescence_fragment: iridescence_fragment,
13282	bumpmap_pars_fragment: bumpmap_pars_fragment,
13283	clipping_planes_fragment: clipping_planes_fragment,
13284	clipping_planes_pars_fragment: clipping_planes_pars_fragment,
13285	clipping_planes_pars_vertex: clipping_planes_pars_vertex,
13286	clipping_planes_vertex: clipping_planes_vertex,
13287	color_fragment: color_fragment,
13288	color_pars_fragment: color_pars_fragment,
13289	color_pars_vertex: color_pars_vertex,
13290	color_vertex: color_vertex,
13291	common: common,
13292	cube_uv_reflection_fragment: cube_uv_reflection_fragment,
13293	defaultnormal_vertex: defaultnormal_vertex,
13294	displacementmap_pars_vertex: displacementmap_pars_vertex,
13295	displacementmap_vertex: displacementmap_vertex,
13296	emissivemap_fragment: emissivemap_fragment,
13297	emissivemap_pars_fragment: emissivemap_pars_fragment,
13298	encodings_fragment: encodings_fragment,
13299	encodings_pars_fragment: encodings_pars_fragment,
13300	envmap_fragment: envmap_fragment,
13301	envmap_common_pars_fragment: envmap_common_pars_fragment,
13302	envmap_pars_fragment: envmap_pars_fragment,
13303	envmap_pars_vertex: envmap_pars_vertex,
13304	envmap_physical_pars_fragment: envmap_physical_pars_fragment,
13305	envmap_vertex: envmap_vertex,
13306	fog_vertex: fog_vertex,
13307	fog_pars_vertex: fog_pars_vertex,
13308	fog_fragment: fog_fragment,
13309	fog_pars_fragment: fog_pars_fragment,
13310	gradientmap_pars_fragment: gradientmap_pars_fragment,
13311	lightmap_fragment: lightmap_fragment,
13312	lightmap_pars_fragment: lightmap_pars_fragment,
13313	lights_lambert_fragment: lights_lambert_fragment,
13314	lights_lambert_pars_fragment: lights_lambert_pars_fragment,
13315	lights_pars_begin: lights_pars_begin,
13316	lights_toon_fragment: lights_toon_fragment,
13317	lights_toon_pars_fragment: lights_toon_pars_fragment,
13318	lights_phong_fragment: lights_phong_fragment,
13319	lights_phong_pars_fragment: lights_phong_pars_fragment,
13320	lights_physical_fragment: lights_physical_fragment,
13321	lights_physical_pars_fragment: lights_physical_pars_fragment,
13322	lights_fragment_begin: lights_fragment_begin,
13323	lights_fragment_maps: lights_fragment_maps,
13324	lights_fragment_end: lights_fragment_end,
13325	logdepthbuf_fragment: logdepthbuf_fragment,
13326	logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
13327	logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
13328	logdepthbuf_vertex: logdepthbuf_vertex,
13329	map_fragment: map_fragment,
13330	map_pars_fragment: map_pars_fragment,
13331	map_particle_fragment: map_particle_fragment,
13332	map_particle_pars_fragment: map_particle_pars_fragment,
13333	metalnessmap_fragment: metalnessmap_fragment,
13334	metalnessmap_pars_fragment: metalnessmap_pars_fragment,
13335	morphcolor_vertex: morphcolor_vertex,
13336	morphnormal_vertex: morphnormal_vertex,
13337	morphtarget_pars_vertex: morphtarget_pars_vertex,
13338	morphtarget_vertex: morphtarget_vertex,
13339	normal_fragment_begin: normal_fragment_begin,
13340	normal_fragment_maps: normal_fragment_maps,
13341	normal_pars_fragment: normal_pars_fragment,
13342	normal_pars_vertex: normal_pars_vertex,
13343	normal_vertex: normal_vertex,
13344	normalmap_pars_fragment: normalmap_pars_fragment,
13345	clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
13346	clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
13347	clearcoat_pars_fragment: clearcoat_pars_fragment,
13348	iridescence_pars_fragment: iridescence_pars_fragment,
13349	output_fragment: output_fragment,
13350	packing: packing,
13351	premultiplied_alpha_fragment: premultiplied_alpha_fragment,
13352	project_vertex: project_vertex,
13353	dithering_fragment: dithering_fragment,
13354	dithering_pars_fragment: dithering_pars_fragment,
13355	roughnessmap_fragment: roughnessmap_fragment,
13356	roughnessmap_pars_fragment: roughnessmap_pars_fragment,
13357	shadowmap_pars_fragment: shadowmap_pars_fragment,
13358	shadowmap_pars_vertex: shadowmap_pars_vertex,
13359	shadowmap_vertex: shadowmap_vertex,
13360	shadowmask_pars_fragment: shadowmask_pars_fragment,
13361	skinbase_vertex: skinbase_vertex,
13362	skinning_pars_vertex: skinning_pars_vertex,
13363	skinning_vertex: skinning_vertex,
13364	skinnormal_vertex: skinnormal_vertex,
13365	specularmap_fragment: specularmap_fragment,
13366	specularmap_pars_fragment: specularmap_pars_fragment,
13367	tonemapping_fragment: tonemapping_fragment,
13368	tonemapping_pars_fragment: tonemapping_pars_fragment,
13369	transmission_fragment: transmission_fragment,
13370	transmission_pars_fragment: transmission_pars_fragment,
13371	uv_pars_fragment: uv_pars_fragment,
13372	uv_pars_vertex: uv_pars_vertex,
13373	uv_vertex: uv_vertex,
13374	uv2_pars_fragment: uv2_pars_fragment,
13375	uv2_pars_vertex: uv2_pars_vertex,
13376	uv2_vertex: uv2_vertex,
13377	worldpos_vertex: worldpos_vertex,
13378
13379	background_vert: vertex$h,
13380	background_frag: fragment$h,
13381	backgroundCube_vert: vertex$g,
13382	backgroundCube_frag: fragment$g,
13383	cube_vert: vertex$f,
13384	cube_frag: fragment$f,
13385	depth_vert: vertex$e,
13386	depth_frag: fragment$e,
13387	distanceRGBA_vert: vertex$d,
13388	distanceRGBA_frag: fragment$d,
13389	equirect_vert: vertex$c,
13390	equirect_frag: fragment$c,
13391	linedashed_vert: vertex$b,
13392	linedashed_frag: fragment$b,
13393	meshbasic_vert: vertex$a,
13394	meshbasic_frag: fragment$a,
13395	meshlambert_vert: vertex$9,
13396	meshlambert_frag: fragment$9,
13397	meshmatcap_vert: vertex$8,
13398	meshmatcap_frag: fragment$8,
13399	meshnormal_vert: vertex$7,
13400	meshnormal_frag: fragment$7,
13401	meshphong_vert: vertex$6,
13402	meshphong_frag: fragment$6,
13403	meshphysical_vert: vertex$5,
13404	meshphysical_frag: fragment$5,
13405	meshtoon_vert: vertex$4,
13406	meshtoon_frag: fragment$4,
13407	points_vert: vertex$3,
13408	points_frag: fragment$3,
13409	shadow_vert: vertex$2,
13410	shadow_frag: fragment$2,
13411	sprite_vert: vertex$1,
13412	sprite_frag: fragment$1
13413};
13414
13415/**
13416 * Uniforms library for shared webgl shaders
13417 */
13418
13419const UniformsLib = {
13420
13421	common: {
13422
13423		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
13424		opacity: { value: 1.0 },
13425
13426		map: { value: null },
13427		uvTransform: { value: /*@__PURE__*/ new Matrix3() },
13428		uv2Transform: { value: /*@__PURE__*/ new Matrix3() },
13429
13430		alphaMap: { value: null },
13431		alphaTest: { value: 0 }
13432
13433	},
13434
13435	specularmap: {
13436
13437		specularMap: { value: null },
13438
13439	},
13440
13441	envmap: {
13442
13443		envMap: { value: null },
13444		flipEnvMap: { value: - 1 },
13445		reflectivity: { value: 1.0 }, // basic, lambert, phong
13446		ior: { value: 1.5 }, // physical
13447		refractionRatio: { value: 0.98 }, // basic, lambert, phong
13448
13449	},
vendor: 5,741 bytes, lines 13450-13755
13450
13451	aomap: {
13452
13453		aoMap: { value: null },
13454		aoMapIntensity: { value: 1 }
13455
13456	},
13457
13458	lightmap: {
13459
13460		lightMap: { value: null },
13461		lightMapIntensity: { value: 1 }
13462
13463	},
13464
13465	emissivemap: {
13466
13467		emissiveMap: { value: null }
13468
13469	},
13470
13471	bumpmap: {
13472
13473		bumpMap: { value: null },
13474		bumpScale: { value: 1 }
13475
13476	},
13477
13478	normalmap: {
13479
13480		normalMap: { value: null },
13481		normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }
13482
13483	},
13484
13485	displacementmap: {
13486
13487		displacementMap: { value: null },
13488		displacementScale: { value: 1 },
13489		displacementBias: { value: 0 }
13490
13491	},
13492
13493	roughnessmap: {
13494
13495		roughnessMap: { value: null }
13496
13497	},
13498
13499	metalnessmap: {
13500
13501		metalnessMap: { value: null }
13502
13503	},
13504
13505	gradientmap: {
13506
13507		gradientMap: { value: null }
13508
13509	},
13510
13511	fog: {
13512
13513		fogDensity: { value: 0.00025 },
13514		fogNear: { value: 1 },
13515		fogFar: { value: 2000 },
13516		fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) }
13517
13518	},
13519
13520	lights: {
13521
13522		ambientLightColor: { value: [] },
13523
13524		lightProbe: { value: [] },
13525
13526		directionalLights: { value: [], properties: {
13527			direction: {},
13528			color: {}
13529		} },
13530
13531		directionalLightShadows: { value: [], properties: {
13532			shadowBias: {},
13533			shadowNormalBias: {},
13534			shadowRadius: {},
13535			shadowMapSize: {}
13536		} },
13537
13538		directionalShadowMap: { value: [] },
13539		directionalShadowMatrix: { value: [] },
13540
13541		spotLights: { value: [], properties: {
13542			color: {},
13543			position: {},
13544			direction: {},
13545			distance: {},
13546			coneCos: {},
13547			penumbraCos: {},
13548			decay: {}
13549		} },
13550
13551		spotLightShadows: { value: [], properties: {
13552			shadowBias: {},
13553			shadowNormalBias: {},
13554			shadowRadius: {},
13555			shadowMapSize: {}
13556		} },
13557
13558		spotLightMap: { value: [] },
13559		spotShadowMap: { value: [] },
13560		spotLightMatrix: { value: [] },
13561
13562		pointLights: { value: [], properties: {
13563			color: {},
13564			position: {},
13565			decay: {},
13566			distance: {}
13567		} },
13568
13569		pointLightShadows: { value: [], properties: {
13570			shadowBias: {},
13571			shadowNormalBias: {},
13572			shadowRadius: {},
13573			shadowMapSize: {},
13574			shadowCameraNear: {},
13575			shadowCameraFar: {}
13576		} },
13577
13578		pointShadowMap: { value: [] },
13579		pointShadowMatrix: { value: [] },
13580
13581		hemisphereLights: { value: [], properties: {
13582			direction: {},
13583			skyColor: {},
13584			groundColor: {}
13585		} },
13586
13587		// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
13588		rectAreaLights: { value: [], properties: {
13589			color: {},
13590			position: {},
13591			width: {},
13592			height: {}
13593		} },
13594
13595		ltc_1: { value: null },
13596		ltc_2: { value: null }
13597
13598	},
13599
13600	points: {
13601
13602		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
13603		opacity: { value: 1.0 },
13604		size: { value: 1.0 },
13605		scale: { value: 1.0 },
13606		map: { value: null },
13607		alphaMap: { value: null },
13608		alphaTest: { value: 0 },
13609		uvTransform: { value: /*@__PURE__*/ new Matrix3() }
13610
13611	},
13612
13613	sprite: {
13614
13615		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
13616		opacity: { value: 1.0 },
13617		center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) },
13618		rotation: { value: 0.0 },
13619		map: { value: null },
13620		alphaMap: { value: null },
13621		alphaTest: { value: 0 },
13622		uvTransform: { value: /*@__PURE__*/ new Matrix3() }
13623
13624	}
13625
13626};
13627
13628const ShaderLib = {
13629
13630	basic: {
13631
13632		uniforms: /*@__PURE__*/ mergeUniforms( [
13633			UniformsLib.common,
13634			UniformsLib.specularmap,
13635			UniformsLib.envmap,
13636			UniformsLib.aomap,
13637			UniformsLib.lightmap,
13638			UniformsLib.fog
13639		] ),
13640
13641		vertexShader: ShaderChunk.meshbasic_vert,
13642		fragmentShader: ShaderChunk.meshbasic_frag
13643
13644	},
13645
13646	lambert: {
13647
13648		uniforms: /*@__PURE__*/ mergeUniforms( [
13649			UniformsLib.common,
13650			UniformsLib.specularmap,
13651			UniformsLib.envmap,
13652			UniformsLib.aomap,
13653			UniformsLib.lightmap,
13654			UniformsLib.emissivemap,
13655			UniformsLib.bumpmap,
13656			UniformsLib.normalmap,
13657			UniformsLib.displacementmap,
13658			UniformsLib.fog,
13659			UniformsLib.lights,
13660			{
13661				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }
13662			}
13663		] ),
13664
13665		vertexShader: ShaderChunk.meshlambert_vert,
13666		fragmentShader: ShaderChunk.meshlambert_frag
13667
13668	},
13669
13670	phong: {
13671
13672		uniforms: /*@__PURE__*/ mergeUniforms( [
13673			UniformsLib.common,
13674			UniformsLib.specularmap,
13675			UniformsLib.envmap,
13676			UniformsLib.aomap,
13677			UniformsLib.lightmap,
13678			UniformsLib.emissivemap,
13679			UniformsLib.bumpmap,
13680			UniformsLib.normalmap,
13681			UniformsLib.displacementmap,
13682			UniformsLib.fog,
13683			UniformsLib.lights,
13684			{
13685				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) },
13686				specular: { value: /*@__PURE__*/ new Color( 0x111111 ) },
13687				shininess: { value: 30 }
13688			}
13689		] ),
13690
13691		vertexShader: ShaderChunk.meshphong_vert,
13692		fragmentShader: ShaderChunk.meshphong_frag
13693
13694	},
13695
13696	standard: {
13697
13698		uniforms: /*@__PURE__*/ mergeUniforms( [
13699			UniformsLib.common,
13700			UniformsLib.envmap,
13701			UniformsLib.aomap,
13702			UniformsLib.lightmap,
13703			UniformsLib.emissivemap,
13704			UniformsLib.bumpmap,
13705			UniformsLib.normalmap,
13706			UniformsLib.displacementmap,
13707			UniformsLib.roughnessmap,
13708			UniformsLib.metalnessmap,
13709			UniformsLib.fog,
13710			UniformsLib.lights,
13711			{
13712				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) },
13713				roughness: { value: 1.0 },
13714				metalness: { value: 0.0 },
13715				envMapIntensity: { value: 1 } // temporary
13716			}
13717		] ),
13718
13719		vertexShader: ShaderChunk.meshphysical_vert,
13720		fragmentShader: ShaderChunk.meshphysical_frag
13721
13722	},
13723
13724	toon: {
13725
13726		uniforms: /*@__PURE__*/ mergeUniforms( [
13727			UniformsLib.common,
13728			UniformsLib.aomap,
13729			UniformsLib.lightmap,
13730			UniformsLib.emissivemap,
13731			UniformsLib.bumpmap,
13732			UniformsLib.normalmap,
13733			UniformsLib.displacementmap,
13734			UniformsLib.gradientmap,
13735			UniformsLib.fog,
13736			UniformsLib.lights,
13737			{
13738				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }
13739			}
13740		] ),
13741
13742		vertexShader: ShaderChunk.meshtoon_vert,
13743		fragmentShader: ShaderChunk.meshtoon_frag
13744
13745	},
13746
13747	matcap: {
13748
13749		uniforms: /*@__PURE__*/ mergeUniforms( [
13750			UniformsLib.common,
13751			UniformsLib.bumpmap,
13752			UniformsLib.normalmap,
13753			UniformsLib.displacementmap,
13754			UniformsLib.fog,
13755			{
vendor: 4,333 bytes, lines 13756-13964
13756				matcap: { value: null }
13757			}
13758		] ),
13759
13760		vertexShader: ShaderChunk.meshmatcap_vert,
13761		fragmentShader: ShaderChunk.meshmatcap_frag
13762
13763	},
13764
13765	points: {
13766
13767		uniforms: /*@__PURE__*/ mergeUniforms( [
13768			UniformsLib.points,
13769			UniformsLib.fog
13770		] ),
13771
13772		vertexShader: ShaderChunk.points_vert,
13773		fragmentShader: ShaderChunk.points_frag
13774
13775	},
13776
13777	dashed: {
13778
13779		uniforms: /*@__PURE__*/ mergeUniforms( [
13780			UniformsLib.common,
13781			UniformsLib.fog,
13782			{
13783				scale: { value: 1 },
13784				dashSize: { value: 1 },
13785				totalSize: { value: 2 }
13786			}
13787		] ),
13788
13789		vertexShader: ShaderChunk.linedashed_vert,
13790		fragmentShader: ShaderChunk.linedashed_frag
13791
13792	},
13793
13794	depth: {
13795
13796		uniforms: /*@__PURE__*/ mergeUniforms( [
13797			UniformsLib.common,
13798			UniformsLib.displacementmap
13799		] ),
13800
13801		vertexShader: ShaderChunk.depth_vert,
13802		fragmentShader: ShaderChunk.depth_frag
13803
13804	},
13805
13806	normal: {
13807
13808		uniforms: /*@__PURE__*/ mergeUniforms( [
13809			UniformsLib.common,
13810			UniformsLib.bumpmap,
13811			UniformsLib.normalmap,
13812			UniformsLib.displacementmap,
13813			{
13814				opacity: { value: 1.0 }
13815			}
13816		] ),
13817
13818		vertexShader: ShaderChunk.meshnormal_vert,
13819		fragmentShader: ShaderChunk.meshnormal_frag
13820
13821	},
13822
13823	sprite: {
13824
13825		uniforms: /*@__PURE__*/ mergeUniforms( [
13826			UniformsLib.sprite,
13827			UniformsLib.fog
13828		] ),
13829
13830		vertexShader: ShaderChunk.sprite_vert,
13831		fragmentShader: ShaderChunk.sprite_frag
13832
13833	},
13834
13835	background: {
13836
13837		uniforms: {
13838			uvTransform: { value: /*@__PURE__*/ new Matrix3() },
13839			t2D: { value: null },
13840			backgroundIntensity: { value: 1 }
13841		},
13842
13843		vertexShader: ShaderChunk.background_vert,
13844		fragmentShader: ShaderChunk.background_frag
13845
13846	},
13847
13848	backgroundCube: {
13849
13850		uniforms: {
13851			envMap: { value: null },
13852			flipEnvMap: { value: - 1 },
13853			backgroundBlurriness: { value: 0 },
13854			backgroundIntensity: { value: 1 }
13855		},
13856
13857		vertexShader: ShaderChunk.backgroundCube_vert,
13858		fragmentShader: ShaderChunk.backgroundCube_frag
13859
13860	},
13861
13862	cube: {
13863
13864		uniforms: {
13865			tCube: { value: null },
13866			tFlip: { value: - 1 },
13867			opacity: { value: 1.0 }
13868		},
13869
13870		vertexShader: ShaderChunk.cube_vert,
13871		fragmentShader: ShaderChunk.cube_frag
13872
13873	},
13874
13875	equirect: {
13876
13877		uniforms: {
13878			tEquirect: { value: null },
13879		},
13880
13881		vertexShader: ShaderChunk.equirect_vert,
13882		fragmentShader: ShaderChunk.equirect_frag
13883
13884	},
13885
13886	distanceRGBA: {
13887
13888		uniforms: /*@__PURE__*/ mergeUniforms( [
13889			UniformsLib.common,
13890			UniformsLib.displacementmap,
13891			{
13892				referencePosition: { value: /*@__PURE__*/ new Vector3() },
13893				nearDistance: { value: 1 },
13894				farDistance: { value: 1000 }
13895			}
13896		] ),
13897
13898		vertexShader: ShaderChunk.distanceRGBA_vert,
13899		fragmentShader: ShaderChunk.distanceRGBA_frag
13900
13901	},
13902
13903	shadow: {
13904
13905		uniforms: /*@__PURE__*/ mergeUniforms( [
13906			UniformsLib.lights,
13907			UniformsLib.fog,
13908			{
13909				color: { value: /*@__PURE__*/ new Color( 0x00000 ) },
13910				opacity: { value: 1.0 }
13911			},
13912		] ),
13913
13914		vertexShader: ShaderChunk.shadow_vert,
13915		fragmentShader: ShaderChunk.shadow_frag
13916
13917	}
13918
13919};
13920
13921ShaderLib.physical = {
13922
13923	uniforms: /*@__PURE__*/ mergeUniforms( [
13924		ShaderLib.standard.uniforms,
13925		{
13926			clearcoat: { value: 0 },
13927			clearcoatMap: { value: null },
13928			clearcoatRoughness: { value: 0 },
13929			clearcoatRoughnessMap: { value: null },
13930			clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) },
13931			clearcoatNormalMap: { value: null },
13932			iridescence: { value: 0 },
13933			iridescenceMap: { value: null },
13934			iridescenceIOR: { value: 1.3 },
13935			iridescenceThicknessMinimum: { value: 100 },
13936			iridescenceThicknessMaximum: { value: 400 },
13937			iridescenceThicknessMap: { value: null },
13938			sheen: { value: 0 },
13939			sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) },
13940			sheenColorMap: { value: null },
13941			sheenRoughness: { value: 1 },
13942			sheenRoughnessMap: { value: null },
13943			transmission: { value: 0 },
13944			transmissionMap: { value: null },
13945			transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() },
13946			transmissionSamplerMap: { value: null },
13947			thickness: { value: 0 },
13948			thicknessMap: { value: null },
13949			attenuationDistance: { value: 0 },
13950			attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) },
13951			specularIntensity: { value: 1 },
13952			specularIntensityMap: { value: null },
13953			specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) },
13954			specularColorMap: { value: null },
13955		}
13956	] ),
13957
13958	vertexShader: ShaderChunk.meshphysical_vert,
13959	fragmentShader: ShaderChunk.meshphysical_frag
13960
13961};
13962
13963const _rgb = { r: 0, b: 0, g: 0 };
13964
vendor: 18,567 bytes, lines 13965-14790
13965function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) {
13966
13967	const clearColor = new Color( 0x000000 );
13968	let clearAlpha = alpha === true ? 0 : 1;
13969
13970	let planeMesh;
13971	let boxMesh;
13972
13973	let currentBackground = null;
13974	let currentBackgroundVersion = 0;
13975	let currentTonemapping = null;
13976
13977	function render( renderList, scene ) {
13978
13979		let forceClear = false;
13980		let background = scene.isScene === true ? scene.background : null;
13981
13982		if ( background && background.isTexture ) {
13983
13984			const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background
13985			background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background );
13986
13987		}
13988
13989		// Ignore background in AR
13990		// TODO: Reconsider this.
13991
13992		const xr = renderer.xr;
13993		const session = xr.getSession && xr.getSession();
13994
13995		if ( session && session.environmentBlendMode === 'additive' ) {
13996
13997			background = null;
13998
13999		}
14000
14001		if ( background === null ) {
14002
14003			setClear( clearColor, clearAlpha );
14004
14005		} else if ( background && background.isColor ) {
14006
14007			setClear( background, 1 );
14008			forceClear = true;
14009
14010		}
14011
14012		if ( renderer.autoClear || forceClear ) {
14013
14014			renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
14015
14016		}
14017
14018		if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
14019
14020			if ( boxMesh === undefined ) {
14021
14022				boxMesh = new Mesh(
14023					new BoxGeometry( 1, 1, 1 ),
14024					new ShaderMaterial( {
14025						name: 'BackgroundCubeMaterial',
14026						uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ),
14027						vertexShader: ShaderLib.backgroundCube.vertexShader,
14028						fragmentShader: ShaderLib.backgroundCube.fragmentShader,
14029						side: BackSide,
14030						depthTest: false,
14031						depthWrite: false,
14032						fog: false
14033					} )
14034				);
14035
14036				boxMesh.geometry.deleteAttribute( 'normal' );
14037				boxMesh.geometry.deleteAttribute( 'uv' );
14038
14039				boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
14040
14041					this.matrixWorld.copyPosition( camera.matrixWorld );
14042
14043				};
14044
14045				// add "envMap" material property so the renderer can evaluate it like for built-in materials
14046				Object.defineProperty( boxMesh.material, 'envMap', {
14047
14048					get: function () {
14049
14050						return this.uniforms.envMap.value;
14051
14052					}
14053
14054				} );
14055
14056				objects.update( boxMesh );
14057
14058			}
14059
14060			boxMesh.material.uniforms.envMap.value = background;
14061			boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
14062			boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
14063			boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14064			boxMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true;
14065
14066			if ( currentBackground !== background ||
14067				currentBackgroundVersion !== background.version ||
14068				currentTonemapping !== renderer.toneMapping ) {
14069
14070				boxMesh.material.needsUpdate = true;
14071
14072				currentBackground = background;
14073				currentBackgroundVersion = background.version;
14074				currentTonemapping = renderer.toneMapping;
14075
14076			}
14077
14078			boxMesh.layers.enableAll();
14079
14080			// push to the pre-sorted opaque render list
14081			renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
14082
14083		} else if ( background && background.isTexture ) {
14084
14085			if ( planeMesh === undefined ) {
14086
14087				planeMesh = new Mesh(
14088					new PlaneGeometry( 2, 2 ),
14089					new ShaderMaterial( {
14090						name: 'BackgroundMaterial',
14091						uniforms: cloneUniforms( ShaderLib.background.uniforms ),
14092						vertexShader: ShaderLib.background.vertexShader,
14093						fragmentShader: ShaderLib.background.fragmentShader,
14094						side: FrontSide,
14095						depthTest: false,
14096						depthWrite: false,
14097						fog: false
14098					} )
14099				);
14100
14101				planeMesh.geometry.deleteAttribute( 'normal' );
14102
14103				// add "map" material property so the renderer can evaluate it like for built-in materials
14104				Object.defineProperty( planeMesh.material, 'map', {
14105
14106					get: function () {
14107
14108						return this.uniforms.t2D.value;
14109
14110					}
14111
14112				} );
14113
14114				objects.update( planeMesh );
14115
14116			}
14117
14118			planeMesh.material.uniforms.t2D.value = background;
14119			planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14120			planeMesh.material.toneMapped = ( background.encoding === sRGBEncoding ) ? false : true;
14121
14122			if ( background.matrixAutoUpdate === true ) {
14123
14124				background.updateMatrix();
14125
14126			}
14127
14128			planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
14129
14130			if ( currentBackground !== background ||
14131				currentBackgroundVersion !== background.version ||
14132				currentTonemapping !== renderer.toneMapping ) {
14133
14134				planeMesh.material.needsUpdate = true;
14135
14136				currentBackground = background;
14137				currentBackgroundVersion = background.version;
14138				currentTonemapping = renderer.toneMapping;
14139
14140			}
14141
14142			planeMesh.layers.enableAll();
14143
14144			// push to the pre-sorted opaque render list
14145			renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
14146
14147		}
14148
14149	}
14150
14151	function setClear( color, alpha ) {
14152
14153		color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) );
14154
14155		state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha );
14156
14157	}
14158
14159	return {
14160
14161		getClearColor: function () {
14162
14163			return clearColor;
14164
14165		},
14166		setClearColor: function ( color, alpha = 1 ) {
14167
14168			clearColor.set( color );
14169			clearAlpha = alpha;
14170			setClear( clearColor, clearAlpha );
14171
14172		},
14173		getClearAlpha: function () {
14174
14175			return clearAlpha;
14176
14177		},
14178		setClearAlpha: function ( alpha ) {
14179
14180			clearAlpha = alpha;
14181			setClear( clearColor, clearAlpha );
14182
14183		},
14184		render: render
14185
14186	};
14187
14188}
14189
14190function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
14191
14192	const maxVertexAttributes = gl.getParameter( 34921 );
14193
14194	const extension = capabilities.isWebGL2 ? null : extensions.get( 'OES_vertex_array_object' );
14195	const vaoAvailable = capabilities.isWebGL2 || extension !== null;
14196
14197	const bindingStates = {};
14198
14199	const defaultState = createBindingState( null );
14200	let currentState = defaultState;
14201	let forceUpdate = false;
14202
14203	function setup( object, material, program, geometry, index ) {
14204
14205		let updateBuffers = false;
14206
14207		if ( vaoAvailable ) {
14208
14209			const state = getBindingState( geometry, program, material );
14210
14211			if ( currentState !== state ) {
14212
14213				currentState = state;
14214				bindVertexArrayObject( currentState.object );
14215
14216			}
14217
14218			updateBuffers = needsUpdate( object, geometry, program, index );
14219
14220			if ( updateBuffers ) saveCache( object, geometry, program, index );
14221
14222		} else {
14223
14224			const wireframe = ( material.wireframe === true );
14225
14226			if ( currentState.geometry !== geometry.id ||
14227				currentState.program !== program.id ||
14228				currentState.wireframe !== wireframe ) {
14229
14230				currentState.geometry = geometry.id;
14231				currentState.program = program.id;
14232				currentState.wireframe = wireframe;
14233
14234				updateBuffers = true;
14235
14236			}
14237
14238		}
14239
14240		if ( index !== null ) {
14241
14242			attributes.update( index, 34963 );
14243
14244		}
14245
14246		if ( updateBuffers || forceUpdate ) {
14247
14248			forceUpdate = false;
14249
14250			setupVertexAttributes( object, material, program, geometry );
14251
14252			if ( index !== null ) {
14253
14254				gl.bindBuffer( 34963, attributes.get( index ).buffer );
14255
14256			}
14257
14258		}
14259
14260	}
14261
14262	function createVertexArrayObject() {
14263
14264		if ( capabilities.isWebGL2 ) return gl.createVertexArray();
14265
14266		return extension.createVertexArrayOES();
14267
14268	}
14269
14270	function bindVertexArrayObject( vao ) {
14271
14272		if ( capabilities.isWebGL2 ) return gl.bindVertexArray( vao );
14273
14274		return extension.bindVertexArrayOES( vao );
14275
14276	}
14277
14278	function deleteVertexArrayObject( vao ) {
14279
14280		if ( capabilities.isWebGL2 ) return gl.deleteVertexArray( vao );
14281
14282		return extension.deleteVertexArrayOES( vao );
14283
14284	}
14285
14286	function getBindingState( geometry, program, material ) {
14287
14288		const wireframe = ( material.wireframe === true );
14289
14290		let programMap = bindingStates[ geometry.id ];
14291
14292		if ( programMap === undefined ) {
14293
14294			programMap = {};
14295			bindingStates[ geometry.id ] = programMap;
14296
14297		}
14298
14299		let stateMap = programMap[ program.id ];
14300
14301		if ( stateMap === undefined ) {
14302
14303			stateMap = {};
14304			programMap[ program.id ] = stateMap;
14305
14306		}
14307
14308		let state = stateMap[ wireframe ];
14309
14310		if ( state === undefined ) {
14311
14312			state = createBindingState( createVertexArrayObject() );
14313			stateMap[ wireframe ] = state;
14314
14315		}
14316
14317		return state;
14318
14319	}
14320
14321	function createBindingState( vao ) {
14322
14323		const newAttributes = [];
14324		const enabledAttributes = [];
14325		const attributeDivisors = [];
14326
14327		for ( let i = 0; i < maxVertexAttributes; i ++ ) {
14328
14329			newAttributes[ i ] = 0;
14330			enabledAttributes[ i ] = 0;
14331			attributeDivisors[ i ] = 0;
14332
14333		}
14334
14335		return {
14336
14337			// for backward compatibility on non-VAO support browser
14338			geometry: null,
14339			program: null,
14340			wireframe: false,
14341
14342			newAttributes: newAttributes,
14343			enabledAttributes: enabledAttributes,
14344			attributeDivisors: attributeDivisors,
14345			object: vao,
14346			attributes: {},
14347			index: null
14348
14349		};
14350
14351	}
14352
14353	function needsUpdate( object, geometry, program, index ) {
14354
14355		const cachedAttributes = currentState.attributes;
14356		const geometryAttributes = geometry.attributes;
14357
14358		let attributesNum = 0;
14359
14360		const programAttributes = program.getAttributes();
14361
14362		for ( const name in programAttributes ) {
14363
14364			const programAttribute = programAttributes[ name ];
14365
14366			if ( programAttribute.location >= 0 ) {
14367
14368				const cachedAttribute = cachedAttributes[ name ];
14369				let geometryAttribute = geometryAttributes[ name ];
14370
14371				if ( geometryAttribute === undefined ) {
14372
14373					if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
14374					if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
14375
14376				}
14377
14378				if ( cachedAttribute === undefined ) return true;
14379
14380				if ( cachedAttribute.attribute !== geometryAttribute ) return true;
14381
14382				if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true;
14383
14384				attributesNum ++;
14385
14386			}
14387
14388		}
14389
14390		if ( currentState.attributesNum !== attributesNum ) return true;
14391
14392		if ( currentState.index !== index ) return true;
14393
14394		return false;
14395
14396	}
14397
14398	function saveCache( object, geometry, program, index ) {
14399
14400		const cache = {};
14401		const attributes = geometry.attributes;
14402		let attributesNum = 0;
14403
14404		const programAttributes = program.getAttributes();
14405
14406		for ( const name in programAttributes ) {
14407
14408			const programAttribute = programAttributes[ name ];
14409
14410			if ( programAttribute.location >= 0 ) {
14411
14412				let attribute = attributes[ name ];
14413
14414				if ( attribute === undefined ) {
14415
14416					if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix;
14417					if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor;
14418
14419				}
14420
14421				const data = {};
14422				data.attribute = attribute;
14423
14424				if ( attribute && attribute.data ) {
14425
14426					data.data = attribute.data;
14427
14428				}
14429
14430				cache[ name ] = data;
14431
14432				attributesNum ++;
14433
14434			}
14435
14436		}
14437
14438		currentState.attributes = cache;
14439		currentState.attributesNum = attributesNum;
14440
14441		currentState.index = index;
14442
14443	}
14444
14445	function initAttributes() {
14446
14447		const newAttributes = currentState.newAttributes;
14448
14449		for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
14450
14451			newAttributes[ i ] = 0;
14452
14453		}
14454
14455	}
14456
14457	function enableAttribute( attribute ) {
14458
14459		enableAttributeAndDivisor( attribute, 0 );
14460
14461	}
14462
14463	function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
14464
14465		const newAttributes = currentState.newAttributes;
14466		const enabledAttributes = currentState.enabledAttributes;
14467		const attributeDivisors = currentState.attributeDivisors;
14468
14469		newAttributes[ attribute ] = 1;
14470
14471		if ( enabledAttributes[ attribute ] === 0 ) {
14472
14473			gl.enableVertexAttribArray( attribute );
14474			enabledAttributes[ attribute ] = 1;
14475
14476		}
14477
14478		if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
14479
14480			const extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
14481
14482			extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
14483			attributeDivisors[ attribute ] = meshPerAttribute;
14484
14485		}
14486
14487	}
14488
14489	function disableUnusedAttributes() {
14490
14491		const newAttributes = currentState.newAttributes;
14492		const enabledAttributes = currentState.enabledAttributes;
14493
14494		for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
14495
14496			if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
14497
14498				gl.disableVertexAttribArray( i );
14499				enabledAttributes[ i ] = 0;
14500
14501			}
14502
14503		}
14504
14505	}
14506
14507	function vertexAttribPointer( index, size, type, normalized, stride, offset ) {
14508
14509		if ( capabilities.isWebGL2 === true && ( type === 5124 || type === 5125 ) ) {
14510
14511			gl.vertexAttribIPointer( index, size, type, stride, offset );
14512
14513		} else {
14514
14515			gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
14516
14517		}
14518
14519	}
14520
14521	function setupVertexAttributes( object, material, program, geometry ) {
14522
14523		if ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
14524
14525			if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;
14526
14527		}
14528
14529		initAttributes();
14530
14531		const geometryAttributes = geometry.attributes;
14532
14533		const programAttributes = program.getAttributes();
14534
14535		const materialDefaultAttributeValues = material.defaultAttributeValues;
14536
14537		for ( const name in programAttributes ) {
14538
14539			const programAttribute = programAttributes[ name ];
14540
14541			if ( programAttribute.location >= 0 ) {
14542
14543				let geometryAttribute = geometryAttributes[ name ];
14544
14545				if ( geometryAttribute === undefined ) {
14546
14547					if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
14548					if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
14549
14550				}
14551
14552				if ( geometryAttribute !== undefined ) {
14553
14554					const normalized = geometryAttribute.normalized;
14555					const size = geometryAttribute.itemSize;
14556
14557					const attribute = attributes.get( geometryAttribute );
14558
14559					// TODO Attribute may not be available on context restore
14560
14561					if ( attribute === undefined ) continue;
14562
14563					const buffer = attribute.buffer;
14564					const type = attribute.type;
14565					const bytesPerElement = attribute.bytesPerElement;
14566
14567					if ( geometryAttribute.isInterleavedBufferAttribute ) {
14568
14569						const data = geometryAttribute.data;
14570						const stride = data.stride;
14571						const offset = geometryAttribute.offset;
14572
14573						if ( data.isInstancedInterleavedBuffer ) {
14574
14575							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
14576
14577								enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute );
14578
14579							}
14580
14581							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
14582
14583								geometry._maxInstanceCount = data.meshPerAttribute * data.count;
14584
14585							}
14586
14587						} else {
14588
14589							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
14590
14591								enableAttribute( programAttribute.location + i );
14592
14593							}
14594
14595						}
14596
14597						gl.bindBuffer( 34962, buffer );
14598
14599						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
14600
14601							vertexAttribPointer(
14602								programAttribute.location + i,
14603								size / programAttribute.locationSize,
14604								type,
14605								normalized,
14606								stride * bytesPerElement,
14607								( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement
14608							);
14609
14610						}
14611
14612					} else {
14613
14614						if ( geometryAttribute.isInstancedBufferAttribute ) {
14615
14616							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
14617
14618								enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute );
14619
14620							}
14621
14622							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
14623
14624								geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
14625
14626							}
14627
14628						} else {
14629
14630							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
14631
14632								enableAttribute( programAttribute.location + i );
14633
14634							}
14635
14636						}
14637
14638						gl.bindBuffer( 34962, buffer );
14639
14640						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
14641
14642							vertexAttribPointer(
14643								programAttribute.location + i,
14644								size / programAttribute.locationSize,
14645								type,
14646								normalized,
14647								size * bytesPerElement,
14648								( size / programAttribute.locationSize ) * i * bytesPerElement
14649							);
14650
14651						}
14652
14653					}
14654
14655				} else if ( materialDefaultAttributeValues !== undefined ) {
14656
14657					const value = materialDefaultAttributeValues[ name ];
14658
14659					if ( value !== undefined ) {
14660
14661						switch ( value.length ) {
14662
14663							case 2:
14664								gl.vertexAttrib2fv( programAttribute.location, value );
14665								break;
14666
14667							case 3:
14668								gl.vertexAttrib3fv( programAttribute.location, value );
14669								break;
14670
14671							case 4:
14672								gl.vertexAttrib4fv( programAttribute.location, value );
14673								break;
14674
14675							default:
14676								gl.vertexAttrib1fv( programAttribute.location, value );
14677
14678						}
14679
14680					}
14681
14682				}
14683
14684			}
14685
14686		}
14687
14688		disableUnusedAttributes();
14689
14690	}
14691
14692	function dispose() {
14693
14694		reset();
14695
14696		for ( const geometryId in bindingStates ) {
14697
14698			const programMap = bindingStates[ geometryId ];
14699
14700			for ( const programId in programMap ) {
14701
14702				const stateMap = programMap[ programId ];
14703
14704				for ( const wireframe in stateMap ) {
14705
14706					deleteVertexArrayObject( stateMap[ wireframe ].object );
14707
14708					delete stateMap[ wireframe ];
14709
14710				}
14711
14712				delete programMap[ programId ];
14713
14714			}
14715
14716			delete bindingStates[ geometryId ];
14717
14718		}
14719
14720	}
14721
14722	function releaseStatesOfGeometry( geometry ) {
14723
14724		if ( bindingStates[ geometry.id ] === undefined ) return;
14725
14726		const programMap = bindingStates[ geometry.id ];
14727
14728		for ( const programId in programMap ) {
14729
14730			const stateMap = programMap[ programId ];
14731
14732			for ( const wireframe in stateMap ) {
14733
14734				deleteVertexArrayObject( stateMap[ wireframe ].object );
14735
14736				delete stateMap[ wireframe ];
14737
14738			}
14739
14740			delete programMap[ programId ];
14741
14742		}
14743
14744		delete bindingStates[ geometry.id ];
14745
14746	}
14747
14748	function releaseStatesOfProgram( program ) {
14749
14750		for ( const geometryId in bindingStates ) {
14751
14752			const programMap = bindingStates[ geometryId ];
14753
14754			if ( programMap[ program.id ] === undefined ) continue;
14755
14756			const stateMap = programMap[ program.id ];
14757
14758			for ( const wireframe in stateMap ) {
14759
14760				deleteVertexArrayObject( stateMap[ wireframe ].object );
14761
14762				delete stateMap[ wireframe ];
14763
14764			}
14765
14766			delete programMap[ program.id ];
14767
14768		}
14769
14770	}
14771
14772	function reset() {
14773
14774		resetDefaultState();
14775		forceUpdate = true;
14776
14777		if ( currentState === defaultState ) return;
14778
14779		currentState = defaultState;
14780		bindVertexArrayObject( currentState.object );
14781
14782	}
14783
14784	// for backward-compatibility
14785
14786	function resetDefaultState() {
14787
14788		defaultState.geometry = null;
14789		defaultState.program = null;
14790		defaultState.wireframe = false;
vendor: 3,700 bytes, lines 14791-14963
14791
14792	}
14793
14794	return {
14795
14796		setup: setup,
14797		reset: reset,
14798		resetDefaultState: resetDefaultState,
14799		dispose: dispose,
14800		releaseStatesOfGeometry: releaseStatesOfGeometry,
14801		releaseStatesOfProgram: releaseStatesOfProgram,
14802
14803		initAttributes: initAttributes,
14804		enableAttribute: enableAttribute,
14805		disableUnusedAttributes: disableUnusedAttributes
14806
14807	};
14808
14809}
14810
14811function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
14812
14813	const isWebGL2 = capabilities.isWebGL2;
14814
14815	let mode;
14816
14817	function setMode( value ) {
14818
14819		mode = value;
14820
14821	}
14822
14823	function render( start, count ) {
14824
14825		gl.drawArrays( mode, start, count );
14826
14827		info.update( count, mode, 1 );
14828
14829	}
14830
14831	function renderInstances( start, count, primcount ) {
14832
14833		if ( primcount === 0 ) return;
14834
14835		let extension, methodName;
14836
14837		if ( isWebGL2 ) {
14838
14839			extension = gl;
14840			methodName = 'drawArraysInstanced';
14841
14842		} else {
14843
14844			extension = extensions.get( 'ANGLE_instanced_arrays' );
14845			methodName = 'drawArraysInstancedANGLE';
14846
14847			if ( extension === null ) {
14848
14849				console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
14850				return;
14851
14852			}
14853
14854		}
14855
14856		extension[ methodName ]( mode, start, count, primcount );
14857
14858		info.update( count, mode, primcount );
14859
14860	}
14861
14862	//
14863
14864	this.setMode = setMode;
14865	this.render = render;
14866	this.renderInstances = renderInstances;
14867
14868}
14869
14870function WebGLCapabilities( gl, extensions, parameters ) {
14871
14872	let maxAnisotropy;
14873
14874	function getMaxAnisotropy() {
14875
14876		if ( maxAnisotropy !== undefined ) return maxAnisotropy;
14877
14878		if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
14879
14880			const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
14881
14882			maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
14883
14884		} else {
14885
14886			maxAnisotropy = 0;
14887
14888		}
14889
14890		return maxAnisotropy;
14891
14892	}
14893
14894	function getMaxPrecision( precision ) {
14895
14896		if ( precision === 'highp' ) {
14897
14898			if ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&
14899				gl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {
14900
14901				return 'highp';
14902
14903			}
14904
14905			precision = 'mediump';
14906
14907		}
14908
14909		if ( precision === 'mediump' ) {
14910
14911			if ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&
14912				gl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {
14913
14914				return 'mediump';
14915
14916			}
14917
14918		}
14919
14920		return 'lowp';
14921
14922	}
14923
14924	const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext;
14925
14926	let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
14927	const maxPrecision = getMaxPrecision( precision );
14928
14929	if ( maxPrecision !== precision ) {
14930
14931		console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
14932		precision = maxPrecision;
14933
14934	}
14935
14936	const drawBuffers = isWebGL2 || extensions.has( 'WEBGL_draw_buffers' );
14937
14938	const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
14939
14940	const maxTextures = gl.getParameter( 34930 );
14941	const maxVertexTextures = gl.getParameter( 35660 );
14942	const maxTextureSize = gl.getParameter( 3379 );
14943	const maxCubemapSize = gl.getParameter( 34076 );
14944
14945	const maxAttributes = gl.getParameter( 34921 );
14946	const maxVertexUniforms = gl.getParameter( 36347 );
14947	const maxVaryings = gl.getParameter( 36348 );
14948	const maxFragmentUniforms = gl.getParameter( 36349 );
14949
14950	const vertexTextures = maxVertexTextures > 0;
14951	const floatFragmentTextures = isWebGL2 || extensions.has( 'OES_texture_float' );
14952	const floatVertexTextures = vertexTextures && floatFragmentTextures;
14953
14954	const maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;
14955
14956	return {
14957
14958		isWebGL2: isWebGL2,
14959
14960		drawBuffers: drawBuffers,
14961
14962		getMaxAnisotropy: getMaxAnisotropy,
14963		getMaxPrecision: getMaxPrecision,
vendor: 1,709 bytes, lines 14964-15046
14964
14965		precision: precision,
14966		logarithmicDepthBuffer: logarithmicDepthBuffer,
14967
14968		maxTextures: maxTextures,
14969		maxVertexTextures: maxVertexTextures,
14970		maxTextureSize: maxTextureSize,
14971		maxCubemapSize: maxCubemapSize,
14972
14973		maxAttributes: maxAttributes,
14974		maxVertexUniforms: maxVertexUniforms,
14975		maxVaryings: maxVaryings,
14976		maxFragmentUniforms: maxFragmentUniforms,
14977
14978		vertexTextures: vertexTextures,
14979		floatFragmentTextures: floatFragmentTextures,
14980		floatVertexTextures: floatVertexTextures,
14981
14982		maxSamples: maxSamples
14983
14984	};
14985
14986}
14987
14988function WebGLClipping( properties ) {
14989
14990	const scope = this;
14991
14992	let globalState = null,
14993		numGlobalPlanes = 0,
14994		localClippingEnabled = false,
14995		renderingShadows = false;
14996
14997	const plane = new Plane(),
14998		viewNormalMatrix = new Matrix3(),
14999
15000		uniform = { value: null, needsUpdate: false };
15001
15002	this.uniform = uniform;
15003	this.numPlanes = 0;
15004	this.numIntersection = 0;
15005
15006	this.init = function ( planes, enableLocalClipping ) {
15007
15008		const enabled =
15009			planes.length !== 0 ||
15010			enableLocalClipping ||
15011			// enable state of previous frame - the clipping code has to
15012			// run another frame in order to reset the state:
15013			numGlobalPlanes !== 0 ||
15014			localClippingEnabled;
15015
15016		localClippingEnabled = enableLocalClipping;
15017
15018		numGlobalPlanes = planes.length;
15019
15020		return enabled;
15021
15022	};
15023
15024	this.beginShadows = function () {
15025
15026		renderingShadows = true;
15027		projectPlanes( null );
15028
15029	};
15030
15031	this.endShadows = function () {
15032
15033		renderingShadows = false;
15034
15035	};
15036
15037	this.setGlobalState = function ( planes, camera ) {
15038
15039		globalState = projectPlanes( planes, camera, 0 );
15040
15041	};
15042
15043	this.setState = function ( material, camera, useCache ) {
15044
15045		const planes = material.clippingPlanes,
15046			clipIntersection = material.clipIntersection,
vendor: 22,947 bytes, lines 15047-16018
15047			clipShadows = material.clipShadows;
15048
15049		const materialProperties = properties.get( material );
15050
15051		if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
15052
15053			// there's no local clipping
15054
15055			if ( renderingShadows ) {
15056
15057				// there's no global clipping
15058
15059				projectPlanes( null );
15060
15061			} else {
15062
15063				resetGlobalState();
15064
15065			}
15066
15067		} else {
15068
15069			const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
15070				lGlobal = nGlobal * 4;
15071
15072			let dstArray = materialProperties.clippingState || null;
15073
15074			uniform.value = dstArray; // ensure unique state
15075
15076			dstArray = projectPlanes( planes, camera, lGlobal, useCache );
15077
15078			for ( let i = 0; i !== lGlobal; ++ i ) {
15079
15080				dstArray[ i ] = globalState[ i ];
15081
15082			}
15083
15084			materialProperties.clippingState = dstArray;
15085			this.numIntersection = clipIntersection ? this.numPlanes : 0;
15086			this.numPlanes += nGlobal;
15087
15088		}
15089
15090
15091	};
15092
15093	function resetGlobalState() {
15094
15095		if ( uniform.value !== globalState ) {
15096
15097			uniform.value = globalState;
15098			uniform.needsUpdate = numGlobalPlanes > 0;
15099
15100		}
15101
15102		scope.numPlanes = numGlobalPlanes;
15103		scope.numIntersection = 0;
15104
15105	}
15106
15107	function projectPlanes( planes, camera, dstOffset, skipTransform ) {
15108
15109		const nPlanes = planes !== null ? planes.length : 0;
15110		let dstArray = null;
15111
15112		if ( nPlanes !== 0 ) {
15113
15114			dstArray = uniform.value;
15115
15116			if ( skipTransform !== true || dstArray === null ) {
15117
15118				const flatSize = dstOffset + nPlanes * 4,
15119					viewMatrix = camera.matrixWorldInverse;
15120
15121				viewNormalMatrix.getNormalMatrix( viewMatrix );
15122
15123				if ( dstArray === null || dstArray.length < flatSize ) {
15124
15125					dstArray = new Float32Array( flatSize );
15126
15127				}
15128
15129				for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
15130
15131					plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
15132
15133					plane.normal.toArray( dstArray, i4 );
15134					dstArray[ i4 + 3 ] = plane.constant;
15135
15136				}
15137
15138			}
15139
15140			uniform.value = dstArray;
15141			uniform.needsUpdate = true;
15142
15143		}
15144
15145		scope.numPlanes = nPlanes;
15146		scope.numIntersection = 0;
15147
15148		return dstArray;
15149
15150	}
15151
15152}
15153
15154function WebGLCubeMaps( renderer ) {
15155
15156	let cubemaps = new WeakMap();
15157
15158	function mapTextureMapping( texture, mapping ) {
15159
15160		if ( mapping === EquirectangularReflectionMapping ) {
15161
15162			texture.mapping = CubeReflectionMapping;
15163
15164		} else if ( mapping === EquirectangularRefractionMapping ) {
15165
15166			texture.mapping = CubeRefractionMapping;
15167
15168		}
15169
15170		return texture;
15171
15172	}
15173
15174	function get( texture ) {
15175
15176		if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) {
15177
15178			const mapping = texture.mapping;
15179
15180			if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
15181
15182				if ( cubemaps.has( texture ) ) {
15183
15184					const cubemap = cubemaps.get( texture ).texture;
15185					return mapTextureMapping( cubemap, texture.mapping );
15186
15187				} else {
15188
15189					const image = texture.image;
15190
15191					if ( image && image.height > 0 ) {
15192
15193						const renderTarget = new WebGLCubeRenderTarget( image.height / 2 );
15194						renderTarget.fromEquirectangularTexture( renderer, texture );
15195						cubemaps.set( texture, renderTarget );
15196
15197						texture.addEventListener( 'dispose', onTextureDispose );
15198
15199						return mapTextureMapping( renderTarget.texture, texture.mapping );
15200
15201					} else {
15202
15203						// image not yet ready. try the conversion next frame
15204
15205						return null;
15206
15207					}
15208
15209				}
15210
15211			}
15212
15213		}
15214
15215		return texture;
15216
15217	}
15218
15219	function onTextureDispose( event ) {
15220
15221		const texture = event.target;
15222
15223		texture.removeEventListener( 'dispose', onTextureDispose );
15224
15225		const cubemap = cubemaps.get( texture );
15226
15227		if ( cubemap !== undefined ) {
15228
15229			cubemaps.delete( texture );
15230			cubemap.dispose();
15231
15232		}
15233
15234	}
15235
15236	function dispose() {
15237
15238		cubemaps = new WeakMap();
15239
15240	}
15241
15242	return {
15243		get: get,
15244		dispose: dispose
15245	};
15246
15247}
15248
15249class OrthographicCamera extends Camera {
15250
15251	constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
15252
15253		super();
15254
15255		this.isOrthographicCamera = true;
15256
15257		this.type = 'OrthographicCamera';
15258
15259		this.zoom = 1;
15260		this.view = null;
15261
15262		this.left = left;
15263		this.right = right;
15264		this.top = top;
15265		this.bottom = bottom;
15266
15267		this.near = near;
15268		this.far = far;
15269
15270		this.updateProjectionMatrix();
15271
15272	}
15273
15274	copy( source, recursive ) {
15275
15276		super.copy( source, recursive );
15277
15278		this.left = source.left;
15279		this.right = source.right;
15280		this.top = source.top;
15281		this.bottom = source.bottom;
15282		this.near = source.near;
15283		this.far = source.far;
15284
15285		this.zoom = source.zoom;
15286		this.view = source.view === null ? null : Object.assign( {}, source.view );
15287
15288		return this;
15289
15290	}
15291
15292	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
15293
15294		if ( this.view === null ) {
15295
15296			this.view = {
15297				enabled: true,
15298				fullWidth: 1,
15299				fullHeight: 1,
15300				offsetX: 0,
15301				offsetY: 0,
15302				width: 1,
15303				height: 1
15304			};
15305
15306		}
15307
15308		this.view.enabled = true;
15309		this.view.fullWidth = fullWidth;
15310		this.view.fullHeight = fullHeight;
15311		this.view.offsetX = x;
15312		this.view.offsetY = y;
15313		this.view.width = width;
15314		this.view.height = height;
15315
15316		this.updateProjectionMatrix();
15317
15318	}
15319
15320	clearViewOffset() {
15321
15322		if ( this.view !== null ) {
15323
15324			this.view.enabled = false;
15325
15326		}
15327
15328		this.updateProjectionMatrix();
15329
15330	}
15331
15332	updateProjectionMatrix() {
15333
15334		const dx = ( this.right - this.left ) / ( 2 * this.zoom );
15335		const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
15336		const cx = ( this.right + this.left ) / 2;
15337		const cy = ( this.top + this.bottom ) / 2;
15338
15339		let left = cx - dx;
15340		let right = cx + dx;
15341		let top = cy + dy;
15342		let bottom = cy - dy;
15343
15344		if ( this.view !== null && this.view.enabled ) {
15345
15346			const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
15347			const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
15348
15349			left += scaleW * this.view.offsetX;
15350			right = left + scaleW * this.view.width;
15351			top -= scaleH * this.view.offsetY;
15352			bottom = top - scaleH * this.view.height;
15353
15354		}
15355
15356		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );
15357
15358		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
15359
15360	}
15361
15362	toJSON( meta ) {
15363
15364		const data = super.toJSON( meta );
15365
15366		data.object.zoom = this.zoom;
15367		data.object.left = this.left;
15368		data.object.right = this.right;
15369		data.object.top = this.top;
15370		data.object.bottom = this.bottom;
15371		data.object.near = this.near;
15372		data.object.far = this.far;
15373
15374		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
15375
15376		return data;
15377
15378	}
15379
15380}
15381
15382const LOD_MIN = 4;
15383
15384// The standard deviations (radians) associated with the extra mips. These are
15385// chosen to approximate a Trowbridge-Reitz distribution function times the
15386// geometric shadowing function. These sigma values squared must match the
15387// variance #defines in cube_uv_reflection_fragment.glsl.js.
15388const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
15389
15390// The maximum length of the blur for loop. Smaller sigmas will use fewer
15391// samples and exit early, but not recompile the shader.
15392const MAX_SAMPLES = 20;
15393
15394const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
15395const _clearColor = /*@__PURE__*/ new Color();
15396let _oldTarget = null;
15397
15398// Golden Ratio
15399const PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
15400const INV_PHI = 1 / PHI;
15401
15402// Vertices of a dodecahedron (except the opposites, which represent the
15403// same axis), used as axis directions evenly spread on a sphere.
15404const _axisDirections = [
15405	/*@__PURE__*/ new Vector3( 1, 1, 1 ),
15406	/*@__PURE__*/ new Vector3( - 1, 1, 1 ),
15407	/*@__PURE__*/ new Vector3( 1, 1, - 1 ),
15408	/*@__PURE__*/ new Vector3( - 1, 1, - 1 ),
15409	/*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ),
15410	/*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ),
15411	/*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ),
15412	/*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ),
15413	/*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ),
15414	/*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ];
15415
15416/**
15417 * This class generates a Prefiltered, Mipmapped Radiance Environment Map
15418 * (PMREM) from a cubeMap environment texture. This allows different levels of
15419 * blur to be quickly accessed based on material roughness. It is packed into a
15420 * special CubeUV format that allows us to perform custom interpolation so that
15421 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
15422 * chain, it only goes down to the LOD_MIN level (above), and then creates extra
15423 * even more filtered 'mips' at the same LOD_MIN resolution, associated with
15424 * higher roughness levels. In this way we maintain resolution to smoothly
15425 * interpolate diffuse lighting while limiting sampling computation.
15426 *
15427 * Paper: Fast, Accurate Image-Based Lighting
15428 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view
15429*/
15430
15431class PMREMGenerator {
15432
15433	constructor( renderer ) {
15434
15435		this._renderer = renderer;
15436		this._pingPongRenderTarget = null;
15437
15438		this._lodMax = 0;
15439		this._cubeSize = 0;
15440		this._lodPlanes = [];
15441		this._sizeLods = [];
15442		this._sigmas = [];
15443
15444		this._blurMaterial = null;
15445		this._cubemapMaterial = null;
15446		this._equirectMaterial = null;
15447
15448		this._compileMaterial( this._blurMaterial );
15449
15450	}
15451
15452	/**
15453	 * Generates a PMREM from a supplied Scene, which can be faster than using an
15454	 * image if networking bandwidth is low. Optional sigma specifies a blur radius
15455	 * in radians to be applied to the scene before PMREM generation. Optional near
15456	 * and far planes ensure the scene is rendered in its entirety (the cubeCamera
15457	 * is placed at the origin).
15458	 */
15459	fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
15460
15461		_oldTarget = this._renderer.getRenderTarget();
15462
15463		this._setSize( 256 );
15464
15465		const cubeUVRenderTarget = this._allocateTargets();
15466		cubeUVRenderTarget.depthBuffer = true;
15467
15468		this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
15469
15470		if ( sigma > 0 ) {
15471
15472			this._blur( cubeUVRenderTarget, 0, 0, sigma );
15473
15474		}
15475
15476		this._applyPMREM( cubeUVRenderTarget );
15477		this._cleanup( cubeUVRenderTarget );
15478
15479		return cubeUVRenderTarget;
15480
15481	}
15482
15483	/**
15484	 * Generates a PMREM from an equirectangular texture, which can be either LDR
15485	 * or HDR. The ideal input image size is 1k (1024 x 512),
15486	 * as this matches best with the 256 x 256 cubemap output.
15487	 */
15488	fromEquirectangular( equirectangular, renderTarget = null ) {
15489
15490		return this._fromTexture( equirectangular, renderTarget );
15491
15492	}
15493
15494	/**
15495	 * Generates a PMREM from an cubemap texture, which can be either LDR
15496	 * or HDR. The ideal input cube size is 256 x 256,
15497	 * as this matches best with the 256 x 256 cubemap output.
15498	 */
15499	fromCubemap( cubemap, renderTarget = null ) {
15500
15501		return this._fromTexture( cubemap, renderTarget );
15502
15503	}
15504
15505	/**
15506	 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
15507	 * your texture's network fetch for increased concurrency.
15508	 */
15509	compileCubemapShader() {
15510
15511		if ( this._cubemapMaterial === null ) {
15512
15513			this._cubemapMaterial = _getCubemapMaterial();
15514			this._compileMaterial( this._cubemapMaterial );
15515
15516		}
15517
15518	}
15519
15520	/**
15521	 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
15522	 * your texture's network fetch for increased concurrency.
15523	 */
15524	compileEquirectangularShader() {
15525
15526		if ( this._equirectMaterial === null ) {
15527
15528			this._equirectMaterial = _getEquirectMaterial();
15529			this._compileMaterial( this._equirectMaterial );
15530
15531		}
15532
15533	}
15534
15535	/**
15536	 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
15537	 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
15538	 * one of them will cause any others to also become unusable.
15539	 */
15540	dispose() {
15541
15542		this._dispose();
15543
15544		if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose();
15545		if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose();
15546
15547	}
15548
15549	// private interface
15550
15551	_setSize( cubeSize ) {
15552
15553		this._lodMax = Math.floor( Math.log2( cubeSize ) );
15554		this._cubeSize = Math.pow( 2, this._lodMax );
15555
15556	}
15557
15558	_dispose() {
15559
15560		if ( this._blurMaterial !== null ) this._blurMaterial.dispose();
15561
15562		if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose();
15563
15564		for ( let i = 0; i < this._lodPlanes.length; i ++ ) {
15565
15566			this._lodPlanes[ i ].dispose();
15567
15568		}
15569
15570	}
15571
15572	_cleanup( outputTarget ) {
15573
15574		this._renderer.setRenderTarget( _oldTarget );
15575		outputTarget.scissorTest = false;
15576		_setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
15577
15578	}
15579
15580	_fromTexture( texture, renderTarget ) {
15581
15582		if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
15583
15584			this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
15585
15586		} else { // Equirectangular
15587
15588			this._setSize( texture.image.width / 4 );
15589
15590		}
15591
15592		_oldTarget = this._renderer.getRenderTarget();
15593
15594		const cubeUVRenderTarget = renderTarget || this._allocateTargets();
15595		this._textureToCubeUV( texture, cubeUVRenderTarget );
15596		this._applyPMREM( cubeUVRenderTarget );
15597		this._cleanup( cubeUVRenderTarget );
15598
15599		return cubeUVRenderTarget;
15600
15601	}
15602
15603	_allocateTargets() {
15604
15605		const width = 3 * Math.max( this._cubeSize, 16 * 7 );
15606		const height = 4 * this._cubeSize;
15607
15608		const params = {
15609			magFilter: LinearFilter,
15610			minFilter: LinearFilter,
15611			generateMipmaps: false,
15612			type: HalfFloatType,
15613			format: RGBAFormat,
15614			encoding: LinearEncoding,
15615			depthBuffer: false
15616		};
15617
15618		const cubeUVRenderTarget = _createRenderTarget( width, height, params );
15619
15620		if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) {
15621
15622			if ( this._pingPongRenderTarget !== null ) {
15623
15624				this._dispose();
15625
15626			}
15627
15628			this._pingPongRenderTarget = _createRenderTarget( width, height, params );
15629
15630			const { _lodMax } = this;
15631			( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) );
15632
15633			this._blurMaterial = _getBlurShader( _lodMax, width, height );
15634
15635		}
15636
15637		return cubeUVRenderTarget;
15638
15639	}
15640
15641	_compileMaterial( material ) {
15642
15643		const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material );
15644		this._renderer.compile( tmpMesh, _flatCamera );
15645
15646	}
15647
15648	_sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
15649
15650		const fov = 90;
15651		const aspect = 1;
15652		const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
15653		const upSign = [ 1, - 1, 1, 1, 1, 1 ];
15654		const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
15655		const renderer = this._renderer;
15656
15657		const originalAutoClear = renderer.autoClear;
15658		const toneMapping = renderer.toneMapping;
15659		renderer.getClearColor( _clearColor );
15660
15661		renderer.toneMapping = NoToneMapping;
15662		renderer.autoClear = false;
15663
15664		const backgroundMaterial = new MeshBasicMaterial( {
15665			name: 'PMREM.Background',
15666			side: BackSide,
15667			depthWrite: false,
15668			depthTest: false,
15669		} );
15670
15671		const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial );
15672
15673		let useSolidColor = false;
15674		const background = scene.background;
15675
15676		if ( background ) {
15677
15678			if ( background.isColor ) {
15679
15680				backgroundMaterial.color.copy( background );
15681				scene.background = null;
15682				useSolidColor = true;
15683
15684			}
15685
15686		} else {
15687
15688			backgroundMaterial.color.copy( _clearColor );
15689			useSolidColor = true;
15690
15691		}
15692
15693		for ( let i = 0; i < 6; i ++ ) {
15694
15695			const col = i % 3;
15696
15697			if ( col === 0 ) {
15698
15699				cubeCamera.up.set( 0, upSign[ i ], 0 );
15700				cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
15701
15702			} else if ( col === 1 ) {
15703
15704				cubeCamera.up.set( 0, 0, upSign[ i ] );
15705				cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
15706
15707			} else {
15708
15709				cubeCamera.up.set( 0, upSign[ i ], 0 );
15710				cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
15711
15712			}
15713
15714			const size = this._cubeSize;
15715
15716			_setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size );
15717
15718			renderer.setRenderTarget( cubeUVRenderTarget );
15719
15720			if ( useSolidColor ) {
15721
15722				renderer.render( backgroundBox, cubeCamera );
15723
15724			}
15725
15726			renderer.render( scene, cubeCamera );
15727
15728		}
15729
15730		backgroundBox.geometry.dispose();
15731		backgroundBox.material.dispose();
15732
15733		renderer.toneMapping = toneMapping;
15734		renderer.autoClear = originalAutoClear;
15735		scene.background = background;
15736
15737	}
15738
15739	_textureToCubeUV( texture, cubeUVRenderTarget ) {
15740
15741		const renderer = this._renderer;
15742
15743		const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping );
15744
15745		if ( isCubeTexture ) {
15746
15747			if ( this._cubemapMaterial === null ) {
15748
15749				this._cubemapMaterial = _getCubemapMaterial();
15750
15751			}
15752
15753			this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1;
15754
15755		} else {
15756
15757			if ( this._equirectMaterial === null ) {
15758
15759				this._equirectMaterial = _getEquirectMaterial();
15760
15761			}
15762
15763		}
15764
15765		const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
15766		const mesh = new Mesh( this._lodPlanes[ 0 ], material );
15767
15768		const uniforms = material.uniforms;
15769
15770		uniforms[ 'envMap' ].value = texture;
15771
15772		const size = this._cubeSize;
15773
15774		_setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size );
15775
15776		renderer.setRenderTarget( cubeUVRenderTarget );
15777		renderer.render( mesh, _flatCamera );
15778
15779	}
15780
15781	_applyPMREM( cubeUVRenderTarget ) {
15782
15783		const renderer = this._renderer;
15784		const autoClear = renderer.autoClear;
15785		renderer.autoClear = false;
15786
15787		for ( let i = 1; i < this._lodPlanes.length; i ++ ) {
15788
15789			const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] );
15790
15791			const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ];
15792
15793			this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
15794
15795		}
15796
15797		renderer.autoClear = autoClear;
15798
15799	}
15800
15801	/**
15802	 * This is a two-pass Gaussian blur for a cubemap. Normally this is done
15803	 * vertically and horizontally, but this breaks down on a cube. Here we apply
15804	 * the blur latitudinally (around the poles), and then longitudinally (towards
15805	 * the poles) to approximate the orthogonally-separable blur. It is least
15806	 * accurate at the poles, but still does a decent job.
15807	 */
15808	_blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
15809
15810		const pingPongRenderTarget = this._pingPongRenderTarget;
15811
15812		this._halfBlur(
15813			cubeUVRenderTarget,
15814			pingPongRenderTarget,
15815			lodIn,
15816			lodOut,
15817			sigma,
15818			'latitudinal',
15819			poleAxis );
15820
15821		this._halfBlur(
15822			pingPongRenderTarget,
15823			cubeUVRenderTarget,
15824			lodOut,
15825			lodOut,
15826			sigma,
15827			'longitudinal',
15828			poleAxis );
15829
15830	}
15831
15832	_halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
15833
15834		const renderer = this._renderer;
15835		const blurMaterial = this._blurMaterial;
15836
15837		if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
15838
15839			console.error(
15840				'blur direction must be either latitudinal or longitudinal!' );
15841
15842		}
15843
15844		// Number of standard deviations at which to cut off the discrete approximation.
15845		const STANDARD_DEVIATIONS = 3;
15846
15847		const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial );
15848		const blurUniforms = blurMaterial.uniforms;
15849
15850		const pixels = this._sizeLods[ lodIn ] - 1;
15851		const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
15852		const sigmaPixels = sigmaRadians / radiansPerPixel;
15853		const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
15854
15855		if ( samples > MAX_SAMPLES ) {
15856
15857			console.warn( `sigmaRadians, ${
15858				sigmaRadians}, is too large and will clip, as it requested ${
15859				samples} samples when the maximum is set to ${MAX_SAMPLES}` );
15860
15861		}
15862
15863		const weights = [];
15864		let sum = 0;
15865
15866		for ( let i = 0; i < MAX_SAMPLES; ++ i ) {
15867
15868			const x = i / sigmaPixels;
15869			const weight = Math.exp( - x * x / 2 );
15870			weights.push( weight );
15871
15872			if ( i === 0 ) {
15873
15874				sum += weight;
15875
15876			} else if ( i < samples ) {
15877
15878				sum += 2 * weight;
15879
15880			}
15881
15882		}
15883
15884		for ( let i = 0; i < weights.length; i ++ ) {
15885
15886			weights[ i ] = weights[ i ] / sum;
15887
15888		}
15889
15890		blurUniforms[ 'envMap' ].value = targetIn.texture;
15891		blurUniforms[ 'samples' ].value = samples;
15892		blurUniforms[ 'weights' ].value = weights;
15893		blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
15894
15895		if ( poleAxis ) {
15896
15897			blurUniforms[ 'poleAxis' ].value = poleAxis;
15898
15899		}
15900
15901		const { _lodMax } = this;
15902		blurUniforms[ 'dTheta' ].value = radiansPerPixel;
15903		blurUniforms[ 'mipInt' ].value = _lodMax - lodIn;
15904
15905		const outputSize = this._sizeLods[ lodOut ];
15906		const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 );
15907		const y = 4 * ( this._cubeSize - outputSize );
15908
15909		_setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
15910		renderer.setRenderTarget( targetOut );
15911		renderer.render( blurMesh, _flatCamera );
15912
15913	}
15914
15915}
15916
15917
15918
15919function _createPlanes( lodMax ) {
15920
15921	const lodPlanes = [];
15922	const sizeLods = [];
15923	const sigmas = [];
15924
15925	let lod = lodMax;
15926
15927	const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
15928
15929	for ( let i = 0; i < totalLods; i ++ ) {
15930
15931		const sizeLod = Math.pow( 2, lod );
15932		sizeLods.push( sizeLod );
15933		let sigma = 1.0 / sizeLod;
15934
15935		if ( i > lodMax - LOD_MIN ) {
15936
15937			sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ];
15938
15939		} else if ( i === 0 ) {
15940
15941			sigma = 0;
15942
15943		}
15944
15945		sigmas.push( sigma );
15946
15947		const texelSize = 1.0 / ( sizeLod - 2 );
15948		const min = - texelSize;
15949		const max = 1 + texelSize;
15950		const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
15951
15952		const cubeFaces = 6;
15953		const vertices = 6;
15954		const positionSize = 3;
15955		const uvSize = 2;
15956		const faceIndexSize = 1;
15957
15958		const position = new Float32Array( positionSize * vertices * cubeFaces );
15959		const uv = new Float32Array( uvSize * vertices * cubeFaces );
15960		const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
15961
15962		for ( let face = 0; face < cubeFaces; face ++ ) {
15963
15964			const x = ( face % 3 ) * 2 / 3 - 1;
15965			const y = face > 2 ? 0 : - 1;
15966			const coordinates = [
15967				x, y, 0,
15968				x + 2 / 3, y, 0,
15969				x + 2 / 3, y + 1, 0,
15970				x, y, 0,
15971				x + 2 / 3, y + 1, 0,
15972				x, y + 1, 0
15973			];
15974			position.set( coordinates, positionSize * vertices * face );
15975			uv.set( uv1, uvSize * vertices * face );
15976			const fill = [ face, face, face, face, face, face ];
15977			faceIndex.set( fill, faceIndexSize * vertices * face );
15978
15979		}
15980
15981		const planes = new BufferGeometry();
15982		planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
15983		planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
15984		planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
15985		lodPlanes.push( planes );
15986
15987		if ( lod > LOD_MIN ) {
15988
15989			lod --;
15990
15991		}
15992
15993	}
15994
15995	return { lodPlanes, sizeLods, sigmas };
15996
15997}
15998
15999function _createRenderTarget( width, height, params ) {
16000
16001	const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params );
16002	cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
16003	cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
16004	cubeUVRenderTarget.scissorTest = true;
16005	return cubeUVRenderTarget;
16006
16007}
16008
16009function _setViewport( target, x, y, width, height ) {
16010
16011	target.viewport.set( x, y, width, height );
16012	target.scissor.set( x, y, width, height );
16013
16014}
16015
16016function _getBlurShader( lodMax, width, height ) {
16017
16018	const weights = new Float32Array( MAX_SAMPLES );
vendor: 4,417 bytes, lines 16019-16257
16019	const poleAxis = new Vector3( 0, 1, 0 );
16020	const shaderMaterial = new ShaderMaterial( {
16021
16022		name: 'SphericalGaussianBlur',
16023
16024		defines: {
16025			'n': MAX_SAMPLES,
16026			'CUBEUV_TEXEL_WIDTH': 1.0 / width,
16027			'CUBEUV_TEXEL_HEIGHT': 1.0 / height,
16028			'CUBEUV_MAX_MIP': `${lodMax}.0`,
16029		},
16030
16031		uniforms: {
16032			'envMap': { value: null },
16033			'samples': { value: 1 },
16034			'weights': { value: weights },
16035			'latitudinal': { value: false },
16036			'dTheta': { value: 0 },
16037			'mipInt': { value: 0 },
16038			'poleAxis': { value: poleAxis }
16039		},
16040
16041		vertexShader: _getCommonVertexShader(),
16042
16043		fragmentShader: /* glsl */`
16044
16045			precision mediump float;
16046			precision mediump int;
16047
16048			varying vec3 vOutputDirection;
16049
16050			uniform sampler2D envMap;
16051			uniform int samples;
16052			uniform float weights[ n ];
16053			uniform bool latitudinal;
16054			uniform float dTheta;
16055			uniform float mipInt;
16056			uniform vec3 poleAxis;
16057
16058			#define ENVMAP_TYPE_CUBE_UV
16059			#include <cube_uv_reflection_fragment>
16060
16061			vec3 getSample( float theta, vec3 axis ) {
16062
16063				float cosTheta = cos( theta );
16064				// Rodrigues' axis-angle rotation
16065				vec3 sampleDirection = vOutputDirection * cosTheta
16066					+ cross( axis, vOutputDirection ) * sin( theta )
16067					+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
16068
16069				return bilinearCubeUV( envMap, sampleDirection, mipInt );
16070
16071			}
16072
16073			void main() {
16074
16075				vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
16076
16077				if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
16078
16079					axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
16080
16081				}
16082
16083				axis = normalize( axis );
16084
16085				gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
16086				gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
16087
16088				for ( int i = 1; i < n; i++ ) {
16089
16090					if ( i >= samples ) {
16091
16092						break;
16093
16094					}
16095
16096					float theta = dTheta * float( i );
16097					gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
16098					gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
16099
16100				}
16101
16102			}
16103		`,
16104
16105		blending: NoBlending,
16106		depthTest: false,
16107		depthWrite: false
16108
16109	} );
16110
16111	return shaderMaterial;
16112
16113}
16114
16115function _getEquirectMaterial() {
16116
16117	return new ShaderMaterial( {
16118
16119		name: 'EquirectangularToCubeUV',
16120
16121		uniforms: {
16122			'envMap': { value: null }
16123		},
16124
16125		vertexShader: _getCommonVertexShader(),
16126
16127		fragmentShader: /* glsl */`
16128
16129			precision mediump float;
16130			precision mediump int;
16131
16132			varying vec3 vOutputDirection;
16133
16134			uniform sampler2D envMap;
16135
16136			#include <common>
16137
16138			void main() {
16139
16140				vec3 outputDirection = normalize( vOutputDirection );
16141				vec2 uv = equirectUv( outputDirection );
16142
16143				gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );
16144
16145			}
16146		`,
16147
16148		blending: NoBlending,
16149		depthTest: false,
16150		depthWrite: false
16151
16152	} );
16153
16154}
16155
16156function _getCubemapMaterial() {
16157
16158	return new ShaderMaterial( {
16159
16160		name: 'CubemapToCubeUV',
16161
16162		uniforms: {
16163			'envMap': { value: null },
16164			'flipEnvMap': { value: - 1 }
16165		},
16166
16167		vertexShader: _getCommonVertexShader(),
16168
16169		fragmentShader: /* glsl */`
16170
16171			precision mediump float;
16172			precision mediump int;
16173
16174			uniform float flipEnvMap;
16175
16176			varying vec3 vOutputDirection;
16177
16178			uniform samplerCube envMap;
16179
16180			void main() {
16181
16182				gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
16183
16184			}
16185		`,
16186
16187		blending: NoBlending,
16188		depthTest: false,
16189		depthWrite: false
16190
16191	} );
16192
16193}
16194
16195function _getCommonVertexShader() {
16196
16197	return /* glsl */`
16198
16199		precision mediump float;
16200		precision mediump int;
16201
16202		attribute float faceIndex;
16203
16204		varying vec3 vOutputDirection;
16205
16206		// RH coordinate system; PMREM face-indexing convention
16207		vec3 getDirection( vec2 uv, float face ) {
16208
16209			uv = 2.0 * uv - 1.0;
16210
16211			vec3 direction = vec3( uv, 1.0 );
16212
16213			if ( face == 0.0 ) {
16214
16215				direction = direction.zyx; // ( 1, v, u ) pos x
16216
16217			} else if ( face == 1.0 ) {
16218
16219				direction = direction.xzy;
16220				direction.xz *= -1.0; // ( -u, 1, -v ) pos y
16221
16222			} else if ( face == 2.0 ) {
16223
16224				direction.x *= -1.0; // ( -u, v, 1 ) pos z
16225
16226			} else if ( face == 3.0 ) {
16227
16228				direction = direction.zyx;
16229				direction.xz *= -1.0; // ( -1, v, -u ) neg x
16230
16231			} else if ( face == 4.0 ) {
16232
16233				direction = direction.xzy;
16234				direction.xy *= -1.0; // ( -u, -1, v ) neg y
16235
16236			} else if ( face == 5.0 ) {
16237
16238				direction.z *= -1.0; // ( u, v, -1 ) neg z
16239
16240			}
16241
16242			return direction;
16243
16244		}
16245
16246		void main() {
16247
16248			vOutputDirection = getDirection( uv, faceIndex );
16249			gl_Position = vec4( position, 1.0 );
16250
16251		}
16252	`;
16253
16254}
16255
16256function WebGLCubeUVMaps( renderer ) {
16257
vendor: 4,214 bytes, lines 16258-16447
16258	let cubeUVmaps = new WeakMap();
16259
16260	let pmremGenerator = null;
16261
16262	function get( texture ) {
16263
16264		if ( texture && texture.isTexture ) {
16265
16266			const mapping = texture.mapping;
16267
16268			const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
16269			const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
16270
16271			// equirect/cube map to cubeUV conversion
16272
16273			if ( isEquirectMap || isCubeMap ) {
16274
16275				if ( texture.isRenderTargetTexture && texture.needsPMREMUpdate === true ) {
16276
16277					texture.needsPMREMUpdate = false;
16278
16279					let renderTarget = cubeUVmaps.get( texture );
16280
16281					if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
16282
16283					renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget );
16284					cubeUVmaps.set( texture, renderTarget );
16285
16286					return renderTarget.texture;
16287
16288				} else {
16289
16290					if ( cubeUVmaps.has( texture ) ) {
16291
16292						return cubeUVmaps.get( texture ).texture;
16293
16294					} else {
16295
16296						const image = texture.image;
16297
16298						if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) {
16299
16300							if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
16301
16302							const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture );
16303							cubeUVmaps.set( texture, renderTarget );
16304
16305							texture.addEventListener( 'dispose', onTextureDispose );
16306
16307							return renderTarget.texture;
16308
16309						} else {
16310
16311							// image not yet ready. try the conversion next frame
16312
16313							return null;
16314
16315						}
16316
16317					}
16318
16319				}
16320
16321			}
16322
16323		}
16324
16325		return texture;
16326
16327	}
16328
16329	function isCubeTextureComplete( image ) {
16330
16331		let count = 0;
16332		const length = 6;
16333
16334		for ( let i = 0; i < length; i ++ ) {
16335
16336			if ( image[ i ] !== undefined ) count ++;
16337
16338		}
16339
16340		return count === length;
16341
16342
16343	}
16344
16345	function onTextureDispose( event ) {
16346
16347		const texture = event.target;
16348
16349		texture.removeEventListener( 'dispose', onTextureDispose );
16350
16351		const cubemapUV = cubeUVmaps.get( texture );
16352
16353		if ( cubemapUV !== undefined ) {
16354
16355			cubeUVmaps.delete( texture );
16356			cubemapUV.dispose();
16357
16358		}
16359
16360	}
16361
16362	function dispose() {
16363
16364		cubeUVmaps = new WeakMap();
16365
16366		if ( pmremGenerator !== null ) {
16367
16368			pmremGenerator.dispose();
16369			pmremGenerator = null;
16370
16371		}
16372
16373	}
16374
16375	return {
16376		get: get,
16377		dispose: dispose
16378	};
16379
16380}
16381
16382function WebGLExtensions( gl ) {
16383
16384	const extensions = {};
16385
16386	function getExtension( name ) {
16387
16388		if ( extensions[ name ] !== undefined ) {
16389
16390			return extensions[ name ];
16391
16392		}
16393
16394		let extension;
16395
16396		switch ( name ) {
16397
16398			case 'WEBGL_depth_texture':
16399				extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
16400				break;
16401
16402			case 'EXT_texture_filter_anisotropic':
16403				extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
16404				break;
16405
16406			case 'WEBGL_compressed_texture_s3tc':
16407				extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
16408				break;
16409
16410			case 'WEBGL_compressed_texture_pvrtc':
16411				extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
16412				break;
16413
16414			default:
16415				extension = gl.getExtension( name );
16416
16417		}
16418
16419		extensions[ name ] = extension;
16420
16421		return extension;
16422
16423	}
16424
16425	return {
16426
16427		has: function ( name ) {
16428
16429			return getExtension( name ) !== null;
16430
16431		},
16432
16433		init: function ( capabilities ) {
16434
16435			if ( capabilities.isWebGL2 ) {
16436
16437				getExtension( 'EXT_color_buffer_float' );
16438
16439			} else {
16440
16441				getExtension( 'WEBGL_depth_texture' );
16442				getExtension( 'OES_texture_float' );
16443				getExtension( 'OES_texture_half_float' );
16444				getExtension( 'OES_texture_half_float_linear' );
16445				getExtension( 'OES_standard_derivatives' );
16446				getExtension( 'OES_element_index_uint' );
16447				getExtension( 'OES_vertex_array_object' );
vendor: 4,537 bytes, lines 16448-16707
16448				getExtension( 'ANGLE_instanced_arrays' );
16449
16450			}
16451
16452			getExtension( 'OES_texture_float_linear' );
16453			getExtension( 'EXT_color_buffer_half_float' );
16454			getExtension( 'WEBGL_multisampled_render_to_texture' );
16455
16456		},
16457
16458		get: function ( name ) {
16459
16460			const extension = getExtension( name );
16461
16462			if ( extension === null ) {
16463
16464				console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
16465
16466			}
16467
16468			return extension;
16469
16470		}
16471
16472	};
16473
16474}
16475
16476function WebGLGeometries( gl, attributes, info, bindingStates ) {
16477
16478	const geometries = {};
16479	const wireframeAttributes = new WeakMap();
16480
16481	function onGeometryDispose( event ) {
16482
16483		const geometry = event.target;
16484
16485		if ( geometry.index !== null ) {
16486
16487			attributes.remove( geometry.index );
16488
16489		}
16490
16491		for ( const name in geometry.attributes ) {
16492
16493			attributes.remove( geometry.attributes[ name ] );
16494
16495		}
16496
16497		geometry.removeEventListener( 'dispose', onGeometryDispose );
16498
16499		delete geometries[ geometry.id ];
16500
16501		const attribute = wireframeAttributes.get( geometry );
16502
16503		if ( attribute ) {
16504
16505			attributes.remove( attribute );
16506			wireframeAttributes.delete( geometry );
16507
16508		}
16509
16510		bindingStates.releaseStatesOfGeometry( geometry );
16511
16512		if ( geometry.isInstancedBufferGeometry === true ) {
16513
16514			delete geometry._maxInstanceCount;
16515
16516		}
16517
16518		//
16519
16520		info.memory.geometries --;
16521
16522	}
16523
16524	function get( object, geometry ) {
16525
16526		if ( geometries[ geometry.id ] === true ) return geometry;
16527
16528		geometry.addEventListener( 'dispose', onGeometryDispose );
16529
16530		geometries[ geometry.id ] = true;
16531
16532		info.memory.geometries ++;
16533
16534		return geometry;
16535
16536	}
16537
16538	function update( geometry ) {
16539
16540		const geometryAttributes = geometry.attributes;
16541
16542		// Updating index buffer in VAO now. See WebGLBindingStates.
16543
16544		for ( const name in geometryAttributes ) {
16545
16546			attributes.update( geometryAttributes[ name ], 34962 );
16547
16548		}
16549
16550		// morph targets
16551
16552		const morphAttributes = geometry.morphAttributes;
16553
16554		for ( const name in morphAttributes ) {
16555
16556			const array = morphAttributes[ name ];
16557
16558			for ( let i = 0, l = array.length; i < l; i ++ ) {
16559
16560				attributes.update( array[ i ], 34962 );
16561
16562			}
16563
16564		}
16565
16566	}
16567
16568	function updateWireframeAttribute( geometry ) {
16569
16570		const indices = [];
16571
16572		const geometryIndex = geometry.index;
16573		const geometryPosition = geometry.attributes.position;
16574		let version = 0;
16575
16576		if ( geometryIndex !== null ) {
16577
16578			const array = geometryIndex.array;
16579			version = geometryIndex.version;
16580
16581			for ( let i = 0, l = array.length; i < l; i += 3 ) {
16582
16583				const a = array[ i + 0 ];
16584				const b = array[ i + 1 ];
16585				const c = array[ i + 2 ];
16586
16587				indices.push( a, b, b, c, c, a );
16588
16589			}
16590
16591		} else {
16592
16593			const array = geometryPosition.array;
16594			version = geometryPosition.version;
16595
16596			for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
16597
16598				const a = i + 0;
16599				const b = i + 1;
16600				const c = i + 2;
16601
16602				indices.push( a, b, b, c, c, a );
16603
16604			}
16605
16606		}
16607
16608		const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
16609		attribute.version = version;
16610
16611		// Updating index buffer in VAO now. See WebGLBindingStates
16612
16613		//
16614
16615		const previousAttribute = wireframeAttributes.get( geometry );
16616
16617		if ( previousAttribute ) attributes.remove( previousAttribute );
16618
16619		//
16620
16621		wireframeAttributes.set( geometry, attribute );
16622
16623	}
16624
16625	function getWireframeAttribute( geometry ) {
16626
16627		const currentAttribute = wireframeAttributes.get( geometry );
16628
16629		if ( currentAttribute ) {
16630
16631			const geometryIndex = geometry.index;
16632
16633			if ( geometryIndex !== null ) {
16634
16635				// if the attribute is obsolete, create a new one
16636
16637				if ( currentAttribute.version < geometryIndex.version ) {
16638
16639					updateWireframeAttribute( geometry );
16640
16641				}
16642
16643			}
16644
16645		} else {
16646
16647			updateWireframeAttribute( geometry );
16648
16649		}
16650
16651		return wireframeAttributes.get( geometry );
16652
16653	}
16654
16655	return {
16656
16657		get: get,
16658		update: update,
16659
16660		getWireframeAttribute: getWireframeAttribute
16661
16662	};
16663
16664}
16665
16666function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
16667
16668	const isWebGL2 = capabilities.isWebGL2;
16669
16670	let mode;
16671
16672	function setMode( value ) {
16673
16674		mode = value;
16675
16676	}
16677
16678	let type, bytesPerElement;
16679
16680	function setIndex( value ) {
16681
16682		type = value.type;
16683		bytesPerElement = value.bytesPerElement;
16684
16685	}
16686
16687	function render( start, count ) {
16688
16689		gl.drawElements( mode, count, type, start * bytesPerElement );
16690
16691		info.update( count, mode, 1 );
16692
16693	}
16694
16695	function renderInstances( start, count, primcount ) {
16696
16697		if ( primcount === 0 ) return;
16698
16699		let extension, methodName;
16700
16701		if ( isWebGL2 ) {
16702
16703			extension = gl;
16704			methodName = 'drawElementsInstanced';
16705
16706		} else {
16707
vendor: 10,265 bytes, lines 16708-17161
16708			extension = extensions.get( 'ANGLE_instanced_arrays' );
16709			methodName = 'drawElementsInstancedANGLE';
16710
16711			if ( extension === null ) {
16712
16713				console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
16714				return;
16715
16716			}
16717
16718		}
16719
16720		extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
16721
16722		info.update( count, mode, primcount );
16723
16724	}
16725
16726	//
16727
16728	this.setMode = setMode;
16729	this.setIndex = setIndex;
16730	this.render = render;
16731	this.renderInstances = renderInstances;
16732
16733}
16734
16735function WebGLInfo( gl ) {
16736
16737	const memory = {
16738		geometries: 0,
16739		textures: 0
16740	};
16741
16742	const render = {
16743		frame: 0,
16744		calls: 0,
16745		triangles: 0,
16746		points: 0,
16747		lines: 0
16748	};
16749
16750	function update( count, mode, instanceCount ) {
16751
16752		render.calls ++;
16753
16754		switch ( mode ) {
16755
16756			case 4:
16757				render.triangles += instanceCount * ( count / 3 );
16758				break;
16759
16760			case 1:
16761				render.lines += instanceCount * ( count / 2 );
16762				break;
16763
16764			case 3:
16765				render.lines += instanceCount * ( count - 1 );
16766				break;
16767
16768			case 2:
16769				render.lines += instanceCount * count;
16770				break;
16771
16772			case 0:
16773				render.points += instanceCount * count;
16774				break;
16775
16776			default:
16777				console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
16778				break;
16779
16780		}
16781
16782	}
16783
16784	function reset() {
16785
16786		render.frame ++;
16787		render.calls = 0;
16788		render.triangles = 0;
16789		render.points = 0;
16790		render.lines = 0;
16791
16792	}
16793
16794	return {
16795		memory: memory,
16796		render: render,
16797		programs: null,
16798		autoReset: true,
16799		reset: reset,
16800		update: update
16801	};
16802
16803}
16804
16805function numericalSort( a, b ) {
16806
16807	return a[ 0 ] - b[ 0 ];
16808
16809}
16810
16811function absNumericalSort( a, b ) {
16812
16813	return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );
16814
16815}
16816
16817function WebGLMorphtargets( gl, capabilities, textures ) {
16818
16819	const influencesList = {};
16820	const morphInfluences = new Float32Array( 8 );
16821	const morphTextures = new WeakMap();
16822	const morph = new Vector4();
16823
16824	const workInfluences = [];
16825
16826	for ( let i = 0; i < 8; i ++ ) {
16827
16828		workInfluences[ i ] = [ i, 0 ];
16829
16830	}
16831
16832	function update( object, geometry, program ) {
16833
16834		const objectInfluences = object.morphTargetInfluences;
16835
16836		if ( capabilities.isWebGL2 === true ) {
16837
16838			// instead of using attributes, the WebGL 2 code path encodes morph targets
16839			// into an array of data textures. Each layer represents a single morph target.
16840
16841			const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
16842			const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
16843
16844			let entry = morphTextures.get( geometry );
16845
16846			if ( entry === undefined || entry.count !== morphTargetsCount ) {
16847
16848				if ( entry !== undefined ) entry.texture.dispose();
16849
16850				const hasMorphPosition = geometry.morphAttributes.position !== undefined;
16851				const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
16852				const hasMorphColors = geometry.morphAttributes.color !== undefined;
16853
16854				const morphTargets = geometry.morphAttributes.position || [];
16855				const morphNormals = geometry.morphAttributes.normal || [];
16856				const morphColors = geometry.morphAttributes.color || [];
16857
16858				let vertexDataCount = 0;
16859
16860				if ( hasMorphPosition === true ) vertexDataCount = 1;
16861				if ( hasMorphNormals === true ) vertexDataCount = 2;
16862				if ( hasMorphColors === true ) vertexDataCount = 3;
16863
16864				let width = geometry.attributes.position.count * vertexDataCount;
16865				let height = 1;
16866
16867				if ( width > capabilities.maxTextureSize ) {
16868
16869					height = Math.ceil( width / capabilities.maxTextureSize );
16870					width = capabilities.maxTextureSize;
16871
16872				}
16873
16874				const buffer = new Float32Array( width * height * 4 * morphTargetsCount );
16875
16876				const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount );
16877				texture.type = FloatType;
16878				texture.needsUpdate = true;
16879
16880				// fill buffer
16881
16882				const vertexDataStride = vertexDataCount * 4;
16883
16884				for ( let i = 0; i < morphTargetsCount; i ++ ) {
16885
16886					const morphTarget = morphTargets[ i ];
16887					const morphNormal = morphNormals[ i ];
16888					const morphColor = morphColors[ i ];
16889
16890					const offset = width * height * 4 * i;
16891
16892					for ( let j = 0; j < morphTarget.count; j ++ ) {
16893
16894						const stride = j * vertexDataStride;
16895
16896						if ( hasMorphPosition === true ) {
16897
16898							morph.fromBufferAttribute( morphTarget, j );
16899
16900							buffer[ offset + stride + 0 ] = morph.x;
16901							buffer[ offset + stride + 1 ] = morph.y;
16902							buffer[ offset + stride + 2 ] = morph.z;
16903							buffer[ offset + stride + 3 ] = 0;
16904
16905						}
16906
16907						if ( hasMorphNormals === true ) {
16908
16909							morph.fromBufferAttribute( morphNormal, j );
16910
16911							buffer[ offset + stride + 4 ] = morph.x;
16912							buffer[ offset + stride + 5 ] = morph.y;
16913							buffer[ offset + stride + 6 ] = morph.z;
16914							buffer[ offset + stride + 7 ] = 0;
16915
16916						}
16917
16918						if ( hasMorphColors === true ) {
16919
16920							morph.fromBufferAttribute( morphColor, j );
16921
16922							buffer[ offset + stride + 8 ] = morph.x;
16923							buffer[ offset + stride + 9 ] = morph.y;
16924							buffer[ offset + stride + 10 ] = morph.z;
16925							buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1;
16926
16927						}
16928
16929					}
16930
16931				}
16932
16933				entry = {
16934					count: morphTargetsCount,
16935					texture: texture,
16936					size: new Vector2( width, height )
16937				};
16938
16939				morphTextures.set( geometry, entry );
16940
16941				function disposeTexture() {
16942
16943					texture.dispose();
16944
16945					morphTextures.delete( geometry );
16946
16947					geometry.removeEventListener( 'dispose', disposeTexture );
16948
16949				}
16950
16951				geometry.addEventListener( 'dispose', disposeTexture );
16952
16953			}
16954
16955			//
16956
16957			let morphInfluencesSum = 0;
16958
16959			for ( let i = 0; i < objectInfluences.length; i ++ ) {
16960
16961				morphInfluencesSum += objectInfluences[ i ];
16962
16963			}
16964
16965			const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
16966
16967			program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
16968			program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences );
16969
16970			program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures );
16971			program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
16972
16973
16974		} else {
16975
16976			// When object doesn't have morph target influences defined, we treat it as a 0-length array
16977			// This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
16978
16979			const length = objectInfluences === undefined ? 0 : objectInfluences.length;
16980
16981			let influences = influencesList[ geometry.id ];
16982
16983			if ( influences === undefined || influences.length !== length ) {
16984
16985				// initialise list
16986
16987				influences = [];
16988
16989				for ( let i = 0; i < length; i ++ ) {
16990
16991					influences[ i ] = [ i, 0 ];
16992
16993				}
16994
16995				influencesList[ geometry.id ] = influences;
16996
16997			}
16998
16999			// Collect influences
17000
17001			for ( let i = 0; i < length; i ++ ) {
17002
17003				const influence = influences[ i ];
17004
17005				influence[ 0 ] = i;
17006				influence[ 1 ] = objectInfluences[ i ];
17007
17008			}
17009
17010			influences.sort( absNumericalSort );
17011
17012			for ( let i = 0; i < 8; i ++ ) {
17013
17014				if ( i < length && influences[ i ][ 1 ] ) {
17015
17016					workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
17017					workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
17018
17019				} else {
17020
17021					workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
17022					workInfluences[ i ][ 1 ] = 0;
17023
17024				}
17025
17026			}
17027
17028			workInfluences.sort( numericalSort );
17029
17030			const morphTargets = geometry.morphAttributes.position;
17031			const morphNormals = geometry.morphAttributes.normal;
17032
17033			let morphInfluencesSum = 0;
17034
17035			for ( let i = 0; i < 8; i ++ ) {
17036
17037				const influence = workInfluences[ i ];
17038				const index = influence[ 0 ];
17039				const value = influence[ 1 ];
17040
17041				if ( index !== Number.MAX_SAFE_INTEGER && value ) {
17042
17043					if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
17044
17045						geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
17046
17047					}
17048
17049					if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
17050
17051						geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
17052
17053					}
17054
17055					morphInfluences[ i ] = value;
17056					morphInfluencesSum += value;
17057
17058				} else {
17059
17060					if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
17061
17062						geometry.deleteAttribute( 'morphTarget' + i );
17063
17064					}
17065
17066					if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
17067
17068						geometry.deleteAttribute( 'morphNormal' + i );
17069
17070					}
17071
17072					morphInfluences[ i ] = 0;
17073
17074				}
17075
17076			}
17077
17078			// GLSL shader uses formula baseinfluence * base + sum(target * influence)
17079			// This allows us to switch between absolute morphs and relative morphs without changing shader code
17080			// When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
17081			const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
17082
17083			program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
17084			program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
17085
17086		}
17087
17088	}
17089
17090	return {
17091
17092		update: update
17093
17094	};
17095
17096}
17097
17098function WebGLObjects( gl, geometries, attributes, info ) {
17099
17100	let updateMap = new WeakMap();
17101
17102	function update( object ) {
17103
17104		const frame = info.render.frame;
17105
17106		const geometry = object.geometry;
17107		const buffergeometry = geometries.get( object, geometry );
17108
17109		// Update once per frame
17110
17111		if ( updateMap.get( buffergeometry ) !== frame ) {
17112
17113			geometries.update( buffergeometry );
17114
17115			updateMap.set( buffergeometry, frame );
17116
17117		}
17118
17119		if ( object.isInstancedMesh ) {
17120
17121			if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
17122
17123				object.addEventListener( 'dispose', onInstancedMeshDispose );
17124
17125			}
17126
17127			attributes.update( object.instanceMatrix, 34962 );
17128
17129			if ( object.instanceColor !== null ) {
17130
17131				attributes.update( object.instanceColor, 34962 );
17132
17133			}
17134
17135		}
17136
17137		return buffergeometry;
17138
17139	}
17140
17141	function dispose() {
17142
17143		updateMap = new WeakMap();
17144
17145	}
17146
17147	function onInstancedMeshDispose( event ) {
17148
17149		const instancedMesh = event.target;
17150
17151		instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
17152
17153		attributes.remove( instancedMesh.instanceMatrix );
17154
17155		if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
17156
17157	}
17158
17159	return {
17160
17161		update: update,
17162		dispose: dispose
17163
17164	};
17165
17166}
17167
17168/**
17169 * Uniforms of a program.
17170 * Those form a tree structure with a special top-level container for the root,
17171 * which you get by calling 'new WebGLUniforms( gl, program )'.
17172 *
17173 *
17174 * Properties of inner nodes including the top-level container:
17175 *
17176 * .seq - array of nested uniforms
17177 * .map - nested uniforms by name
17178 *
17179 *
17180 * Methods of all nodes except the top-level container:
17181 *
17182 * .setValue( gl, value, [textures] )
17183 *
17184 * 		uploads a uniform value(s)
17185 *  	the 'textures' parameter is needed for sampler uniforms
17186 *
17187 *
17188 * Static methods of the top-level container (textures factorizations):
17189 *
17190 * .upload( gl, seq, values, textures )
17191 *
17192 * 		sets uniforms in 'seq' to 'values[id].value'
17193 *
17194 * .seqWithValue( seq, values ) : filteredSeq
17195 *
17196 * 		filters 'seq' entries with corresponding entry in values
17197 *
17198 *
17199 * Methods of the top-level container (textures factorizations):
17200 *
17201 * .setValue( gl, name, value, textures )
17202 *
17203 * 		sets uniform with  name 'name' to 'value'
17204 *
17205 * .setOptional( gl, obj, prop )
17206 *
17207 * 		like .set for an optional property of the object
17208 *
17209 */
17210
17211const emptyTexture = /*@__PURE__*/ new Texture();
17212const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture();
17213const empty3dTexture = /*@__PURE__*/ new Data3DTexture();
17214const emptyCubeTexture = /*@__PURE__*/ new CubeTexture();
17215
17216// --- Utilities ---
17217
vendor: 14,818 bytes, lines 17218-18089
17218// Array Caches (provide typed arrays for temporary by size)
17219
17220const arrayCacheF32 = [];
17221const arrayCacheI32 = [];
17222
17223// Float32Array caches used for uploading Matrix uniforms
17224
17225const mat4array = new Float32Array( 16 );
17226const mat3array = new Float32Array( 9 );
17227const mat2array = new Float32Array( 4 );
17228
17229// Flattening for arrays of vectors and matrices
17230
17231function flatten( array, nBlocks, blockSize ) {
17232
17233	const firstElem = array[ 0 ];
17234
17235	if ( firstElem <= 0 || firstElem > 0 ) return array;
17236	// unoptimized: ! isNaN( firstElem )
17237	// see http://jacksondunstan.com/articles/983
17238
17239	const n = nBlocks * blockSize;
17240	let r = arrayCacheF32[ n ];
17241
17242	if ( r === undefined ) {
17243
17244		r = new Float32Array( n );
17245		arrayCacheF32[ n ] = r;
17246
17247	}
17248
17249	if ( nBlocks !== 0 ) {
17250
17251		firstElem.toArray( r, 0 );
17252
17253		for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
17254
17255			offset += blockSize;
17256			array[ i ].toArray( r, offset );
17257
17258		}
17259
17260	}
17261
17262	return r;
17263
17264}
17265
17266function arraysEqual( a, b ) {
17267
17268	if ( a.length !== b.length ) return false;
17269
17270	for ( let i = 0, l = a.length; i < l; i ++ ) {
17271
17272		if ( a[ i ] !== b[ i ] ) return false;
17273
17274	}
17275
17276	return true;
17277
17278}
17279
17280function copyArray( a, b ) {
17281
17282	for ( let i = 0, l = b.length; i < l; i ++ ) {
17283
17284		a[ i ] = b[ i ];
17285
17286	}
17287
17288}
17289
17290// Texture unit allocation
17291
17292function allocTexUnits( textures, n ) {
17293
17294	let r = arrayCacheI32[ n ];
17295
17296	if ( r === undefined ) {
17297
17298		r = new Int32Array( n );
17299		arrayCacheI32[ n ] = r;
17300
17301	}
17302
17303	for ( let i = 0; i !== n; ++ i ) {
17304
17305		r[ i ] = textures.allocateTextureUnit();
17306
17307	}
17308
17309	return r;
17310
17311}
17312
17313// --- Setters ---
17314
17315// Note: Defining these methods externally, because they come in a bunch
17316// and this way their names minify.
17317
17318// Single scalar
17319
17320function setValueV1f( gl, v ) {
17321
17322	const cache = this.cache;
17323
17324	if ( cache[ 0 ] === v ) return;
17325
17326	gl.uniform1f( this.addr, v );
17327
17328	cache[ 0 ] = v;
17329
17330}
17331
17332// Single float vector (from flat array or THREE.VectorN)
17333
17334function setValueV2f( gl, v ) {
17335
17336	const cache = this.cache;
17337
17338	if ( v.x !== undefined ) {
17339
17340		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
17341
17342			gl.uniform2f( this.addr, v.x, v.y );
17343
17344			cache[ 0 ] = v.x;
17345			cache[ 1 ] = v.y;
17346
17347		}
17348
17349	} else {
17350
17351		if ( arraysEqual( cache, v ) ) return;
17352
17353		gl.uniform2fv( this.addr, v );
17354
17355		copyArray( cache, v );
17356
17357	}
17358
17359}
17360
17361function setValueV3f( gl, v ) {
17362
17363	const cache = this.cache;
17364
17365	if ( v.x !== undefined ) {
17366
17367		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
17368
17369			gl.uniform3f( this.addr, v.x, v.y, v.z );
17370
17371			cache[ 0 ] = v.x;
17372			cache[ 1 ] = v.y;
17373			cache[ 2 ] = v.z;
17374
17375		}
17376
17377	} else if ( v.r !== undefined ) {
17378
17379		if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
17380
17381			gl.uniform3f( this.addr, v.r, v.g, v.b );
17382
17383			cache[ 0 ] = v.r;
17384			cache[ 1 ] = v.g;
17385			cache[ 2 ] = v.b;
17386
17387		}
17388
17389	} else {
17390
17391		if ( arraysEqual( cache, v ) ) return;
17392
17393		gl.uniform3fv( this.addr, v );
17394
17395		copyArray( cache, v );
17396
17397	}
17398
17399}
17400
17401function setValueV4f( gl, v ) {
17402
17403	const cache = this.cache;
17404
17405	if ( v.x !== undefined ) {
17406
17407		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
17408
17409			gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
17410
17411			cache[ 0 ] = v.x;
17412			cache[ 1 ] = v.y;
17413			cache[ 2 ] = v.z;
17414			cache[ 3 ] = v.w;
17415
17416		}
17417
17418	} else {
17419
17420		if ( arraysEqual( cache, v ) ) return;
17421
17422		gl.uniform4fv( this.addr, v );
17423
17424		copyArray( cache, v );
17425
17426	}
17427
17428}
17429
17430// Single matrix (from flat array or THREE.MatrixN)
17431
17432function setValueM2( gl, v ) {
17433
17434	const cache = this.cache;
17435	const elements = v.elements;
17436
17437	if ( elements === undefined ) {
17438
17439		if ( arraysEqual( cache, v ) ) return;
17440
17441		gl.uniformMatrix2fv( this.addr, false, v );
17442
17443		copyArray( cache, v );
17444
17445	} else {
17446
17447		if ( arraysEqual( cache, elements ) ) return;
17448
17449		mat2array.set( elements );
17450
17451		gl.uniformMatrix2fv( this.addr, false, mat2array );
17452
17453		copyArray( cache, elements );
17454
17455	}
17456
17457}
17458
17459function setValueM3( gl, v ) {
17460
17461	const cache = this.cache;
17462	const elements = v.elements;
17463
17464	if ( elements === undefined ) {
17465
17466		if ( arraysEqual( cache, v ) ) return;
17467
17468		gl.uniformMatrix3fv( this.addr, false, v );
17469
17470		copyArray( cache, v );
17471
17472	} else {
17473
17474		if ( arraysEqual( cache, elements ) ) return;
17475
17476		mat3array.set( elements );
17477
17478		gl.uniformMatrix3fv( this.addr, false, mat3array );
17479
17480		copyArray( cache, elements );
17481
17482	}
17483
17484}
17485
17486function setValueM4( gl, v ) {
17487
17488	const cache = this.cache;
17489	const elements = v.elements;
17490
17491	if ( elements === undefined ) {
17492
17493		if ( arraysEqual( cache, v ) ) return;
17494
17495		gl.uniformMatrix4fv( this.addr, false, v );
17496
17497		copyArray( cache, v );
17498
17499	} else {
17500
17501		if ( arraysEqual( cache, elements ) ) return;
17502
17503		mat4array.set( elements );
17504
17505		gl.uniformMatrix4fv( this.addr, false, mat4array );
17506
17507		copyArray( cache, elements );
17508
17509	}
17510
17511}
17512
17513// Single integer / boolean
17514
17515function setValueV1i( gl, v ) {
17516
17517	const cache = this.cache;
17518
17519	if ( cache[ 0 ] === v ) return;
17520
17521	gl.uniform1i( this.addr, v );
17522
17523	cache[ 0 ] = v;
17524
17525}
17526
17527// Single integer / boolean vector (from flat array or THREE.VectorN)
17528
17529function setValueV2i( gl, v ) {
17530
17531	const cache = this.cache;
17532
17533	if ( v.x !== undefined ) {
17534
17535		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
17536
17537			gl.uniform2i( this.addr, v.x, v.y );
17538
17539			cache[ 0 ] = v.x;
17540			cache[ 1 ] = v.y;
17541
17542		}
17543
17544	} else {
17545
17546		if ( arraysEqual( cache, v ) ) return;
17547
17548		gl.uniform2iv( this.addr, v );
17549
17550		copyArray( cache, v );
17551
17552	}
17553
17554}
17555
17556function setValueV3i( gl, v ) {
17557
17558	const cache = this.cache;
17559
17560	if ( v.x !== undefined ) {
17561
17562		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
17563
17564			gl.uniform3i( this.addr, v.x, v.y, v.z );
17565
17566			cache[ 0 ] = v.x;
17567			cache[ 1 ] = v.y;
17568			cache[ 2 ] = v.z;
17569
17570		}
17571
17572	} else {
17573
17574		if ( arraysEqual( cache, v ) ) return;
17575
17576		gl.uniform3iv( this.addr, v );
17577
17578		copyArray( cache, v );
17579
17580	}
17581
17582}
17583
17584function setValueV4i( gl, v ) {
17585
17586	const cache = this.cache;
17587
17588	if ( v.x !== undefined ) {
17589
17590		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
17591
17592			gl.uniform4i( this.addr, v.x, v.y, v.z, v.w );
17593
17594			cache[ 0 ] = v.x;
17595			cache[ 1 ] = v.y;
17596			cache[ 2 ] = v.z;
17597			cache[ 3 ] = v.w;
17598
17599		}
17600
17601	} else {
17602
17603		if ( arraysEqual( cache, v ) ) return;
17604
17605		gl.uniform4iv( this.addr, v );
17606
17607		copyArray( cache, v );
17608
17609	}
17610
17611}
17612
17613// Single unsigned integer
17614
17615function setValueV1ui( gl, v ) {
17616
17617	const cache = this.cache;
17618
17619	if ( cache[ 0 ] === v ) return;
17620
17621	gl.uniform1ui( this.addr, v );
17622
17623	cache[ 0 ] = v;
17624
17625}
17626
17627// Single unsigned integer vector (from flat array or THREE.VectorN)
17628
17629function setValueV2ui( gl, v ) {
17630
17631	const cache = this.cache;
17632
17633	if ( v.x !== undefined ) {
17634
17635		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
17636
17637			gl.uniform2ui( this.addr, v.x, v.y );
17638
17639			cache[ 0 ] = v.x;
17640			cache[ 1 ] = v.y;
17641
17642		}
17643
17644	} else {
17645
17646		if ( arraysEqual( cache, v ) ) return;
17647
17648		gl.uniform2uiv( this.addr, v );
17649
17650		copyArray( cache, v );
17651
17652	}
17653
17654}
17655
17656function setValueV3ui( gl, v ) {
17657
17658	const cache = this.cache;
17659
17660	if ( v.x !== undefined ) {
17661
17662		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
17663
17664			gl.uniform3ui( this.addr, v.x, v.y, v.z );
17665
17666			cache[ 0 ] = v.x;
17667			cache[ 1 ] = v.y;
17668			cache[ 2 ] = v.z;
17669
17670		}
17671
17672	} else {
17673
17674		if ( arraysEqual( cache, v ) ) return;
17675
17676		gl.uniform3uiv( this.addr, v );
17677
17678		copyArray( cache, v );
17679
17680	}
17681
17682}
17683
17684function setValueV4ui( gl, v ) {
17685
17686	const cache = this.cache;
17687
17688	if ( v.x !== undefined ) {
17689
17690		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
17691
17692			gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w );
17693
17694			cache[ 0 ] = v.x;
17695			cache[ 1 ] = v.y;
17696			cache[ 2 ] = v.z;
17697			cache[ 3 ] = v.w;
17698
17699		}
17700
17701	} else {
17702
17703		if ( arraysEqual( cache, v ) ) return;
17704
17705		gl.uniform4uiv( this.addr, v );
17706
17707		copyArray( cache, v );
17708
17709	}
17710
17711}
17712
17713
17714// Single texture (2D / Cube)
17715
17716function setValueT1( gl, v, textures ) {
17717
17718	const cache = this.cache;
17719	const unit = textures.allocateTextureUnit();
17720
17721	if ( cache[ 0 ] !== unit ) {
17722
17723		gl.uniform1i( this.addr, unit );
17724		cache[ 0 ] = unit;
17725
17726	}
17727
17728	textures.setTexture2D( v || emptyTexture, unit );
17729
17730}
17731
17732function setValueT3D1( gl, v, textures ) {
17733
17734	const cache = this.cache;
17735	const unit = textures.allocateTextureUnit();
17736
17737	if ( cache[ 0 ] !== unit ) {
17738
17739		gl.uniform1i( this.addr, unit );
17740		cache[ 0 ] = unit;
17741
17742	}
17743
17744	textures.setTexture3D( v || empty3dTexture, unit );
17745
17746}
17747
17748function setValueT6( gl, v, textures ) {
17749
17750	const cache = this.cache;
17751	const unit = textures.allocateTextureUnit();
17752
17753	if ( cache[ 0 ] !== unit ) {
17754
17755		gl.uniform1i( this.addr, unit );
17756		cache[ 0 ] = unit;
17757
17758	}
17759
17760	textures.setTextureCube( v || emptyCubeTexture, unit );
17761
17762}
17763
17764function setValueT2DArray1( gl, v, textures ) {
17765
17766	const cache = this.cache;
17767	const unit = textures.allocateTextureUnit();
17768
17769	if ( cache[ 0 ] !== unit ) {
17770
17771		gl.uniform1i( this.addr, unit );
17772		cache[ 0 ] = unit;
17773
17774	}
17775
17776	textures.setTexture2DArray( v || emptyArrayTexture, unit );
17777
17778}
17779
17780// Helper to pick the right setter for the singular case
17781
17782function getSingularSetter( type ) {
17783
17784	switch ( type ) {
17785
17786		case 0x1406: return setValueV1f; // FLOAT
17787		case 0x8b50: return setValueV2f; // _VEC2
17788		case 0x8b51: return setValueV3f; // _VEC3
17789		case 0x8b52: return setValueV4f; // _VEC4
17790
17791		case 0x8b5a: return setValueM2; // _MAT2
17792		case 0x8b5b: return setValueM3; // _MAT3
17793		case 0x8b5c: return setValueM4; // _MAT4
17794
17795		case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
17796		case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
17797		case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
17798		case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
17799
17800		case 0x1405: return setValueV1ui; // UINT
17801		case 0x8dc6: return setValueV2ui; // _VEC2
17802		case 0x8dc7: return setValueV3ui; // _VEC3
17803		case 0x8dc8: return setValueV4ui; // _VEC4
17804
17805		case 0x8b5e: // SAMPLER_2D
17806		case 0x8d66: // SAMPLER_EXTERNAL_OES
17807		case 0x8dca: // INT_SAMPLER_2D
17808		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
17809		case 0x8b62: // SAMPLER_2D_SHADOW
17810			return setValueT1;
17811
17812		case 0x8b5f: // SAMPLER_3D
17813		case 0x8dcb: // INT_SAMPLER_3D
17814		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
17815			return setValueT3D1;
17816
17817		case 0x8b60: // SAMPLER_CUBE
17818		case 0x8dcc: // INT_SAMPLER_CUBE
17819		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
17820		case 0x8dc5: // SAMPLER_CUBE_SHADOW
17821			return setValueT6;
17822
17823		case 0x8dc1: // SAMPLER_2D_ARRAY
17824		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
17825		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
17826		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
17827			return setValueT2DArray1;
17828
17829	}
17830
17831}
17832
17833
17834// Array of scalars
17835
17836function setValueV1fArray( gl, v ) {
17837
17838	gl.uniform1fv( this.addr, v );
17839
17840}
17841
17842// Array of vectors (from flat array or array of THREE.VectorN)
17843
17844function setValueV2fArray( gl, v ) {
17845
17846	const data = flatten( v, this.size, 2 );
17847
17848	gl.uniform2fv( this.addr, data );
17849
17850}
17851
17852function setValueV3fArray( gl, v ) {
17853
17854	const data = flatten( v, this.size, 3 );
17855
17856	gl.uniform3fv( this.addr, data );
17857
17858}
17859
17860function setValueV4fArray( gl, v ) {
17861
17862	const data = flatten( v, this.size, 4 );
17863
17864	gl.uniform4fv( this.addr, data );
17865
17866}
17867
17868// Array of matrices (from flat array or array of THREE.MatrixN)
17869
17870function setValueM2Array( gl, v ) {
17871
17872	const data = flatten( v, this.size, 4 );
17873
17874	gl.uniformMatrix2fv( this.addr, false, data );
17875
17876}
17877
17878function setValueM3Array( gl, v ) {
17879
17880	const data = flatten( v, this.size, 9 );
17881
17882	gl.uniformMatrix3fv( this.addr, false, data );
17883
17884}
17885
17886function setValueM4Array( gl, v ) {
17887
17888	const data = flatten( v, this.size, 16 );
17889
17890	gl.uniformMatrix4fv( this.addr, false, data );
17891
17892}
17893
17894// Array of integer / boolean
17895
17896function setValueV1iArray( gl, v ) {
17897
17898	gl.uniform1iv( this.addr, v );
17899
17900}
17901
17902// Array of integer / boolean vectors (from flat array)
17903
17904function setValueV2iArray( gl, v ) {
17905
17906	gl.uniform2iv( this.addr, v );
17907
17908}
17909
17910function setValueV3iArray( gl, v ) {
17911
17912	gl.uniform3iv( this.addr, v );
17913
17914}
17915
17916function setValueV4iArray( gl, v ) {
17917
17918	gl.uniform4iv( this.addr, v );
17919
17920}
17921
17922// Array of unsigned integer
17923
17924function setValueV1uiArray( gl, v ) {
17925
17926	gl.uniform1uiv( this.addr, v );
17927
17928}
17929
17930// Array of unsigned integer vectors (from flat array)
17931
17932function setValueV2uiArray( gl, v ) {
17933
17934	gl.uniform2uiv( this.addr, v );
17935
17936}
17937
17938function setValueV3uiArray( gl, v ) {
17939
17940	gl.uniform3uiv( this.addr, v );
17941
17942}
17943
17944function setValueV4uiArray( gl, v ) {
17945
17946	gl.uniform4uiv( this.addr, v );
17947
17948}
17949
17950
17951// Array of textures (2D / 3D / Cube / 2DArray)
17952
17953function setValueT1Array( gl, v, textures ) {
17954
17955	const cache = this.cache;
17956
17957	const n = v.length;
17958
17959	const units = allocTexUnits( textures, n );
17960
17961	if ( ! arraysEqual( cache, units ) ) {
17962
17963		gl.uniform1iv( this.addr, units );
17964
17965		copyArray( cache, units );
17966
17967	}
17968
17969	for ( let i = 0; i !== n; ++ i ) {
17970
17971		textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
17972
17973	}
17974
17975}
17976
17977function setValueT3DArray( gl, v, textures ) {
17978
17979	const cache = this.cache;
17980
17981	const n = v.length;
17982
17983	const units = allocTexUnits( textures, n );
17984
17985	if ( ! arraysEqual( cache, units ) ) {
17986
17987		gl.uniform1iv( this.addr, units );
17988
17989		copyArray( cache, units );
17990
17991	}
17992
17993	for ( let i = 0; i !== n; ++ i ) {
17994
17995		textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] );
17996
17997	}
17998
17999}
18000
18001function setValueT6Array( gl, v, textures ) {
18002
18003	const cache = this.cache;
18004
18005	const n = v.length;
18006
18007	const units = allocTexUnits( textures, n );
18008
18009	if ( ! arraysEqual( cache, units ) ) {
18010
18011		gl.uniform1iv( this.addr, units );
18012
18013		copyArray( cache, units );
18014
18015	}
18016
18017	for ( let i = 0; i !== n; ++ i ) {
18018
18019		textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
18020
18021	}
18022
18023}
18024
18025function setValueT2DArrayArray( gl, v, textures ) {
18026
18027	const cache = this.cache;
18028
18029	const n = v.length;
18030
18031	const units = allocTexUnits( textures, n );
18032
18033	if ( ! arraysEqual( cache, units ) ) {
18034
18035		gl.uniform1iv( this.addr, units );
18036
18037		copyArray( cache, units );
18038
18039	}
18040
18041	for ( let i = 0; i !== n; ++ i ) {
18042
18043		textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] );
18044
18045	}
18046
18047}
18048
18049
18050// Helper to pick the right setter for a pure (bottom-level) array
18051
18052function getPureArraySetter( type ) {
18053
18054	switch ( type ) {
18055
18056		case 0x1406: return setValueV1fArray; // FLOAT
18057		case 0x8b50: return setValueV2fArray; // _VEC2
18058		case 0x8b51: return setValueV3fArray; // _VEC3
18059		case 0x8b52: return setValueV4fArray; // _VEC4
18060
18061		case 0x8b5a: return setValueM2Array; // _MAT2
18062		case 0x8b5b: return setValueM3Array; // _MAT3
18063		case 0x8b5c: return setValueM4Array; // _MAT4
18064
18065		case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
18066		case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
18067		case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
18068		case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
18069
18070		case 0x1405: return setValueV1uiArray; // UINT
18071		case 0x8dc6: return setValueV2uiArray; // _VEC2
18072		case 0x8dc7: return setValueV3uiArray; // _VEC3
18073		case 0x8dc8: return setValueV4uiArray; // _VEC4
18074
18075		case 0x8b5e: // SAMPLER_2D
18076		case 0x8d66: // SAMPLER_EXTERNAL_OES
18077		case 0x8dca: // INT_SAMPLER_2D
18078		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
18079		case 0x8b62: // SAMPLER_2D_SHADOW
18080			return setValueT1Array;
18081
18082		case 0x8b5f: // SAMPLER_3D
18083		case 0x8dcb: // INT_SAMPLER_3D
18084		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
18085			return setValueT3DArray;
18086
18087		case 0x8b60: // SAMPLER_CUBE
18088		case 0x8dcc: // INT_SAMPLER_CUBE
18089		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
vendor: 26,694 bytes, lines 18090-19085
18090		case 0x8dc5: // SAMPLER_CUBE_SHADOW
18091			return setValueT6Array;
18092
18093		case 0x8dc1: // SAMPLER_2D_ARRAY
18094		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
18095		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
18096		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
18097			return setValueT2DArrayArray;
18098
18099	}
18100
18101}
18102
18103// --- Uniform Classes ---
18104
18105class SingleUniform {
18106
18107	constructor( id, activeInfo, addr ) {
18108
18109		this.id = id;
18110		this.addr = addr;
18111		this.cache = [];
18112		this.setValue = getSingularSetter( activeInfo.type );
18113
18114		// this.path = activeInfo.name; // DEBUG
18115
18116	}
18117
18118}
18119
18120class PureArrayUniform {
18121
18122	constructor( id, activeInfo, addr ) {
18123
18124		this.id = id;
18125		this.addr = addr;
18126		this.cache = [];
18127		this.size = activeInfo.size;
18128		this.setValue = getPureArraySetter( activeInfo.type );
18129
18130		// this.path = activeInfo.name; // DEBUG
18131
18132	}
18133
18134}
18135
18136class StructuredUniform {
18137
18138	constructor( id ) {
18139
18140		this.id = id;
18141
18142		this.seq = [];
18143		this.map = {};
18144
18145	}
18146
18147	setValue( gl, value, textures ) {
18148
18149		const seq = this.seq;
18150
18151		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
18152
18153			const u = seq[ i ];
18154			u.setValue( gl, value[ u.id ], textures );
18155
18156		}
18157
18158	}
18159
18160}
18161
18162// --- Top-level ---
18163
18164// Parser - builds up the property tree from the path strings
18165
18166const RePathPart = /(\w+)(\])?(\[|\.)?/g;
18167
18168// extracts
18169// 	- the identifier (member name or array index)
18170//  - followed by an optional right bracket (found when array index)
18171//  - followed by an optional left bracket or dot (type of subscript)
18172//
18173// Note: These portions can be read in a non-overlapping fashion and
18174// allow straightforward parsing of the hierarchy that WebGL encodes
18175// in the uniform names.
18176
18177function addUniform( container, uniformObject ) {
18178
18179	container.seq.push( uniformObject );
18180	container.map[ uniformObject.id ] = uniformObject;
18181
18182}
18183
18184function parseUniform( activeInfo, addr, container ) {
18185
18186	const path = activeInfo.name,
18187		pathLength = path.length;
18188
18189	// reset RegExp object, because of the early exit of a previous run
18190	RePathPart.lastIndex = 0;
18191
18192	while ( true ) {
18193
18194		const match = RePathPart.exec( path ),
18195			matchEnd = RePathPart.lastIndex;
18196
18197		let id = match[ 1 ];
18198		const idIsIndex = match[ 2 ] === ']',
18199			subscript = match[ 3 ];
18200
18201		if ( idIsIndex ) id = id | 0; // convert to integer
18202
18203		if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
18204
18205			// bare name or "pure" bottom-level array "[0]" suffix
18206
18207			addUniform( container, subscript === undefined ?
18208				new SingleUniform( id, activeInfo, addr ) :
18209				new PureArrayUniform( id, activeInfo, addr ) );
18210
18211			break;
18212
18213		} else {
18214
18215			// step into inner node / create it in case it doesn't exist
18216
18217			const map = container.map;
18218			let next = map[ id ];
18219
18220			if ( next === undefined ) {
18221
18222				next = new StructuredUniform( id );
18223				addUniform( container, next );
18224
18225			}
18226
18227			container = next;
18228
18229		}
18230
18231	}
18232
18233}
18234
18235// Root Container
18236
18237class WebGLUniforms {
18238
18239	constructor( gl, program ) {
18240
18241		this.seq = [];
18242		this.map = {};
18243
18244		const n = gl.getProgramParameter( program, 35718 );
18245
18246		for ( let i = 0; i < n; ++ i ) {
18247
18248			const info = gl.getActiveUniform( program, i ),
18249				addr = gl.getUniformLocation( program, info.name );
18250
18251			parseUniform( info, addr, this );
18252
18253		}
18254
18255	}
18256
18257	setValue( gl, name, value, textures ) {
18258
18259		const u = this.map[ name ];
18260
18261		if ( u !== undefined ) u.setValue( gl, value, textures );
18262
18263	}
18264
18265	setOptional( gl, object, name ) {
18266
18267		const v = object[ name ];
18268
18269		if ( v !== undefined ) this.setValue( gl, name, v );
18270
18271	}
18272
18273	static upload( gl, seq, values, textures ) {
18274
18275		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
18276
18277			const u = seq[ i ],
18278				v = values[ u.id ];
18279
18280			if ( v.needsUpdate !== false ) {
18281
18282				// note: always updating when .needsUpdate is undefined
18283				u.setValue( gl, v.value, textures );
18284
18285			}
18286
18287		}
18288
18289	}
18290
18291	static seqWithValue( seq, values ) {
18292
18293		const r = [];
18294
18295		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
18296
18297			const u = seq[ i ];
18298			if ( u.id in values ) r.push( u );
18299
18300		}
18301
18302		return r;
18303
18304	}
18305
18306}
18307
18308function WebGLShader( gl, type, string ) {
18309
18310	const shader = gl.createShader( type );
18311
18312	gl.shaderSource( shader, string );
18313	gl.compileShader( shader );
18314
18315	return shader;
18316
18317}
18318
18319let programIdCount = 0;
18320
18321function handleSource( string, errorLine ) {
18322
18323	const lines = string.split( '\n' );
18324	const lines2 = [];
18325
18326	const from = Math.max( errorLine - 6, 0 );
18327	const to = Math.min( errorLine + 6, lines.length );
18328
18329	for ( let i = from; i < to; i ++ ) {
18330
18331		const line = i + 1;
18332		lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` );
18333
18334	}
18335
18336	return lines2.join( '\n' );
18337
18338}
18339
18340function getEncodingComponents( encoding ) {
18341
18342	switch ( encoding ) {
18343
18344		case LinearEncoding:
18345			return [ 'Linear', '( value )' ];
18346		case sRGBEncoding:
18347			return [ 'sRGB', '( value )' ];
18348		default:
18349			console.warn( 'THREE.WebGLProgram: Unsupported encoding:', encoding );
18350			return [ 'Linear', '( value )' ];
18351
18352	}
18353
18354}
18355
18356function getShaderErrors( gl, shader, type ) {
18357
18358	const status = gl.getShaderParameter( shader, 35713 );
18359	const errors = gl.getShaderInfoLog( shader ).trim();
18360
18361	if ( status && errors === '' ) return '';
18362
18363	const errorMatches = /ERROR: 0:(\d+)/.exec( errors );
18364	if ( errorMatches ) {
18365
18366		// --enable-privileged-webgl-extension
18367		// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
18368
18369		const errorLine = parseInt( errorMatches[ 1 ] );
18370		return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine );
18371
18372	} else {
18373
18374		return errors;
18375
18376	}
18377
18378}
18379
18380function getTexelEncodingFunction( functionName, encoding ) {
18381
18382	const components = getEncodingComponents( encoding );
18383	return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';
18384
18385}
18386
18387function getToneMappingFunction( functionName, toneMapping ) {
18388
18389	let toneMappingName;
18390
18391	switch ( toneMapping ) {
18392
18393		case LinearToneMapping:
18394			toneMappingName = 'Linear';
18395			break;
18396
18397		case ReinhardToneMapping:
18398			toneMappingName = 'Reinhard';
18399			break;
18400
18401		case CineonToneMapping:
18402			toneMappingName = 'OptimizedCineon';
18403			break;
18404
18405		case ACESFilmicToneMapping:
18406			toneMappingName = 'ACESFilmic';
18407			break;
18408
18409		case CustomToneMapping:
18410			toneMappingName = 'Custom';
18411			break;
18412
18413		default:
18414			console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
18415			toneMappingName = 'Linear';
18416
18417	}
18418
18419	return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
18420
18421}
18422
18423function generateExtensions( parameters ) {
18424
18425	const chunks = [
18426		( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',
18427		( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
18428		( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',
18429		( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
18430	];
18431
18432	return chunks.filter( filterEmptyLine ).join( '\n' );
18433
18434}
18435
18436function generateDefines( defines ) {
18437
18438	const chunks = [];
18439
18440	for ( const name in defines ) {
18441
18442		const value = defines[ name ];
18443
18444		if ( value === false ) continue;
18445
18446		chunks.push( '#define ' + name + ' ' + value );
18447
18448	}
18449
18450	return chunks.join( '\n' );
18451
18452}
18453
18454function fetchAttributeLocations( gl, program ) {
18455
18456	const attributes = {};
18457
18458	const n = gl.getProgramParameter( program, 35721 );
18459
18460	for ( let i = 0; i < n; i ++ ) {
18461
18462		const info = gl.getActiveAttrib( program, i );
18463		const name = info.name;
18464
18465		let locationSize = 1;
18466		if ( info.type === 35674 ) locationSize = 2;
18467		if ( info.type === 35675 ) locationSize = 3;
18468		if ( info.type === 35676 ) locationSize = 4;
18469
18470		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
18471
18472		attributes[ name ] = {
18473			type: info.type,
18474			location: gl.getAttribLocation( program, name ),
18475			locationSize: locationSize
18476		};
18477
18478	}
18479
18480	return attributes;
18481
18482}
18483
18484function filterEmptyLine( string ) {
18485
18486	return string !== '';
18487
18488}
18489
18490function replaceLightNums( string, parameters ) {
18491
18492	const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps;
18493
18494	return string
18495		.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
18496		.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
18497		.replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps )
18498		.replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords )
18499		.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
18500		.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
18501		.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
18502		.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
18503		.replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps )
18504		.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
18505		.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
18506
18507}
18508
18509function replaceClippingPlaneNums( string, parameters ) {
18510
18511	return string
18512		.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
18513		.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
18514
18515}
18516
18517// Resolve Includes
18518
18519const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
18520
18521function resolveIncludes( string ) {
18522
18523	return string.replace( includePattern, includeReplacer );
18524
18525}
18526
18527function includeReplacer( match, include ) {
18528
18529	const string = ShaderChunk[ include ];
18530
18531	if ( string === undefined ) {
18532
18533		throw new Error( 'Can not resolve #include <' + include + '>' );
18534
18535	}
18536
18537	return resolveIncludes( string );
18538
18539}
18540
18541// Unroll Loops
18542
18543const unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;
18544
18545function unrollLoops( string ) {
18546
18547	return string.replace( unrollLoopPattern, loopReplacer );
18548
18549}
18550
18551function loopReplacer( match, start, end, snippet ) {
18552
18553	let string = '';
18554
18555	for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
18556
18557		string += snippet
18558			.replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
18559			.replace( /UNROLLED_LOOP_INDEX/g, i );
18560
18561	}
18562
18563	return string;
18564
18565}
18566
18567//
18568
18569function generatePrecision( parameters ) {
18570
18571	let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
18572
18573	if ( parameters.precision === 'highp' ) {
18574
18575		precisionstring += '\n#define HIGH_PRECISION';
18576
18577	} else if ( parameters.precision === 'mediump' ) {
18578
18579		precisionstring += '\n#define MEDIUM_PRECISION';
18580
18581	} else if ( parameters.precision === 'lowp' ) {
18582
18583		precisionstring += '\n#define LOW_PRECISION';
18584
18585	}
18586
18587	return precisionstring;
18588
18589}
18590
18591function generateShadowMapTypeDefine( parameters ) {
18592
18593	let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
18594
18595	if ( parameters.shadowMapType === PCFShadowMap ) {
18596
18597		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
18598
18599	} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
18600
18601		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
18602
18603	} else if ( parameters.shadowMapType === VSMShadowMap ) {
18604
18605		shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
18606
18607	}
18608
18609	return shadowMapTypeDefine;
18610
18611}
18612
18613function generateEnvMapTypeDefine( parameters ) {
18614
18615	let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
18616
18617	if ( parameters.envMap ) {
18618
18619		switch ( parameters.envMapMode ) {
18620
18621			case CubeReflectionMapping:
18622			case CubeRefractionMapping:
18623				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
18624				break;
18625
18626			case CubeUVReflectionMapping:
18627				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
18628				break;
18629
18630		}
18631
18632	}
18633
18634	return envMapTypeDefine;
18635
18636}
18637
18638function generateEnvMapModeDefine( parameters ) {
18639
18640	let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
18641
18642	if ( parameters.envMap ) {
18643
18644		switch ( parameters.envMapMode ) {
18645
18646			case CubeRefractionMapping:
18647
18648				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
18649				break;
18650
18651		}
18652
18653	}
18654
18655	return envMapModeDefine;
18656
18657}
18658
18659function generateEnvMapBlendingDefine( parameters ) {
18660
18661	let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
18662
18663	if ( parameters.envMap ) {
18664
18665		switch ( parameters.combine ) {
18666
18667			case MultiplyOperation:
18668				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
18669				break;
18670
18671			case MixOperation:
18672				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
18673				break;
18674
18675			case AddOperation:
18676				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
18677				break;
18678
18679		}
18680
18681	}
18682
18683	return envMapBlendingDefine;
18684
18685}
18686
18687function generateCubeUVSize( parameters ) {
18688
18689	const imageHeight = parameters.envMapCubeUVHeight;
18690
18691	if ( imageHeight === null ) return null;
18692
18693	const maxMip = Math.log2( imageHeight ) - 2;
18694
18695	const texelHeight = 1.0 / imageHeight;
18696
18697	const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) );
18698
18699	return { texelWidth, texelHeight, maxMip };
18700
18701}
18702
18703function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
18704
18705	// TODO Send this event to Three.js DevTools
18706	// console.log( 'WebGLProgram', cacheKey );
18707
18708	const gl = renderer.getContext();
18709
18710	const defines = parameters.defines;
18711
18712	let vertexShader = parameters.vertexShader;
18713	let fragmentShader = parameters.fragmentShader;
18714
18715	const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
18716	const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
18717	const envMapModeDefine = generateEnvMapModeDefine( parameters );
18718	const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
18719	const envMapCubeUVSize = generateCubeUVSize( parameters );
18720
18721	const customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );
18722
18723	const customDefines = generateDefines( defines );
18724
18725	const program = gl.createProgram();
18726
18727	let prefixVertex, prefixFragment;
18728	let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
18729
18730	if ( parameters.isRawShaderMaterial ) {
18731
18732		prefixVertex = [
18733
18734			customDefines
18735
18736		].filter( filterEmptyLine ).join( '\n' );
18737
18738		if ( prefixVertex.length > 0 ) {
18739
18740			prefixVertex += '\n';
18741
18742		}
18743
18744		prefixFragment = [
18745
18746			customExtensions,
18747			customDefines
18748
18749		].filter( filterEmptyLine ).join( '\n' );
18750
18751		if ( prefixFragment.length > 0 ) {
18752
18753			prefixFragment += '\n';
18754
18755		}
18756
18757	} else {
18758
18759		prefixVertex = [
18760
18761			generatePrecision( parameters ),
18762
18763			'#define SHADER_NAME ' + parameters.shaderName,
18764
18765			customDefines,
18766
18767			parameters.instancing ? '#define USE_INSTANCING' : '',
18768			parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
18769
18770			parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',
18771
18772			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
18773			( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
18774
18775			parameters.map ? '#define USE_MAP' : '',
18776			parameters.envMap ? '#define USE_ENVMAP' : '',
18777			parameters.envMap ? '#define ' + envMapModeDefine : '',
18778			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
18779			parameters.aoMap ? '#define USE_AOMAP' : '',
18780			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
18781			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
18782			parameters.normalMap ? '#define USE_NORMALMAP' : '',
18783			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
18784			( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
18785
18786			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
18787			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
18788			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
18789
18790			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
18791			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
18792
18793			parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',
18794
18795			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
18796			parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '',
18797			parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '',
18798
18799			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
18800			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
18801			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
18802
18803			parameters.transmission ? '#define USE_TRANSMISSION' : '',
18804			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
18805			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
18806
18807			parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '',
18808			parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '',
18809
18810			parameters.vertexTangents ? '#define USE_TANGENT' : '',
18811			parameters.vertexColors ? '#define USE_COLOR' : '',
18812			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
18813			parameters.vertexUvs ? '#define USE_UV' : '',
18814			parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
18815
18816			parameters.flatShading ? '#define FLAT_SHADED' : '',
18817
18818			parameters.skinning ? '#define USE_SKINNING' : '',
18819
18820			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
18821			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
18822			( parameters.morphColors && parameters.isWebGL2 ) ? '#define USE_MORPHCOLORS' : '',
18823			( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE' : '',
18824			( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '',
18825			( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '',
18826			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
18827			parameters.flipSided ? '#define FLIP_SIDED' : '',
18828
18829			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
18830			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
18831
18832			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
18833
18834			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
18835			( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
18836
18837			'uniform mat4 modelMatrix;',
18838			'uniform mat4 modelViewMatrix;',
18839			'uniform mat4 projectionMatrix;',
18840			'uniform mat4 viewMatrix;',
18841			'uniform mat3 normalMatrix;',
18842			'uniform vec3 cameraPosition;',
18843			'uniform bool isOrthographic;',
18844
18845			'#ifdef USE_INSTANCING',
18846
18847			'	attribute mat4 instanceMatrix;',
18848
18849			'#endif',
18850
18851			'#ifdef USE_INSTANCING_COLOR',
18852
18853			'	attribute vec3 instanceColor;',
18854
18855			'#endif',
18856
18857			'attribute vec3 position;',
18858			'attribute vec3 normal;',
18859			'attribute vec2 uv;',
18860
18861			'#ifdef USE_TANGENT',
18862
18863			'	attribute vec4 tangent;',
18864
18865			'#endif',
18866
18867			'#if defined( USE_COLOR_ALPHA )',
18868
18869			'	attribute vec4 color;',
18870
18871			'#elif defined( USE_COLOR )',
18872
18873			'	attribute vec3 color;',
18874
18875			'#endif',
18876
18877			'#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )',
18878
18879			'	attribute vec3 morphTarget0;',
18880			'	attribute vec3 morphTarget1;',
18881			'	attribute vec3 morphTarget2;',
18882			'	attribute vec3 morphTarget3;',
18883
18884			'	#ifdef USE_MORPHNORMALS',
18885
18886			'		attribute vec3 morphNormal0;',
18887			'		attribute vec3 morphNormal1;',
18888			'		attribute vec3 morphNormal2;',
18889			'		attribute vec3 morphNormal3;',
18890
18891			'	#else',
18892
18893			'		attribute vec3 morphTarget4;',
18894			'		attribute vec3 morphTarget5;',
18895			'		attribute vec3 morphTarget6;',
18896			'		attribute vec3 morphTarget7;',
18897
18898			'	#endif',
18899
18900			'#endif',
18901
18902			'#ifdef USE_SKINNING',
18903
18904			'	attribute vec4 skinIndex;',
18905			'	attribute vec4 skinWeight;',
18906
18907			'#endif',
18908
18909			'\n'
18910
18911		].filter( filterEmptyLine ).join( '\n' );
18912
18913		prefixFragment = [
18914
18915			customExtensions,
18916
18917			generatePrecision( parameters ),
18918
18919			'#define SHADER_NAME ' + parameters.shaderName,
18920
18921			customDefines,
18922
18923			( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
18924			( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',
18925
18926			parameters.map ? '#define USE_MAP' : '',
18927			parameters.matcap ? '#define USE_MATCAP' : '',
18928			parameters.envMap ? '#define USE_ENVMAP' : '',
18929			parameters.envMap ? '#define ' + envMapTypeDefine : '',
18930			parameters.envMap ? '#define ' + envMapModeDefine : '',
18931			parameters.envMap ? '#define ' + envMapBlendingDefine : '',
18932			envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '',
18933			envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '',
18934			envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '',
18935			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
18936			parameters.aoMap ? '#define USE_AOMAP' : '',
18937			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
18938			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
18939			parameters.normalMap ? '#define USE_NORMALMAP' : '',
18940			( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',
18941			( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',
18942
18943			parameters.clearcoat ? '#define USE_CLEARCOAT' : '',
18944			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
18945			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
18946			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
18947
18948			parameters.iridescence ? '#define USE_IRIDESCENCE' : '',
18949			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
18950			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
18951
18952			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
18953			parameters.specularIntensityMap ? '#define USE_SPECULARINTENSITYMAP' : '',
18954			parameters.specularColorMap ? '#define USE_SPECULARCOLORMAP' : '',
18955			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
18956			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
18957
18958			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
18959			parameters.alphaTest ? '#define USE_ALPHATEST' : '',
18960
18961			parameters.sheen ? '#define USE_SHEEN' : '',
18962			parameters.sheenColorMap ? '#define USE_SHEENCOLORMAP' : '',
18963			parameters.sheenRoughnessMap ? '#define USE_SHEENROUGHNESSMAP' : '',
18964
18965			parameters.transmission ? '#define USE_TRANSMISSION' : '',
18966			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
18967			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
18968
18969			parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '',
18970
18971			parameters.vertexTangents ? '#define USE_TANGENT' : '',
18972			parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
18973			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
18974			parameters.vertexUvs ? '#define USE_UV' : '',
18975			parameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',
18976
18977			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
18978
18979			parameters.flatShading ? '#define FLAT_SHADED' : '',
18980
18981			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
18982			parameters.flipSided ? '#define FLIP_SIDED' : '',
18983
18984			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
18985			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
18986
18987			parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
18988
18989			parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '',
18990
18991			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
18992			( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
18993
18994			'uniform mat4 viewMatrix;',
18995			'uniform vec3 cameraPosition;',
18996			'uniform bool isOrthographic;',
18997
18998			( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
18999			( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
19000			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
19001
19002			parameters.dithering ? '#define DITHERING' : '',
19003			parameters.opaque ? '#define OPAQUE' : '',
19004
19005			ShaderChunk[ 'encodings_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
19006			getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ),
19007
19008			parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
19009
19010			'\n'
19011
19012		].filter( filterEmptyLine ).join( '\n' );
19013
19014	}
19015
19016	vertexShader = resolveIncludes( vertexShader );
19017	vertexShader = replaceLightNums( vertexShader, parameters );
19018	vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
19019
19020	fragmentShader = resolveIncludes( fragmentShader );
19021	fragmentShader = replaceLightNums( fragmentShader, parameters );
19022	fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
19023
19024	vertexShader = unrollLoops( vertexShader );
19025	fragmentShader = unrollLoops( fragmentShader );
19026
19027	if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !== true ) {
19028
19029		// GLSL 3.0 conversion for built-in materials and ShaderMaterial
19030
19031		versionString = '#version 300 es\n';
19032
19033		prefixVertex = [
19034			'precision mediump sampler2DArray;',
19035			'#define attribute in',
19036			'#define varying out',
19037			'#define texture2D texture'
19038		].join( '\n' ) + '\n' + prefixVertex;
19039
19040		prefixFragment = [
19041			'#define varying in',
19042			( parameters.glslVersion === GLSL3 ) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;',
19043			( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
19044			'#define gl_FragDepthEXT gl_FragDepth',
19045			'#define texture2D texture',
19046			'#define textureCube texture',
19047			'#define texture2DProj textureProj',
19048			'#define texture2DLodEXT textureLod',
19049			'#define texture2DProjLodEXT textureProjLod',
19050			'#define textureCubeLodEXT textureLod',
19051			'#define texture2DGradEXT textureGrad',
19052			'#define texture2DProjGradEXT textureProjGrad',
19053			'#define textureCubeGradEXT textureGrad'
19054		].join( '\n' ) + '\n' + prefixFragment;
19055
19056	}
19057
19058	const vertexGlsl = versionString + prefixVertex + vertexShader;
19059	const fragmentGlsl = versionString + prefixFragment + fragmentShader;
19060
19061	// console.log( '*VERTEX*', vertexGlsl );
19062	// console.log( '*FRAGMENT*', fragmentGlsl );
19063
19064	const glVertexShader = WebGLShader( gl, 35633, vertexGlsl );
19065	const glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );
19066
19067	gl.attachShader( program, glVertexShader );
19068	gl.attachShader( program, glFragmentShader );
19069
19070	// Force a particular attribute to index 0.
19071
19072	if ( parameters.index0AttributeName !== undefined ) {
19073
19074		gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
19075
19076	} else if ( parameters.morphTargets === true ) {
19077
19078		// programs with morphTargets displace position out of attribute 0
19079		gl.bindAttribLocation( program, 0, 'position' );
19080
19081	}
19082
19083	gl.linkProgram( program );
19084
19085	// check for link errors
19086	if ( renderer.debug.checkShaderErrors ) {
19087
19088		const programLog = gl.getProgramInfoLog( program ).trim();
19089		const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
19090		const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
19091
19092		let runnable = true;
19093		let haveDiagnostics = true;
19094
19095		if ( gl.getProgramParameter( program, 35714 ) === false ) {
19096
19097			runnable = false;
19098
19099			const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
19100			const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
19101
19102			console.error(
19103				'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
19104				'VALIDATE_STATUS ' + gl.getProgramParameter( program, 35715 ) + '\n\n' +
19105				'Program Info Log: ' + programLog + '\n' +
19106				vertexErrors + '\n' +
19107				fragmentErrors
19108			);
19109
19110		} else if ( programLog !== '' ) {
19111
19112			console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
19113
19114		} else if ( vertexLog === '' || fragmentLog === '' ) {
19115
19116			haveDiagnostics = false;
19117
19118		}
19119
19120		if ( haveDiagnostics ) {
19121
19122			this.diagnostics = {
19123
19124				runnable: runnable,
19125
19126				programLog: programLog,
19127
19128				vertexShader: {
19129
19130					log: vertexLog,
19131					prefix: prefixVertex
19132
19133				},
19134
19135				fragmentShader: {
19136
19137					log: fragmentLog,
19138					prefix: prefixFragment
19139
19140				}
19141
19142			};
19143
19144		}
19145
19146	}
19147
19148	// Clean up
19149
19150	// Crashes in iOS9 and iOS10. #18402
19151	// gl.detachShader( program, glVertexShader );
19152	// gl.detachShader( program, glFragmentShader );
19153
19154	gl.deleteShader( glVertexShader );
19155	gl.deleteShader( glFragmentShader );
19156
19157	// set up caching for uniform locations
19158
19159	let cachedUniforms;
19160
19161	this.getUniforms = function () {
19162
19163		if ( cachedUniforms === undefined ) {
19164
19165			cachedUniforms = new WebGLUniforms( gl, program );
19166
19167		}
19168
19169		return cachedUniforms;
19170
19171	};
19172
19173	// set up caching for attribute locations
19174
19175	let cachedAttributes;
19176
19177	this.getAttributes = function () {
19178
19179		if ( cachedAttributes === undefined ) {
19180
19181			cachedAttributes = fetchAttributeLocations( gl, program );
19182
19183		}
19184
19185		return cachedAttributes;
19186
19187	};
19188
19189	// free resource
19190
19191	this.destroy = function () {
19192
19193		bindingStates.releaseStatesOfProgram( this );
19194
19195		gl.deleteProgram( program );
19196		this.program = undefined;
19197
19198	};
19199
19200	//
19201
19202	this.name = parameters.shaderName;
19203	this.id = programIdCount ++;
19204	this.cacheKey = cacheKey;
19205	this.usedTimes = 1;
19206	this.program = program;
19207	this.vertexShader = glVertexShader;
19208	this.fragmentShader = glFragmentShader;
19209
19210	return this;
19211
19212}
19213
19214let _id = 0;
19215
19216class WebGLShaderCache {
19217
19218	constructor() {
19219
19220		this.shaderCache = new Map();
19221		this.materialCache = new Map();
19222
19223	}
19224
19225	update( material ) {
19226
19227		const vertexShader = material.vertexShader;
19228		const fragmentShader = material.fragmentShader;
19229
19230		const vertexShaderStage = this._getShaderStage( vertexShader );
19231		const fragmentShaderStage = this._getShaderStage( fragmentShader );
19232
19233		const materialShaders = this._getShaderCacheForMaterial( material );
19234
19235		if ( materialShaders.has( vertexShaderStage ) === false ) {
19236
19237			materialShaders.add( vertexShaderStage );
19238			vertexShaderStage.usedTimes ++;
19239
19240		}
19241
19242		if ( materialShaders.has( fragmentShaderStage ) === false ) {
19243
19244			materialShaders.add( fragmentShaderStage );
19245			fragmentShaderStage.usedTimes ++;
19246
19247		}
19248
19249		return this;
19250
19251	}
19252
19253	remove( material ) {
19254
19255		const materialShaders = this.materialCache.get( material );
19256
19257		for ( const shaderStage of materialShaders ) {
19258
19259			shaderStage.usedTimes --;
19260
19261			if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code );
19262
19263		}
19264
19265		this.materialCache.delete( material );
19266
19267		return this;
19268
19269	}
19270
19271	getVertexShaderID( material ) {
19272
19273		return this._getShaderStage( material.vertexShader ).id;
19274
19275	}
19276
19277	getFragmentShaderID( material ) {
19278
19279		return this._getShaderStage( material.fragmentShader ).id;
19280
19281	}
19282
19283	dispose() {
19284
19285		this.shaderCache.clear();
19286		this.materialCache.clear();
19287
19288	}
19289
19290	_getShaderCacheForMaterial( material ) {
19291
19292		const cache = this.materialCache;
19293		let set = cache.get( material );
19294
19295		if ( set === undefined ) {
19296
19297			set = new Set();
19298			cache.set( material, set );
19299
19300		}
19301
19302		return set;
19303
19304	}
19305
19306	_getShaderStage( code ) {
19307
19308		const cache = this.shaderCache;
19309		let stage = cache.get( code );
19310
19311		if ( stage === undefined ) {
19312
19313			stage = new WebGLShaderStage( code );
19314			cache.set( code, stage );
19315
19316		}
19317
19318		return stage;
19319
19320	}
19321
19322}
19323
19324class WebGLShaderStage {
19325
19326	constructor( code ) {
19327
19328		this.id = _id ++;
19329
19330		this.code = code;
19331		this.usedTimes = 0;
19332
19333	}
19334
19335}
19336
19337function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) {
19338
19339	const _programLayers = new Layers();
19340	const _customShaders = new WebGLShaderCache();
19341	const programs = [];
19342
19343	const isWebGL2 = capabilities.isWebGL2;
19344	const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
19345	const vertexTextures = capabilities.vertexTextures;
19346	let precision = capabilities.precision;
19347
19348	const shaderIDs = {
19349		MeshDepthMaterial: 'depth',
19350		MeshDistanceMaterial: 'distanceRGBA',
19351		MeshNormalMaterial: 'normal',
19352		MeshBasicMaterial: 'basic',
19353		MeshLambertMaterial: 'lambert',
19354		MeshPhongMaterial: 'phong',
19355		MeshToonMaterial: 'toon',
19356		MeshStandardMaterial: 'physical',
19357		MeshPhysicalMaterial: 'physical',
19358		MeshMatcapMaterial: 'matcap',
19359		LineBasicMaterial: 'basic',
19360		LineDashedMaterial: 'dashed',
19361		PointsMaterial: 'points',
19362		ShadowMaterial: 'shadow',
19363		SpriteMaterial: 'sprite'
19364	};
19365
19366	function getParameters( material, lights, shadows, scene, object ) {
19367
19368		const fog = scene.fog;
19369		const geometry = object.geometry;
19370		const environment = material.isMeshStandardMaterial ? scene.environment : null;
19371
19372		const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
19373		const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null;
19374
19375		const shaderID = shaderIDs[ material.type ];
19376
19377		// heuristics to create shader parameters according to lights in the scene
19378		// (not to blow over maxLights budget)
19379
19380		if ( material.precision !== null ) {
19381
19382			precision = capabilities.getMaxPrecision( material.precision );
19383
19384			if ( precision !== material.precision ) {
19385
19386				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
19387
19388			}
19389
19390		}
19391
19392		//
19393
19394		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
19395		const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
19396
19397		let morphTextureStride = 0;
19398
19399		if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1;
19400		if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2;
19401		if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3;
19402
19403		//
19404
19405		let vertexShader, fragmentShader;
19406		let customVertexShaderID, customFragmentShaderID;
19407
19408		if ( shaderID ) {
19409
19410			const shader = ShaderLib[ shaderID ];
19411
19412			vertexShader = shader.vertexShader;
19413			fragmentShader = shader.fragmentShader;
19414
19415		} else {
19416
19417			vertexShader = material.vertexShader;
19418			fragmentShader = material.fragmentShader;
19419
19420			_customShaders.update( material );
19421
19422			customVertexShaderID = _customShaders.getVertexShaderID( material );
19423			customFragmentShaderID = _customShaders.getFragmentShaderID( material );
19424
19425		}
19426
19427		const currentRenderTarget = renderer.getRenderTarget();
19428
19429		const useAlphaTest = material.alphaTest > 0;
19430		const useClearcoat = material.clearcoat > 0;
19431		const useIridescence = material.iridescence > 0;
19432
19433		const parameters = {
19434
19435			isWebGL2: isWebGL2,
19436
19437			shaderID: shaderID,
19438			shaderName: material.type,
19439
19440			vertexShader: vertexShader,
19441			fragmentShader: fragmentShader,
19442			defines: material.defines,
19443
19444			customVertexShaderID: customVertexShaderID,
19445			customFragmentShaderID: customFragmentShaderID,
19446
19447			isRawShaderMaterial: material.isRawShaderMaterial === true,
19448			glslVersion: material.glslVersion,
19449
19450			precision: precision,
19451
19452			instancing: object.isInstancedMesh === true,
19453			instancingColor: object.isInstancedMesh === true && object.instanceColor !== null,
19454
19455			supportsVertexTextures: vertexTextures,
19456			outputEncoding: ( currentRenderTarget === null ) ? renderer.outputEncoding : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.encoding : LinearEncoding ),
19457			map: !! material.map,
19458			matcap: !! material.matcap,
19459			envMap: !! envMap,
19460			envMapMode: envMap && envMap.mapping,
19461			envMapCubeUVHeight: envMapCubeUVHeight,
19462			lightMap: !! material.lightMap,
19463			aoMap: !! material.aoMap,
19464			emissiveMap: !! material.emissiveMap,
19465			bumpMap: !! material.bumpMap,
19466			normalMap: !! material.normalMap,
19467			objectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,
19468			tangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,
19469
19470			decodeVideoTexture: !! material.map && ( material.map.isVideoTexture === true ) && ( material.map.encoding === sRGBEncoding ),
19471
19472			clearcoat: useClearcoat,
19473			clearcoatMap: useClearcoat && !! material.clearcoatMap,
19474			clearcoatRoughnessMap: useClearcoat && !! material.clearcoatRoughnessMap,
19475			clearcoatNormalMap: useClearcoat && !! material.clearcoatNormalMap,
19476
19477			iridescence: useIridescence,
19478			iridescenceMap: useIridescence && !! material.iridescenceMap,
19479			iridescenceThicknessMap: useIridescence && !! material.iridescenceThicknessMap,
19480
19481			displacementMap: !! material.displacementMap,
19482			roughnessMap: !! material.roughnessMap,
19483			metalnessMap: !! material.metalnessMap,
19484			specularMap: !! material.specularMap,
19485			specularIntensityMap: !! material.specularIntensityMap,
19486			specularColorMap: !! material.specularColorMap,
19487
19488			opaque: material.transparent === false && material.blending === NormalBlending,
19489
19490			alphaMap: !! material.alphaMap,
19491			alphaTest: useAlphaTest,
19492
19493			gradientMap: !! material.gradientMap,
19494
19495			sheen: material.sheen > 0,
19496			sheenColorMap: !! material.sheenColorMap,
19497			sheenRoughnessMap: !! material.sheenRoughnessMap,
19498
19499			transmission: material.transmission > 0,
19500			transmissionMap: !! material.transmissionMap,
19501			thicknessMap: !! material.thicknessMap,
19502
19503			combine: material.combine,
19504
19505			vertexTangents: ( !! material.normalMap && !! geometry.attributes.tangent ),
19506			vertexColors: material.vertexColors,
19507			vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4,
19508			vertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || !! material.displacementMap || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || !! material.sheenColorMap || !! material.sheenRoughnessMap,
19509			uvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.iridescenceMap || !! material.iridescenceThicknessMap || material.transmission > 0 || !! material.transmissionMap || !! material.thicknessMap || !! material.specularIntensityMap || !! material.specularColorMap || material.sheen > 0 || !! material.sheenColorMap || !! material.sheenRoughnessMap ) && !! material.displacementMap,
19510
19511			fog: !! fog,
19512			useFog: material.fog === true,
19513			fogExp2: ( fog && fog.isFogExp2 ),
19514
19515			flatShading: !! material.flatShading,
19516
19517			sizeAttenuation: material.sizeAttenuation,
19518			logarithmicDepthBuffer: logarithmicDepthBuffer,
19519
19520			skinning: object.isSkinnedMesh === true,
19521
19522			morphTargets: geometry.morphAttributes.position !== undefined,
19523			morphNormals: geometry.morphAttributes.normal !== undefined,
19524			morphColors: geometry.morphAttributes.color !== undefined,
19525			morphTargetsCount: morphTargetsCount,
19526			morphTextureStride: morphTextureStride,
19527
19528			numDirLights: lights.directional.length,
19529			numPointLights: lights.point.length,
19530			numSpotLights: lights.spot.length,
19531			numSpotLightMaps: lights.spotLightMap.length,
19532			numRectAreaLights: lights.rectArea.length,
19533			numHemiLights: lights.hemi.length,
19534
19535			numDirLightShadows: lights.directionalShadowMap.length,
19536			numPointLightShadows: lights.pointShadowMap.length,
19537			numSpotLightShadows: lights.spotShadowMap.length,
19538			numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps,
19539
19540			numClippingPlanes: clipping.numPlanes,
19541			numClipIntersection: clipping.numIntersection,
19542
19543			dithering: material.dithering,
19544
19545			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
19546			shadowMapType: renderer.shadowMap.type,
19547
19548			toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
19549			useLegacyLights: renderer.useLegacyLights,
19550
19551			premultipliedAlpha: material.premultipliedAlpha,
19552
19553			doubleSided: material.side === DoubleSide,
19554			flipSided: material.side === BackSide,
19555
19556			useDepthPacking: !! material.depthPacking,
19557			depthPacking: material.depthPacking || 0,
19558
19559			index0AttributeName: material.index0AttributeName,
19560
19561			extensionDerivatives: material.extensions && material.extensions.derivatives,
19562			extensionFragDepth: material.extensions && material.extensions.fragDepth,
19563			extensionDrawBuffers: material.extensions && material.extensions.drawBuffers,
19564			extensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,
19565
19566			rendererExtensionFragDepth: isWebGL2 || extensions.has( 'EXT_frag_depth' ),
19567			rendererExtensionDrawBuffers: isWebGL2 || extensions.has( 'WEBGL_draw_buffers' ),
19568			rendererExtensionShaderTextureLod: isWebGL2 || extensions.has( 'EXT_shader_texture_lod' ),
19569
19570			customProgramCacheKey: material.customProgramCacheKey()
19571
19572		};
19573
19574		return parameters;
19575
19576	}
19577
19578	function getProgramCacheKey( parameters ) {
19579
19580		const array = [];
19581
19582		if ( parameters.shaderID ) {
19583
19584			array.push( parameters.shaderID );
19585
19586		} else {
19587
19588			array.push( parameters.customVertexShaderID );
19589			array.push( parameters.customFragmentShaderID );
19590
19591		}
19592
19593		if ( parameters.defines !== undefined ) {
19594
19595			for ( const name in parameters.defines ) {
19596
19597				array.push( name );
19598				array.push( parameters.defines[ name ] );
19599
19600			}
19601
19602		}
19603
19604		if ( parameters.isRawShaderMaterial === false ) {
19605
19606			getProgramCacheKeyParameters( array, parameters );
19607			getProgramCacheKeyBooleans( array, parameters );
19608			array.push( renderer.outputEncoding );
19609
19610		}
19611
19612		array.push( parameters.customProgramCacheKey );
19613
19614		return array.join();
19615
19616	}
19617
19618	function getProgramCacheKeyParameters( array, parameters ) {
19619
19620		array.push( parameters.precision );
19621		array.push( parameters.outputEncoding );
19622		array.push( parameters.envMapMode );
19623		array.push( parameters.envMapCubeUVHeight );
19624		array.push( parameters.combine );
19625		array.push( parameters.vertexUvs );
19626		array.push( parameters.fogExp2 );
19627		array.push( parameters.sizeAttenuation );
19628		array.push( parameters.morphTargetsCount );
19629		array.push( parameters.morphAttributeCount );
19630		array.push( parameters.numDirLights );
19631		array.push( parameters.numPointLights );
19632		array.push( parameters.numSpotLights );
19633		array.push( parameters.numSpotLightMaps );
19634		array.push( parameters.numHemiLights );
19635		array.push( parameters.numRectAreaLights );
19636		array.push( parameters.numDirLightShadows );
19637		array.push( parameters.numPointLightShadows );
19638		array.push( parameters.numSpotLightShadows );
19639		array.push( parameters.numSpotLightShadowsWithMaps );
19640		array.push( parameters.shadowMapType );
19641		array.push( parameters.toneMapping );
19642		array.push( parameters.numClippingPlanes );
19643		array.push( parameters.numClipIntersection );
19644		array.push( parameters.depthPacking );
19645
19646	}
19647
19648	function getProgramCacheKeyBooleans( array, parameters ) {
19649
19650		_programLayers.disableAll();
19651
19652		if ( parameters.isWebGL2 )
19653			_programLayers.enable( 0 );
19654		if ( parameters.supportsVertexTextures )
19655			_programLayers.enable( 1 );
19656		if ( parameters.instancing )
19657			_programLayers.enable( 2 );
19658		if ( parameters.instancingColor )
19659			_programLayers.enable( 3 );
19660		if ( parameters.map )
19661			_programLayers.enable( 4 );
vendor: 5,121 bytes, lines 19662-19864
19662		if ( parameters.matcap )
19663			_programLayers.enable( 5 );
19664		if ( parameters.envMap )
19665			_programLayers.enable( 6 );
19666		if ( parameters.lightMap )
19667			_programLayers.enable( 7 );
19668		if ( parameters.aoMap )
19669			_programLayers.enable( 8 );
19670		if ( parameters.emissiveMap )
19671			_programLayers.enable( 9 );
19672		if ( parameters.bumpMap )
19673			_programLayers.enable( 10 );
19674		if ( parameters.normalMap )
19675			_programLayers.enable( 11 );
19676		if ( parameters.objectSpaceNormalMap )
19677			_programLayers.enable( 12 );
19678		if ( parameters.tangentSpaceNormalMap )
19679			_programLayers.enable( 13 );
19680		if ( parameters.clearcoat )
19681			_programLayers.enable( 14 );
19682		if ( parameters.clearcoatMap )
19683			_programLayers.enable( 15 );
19684		if ( parameters.clearcoatRoughnessMap )
19685			_programLayers.enable( 16 );
19686		if ( parameters.clearcoatNormalMap )
19687			_programLayers.enable( 17 );
19688		if ( parameters.iridescence )
19689			_programLayers.enable( 18 );
19690		if ( parameters.iridescenceMap )
19691			_programLayers.enable( 19 );
19692		if ( parameters.iridescenceThicknessMap )
19693			_programLayers.enable( 20 );
19694		if ( parameters.displacementMap )
19695			_programLayers.enable( 21 );
19696		if ( parameters.specularMap )
19697			_programLayers.enable( 22 );
19698		if ( parameters.roughnessMap )
19699			_programLayers.enable( 23 );
19700		if ( parameters.metalnessMap )
19701			_programLayers.enable( 24 );
19702		if ( parameters.gradientMap )
19703			_programLayers.enable( 25 );
19704		if ( parameters.alphaMap )
19705			_programLayers.enable( 26 );
19706		if ( parameters.alphaTest )
19707			_programLayers.enable( 27 );
19708		if ( parameters.vertexColors )
19709			_programLayers.enable( 28 );
19710		if ( parameters.vertexAlphas )
19711			_programLayers.enable( 29 );
19712		if ( parameters.vertexUvs )
19713			_programLayers.enable( 30 );
19714		if ( parameters.vertexTangents )
19715			_programLayers.enable( 31 );
19716		if ( parameters.uvsVertexOnly )
19717			_programLayers.enable( 32 );
19718
19719		array.push( _programLayers.mask );
19720		_programLayers.disableAll();
19721
19722		if ( parameters.fog )
19723			_programLayers.enable( 0 );
19724		if ( parameters.useFog )
19725			_programLayers.enable( 1 );
19726		if ( parameters.flatShading )
19727			_programLayers.enable( 2 );
19728		if ( parameters.logarithmicDepthBuffer )
19729			_programLayers.enable( 3 );
19730		if ( parameters.skinning )
19731			_programLayers.enable( 4 );
19732		if ( parameters.morphTargets )
19733			_programLayers.enable( 5 );
19734		if ( parameters.morphNormals )
19735			_programLayers.enable( 6 );
19736		if ( parameters.morphColors )
19737			_programLayers.enable( 7 );
19738		if ( parameters.premultipliedAlpha )
19739			_programLayers.enable( 8 );
19740		if ( parameters.shadowMapEnabled )
19741			_programLayers.enable( 9 );
19742		if ( parameters.useLegacyLights )
19743			_programLayers.enable( 10 );
19744		if ( parameters.doubleSided )
19745			_programLayers.enable( 11 );
19746		if ( parameters.flipSided )
19747			_programLayers.enable( 12 );
19748		if ( parameters.useDepthPacking )
19749			_programLayers.enable( 13 );
19750		if ( parameters.dithering )
19751			_programLayers.enable( 14 );
19752		if ( parameters.specularIntensityMap )
19753			_programLayers.enable( 15 );
19754		if ( parameters.specularColorMap )
19755			_programLayers.enable( 16 );
19756		if ( parameters.transmission )
19757			_programLayers.enable( 17 );
19758		if ( parameters.transmissionMap )
19759			_programLayers.enable( 18 );
19760		if ( parameters.thicknessMap )
19761			_programLayers.enable( 19 );
19762		if ( parameters.sheen )
19763			_programLayers.enable( 20 );
19764		if ( parameters.sheenColorMap )
19765			_programLayers.enable( 21 );
19766		if ( parameters.sheenRoughnessMap )
19767			_programLayers.enable( 22 );
19768		if ( parameters.decodeVideoTexture )
19769			_programLayers.enable( 23 );
19770		if ( parameters.opaque )
19771			_programLayers.enable( 24 );
19772
19773		array.push( _programLayers.mask );
19774
19775	}
19776
19777	function getUniforms( material ) {
19778
19779		const shaderID = shaderIDs[ material.type ];
19780		let uniforms;
19781
19782		if ( shaderID ) {
19783
19784			const shader = ShaderLib[ shaderID ];
19785			uniforms = UniformsUtils.clone( shader.uniforms );
19786
19787		} else {
19788
19789			uniforms = material.uniforms;
19790
19791		}
19792
19793		return uniforms;
19794
19795	}
19796
19797	function acquireProgram( parameters, cacheKey ) {
19798
19799		let program;
19800
19801		// Check if code has been already compiled
19802		for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
19803
19804			const preexistingProgram = programs[ p ];
19805
19806			if ( preexistingProgram.cacheKey === cacheKey ) {
19807
19808				program = preexistingProgram;
19809				++ program.usedTimes;
19810
19811				break;
19812
19813			}
19814
19815		}
19816
19817		if ( program === undefined ) {
19818
19819			program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
19820			programs.push( program );
19821
19822		}
19823
19824		return program;
19825
19826	}
19827
19828	function releaseProgram( program ) {
19829
19830		if ( -- program.usedTimes === 0 ) {
19831
19832			// Remove from unordered set
19833			const i = programs.indexOf( program );
19834			programs[ i ] = programs[ programs.length - 1 ];
19835			programs.pop();
19836
19837			// Free WebGL resources
19838			program.destroy();
19839
19840		}
19841
19842	}
19843
19844	function releaseShaderCache( material ) {
19845
19846		_customShaders.remove( material );
19847
19848	}
19849
19850	function dispose() {
19851
19852		_customShaders.dispose();
19853
19854	}
19855
19856	return {
19857		getParameters: getParameters,
19858		getProgramCacheKey: getProgramCacheKey,
19859		getUniforms: getUniforms,
19860		acquireProgram: acquireProgram,
19861		releaseProgram: releaseProgram,
19862		releaseShaderCache: releaseShaderCache,
19863		// Exposed for resource monitoring & error feedback via renderer.info:
19864		programs: programs,
vendor: 4,538 bytes, lines 19865-20146
19865		dispose: dispose
19866	};
19867
19868}
19869
19870function WebGLProperties() {
19871
19872	let properties = new WeakMap();
19873
19874	function get( object ) {
19875
19876		let map = properties.get( object );
19877
19878		if ( map === undefined ) {
19879
19880			map = {};
19881			properties.set( object, map );
19882
19883		}
19884
19885		return map;
19886
19887	}
19888
19889	function remove( object ) {
19890
19891		properties.delete( object );
19892
19893	}
19894
19895	function update( object, key, value ) {
19896
19897		properties.get( object )[ key ] = value;
19898
19899	}
19900
19901	function dispose() {
19902
19903		properties = new WeakMap();
19904
19905	}
19906
19907	return {
19908		get: get,
19909		remove: remove,
19910		update: update,
19911		dispose: dispose
19912	};
19913
19914}
19915
19916function painterSortStable( a, b ) {
19917
19918	if ( a.groupOrder !== b.groupOrder ) {
19919
19920		return a.groupOrder - b.groupOrder;
19921
19922	} else if ( a.renderOrder !== b.renderOrder ) {
19923
19924		return a.renderOrder - b.renderOrder;
19925
19926	} else if ( a.material.id !== b.material.id ) {
19927
19928		return a.material.id - b.material.id;
19929
19930	} else if ( a.z !== b.z ) {
19931
19932		return a.z - b.z;
19933
19934	} else {
19935
19936		return a.id - b.id;
19937
19938	}
19939
19940}
19941
19942function reversePainterSortStable( a, b ) {
19943
19944	if ( a.groupOrder !== b.groupOrder ) {
19945
19946		return a.groupOrder - b.groupOrder;
19947
19948	} else if ( a.renderOrder !== b.renderOrder ) {
19949
19950		return a.renderOrder - b.renderOrder;
19951
19952	} else if ( a.z !== b.z ) {
19953
19954		return b.z - a.z;
19955
19956	} else {
19957
19958		return a.id - b.id;
19959
19960	}
19961
19962}
19963
19964
19965function WebGLRenderList() {
19966
19967	const renderItems = [];
19968	let renderItemsIndex = 0;
19969
19970	const opaque = [];
19971	const transmissive = [];
19972	const transparent = [];
19973
19974	function init() {
19975
19976		renderItemsIndex = 0;
19977
19978		opaque.length = 0;
19979		transmissive.length = 0;
19980		transparent.length = 0;
19981
19982	}
19983
19984	function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
19985
19986		let renderItem = renderItems[ renderItemsIndex ];
19987
19988		if ( renderItem === undefined ) {
19989
19990			renderItem = {
19991				id: object.id,
19992				object: object,
19993				geometry: geometry,
19994				material: material,
19995				groupOrder: groupOrder,
19996				renderOrder: object.renderOrder,
19997				z: z,
19998				group: group
19999			};
20000
20001			renderItems[ renderItemsIndex ] = renderItem;
20002
20003		} else {
20004
20005			renderItem.id = object.id;
20006			renderItem.object = object;
20007			renderItem.geometry = geometry;
20008			renderItem.material = material;
20009			renderItem.groupOrder = groupOrder;
20010			renderItem.renderOrder = object.renderOrder;
20011			renderItem.z = z;
20012			renderItem.group = group;
20013
20014		}
20015
20016		renderItemsIndex ++;
20017
20018		return renderItem;
20019
20020	}
20021
20022	function push( object, geometry, material, groupOrder, z, group ) {
20023
20024		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
20025
20026		if ( material.transmission > 0.0 ) {
20027
20028			transmissive.push( renderItem );
20029
20030		} else if ( material.transparent === true ) {
20031
20032			transparent.push( renderItem );
20033
20034		} else {
20035
20036			opaque.push( renderItem );
20037
20038		}
20039
20040	}
20041
20042	function unshift( object, geometry, material, groupOrder, z, group ) {
20043
20044		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
20045
20046		if ( material.transmission > 0.0 ) {
20047
20048			transmissive.unshift( renderItem );
20049
20050		} else if ( material.transparent === true ) {
20051
20052			transparent.unshift( renderItem );
20053
20054		} else {
20055
20056			opaque.unshift( renderItem );
20057
20058		}
20059
20060	}
20061
20062	function sort( customOpaqueSort, customTransparentSort ) {
20063
20064		if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
20065		if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
20066		if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
20067
20068	}
20069
20070	function finish() {
20071
20072		// Clear references from inactive renderItems in the list
20073
20074		for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
20075
20076			const renderItem = renderItems[ i ];
20077
20078			if ( renderItem.id === null ) break;
20079
20080			renderItem.id = null;
20081			renderItem.object = null;
20082			renderItem.geometry = null;
20083			renderItem.material = null;
20084			renderItem.group = null;
20085
20086		}
20087
20088	}
20089
20090	return {
20091
20092		opaque: opaque,
20093		transmissive: transmissive,
20094		transparent: transparent,
20095
20096		init: init,
20097		push: push,
20098		unshift: unshift,
20099		finish: finish,
20100
20101		sort: sort
20102	};
20103
20104}
20105
20106function WebGLRenderLists() {
20107
20108	let lists = new WeakMap();
20109
20110	function get( scene, renderCallDepth ) {
20111
20112		const listArray = lists.get( scene );
20113		let list;
20114
20115		if ( listArray === undefined ) {
20116
20117			list = new WebGLRenderList();
20118			lists.set( scene, [ list ] );
20119
20120		} else {
20121
20122			if ( renderCallDepth >= listArray.length ) {
20123
20124				list = new WebGLRenderList();
20125				listArray.push( list );
20126
20127			} else {
20128
20129				list = listArray[ renderCallDepth ];
20130
20131			}
20132
20133		}
20134
20135		return list;
20136
20137	}
20138
20139	function dispose() {
20140
20141		lists = new WeakMap();
20142
20143	}
20144
20145	return {
20146		get: get,
vendor: 10,755 bytes, lines 20147-20614
20147		dispose: dispose
20148	};
20149
20150}
20151
20152function UniformsCache() {
20153
20154	const lights = {};
20155
20156	return {
20157
20158		get: function ( light ) {
20159
20160			if ( lights[ light.id ] !== undefined ) {
20161
20162				return lights[ light.id ];
20163
20164			}
20165
20166			let uniforms;
20167
20168			switch ( light.type ) {
20169
20170				case 'DirectionalLight':
20171					uniforms = {
20172						direction: new Vector3(),
20173						color: new Color()
20174					};
20175					break;
20176
20177				case 'SpotLight':
20178					uniforms = {
20179						position: new Vector3(),
20180						direction: new Vector3(),
20181						color: new Color(),
20182						distance: 0,
20183						coneCos: 0,
20184						penumbraCos: 0,
20185						decay: 0
20186					};
20187					break;
20188
20189				case 'PointLight':
20190					uniforms = {
20191						position: new Vector3(),
20192						color: new Color(),
20193						distance: 0,
20194						decay: 0
20195					};
20196					break;
20197
20198				case 'HemisphereLight':
20199					uniforms = {
20200						direction: new Vector3(),
20201						skyColor: new Color(),
20202						groundColor: new Color()
20203					};
20204					break;
20205
20206				case 'RectAreaLight':
20207					uniforms = {
20208						color: new Color(),
20209						position: new Vector3(),
20210						halfWidth: new Vector3(),
20211						halfHeight: new Vector3()
20212					};
20213					break;
20214
20215			}
20216
20217			lights[ light.id ] = uniforms;
20218
20219			return uniforms;
20220
20221		}
20222
20223	};
20224
20225}
20226
20227function ShadowUniformsCache() {
20228
20229	const lights = {};
20230
20231	return {
20232
20233		get: function ( light ) {
20234
20235			if ( lights[ light.id ] !== undefined ) {
20236
20237				return lights[ light.id ];
20238
20239			}
20240
20241			let uniforms;
20242
20243			switch ( light.type ) {
20244
20245				case 'DirectionalLight':
20246					uniforms = {
20247						shadowBias: 0,
20248						shadowNormalBias: 0,
20249						shadowRadius: 1,
20250						shadowMapSize: new Vector2()
20251					};
20252					break;
20253
20254				case 'SpotLight':
20255					uniforms = {
20256						shadowBias: 0,
20257						shadowNormalBias: 0,
20258						shadowRadius: 1,
20259						shadowMapSize: new Vector2()
20260					};
20261					break;
20262
20263				case 'PointLight':
20264					uniforms = {
20265						shadowBias: 0,
20266						shadowNormalBias: 0,
20267						shadowRadius: 1,
20268						shadowMapSize: new Vector2(),
20269						shadowCameraNear: 1,
20270						shadowCameraFar: 1000
20271					};
20272					break;
20273
20274				// TODO (abelnation): set RectAreaLight shadow uniforms
20275
20276			}
20277
20278			lights[ light.id ] = uniforms;
20279
20280			return uniforms;
20281
20282		}
20283
20284	};
20285
20286}
20287
20288
20289
20290let nextVersion = 0;
20291
20292function shadowCastingAndTexturingLightsFirst( lightA, lightB ) {
20293
20294	return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 );
20295
20296}
20297
20298function WebGLLights( extensions, capabilities ) {
20299
20300	const cache = new UniformsCache();
20301
20302	const shadowCache = ShadowUniformsCache();
20303
20304	const state = {
20305
20306		version: 0,
20307
20308		hash: {
20309			directionalLength: - 1,
20310			pointLength: - 1,
20311			spotLength: - 1,
20312			rectAreaLength: - 1,
20313			hemiLength: - 1,
20314
20315			numDirectionalShadows: - 1,
20316			numPointShadows: - 1,
20317			numSpotShadows: - 1,
20318			numSpotMaps: - 1
20319		},
20320
20321		ambient: [ 0, 0, 0 ],
20322		probe: [],
20323		directional: [],
20324		directionalShadow: [],
20325		directionalShadowMap: [],
20326		directionalShadowMatrix: [],
20327		spot: [],
20328		spotLightMap: [],
20329		spotShadow: [],
20330		spotShadowMap: [],
20331		spotLightMatrix: [],
20332		rectArea: [],
20333		rectAreaLTC1: null,
20334		rectAreaLTC2: null,
20335		point: [],
20336		pointShadow: [],
20337		pointShadowMap: [],
20338		pointShadowMatrix: [],
20339		hemi: [],
20340		numSpotLightShadowsWithMaps: 0
20341
20342	};
20343
20344	for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
20345
20346	const vector3 = new Vector3();
20347	const matrix4 = new Matrix4();
20348	const matrix42 = new Matrix4();
20349
20350	function setup( lights, useLegacyLights ) {
20351
20352		let r = 0, g = 0, b = 0;
20353
20354		for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
20355
20356		let directionalLength = 0;
20357		let pointLength = 0;
20358		let spotLength = 0;
20359		let rectAreaLength = 0;
20360		let hemiLength = 0;
20361
20362		let numDirectionalShadows = 0;
20363		let numPointShadows = 0;
20364		let numSpotShadows = 0;
20365		let numSpotMaps = 0;
20366		let numSpotShadowsWithMaps = 0;
20367
20368		// ordering : [shadow casting + map texturing, map texturing, shadow casting, none ]
20369		lights.sort( shadowCastingAndTexturingLightsFirst );
20370
20371		// artist-friendly light intensity scaling factor
20372		const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1;
20373
20374		for ( let i = 0, l = lights.length; i < l; i ++ ) {
20375
20376			const light = lights[ i ];
20377
20378			const color = light.color;
20379			const intensity = light.intensity;
20380			const distance = light.distance;
20381
20382			const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
20383
20384			if ( light.isAmbientLight ) {
20385
20386				r += color.r * intensity * scaleFactor;
20387				g += color.g * intensity * scaleFactor;
20388				b += color.b * intensity * scaleFactor;
20389
20390			} else if ( light.isLightProbe ) {
20391
20392				for ( let j = 0; j < 9; j ++ ) {
20393
20394					state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
20395
20396				}
20397
20398			} else if ( light.isDirectionalLight ) {
20399
20400				const uniforms = cache.get( light );
20401
20402				uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
20403
20404				if ( light.castShadow ) {
20405
20406					const shadow = light.shadow;
20407
20408					const shadowUniforms = shadowCache.get( light );
20409
20410					shadowUniforms.shadowBias = shadow.bias;
20411					shadowUniforms.shadowNormalBias = shadow.normalBias;
20412					shadowUniforms.shadowRadius = shadow.radius;
20413					shadowUniforms.shadowMapSize = shadow.mapSize;
20414
20415					state.directionalShadow[ directionalLength ] = shadowUniforms;
20416					state.directionalShadowMap[ directionalLength ] = shadowMap;
20417					state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
20418
20419					numDirectionalShadows ++;
20420
20421				}
20422
20423				state.directional[ directionalLength ] = uniforms;
20424
20425				directionalLength ++;
20426
20427			} else if ( light.isSpotLight ) {
20428
20429				const uniforms = cache.get( light );
20430
20431				uniforms.position.setFromMatrixPosition( light.matrixWorld );
20432
20433				uniforms.color.copy( color ).multiplyScalar( intensity * scaleFactor );
20434				uniforms.distance = distance;
20435
20436				uniforms.coneCos = Math.cos( light.angle );
20437				uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
20438				uniforms.decay = light.decay;
20439
20440				state.spot[ spotLength ] = uniforms;
20441
20442				const shadow = light.shadow;
20443
20444				if ( light.map ) {
20445
20446					state.spotLightMap[ numSpotMaps ] = light.map;
20447					numSpotMaps ++;
20448
20449					// make sure the lightMatrix is up to date
20450					// TODO : do it if required only
20451					shadow.updateMatrices( light );
20452
20453					if ( light.castShadow ) numSpotShadowsWithMaps ++;
20454
20455				}
20456
20457				state.spotLightMatrix[ spotLength ] = shadow.matrix;
20458
20459				if ( light.castShadow ) {
20460
20461					const shadowUniforms = shadowCache.get( light );
20462
20463					shadowUniforms.shadowBias = shadow.bias;
20464					shadowUniforms.shadowNormalBias = shadow.normalBias;
20465					shadowUniforms.shadowRadius = shadow.radius;
20466					shadowUniforms.shadowMapSize = shadow.mapSize;
20467
20468					state.spotShadow[ spotLength ] = shadowUniforms;
20469					state.spotShadowMap[ spotLength ] = shadowMap;
20470
20471					numSpotShadows ++;
20472
20473				}
20474
20475				spotLength ++;
20476
20477			} else if ( light.isRectAreaLight ) {
20478
20479				const uniforms = cache.get( light );
20480
20481				uniforms.color.copy( color ).multiplyScalar( intensity );
20482
20483				uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
20484				uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
20485
20486				state.rectArea[ rectAreaLength ] = uniforms;
20487
20488				rectAreaLength ++;
20489
20490			} else if ( light.isPointLight ) {
20491
20492				const uniforms = cache.get( light );
20493
20494				uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
20495				uniforms.distance = light.distance;
20496				uniforms.decay = light.decay;
20497
20498				if ( light.castShadow ) {
20499
20500					const shadow = light.shadow;
20501
20502					const shadowUniforms = shadowCache.get( light );
20503
20504					shadowUniforms.shadowBias = shadow.bias;
20505					shadowUniforms.shadowNormalBias = shadow.normalBias;
20506					shadowUniforms.shadowRadius = shadow.radius;
20507					shadowUniforms.shadowMapSize = shadow.mapSize;
20508					shadowUniforms.shadowCameraNear = shadow.camera.near;
20509					shadowUniforms.shadowCameraFar = shadow.camera.far;
20510
20511					state.pointShadow[ pointLength ] = shadowUniforms;
20512					state.pointShadowMap[ pointLength ] = shadowMap;
20513					state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
20514
20515					numPointShadows ++;
20516
20517				}
20518
20519				state.point[ pointLength ] = uniforms;
20520
20521				pointLength ++;
20522
20523			} else if ( light.isHemisphereLight ) {
20524
20525				const uniforms = cache.get( light );
20526
20527				uniforms.skyColor.copy( light.color ).multiplyScalar( intensity * scaleFactor );
20528				uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity * scaleFactor );
20529
20530				state.hemi[ hemiLength ] = uniforms;
20531
20532				hemiLength ++;
20533
20534			}
20535
20536		}
20537
20538		if ( rectAreaLength > 0 ) {
20539
20540			if ( capabilities.isWebGL2 ) {
20541
20542				// WebGL 2
20543
20544				state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
20545				state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
20546
20547			} else {
20548
20549				// WebGL 1
20550
20551				if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
20552
20553					state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
20554					state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
20555
20556				} else if ( extensions.has( 'OES_texture_half_float_linear' ) === true ) {
20557
20558					state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
20559					state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
20560
20561				} else {
20562
20563					console.error( 'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' );
20564
20565				}
20566
20567			}
20568
20569		}
20570
20571		state.ambient[ 0 ] = r;
20572		state.ambient[ 1 ] = g;
20573		state.ambient[ 2 ] = b;
20574
20575		const hash = state.hash;
20576
20577		if ( hash.directionalLength !== directionalLength ||
20578			hash.pointLength !== pointLength ||
20579			hash.spotLength !== spotLength ||
20580			hash.rectAreaLength !== rectAreaLength ||
20581			hash.hemiLength !== hemiLength ||
20582			hash.numDirectionalShadows !== numDirectionalShadows ||
20583			hash.numPointShadows !== numPointShadows ||
20584			hash.numSpotShadows !== numSpotShadows ||
20585			hash.numSpotMaps !== numSpotMaps ) {
20586
20587			state.directional.length = directionalLength;
20588			state.spot.length = spotLength;
20589			state.rectArea.length = rectAreaLength;
20590			state.point.length = pointLength;
20591			state.hemi.length = hemiLength;
20592
20593			state.directionalShadow.length = numDirectionalShadows;
20594			state.directionalShadowMap.length = numDirectionalShadows;
20595			state.pointShadow.length = numPointShadows;
20596			state.pointShadowMap.length = numPointShadows;
20597			state.spotShadow.length = numSpotShadows;
20598			state.spotShadowMap.length = numSpotShadows;
20599			state.directionalShadowMatrix.length = numDirectionalShadows;
20600			state.pointShadowMatrix.length = numPointShadows;
20601			state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps;
20602			state.spotLightMap.length = numSpotMaps;
20603			state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps;
20604
20605			hash.directionalLength = directionalLength;
20606			hash.pointLength = pointLength;
20607			hash.spotLength = spotLength;
20608			hash.rectAreaLength = rectAreaLength;
20609			hash.hemiLength = hemiLength;
20610
20611			hash.numDirectionalShadows = numDirectionalShadows;
20612			hash.numPointShadows = numPointShadows;
20613			hash.numSpotShadows = numSpotShadows;
20614			hash.numSpotMaps = numSpotMap
vendor: 5,016 bytes, lines 20614-20877
20614s;
20615
20616			state.version = nextVersion ++;
20617
20618		}
20619
20620	}
20621
20622	function setupView( lights, camera ) {
20623
20624		let directionalLength = 0;
20625		let pointLength = 0;
20626		let spotLength = 0;
20627		let rectAreaLength = 0;
20628		let hemiLength = 0;
20629
20630		const viewMatrix = camera.matrixWorldInverse;
20631
20632		for ( let i = 0, l = lights.length; i < l; i ++ ) {
20633
20634			const light = lights[ i ];
20635
20636			if ( light.isDirectionalLight ) {
20637
20638				const uniforms = state.directional[ directionalLength ];
20639
20640				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
20641				vector3.setFromMatrixPosition( light.target.matrixWorld );
20642				uniforms.direction.sub( vector3 );
20643				uniforms.direction.transformDirection( viewMatrix );
20644
20645				directionalLength ++;
20646
20647			} else if ( light.isSpotLight ) {
20648
20649				const uniforms = state.spot[ spotLength ];
20650
20651				uniforms.position.setFromMatrixPosition( light.matrixWorld );
20652				uniforms.position.applyMatrix4( viewMatrix );
20653
20654				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
20655				vector3.setFromMatrixPosition( light.target.matrixWorld );
20656				uniforms.direction.sub( vector3 );
20657				uniforms.direction.transformDirection( viewMatrix );
20658
20659				spotLength ++;
20660
20661			} else if ( light.isRectAreaLight ) {
20662
20663				const uniforms = state.rectArea[ rectAreaLength ];
20664
20665				uniforms.position.setFromMatrixPosition( light.matrixWorld );
20666				uniforms.position.applyMatrix4( viewMatrix );
20667
20668				// extract local rotation of light to derive width/height half vectors
20669				matrix42.identity();
20670				matrix4.copy( light.matrixWorld );
20671				matrix4.premultiply( viewMatrix );
20672				matrix42.extractRotation( matrix4 );
20673
20674				uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
20675				uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
20676
20677				uniforms.halfWidth.applyMatrix4( matrix42 );
20678				uniforms.halfHeight.applyMatrix4( matrix42 );
20679
20680				rectAreaLength ++;
20681
20682			} else if ( light.isPointLight ) {
20683
20684				const uniforms = state.point[ pointLength ];
20685
20686				uniforms.position.setFromMatrixPosition( light.matrixWorld );
20687				uniforms.position.applyMatrix4( viewMatrix );
20688
20689				pointLength ++;
20690
20691			} else if ( light.isHemisphereLight ) {
20692
20693				const uniforms = state.hemi[ hemiLength ];
20694
20695				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
20696				uniforms.direction.transformDirection( viewMatrix );
20697
20698				hemiLength ++;
20699
20700			}
20701
20702		}
20703
20704	}
20705
20706	return {
20707		setup: setup,
20708		setupView: setupView,
20709		state: state
20710	};
20711
20712}
20713
20714function WebGLRenderState( extensions, capabilities ) {
20715
20716	const lights = new WebGLLights( extensions, capabilities );
20717
20718	const lightsArray = [];
20719	const shadowsArray = [];
20720
20721	function init() {
20722
20723		lightsArray.length = 0;
20724		shadowsArray.length = 0;
20725
20726	}
20727
20728	function pushLight( light ) {
20729
20730		lightsArray.push( light );
20731
20732	}
20733
20734	function pushShadow( shadowLight ) {
20735
20736		shadowsArray.push( shadowLight );
20737
20738	}
20739
20740	function setupLights( useLegacyLights ) {
20741
20742		lights.setup( lightsArray, useLegacyLights );
20743
20744	}
20745
20746	function setupLightsView( camera ) {
20747
20748		lights.setupView( lightsArray, camera );
20749
20750	}
20751
20752	const state = {
20753		lightsArray: lightsArray,
20754		shadowsArray: shadowsArray,
20755
20756		lights: lights
20757	};
20758
20759	return {
20760		init: init,
20761		state: state,
20762		setupLights: setupLights,
20763		setupLightsView: setupLightsView,
20764
20765		pushLight: pushLight,
20766		pushShadow: pushShadow
20767	};
20768
20769}
20770
20771function WebGLRenderStates( extensions, capabilities ) {
20772
20773	let renderStates = new WeakMap();
20774
20775	function get( scene, renderCallDepth = 0 ) {
20776
20777		const renderStateArray = renderStates.get( scene );
20778		let renderState;
20779
20780		if ( renderStateArray === undefined ) {
20781
20782			renderState = new WebGLRenderState( extensions, capabilities );
20783			renderStates.set( scene, [ renderState ] );
20784
20785		} else {
20786
20787			if ( renderCallDepth >= renderStateArray.length ) {
20788
20789				renderState = new WebGLRenderState( extensions, capabilities );
20790				renderStateArray.push( renderState );
20791
20792			} else {
20793
20794				renderState = renderStateArray[ renderCallDepth ];
20795
20796			}
20797
20798		}
20799
20800		return renderState;
20801
20802	}
20803
20804	function dispose() {
20805
20806		renderStates = new WeakMap();
20807
20808	}
20809
20810	return {
20811		get: get,
20812		dispose: dispose
20813	};
20814
20815}
20816
20817class MeshDepthMaterial extends Material {
20818
20819	constructor( parameters ) {
20820
20821		super();
20822
20823		this.isMeshDepthMaterial = true;
20824
20825		this.type = 'MeshDepthMaterial';
20826
20827		this.depthPacking = BasicDepthPacking;
20828
20829		this.map = null;
20830
20831		this.alphaMap = null;
20832
20833		this.displacementMap = null;
20834		this.displacementScale = 1;
20835		this.displacementBias = 0;
20836
20837		this.wireframe = false;
20838		this.wireframeLinewidth = 1;
20839
20840		this.setValues( parameters );
20841
20842	}
20843
20844	copy( source ) {
20845
20846		super.copy( source );
20847
20848		this.depthPacking = source.depthPacking;
20849
20850		this.map = source.map;
20851
20852		this.alphaMap = source.alphaMap;
20853
20854		this.displacementMap = source.displacementMap;
20855		this.displacementScale = source.displacementScale;
20856		this.displacementBias = source.displacementBias;
20857
20858		this.wireframe = source.wireframe;
20859		this.wireframeLinewidth = source.wireframeLinewidth;
20860
20861		return this;
20862
20863	}
20864
20865}
20866
20867class MeshDistanceMaterial extends Material {
20868
20869	constructor( parameters ) {
20870
20871		super();
20872
20873		this.isMeshDistanceMaterial = true;
20874
20875		this.type = 'MeshDistanceMaterial';
20876
20877		this.
vendor: 6,012 bytes, lines 20877-21083
20877referencePosition = new Vector3();
20878		this.nearDistance = 1;
20879		this.farDistance = 1000;
20880
20881		this.map = null;
20882
20883		this.alphaMap = null;
20884
20885		this.displacementMap = null;
20886		this.displacementScale = 1;
20887		this.displacementBias = 0;
20888
20889		this.setValues( parameters );
20890
20891	}
20892
20893	copy( source ) {
20894
20895		super.copy( source );
20896
20897		this.referencePosition.copy( source.referencePosition );
20898		this.nearDistance = source.nearDistance;
20899		this.farDistance = source.farDistance;
20900
20901		this.map = source.map;
20902
20903		this.alphaMap = source.alphaMap;
20904
20905		this.displacementMap = source.displacementMap;
20906		this.displacementScale = source.displacementScale;
20907		this.displacementBias = source.displacementBias;
20908
20909		return this;
20910
20911	}
20912
20913}
20914
20915const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
20916
20917const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
20918
20919function WebGLShadowMap( _renderer, _objects, _capabilities ) {
20920
20921	let _frustum = new Frustum();
20922
20923	const _shadowMapSize = new Vector2(),
20924		_viewportSize = new Vector2(),
20925
20926		_viewport = new Vector4(),
20927
20928		_depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ),
20929		_distanceMaterial = new MeshDistanceMaterial(),
20930
20931		_materialCache = {},
20932
20933		_maxTextureSize = _capabilities.maxTextureSize;
20934
20935	const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide };
20936
20937	const shadowMaterialVertical = new ShaderMaterial( {
20938		defines: {
20939			VSM_SAMPLES: 8
20940		},
20941		uniforms: {
20942			shadow_pass: { value: null },
20943			resolution: { value: new Vector2() },
20944			radius: { value: 4.0 }
20945		},
20946
20947		vertexShader: vertex,
20948		fragmentShader: fragment
20949
20950	} );
20951
20952	const shadowMaterialHorizontal = shadowMaterialVertical.clone();
20953	shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
20954
20955	const fullScreenTri = new BufferGeometry();
20956	fullScreenTri.setAttribute(
20957		'position',
20958		new BufferAttribute(
20959			new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
20960			3
20961		)
20962	);
20963
20964	const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
20965
20966	const scope = this;
20967
20968	this.enabled = false;
20969
20970	this.autoUpdate = true;
20971	this.needsUpdate = false;
20972
20973	this.type = PCFShadowMap;
20974
20975	this.render = function ( lights, scene, camera ) {
20976
20977		if ( scope.enabled === false ) return;
20978		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
20979
20980		if ( lights.length === 0 ) return;
20981
20982		const currentRenderTarget = _renderer.getRenderTarget();
20983		const activeCubeFace = _renderer.getActiveCubeFace();
20984		const activeMipmapLevel = _renderer.getActiveMipmapLevel();
20985
20986		const _state = _renderer.state;
20987
20988		// Set GL state for depth map.
20989		_state.setBlending( NoBlending );
20990		_state.buffers.color.setClear( 1, 1, 1, 1 );
20991		_state.buffers.depth.setTest( true );
20992		_state.setScissorTest( false );
20993
20994		// render depth map
20995
20996		for ( let i = 0, il = lights.length; i < il; i ++ ) {
20997
20998			const light = lights[ i ];
20999			const shadow = light.shadow;
21000
21001			if ( shadow === undefined ) {
21002
21003				console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
21004				continue;
21005
21006			}
21007
21008			if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
21009
21010			_shadowMapSize.copy( shadow.mapSize );
21011
21012			const shadowFrameExtents = shadow.getFrameExtents();
21013
21014			_shadowMapSize.multiply( shadowFrameExtents );
21015
21016			_viewportSize.copy( shadow.mapSize );
21017
21018			if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) {
21019
21020				if ( _shadowMapSize.x > _maxTextureSize ) {
21021
21022					_viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x );
21023					_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
21024					shadow.mapSize.x = _viewportSize.x;
21025
21026				}
21027
21028				if ( _shadowMapSize.y > _maxTextureSize ) {
21029
21030					_viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y );
21031					_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
21032					shadow.mapSize.y = _viewportSize.y;
21033
21034				}
21035
21036			}
21037
21038			if ( shadow.map === null ) {
21039
21040				const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {};
21041
21042				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
21043				shadow.map.texture.name = light.name + '.shadowMap';
21044
21045				shadow.camera.updateProjectionMatrix();
21046
21047			}
21048
21049			_renderer.setRenderTarget( shadow.map );
21050			_renderer.clear();
21051
21052			const viewportCount = shadow.getViewportCount();
21053
21054			for ( let vp = 0; vp < viewportCount; vp ++ ) {
21055
21056				const viewport = shadow.getViewport( vp );
21057
21058				_viewport.set(
21059					_viewportSize.x * viewport.x,
21060					_viewportSize.y * viewport.y,
21061					_viewportSize.x * viewport.z,
21062					_viewportSize.y * viewport.w
21063				);
21064
21065				_state.viewport( _viewport );
21066
21067				shadow.updateMatrices( light, vp );
21068
21069				_frustum = shadow.getFrustum();
21070
21071				renderObject( scene, camera, shadow.camera, light, this.type );
21072
21073			}
21074
21075			// do blur pass for VSM
21076
21077			if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) {
21078
21079				VSMPass( shadow, camera );
21080
21081			}
21082
21083			shadow.needsUpdate = false;
vendor: 1,882 bytes, lines 21084-21146
21084
21085		}
21086
21087		scope.needsUpdate = false;
21088
21089		_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
21090
21091	};
21092
21093	function VSMPass( shadow, camera ) {
21094
21095		const geometry = _objects.update( fullScreenMesh );
21096
21097		if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) {
21098
21099			shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
21100			shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
21101
21102			shadowMaterialVertical.needsUpdate = true;
21103			shadowMaterialHorizontal.needsUpdate = true;
21104
21105		}
21106
21107		if ( shadow.mapPass === null ) {
21108
21109			shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y );
21110
21111		}
21112
21113		// vertical pass
21114
21115		shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
21116		shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
21117		shadowMaterialVertical.uniforms.radius.value = shadow.radius;
21118		_renderer.setRenderTarget( shadow.mapPass );
21119		_renderer.clear();
21120		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
21121
21122		// horizontal pass
21123
21124		shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
21125		shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
21126		shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
21127		_renderer.setRenderTarget( shadow.map );
21128		_renderer.clear();
21129		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
21130
21131	}
21132
21133	function getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) {
21134
21135		let result = null;
21136
21137		const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial;
21138
21139		if ( customMaterial !== undefined ) {
21140
21141			result = customMaterial;
21142
21143		} else {
21144
21145			result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial;
21146
vendor: 1,354 bytes, lines 21147-21197
21147			if ( ( _renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) ||
21148				( material.displacementMap && material.displacementScale !== 0 ) ||
21149				( material.alphaMap && material.alphaTest > 0 ) ||
21150				( material.map && material.alphaTest > 0 ) ) {
21151
21152				// in this case we need a unique material instance reflecting the
21153				// appropriate state
21154
21155				const keyA = result.uuid, keyB = material.uuid;
21156
21157				let materialsForVariant = _materialCache[ keyA ];
21158
21159				if ( materialsForVariant === undefined ) {
21160
21161					materialsForVariant = {};
21162					_materialCache[ keyA ] = materialsForVariant;
21163
21164				}
21165
21166				let cachedMaterial = materialsForVariant[ keyB ];
21167
21168				if ( cachedMaterial === undefined ) {
21169
21170					cachedMaterial = result.clone();
21171					materialsForVariant[ keyB ] = cachedMaterial;
21172
21173				}
21174
21175				result = cachedMaterial;
21176
21177			}
21178
21179		}
21180
21181		result.visible = material.visible;
21182		result.wireframe = material.wireframe;
21183
21184		if ( type === VSMShadowMap ) {
21185
21186			result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
21187
21188		} else {
21189
21190			result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
21191
21192		}
21193
21194		result.alphaMap = material.alphaMap;
21195		result.alphaTest = material.alphaTest;
21196		result.map = material.map;
21197
vendor: 9,683 bytes, lines 21198-21696
21198		result.clipShadows = material.clipShadows;
21199		result.clippingPlanes = material.clippingPlanes;
21200		result.clipIntersection = material.clipIntersection;
21201
21202		result.displacementMap = material.displacementMap;
21203		result.displacementScale = material.displacementScale;
21204		result.displacementBias = material.displacementBias;
21205
21206		result.wireframeLinewidth = material.wireframeLinewidth;
21207		result.linewidth = material.linewidth;
21208
21209		if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
21210
21211			result.referencePosition.setFromMatrixPosition( light.matrixWorld );
21212			result.nearDistance = shadowCameraNear;
21213			result.farDistance = shadowCameraFar;
21214
21215		}
21216
21217		return result;
21218
21219	}
21220
21221	function renderObject( object, camera, shadowCamera, light, type ) {
21222
21223		if ( object.visible === false ) return;
21224
21225		const visible = object.layers.test( camera.layers );
21226
21227		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
21228
21229			if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
21230
21231				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
21232
21233				const geometry = _objects.update( object );
21234				const material = object.material;
21235
21236				if ( Array.isArray( material ) ) {
21237
21238					const groups = geometry.groups;
21239
21240					for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
21241
21242						const group = groups[ k ];
21243						const groupMaterial = material[ group.materialIndex ];
21244
21245						if ( groupMaterial && groupMaterial.visible ) {
21246
21247							const depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );
21248
21249							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
21250
21251						}
21252
21253					}
21254
21255				} else if ( material.visible ) {
21256
21257					const depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type );
21258
21259					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
21260
21261				}
21262
21263			}
21264
21265		}
21266
21267		const children = object.children;
21268
21269		for ( let i = 0, l = children.length; i < l; i ++ ) {
21270
21271			renderObject( children[ i ], camera, shadowCamera, light, type );
21272
21273		}
21274
21275	}
21276
21277}
21278
21279function WebGLState( gl, extensions, capabilities ) {
21280
21281	const isWebGL2 = capabilities.isWebGL2;
21282
21283	function ColorBuffer() {
21284
21285		let locked = false;
21286
21287		const color = new Vector4();
21288		let currentColorMask = null;
21289		const currentColorClear = new Vector4( 0, 0, 0, 0 );
21290
21291		return {
21292
21293			setMask: function ( colorMask ) {
21294
21295				if ( currentColorMask !== colorMask && ! locked ) {
21296
21297					gl.colorMask( colorMask, colorMask, colorMask, colorMask );
21298					currentColorMask = colorMask;
21299
21300				}
21301
21302			},
21303
21304			setLocked: function ( lock ) {
21305
21306				locked = lock;
21307
21308			},
21309
21310			setClear: function ( r, g, b, a, premultipliedAlpha ) {
21311
21312				if ( premultipliedAlpha === true ) {
21313
21314					r *= a; g *= a; b *= a;
21315
21316				}
21317
21318				color.set( r, g, b, a );
21319
21320				if ( currentColorClear.equals( color ) === false ) {
21321
21322					gl.clearColor( r, g, b, a );
21323					currentColorClear.copy( color );
21324
21325				}
21326
21327			},
21328
21329			reset: function () {
21330
21331				locked = false;
21332
21333				currentColorMask = null;
21334				currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
21335
21336			}
21337
21338		};
21339
21340	}
21341
21342	function DepthBuffer() {
21343
21344		let locked = false;
21345
21346		let currentDepthMask = null;
21347		let currentDepthFunc = null;
21348		let currentDepthClear = null;
21349
21350		return {
21351
21352			setTest: function ( depthTest ) {
21353
21354				if ( depthTest ) {
21355
21356					enable( 2929 );
21357
21358				} else {
21359
21360					disable( 2929 );
21361
21362				}
21363
21364			},
21365
21366			setMask: function ( depthMask ) {
21367
21368				if ( currentDepthMask !== depthMask && ! locked ) {
21369
21370					gl.depthMask( depthMask );
21371					currentDepthMask = depthMask;
21372
21373				}
21374
21375			},
21376
21377			setFunc: function ( depthFunc ) {
21378
21379				if ( currentDepthFunc !== depthFunc ) {
21380
21381					switch ( depthFunc ) {
21382
21383						case NeverDepth:
21384
21385							gl.depthFunc( 512 );
21386							break;
21387
21388						case AlwaysDepth:
21389
21390							gl.depthFunc( 519 );
21391							break;
21392
21393						case LessDepth:
21394
21395							gl.depthFunc( 513 );
21396							break;
21397
21398						case LessEqualDepth:
21399
21400							gl.depthFunc( 515 );
21401							break;
21402
21403						case EqualDepth:
21404
21405							gl.depthFunc( 514 );
21406							break;
21407
21408						case GreaterEqualDepth:
21409
21410							gl.depthFunc( 518 );
21411							break;
21412
21413						case GreaterDepth:
21414
21415							gl.depthFunc( 516 );
21416							break;
21417
21418						case NotEqualDepth:
21419
21420							gl.depthFunc( 517 );
21421							break;
21422
21423						default:
21424
21425							gl.depthFunc( 515 );
21426
21427					}
21428
21429					currentDepthFunc = depthFunc;
21430
21431				}
21432
21433			},
21434
21435			setLocked: function ( lock ) {
21436
21437				locked = lock;
21438
21439			},
21440
21441			setClear: function ( depth ) {
21442
21443				if ( currentDepthClear !== depth ) {
21444
21445					gl.clearDepth( depth );
21446					currentDepthClear = depth;
21447
21448				}
21449
21450			},
21451
21452			reset: function () {
21453
21454				locked = false;
21455
21456				currentDepthMask = null;
21457				currentDepthFunc = null;
21458				currentDepthClear = null;
21459
21460			}
21461
21462		};
21463
21464	}
21465
21466	function StencilBuffer() {
21467
21468		let locked = false;
21469
21470		let currentStencilMask = null;
21471		let currentStencilFunc = null;
21472		let currentStencilRef = null;
21473		let currentStencilFuncMask = null;
21474		let currentStencilFail = null;
21475		let currentStencilZFail = null;
21476		let currentStencilZPass = null;
21477		let currentStencilClear = null;
21478
21479		return {
21480
21481			setTest: function ( stencilTest ) {
21482
21483				if ( ! locked ) {
21484
21485					if ( stencilTest ) {
21486
21487						enable( 2960 );
21488
21489					} else {
21490
21491						disable( 2960 );
21492
21493					}
21494
21495				}
21496
21497			},
21498
21499			setMask: function ( stencilMask ) {
21500
21501				if ( currentStencilMask !== stencilMask && ! locked ) {
21502
21503					gl.stencilMask( stencilMask );
21504					currentStencilMask = stencilMask;
21505
21506				}
21507
21508			},
21509
21510			setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
21511
21512				if ( currentStencilFunc !== stencilFunc ||
21513				     currentStencilRef !== stencilRef ||
21514				     currentStencilFuncMask !== stencilMask ) {
21515
21516					gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
21517
21518					currentStencilFunc = stencilFunc;
21519					currentStencilRef = stencilRef;
21520					currentStencilFuncMask = stencilMask;
21521
21522				}
21523
21524			},
21525
21526			setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
21527
21528				if ( currentStencilFail !== stencilFail ||
21529				     currentStencilZFail !== stencilZFail ||
21530				     currentStencilZPass !== stencilZPass ) {
21531
21532					gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
21533
21534					currentStencilFail = stencilFail;
21535					currentStencilZFail = stencilZFail;
21536					currentStencilZPass = stencilZPass;
21537
21538				}
21539
21540			},
21541
21542			setLocked: function ( lock ) {
21543
21544				locked = lock;
21545
21546			},
21547
21548			setClear: function ( stencil ) {
21549
21550				if ( currentStencilClear !== stencil ) {
21551
21552					gl.clearStencil( stencil );
21553					currentStencilClear = stencil;
21554
21555				}
21556
21557			},
21558
21559			reset: function () {
21560
21561				locked = false;
21562
21563				currentStencilMask = null;
21564				currentStencilFunc = null;
21565				currentStencilRef = null;
21566				currentStencilFuncMask = null;
21567				currentStencilFail = null;
21568				currentStencilZFail = null;
21569				currentStencilZPass = null;
21570				currentStencilClear = null;
21571
21572			}
21573
21574		};
21575
21576	}
21577
21578	//
21579
21580	const colorBuffer = new ColorBuffer();
21581	const depthBuffer = new DepthBuffer();
21582	const stencilBuffer = new StencilBuffer();
21583
21584	const uboBindings = new WeakMap();
21585	const uboProgramMap = new WeakMap();
21586
21587	let enabledCapabilities = {};
21588
21589	let currentBoundFramebuffers = {};
21590	let currentDrawbuffers = new WeakMap();
21591	let defaultDrawbuffers = [];
21592
21593	let currentProgram = null;
21594
21595	let currentBlendingEnabled = false;
21596	let currentBlending = null;
21597	let currentBlendEquation = null;
21598	let currentBlendSrc = null;
21599	let currentBlendDst = null;
21600	let currentBlendEquationAlpha = null;
21601	let currentBlendSrcAlpha = null;
21602	let currentBlendDstAlpha = null;
21603	let currentPremultipledAlpha = false;
21604
21605	let currentFlipSided = null;
21606	let currentCullFace = null;
21607
21608	let currentLineWidth = null;
21609
21610	let currentPolygonOffsetFactor = null;
21611	let currentPolygonOffsetUnits = null;
21612
21613	const maxTextures = gl.getParameter( 35661 );
21614
21615	let lineWidthAvailable = false;
21616	let version = 0;
21617	const glVersion = gl.getParameter( 7938 );
21618
21619	if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
21620
21621		version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
21622		lineWidthAvailable = ( version >= 1.0 );
21623
21624	} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
21625
21626		version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
21627		lineWidthAvailable = ( version >= 2.0 );
21628
21629	}
21630
21631	let currentTextureSlot = null;
21632	let currentBoundTextures = {};
21633
21634	const scissorParam = gl.getParameter( 3088 );
21635	const viewportParam = gl.getParameter( 2978 );
21636
21637	const currentScissor = new Vector4().fromArray( scissorParam );
21638	const currentViewport = new Vector4().fromArray( viewportParam );
21639
21640	function createTexture( type, target, count ) {
21641
21642		const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
21643		const texture = gl.createTexture();
21644
21645		gl.bindTexture( type, texture );
21646		gl.texParameteri( type, 10241, 9728 );
21647		gl.texParameteri( type, 10240, 9728 );
21648
21649		for ( let i = 0; i < count; i ++ ) {
21650
21651			gl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );
21652
21653		}
21654
21655		return texture;
21656
21657	}
21658
21659	const emptyTextures = {};
21660	emptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );
21661	emptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );
21662
21663	// init
21664
21665	colorBuffer.setClear( 0, 0, 0, 1 );
21666	depthBuffer.setClear( 1 );
21667	stencilBuffer.setClear( 0 );
21668
21669	enable( 2929 );
21670	depthBuffer.setFunc( LessEqualDepth );
21671
21672	setFlipSided( false );
21673	setCullFace( CullFaceBack );
21674	enable( 2884 );
21675
21676	setBlending( NoBlending );
21677
21678	//
21679
21680	function enable( id ) {
21681
21682		if ( enabledCapabilities[ id ] !== true ) {
21683
21684			gl.enable( id );
21685			enabledCapabilities[ id ] = true;
21686
21687		}
21688
21689	}
21690
21691	function disable( id ) {
21692
21693		if ( enabledCapabilities[ id ] !== false ) {
21694
21695			gl.disable( id );
21696			enabledCapabilities[ id ] = false;
21697
21698		}
21699
21700	}
21701
21702	function bindFramebuffer( target, framebuffer ) {
21703
21704		if ( currentBoundFramebuffers[ target ] !== framebuffer ) {
21705
21706			gl.bindFramebuffer( target, framebuffer );
21707
21708			currentBoundFramebuffers[ target ] = framebuffer;
21709
21710			if ( isWebGL2 ) {
21711
21712				// 36009 is equivalent to 36160
21713
21714				if ( target === 36009 ) {
21715
21716					currentBoundFramebuffers[ 36160 ] = framebuffer;
21717
21718				}
21719
21720				if ( target === 36160 ) {
21721
21722					currentBoundFramebuffers[ 36009 ] = framebuffer;
21723
21724				}
21725
21726			}
21727
21728			return true;
21729
21730		}
21731
21732		return false;
21733
21734	}
21735
21736	function drawBuffers( renderTarget, framebuffer ) {
21737
21738		let drawBuffers = defaultDrawbuffers;
21739
21740		let needsUpdate = false;
21741
21742		if ( renderTarget ) {
21743
21744			drawBuffers = currentDrawbuffers.get( framebuffer );
21745
21746			if ( drawBuffers === undefined ) {
21747
21748				drawBuffers = [];
21749				currentDrawbuffers.set( framebuffer, drawBuffers );
21750
21751			}
21752
21753			if ( renderTarget.isWebGLMultipleRenderTargets ) {
21754
21755				const textures = renderTarget.texture;
21756
21757				if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== 36064 ) {
21758
21759					for ( let i = 0, il = textures.length; i < il; i ++ ) {
21760
21761						drawBuffers[ i ] = 36064 + i;
21762
21763					}
21764
21765					drawBuffers.length = textures.length;
21766
21767					needsUpdate = true;
21768
21769				}
21770
21771			} else {
21772
21773				if ( drawBuffers[ 0 ] !== 36064 ) {
21774
21775					drawBuffers[ 0 ] = 36064;
21776
21777					needsUpdate = true;
21778
21779				}
21780
21781			}
21782
21783		} else {
21784
21785			if ( drawBuffers[ 0 ] !== 1029 ) {
21786
21787				drawBuffers[ 0 ] = 1029;
21788
21789				needsUpdate = true;
21790
21791			}
21792
21793		}
21794
21795		if ( needsUpdate ) {
21796
21797			if ( capabilities.isWebGL2 ) {
21798
21799				gl.drawBuffers( drawBuffers );
21800
21801			} else {
21802
21803				extensions.get( 'WEBGL_draw_buffers' ).drawBuffersWEBGL( drawBuffers );
21804
21805			}
21806
21807		}
21808
21809
21810	}
21811
21812	function useProgram( program ) {
21813
21814		if ( currentProgram !== program ) {
21815
21816			gl.useProgram( program );
21817
21818			currentProgram = program;
21819
21820			return true;
21821
21822		}
21823
21824		return false;
21825
21826	}
21827
21828	const equationToGL = {
21829		[ AddEquation ]: 32774,
21830		[ SubtractEquation ]: 32778,
21831		[ ReverseSubtractEquation ]: 32779
21832	};
21833
21834	if ( isWebGL2 ) {
21835
21836		equationToGL[ MinEquation ] = 32775;
21837		equationToGL[ MaxEquation ] = 32776;
21838
21839	} else {
21840
21841		const extension = extensions.get( 'EXT_blend_minmax' );
21842
21843		if ( extension !== null ) {
21844
21845			equationToGL[ MinEquation ] = extension.MIN_EXT;
21846			equationToGL[ MaxEquation ] = extension.MAX_EXT;
21847
21848		}
21849
21850	}
21851
21852	const factorToGL = {
21853		[ ZeroFactor ]: 0,
21854		[ OneFactor ]: 1,
21855		[ SrcColorFactor ]: 768,
21856		[ SrcAlphaFactor ]: 770,
21857		[ SrcAlphaSaturateFactor ]: 776,
21858		[ DstColorFactor ]: 774,
21859		[ DstAlphaFactor ]: 772,
21860		[ OneMinusSrcColorFactor ]: 769,
21861		[ OneMinusSrcAlphaFactor ]: 771,
21862		[ OneMinusDstColorFactor ]: 775,
21863		[ OneMinusDstAlphaFactor ]: 773
21864	};
21865
21866	function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {
21867
21868		if ( blending === NoBlending ) {
21869
21870			if ( currentBlendingEnabled === true ) {
21871
21872				disable( 3042 );
21873				currentBlendingEnabled = false;
21874
21875			}
21876
21877			return;
21878
21879		}
21880
21881		if ( currentBlendingEnabled === false ) {
21882
21883			enable( 3042 );
21884			currentBlendingEnabled = true;
21885
21886		}
21887
21888		if ( blending !== CustomBlending ) {
21889
21890			if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
21891
21892				if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
21893
21894					gl.blendEquation( 32774 );
21895
21896					currentBlendEquation = AddEquation;
21897					currentBlendEquationAlpha = AddEquation;
21898
21899				}
21900
21901				if ( premultipliedAlpha ) {
21902
21903					switch ( blending ) {
21904
21905						case NormalBlending:
21906							gl.blendFuncSeparate( 1, 771, 1, 771 );
21907							break;
21908
21909						case AdditiveBlending:
21910							gl.blendFunc( 1, 1 );
21911							break;
21912
21913						case SubtractiveBlending:
21914							gl.blendFuncSeparate( 0, 769, 0, 1 );
21915							break;
21916
21917						case MultiplyBlending:
21918							gl.blendFuncSeparate( 0, 768, 0, 770 );
21919							break;
21920
21921						default:
21922							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
21923							break;
21924
21925					}
21926
21927				} else {
21928
21929					switch ( blending ) {
21930
21931						case NormalBlending:
21932							gl.blendFuncSeparate( 770, 771, 1, 771 );
21933							break;
21934
21935						case AdditiveBlending:
21936							gl.blendFunc( 770, 1 );
21937							break;
21938
21939						case SubtractiveBlending:
21940							gl.blendFuncSeparate( 0, 769, 0, 1 );
21941							break;
21942
21943						case MultiplyBlending:
21944							gl.blendFunc( 0, 768 );
21945							break;
21946
21947						default:
21948							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
21949							break;
21950
21951					}
21952
21953				}
21954
21955				currentBlendSrc = null;
21956				currentBlendDst = null;
21957				currentBlendSrcAlpha = null;
21958				currentBlendDstAlpha = null;
21959
21960				currentBlending = blending;
21961				currentPremultipledAlpha = premultipliedAlpha;
21962
21963			}
21964
21965			return;
21966
21967		}
21968
21969		// custom blending
21970
21971		blendEquationAlpha = blendEquationAlpha || blendEquation;
21972		blendSrcAlpha = blendSrcAlpha || blendSrc;
21973		blendDstAlpha = blendDstAlpha || blendDst;
21974
21975		if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
21976
21977			gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
21978
21979			currentBlendEquation = blendEquation;
21980			currentBlendEquationAlpha = blendEquationAlpha;
21981
21982		}
21983
21984		if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
21985
21986			gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
21987
21988			currentBlendSrc = blendSrc;
21989			currentBlendDst = blendDst;
21990			currentBlendSrcAlpha = blendSrcAlpha;
21991			currentBlendDstAlpha = blendDstAlpha;
21992
21993		}
21994
21995		currentBlending = blending;
21996		currentPremultipledAlpha = false;
21997
21998	}
21999
22000	function setMaterial( material, frontFaceCW ) {
22001
22002		material.side === DoubleSide
22003			? disable( 2884 )
22004			: enable( 2884 );
22005
22006		let flipSided = ( material.side === BackSide );
22007		if ( frontFaceCW ) flipSided = ! flipSided;
22008
22009		setFlipSided( flipSided );
22010
22011		( material.blending === NormalBlending && material.transparent === false )
22012			? setBlending( NoBlending )
22013			: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );
22014
22015		depthBuffer.setFunc( material.depthFunc );
22016		depthBuffer.setTest( material.depthTest );
22017		depthBuffer.setMask( material.depthWrite );
22018		colorBuffer.setMask( material.colorWrite );
22019
22020		const stencilWrite = material.stencilWrite;
22021		stencilBuffer.setTest( stencilWrite );
22022		if ( stencilWrite ) {
22023
22024			stencilBuffer.setMask( material.stencilWriteMask );
22025			stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
22026			stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
22027
22028		}
22029
22030		setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
22031
22032		material.alphaToCoverage === true
22033			? enable( 32926 )
22034			: disable( 32926 );
22035
22036	}
22037
22038	//
22039
22040	function setFlipSided( flipSided ) {
22041
22042		if ( currentFlipSided !== flipSided ) {
22043
22044			if ( flipSided ) {
22045
22046				gl.frontFace( 2304 );
22047
22048			} else {
22049
22050				gl.frontFace( 2305 );
22051
22052			}
22053
22054			currentFlipSided = flipSided;
22055
22056		}
22057
22058	}
22059
22060	function setCullFace( cullFace ) {
22061
22062		if ( cullFace !== CullFaceNone ) {
22063
22064			enable( 2884 );
22065
22066			if ( cullFace !== currentCullFace ) {
22067
22068				if ( cullFace === CullFaceBack ) {
22069
22070					gl.cullFace( 1029 );
22071
22072				} else if ( cullFace === CullFaceFront ) {
22073
22074					gl.cullFace( 1028 );
22075
22076				} else {
22077
22078					gl.cullFace( 1032 );
22079
22080				}
22081
22082			}
22083
22084		} else {
22085
22086			disable( 2884 );
22087
22088		}
22089
22090		currentCullFace = cullFace;
22091
22092	}
22093
22094	function setLineWidth( width ) {
22095
22096		if ( width !== currentLineWidth ) {
22097
22098			if ( lineWidthAvailable ) gl.lineWidth( width );
22099
22100			currentLineWidth = width;
22101
22102		}
22103
22104	}
22105
22106	function setPolygonOffset( polygonOffset, factor, units ) {
22107
22108		if ( polygonOffset ) {
22109
22110			enable( 32823 );
22111
22112			if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
22113
22114				gl.polygonOffset( factor, units );
22115
22116				currentPolygonOffsetFactor = factor;
22117				currentPolygonOffsetUnits = units;
22118
22119			}
22120
22121		} else {
22122
22123			disable( 32823 );
22124
22125		}
22126
22127	}
22128
22129	function setScissorTest( scissorTest ) {
22130
22131		if ( scissorTest ) {
22132
22133			enable( 3089 );
22134
22135		} else {
22136
22137			disable( 3089 );
22138
22139		}
22140
22141	}
22142
22143	// texture
22144
22145	function activeTexture( webglSlot ) {
22146
22147		if ( webglSlot === undefined ) webglSlot = 33984 + maxTextures - 1;
22148
22149		if ( currentTextureSlot !== webglSlot ) {
22150
22151			gl.activeTexture( webglSlot );
22152			currentTextureSlot = webglSlot;
22153
22154		}
22155
22156	}
22157
22158	function bindTexture( webglType, webglTexture, webglSlot ) {
22159
22160		if ( webglSlot === undefined ) {
22161
22162			if ( currentTextureSlot === null ) {
22163
22164				webglSlot = 33984 + maxTextures - 1;
22165
22166			} else {
22167
22168				webglSlot = currentTextureSlot;
22169
22170			}
22171
22172		}
22173
22174		let boundTexture = currentBoundTextures[ webglSlot ];
22175
22176		if ( boundTexture === undefined ) {
22177
22178			boundTexture = { type: undefined, texture: undefined };
22179			currentBoundTextures[ webglSlot ] = boundTexture;
22180
22181		}
22182
22183		if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
22184
22185			if ( currentTextureSlot !== webglSlot ) {
22186
22187				gl.activeTexture( webglSlot );
22188				currentTextureSlot = webglSlot;
22189
22190			}
22191
22192			gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
22193
22194			boundTexture.type = webglType;
22195			boundTexture.texture = webglTexture;
22196
22197		}
22198
22199	}
22200
22201	function unbindTexture() {
22202
22203		const boundTexture = currentBoundTextures[ currentTextureSlot ];
22204
22205		if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
22206
22207			gl.bindTexture( boundTexture.type, null );
22208
22209			boundTexture.type = undefined;
22210			boundTexture.texture = undefined;
22211
22212		}
22213
22214	}
22215
22216	function compressedTexImage2D() {
22217
22218		try {
22219
22220			gl.compressedTexImage2D.apply( gl, arguments );
22221
22222		} catch ( error ) {
22223
22224			console.error( 'THREE.WebGLState:', error );
22225
22226		}
22227
22228	}
22229
22230	function compressedTexImage3D() {
22231
22232		try {
22233
22234			gl.compressedTexImage3D.apply( gl, arguments );
22235
22236		} catch ( error ) {
22237
22238			console.error( 'THREE.WebGLState:', error );
22239
22240		}
22241
22242	}
22243
22244	function texSubImage2D() {
22245
22246		try {
22247
22248			gl.texSubImage2D.apply( gl, arguments );
22249
22250		} catch ( error ) {
22251
22252			console.error( 'THREE.WebGLState:', error );
22253
22254		}
22255
22256	}
22257
22258	function texSubImage3D() {
22259
22260		try {
22261
22262			gl.texSubImage3D.apply( gl, arguments );
22263
22264		} catch ( error ) {
22265
22266			console.error( 'THREE.WebGLState:', error );
22267
22268		}
22269
22270	}
22271
22272	function compressedTexSubImage2D() {
22273
22274		try {
22275
22276			gl.compressedTexSubImage2D.apply( gl, arguments );
22277
22278		} catch ( error ) {
22279
22280			console.error( 'THREE.WebGLState:', error );
22281
22282		}
22283
22284	}
22285
22286	function compressedTexSubImage3D() {
22287
22288		try {
22289
22290			gl.compressedTexSubImage3D.apply( gl, arguments );
22291
22292		} catch ( error ) {
22293
22294			console.error( 'THREE.WebGLState:', error );
22295
22296		}
22297
22298	}
22299
22300	function texStorage2D() {
22301
22302		try {
22303
22304			gl.texStorage2D.apply( gl, arguments );
22305
22306		} catch ( error ) {
22307
22308			console.error( 'THREE.WebGLState:', error );
22309
22310		}
22311
22312	}
22313
22314	function texStorage3D() {
22315
22316		try {
22317
22318			gl.texStorage3D.apply( gl, arguments );
22319
22320		} catch ( error ) {
22321
22322			console.error( 'THREE.WebGLState:', error );
22323
22324		}
22325
22326	}
22327
22328	function texImage2D() {
22329
22330		try {
22331
22332			gl.texImage2D.apply( gl, arguments );
22333
22334		} catch ( error ) {
22335
22336			console.error( 'THREE.WebGLState:', error );
22337
22338		}
22339
22340	}
22341
22342	function texImage3D() {
22343
22344		try {
22345
22346			gl.texImage3D.apply( gl, arguments );
22347
22348		} catch ( error ) {
22349
22350			console.error( 'THREE.WebGLState:', error );
22351
22352		}
22353
22354	}
22355
22356	//
22357
22358	function scissor( scissor ) {
22359
22360		if ( currentScissor.equals( scissor ) === false ) {
22361
22362			gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
22363			currentScissor.copy( scissor );
22364
22365		}
22366
22367	}
22368
22369	function viewport( viewport ) {
22370
22371		if ( currentViewport.equals( viewport ) === false ) {
22372
22373			gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
22374			currentViewport.copy( viewport );
22375
22376		}
22377
22378	}
22379
22380	function updateUBOMapping( uniformsGroup, program ) {
22381
22382		let mapping = uboProgramMap.get( program );
22383
22384		if ( mapping === undefined ) {
22385
22386			mapping = new WeakMap();
22387
22388			uboProgramMap.set( program, mapping );
22389
22390		}
22391
22392		let blockIndex = mapping.get( uniformsGroup );
22393
22394		if ( blockIndex === undefined ) {
22395
22396			blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name );
22397
22398			mapping.set( uniformsGroup, blockIndex );
22399
22400		}
22401
22402	}
22403
22404	function uniformBlockBinding( uniformsGroup, program ) {
22405
22406		const mapping = uboProgramMap.get( program );
22407		const blockIndex = mapping.get( uniformsGroup );
22408
22409		if ( uboBindings.get( program ) !== blockIndex ) {
22410
22411			// bind shader specific block index to global block point
22412			gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex );
22413
22414			uboBindings.set( program, blockIndex );
22415
22416		}
22417
22418	}
22419
22420	//
22421
22422	function reset() {
22423
22424		// reset state
22425
22426		gl.disable( 3042 );
22427		gl.disable( 2884 );
22428		gl.disable( 2929 );
22429		gl.disable( 32823 );
22430		gl.disable( 3089 );
22431		gl.disable( 2960 );
22432		gl.disable( 32926 );
22433
22434		gl.blendEquation( 32774 );
22435		gl.blendFunc( 1, 0 );
22436		gl.blendFuncSeparate( 1, 0, 1, 0 );
22437
22438		gl.colorMask( true, true, true, true );
22439		gl.clearColor( 0, 0, 0, 0 );
22440
22441		gl.depthMask( true );
22442		gl.depthFunc( 513 );
22443		gl.clearDepth( 1 );
22444
22445		gl.stencilMask( 0xffffffff );
22446		gl.stencilFunc( 519, 0, 0xffffffff );
22447		gl.stencilOp( 7680, 7680, 7680 );
22448		gl.clearStencil( 0 );
22449
22450		gl.cullFace( 1029 );
22451		gl.frontFace( 2305 );
22452
22453		gl.polygonOffset( 0, 0 );
22454
22455		gl.activeTexture( 33984 );
22456
22457		gl.bindFramebuffer( 36160, null );
22458
22459		if ( isWebGL2 === true ) {
22460
22461			gl.bindFramebuffer( 36009, null );
22462			gl.bindFramebuffer( 36008, null );
22463
22464		}
22465
22466		gl.useProgram( null );
22467
22468		gl.lineWidth( 1 );
22469
22470		gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height );
22471		gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height );
22472
22473		// reset internals
22474
22475		enabledCapabilities = {};
22476
22477		currentTextureSlot = null;
22478		currentBoundTextures = {};
22479
22480		currentBoundFramebuffers = {};
vendor: 4,181 bytes, lines 22481-22636
22481		currentDrawbuffers = new WeakMap();
22482		defaultDrawbuffers = [];
22483
22484		currentProgram = null;
22485
22486		currentBlendingEnabled = false;
22487		currentBlending = null;
22488		currentBlendEquation = null;
22489		currentBlendSrc = null;
22490		currentBlendDst = null;
22491		currentBlendEquationAlpha = null;
22492		currentBlendSrcAlpha = null;
22493		currentBlendDstAlpha = null;
22494		currentPremultipledAlpha = false;
22495
22496		currentFlipSided = null;
22497		currentCullFace = null;
22498
22499		currentLineWidth = null;
22500
22501		currentPolygonOffsetFactor = null;
22502		currentPolygonOffsetUnits = null;
22503
22504		currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height );
22505		currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height );
22506
22507		colorBuffer.reset();
22508		depthBuffer.reset();
22509		stencilBuffer.reset();
22510
22511	}
22512
22513	return {
22514
22515		buffers: {
22516			color: colorBuffer,
22517			depth: depthBuffer,
22518			stencil: stencilBuffer
22519		},
22520
22521		enable: enable,
22522		disable: disable,
22523
22524		bindFramebuffer: bindFramebuffer,
22525		drawBuffers: drawBuffers,
22526
22527		useProgram: useProgram,
22528
22529		setBlending: setBlending,
22530		setMaterial: setMaterial,
22531
22532		setFlipSided: setFlipSided,
22533		setCullFace: setCullFace,
22534
22535		setLineWidth: setLineWidth,
22536		setPolygonOffset: setPolygonOffset,
22537
22538		setScissorTest: setScissorTest,
22539
22540		activeTexture: activeTexture,
22541		bindTexture: bindTexture,
22542		unbindTexture: unbindTexture,
22543		compressedTexImage2D: compressedTexImage2D,
22544		compressedTexImage3D: compressedTexImage3D,
22545		texImage2D: texImage2D,
22546		texImage3D: texImage3D,
22547
22548		updateUBOMapping: updateUBOMapping,
22549		uniformBlockBinding: uniformBlockBinding,
22550
22551		texStorage2D: texStorage2D,
22552		texStorage3D: texStorage3D,
22553		texSubImage2D: texSubImage2D,
22554		texSubImage3D: texSubImage3D,
22555		compressedTexSubImage2D: compressedTexSubImage2D,
22556		compressedTexSubImage3D: compressedTexSubImage3D,
22557
22558		scissor: scissor,
22559		viewport: viewport,
22560
22561		reset: reset
22562
22563	};
22564
22565}
22566
22567function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
22568
22569	const isWebGL2 = capabilities.isWebGL2;
22570	const maxTextures = capabilities.maxTextures;
22571	const maxCubemapSize = capabilities.maxCubemapSize;
22572	const maxTextureSize = capabilities.maxTextureSize;
22573	const maxSamples = capabilities.maxSamples;
22574	const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null;
22575	const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent );
22576
22577	const _videoTextures = new WeakMap();
22578	let _canvas;
22579
22580	const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source
22581
22582	// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
22583	// also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
22584	// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
22585
22586	let useOffscreenCanvas = false;
22587
22588	try {
22589
22590		useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
22591			// eslint-disable-next-line compat/compat
22592			&& ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
22593
22594	} catch ( err ) {
22595
22596		// Ignore any errors
22597
22598	}
22599
22600	function createCanvas( width, height ) {
22601
22602		// Use OffscreenCanvas when available. Specially needed in web workers
22603
22604		return useOffscreenCanvas ?
22605			// eslint-disable-next-line compat/compat
22606			new OffscreenCanvas( width, height ) : createElementNS( 'canvas' );
22607
22608	}
22609
22610	function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
22611
22612		let scale = 1;
22613
22614		// handle case if texture exceeds max size
22615
22616		if ( image.width > maxSize || image.height > maxSize ) {
22617
22618			scale = maxSize / Math.max( image.width, image.height );
22619
22620		}
22621
22622		// only perform resize if necessary
22623
22624		if ( scale < 1 || needsPowerOfTwo === true ) {
22625
22626			// only perform resize for certain image types
22627
22628			if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
22629				( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
22630				( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
22631
22632				const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor;
22633
22634				const width = floor( scale * image.width );
22635				const height = floor( scale * image.height );
22636
22637				if ( _canvas === undefined ) _canvas = createCanvas( width, height );
22638
22639				// cube textures can't reuse the same canvas
22640
22641				const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
22642
22643				canvas.width = width;
22644				canvas.height = height;
22645
22646				const context = canvas.getContext( '2d' );
22647				context.drawImage( image, 0, 0, width, height );
22648
22649				console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );
22650
22651				return canvas;
22652
22653			} else {
22654
22655				if ( 'data' in image ) {
22656
22657					console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );
22658
22659				}
22660
22661				return image;
22662
22663			}
22664
22665		}
22666
22667		return image;
22668
22669	}
22670
22671	function isPowerOfTwo$1( image ) {
22672
22673		return isPowerOfTwo( image.width ) && isPowerOfTwo( image.height );
22674
22675	}
22676
22677	function textureNeedsPowerOfTwo( texture ) {
22678
22679		if ( isWebGL2 ) return false;
22680
22681		return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
22682			( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
22683
22684	}
22685
22686	function textureNeedsGenerateMipmaps( texture, supportsMips ) {
22687
22688		return texture.generateMipmaps && supportsMips &&
22689			texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
22690
22691	}
22692
22693	function generateMipmap( target ) {
22694
22695		_gl.generateMipmap( target );
22696
22697	}
22698
22699	function getInternalFormat( internalFormatName, glFormat, glType, encoding, forceLinearEncoding = false ) {
22700
22701		if ( isWebGL2 === false ) return glFormat;
22702
22703		if ( internalFormatName !== null ) {
22704
22705			if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
22706
22707			console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
22708
22709		}
22710
22711		let internalFormat = glFormat;
22712
22713		if ( glFormat === 6403 ) {
22714
22715			if ( glType === 5126 ) internalFormat = 33326;
22716			if ( glType === 5131 ) internalFormat = 33325;
22717			if ( glType === 5121 ) internalFormat = 33321;
22718
22719		}
22720
22721		if ( glFormat === 33319 ) {
22722
22723			if ( glType === 5126 ) internalFormat = 33328;
22724			if ( glType === 5131 ) internalFormat = 33327;
22725			if ( glType === 5121 ) internalFormat = 33323;
22726
22727		}
22728
22729		if ( glFormat === 6408 ) {
22730
22731			if ( glType === 5126 ) internalFormat = 34836;
22732			if ( glType === 5131 ) internalFormat = 34842;
22733			if ( glType === 5121 ) internalFormat = ( encoding === sRGBEncoding && forceLinearEncoding === false ) ? 35907 : 32856;
22734			if ( glType === 32819 ) internalFormat = 32854;
22735			if ( glType === 32820 ) internalFormat = 32855;
22736
22737		}
22738
22739		if ( internalFormat === 33325 || internalFormat === 33326 ||
22740			internalFormat === 33327 || internalFormat === 33328 ||
22741			internalFormat === 34842 || internalFormat === 34836 ) {
22742
22743			extensions.get( 'EXT_color_buffer_float' );
22744
22745		}
22746
22747		return internalFormat;
22748
22749	}
22750
22751	function getMipLevels( texture, image, supportsMips ) {
22752
22753		if ( textureNeedsGenerateMipmaps( texture, supportsMips ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) {
22754
22755			return Math.log2( Math.max( image.width, image.height ) ) + 1;
22756
22757		} else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) {
22758
22759			// user-defined mipmaps
22760
22761			return texture.mipmaps.length;
22762
22763		} else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) {
22764
22765			return image.mipmaps.length;
22766
22767		} else {
22768
22769			// texture without mipmaps (only base level)
22770
22771			return 1;
22772
22773		}
22774
22775	}
22776
22777	// Fallback filters for non-power-of-2 textures
22778
22779	function filterFallback( f ) {
22780
22781		if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {
22782
22783			return 9728;
22784
22785		}
22786
22787		return 9729;
22788
22789	}
22790
22791	//
22792
22793	function onTextureDispose( event ) {
22794
22795		const texture = event.target;
22796
22797		texture.removeEventListener( 'dispose', onTextureDispose );
22798
22799		deallocateTexture( texture );
22800
22801		if ( texture.isVideoTexture ) {
22802
22803			_videoTextures.delete( texture );
22804
22805		}
22806
22807	}
22808
22809	function onRenderTargetDispose( event ) {
22810
22811		const renderTarget = event.target;
22812
22813		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
22814
22815		deallocateRenderTarget( renderTarget );
22816
22817	}
22818
22819	//
22820
22821	function deallocateTexture( texture ) {
22822
22823		const textureProperties = properties.get( texture );
22824
22825		if ( textureProperties.__webglInit === undefined ) return;
22826
22827		// check if it's necessary to remove the WebGLTexture object
22828
22829		const source = texture.source;
22830		const webglTextures = _sources.get( source );
22831
22832		if ( webglTextures ) {
22833
22834			const webglTexture = webglTextures[ textureProperties.__cacheKey ];
22835			webglTexture.usedTimes --;
22836
22837			// the WebGLTexture object is not used anymore, remove it
22838
22839			if ( webglTexture.usedTimes === 0 ) {
22840
22841				deleteTexture( texture );
22842
22843			}
22844
22845			// remove the weak map entry if no WebGLTexture uses the source anymore
22846
22847			if ( Object.keys( webglTextures ).length === 0 ) {
22848
22849				_sources.delete( source );
22850
22851			}
22852
22853		}
22854
22855		properties.remove( texture );
22856
22857	}
22858
22859	function deleteTexture( texture ) {
22860
22861		const textureProperties = properties.get( texture );
22862		_gl.deleteTexture( textureProperties.__webglTexture );
22863
22864		const source = texture.source;
22865		const webglTextures = _sources.get( source );
22866		delete webglTextures[ textureProperties.__cacheKey ];
22867
22868		info.memory.textures --;
22869
22870	}
22871
22872	function deallocateRenderTarget( renderTarget ) {
22873
22874		const texture = renderTarget.texture;
22875
22876		const renderTargetProperties = properties.get( renderTarget );
22877		const textureProperties = properties.get( texture );
22878
22879		if ( textureProperties.__webglTexture !== undefined ) {
22880
22881			_gl.deleteTexture( textureProperties.__webglTexture );
22882
22883			info.memory.textures --;
22884
22885		}
22886
22887		if ( renderTarget.depthTexture ) {
22888
22889			renderTarget.depthTexture.dispose();
22890
22891		}
22892
22893		if ( renderTarget.isWebGLCubeRenderTarget ) {
22894
22895			for ( let i = 0; i < 6; i ++ ) {
22896
22897				_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
22898				if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
22899
22900			}
22901
22902		} else {
22903
22904			_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
22905			if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
22906			if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
22907
22908			if ( renderTargetProperties.__webglColorRenderbuffer ) {
22909
22910				for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) {
22911
22912					if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] );
22913
22914				}
22915
22916			}
22917
22918			if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
22919
22920		}
22921
22922		if ( renderTarget.isWebGLMultipleRenderTargets ) {
22923
22924			for ( let i = 0, il = texture.length; i < il; i ++ ) {
22925
22926				const attachmentProperties = properties.get( texture[ i ] );
22927
22928				if ( attachmentProperties.__webglTexture ) {
22929
22930					_gl.deleteTexture( attachmentProperties.__webglTexture );
22931
22932					info.memory.textures --;
22933
22934				}
22935
22936				properties.remove( texture[ i ] );
22937
22938			}
22939
22940		}
22941
22942		properties.remove( texture );
22943		properties.remove( renderTarget );
22944
22945	}
22946
22947	//
22948
22949	let textureUnits = 0;
22950
22951	function resetTextureUnits() {
22952
22953		textureUnits = 0;
22954
22955	}
22956
22957	function allocateTextureUnit() {
22958
22959		const textureUnit = textureUnits;
22960
22961		if ( textureUnit >= maxTextures ) {
22962
22963			console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );
22964
22965		}
22966
22967		textureUnits += 1;
22968
22969		return textureUnit;
22970
22971	}
22972
22973	function getTextureCacheKey( texture ) {
22974
22975		const array = [];
22976
22977		array.push( texture.wrapS );
22978		array.push( texture.wrapT );
22979		array.push( texture.wrapR || 0 );
22980		array.push( texture.magFilter );
22981		array.push( texture.minFilter );
22982		array.push( texture.anisotropy );
22983		array.push( texture.internalFormat );
22984		array.push( texture.format );
22985		array.push( texture.type );
22986		array.push( texture.generateMipmaps );
22987		array.push( texture.premultiplyAlpha );
22988		array.push( texture.flipY );
22989		array.push( texture.unpackAlignment );
22990		array.push( texture.encoding );
22991
22992		return array.join();
22993
22994	}
22995
22996	//
22997
22998	function setTexture2D( texture, slot ) {
22999
23000		const textureProperties = properties.get( texture );
23001
23002		if ( texture.isVideoTexture ) updateVideoTexture( texture );
23003
23004		if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) {
23005
23006			const image = texture.image;
23007
23008			if ( image === null ) {
23009
23010				console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' );
23011
23012			} else if ( image.complete === false ) {
23013
23014				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
23015
23016			} else {
23017
23018				uploadTexture( textureProperties, texture, slot );
23019				return;
23020
23021			}
23022
23023		}
23024
23025		state.bindTexture( 3553, textureProperties.__webglTexture, 33984 + slot );
23026
23027	}
23028
23029	function setTexture2DArray( texture, slot ) {
23030
23031		const textureProperties = properties.get( texture );
23032
23033		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
23034
23035			uploadTexture( textureProperties, texture, slot );
23036			return;
23037
23038		}
23039
23040		state.bindTexture( 35866, textureProperties.__webglTexture, 33984 + slot );
23041
23042	}
23043
23044	function setTexture3D( texture, slot ) {
23045
23046		const textureProperties = properties.get( texture );
23047
23048		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
23049
23050			uploadTexture( textureProperties, texture, slot );
23051			return;
23052
23053		}
23054
23055		state.bindTexture( 32879, textureProperties.__webglTexture, 33984 + slot );
23056
23057	}
23058
23059	function setTextureCube( texture, slot ) {
23060
23061		const textureProperties = properties.get( texture );
23062
23063		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
23064
23065			uploadCubeTexture( textureProperties, texture, slot );
23066			return;
23067
23068		}
23069
23070		state.bindTexture( 34067, textureProperties.__webglTexture, 33984 + slot );
23071
23072	}
23073
23074	const wrappingToGL = {
23075		[ RepeatWrapping ]: 10497,
23076		[ ClampToEdgeWrapping ]: 33071,
23077		[ MirroredRepeatWrapping ]: 33648
23078	};
23079
23080	const filterToGL = {
23081		[ NearestFilter ]: 9728,
23082		[ NearestMipmapNearestFilter ]: 9984,
23083		[ NearestMipmapLinearFilter ]: 9986,
23084
23085		[ LinearFilter ]: 9729,
23086		[ LinearMipmapNearestFilter ]: 9985,
23087		[ LinearMipmapLinearFilter ]: 9987
23088	};
23089
23090	function setTextureParameters( textureType, texture, supportsMips ) {
23091
23092		if ( supportsMips ) {
23093
23094			_gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );
23095			_gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );
23096
23097			if ( textureType === 32879 || textureType === 35866 ) {
23098
23099				_gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );
23100
23101			}
23102
23103			_gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );
23104			_gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );
23105
23106		} else {
23107
23108			_gl.texParameteri( textureType, 10242, 33071 );
23109			_gl.texParameteri( textureType, 10243, 33071 );
23110
23111			if ( textureType === 32879 || textureType === 35866 ) {
23112
23113				_gl.texParameteri( textureType, 32882, 33071 );
23114
23115			}
23116
23117			if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {
23118
23119				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
23120
23121			}
23122
23123			_gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );
23124			_gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );
23125
23126			if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {
23127
23128				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
23129
23130			}
23131
23132		}
23133
23134		if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
23135
23136			const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
23137
23138			if ( texture.magFilter === NearestFilter ) return;
23139			if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return;
23140			if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension for WebGL 1 and WebGL 2
23141			if ( isWebGL2 === false && ( texture.type === HalfFloatType && extensions.has( 'OES_texture_half_float_linear' ) === false ) ) return; // verify extension for WebGL 1 only
23142
23143			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
23144
23145				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
23146				properties.get( texture ).__currentAnisotropy = texture.anisotropy;
23147
23148			}
23149
23150		}
23151
23152	}
23153
23154	function initTexture( textureProperties, texture ) {
23155
23156		let forceUpload = false;
23157
23158		if ( textureProperties.__webglInit === undefined ) {
23159
23160			textureProperties.__webglInit = true;
23161
23162			texture.addEventListener( 'dispose', onTextureDispose );
23163
23164		}
23165
23166		// create Source <-> WebGLTextures mapping if necessary
23167
23168		const source = texture.source;
23169		let webglTextures = _sources.get( source );
23170
23171		if ( webglTextures === undefined ) {
23172
23173			webglTextures = {};
23174			_sources.set( source, webglTextures );
23175
23176		}
23177
23178		// check if there is already a WebGLTexture object for the given texture parameters
23179
23180		const textureCacheKey = getTextureCacheKey( texture );
23181
23182		if ( textureCacheKey !== textureProperties.__cacheKey ) {
23183
23184			// if not, create a new instance of WebGLTexture
23185
23186			if ( webglTextures[ textureCacheKey ] === undefined ) {
23187
23188				// create new entry
23189
23190				webglTextures[ textureCacheKey ] = {
23191					texture: _gl.createTexture(),
23192					usedTimes: 0
23193				};
23194
23195				info.memory.textures ++;
23196
23197				// when a new instance of WebGLTexture was created, a texture upload is required
23198				// even if the image contents are identical
23199
23200				forceUpload = true;
23201
23202			}
23203
23204			webglTextures[ textureCacheKey ].usedTimes ++;
23205
23206			// every time the texture cache key changes, it's necessary to check if an instance of
23207			// WebGLTexture can be deleted in order to avoid a memory leak.
23208
23209			const webglTexture = webglTextures[ textureProperties.__cacheKey ];
23210
23211			if ( webglTexture !== undefined ) {
23212
23213				webglTextures[ textureProperties.__cacheKey ].usedTimes --;
23214
23215				if ( webglTexture.usedTimes === 0 ) {
23216
23217					deleteTexture( texture );
23218
23219				}
23220
23221			}
23222
23223			// store references to cache key and WebGLTexture object
23224
23225			textureProperties.__cacheKey = textureCacheKey;
23226			textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture;
23227
23228		}
23229
23230		return forceUpload;
23231
23232	}
23233
23234	function uploadTexture( textureProperties, texture, slot ) {
23235
23236		let textureType = 3553;
23237
23238		if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = 35866;
23239		if ( texture.isData3DTexture ) textureType = 32879;
23240
23241		const forceUpload = initTexture( textureProperties, texture );
23242		const source = texture.source;
23243
23244		state.bindTexture( textureType, textureProperties.__webglTexture, 33984 + slot );
23245
23246		const sourceProperties = properties.get( source );
23247
23248		if ( source.version !== sourceProperties.__version || forceUpload === true ) {
23249
23250			state.activeTexture( 33984 + slot );
23251
23252			_gl.pixelStorei( 37440, texture.flipY );
23253			_gl.pixelStorei( 37441, texture.premultiplyAlpha );
23254			_gl.pixelStorei( 3317, texture.unpackAlignment );
23255			_gl.pixelStorei( 37443, 0 );
23256
23257			const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) === false;
23258			let image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );
23259			image = verifyColorSpace( texture, image );
23260
23261			const supportsMips = isPowerOfTwo$1( image ) || isWebGL2,
23262				glFormat = utils.convert( texture.format, texture.encoding );
23263
23264			let glType = utils.convert( texture.type ),
23265				glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.isVideoTexture );
23266
23267			setTextureParameters( textureType, texture, supportsMips );
23268
23269			let mipmap;
23270			const mipmaps = texture.mipmaps;
23271
23272			const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true );
23273			const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
23274			const levels = getMipLevels( texture, image, supportsMips );
23275
23276			if ( texture.isDepthTexture ) {
23277
23278				// populate depth texture with dummy data
23279
23280				glInternalFormat = 6402;
23281
23282				if ( isWebGL2 ) {
23283
23284					if ( texture.type === FloatType ) {
23285
23286						glInternalFormat = 36012;
23287
23288					} else if ( texture.type === UnsignedIntType ) {
23289
23290						glInternalFormat = 33190;
23291
23292					} else if ( texture.type === UnsignedInt248Type ) {
23293
23294						glInternalFormat = 35056;
23295
23296					} else {
23297
23298						glInternalFormat = 33189; // WebGL2 requires sized internalformat for glTexImage2D
23299
23300					}
23301
23302				} else {
23303
23304					if ( texture.type === FloatType ) {
23305
23306						console.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );
23307
23308					}
23309
23310				}
23311
23312				// validation checks for WebGL 1
23313
23314				if ( texture.format === DepthFormat && glInternalFormat === 6402 ) {
23315
23316					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
23317					// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
23318					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
23319					if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {
23320
23321						console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
23322
23323						texture.type = UnsignedIntType;
23324						glType = utils.convert( texture.type );
23325
23326					}
23327
23328				}
23329
23330				if ( texture.format === DepthStencilFormat && glInternalFormat === 6402 ) {
23331
23332					// Depth stencil textures need the DEPTH_STENCIL internal format
23333					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
23334					glInternalFormat = 34041;
23335
23336					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
23337					// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
23338					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
23339					if ( texture.type !== UnsignedInt248Type ) {
23340
23341						console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
23342
23343						texture.type = UnsignedInt248Type;
23344						glType = utils.convert( texture.type );
23345
23346					}
23347
23348				}
23349
23350				//
23351
23352				if ( allocateMemory ) {
23353
23354					if ( useTexStorage ) {
23355
23356						state.texStorage2D( 3553, 1, glInternalFormat, image.width, image.height );
23357
23358					} else {
23359
23360						state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
23361
23362					}
23363
23364				}
23365
23366			} else if ( texture.isDataTexture ) {
23367
23368				// use manually created mipmaps if available
23369				// if there are no manual mipmaps
23370				// set 0 level mipmap and then use GL to generate other mipmap levels
23371
23372				if ( mipmaps.length > 0 && supportsMips ) {
23373
23374					if ( useTexStorage && allocateMemory ) {
23375
23376						state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
23377
23378					}
23379
23380					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
23381
23382						mipmap = mipmaps[ i ];
23383
23384						if ( useTexStorage ) {
23385
23386							state.texSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
23387
23388						} else {
23389
23390							state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
23391
23392						}
23393
23394					}
23395
23396					texture.generateMipmaps = false;
23397
23398				} else {
23399
23400					if ( useTexStorage ) {
23401
23402						if ( allocateMemory ) {
23403
23404							state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height );
23405
23406						}
23407
23408						state.texSubImage2D( 3553, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
23409
23410					} else {
23411
23412						state.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
23413
23414					}
23415
23416				}
23417
23418			} else if ( texture.isCompressedTexture ) {
23419
23420				if ( texture.isCompressedArrayTexture ) {
23421
23422					if ( useTexStorage && allocateMemory ) {
23423
23424						state.texStorage3D( 35866, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth );
23425
23426					}
23427
23428					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
23429
23430						mipmap = mipmaps[ i ];
23431
23432						if ( texture.format !== RGBAFormat ) {
23433
23434							if ( glFormat !== null ) {
23435
23436								if ( useTexStorage ) {
23437
23438									state.compressedTexSubImage3D( 35866, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 );
23439
23440								} else {
23441
23442									state.compressedTexImage3D( 35866, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 );
23443
23444								}
23445
23446							} else {
23447
23448								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
23449
23450							}
23451
23452						} else {
23453
23454							if ( useTexStorage ) {
23455
23456								state.texSubImage3D( 35866, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data );
23457
23458							} else {
23459
23460								state.texImage3D( 35866, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data );
23461
23462							}
23463
23464						}
23465
23466					}
23467
23468				} else {
23469
23470					if ( useTexStorage && allocateMemory ) {
23471
23472						state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
23473
23474					}
23475
23476					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
23477
23478						mipmap = mipmaps[ i ];
23479
23480						if ( texture.format !== RGBAFormat ) {
23481
23482							if ( glFormat !== null ) {
23483
23484								if ( useTexStorage ) {
23485
23486									state.compressedTexSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
23487
23488								} else {
23489
23490									state.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
23491
23492								}
23493
23494							} else {
23495
23496								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
23497
23498							}
23499
23500						} else {
23501
23502							if ( useTexStorage ) {
23503
23504								state.texSubImage2D( 3553, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
23505
23506							} else {
23507
23508								state.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
23509
23510							}
23511
23512						}
23513
23514					}
23515
23516				}
23517
23518			} else if ( texture.isDataArrayTexture ) {
23519
23520				if ( useTexStorage ) {
23521
23522					if ( allocateMemory ) {
23523
23524						state.texStorage3D( 35866, levels, glInternalFormat, image.width, image.height, image.depth );
23525
23526					}
23527
23528					state.texSubImage3D( 35866, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
23529
23530				} else {
23531
23532					state.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
23533
23534				}
23535
23536			} else if ( texture.isData3DTexture ) {
23537
23538				if ( useTexStorage ) {
23539
23540					if ( allocateMemory ) {
23541
23542						state.texStorage3D( 32879, levels, glInternalFormat, image.width, image.height, image.depth );
23543
23544					}
23545
23546					state.texSubImage3D( 32879, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
23547
23548				} else {
23549
23550					state.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
23551
23552				}
23553
23554			}
23554 else if ( texture.isFramebufferTexture ) {
23555
23556				if ( allocateMemory ) {
23557
23558					if ( useTexStorage ) {
23559
23560						state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height );
23561
23562					} else {
23563
23564						let width = image.width, height = image.height;
23565
23566						for ( let i = 0; i < levels; i ++ ) {
23567
23568							state.texImage2D( 3553, i, glInternalFormat, width, height, 0, glFormat, glType, null );
23569
23570							width >>= 1;
23571							height >>= 1;
23572
23573						}
23574
23575					}
23576
23577				}
23578
23579			} else {
23580
23581				// regular Texture (image, video, canvas)
23582
23583				// use manually created mipmaps if available
23584				// if there are no manual mipmaps
23585				// set 0 level mipmap and then use GL to generate other mipmap levels
23586
23587				if ( mipmaps.length > 0 && supportsMips ) {
23588
23589					if ( useTexStorage && allocateMemory ) {
23590
23591						state.texStorage2D( 3553, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
23592
23593					}
23594
23595					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
23596
23597						mipmap = mipmaps[ i ];
23598
23599						if ( useTexStorage ) {
23600
23601							state.texSubImage2D( 3553, i, 0, 0, glFormat, glType, mipmap );
23602
23603						} else {
23604
23605							state.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );
23606
23607						}
23608
23609					}
23610
23611					texture.generateMipmaps = false;
23612
23613				} else {
23614
23615					if ( useTexStorage ) {
23616
23617						if ( allocateMemory ) {
23618
23619							state.texStorage2D( 3553, levels, glInternalFormat, image.width, image.height );
23620
23621						}
23622
23623						state.texSubImage2D( 3553, 0, 0, 0, glFormat, glType, image );
23624
23625					} else {
23626
23627						state.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );
23628
23629					}
23630
23631				}
23632
23633			}
23634
23635			if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
23636
23637				generateMipmap( textureType );
23638
23639			}
23640
23641			sourceProperties.__version = source.version;
23642
23643			if ( texture.onUpdate ) texture.onUpdate( texture );
23644
23645		}
23646
23647		textureProperties.__version = texture.version;
23648
23649	}
23650
23651	function uploadCubeTexture( textureProperties, texture, slot ) {
23652
23653		if ( texture.image.length !== 6 ) return;
23654
23655		const forceUpload = initTexture( textureProperties, texture );
23656		const source = texture.source;
23657
23658		state.bindTexture( 34067, textureProperties.__webglTexture, 33984 + slot );
23659
23660		const sourceProperties = properties.get( source );
23661
23662		if ( source.version !== sourceProperties.__version || forceUpload === true ) {
23663
23664			state.activeTexture( 33984 + slot );
23665
23666			_gl.pixelStorei( 37440, texture.flipY );
23667			_gl.pixelStorei( 37441, texture.premultiplyAlpha );
23668			_gl.pixelStorei( 3317, texture.unpackAlignment );
23669			_gl.pixelStorei( 37443, 0 );
23670
23671			const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture );
23672			const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
23673
23674			const cubeImage = [];
23675
23676			for ( let i = 0; i < 6; i ++ ) {
23677
23678				if ( ! isCompressed && ! isDataTexture ) {
23679
23680					cubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );
23681
23682				} else {
23683
23684					cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
23685
23686				}
23687
23688				cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] );
23689
23690			}
23691
23692			const image = cubeImage[ 0 ],
23693				supportsMips = isPowerOfTwo$1( image ) || isWebGL2,
23694				glFormat = utils.convert( texture.format, texture.encoding ),
23695				glType = utils.convert( texture.type ),
23696				glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
23697
23698			const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true );
23699			const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
23700			let levels = getMipLevels( texture, image, supportsMips );
23701
23702			setTextureParameters( 34067, texture, supportsMips );
23703
23704			let mipmaps;
23705
23706			if ( isCompressed ) {
23707
23708				if ( useTexStorage && allocateMemory ) {
23709
23710					state.texStorage2D( 34067, levels, glInternalFormat, image.width, image.height );
23711
23712				}
23713
23714				for ( let i = 0; i < 6; i ++ ) {
23715
23716					mipmaps = cubeImage[ i ].mipmaps;
23717
23718					for ( let j = 0; j < mipmaps.length; j ++ ) {
23719
23720						const mipmap = mipmaps[ j ];
23721
23722						if ( texture.format !== RGBAFormat ) {
23723
23724							if ( glFormat !== null ) {
23725
23726								if ( useTexStorage ) {
23727
23728									state.compressedTexSubImage2D( 34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
23729
23730								} else {
23731
23732									state.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
23733
23734								}
23735
23736							} else {
23737
23738								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
23739
23740							}
23741
23742						} else {
23743
23744							if ( useTexStorage ) {
23745
23746								state.texSubImage2D( 34069 + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
23747
23748							} else {
23749
23750								state.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
23751
23752							}
23753
23754						}
23755
23756					}
23757
23758				}
23759
23760			} else {
23761
23762				mipmaps = texture.mipmaps;
23763
23764				if ( useTexStorage && allocateMemory ) {
23765
23766					// TODO: Uniformly handle mipmap definitions
23767					// Normal textures and compressed cube textures define base level + mips with their mipmap array
23768					// Uncompressed cube textures use their mipmap array only for mips (no base level)
23769
23770					if ( mipmaps.length > 0 ) levels ++;
23771
23772					state.texStorage2D( 34067, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height );
23773
23774				}
23775
23776				for ( let i = 0; i < 6; i ++ ) {
23777
23778					if ( isDataTexture ) {
23779
23780						if ( useTexStorage ) {
23781
23782							state.texSubImage2D( 34069 + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data );
23783
23784						} else {
23785
23786							state.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
23787
23788						}
23789
23790						for ( let j = 0; j < mipmaps.length; j ++ ) {
23791
23792							const mipmap = mipmaps[ j ];
23793							const mipmapImage = mipmap.image[ i ].image;
23794
23795							if ( useTexStorage ) {
23796
23797								state.texSubImage2D( 34069 + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data );
23798
23799							} else {
23800
23801								state.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
23802
23803							}
23804
23805						}
23806
23807					} else {
23808
23809						if ( useTexStorage ) {
23810
23811							state.texSubImage2D( 34069 + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] );
23812
23813						} else {
23814
23815							state.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
23816
23817						}
23818
23819						for ( let j = 0; j < mipmaps.length; j ++ ) {
23820
23821							const mipmap = mipmaps[ j ];
23822
23823							if ( useTexStorage ) {
23824
23825								state.texSubImage2D( 34069 + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] );
23826
23827							} else {
23828
23829								state.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
23830
23831							}
23832
23833						}
23834
23835					}
23836
23837				}
23838
23839			}
23840
23841			if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
23842
23843				// We assume images for cube map have the same size.
23844				generateMipmap( 34067 );
23845
23846			}
23847
23848			sourceProperties.__version = source.version;
23849
23850			if ( texture.onUpdate ) texture.onUpdate( texture );
23851
23852		}
23853
23854		textureProperties.__version = texture.version;
23855
23856	}
23857
23858	// Render targets
23859
23860	// Setup storage for target texture and bind it to correct framebuffer
23861	function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) {
23862
23863		const glFormat = utils.convert( texture.format, texture.encoding );
23864		const glType = utils.convert( texture.type );
23865		const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
23866		const renderTargetProperties = properties.get( renderTarget );
23867
23868		if ( ! renderTargetProperties.__hasExternalTextures ) {
23869
23870			if ( textureTarget === 32879 || textureTarget === 35866 ) {
23871
23872				state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null );
23873
23874			} else {
23875
23876				state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
23877
23878			}
23879
23880		}
23881
23882		state.bindFramebuffer( 36160, framebuffer );
23883
23884		if ( useMultisampledRTT( renderTarget ) ) {
23885
23886			multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) );
23887
23888		} else if ( textureTarget === 3553 || ( textureTarget >= 34069 && textureTarget <= 34074 ) ) { // see #24753
23889
23890			_gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 );
23891
23892		}
23893
23894		state.bindFramebuffer( 36160, null );
23895
23896	}
23897
23898
23899	// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
23900	function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
23901
23902		_gl.bindRenderbuffer( 36161, renderbuffer );
23903
23904		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
23905
23906			let glInternalFormat = 33189;
23907
23908			if ( isMultisample || useMultisampledRTT( renderTarget ) ) {
23909
23910				const depthTexture = renderTarget.depthTexture;
23911
23912				if ( depthTexture && depthTexture.isDepthTexture ) {
23913
23914					if ( depthTexture.type === FloatType ) {
23915
23916						glInternalFormat = 36012;
23917
23918					} else if ( depthTexture.type === UnsignedIntType ) {
23919
23920						glInternalFormat = 33190;
23921
23922					}
23923
23924				}
23925
23926				const samples = getRenderTargetSamples( renderTarget );
23927
23928				if ( useMultisampledRTT( renderTarget ) ) {
23929
23930					multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
23931
23932				} else {
23933
23934					_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
23935
23936				}
23937
23938			} else {
23939
23940				_gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
23941
23942			}
23943
23944			_gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );
23945
23946		} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
23947
23948			const samples = getRenderTargetSamples( renderTarget );
23949
23950			if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) {
23951
23952				_gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );
23953
23954			} else if ( useMultisampledRTT( renderTarget ) ) {
23955
23956				multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, 35056, renderTarget.width, renderTarget.height );
23957
23958			} else {
23959
23960				_gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );
23961
23962			}
23963
23964
23965			_gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );
23966
23967		} else {
23968
23969			const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [ renderTarget.texture ];
23970
23971			for ( let i = 0; i < textures.length; i ++ ) {
23972
23973				const texture = textures[ i ];
23974
23975				const glFormat = utils.convert( texture.format, texture.encoding );
23976				const glType = utils.convert( texture.type );
23977				const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding );
23978				const samples = getRenderTargetSamples( renderTarget );
23979
23980				if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) {
23981
23982					_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
23983
23984				} else if ( useMultisampledRTT( renderTarget ) ) {
23985
23986					multisampledRTTExt.renderbufferStorageMultisampleEXT( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
23987
23988				} else {
23989
23990					_gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );
23991
23992				}
23993
23994			}
23995
23996		}
23997
23998		_gl.bindRenderbuffer( 36161, null );
23999
24000	}
24001
24002	// Setup resources for a Depth Texture for a FBO (needs an extension)
24003	function setupDepthTexture( framebuffer, renderTarget ) {
24004
24005		const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
24006		if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
24007
24008		state.bindFramebuffer( 36160, framebuffer );
24009
24010		if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
24011
24012			throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
24013
24014		}
24015
24016		// upload an empty depth texture with framebuffer size
24017		if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
24018				renderTarget.depthTexture.image.width !== renderTarget.width ||
24019				renderTarget.depthTexture.image.height !== renderTarget.height ) {
24020
24021			renderTarget.depthTexture.image.width = renderTarget.width;
24022			renderTarget.depthTexture.image.height = renderTarget.height;
24023			renderTarget.depthTexture.needsUpdate = true;
24024
24025		}
24026
24027		setTexture2D( renderTarget.depthTexture, 0 );
24028
24029		const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
24030		const samples = getRenderTargetSamples( renderTarget );
24031
24032		if ( renderTarget.depthTexture.format === DepthFormat ) {
24033
24034			if ( useMultisampledRTT( renderTarget ) ) {
24035
24036				multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 36096, 3553, webglDepthTexture, 0, samples );
24037
24038			} else {
24039
24040				_gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );
24041
24042			}
24043
24044		} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
24045
24046			if ( useMultisampledRTT( renderTarget ) ) {
24047
24048				multisampledRTTExt.framebufferTexture2DMultisampleEXT( 36160, 33306, 3553, webglDepthTexture, 0, samples );
24049
24050			} else {
24051
24052				_gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );
24053
24054			}
24055
24056		} else {
24057
24058			throw new Error( 'Unknown depthTexture format' );
24059
24060		}
24061
24062	}
24063
24064	// Setup GL resources for a non-texture depth buffer
24065	function setupDepthRenderbuffer( renderTarget ) {
24066
24067		const renderTargetProperties = properties.get( renderTarget );
24068		const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
24069
24070		if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) {
24071
24072			if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
24073
24074			setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
24075
24076		} else {
24077
24078			if ( isCube ) {
24079
24080				renderTargetProperties.__webglDepthbuffer = [];
24081
24082				for ( let i = 0; i < 6; i ++ ) {
24083
24084					state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );
24085					renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
24086					setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
24087
24088				}
24089
24090			} else {
24091
24092				state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
24093				renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
24094				setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
24095
24096			}
24097
24098		}
24099
24100		state.bindFramebuffer( 36160, null );
24101
24102	}
24103
24104	// rebind framebuffer with external textures
24105	function rebindTextures( renderTarget, colorTexture, depthTexture ) {
24106
24107		const renderTargetProperties = properties.get( renderTarget );
24108
24109		if ( colorTexture !== undefined ) {
24110
24111			setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, 36064, 3553 );
24112
24113		}
24114
24115		if ( depthTexture !== undefined ) {
24116
24117			setupDepthRenderbuffer( renderTarget );
24118
24119		}
24120
24121	}
24122
24123	// Set up GL resources for the render target
24124	function setupRenderTarget( renderTarget ) {
24125
24126		const texture = renderTarget.texture;
24127
24128		const renderTargetProperties = properties.get( renderTarget );
24129		const textureProperties = properties.get( texture );
24130
24131		renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
24132
24133		if ( renderTarget.isWebGLMultipleRenderTargets !== true ) {
24134
24135			if ( textureProperties.__webglTexture === undefined ) {
24136
24137				textureProperties.__webglTexture = _gl.createTexture();
24138
24139			}
24140
24141			textureProperties.__version = texture.version;
24142			info.memory.textures ++;
24143
24144		}
24145
24146		const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
24147		const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true );
24148		const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2;
24149
24150		// Setup framebuffer
24151
24152		if ( isCube ) {
24153
24154			renderTargetProperties.__webglFramebuffer = [];
24155
24156			for ( let i = 0; i < 6; i ++ ) {
24157
24158				renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
24159
24160			}
24161
24162		} else {
24163
24164			renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
24165
24166			if ( isMultipleRenderTargets ) {
24167
24168				if ( capabilities.drawBuffers ) {
24169
24170					const textures = renderTarget.texture;
24171
24172					for ( let i = 0, il = textures.length; i < il; i ++ ) {
24173
24174						const attachmentProperties = properties.get( textures[ i ] );
24175
24176						if ( attachmentProperties.__webglTexture === undefined ) {
24177
24178							attachmentProperties.__webglTexture = _gl.createTexture();
24179
24180							info.memory.textures ++;
24181
24182						}
24183
24184					}
24185
24186				} else {
24187
24188					console.warn( 'THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.' );
24189
24190				}
24191
24192			}
24193
24194			if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) {
24195
24196				const textures = isMultipleRenderTargets ? texture : [ texture ];
24197
24198				renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
24199				renderTargetProperties.__webglColorRenderbuffer = [];
24200
24201				state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
24202
24203				for ( let i = 0; i < textures.length; i ++ ) {
24204
24205					const texture = textures[ i ];
24206					renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer();
24207
24208					_gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] );
24209
24210					const glFormat = utils.convert( texture.format, texture.encoding );
24211					const glType = utils.convert( texture.type );
24212					const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, renderTarget.isXRRenderTarget === true );
24213					const samples = getRenderTargetSamples( renderTarget );
24214					_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );
24215
24216					_gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] );
24217
24218				}
24219
24220				_gl.bindRenderbuffer( 36161, null );
24221
24222				if ( renderTarget.depthBuffer ) {
24223
24224					renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
24225					setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
24226
24227				}
24228
24229				state.bindFramebuffer( 36160, null );
24230
24231			}
24232
24233		}
24234
24235		// Setup color buffer
24236
24237		if ( isCube ) {
24238
24239			state.bindTexture( 34067, textureProperties.__webglTexture );
24240			setTextureParameters( 34067, texture, supportsMips );
24241
24242			for ( let i = 0; i < 6; i ++ ) {
24243
24244				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, 36064, 34069 + i );
24245
24246			}
24247
24248			if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
24249
24250				generateMipmap( 34067 );
24251
24252			}
24253
24254			state.unbindTexture();
24255
24256		} else if ( isMultipleRenderTargets ) {
24257
24258			const textures = renderTarget.texture;
24259
24260			for ( let i = 0, il = textures.length; i < il; i ++ ) {
24261
24262				const attachment = textures[ i ];
24263				const attachmentProperties = properties.get( attachment );
24264
24265				state.bindTexture( 3553, attachmentProperties.__webglTexture );
24266				setTextureParameters( 3553, attachment, supportsMips );
24267				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, 36064 + i, 3553 );
24268
24269				if ( textureNeedsGenerateMipmaps( attachment, supportsMips ) ) {
24270
24271					generateMipmap( 3553 );
24272
24273				}
24274
24275			}
24276
24277			state.unbindTexture();
24278
24279		} else {
24280
24281			let glTextureType = 3553;
24282
24283			if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) {
24284
24285				if ( isWebGL2 ) {
24286
24287					glTextureType = renderTarget.isWebGL3DRenderTarget ? 32879 : 35866;
24288
24289				} else {
24290
24291					console.error( 'THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2.' );
24292
24293				}
24294
24295			}
24296
24297			state.bindTexture( glTextureType, textureProperties.__webglTexture );
24298			setTextureParameters( glTextureType, texture, supportsMips );
24299			setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, 36064, glTextureType );
24300
24301			if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
24302
24303				generateMipmap( glTextureType );
24304
24305			}
24306
24307			state.unbindTexture();
24308
24309		}
24310
24311		// Setup depth and stencil buffers
24312
24313		if ( renderTarget.depthBuffer ) {
24314
24315			setupDepthRenderbuffer( renderTarget );
24316
24317		}
24318
24319	}
24320
24321	function updateRenderTargetMipmap( renderTarget ) {
24322
24323		const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2;
24324
24325		const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [ renderTarget.texture ];
24326
24327		for ( let i = 0, il = textures.length; i < il; i ++ ) {
24328
24329			const texture = textures[ i ];
24330
24331			if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
24332
24333				const target = renderTarget.isWebGLCubeRenderTarget ? 34067 : 3553;
24334				const webglTexture = properties.get( texture ).__webglTexture;
24335
24336				state.bindTexture( target, webglTexture );
24337				generateMipmap( target );
24338				state.unbindTexture();
24339
24340			}
24341
24342		}
24343
24344	}
24345
24346	function updateMultisampleRenderTarget( renderTarget ) {
24347
24348		if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) {
24349
24350			const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [ renderTarget.texture ];
24351			const width = renderTarget.width;
24352			const height = renderTarget.height;
24353			let mask = 16384;
24354			const invalidationArray = [];
24355			const depthStyle = renderTarget.stencilBuffer ? 33306 : 36096;
24356			const renderTargetProperties = properties.get( renderTarget );
24357			const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true );
24358
24359			// If MRT we need to remove FBO attachments
24360			if ( isMultipleRenderTargets ) {
24361
24362				for ( let i = 0; i < textures.length; i ++ ) {
24363
24364					state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
24365					_gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, null );
24366
24367					state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
24368					_gl.framebufferTexture2D( 36009, 36064 + i, 3553, null, 0 );
24369
24370				}
24371
24372			}
24373
24374			state.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );
24375			state.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );
24376
24377			for ( let i = 0; i < textures.length; i ++ ) {
24378
24379				invalidationArray.push( 36064 + i );
24380
24381				if ( renderTarget.depthBuffer ) {
24382
24383					invalidationArray.push( depthStyle );
24384
24385				}
24386
24387				const ignoreDepthValues = ( renderTargetProperties.__ignoreDepthValues !== undefined ) ? renderTargetProperties.__ignoreDepthValues : false;
24388
24389				if ( ignoreDepthValues === false ) {
24390
24391					if ( renderTarget.depthBuffer ) mask |= 256;
24392					if ( renderTarget.stencilBuffer ) mask |= 1024;
24393
24394				}
24395
24396				if ( isMultipleRenderTargets ) {
24397
24398					_gl.framebufferRenderbuffer( 36008, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] );
24399
24400				}
24401
24402				if ( ignoreDepthValues === true ) {
24403
24404					_gl.invalidateFramebuffer( 36008, [ depthStyle ] );
24405					_gl.invalidateFramebuffer( 36009, [ depthStyle ] );
24406
24407				}
24408
24409				if ( isMultipleRenderTargets ) {
24410
24411					const webglTexture = properties.get( textures[ i ] ).__webglTexture;
24412					_gl.framebufferTexture2D( 36009, 36064, 3553, webglTexture, 0 );
24413
24414				}
24415
24416				_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );
24417
24418				if ( supportsInvalidateFramebuffer ) {
24419
24420					_gl.invalidateFramebuffer( 36008, invalidationArray );
24421
24422				}
24423
24424
24425			}
24426
24427			state.bindFramebuffer( 36008, null );
24428			state.bindFramebuffer( 36009, null );
24429
24430			// If MRT since pre-blit we removed the FBO we need to reconstruct the attachments
24431			if ( isMultipleRenderTargets ) {
24432
24433				for ( let i = 0; i < textures.length; i ++ ) {
24434
24435					state.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );
24436					_gl.framebufferRenderbuffer( 36160, 36064 + i, 36161, renderTargetProperties.__webglColorRenderbuffer[ i ] );
24437
24438					const webglTexture = properties.get( textures[ i ] ).__webglTexture;
24439
24440					state.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );
24441					_gl.framebufferTexture2D( 36009, 36064 + i, 3553, webglTexture, 0 );
24442
24443				}
24444
24445			}
24446
24447			state.bindFramebuffer( 36009, renderTargetProperties.__webglMultisampledFramebuffer );
24448
24449		}
24450
24451	}
24452
24453	function getRenderTargetSamples( renderTarget ) {
24454
24455		return Math.min( maxSamples, renderTarget.samples );
24456
24457	}
24458
24459	function useMultisampledRTT( renderTarget ) {
24460
24461		const renderTargetProperties = properties.get( renderTarget );
24462
24463		return isWebGL2 && renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false;
24464
24465	}
24466
24467	function updateVideoTexture( texture ) {
24468
24469		const frame = info.render.frame;
24470
24471		// Check the last frame we updated the VideoTexture
24472
24473		if ( _videoTextures.get( texture ) !== frame ) {
24474
24475			_videoTextures.set( texture, frame );
24476			texture.update();
24477
24478		}
24479
24480	}
24481
24482	function verifyColorSpace( texture, image ) {
24483
24484		const encoding = texture.encoding;
24485		const format = texture.format;
24486		const type = texture.type;
24487
24488		if ( texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat ) return image;
24489
24490		if ( encoding !== LinearEncoding ) {
24491
24492			// sRGB
24493
24494			if ( encoding === sRGBEncoding ) {
24495
24496				if ( isWebGL2 === false ) {
24497
24498					// in WebGL 1, try to use EXT_sRGB extension and unsized formats
24499
24500					if ( extensions.has( 'EXT_sRGB' ) === true && format === RGBAFormat ) {
24501
24502						texture.format = _SRGBAFormat;
24503
24504						// it's not possible to generate mips in WebGL 1 with this extension
24505
24506						texture.minFilter = LinearFilter;
24507						texture.generateMipmaps = false;
24508
24509					} else {
24510
24511						// slow fallback (CPU decode)
24512
24513						image = ImageUtils.sRGBToLinear( image );
24514
24515					}
24516
24517				} else {
24518
24519					// in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format
24520
24521					if ( format !== RGBAFormat || type !== UnsignedByteType ) {
24522
24523						console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' );
24524
24525					}
24526
24527				}
24528
24529			} else {
24530
24531				console.error( 'THREE.WebGLTextures: Unsupported texture encoding:', encoding );
24532
24533			}
24534
24535		}
24536
24537		return image;
24538
24539	}
24540
24541	//
24542
24543	this.allocateTextureUnit = allocateTextureUnit;
24544	this.resetTextureUnits = resetTextureUnits;
24545
24546	this.setTexture2D = setTexture2D;
24547	this.setTexture2DArray = setTexture2DArray;
24548	this.setTexture3D = setTexture3D;
24549	this.setTextureCube = setTextureCube;
24550	this.rebindTextures = rebindTextures;
24551	this.setupRenderTarget = setupRenderTarget;
24552	this.updateRenderTargetMipmap = updateRenderTargetMipmap;
24553	this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
24554	this.setupDepthRenderbuffer = setupDepthRenderbuffer;
24555	this.setupFrameBufferTexture = setupFrameBufferTexture;
24556	this.useMultisampledRTT = useMultisampledRTT;
24557
24558}
24559
24560function WebGLUtils( gl, extensions, capabilities ) {
24561
24562	const isWebGL2 = capabilities.isWebGL2;
24563
24564	function convert( p, encoding = null ) {
24565
24566		let extension;
24567
24568		if ( p === UnsignedByteType ) return 5121;
24569		if ( p === UnsignedShort4444Type ) return 32819;
24570		if ( p === UnsignedShort5551Type ) return 32820;
24571
24572		if ( p === ByteType ) return 5120;
24573		if ( p === ShortType ) return 5122;
24574		if ( p === UnsignedShortType ) return 5123;
24575		if ( p === IntType ) return 5124;
24576		if ( p === UnsignedIntType ) return 5125;
24577		if ( p === FloatType ) return 5126;
24578
24579		if ( p === HalfFloatType ) {
24580
24581			if ( isWebGL2 ) return 5131;
24582
24583			extension = extensions.get( 'OES_texture_half_float' );
24584
24585			if ( extension !== null ) {
24586
24587				return extension.HALF_FLOAT_OES;
24588
24589			} else {
24590
24591				return null;
24592
24593			}
24594
24595		}
24596
24597		if ( p === AlphaFormat ) return 6406;
24598		if ( p === RGBAFormat ) return 6408;
24599		if ( p === LuminanceFormat ) return 6409;
24600		if ( p === LuminanceAlphaFormat ) return 6410;
24601		if ( p === DepthFormat ) return 6402;
24602		if ( p === DepthStencilFormat ) return 34041;
24603
24604		// WebGL 1 sRGB fallback
24605
24606		if ( p === _SRGBAFormat ) {
24607
24608			extension = extensions.get( 'EXT_sRGB' );
24609
24610			if ( extension !== null ) {
24611
24612				return extension.SRGB_ALPHA_EXT;
24613
24614			} else {
24615
24616				return null;
24617
24618			}
24619
24620		}
24621
24622		// WebGL2 formats.
24623
24624		if ( p === RedFormat ) return 6403;
24625		if ( p === RedIntegerFormat ) return 36244;
24626		if ( p === RGFormat ) return 33319;
24627		if ( p === RGIntegerFormat ) return 33320;
24628		if ( p === RGBAIntegerFormat ) return 36249;
24629
24630		// S3TC
24631
24632		if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
24633
24634			if ( encoding === sRGBEncoding ) {
24635
24636				extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' );
24637
24638				if ( extension !== null ) {
24639
24640					if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT;
24641					if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
24642					if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
24643					if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
24644
24645				} else {
24646
24647					return null;
24648
24649				}
24650
24651			} else {
24652
24653				extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
24654
24655				if ( extension !== null ) {
24656
24657					if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
24658					if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
24659					if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
24660					if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
24661
24662				} else {
24663
24664					return null;
24665
24666				}
24667
24668			}
24669
24670		}
24671
24672		// PVRTC
24673
24674		if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
24675
24676			extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
24677
24678			if ( extension !== null ) {
24679
24680				if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
24681				if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
24682				if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
24683				if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
24684
24685			} else {
24686
24687				return null;
24688
24689			}
24690
24691		}
24692
24693		// ETC1
24694
24695		if ( p === RGB_ETC1_Format ) {
24696
24697			extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
24698
24699			if ( extension !== null ) {
24700
24701				return extension.COMPRESSED_RGB_ETC1_WEBGL;
24702
24703			} else {
24704
24705				return null;
24706
24707			}
24708
24709		}
24710
24711		// ETC2
24712
24713		if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
24714
24715			extension = extensions.get( 'WEBGL_compressed_texture_etc' );
24716
24717			if ( extension !== null ) {
24718
24719				if ( p === RGB_ETC2_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
24720				if ( p === RGBA_ETC2_EAC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
24721
24722			} else {
24723
24724				return null;
24725
24726			}
24727
24728		}
24729
24730		// ASTC
24731
24732		if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
24733			p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
24734			p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
24735			p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
24736			p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
24737
24738			extension = extensions.get( 'WEBGL_compressed_texture_astc' );
24739
24740			if ( extension !== null ) {
24741
24742				if ( p === RGBA_ASTC_4x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
24743				if ( p === RGBA_ASTC_5x4_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
24744				if ( p === RGBA_ASTC_5x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR;
24745				if ( p === RGBA_ASTC_6x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR;
24746				if ( p === RGBA_ASTC_6x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR;
24747				if ( p === RGBA_ASTC_8x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR;
24748				if ( p === RGBA_ASTC_8x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR;
24749				if ( p === RGBA_ASTC_8x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR;
24750				if ( p === RGBA_ASTC_10x5_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR;
24751				if ( p === RGBA_ASTC_10x6_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR;
24752				if ( p === RGBA_ASTC_10x8_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR;
24753				if ( p === RGBA_ASTC_10x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR;
24754				if ( p === RGBA_ASTC_12x10_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR;
24755				if ( p === RGBA_ASTC_12x12_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR;
24756
24757			} else {
24758
24759				return null;
24760
24761			}
24762
24763		}
24764
24765		// BPTC
24766
24767		if ( p === RGBA_BPTC_Format ) {
24768
24769			extension = extensions.get( 'EXT_texture_compression_bptc' );
24770
24771			if ( extension !== null ) {
24772
24773				if ( p === RGBA_BPTC_Format ) return ( encoding === sRGBEncoding ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
24774
24775			} else {
24776
24777				return null;
24778
24779			}
24780
24781		}
24782
vendor: 19,771 bytes, lines 24783-25684
24783		// RGTC
24784
24785		if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) {
24786
24787			extension = extensions.get( 'EXT_texture_compression_rgtc' );
24788
24789			if ( extension !== null ) {
24790
24791				if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT;
24792				if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT;
24793				if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT;
24794				if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
24795
24796			} else {
24797
24798				return null;
24799
24800			}
24801
24802		}
24803
24804		//
24805
24806		if ( p === UnsignedInt248Type ) {
24807
24808			if ( isWebGL2 ) return 34042;
24809
24810			extension = extensions.get( 'WEBGL_depth_texture' );
24811
24812			if ( extension !== null ) {
24813
24814				return extension.UNSIGNED_INT_24_8_WEBGL;
24815
24816			} else {
24817
24818				return null;
24819
24820			}
24821
24822		}
24823
24824		// if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats)
24825
24826		return ( gl[ p ] !== undefined ) ? gl[ p ] : null;
24827
24828	}
24829
24830	return { convert: convert };
24831
24832}
24833
24834class ArrayCamera extends PerspectiveCamera {
24835
24836	constructor( array = [] ) {
24837
24838		super();
24839
24840		this.isArrayCamera = true;
24841
24842		this.cameras = array;
24843
24844	}
24845
24846}
24847
24848class Group extends Object3D {
24849
24850	constructor() {
24851
24852		super();
24853
24854		this.isGroup = true;
24855
24856		this.type = 'Group';
24857
24858	}
24859
24860}
24861
24862const _moveEvent = { type: 'move' };
24863
24864class WebXRController {
24865
24866	constructor() {
24867
24868		this._targetRay = null;
24869		this._grip = null;
24870		this._hand = null;
24871
24872	}
24873
24874	getHandSpace() {
24875
24876		if ( this._hand === null ) {
24877
24878			this._hand = new Group();
24879			this._hand.matrixAutoUpdate = false;
24880			this._hand.visible = false;
24881
24882			this._hand.joints = {};
24883			this._hand.inputState = { pinching: false };
24884
24885		}
24886
24887		return this._hand;
24888
24889	}
24890
24891	getTargetRaySpace() {
24892
24893		if ( this._targetRay === null ) {
24894
24895			this._targetRay = new Group();
24896			this._targetRay.matrixAutoUpdate = false;
24897			this._targetRay.visible = false;
24898			this._targetRay.hasLinearVelocity = false;
24899			this._targetRay.linearVelocity = new Vector3();
24900			this._targetRay.hasAngularVelocity = false;
24901			this._targetRay.angularVelocity = new Vector3();
24902
24903		}
24904
24905		return this._targetRay;
24906
24907	}
24908
24909	getGripSpace() {
24910
24911		if ( this._grip === null ) {
24912
24913			this._grip = new Group();
24914			this._grip.matrixAutoUpdate = false;
24915			this._grip.visible = false;
24916			this._grip.hasLinearVelocity = false;
24917			this._grip.linearVelocity = new Vector3();
24918			this._grip.hasAngularVelocity = false;
24919			this._grip.angularVelocity = new Vector3();
24920
24921		}
24922
24923		return this._grip;
24924
24925	}
24926
24927	dispatchEvent( event ) {
24928
24929		if ( this._targetRay !== null ) {
24930
24931			this._targetRay.dispatchEvent( event );
24932
24933		}
24934
24935		if ( this._grip !== null ) {
24936
24937			this._grip.dispatchEvent( event );
24938
24939		}
24940
24941		if ( this._hand !== null ) {
24942
24943			this._hand.dispatchEvent( event );
24944
24945		}
24946
24947		return this;
24948
24949	}
24950
24951	connect( inputSource ) {
24952
24953		if ( inputSource && inputSource.hand ) {
24954
24955			const hand = this._hand;
24956
24957			if ( hand ) {
24958
24959				for ( const inputjoint of inputSource.hand.values() ) {
24960
24961					// Initialize hand with joints when connected
24962					this._getHandJoint( hand, inputjoint );
24963
24964				}
24965
24966			}
24967
24968		}
24969
24970		this.dispatchEvent( { type: 'connected', data: inputSource } );
24971
24972		return this;
24973
24974	}
24975
24976	disconnect( inputSource ) {
24977
24978		this.dispatchEvent( { type: 'disconnected', data: inputSource } );
24979
24980		if ( this._targetRay !== null ) {
24981
24982			this._targetRay.visible = false;
24983
24984		}
24985
24986		if ( this._grip !== null ) {
24987
24988			this._grip.visible = false;
24989
24990		}
24991
24992		if ( this._hand !== null ) {
24993
24994			this._hand.visible = false;
24995
24996		}
24997
24998		return this;
24999
25000	}
25001
25002	update( inputSource, frame, referenceSpace ) {
25003
25004		let inputPose = null;
25005		let gripPose = null;
25006		let handPose = null;
25007
25008		const targetRay = this._targetRay;
25009		const grip = this._grip;
25010		const hand = this._hand;
25011
25012		if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
25013
25014			if ( hand && inputSource.hand ) {
25015
25016				handPose = true;
25017
25018				for ( const inputjoint of inputSource.hand.values() ) {
25019
25020					// Update the joints groups with the XRJoint poses
25021					const jointPose = frame.getJointPose( inputjoint, referenceSpace );
25022
25023					// The transform of this joint will be updated with the joint pose on each frame
25024					const joint = this._getHandJoint( hand, inputjoint );
25025
25026					if ( jointPose !== null ) {
25027
25028						joint.matrix.fromArray( jointPose.transform.matrix );
25029						joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
25030						joint.jointRadius = jointPose.radius;
25031
25032					}
25033
25034					joint.visible = jointPose !== null;
25035
25036				}
25037
25038				// Custom events
25039
25040				// Check pinchz
25041				const indexTip = hand.joints[ 'index-finger-tip' ];
25042				const thumbTip = hand.joints[ 'thumb-tip' ];
25043				const distance = indexTip.position.distanceTo( thumbTip.position );
25044
25045				const distanceToPinch = 0.02;
25046				const threshold = 0.005;
25047
25048				if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
25049
25050					hand.inputState.pinching = false;
25051					this.dispatchEvent( {
25052						type: 'pinchend',
25053						handedness: inputSource.handedness,
25054						target: this
25055					} );
25056
25057				} else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
25058
25059					hand.inputState.pinching = true;
25060					this.dispatchEvent( {
25061						type: 'pinchstart',
25062						handedness: inputSource.handedness,
25063						target: this
25064					} );
25065
25066				}
25067
25068			} else {
25069
25070				if ( grip !== null && inputSource.gripSpace ) {
25071
25072					gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
25073
25074					if ( gripPose !== null ) {
25075
25076						grip.matrix.fromArray( gripPose.transform.matrix );
25077						grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
25078
25079						if ( gripPose.linearVelocity ) {
25080
25081							grip.hasLinearVelocity = true;
25082							grip.linearVelocity.copy( gripPose.linearVelocity );
25083
25084						} else {
25085
25086							grip.hasLinearVelocity = false;
25087
25088						}
25089
25090						if ( gripPose.angularVelocity ) {
25091
25092							grip.hasAngularVelocity = true;
25093							grip.angularVelocity.copy( gripPose.angularVelocity );
25094
25095						} else {
25096
25097							grip.hasAngularVelocity = false;
25098
25099						}
25100
25101					}
25102
25103				}
25104
25105			}
25106
25107			if ( targetRay !== null ) {
25108
25109				inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
25110
25111				// Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it
25112				if ( inputPose === null && gripPose !== null ) {
25113
25114					inputPose = gripPose;
25115
25116				}
25117
25118				if ( inputPose !== null ) {
25119
25120					targetRay.matrix.fromArray( inputPose.transform.matrix );
25121					targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
25122
25123					if ( inputPose.linearVelocity ) {
25124
25125						targetRay.hasLinearVelocity = true;
25126						targetRay.linearVelocity.copy( inputPose.linearVelocity );
25127
25128					} else {
25129
25130						targetRay.hasLinearVelocity = false;
25131
25132					}
25133
25134					if ( inputPose.angularVelocity ) {
25135
25136						targetRay.hasAngularVelocity = true;
25137						targetRay.angularVelocity.copy( inputPose.angularVelocity );
25138
25139					} else {
25140
25141						targetRay.hasAngularVelocity = false;
25142
25143					}
25144
25145					this.dispatchEvent( _moveEvent );
25146
25147				}
25148
25149			}
25150
25151
25152		}
25153
25154		if ( targetRay !== null ) {
25155
25156			targetRay.visible = ( inputPose !== null );
25157
25158		}
25159
25160		if ( grip !== null ) {
25161
25162			grip.visible = ( gripPose !== null );
25163
25164		}
25165
25166		if ( hand !== null ) {
25167
25168			hand.visible = ( handPose !== null );
25169
25170		}
25171
25172		return this;
25173
25174	}
25175
25176	// private method
25177
25178	_getHandJoint( hand, inputjoint ) {
25179
25180		if ( hand.joints[ inputjoint.jointName ] === undefined ) {
25181
25182			const joint = new Group();
25183			joint.matrixAutoUpdate = false;
25184			joint.visible = false;
25185			hand.joints[ inputjoint.jointName ] = joint;
25186
25187			hand.add( joint );
25188
25189		}
25190
25191		return hand.joints[ inputjoint.jointName ];
25192
25193	}
25194
25195}
25196
25197class DepthTexture extends Texture {
25198
25199	constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
25200
25201		format = format !== undefined ? format : DepthFormat;
25202
25203		if ( format !== DepthFormat && format !== DepthStencilFormat ) {
25204
25205			throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
25206
25207		}
25208
25209		if ( type === undefined && format === DepthFormat ) type = UnsignedIntType;
25210		if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
25211
25212		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
25213
25214		this.isDepthTexture = true;
25215
25216		this.image = { width: width, height: height };
25217
25218		this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
25219		this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
25220
25221		this.flipY = false;
25222		this.generateMipmaps = false;
25223
25224	}
25225
25226
25227}
25228
25229class WebXRManager extends EventDispatcher {
25230
25231	constructor( renderer, gl ) {
25232
25233		super();
25234
25235		const scope = this;
25236
25237		let session = null;
25238		let framebufferScaleFactor = 1.0;
25239
25240		let referenceSpace = null;
25241		let referenceSpaceType = 'local-floor';
25242		// Set default foveation to maximum.
25243		let foveation = 1.0;
25244		let customReferenceSpace = null;
25245
25246		let pose = null;
25247		let glBinding = null;
25248		let glProjLayer = null;
25249		let glBaseLayer = null;
25250		let xrFrame = null;
25251		const attributes = gl.getContextAttributes();
25252		let initialRenderTarget = null;
25253		let newRenderTarget = null;
25254
25255		const controllers = [];
25256		const controllerInputSources = [];
25257
25258		const planes = new Set();
25259		const planesLastChangedTimes = new Map();
25260
25261		//
25262
25263		const cameraL = new PerspectiveCamera();
25264		cameraL.layers.enable( 1 );
25265		cameraL.viewport = new Vector4();
25266
25267		const cameraR = new PerspectiveCamera();
25268		cameraR.layers.enable( 2 );
25269		cameraR.viewport = new Vector4();
25270
25271		const cameras = [ cameraL, cameraR ];
25272
25273		const cameraVR = new ArrayCamera();
25274		cameraVR.layers.enable( 1 );
25275		cameraVR.layers.enable( 2 );
25276
25277		let _currentDepthNear = null;
25278		let _currentDepthFar = null;
25279
25280		//
25281
25282		this.cameraAutoUpdate = true;
25283		this.enabled = false;
25284
25285		this.isPresenting = false;
25286
25287		this.getController = function ( index ) {
25288
25289			let controller = controllers[ index ];
25290
25291			if ( controller === undefined ) {
25292
25293				controller = new WebXRController();
25294				controllers[ index ] = controller;
25295
25296			}
25297
25298			return controller.getTargetRaySpace();
25299
25300		};
25301
25302		this.getControllerGrip = function ( index ) {
25303
25304			let controller = controllers[ index ];
25305
25306			if ( controller === undefined ) {
25307
25308				controller = new WebXRController();
25309				controllers[ index ] = controller;
25310
25311			}
25312
25313			return controller.getGripSpace();
25314
25315		};
25316
25317		this.getHand = function ( index ) {
25318
25319			let controller = controllers[ index ];
25320
25321			if ( controller === undefined ) {
25322
25323				controller = new WebXRController();
25324				controllers[ index ] = controller;
25325
25326			}
25327
25328			return controller.getHandSpace();
25329
25330		};
25331
25332		//
25333
25334		function onSessionEvent( event ) {
25335
25336			const controllerIndex = controllerInputSources.indexOf( event.inputSource );
25337
25338			if ( controllerIndex === - 1 ) {
25339
25340				return;
25341
25342			}
25343
25344			const controller = controllers[ controllerIndex ];
25345
25346			if ( controller !== undefined ) {
25347
25348				controller.dispatchEvent( { type: event.type, data: event.inputSource } );
25349
25350			}
25351
25352		}
25353
25354		function onSessionEnd() {
25355
25356			session.removeEventListener( 'select', onSessionEvent );
25357			session.removeEventListener( 'selectstart', onSessionEvent );
25358			session.removeEventListener( 'selectend', onSessionEvent );
25359			session.removeEventListener( 'squeeze', onSessionEvent );
25360			session.removeEventListener( 'squeezestart', onSessionEvent );
25361			session.removeEventListener( 'squeezeend', onSessionEvent );
25362			session.removeEventListener( 'end', onSessionEnd );
25363			session.removeEventListener( 'inputsourceschange', onInputSourcesChange );
25364
25365			for ( let i = 0; i < controllers.length; i ++ ) {
25366
25367				const inputSource = controllerInputSources[ i ];
25368
25369				if ( inputSource === null ) continue;
25370
25371				controllerInputSources[ i ] = null;
25372
25373				controllers[ i ].disconnect( inputSource );
25374
25375			}
25376
25377			_currentDepthNear = null;
25378			_currentDepthFar = null;
25379
25380			// restore framebuffer/rendering state
25381
25382			renderer.setRenderTarget( initialRenderTarget );
25383
25384			glBaseLayer = null;
25385			glProjLayer = null;
25386			glBinding = null;
25387			session = null;
25388			newRenderTarget = null;
25389
25390			//
25391
25392			animation.stop();
25393
25394			scope.isPresenting = false;
25395
25396			scope.dispatchEvent( { type: 'sessionend' } );
25397
25398		}
25399
25400		this.setFramebufferScaleFactor = function ( value ) {
25401
25402			framebufferScaleFactor = value;
25403
25404			if ( scope.isPresenting === true ) {
25405
25406				console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
25407
25408			}
25409
25410		};
25411
25412		this.setReferenceSpaceType = function ( value ) {
25413
25414			referenceSpaceType = value;
25415
25416			if ( scope.isPresenting === true ) {
25417
25418				console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
25419
25420			}
25421
25422		};
25423
25424		this.getReferenceSpace = function () {
25425
25426			return customReferenceSpace || referenceSpace;
25427
25428		};
25429
25430		this.setReferenceSpace = function ( space ) {
25431
25432			customReferenceSpace = space;
25433
25434		};
25435
25436		this.getBaseLayer = function () {
25437
25438			return glProjLayer !== null ? glProjLayer : glBaseLayer;
25439
25440		};
25441
25442		this.getBinding = function () {
25443
25444			return glBinding;
25445
25446		};
25447
25448		this.getFrame = function () {
25449
25450			return xrFrame;
25451
25452		};
25453
25454		this.getSession = function () {
25455
25456			return session;
25457
25458		};
25459
25460		this.setSession = async function ( value ) {
25461
25462			session = value;
25463
25464			if ( session !== null ) {
25465
25466				initialRenderTarget = renderer.getRenderTarget();
25467
25468				session.addEventListener( 'select', onSessionEvent );
25469				session.addEventListener( 'selectstart', onSessionEvent );
25470				session.addEventListener( 'selectend', onSessionEvent );
25471				session.addEventListener( 'squeeze', onSessionEvent );
25472				session.addEventListener( 'squeezestart', onSessionEvent );
25473				session.addEventListener( 'squeezeend', onSessionEvent );
25474				session.addEventListener( 'end', onSessionEnd );
25475				session.addEventListener( 'inputsourceschange', onInputSourcesChange );
25476
25477				if ( attributes.xrCompatible !== true ) {
25478
25479					await gl.makeXRCompatible();
25480
25481				}
25482
25483				if ( ( session.renderState.layers === undefined ) || ( renderer.capabilities.isWebGL2 === false ) ) {
25484
25485					const layerInit = {
25486						antialias: ( session.renderState.layers === undefined ) ? attributes.antialias : true,
25487						alpha: attributes.alpha,
25488						depth: attributes.depth,
25489						stencil: attributes.stencil,
25490						framebufferScaleFactor: framebufferScaleFactor
25491					};
25492
25493					glBaseLayer = new XRWebGLLayer( session, gl, layerInit );
25494
25495					session.updateRenderState( { baseLayer: glBaseLayer } );
25496
25497					newRenderTarget = new WebGLRenderTarget(
25498						glBaseLayer.framebufferWidth,
25499						glBaseLayer.framebufferHeight,
25500						{
25501							format: RGBAFormat,
25502							type: UnsignedByteType,
25503							encoding: renderer.outputEncoding,
25504							stencilBuffer: attributes.stencil
25505						}
25506					);
25507
25508				} else {
25509
25510					let depthFormat = null;
25511					let depthType = null;
25512					let glDepthFormat = null;
25513
25514					if ( attributes.depth ) {
25515
25516						glDepthFormat = attributes.stencil ? 35056 : 33190;
25517						depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat;
25518						depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType;
25519
25520					}
25521
25522					const projectionlayerInit = {
25523						colorFormat: 32856,
25524						depthFormat: glDepthFormat,
25525						scaleFactor: framebufferScaleFactor
25526					};
25527
25528					glBinding = new XRWebGLBinding( session, gl );
25529
25530					glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
25531
25532					session.updateRenderState( { layers: [ glProjLayer ] } );
25533
25534					newRenderTarget = new WebGLRenderTarget(
25535						glProjLayer.textureWidth,
25536						glProjLayer.textureHeight,
25537						{
25538							format: RGBAFormat,
25539							type: UnsignedByteType,
25540							depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ),
25541							stencilBuffer: attributes.stencil,
25542							encoding: renderer.outputEncoding,
25543							samples: attributes.antialias ? 4 : 0
25544						} );
25545
25546					const renderTargetProperties = renderer.properties.get( newRenderTarget );
25547					renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues;
25548
25549				}
25550
25551				newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278
25552
25553				this.setFoveation( foveation );
25554
25555				customReferenceSpace = null;
25556				referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
25557
25558				animation.setContext( session );
25559				animation.start();
25560
25561				scope.isPresenting = true;
25562
25563				scope.dispatchEvent( { type: 'sessionstart' } );
25564
25565			}
25566
25567		};
25568
25569		function onInputSourcesChange( event ) {
25570
25571			// Notify disconnected
25572
25573			for ( let i = 0; i < event.removed.length; i ++ ) {
25574
25575				const inputSource = event.removed[ i ];
25576				const index = controllerInputSources.indexOf( inputSource );
25577
25578				if ( index >= 0 ) {
25579
25580					controllerInputSources[ index ] = null;
25581					controllers[ index ].disconnect( inputSource );
25582
25583				}
25584
25585			}
25586
25587			// Notify connected
25588
25589			for ( let i = 0; i < event.added.length; i ++ ) {
25590
25591				const inputSource = event.added[ i ];
25592
25593				let controllerIndex = controllerInputSources.indexOf( inputSource );
25594
25595				if ( controllerIndex === - 1 ) {
25596
25597					// Assign input source a controller that currently has no input source
25598
25599					for ( let i = 0; i < controllers.length; i ++ ) {
25600
25601						if ( i >= controllerInputSources.length ) {
25602
25603							controllerInputSources.push( inputSource );
25604							controllerIndex = i;
25605							break;
25606
25607						} else if ( controllerInputSources[ i ] === null ) {
25608
25609							controllerInputSources[ i ] = inputSource;
25610							controllerIndex = i;
25611							break;
25612
25613						}
25614
25615					}
25616
25617					// If all controllers do currently receive input we ignore new ones
25618
25619					if ( controllerIndex === - 1 ) break;
25620
25621				}
25622
25623				const controller = controllers[ controllerIndex ];
25624
25625				if ( controller ) {
25626
25627					controller.connect( inputSource );
25628
25629				}
25630
25631			}
25632
25633		}
25634
25635		//
25636
25637		const cameraLPos = new Vector3();
25638		const cameraRPos = new Vector3();
25639
25640		/**
25641		 * Assumes 2 cameras that are parallel and share an X-axis, and that
25642		 * the cameras' projection and world matrices have already been set.
25643		 * And that near and far planes are identical for both cameras.
25644		 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
25645		 */
25646		function setProjectionFromUnion( camera, cameraL, cameraR ) {
25647
25648			cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
25649			cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
25650
25651			const ipd = cameraLPos.distanceTo( cameraRPos );
25652
25653			const projL = cameraL.projectionMatrix.elements;
25654			const projR = cameraR.projectionMatrix.elements;
25655
25656			// VR systems will have identical far and near planes, and
25657			// most likely identical top and bottom frustum extents.
25658			// Use the left camera for these values.
25659			const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
25660			const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
25661			const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
25662			const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
25663
25664			const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
25665			const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
25666			const left = near * leftFov;
25667			const right = near * rightFov;
25668
25669			// Calculate the new camera's position offset from the
25670			// left camera. xOffset should be roughly half `ipd`.
25671			const zOffset = ipd / ( - leftFov + rightFov );
25672			const xOffset = zOffset * - leftFov;
25673
25674			// TODO: Better way to apply this offset?
25675			cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
25676			camera.translateX( xOffset );
25677			camera.translateZ( zOffset );
25678			camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
25679			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
25680
25681			// Find the union of the frustum values of the cameras and scale
25682			// the values so that the near plane's position does not change in world space,
25683			// although must now be relative to the new union camera.
25684			const near2 = near + zOffset;
25685			const far2 = far + zOffset;
25686			const left2 = left - xOffset;
25687			const right2 = right + ( ipd - xOffset );
25688			const top2 = topFov * far / far2 * near2;
25689			const bottom2 = bottomFov * far / far2 * near2;
25690
25691			camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
25692
25693		}
25694
25695		function updateCamera( camera, parent ) {
25696
25697			if ( parent === null ) {
25698
25699				camera.matrixWorld.copy( camera.matrix );
25700
25701			} else {
25702
25703				camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
25704
25705			}
25706
25707			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
25708
25709		}
25710
25711		this.updateCamera = function ( camera ) {
25712
25713			if ( session === null ) return;
25714
25715			cameraVR.near = cameraR.near = cameraL.near = camera.near;
25716			cameraVR.far = cameraR.far = cameraL.far = camera.far;
25717
25718			if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
25719
25720				// Note that the new renderState won't apply until the next frame. See #18320
25721
25722				session.updateRenderState( {
25723					depthNear: cameraVR.near,
25724					depthFar: cameraVR.far
25725				} );
25726
25727				_currentDepthNear = cameraVR.near;
25728				_currentDepthFar = cameraVR.far;
25729
25730			}
25731
25732			const parent = camera.parent;
25733			const cameras = cameraVR.cameras;
25734
25735			updateCamera( cameraVR, parent );
25736
25737			for ( let i = 0; i < cameras.length; i ++ ) {
25738
25739				updateCamera( cameras[ i ], parent );
25740
25741			}
25742
25743			cameraVR.matrixWorld.decompose( cameraVR.position, cameraVR.quaternion, cameraVR.scale );
25744
25745			// update user camera and its children
25746
25747			camera.matrix.copy( cameraVR.matrix );
25748			camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
25749
25750			const children = camera.children;
25751
25752			for ( let i = 0, l = children.length; i < l; i ++ ) {
25753
25754				children[ i ].updateMatrixWorld( true );
25755
25756			}
25757
25758			// update projection matrix for proper view frustum culling
25759
25760			if ( cameras.length === 2 ) {
25761
25762				setProjectionFromUnion( cameraVR, cameraL, cameraR );
25763
25764			} else {
25765
25766				// assume single camera setup (AR)
25767
25768				cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
25769
25770			}
25771
25772		};
25773
25774		this.getCamera = function () {
25775
25776			return cameraVR;
25777
25778		};
25779
25780		this.getFoveation = function () {
25781
25782			if ( glProjLayer === null && glBaseLayer === null ) {
25783
25784				return undefined;
25785
25786			}
25787
25788			return foveation;
25789
25790		};
25791
25792		this.setFoveation = function ( value ) {
25793
25794			// 0 = no foveation = full resolution
25795			// 1 = maximum foveation = the edges render at lower resolution
25796
25797			foveation = value;
25798
25799			if ( glProjLayer !== null ) {
25800
25801				glProjLayer.fixedFoveation = value;
25802
25803			}
25804
25805			if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) {
25806
25807				glBaseLayer.fixedFoveation = value;
25808
25809			}
25810
25811		};
25812
25813		this.getPlanes = function () {
25814
25815			return planes;
25816
25817		};
25818
25819		// Animation Loop
25820
25821		let onAnimationFrameCallback = null;
25822
25823		function onAnimationFrame( time, frame ) {
25824
25825			pose = frame.getViewerPose( customReferenceSpace || referenceSpace );
25826			xrFrame = frame;
25827
25828			if ( pose !== null ) {
25829
25830				const views = pose.views;
25831
25832				if ( glBaseLayer !== null ) {
25833
25834					renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer );
25835					renderer.setRenderTarget( newRenderTarget );
25836
25837				}
25838
25839				let cameraVRNeedsUpdate = false;
25840
25841				// check if it's necessary to rebuild cameraVR's camera list
25842
25843				if ( views.length !== cameraVR.cameras.length ) {
25844
25845					cameraVR.cameras.length = 0;
25846					cameraVRNeedsUpdate = true;
25847
25848				}
25849
25850				for ( let i = 0; i < views.length; i ++ ) {
25851
25852					const view = views[ i ];
25853
25854					let viewport = null;
25855
25856					if ( glBaseLayer !== null ) {
25857
25858						viewport = glBaseLayer.getViewport( view );
25859
25860					} else {
25861
25862						const glSubImage = glBinding.getViewSubImage( glProjLayer, view );
25863						viewport = glSubImage.viewport;
25864
25865						// For side-by-side projection, we only produce a single texture for both eyes.
25866						if ( i === 0 ) {
25867
25868							renderer.setRenderTargetTextures(
25869								newRenderTarget,
25870								glSubImage.colorTexture,
25871								glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture );
25872
25873							renderer.setRenderTarget( newRenderTarget );
25874
25875						}
25876
25877					}
25878
25879					let camera = cameras[ i ];
25880
25881					if ( camera === undefined ) {
25882
25883						camera = new PerspectiveCamera();
25884						camera.layers.enable( i );
25885						camera.viewport = new Vector4();
25886						cameras[ i ] = camera;
25887
25888					}
25889
25890					camera.matrix.fromArray( view.transform.matrix );
25891					camera.projectionMatrix.fromArray( view.projectionMatrix );
25892					camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
25893
25894					if ( i === 0 ) {
25895
25896						cameraVR.matrix.copy( camera.matrix );
25897
25898					}
25899
25900					if ( cameraVRNeedsUpdate === true ) {
25901
25902						cameraVR.cameras.push( camera );
25903
25904					}
25905
25906				}
25907
25908			}
25909
25910			//
25911
25912			for ( let i = 0; i < controllers.length; i ++ ) {
25913
25914				const inputSource = controllerInputSources[ i ];
25915				const controller = controllers[ i ];
25916
25917				if ( inputSource !== null && controller !== undefined ) {
25918
25919					controller.update( inputSource, frame, customReferenceSpace || referenceSpace );
25920
25921				}
25922
25923			}
25924
25925			if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
25926
25927			if ( frame.detectedPlanes ) {
25928
25929				scope.dispatchEvent( { type: 'planesdetected', data: frame.detectedPlanes } );
25930
25931				let planesToRemove = null;
25932
25933				for ( const plane of planes ) {
25934
25935					if ( ! frame.detectedPlanes.has( plane ) ) {
25936
25937						if ( planesToRemove === null ) {
25938
25939							planesToRemove = [];
25940
25941						}
25942
25943						planesToRemove.push( plane );
25944
25945					}
25946
25947				}
25948
25949				if ( planesToRemove !== null ) {
25950
25951					for ( const plane of planesToRemove ) {
25952
25953						planes.delete( plane );
25954						planesLastChangedTimes.delete( plane );
25955						scope.dispatchEvent( { type: 'planeremoved', data: plane } );
25956
25957					}
25958
25959				}
25960
25961				for ( const plane of frame.detectedPlanes ) {
25962
vendor: 16,384 bytes, lines 25963-26738
25963					if ( ! planes.has( plane ) ) {
25964
25965						planes.add( plane );
25966						planesLastChangedTimes.set( plane, frame.lastChangedTime );
25967						scope.dispatchEvent( { type: 'planeadded', data: plane } );
25968
25969					} else {
25970
25971						const lastKnownTime = planesLastChangedTimes.get( plane );
25972
25973						if ( plane.lastChangedTime > lastKnownTime ) {
25974
25975							planesLastChangedTimes.set( plane, plane.lastChangedTime );
25976							scope.dispatchEvent( { type: 'planechanged', data: plane } );
25977
25978						}
25979
25980					}
25981
25982				}
25983
25984			}
25985
25986			xrFrame = null;
25987
25988		}
25989
25990		const animation = new WebGLAnimation();
25991
25992		animation.setAnimationLoop( onAnimationFrame );
25993
25994		this.setAnimationLoop = function ( callback ) {
25995
25996			onAnimationFrameCallback = callback;
25997
25998		};
25999
26000		this.dispose = function () {};
26001
26002	}
26003
26004}
26005
26006function WebGLMaterials( renderer, properties ) {
26007
26008	function refreshFogUniforms( uniforms, fog ) {
26009
26010		fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) );
26011
26012		if ( fog.isFog ) {
26013
26014			uniforms.fogNear.value = fog.near;
26015			uniforms.fogFar.value = fog.far;
26016
26017		} else if ( fog.isFogExp2 ) {
26018
26019			uniforms.fogDensity.value = fog.density;
26020
26021		}
26022
26023	}
26024
26025	function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
26026
26027		if ( material.isMeshBasicMaterial ) {
26028
26029			refreshUniformsCommon( uniforms, material );
26030
26031		} else if ( material.isMeshLambertMaterial ) {
26032
26033			refreshUniformsCommon( uniforms, material );
26034
26035		} else if ( material.isMeshToonMaterial ) {
26036
26037			refreshUniformsCommon( uniforms, material );
26038			refreshUniformsToon( uniforms, material );
26039
26040		} else if ( material.isMeshPhongMaterial ) {
26041
26042			refreshUniformsCommon( uniforms, material );
26043			refreshUniformsPhong( uniforms, material );
26044
26045		} else if ( material.isMeshStandardMaterial ) {
26046
26047			refreshUniformsCommon( uniforms, material );
26048			refreshUniformsStandard( uniforms, material );
26049
26050			if ( material.isMeshPhysicalMaterial ) {
26051
26052				refreshUniformsPhysical( uniforms, material, transmissionRenderTarget );
26053
26054			}
26055
26056		} else if ( material.isMeshMatcapMaterial ) {
26057
26058			refreshUniformsCommon( uniforms, material );
26059			refreshUniformsMatcap( uniforms, material );
26060
26061		} else if ( material.isMeshDepthMaterial ) {
26062
26063			refreshUniformsCommon( uniforms, material );
26064
26065		} else if ( material.isMeshDistanceMaterial ) {
26066
26067			refreshUniformsCommon( uniforms, material );
26068			refreshUniformsDistance( uniforms, material );
26069
26070		} else if ( material.isMeshNormalMaterial ) {
26071
26072			refreshUniformsCommon( uniforms, material );
26073
26074		} else if ( material.isLineBasicMaterial ) {
26075
26076			refreshUniformsLine( uniforms, material );
26077
26078			if ( material.isLineDashedMaterial ) {
26079
26080				refreshUniformsDash( uniforms, material );
26081
26082			}
26083
26084		} else if ( material.isPointsMaterial ) {
26085
26086			refreshUniformsPoints( uniforms, material, pixelRatio, height );
26087
26088		} else if ( material.isSpriteMaterial ) {
26089
26090			refreshUniformsSprites( uniforms, material );
26091
26092		} else if ( material.isShadowMaterial ) {
26093
26094			uniforms.color.value.copy( material.color );
26095			uniforms.opacity.value = material.opacity;
26096
26097		} else if ( material.isShaderMaterial ) {
26098
26099			material.uniformsNeedUpdate = false; // #15581
26100
26101		}
26102
26103	}
26104
26105	function refreshUniformsCommon( uniforms, material ) {
26106
26107		uniforms.opacity.value = material.opacity;
26108
26109		if ( material.color ) {
26110
26111			uniforms.diffuse.value.copy( material.color );
26112
26113		}
26114
26115		if ( material.emissive ) {
26116
26117			uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
26118
26119		}
26120
26121		if ( material.map ) {
26122
26123			uniforms.map.value = material.map;
26124
26125		}
26126
26127		if ( material.alphaMap ) {
26128
26129			uniforms.alphaMap.value = material.alphaMap;
26130
26131		}
26132
26133		if ( material.bumpMap ) {
26134
26135			uniforms.bumpMap.value = material.bumpMap;
26136			uniforms.bumpScale.value = material.bumpScale;
26137			if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;
26138
26139		}
26140
26141		if ( material.displacementMap ) {
26142
26143			uniforms.displacementMap.value = material.displacementMap;
26144			uniforms.displacementScale.value = material.displacementScale;
26145			uniforms.displacementBias.value = material.displacementBias;
26146
26147		}
26148
26149		if ( material.emissiveMap ) {
26150
26151			uniforms.emissiveMap.value = material.emissiveMap;
26152
26153		}
26154
26155		if ( material.normalMap ) {
26156
26157			uniforms.normalMap.value = material.normalMap;
26158			uniforms.normalScale.value.copy( material.normalScale );
26159			if ( material.side === BackSide ) uniforms.normalScale.value.negate();
26160
26161		}
26162
26163		if ( material.specularMap ) {
26164
26165			uniforms.specularMap.value = material.specularMap;
26166
26167		}
26168
26169		if ( material.alphaTest > 0 ) {
26170
26171			uniforms.alphaTest.value = material.alphaTest;
26172
26173		}
26174
26175		const envMap = properties.get( material ).envMap;
26176
26177		if ( envMap ) {
26178
26179			uniforms.envMap.value = envMap;
26180
26181			uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
26182
26183			uniforms.reflectivity.value = material.reflectivity;
26184			uniforms.ior.value = material.ior;
26185			uniforms.refractionRatio.value = material.refractionRatio;
26186
26187		}
26188
26189		if ( material.lightMap ) {
26190
26191			uniforms.lightMap.value = material.lightMap;
26192
26193			// artist-friendly light intensity scaling factor
26194			const scaleFactor = ( renderer.useLegacyLights === true ) ? Math.PI : 1;
26195
26196			uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor;
26197
26198		}
26199
26200		if ( material.aoMap ) {
26201
26202			uniforms.aoMap.value = material.aoMap;
26203			uniforms.aoMapIntensity.value = material.aoMapIntensity;
26204
26205		}
26206
26207		// uv repeat and offset setting priorities
26208		// 1. color map
26209		// 2. specular map
26210		// 3. displacementMap map
26211		// 4. normal map
26212		// 5. bump map
26213		// 6. roughnessMap map
26214		// 7. metalnessMap map
26215		// 8. alphaMap map
26216		// 9. emissiveMap map
26217		// 10. clearcoat map
26218		// 11. clearcoat normal map
26219		// 12. clearcoat roughnessMap map
26220		// 13. iridescence map
26221		// 14. iridescence thickness map
26222		// 15. specular intensity map
26223		// 16. specular tint map
26224		// 17. transmission map
26225		// 18. thickness map
26226
26227		let uvScaleMap;
26228
26229		if ( material.map ) {
26230
26231			uvScaleMap = material.map;
26232
26233		} else if ( material.specularMap ) {
26234
26235			uvScaleMap = material.specularMap;
26236
26237		} else if ( material.displacementMap ) {
26238
26239			uvScaleMap = material.displacementMap;
26240
26241		} else if ( material.normalMap ) {
26242
26243			uvScaleMap = material.normalMap;
26244
26245		} else if ( material.bumpMap ) {
26246
26247			uvScaleMap = material.bumpMap;
26248
26249		} else if ( material.roughnessMap ) {
26250
26251			uvScaleMap = material.roughnessMap;
26252
26253		} else if ( material.metalnessMap ) {
26254
26255			uvScaleMap = material.metalnessMap;
26256
26257		} else if ( material.alphaMap ) {
26258
26259			uvScaleMap = material.alphaMap;
26260
26261		} else if ( material.emissiveMap ) {
26262
26263			uvScaleMap = material.emissiveMap;
26264
26265		} else if ( material.clearcoatMap ) {
26266
26267			uvScaleMap = material.clearcoatMap;
26268
26269		} else if ( material.clearcoatNormalMap ) {
26270
26271			uvScaleMap = material.clearcoatNormalMap;
26272
26273		} else if ( material.clearcoatRoughnessMap ) {
26274
26275			uvScaleMap = material.clearcoatRoughnessMap;
26276
26277		} else if ( material.iridescenceMap ) {
26278
26279			uvScaleMap = material.iridescenceMap;
26280
26281		} else if ( material.iridescenceThicknessMap ) {
26282
26283			uvScaleMap = material.iridescenceThicknessMap;
26284
26285		} else if ( material.specularIntensityMap ) {
26286
26287			uvScaleMap = material.specularIntensityMap;
26288
26289		} else if ( material.specularColorMap ) {
26290
26291			uvScaleMap = material.specularColorMap;
26292
26293		} else if ( material.transmissionMap ) {
26294
26295			uvScaleMap = material.transmissionMap;
26296
26297		} else if ( material.thicknessMap ) {
26298
26299			uvScaleMap = material.thicknessMap;
26300
26301		} else if ( material.sheenColorMap ) {
26302
26303			uvScaleMap = material.sheenColorMap;
26304
26305		} else if ( material.sheenRoughnessMap ) {
26306
26307			uvScaleMap = material.sheenRoughnessMap;
26308
26309		}
26310
26311		if ( uvScaleMap !== undefined ) {
26312
26313			// backwards compatibility
26314			if ( uvScaleMap.isWebGLRenderTarget ) {
26315
26316				uvScaleMap = uvScaleMap.texture;
26317
26318			}
26319
26320			if ( uvScaleMap.matrixAutoUpdate === true ) {
26321
26322				uvScaleMap.updateMatrix();
26323
26324			}
26325
26326			uniforms.uvTransform.value.copy( uvScaleMap.matrix );
26327
26328		}
26329
26330		// uv repeat and offset setting priorities for uv2
26331		// 1. ao map
26332		// 2. light map
26333
26334		let uv2ScaleMap;
26335
26336		if ( material.aoMap ) {
26337
26338			uv2ScaleMap = material.aoMap;
26339
26340		} else if ( material.lightMap ) {
26341
26342			uv2ScaleMap = material.lightMap;
26343
26344		}
26345
26346		if ( uv2ScaleMap !== undefined ) {
26347
26348			// backwards compatibility
26349			if ( uv2ScaleMap.isWebGLRenderTarget ) {
26350
26351				uv2ScaleMap = uv2ScaleMap.texture;
26352
26353			}
26354
26355			if ( uv2ScaleMap.matrixAutoUpdate === true ) {
26356
26357				uv2ScaleMap.updateMatrix();
26358
26359			}
26360
26361			uniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );
26362
26363		}
26364
26365	}
26366
26367	function refreshUniformsLine( uniforms, material ) {
26368
26369		uniforms.diffuse.value.copy( material.color );
26370		uniforms.opacity.value = material.opacity;
26371
26372	}
26373
26374	function refreshUniformsDash( uniforms, material ) {
26375
26376		uniforms.dashSize.value = material.dashSize;
26377		uniforms.totalSize.value = material.dashSize + material.gapSize;
26378		uniforms.scale.value = material.scale;
26379
26380	}
26381
26382	function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
26383
26384		uniforms.diffuse.value.copy( material.color );
26385		uniforms.opacity.value = material.opacity;
26386		uniforms.size.value = material.size * pixelRatio;
26387		uniforms.scale.value = height * 0.5;
26388
26389		if ( material.map ) {
26390
26391			uniforms.map.value = material.map;
26392
26393		}
26394
26395		if ( material.alphaMap ) {
26396
26397			uniforms.alphaMap.value = material.alphaMap;
26398
26399		}
26400
26401		if ( material.alphaTest > 0 ) {
26402
26403			uniforms.alphaTest.value = material.alphaTest;
26404
26405		}
26406
26407		// uv repeat and offset setting priorities
26408		// 1. color map
26409		// 2. alpha map
26410
26411		let uvScaleMap;
26412
26413		if ( material.map ) {
26414
26415			uvScaleMap = material.map;
26416
26417		} else if ( material.alphaMap ) {
26418
26419			uvScaleMap = material.alphaMap;
26420
26421		}
26422
26423		if ( uvScaleMap !== undefined ) {
26424
26425			if ( uvScaleMap.matrixAutoUpdate === true ) {
26426
26427				uvScaleMap.updateMatrix();
26428
26429			}
26430
26431			uniforms.uvTransform.value.copy( uvScaleMap.matrix );
26432
26433		}
26434
26435	}
26436
26437	function refreshUniformsSprites( uniforms, material ) {
26438
26439		uniforms.diffuse.value.copy( material.color );
26440		uniforms.opacity.value = material.opacity;
26441		uniforms.rotation.value = material.rotation;
26442
26443		if ( material.map ) {
26444
26445			uniforms.map.value = material.map;
26446
26447		}
26448
26449		if ( material.alphaMap ) {
26450
26451			uniforms.alphaMap.value = material.alphaMap;
26452
26453		}
26454
26455		if ( material.alphaTest > 0 ) {
26456
26457			uniforms.alphaTest.value = material.alphaTest;
26458
26459		}
26460
26461		// uv repeat and offset setting priorities
26462		// 1. color map
26463		// 2. alpha map
26464
26465		let uvScaleMap;
26466
26467		if ( material.map ) {
26468
26469			uvScaleMap = material.map;
26470
26471		} else if ( material.alphaMap ) {
26472
26473			uvScaleMap = material.alphaMap;
26474
26475		}
26476
26477		if ( uvScaleMap !== undefined ) {
26478
26479			if ( uvScaleMap.matrixAutoUpdate === true ) {
26480
26481				uvScaleMap.updateMatrix();
26482
26483			}
26484
26485			uniforms.uvTransform.value.copy( uvScaleMap.matrix );
26486
26487		}
26488
26489	}
26490
26491	function refreshUniformsPhong( uniforms, material ) {
26492
26493		uniforms.specular.value.copy( material.specular );
26494		uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
26495
26496	}
26497
26498	function refreshUniformsToon( uniforms, material ) {
26499
26500		if ( material.gradientMap ) {
26501
26502			uniforms.gradientMap.value = material.gradientMap;
26503
26504		}
26505
26506	}
26507
26508	function refreshUniformsStandard( uniforms, material ) {
26509
26510		uniforms.roughness.value = material.roughness;
26511		uniforms.metalness.value = material.metalness;
26512
26513		if ( material.roughnessMap ) {
26514
26515			uniforms.roughnessMap.value = material.roughnessMap;
26516
26517		}
26518
26519		if ( material.metalnessMap ) {
26520
26521			uniforms.metalnessMap.value = material.metalnessMap;
26522
26523		}
26524
26525		const envMap = properties.get( material ).envMap;
26526
26527		if ( envMap ) {
26528
26529			//uniforms.envMap.value = material.envMap; // part of uniforms common
26530			uniforms.envMapIntensity.value = material.envMapIntensity;
26531
26532		}
26533
26534	}
26535
26536	function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) {
26537
26538		uniforms.ior.value = material.ior; // also part of uniforms common
26539
26540		if ( material.sheen > 0 ) {
26541
26542			uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen );
26543
26544			uniforms.sheenRoughness.value = material.sheenRoughness;
26545
26546			if ( material.sheenColorMap ) {
26547
26548				uniforms.sheenColorMap.value = material.sheenColorMap;
26549
26550			}
26551
26552			if ( material.sheenRoughnessMap ) {
26553
26554				uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap;
26555
26556			}
26557
26558		}
26559
26560		if ( material.clearcoat > 0 ) {
26561
26562			uniforms.clearcoat.value = material.clearcoat;
26563			uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
26564
26565			if ( material.clearcoatMap ) {
26566
26567				uniforms.clearcoatMap.value = material.clearcoatMap;
26568
26569			}
26570
26571			if ( material.clearcoatRoughnessMap ) {
26572
26573				uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
26574
26575			}
26576
26577			if ( material.clearcoatNormalMap ) {
26578
26579				uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
26580				uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
26581
26582				if ( material.side === BackSide ) {
26583
26584					uniforms.clearcoatNormalScale.value.negate();
26585
26586				}
26587
26588			}
26589
26590		}
26591
26592		if ( material.iridescence > 0 ) {
26593
26594			uniforms.iridescence.value = material.iridescence;
26595			uniforms.iridescenceIOR.value = material.iridescenceIOR;
26596			uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ];
26597			uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ];
26598
26599			if ( material.iridescenceMap ) {
26600
26601				uniforms.iridescenceMap.value = material.iridescenceMap;
26602
26603			}
26604
26605			if ( material.iridescenceThicknessMap ) {
26606
26607				uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap;
26608
26609			}
26610
26611		}
26612
26613		if ( material.transmission > 0 ) {
26614
26615			uniforms.transmission.value = material.transmission;
26616			uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
26617			uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
26618
26619			if ( material.transmissionMap ) {
26620
26621				uniforms.transmissionMap.value = material.transmissionMap;
26622
26623			}
26624
26625			uniforms.thickness.value = material.thickness;
26626
26627			if ( material.thicknessMap ) {
26628
26629				uniforms.thicknessMap.value = material.thicknessMap;
26630
26631			}
26632
26633			uniforms.attenuationDistance.value = material.attenuationDistance;
26634			uniforms.attenuationColor.value.copy( material.attenuationColor );
26635
26636		}
26637
26638		uniforms.specularIntensity.value = material.specularIntensity;
26639		uniforms.specularColor.value.copy( material.specularColor );
26640
26641		if ( material.specularIntensityMap ) {
26642
26643			uniforms.specularIntensityMap.value = material.specularIntensityMap;
26644
26645		}
26646
26647		if ( material.specularColorMap ) {
26648
26649			uniforms.specularColorMap.value = material.specularColorMap;
26650
26651		}
26652
26653	}
26654
26655	function refreshUniformsMatcap( uniforms, material ) {
26656
26657		if ( material.matcap ) {
26658
26659			uniforms.matcap.value = material.matcap;
26660
26661		}
26662
26663	}
26664
26665	function refreshUniformsDistance( uniforms, material ) {
26666
26667		uniforms.referencePosition.value.copy( material.referencePosition );
26668		uniforms.nearDistance.value = material.nearDistance;
26669		uniforms.farDistance.value = material.farDistance;
26670
26671	}
26672
26673	return {
26674		refreshFogUniforms: refreshFogUniforms,
26675		refreshMaterialUniforms: refreshMaterialUniforms
26676	};
26677
26678}
26679
26680function WebGLUniformsGroups( gl, info, capabilities, state ) {
26681
26682	let buffers = {};
26683	let updateList = {};
26684	let allocatedBindingPoints = [];
26685
26686	const maxBindingPoints = ( capabilities.isWebGL2 ) ? gl.getParameter( 35375 ) : 0; // binding points are global whereas block indices are per shader program
26687
26688	function bind( uniformsGroup, program ) {
26689
26690		const webglProgram = program.program;
26691		state.uniformBlockBinding( uniformsGroup, webglProgram );
26692
26693	}
26694
26695	function update( uniformsGroup, program ) {
26696
26697		let buffer = buffers[ uniformsGroup.id ];
26698
26699		if ( buffer === undefined ) {
26700
26701			prepareUniformsGroup( uniformsGroup );
26702
26703			buffer = createBuffer( uniformsGroup );
26704			buffers[ uniformsGroup.id ] = buffer;
26705
26706			uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose );
26707
26708		}
26709
26710		// ensure to update the binding points/block indices mapping for this program
26711
26712		const webglProgram = program.program;
26713		state.updateUBOMapping( uniformsGroup, webglProgram );
26714
26715		// update UBO once per frame
26716
26717		const frame = info.render.frame;
26718
26719		if ( updateList[ uniformsGroup.id ] !== frame ) {
26720
26721			updateBufferData( uniformsGroup );
26722
26723			updateList[ uniformsGroup.id ] = frame;
26724
26725		}
26726
26727	}
26728
26729	function createBuffer( uniformsGroup ) {
26730
26731		// the setup of an UBO is independent of a particular shader program but global
26732
26733		const bindingPointIndex = allocateBindingPointIndex();
26734		uniformsGroup.__bindingPointIndex = bindingPointIndex;
26735
26736		const buffer = gl.createBuffer();
26737		const size = uniformsGroup.__size;
26738		const usage = uniformsGroup
26738.usage;
26739
26740		gl.bindBuffer( 35345, buffer );
26741		gl.bufferData( 35345, size, usage );
26742		gl.bindBuffer( 35345, null );
26743		gl.bindBufferBase( 35345, bindingPointIndex, buffer );
26744
26745		return buffer;
26746
26747	}
26748
26749	function allocateBindingPointIndex() {
26750
26751		for ( let i = 0; i < maxBindingPoints; i ++ ) {
26752
26753			if ( allocatedBindingPoints.indexOf( i ) === - 1 ) {
26754
26755				allocatedBindingPoints.push( i );
26756				return i;
26757
26758			}
26759
26760		}
26761
26762		console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' );
26763
26764		return 0;
26765
26766	}
26767
26768	function updateBufferData( uniformsGroup ) {
26769
26770		const buffer = buffers[ uniformsGroup.id ];
26771		const uniforms = uniformsGroup.uniforms;
26772		const cache = uniformsGroup.__cache;
26773
26774		gl.bindBuffer( 35345, buffer );
26775
26776		for ( let i = 0, il = uniforms.length; i < il; i ++ ) {
26777
26778			const uniform = uniforms[ i ];
26779
26780			// partly update the buffer if necessary
26781
26782			if ( hasUniformChanged( uniform, i, cache ) === true ) {
26783
26784				const offset = uniform.__offset;
26785
26786				const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
26787
26788				let arrayOffset = 0;
26789
26790				for ( let i = 0; i < values.length; i ++ ) {
26791
26792					const value = values[ i ];
26793
26794					const info = getUniformSize( value );
26795
26796					if ( typeof value === 'number' ) {
26797
26798						uniform.__data[ 0 ] = value;
26799						gl.bufferSubData( 35345, offset + arrayOffset, uniform.__data );
26800
26801					} else if ( value.isMatrix3 ) {
26802
26803						// manually converting 3x3 to 3x4
26804
26805						uniform.__data[ 0 ] = value.elements[ 0 ];
26806						uniform.__data[ 1 ] = value.elements[ 1 ];
26807						uniform.__data[ 2 ] = value.elements[ 2 ];
26808						uniform.__data[ 3 ] = value.elements[ 0 ];
26809						uniform.__data[ 4 ] = value.elements[ 3 ];
26810						uniform.__data[ 5 ] = value.elements[ 4 ];
26811						uniform.__data[ 6 ] = value.elements[ 5 ];
26812						uniform.__data[ 7 ] = value.elements[ 0 ];
26813						uniform.__data[ 8 ] = value.elements[ 6 ];
26814						uniform.__data[ 9 ] = value.elements[ 7 ];
26815						uniform.__data[ 10 ] = value.elements[ 8 ];
26816						uniform.__data[ 11 ] = value.elements[ 0 ];
26817
26818					} else {
26819
26820						value.toArray( uniform.__data, arrayOffset );
26821
26822						arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
26823
26824					}
26825
26826				}
26827
26828				gl.bufferSubData( 35345, offset, uniform.__data );
26829
26830			}
26831
26832		}
26833
26834		gl.bindBuffer( 35345, null );
26835
26836	}
26837
26838	function hasUniformChanged( uniform, index, cache ) {
26839
26840		const value = uniform.value;
26841
26842		if ( cache[ index ] === undefined ) {
26843
26844			// cache entry does not exist so far
26845
26846			if ( typeof value === 'number' ) {
26847
26848				cache[ index ] = value;
26849
26850			} else {
26851
26852				const values = Array.isArray( value ) ? value : [ value ];
26853
26854				const tempValues = [];
26855
26856				for ( let i = 0; i < values.length; i ++ ) {
26857
26858					tempValues.push( values[ i ].clone() );
26859
26860				}
26861
26862				cache[ index ] = tempValues;
26863
26864			}
26865
26866			return true;
26867
26868		} else {
26869
26870			// compare current value with cached entry
26871
26872			if ( typeof value === 'number' ) {
26873
26874				if ( cache[ index ] !== value ) {
26875
26876					cache[ index ] = value;
26877					return true;
26878
26879				}
26880
26881			} else {
26882
26883				const cachedObjects = Array.isArray( cache[ index ] ) ? cache[ index ] : [ cache[ index ] ];
26884				const values = Array.isArray( value ) ? value : [ value ];
26885
26886				for ( let i = 0; i < cachedObjects.length; i ++ ) {
26887
26888					const cachedObject = cachedObjects[ i ];
26889
26890					if ( cachedObject.equals( values[ i ] ) === false ) {
26891
26892						cachedObject.copy( values[ i ] );
26893						return true;
26894
26895					}
26896
26897				}
26898
26899			}
26900
26901		}
26902
26903		return false;
26904
26905	}
26906
26907	function prepareUniformsGroup( uniformsGroup ) {
26908
26909		// determine total buffer size according to the STD140 layout
26910		// Hint: STD140 is the only supported layout in WebGL 2
26911
26912		const uniforms = uniformsGroup.uniforms;
26913
26914		let offset = 0; // global buffer offset in bytes
26915		const chunkSize = 16; // size of a chunk in bytes
26916		let chunkOffset = 0; // offset within a single chunk in bytes
26917
26918		for ( let i = 0, l = uniforms.length; i < l; i ++ ) {
26919
26920			const uniform = uniforms[ i ];
26921
26922			const infos = {
26923				boundary: 0, // bytes
26924				storage: 0 // bytes
26925			};
26926
26927			const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
26928
26929			for ( let j = 0, jl = values.length; j < jl; j ++ ) {
26930
26931				const value = values[ j ];
26932
26933				const info = getUniformSize( value );
26934
26935				infos.boundary += info.boundary;
26936				infos.storage += info.storage;
26937
26938			}
26939
26940			// the following two properties will be used for partial buffer updates
26941
26942			uniform.__data = new Float32Array( infos.storage / Float32Array.BYTES_PER_ELEMENT );
26943			uniform.__offset = offset;
26944
26945			//
26946
26947			if ( i > 0 ) {
26948
26949				chunkOffset = offset % chunkSize;
26950
26951				const remainingSizeInChunk = chunkSize - chunkOffset;
26952
26953				// check for chunk overflow
26954
26955				if ( chunkOffset !== 0 && ( remainingSizeInChunk - infos.boundary ) < 0 ) {
26956
26957					// add padding and adjust offset
26958
26959					offset += ( chunkSize - chunkOffset );
26960					uniform.__offset = offset;
26961
26962				}
26963
26964			}
26965
26966			offset += infos.storage;
26967
26968		}
26969
26970		// ensure correct final padding
26971
26972		chunkOffset = offset % chunkSize;
26973
26974		if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset );
26975
26976		//
26977
26978		uniformsGroup.__size = offset;
26979		uniformsGroup.__cache = {};
26980
26981		return this;
26982
26983	}
26984
26985	function getUniformSize( value ) {
26986
26987		const info = {
26988			boundary: 0, // bytes
26989			storage: 0 // bytes
26990		};
26991
26992		// determine sizes according to STD140
26993
26994		if ( typeof value === 'number' ) {
26995
26996			// float/int
26997
26998			info.boundary = 4;
26999			info.storage = 4;
27000
27001		} else if ( value.isVector2 ) {
27002
27003			// vec2
27004
27005			info.boundary = 8;
27006			info.storage = 8;
27007
27008		} else if ( value.isVector3 || value.isColor ) {
27009
27010			// vec3
27011
27012			info.boundary = 16;
27013			info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes
27014
27015		} else if ( value.isVector4 ) {
27016
27017			// vec4
27018
27019			info.boundary = 16;
27020			info.storage = 16;
27021
27022		} else if ( value.isMatrix3 ) {
27023
27024			// mat3 (in STD140 a 3x3 matrix is represented as 3x4)
27025
27026			info.boundary = 48;
27027			info.storage = 48;
27028
27029		} else if ( value.isMatrix4 ) {
27030
27031			// mat4
27032
27033			info.boundary = 64;
27034			info.storage = 64;
27035
27036		} else if ( value.isTexture ) {
27037
27038			console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' );
27039
27040		} else {
27041
27042			console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value );
27043
27044		}
27045
27046		return info;
27047
27048	}
27049
27050	function onUniformsGroupsDispose( event ) {
27051
27052		const uniformsGroup = event.target;
27053
27054		uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose );
27055
27056		const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex );
27057		allocatedBindingPoints.splice( index, 1 );
27058
27059		gl.deleteBuffer( buffers[ uniformsGroup.id ] );
27060
27061		delete buffers[ uniformsGroup.id ];
27062		delete updateList[ uniformsGroup.id ];
27063
27064	}
27065
27066	function dispose() {
27067
27068		for ( const id in buffers ) {
27069
27070			gl.deleteBuffer( buffers[ id ] );
27071
27072		}
27073
27074		allocatedBindingPoints = [];
27075		buffers = {};
27076		updateList = {};
27077
27078	}
27079
27080	return {
27081
27082		bind: bind,
27083		update: update,
27084
27085		dispose: dispose
27086
27087	};
27088
27089}
27090
27091function createCanvasElement() {
27092
27093	const canvas = createElementNS( 'canvas' );
27094	canvas.style.display = 'block';
27095	return canvas;
27096
27097}
27098
27099function WebGLRenderer( parameters = {} ) {
27100
27101	this.isWebGLRenderer = true;
27102
27103	const _canvas = parameters.canvas !== undefined ? parameters.canvas : createCanvasElement(),
27104		_context = parameters.context !== undefined ? parameters.context : null,
27105
27106		_depth = parameters.depth !== undefined ? parameters.depth : true,
27107		_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
27108		_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
27109		_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
27110		_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
27111		_powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',
27112		_failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;
27113
27114	let _alpha;
27115
27116	if ( _context !== null ) {
27117
27118		_alpha = _context.getContextAttributes().alpha;
27119
27120	} else {
27121
27122		_alpha = parameters.alpha !== undefined ? parameters.alpha : false;
27123
27124	}
27125
27126	let currentRenderList = null;
27127	let currentRenderState = null;
27128
27129	// render() can be called from within a callback triggered by another render.
27130	// We track this so that the nested render call gets its list and state isolated from the parent render call.
27131
27132	const renderListStack = [];
27133	const renderStateStack = [];
27134
27135	// public properties
27136
27137	this.domElement = _canvas;
27138
27139	// Debug configuration container
27140	this.debug = {
27141
27142		/**
27143		 * Enables error checking and reporting when shader programs are being compiled
27144		 * @type {boolean}
27145		 */
vendor: 10,774 bytes, lines 27146-27661
27146		checkShaderErrors: true
27147	};
27148
27149	// clearing
27150
27151	this.autoClear = true;
27152	this.autoClearColor = true;
27153	this.autoClearDepth = true;
27154	this.autoClearStencil = true;
27155
27156	// scene graph
27157
27158	this.sortObjects = true;
27159
27160	// user-defined clipping
27161
27162	this.clippingPlanes = [];
27163	this.localClippingEnabled = false;
27164
27165	// physically based shading
27166
27167	this.outputEncoding = LinearEncoding;
27168
27169	// physical lights
27170
27171	this.useLegacyLights = true;
27172
27173	// tone mapping
27174
27175	this.toneMapping = NoToneMapping;
27176	this.toneMappingExposure = 1.0;
27177
27178	// internal properties
27179
27180	const _this = this;
27181
27182	let _isContextLost = false;
27183
27184	// internal state cache
27185
27186	let _currentActiveCubeFace = 0;
27187	let _currentActiveMipmapLevel = 0;
27188	let _currentRenderTarget = null;
27189	let _currentMaterialId = - 1;
27190
27191	let _currentCamera = null;
27192
27193	const _currentViewport = new Vector4();
27194	const _currentScissor = new Vector4();
27195	let _currentScissorTest = null;
27196
27197	//
27198
27199	let _width = _canvas.width;
27200	let _height = _canvas.height;
27201
27202	let _pixelRatio = 1;
27203	let _opaqueSort = null;
27204	let _transparentSort = null;
27205
27206	const _viewport = new Vector4( 0, 0, _width, _height );
27207	const _scissor = new Vector4( 0, 0, _width, _height );
27208	let _scissorTest = false;
27209
27210	// frustum
27211
27212	const _frustum = new Frustum();
27213
27214	// clipping
27215
27216	let _clippingEnabled = false;
27217	let _localClippingEnabled = false;
27218
27219	// transmission
27220
27221	let _transmissionRenderTarget = null;
27222
27223	// camera matrices cache
27224
27225	const _projScreenMatrix = new Matrix4();
27226
27227	const _vector3 = new Vector3();
27228
27229	const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
27230
27231	function getTargetPixelRatio() {
27232
27233		return _currentRenderTarget === null ? _pixelRatio : 1;
27234
27235	}
27236
27237	// initialize
27238
27239	let _gl = _context;
27240
27241	function getContext( contextNames, contextAttributes ) {
27242
27243		for ( let i = 0; i < contextNames.length; i ++ ) {
27244
27245			const contextName = contextNames[ i ];
27246			const context = _canvas.getContext( contextName, contextAttributes );
27247			if ( context !== null ) return context;
27248
27249		}
27250
27251		return null;
27252
27253	}
27254
27255	try {
27256
27257		const contextAttributes = {
27258			alpha: true,
27259			depth: _depth,
27260			stencil: _stencil,
27261			antialias: _antialias,
27262			premultipliedAlpha: _premultipliedAlpha,
27263			preserveDrawingBuffer: _preserveDrawingBuffer,
27264			powerPreference: _powerPreference,
27265			failIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat
27266		};
27267
27268		// OffscreenCanvas does not have setAttribute, see #22811
27269		if ( 'setAttribute' in _canvas ) _canvas.setAttribute( 'data-engine', `three.js r${REVISION}` );
27270
27271		// event listeners must be registered before WebGL context is created, see #12753
27272		_canvas.addEventListener( 'webglcontextlost', onContextLost, false );
27273		_canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
27274		_canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false );
27275
27276		if ( _gl === null ) {
27277
27278			const contextNames = [ 'webgl2', 'webgl', 'experimental-webgl' ];
27279
27280			if ( _this.isWebGL1Renderer === true ) {
27281
27282				contextNames.shift();
27283
27284			}
27285
27286			_gl = getContext( contextNames, contextAttributes );
27287
27288			if ( _gl === null ) {
27289
27290				if ( getContext( contextNames ) ) {
27291
27292					throw new Error( 'Error creating WebGL context with your selected attributes.' );
27293
27294				} else {
27295
27296					throw new Error( 'Error creating WebGL context.' );
27297
27298				}
27299
27300			}
27301
27302		}
27303
27304		// Some experimental-webgl implementations do not have getShaderPrecisionFormat
27305
27306		if ( _gl.getShaderPrecisionFormat === undefined ) {
27307
27308			_gl.getShaderPrecisionFormat = function () {
27309
27310				return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
27311
27312			};
27313
27314		}
27315
27316	} catch ( error ) {
27317
27318		console.error( 'THREE.WebGLRenderer: ' + error.message );
27319		throw error;
27320
27321	}
27322
27323	let extensions, capabilities, state, info;
27324	let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
27325	let programCache, materials, renderLists, renderStates, clipping, shadowMap;
27326
27327	let background, morphtargets, bufferRenderer, indexedBufferRenderer;
27328
27329	let utils, bindingStates, uniformsGroups;
27330
27331	function initGLContext() {
27332
27333		extensions = new WebGLExtensions( _gl );
27334
27335		capabilities = new WebGLCapabilities( _gl, extensions, parameters );
27336
27337		extensions.init( capabilities );
27338
27339		utils = new WebGLUtils( _gl, extensions, capabilities );
27340
27341		state = new WebGLState( _gl, extensions, capabilities );
27342
27343		info = new WebGLInfo();
27344		properties = new WebGLProperties();
27345		textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
27346		cubemaps = new WebGLCubeMaps( _this );
27347		cubeuvmaps = new WebGLCubeUVMaps( _this );
27348		attributes = new WebGLAttributes( _gl, capabilities );
27349		bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
27350		geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
27351		objects = new WebGLObjects( _gl, geometries, attributes, info );
27352		morphtargets = new WebGLMorphtargets( _gl, capabilities, textures );
27353		clipping = new WebGLClipping( properties );
27354		programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );
27355		materials = new WebGLMaterials( _this, properties );
27356		renderLists = new WebGLRenderLists();
27357		renderStates = new WebGLRenderStates( extensions, capabilities );
27358		background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, _premultipliedAlpha );
27359		shadowMap = new WebGLShadowMap( _this, objects, capabilities );
27360		uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state );
27361
27362		bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
27363		indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
27364
27365		info.programs = programCache.programs;
27366
27367		_this.capabilities = capabilities;
27368		_this.extensions = extensions;
27369		_this.properties = properties;
27370		_this.renderLists = renderLists;
27371		_this.shadowMap = shadowMap;
27372		_this.state = state;
27373		_this.info = info;
27374
27375	}
27376
27377	initGLContext();
27378
27379	// xr
27380
27381	const xr = new WebXRManager( _this, _gl );
27382
27383	this.xr = xr;
27384
27385	// API
27386
27387	this.getContext = function () {
27388
27389		return _gl;
27390
27391	};
27392
27393	this.getContextAttributes = function () {
27394
27395		return _gl.getContextAttributes();
27396
27397	};
27398
27399	this.forceContextLoss = function () {
27400
27401		const extension = extensions.get( 'WEBGL_lose_context' );
27402		if ( extension ) extension.loseContext();
27403
27404	};
27405
27406	this.forceContextRestore = function () {
27407
27408		const extension = extensions.get( 'WEBGL_lose_context' );
27409		if ( extension ) extension.restoreContext();
27410
27411	};
27412
27413	this.getPixelRatio = function () {
27414
27415		return _pixelRatio;
27416
27417	};
27418
27419	this.setPixelRatio = function ( value ) {
27420
27421		if ( value === undefined ) return;
27422
27423		_pixelRatio = value;
27424
27425		this.setSize( _width, _height, false );
27426
27427	};
27428
27429	this.getSize = function ( target ) {
27430
27431		return target.set( _width, _height );
27432
27433	};
27434
27435	this.setSize = function ( width, height, updateStyle = true ) {
27436
27437		if ( xr.isPresenting ) {
27438
27439			console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
27440			return;
27441
27442		}
27443
27444		_width = width;
27445		_height = height;
27446
27447		_canvas.width = Math.floor( width * _pixelRatio );
27448		_canvas.height = Math.floor( height * _pixelRatio );
27449
27450		if ( updateStyle === true ) {
27451
27452			_canvas.style.width = width + 'px';
27453			_canvas.style.height = height + 'px';
27454
27455		}
27456
27457		this.setViewport( 0, 0, width, height );
27458
27459	};
27460
27461	this.getDrawingBufferSize = function ( target ) {
27462
27463		return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
27464
27465	};
27466
27467	this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
27468
27469		_width = width;
27470		_height = height;
27471
27472		_pixelRatio = pixelRatio;
27473
27474		_canvas.width = Math.floor( width * pixelRatio );
27475		_canvas.height = Math.floor( height * pixelRatio );
27476
27477		this.setViewport( 0, 0, width, height );
27478
27479	};
27480
27481	this.getCurrentViewport = function ( target ) {
27482
27483		return target.copy( _currentViewport );
27484
27485	};
27486
27487	this.getViewport = function ( target ) {
27488
27489		return target.copy( _viewport );
27490
27491	};
27492
27493	this.setViewport = function ( x, y, width, height ) {
27494
27495		if ( x.isVector4 ) {
27496
27497			_viewport.set( x.x, x.y, x.z, x.w );
27498
27499		} else {
27500
27501			_viewport.set( x, y, width, height );
27502
27503		}
27504
27505		state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
27506
27507	};
27508
27509	this.getScissor = function ( target ) {
27510
27511		return target.copy( _scissor );
27512
27513	};
27514
27515	this.setScissor = function ( x, y, width, height ) {
27516
27517		if ( x.isVector4 ) {
27518
27519			_scissor.set( x.x, x.y, x.z, x.w );
27520
27521		} else {
27522
27523			_scissor.set( x, y, width, height );
27524
27525		}
27526
27527		state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
27528
27529	};
27530
27531	this.getScissorTest = function () {
27532
27533		return _scissorTest;
27534
27535	};
27536
27537	this.setScissorTest = function ( boolean ) {
27538
27539		state.setScissorTest( _scissorTest = boolean );
27540
27541	};
27542
27543	this.setOpaqueSort = function ( method ) {
27544
27545		_opaqueSort = method;
27546
27547	};
27548
27549	this.setTransparentSort = function ( method ) {
27550
27551		_transparentSort = method;
27552
27553	};
27554
27555	// Clearing
27556
27557	this.getClearColor = function ( target ) {
27558
27559		return target.copy( background.getClearColor() );
27560
27561	};
27562
27563	this.setClearColor = function () {
27564
27565		background.setClearColor.apply( background, arguments );
27566
27567	};
27568
27569	this.getClearAlpha = function () {
27570
27571		return background.getClearAlpha();
27572
27573	};
27574
27575	this.setClearAlpha = function () {
27576
27577		background.setClearAlpha.apply( background, arguments );
27578
27579	};
27580
27581	this.clear = function ( color = true, depth = true, stencil = true ) {
27582
27583		let bits = 0;
27584
27585		if ( color ) bits |= 16384;
27586		if ( depth ) bits |= 256;
27587		if ( stencil ) bits |= 1024;
27588
27589		_gl.clear( bits );
27590
27591	};
27592
27593	this.clearColor = function () {
27594
27595		this.clear( true, false, false );
27596
27597	};
27598
27599	this.clearDepth = function () {
27600
27601		this.clear( false, true, false );
27602
27603	};
27604
27605	this.clearStencil = function () {
27606
27607		this.clear( false, false, true );
27608
27609	};
27610
27611	//
27612
27613	this.dispose = function () {
27614
27615		_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
27616		_canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
27617		_canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false );
27618
27619		renderLists.dispose();
27620		renderStates.dispose();
27621		properties.dispose();
27622		cubemaps.dispose();
27623		cubeuvmaps.dispose();
27624		objects.dispose();
27625		bindingStates.dispose();
27626		uniformsGroups.dispose();
27627		programCache.dispose();
27628
27629		xr.dispose();
27630
27631		xr.removeEventListener( 'sessionstart', onXRSessionStart );
27632		xr.removeEventListener( 'sessionend', onXRSessionEnd );
27633
27634		if ( _transmissionRenderTarget ) {
27635
27636			_transmissionRenderTarget.dispose();
27637			_transmissionRenderTarget = null;
27638
27639		}
27640
27641		animation.stop();
27642
27643	};
27644
27645	// Events
27646
27647	function onContextLost( event ) {
27648
27649		event.preventDefault();
27650
27651		console.log( 'THREE.WebGLRenderer: Context Lost.' );
27652
27653		_isContextLost = true;
27654
27655	}
27656
27657	function onContextRestore( /* event */ ) {
27658
27659		console.log( 'THREE.WebGLRenderer: Context Restored.' );
27660
27661		_isContextLost = false;
vendor: 4,782 bytes, lines 27662-27891
27662
27663		const infoAutoReset = info.autoReset;
27664		const shadowMapEnabled = shadowMap.enabled;
27665		const shadowMapAutoUpdate = shadowMap.autoUpdate;
27666		const shadowMapNeedsUpdate = shadowMap.needsUpdate;
27667		const shadowMapType = shadowMap.type;
27668
27669		initGLContext();
27670
27671		info.autoReset = infoAutoReset;
27672		shadowMap.enabled = shadowMapEnabled;
27673		shadowMap.autoUpdate = shadowMapAutoUpdate;
27674		shadowMap.needsUpdate = shadowMapNeedsUpdate;
27675		shadowMap.type = shadowMapType;
27676
27677	}
27678
27679	function onContextCreationError( event ) {
27680
27681		console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage );
27682
27683	}
27684
27685	function onMaterialDispose( event ) {
27686
27687		const material = event.target;
27688
27689		material.removeEventListener( 'dispose', onMaterialDispose );
27690
27691		deallocateMaterial( material );
27692
27693	}
27694
27695	// Buffer deallocation
27696
27697	function deallocateMaterial( material ) {
27698
27699		releaseMaterialProgramReferences( material );
27700
27701		properties.remove( material );
27702
27703	}
27704
27705
27706	function releaseMaterialProgramReferences( material ) {
27707
27708		const programs = properties.get( material ).programs;
27709
27710		if ( programs !== undefined ) {
27711
27712			programs.forEach( function ( program ) {
27713
27714				programCache.releaseProgram( program );
27715
27716			} );
27717
27718			if ( material.isShaderMaterial ) {
27719
27720				programCache.releaseShaderCache( material );
27721
27722			}
27723
27724		}
27725
27726	}
27727
27728	// Buffer rendering
27729
27730	this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
27731
27732		if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
27733
27734		const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
27735
27736		const program = setProgram( camera, scene, geometry, material, object );
27737
27738		state.setMaterial( material, frontFaceCW );
27739
27740		//
27741
27742		let index = geometry.index;
27743		let rangeFactor = 1;
27744
27745		if ( material.wireframe === true ) {
27746
27747			index = geometries.getWireframeAttribute( geometry );
27748			rangeFactor = 2;
27749
27750		}
27751
27752		//
27753
27754		const drawRange = geometry.drawRange;
27755		const position = geometry.attributes.position;
27756
27757		let drawStart = drawRange.start * rangeFactor;
27758		let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor;
27759
27760		if ( group !== null ) {
27761
27762			drawStart = Math.max( drawStart, group.start * rangeFactor );
27763			drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor );
27764
27765		}
27766
27767		if ( index !== null ) {
27768
27769			drawStart = Math.max( drawStart, 0 );
27770			drawEnd = Math.min( drawEnd, index.count );
27771
27772		} else if ( position !== undefined && position !== null ) {
27773
27774			drawStart = Math.max( drawStart, 0 );
27775			drawEnd = Math.min( drawEnd, position.count );
27776
27777		}
27778
27779		const drawCount = drawEnd - drawStart;
27780
27781		if ( drawCount < 0 || drawCount === Infinity ) return;
27782
27783		//
27784
27785		bindingStates.setup( object, material, program, geometry, index );
27786
27787		let attribute;
27788		let renderer = bufferRenderer;
27789
27790		if ( index !== null ) {
27791
27792			attribute = attributes.get( index );
27793
27794			renderer = indexedBufferRenderer;
27795			renderer.setIndex( attribute );
27796
27797		}
27798
27799		//
27800
27801		if ( object.isMesh ) {
27802
27803			if ( material.wireframe === true ) {
27804
27805				state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
27806				renderer.setMode( 1 );
27807
27808			} else {
27809
27810				renderer.setMode( 4 );
27811
27812			}
27813
27814		} else if ( object.isLine ) {
27815
27816			let lineWidth = material.linewidth;
27817
27818			if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
27819
27820			state.setLineWidth( lineWidth * getTargetPixelRatio() );
27821
27822			if ( object.isLineSegments ) {
27823
27824				renderer.setMode( 1 );
27825
27826			} else if ( object.isLineLoop ) {
27827
27828				renderer.setMode( 2 );
27829
27830			} else {
27831
27832				renderer.setMode( 3 );
27833
27834			}
27835
27836		} else if ( object.isPoints ) {
27837
27838			renderer.setMode( 0 );
27839
27840		} else if ( object.isSprite ) {
27841
27842			renderer.setMode( 4 );
27843
27844		}
27845
27846		if ( object.isInstancedMesh ) {
27847
27848			renderer.renderInstances( drawStart, drawCount, object.count );
27849
27850		} else if ( geometry.isInstancedBufferGeometry ) {
27851
27852			const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity;
27853			const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount );
27854
27855			renderer.renderInstances( drawStart, drawCount, instanceCount );
27856
27857		} else {
27858
27859			renderer.render( drawStart, drawCount );
27860
27861		}
27862
27863	};
27864
27865	// Compile
27866
27867	this.compile = function ( scene, camera ) {
27868
27869		function prepare( material, scene, object ) {
27870
27871			if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
27872
27873				material.side = BackSide;
27874				material.needsUpdate = true;
27875				getProgram( material, scene, object );
27876
27877				material.side = FrontSide;
27878				material.needsUpdate = true;
27879				getProgram( material, scene, object );
27880
27881				material.side = DoubleSide;
27882
27883			} else {
27884
27885				getProgram( material, scene, object );
27886
27887			}
27888
27889		}
27890
27891		currentRenderState = renderStates.get( scene );
vendor: 20,613 bytes, lines 27892-28663
27892		currentRenderState.init();
27893
27894		renderStateStack.push( currentRenderState );
27895
27896		scene.traverseVisible( function ( object ) {
27897
27898			if ( object.isLight && object.layers.test( camera.layers ) ) {
27899
27900				currentRenderState.pushLight( object );
27901
27902				if ( object.castShadow ) {
27903
27904					currentRenderState.pushShadow( object );
27905
27906				}
27907
27908			}
27909
27910		} );
27911
27912		currentRenderState.setupLights( _this.useLegacyLights );
27913
27914		scene.traverse( function ( object ) {
27915
27916			const material = object.material;
27917
27918			if ( material ) {
27919
27920				if ( Array.isArray( material ) ) {
27921
27922					for ( let i = 0; i < material.length; i ++ ) {
27923
27924						const material2 = material[ i ];
27925
27926						prepare( material2, scene, object );
27927
27928					}
27929
27930				} else {
27931
27932					prepare( material, scene, object );
27933
27934				}
27935
27936			}
27937
27938		} );
27939
27940		renderStateStack.pop();
27941		currentRenderState = null;
27942
27943	};
27944
27945	// Animation Loop
27946
27947	let onAnimationFrameCallback = null;
27948
27949	function onAnimationFrame( time ) {
27950
27951		if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
27952
27953	}
27954
27955	function onXRSessionStart() {
27956
27957		animation.stop();
27958
27959	}
27960
27961	function onXRSessionEnd() {
27962
27963		animation.start();
27964
27965	}
27966
27967	const animation = new WebGLAnimation();
27968	animation.setAnimationLoop( onAnimationFrame );
27969
27970	if ( typeof self !== 'undefined' ) animation.setContext( self );
27971
27972	this.setAnimationLoop = function ( callback ) {
27973
27974		onAnimationFrameCallback = callback;
27975		xr.setAnimationLoop( callback );
27976
27977		( callback === null ) ? animation.stop() : animation.start();
27978
27979	};
27980
27981	xr.addEventListener( 'sessionstart', onXRSessionStart );
27982	xr.addEventListener( 'sessionend', onXRSessionEnd );
27983
27984	// Rendering
27985
27986	this.render = function ( scene, camera ) {
27987
27988		if ( camera !== undefined && camera.isCamera !== true ) {
27989
27990			console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
27991			return;
27992
27993		}
27994
27995		if ( _isContextLost === true ) return;
27996
27997		// update scene graph
27998
27999		if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
28000
28001		// update camera matrices and frustum
28002
28003		if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
28004
28005		if ( xr.enabled === true && xr.isPresenting === true ) {
28006
28007			if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera );
28008
28009			camera = xr.getCamera(); // use XR camera for rendering
28010
28011		}
28012
28013		//
28014		if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget );
28015
28016		currentRenderState = renderStates.get( scene, renderStateStack.length );
28017		currentRenderState.init();
28018
28019		renderStateStack.push( currentRenderState );
28020
28021		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
28022		_frustum.setFromProjectionMatrix( _projScreenMatrix );
28023
28024		_localClippingEnabled = this.localClippingEnabled;
28025		_clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled );
28026
28027		currentRenderList = renderLists.get( scene, renderListStack.length );
28028		currentRenderList.init();
28029
28030		renderListStack.push( currentRenderList );
28031
28032		projectObject( scene, camera, 0, _this.sortObjects );
28033
28034		currentRenderList.finish();
28035
28036		if ( _this.sortObjects === true ) {
28037
28038			currentRenderList.sort( _opaqueSort, _transparentSort );
28039
28040		}
28041
28042		//
28043
28044		if ( _clippingEnabled === true ) clipping.beginShadows();
28045
28046		const shadowsArray = currentRenderState.state.shadowsArray;
28047
28048		shadowMap.render( shadowsArray, scene, camera );
28049
28050		if ( _clippingEnabled === true ) clipping.endShadows();
28051
28052		//
28053
28054		if ( this.info.autoReset === true ) this.info.reset();
28055
28056		//
28057
28058		background.render( currentRenderList, scene );
28059
28060		// render scene
28061
28062		currentRenderState.setupLights( _this.useLegacyLights );
28063
28064		if ( camera.isArrayCamera ) {
28065
28066			const cameras = camera.cameras;
28067
28068			for ( let i = 0, l = cameras.length; i < l; i ++ ) {
28069
28070				const camera2 = cameras[ i ];
28071
28072				renderScene( currentRenderList, scene, camera2, camera2.viewport );
28073
28074			}
28075
28076		} else {
28077
28078			renderScene( currentRenderList, scene, camera );
28079
28080		}
28081
28082		//
28083
28084		if ( _currentRenderTarget !== null ) {
28085
28086			// resolve multisample renderbuffers to a single-sample texture if necessary
28087
28088			textures.updateMultisampleRenderTarget( _currentRenderTarget );
28089
28090			// Generate mipmap if we're using any kind of mipmap filtering
28091
28092			textures.updateRenderTargetMipmap( _currentRenderTarget );
28093
28094		}
28095
28096		//
28097
28098		if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
28099
28100		// _gl.finish();
28101
28102		bindingStates.resetDefaultState();
28103		_currentMaterialId = - 1;
28104		_currentCamera = null;
28105
28106		renderStateStack.pop();
28107
28108		if ( renderStateStack.length > 0 ) {
28109
28110			currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
28111
28112		} else {
28113
28114			currentRenderState = null;
28115
28116		}
28117
28118		renderListStack.pop();
28119
28120		if ( renderListStack.length > 0 ) {
28121
28122			currentRenderList = renderListStack[ renderListStack.length - 1 ];
28123
28124		} else {
28125
28126			currentRenderList = null;
28127
28128		}
28129
28130	};
28131
28132	function projectObject( object, camera, groupOrder, sortObjects ) {
28133
28134		if ( object.visible === false ) return;
28135
28136		const visible = object.layers.test( camera.layers );
28137
28138		if ( visible ) {
28139
28140			if ( object.isGroup ) {
28141
28142				groupOrder = object.renderOrder;
28143
28144			} else if ( object.isLOD ) {
28145
28146				if ( object.autoUpdate === true ) object.update( camera );
28147
28148			} else if ( object.isLight ) {
28149
28150				currentRenderState.pushLight( object );
28151
28152				if ( object.castShadow ) {
28153
28154					currentRenderState.pushShadow( object );
28155
28156				}
28157
28158			} else if ( object.isSprite ) {
28159
28160				if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
28161
28162					if ( sortObjects ) {
28163
28164						_vector3.setFromMatrixPosition( object.matrixWorld )
28165							.applyMatrix4( _projScreenMatrix );
28166
28167					}
28168
28169					const geometry = objects.update( object );
28170					const material = object.material;
28171
28172					if ( material.visible ) {
28173
28174						currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
28175
28176					}
28177
28178				}
28179
28180			} else if ( object.isMesh || object.isLine || object.isPoints ) {
28181
28182				if ( object.isSkinnedMesh ) {
28183
28184					// update skeleton only once in a frame
28185
28186					if ( object.skeleton.frame !== info.render.frame ) {
28187
28188						object.skeleton.update();
28189						object.skeleton.frame = info.render.frame;
28190
28191					}
28192
28193				}
28194
28195				if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
28196
28197					if ( sortObjects ) {
28198
28199						_vector3.setFromMatrixPosition( object.matrixWorld )
28200							.applyMatrix4( _projScreenMatrix );
28201
28202					}
28203
28204					const geometry = objects.update( object );
28205					const material = object.material;
28206
28207					if ( Array.isArray( material ) ) {
28208
28209						const groups = geometry.groups;
28210
28211						for ( let i = 0, l = groups.length; i < l; i ++ ) {
28212
28213							const group = groups[ i ];
28214							const groupMaterial = material[ group.materialIndex ];
28215
28216							if ( groupMaterial && groupMaterial.visible ) {
28217
28218								currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
28219
28220							}
28221
28222						}
28223
28224					} else if ( material.visible ) {
28225
28226						currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
28227
28228					}
28229
28230				}
28231
28232			}
28233
28234		}
28235
28236		const children = object.children;
28237
28238		for ( let i = 0, l = children.length; i < l; i ++ ) {
28239
28240			projectObject( children[ i ], camera, groupOrder, sortObjects );
28241
28242		}
28243
28244	}
28245
28246	function renderScene( currentRenderList, scene, camera, viewport ) {
28247
28248		const opaqueObjects = currentRenderList.opaque;
28249		const transmissiveObjects = currentRenderList.transmissive;
28250		const transparentObjects = currentRenderList.transparent;
28251
28252		currentRenderState.setupLightsView( camera );
28253
28254		if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera );
28255
28256		if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, scene, camera );
28257
28258		if ( viewport ) state.viewport( _currentViewport.copy( viewport ) );
28259
28260		if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
28261		if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera );
28262		if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
28263
28264		// Ensure depth buffer writing is enabled so it can be cleared on next render
28265
28266		state.buffers.depth.setTest( true );
28267		state.buffers.depth.setMask( true );
28268		state.buffers.color.setMask( true );
28269
28270		state.setPolygonOffset( false );
28271
28272	}
28273
28274	function renderTransmissionPass( opaqueObjects, scene, camera ) {
28275
28276		const isWebGL2 = capabilities.isWebGL2;
28277
28278		if ( _transmissionRenderTarget === null ) {
28279
28280			_transmissionRenderTarget = new WebGLRenderTarget( 1024, 1024, {
28281				generateMipmaps: true,
28282				type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType,
28283				minFilter: LinearMipmapLinearFilter,
28284				samples: ( isWebGL2 && _antialias === true ) ? 4 : 0
28285			} );
28286
28287		}
28288
28289		//
28290
28291		const currentRenderTarget = _this.getRenderTarget();
28292		_this.setRenderTarget( _transmissionRenderTarget );
28293		_this.clear();
28294
28295		// Turn off the features which can affect the frag color for opaque objects pass.
28296		// Otherwise they are applied twice in opaque objects pass and transmission objects pass.
28297		const currentToneMapping = _this.toneMapping;
28298		_this.toneMapping = NoToneMapping;
28299
28300		renderObjects( opaqueObjects, scene, camera );
28301
28302		_this.toneMapping = currentToneMapping;
28303
28304		textures.updateMultisampleRenderTarget( _transmissionRenderTarget );
28305		textures.updateRenderTargetMipmap( _transmissionRenderTarget );
28306
28307		_this.setRenderTarget( currentRenderTarget );
28308
28309	}
28310
28311	function renderObjects( renderList, scene, camera ) {
28312
28313		const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
28314
28315		for ( let i = 0, l = renderList.length; i < l; i ++ ) {
28316
28317			const renderItem = renderList[ i ];
28318
28319			const object = renderItem.object;
28320			const geometry = renderItem.geometry;
28321			const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
28322			const group = renderItem.group;
28323
28324			if ( object.layers.test( camera.layers ) ) {
28325
28326				renderObject( object, scene, camera, geometry, material, group );
28327
28328			}
28329
28330		}
28331
28332	}
28333
28334	function renderObject( object, scene, camera, geometry, material, group ) {
28335
28336		object.onBeforeRender( _this, scene, camera, geometry, material, group );
28337
28338		object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
28339		object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
28340
28341		material.onBeforeRender( _this, scene, camera, geometry, object, group );
28342
28343		if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
28344
28345			material.side = BackSide;
28346			material.needsUpdate = true;
28347			_this.renderBufferDirect( camera, scene, geometry, material, object, group );
28348
28349			material.side = FrontSide;
28350			material.needsUpdate = true;
28351			_this.renderBufferDirect( camera, scene, geometry, material, object, group );
28352
28353			material.side = DoubleSide;
28354
28355		} else {
28356
28357			_this.renderBufferDirect( camera, scene, geometry, material, object, group );
28358
28359		}
28360
28361		object.onAfterRender( _this, scene, camera, geometry, material, group );
28362
28363	}
28364
28365	function getProgram( material, scene, object ) {
28366
28367		if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
28368
28369		const materialProperties = properties.get( material );
28370
28371		const lights = currentRenderState.state.lights;
28372		const shadowsArray = currentRenderState.state.shadowsArray;
28373
28374		const lightsStateVersion = lights.state.version;
28375
28376		const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
28377		const programCacheKey = programCache.getProgramCacheKey( parameters );
28378
28379		let programs = materialProperties.programs;
28380
28381		// always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change
28382
28383		materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
28384		materialProperties.fog = scene.fog;
28385		materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment );
28386
28387		if ( programs === undefined ) {
28388
28389			// new material
28390
28391			material.addEventListener( 'dispose', onMaterialDispose );
28392
28393			programs = new Map();
28394			materialProperties.programs = programs;
28395
28396		}
28397
28398		let program = programs.get( programCacheKey );
28399
28400		if ( program !== undefined ) {
28401
28402			// early out if program and light state is identical
28403
28404			if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) {
28405
28406				updateCommonMaterialProperties( material, parameters );
28407
28408				return program;
28409
28410			}
28411
28412		} else {
28413
28414			parameters.uniforms = programCache.getUniforms( material );
28415
28416			material.onBuild( object, parameters, _this );
28417
28418			material.onBeforeCompile( parameters, _this );
28419
28420			program = programCache.acquireProgram( parameters, programCacheKey );
28421			programs.set( programCacheKey, program );
28422
28423			materialProperties.uniforms = parameters.uniforms;
28424
28425		}
28426
28427		const uniforms = materialProperties.uniforms;
28428
28429		if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) {
28430
28431			uniforms.clippingPlanes = clipping.uniform;
28432
28433		}
28434
28435		updateCommonMaterialProperties( material, parameters );
28436
28437		// store the light setup it was created for
28438
28439		materialProperties.needsLights = materialNeedsLights( material );
28440		materialProperties.lightsStateVersion = lightsStateVersion;
28441
28442		if ( materialProperties.needsLights ) {
28443
28444			// wire up the material to this renderer's lighting state
28445
28446			uniforms.ambientLightColor.value = lights.state.ambient;
28447			uniforms.lightProbe.value = lights.state.probe;
28448			uniforms.directionalLights.value = lights.state.directional;
28449			uniforms.directionalLightShadows.value = lights.state.directionalShadow;
28450			uniforms.spotLights.value = lights.state.spot;
28451			uniforms.spotLightShadows.value = lights.state.spotShadow;
28452			uniforms.rectAreaLights.value = lights.state.rectArea;
28453			uniforms.ltc_1.value = lights.state.rectAreaLTC1;
28454			uniforms.ltc_2.value = lights.state.rectAreaLTC2;
28455			uniforms.pointLights.value = lights.state.point;
28456			uniforms.pointLightShadows.value = lights.state.pointShadow;
28457			uniforms.hemisphereLights.value = lights.state.hemi;
28458
28459			uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
28460			uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
28461			uniforms.spotShadowMap.value = lights.state.spotShadowMap;
28462			uniforms.spotLightMatrix.value = lights.state.spotLightMatrix;
28463			uniforms.spotLightMap.value = lights.state.spotLightMap;
28464			uniforms.pointShadowMap.value = lights.state.pointShadowMap;
28465			uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
28466			// TODO (abelnation): add area lights shadow info to uniforms
28467
28468		}
28469
28470		const progUniforms = program.getUniforms();
28471		const uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, uniforms );
28472
28473		materialProperties.currentProgram = program;
28474		materialProperties.uniformsList = uniformsList;
28475
28476		return program;
28477
28478	}
28479
28480	function updateCommonMaterialProperties( material, parameters ) {
28481
28482		const materialProperties = properties.get( material );
28483
28484		materialProperties.outputEncoding = parameters.outputEncoding;
28485		materialProperties.instancing = parameters.instancing;
28486		materialProperties.skinning = parameters.skinning;
28487		materialProperties.morphTargets = parameters.morphTargets;
28488		materialProperties.morphNormals = parameters.morphNormals;
28489		materialProperties.morphColors = parameters.morphColors;
28490		materialProperties.morphTargetsCount = parameters.morphTargetsCount;
28491		materialProperties.numClippingPlanes = parameters.numClippingPlanes;
28492		materialProperties.numIntersection = parameters.numClipIntersection;
28493		materialProperties.vertexAlphas = parameters.vertexAlphas;
28494		materialProperties.vertexTangents = parameters.vertexTangents;
28495		materialProperties.toneMapping = parameters.toneMapping;
28496
28497	}
28498
28499	function setProgram( camera, scene, geometry, material, object ) {
28500
28501		if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
28502
28503		textures.resetTextureUnits();
28504
28505		const fog = scene.fog;
28506		const environment = material.isMeshStandardMaterial ? scene.environment : null;
28507		const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.encoding : LinearEncoding );
28508		const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
28509		const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4;
28510		const vertexTangents = !! material.normalMap && !! geometry.attributes.tangent;
28511		const morphTargets = !! geometry.morphAttributes.position;
28512		const morphNormals = !! geometry.morphAttributes.normal;
28513		const morphColors = !! geometry.morphAttributes.color;
28514		const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping;
28515
28516		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
28517		const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
28518
28519		const materialProperties = properties.get( material );
28520		const lights = currentRenderState.state.lights;
28521
28522		if ( _clippingEnabled === true ) {
28523
28524			if ( _localClippingEnabled === true || camera !== _currentCamera ) {
28525
28526				const useCache =
28527					camera === _currentCamera &&
28528					material.id === _currentMaterialId;
28529
28530				// we might want to call this function with some ClippingGroup
28531				// object instead of the material, once it becomes feasible
28532				// (#8465, #8379)
28533				clipping.setState( material, camera, useCache );
28534
28535			}
28536
28537		}
28538
28539		//
28540
28541		let needsProgramChange = false;
28542
28543		if ( material.version === materialProperties.__version ) {
28544
28545			if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
28546
28547				needsProgramChange = true;
28548
28549			} else if ( materialProperties.outputEncoding !== encoding ) {
28550
28551				needsProgramChange = true;
28552
28553			} else if ( object.isInstancedMesh && materialProperties.instancing === false ) {
28554
28555				needsProgramChange = true;
28556
28557			} else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) {
28558
28559				needsProgramChange = true;
28560
28561			} else if ( object.isSkinnedMesh && materialProperties.skinning === false ) {
28562
28563				needsProgramChange = true;
28564
28565			} else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) {
28566
28567				needsProgramChange = true;
28568
28569			} else if ( materialProperties.envMap !== envMap ) {
28570
28571				needsProgramChange = true;
28572
28573			} else if ( material.fog === true && materialProperties.fog !== fog ) {
28574
28575				needsProgramChange = true;
28576
28577			} else if ( materialProperties.numClippingPlanes !== undefined &&
28578				( materialProperties.numClippingPlanes !== clipping.numPlanes ||
28579				materialProperties.numIntersection !== clipping.numIntersection ) ) {
28580
28581				needsProgramChange = true;
28582
28583			} else if ( materialProperties.vertexAlphas !== vertexAlphas ) {
28584
28585				needsProgramChange = true;
28586
28587			} else if ( materialProperties.vertexTangents !== vertexTangents ) {
28588
28589				needsProgramChange = true;
28590
28591			} else if ( materialProperties.morphTargets !== morphTargets ) {
28592
28593				needsProgramChange = true;
28594
28595			} else if ( materialProperties.morphNormals !== morphNormals ) {
28596
28597				needsProgramChange = true;
28598
28599			} else if ( materialProperties.morphColors !== morphColors ) {
28600
28601				needsProgramChange = true;
28602
28603			} else if ( materialProperties.toneMapping !== toneMapping ) {
28604
28605				needsProgramChange = true;
28606
28607			} else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) {
28608
28609				needsProgramChange = true;
28610
28611			}
28612
28613		} else {
28614
28615			needsProgramChange = true;
28616			materialProperties.__version = material.version;
28617
28618		}
28619
28620		//
28621
28622		let program = materialProperties.currentProgram;
28623
28624		if ( needsProgramChange === true ) {
28625
28626			program = getProgram( material, scene, object );
28627
28628		}
28629
28630		let refreshProgram = false;
28631		let refreshMaterial = false;
28632		let refreshLights = false;
28633
28634		const p_uniforms = program.getUniforms(),
28635			m_uniforms = materialProperties.uniforms;
28636
28637		if ( state.useProgram( program.program ) ) {
28638
28639			refreshProgram = true;
28640			refreshMaterial = true;
28641			refreshLights = true;
28642
28643		}
28644
28645		if ( material.id !== _currentMaterialId ) {
28646
28647			_currentMaterialId = material.id;
28648
28649			refreshMaterial = true;
28650
28651		}
28652
28653		if ( refreshProgram || _currentCamera !== camera ) {
28654
28655			p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
28656
28657			if ( capabilities.logarithmicDepthBuffer ) {
28658
28659				p_uniforms.setValue( _gl, 'logDepthBufFC',
28660					2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
28661
28662			}
28663
28664			if ( _currentCamera !== camera ) {
28665
28666				_currentCamera = camera;
28667
28668				// lighting uniforms depend on the camera so enforce an update
28669				// now, in case this material supports lights - or later, when
28670				// the next material that does gets activated:
28671
28672				refreshMaterial = true;		// set to true on material change
28673				refreshLights = true;		// remains set until update done
28674
28675			}
28676
28677			// load material specific uniforms
28678			// (shader material also gets them for the sake of genericity)
28679
28680			if ( material.isShaderMaterial ||
28681				material.isMeshPhongMaterial ||
28682				material.isMeshToonMaterial ||
28683				material.isMeshStandardMaterial ||
28684				material.envMap ) {
28685
28686				const uCamPos = p_uniforms.map.cameraPosition;
28687
28688				if ( uCamPos !== undefined ) {
28689
28690					uCamPos.setValue( _gl,
28691						_vector3.setFromMatrixPosition( camera.matrixWorld ) );
28692
28693				}
28694
28695			}
28696
28697			if ( material.isMeshPhongMaterial ||
28698				material.isMeshToonMaterial ||
28699				material.isMeshLambertMaterial ||
28700				material.isMeshBasicMaterial ||
28701				material.isMeshStandardMaterial ||
28702				material.isShaderMaterial ) {
28703
28704				p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
28705
28706			}
28707
28708			if ( material.isMeshPhongMaterial ||
28709				material.isMeshToonMaterial ||
28710				material.isMeshLambertMaterial ||
28711				material.isMeshBasicMaterial ||
28712				material.isMeshStandardMaterial ||
28713				material.isShaderMaterial ||
28714				material.isShadowMaterial ||
28715				object.isSkinnedMesh ) {
28716
28717				p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
28718
28719			}
28720
28721		}
28722
28723		// skinning and morph target uniforms must be set even if material didn't change
28724		// auto-setting of texture unit for bone and morph texture must go before other textures
28725		// otherwise textures used for skinning and morphing can take over texture units reserved for other material textures
28726
28727		if ( object.isSkinnedMesh ) {
28728
28729			p_uniforms.setOptional( _gl, object, 'bindMatrix' );
28730			p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
28731
28732			const skeleton = object.skeleton;
28733
28734			if ( skeleton ) {
28735
28736				if ( capabilities.floatVertexTextures ) {
28737
28738					if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture();
28739
28740					p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
28741					p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );
28742
28743				} else {
28744
28745					console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' );
28746
28747				}
28748
28749			}
28750
28751		}
28752
28753		const morphAttributes = geometry.morphAttributes;
28754
28755		if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined && capabilities.isWebGL2 === true ) ) {
28756
28757			morphtargets.update( object, geometry, program );
28758
28759		}
28760
28761		if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
28762
28763			materialProperties.receiveShadow = object.receiveShadow;
28764			p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
28765
28766		}
28767
28768		// https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512
28769
28770		if ( material.isMeshGouraudMaterial && material.envMap !== null ) {
28771
28772			m_uniforms.envMap.value = envMap;
28773
28774			m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
28775
28776		}
28777
28778		if ( refreshMaterial ) {
28779
28780			p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
28781
28782			if ( materialProperties.needsLights ) {
28783
28784				// the current material requires lighting info
28785
28786				// note: all lighting uniforms are always set correctly
28787				// they simply reference the renderer's state for their
28788				// values
28789				//
28790				// use the current material's .needsUpdate flags to set
28791				// the GL state when required
28792
28793				markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
28794
28795			}
28796
28797			// refresh uniforms common to several materials
28798
28799			if ( fog && material.fog === true ) {
28800
28801				materials.refreshFogUniforms( m_uniforms, fog );
28802
28803			}
28804
28805			materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget );
28806
28807			WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
28808
28809		}
28810
28811		if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
28812
28813			WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
28814			material.uniformsNeedUpdate = false;
vendor: 4,663 bytes, lines 28815-28981
28815
28816		}
28817
28818		if ( material.isSpriteMaterial ) {
28819
28820			p_uniforms.setValue( _gl, 'center', object.center );
28821
28822		}
28823
28824		// common matrices
28825
28826		p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
28827		p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
28828		p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
28829
28830		// UBOs
28831
28832		if ( material.isShaderMaterial || material.isRawShaderMaterial ) {
28833
28834			const groups = material.uniformsGroups;
28835
28836			for ( let i = 0, l = groups.length; i < l; i ++ ) {
28837
28838				if ( capabilities.isWebGL2 ) {
28839
28840					const group = groups[ i ];
28841
28842					uniformsGroups.update( group, program );
28843					uniformsGroups.bind( group, program );
28844
28845				} else {
28846
28847					console.warn( 'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' );
28848
28849				}
28850
28851			}
28852
28853		}
28854
28855		return program;
28856
28857	}
28858
28859	// If uniforms are marked as clean, they don't need to be loaded to the GPU.
28860
28861	function markUniformsLightsNeedsUpdate( uniforms, value ) {
28862
28863		uniforms.ambientLightColor.needsUpdate = value;
28864		uniforms.lightProbe.needsUpdate = value;
28865
28866		uniforms.directionalLights.needsUpdate = value;
28867		uniforms.directionalLightShadows.needsUpdate = value;
28868		uniforms.pointLights.needsUpdate = value;
28869		uniforms.pointLightShadows.needsUpdate = value;
28870		uniforms.spotLights.needsUpdate = value;
28871		uniforms.spotLightShadows.needsUpdate = value;
28872		uniforms.rectAreaLights.needsUpdate = value;
28873		uniforms.hemisphereLights.needsUpdate = value;
28874
28875	}
28876
28877	function materialNeedsLights( material ) {
28878
28879		return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
28880			material.isMeshStandardMaterial || material.isShadowMaterial ||
28881			( material.isShaderMaterial && material.lights === true );
28882
28883	}
28884
28885	this.getActiveCubeFace = function () {
28886
28887		return _currentActiveCubeFace;
28888
28889	};
28890
28891	this.getActiveMipmapLevel = function () {
28892
28893		return _currentActiveMipmapLevel;
28894
28895	};
28896
28897	this.getRenderTarget = function () {
28898
28899		return _currentRenderTarget;
28900
28901	};
28902
28903	this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) {
28904
28905		properties.get( renderTarget.texture ).__webglTexture = colorTexture;
28906		properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture;
28907
28908		const renderTargetProperties = properties.get( renderTarget );
28909		renderTargetProperties.__hasExternalTextures = true;
28910
28911		if ( renderTargetProperties.__hasExternalTextures ) {
28912
28913			renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined;
28914
28915			if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) {
28916
28917				// The multisample_render_to_texture extension doesn't work properly if there
28918				// are midframe flushes and an external depth buffer. Disable use of the extension.
28919				if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) {
28920
28921					console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' );
28922					renderTargetProperties.__useRenderToTexture = false;
28923
28924				}
28925
28926			}
28927
28928		}
28929
28930	};
28931
28932	this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) {
28933
28934		const renderTargetProperties = properties.get( renderTarget );
28935		renderTargetProperties.__webglFramebuffer = defaultFramebuffer;
28936		renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined;
28937
28938	};
28939
28940	this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
28941
28942		_currentRenderTarget = renderTarget;
28943		_currentActiveCubeFace = activeCubeFace;
28944		_currentActiveMipmapLevel = activeMipmapLevel;
28945
28946		let useDefaultFramebuffer = true;
28947		let framebuffer = null;
28948		let isCube = false;
28949		let isRenderTarget3D = false;
28950
28951		if ( renderTarget ) {
28952
28953			const renderTargetProperties = properties.get( renderTarget );
28954
28955			if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) {
28956
28957				// We need to make sure to rebind the framebuffer.
28958				state.bindFramebuffer( 36160, null );
28959				useDefaultFramebuffer = false;
28960
28961			} else if ( renderTargetProperties.__webglFramebuffer === undefined ) {
28962
28963				textures.setupRenderTarget( renderTarget );
28964
28965			} else if ( renderTargetProperties.__hasExternalTextures ) {
28966
28967				// Color and depth texture must be rebound in order for the swapchain to update.
28968				textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture );
28969
28970			}
28971
28972			const texture = renderTarget.texture;
28973
28974			if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
28975
28976				isRenderTarget3D = true;
28977
28978			}
28979
28980			const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
28981
28982			if ( renderTarget.isWebGLCubeRenderTarget ) {
28983
28984				framebuffer = __webglFramebuffer[ activeCubeFace ];
28985				isCube = true;
28986
28987			} else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) {
28988
28989				framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
28990
28991			} else {
28992
28993				framebuffer = __webglFramebuffer;
28994
28995			}
28996
28997			_currentViewport.copy( renderTarget.viewport );
28998			_currentScissor.copy( renderTarget.scissor );
28999			_currentScissorTest = renderTarget.scissorTest;
29000
29001		} else {
29002
29003			_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
29004			_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
29005			_currentScissorTest = _scissorTest;
29006
29007		}
29008
29009		const framebufferBound = state.bindFramebuffer( 36160, framebuffer );
29010
29011		if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) {
29012
29013			state.drawBuffers( renderTarget, framebuffer );
29014
29015		}
29016
29017		state.viewport( _currentViewport );
29018		state.scissor( _currentScissor );
29019		state.setScissorTest( _currentScissorTest );
29020
29021		if ( isCube ) {
29022
29023			const textureProperties = properties.get( renderTarget.texture );
29024			_gl.framebufferTexture2D( 36160, 36064, 34069 + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
29025
29026		} else if ( isRenderTarget3D ) {
29027
29028			const textureProperties = properties.get( renderTarget.texture );
29029			const layer = activeCubeFace || 0;
29030			_gl.framebufferTextureLayer( 36160, 36064, textureProperties.__webglTexture, activeMipmapLevel || 0, layer );
29031
29032		}
29033
29034		_currentMaterialId = - 1; // reset current material to ensure correct uniform bindings
29035
29036	};
29037
29038	this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
29039
29040		if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
29041
29042			console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
29043			return;
29044
29045		}
29046
29047		let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
29048
29049		if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
29050
29051			framebuffer = framebuffer[ activeCubeFaceIndex ];
29052
29053		}
29054
29055		if ( framebuffer ) {
29056
29057			state.bindFramebuffer( 36160, framebuffer );
29058
29059			try {
29060
29061				const texture = renderTarget.texture;
29062				const textureFormat = texture.format;
29063				const textureType = texture.type;
29064
29065				if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {
29066
29067					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
29068					return;
29069
29070				}
29071
29072				const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has( 'EXT_color_buffer_float' ) ) );
29073
29074				if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // Edge and Chrome Mac < 52 (#9513)
29075					! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.has( 'OES_texture_float' ) || extensions.has( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
29076					! halfFloatSupportedByExt ) {
29077
29078					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
29079					return;
29080
29081				}
29082
29083				// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
29084
29085				if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
29086
29087					_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
29088
29089				}
29090
29091			} finally {
29092
29093				// restore framebuffer of current render target if necessary
29094
29095				const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null;
29096				state.bindFramebuffer( 36160, framebuffer );
29097
29098			}
29099
29100		}
29101
29102	};
29103
29104	this.copyFramebufferToTexture = function ( position, texture, level = 0 ) {
29105
29106		const levelScale = Math.pow( 2, - level );
29107		const width = Math.floor( texture.image.width * levelScale );
29108		const height = Math.floor( texture.image.height * levelScale );
29109
29110		textures.setTexture2D( texture, 0 );
29111
29112		_gl.copyTexSubImage2D( 3553, level, 0, 0, position.x, position.y, width, height );
29113
29114		state.unbindTexture();
29115
29116	};
29117
29118	this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
29119
29120		const width = srcTexture.image.width;
29121		const height = srcTexture.image.height;
29122		const glFormat = utils.convert( dstTexture.format );
29123		const glType = utils.convert( dstTexture.type );
29124
29125		textures.setTexture2D( dstTexture, 0 );
29126
29127		// As another texture upload may have changed pixelStorei
29128		// parameters, make sure they are correct for the dstTexture
29129		_gl.pixelStorei( 37440, dstTexture.flipY );
29130		_gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
29131		_gl.pixelStorei( 3317, dstTexture.unpackAlignment );
29132
29133		if ( srcTexture.isDataTexture ) {
29134
29135			_gl.texSubImage2D( 3553, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
29136
29137		} else {
29138
29139			if ( srcTexture.isCompressedTexture ) {
29140
29141				_gl.compressedTexSubImage2D( 3553, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
29142
29143			} else {
29144
29145				_gl.texSubImage2D( 3553, level, position.x, position.y, glFormat, glType, srcTexture.image );
29146
29147			}
29148
29149		}
29150
29151		// Generate mipmaps only when copying level 0
29152		if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( 3553 );
29153
29154		state.unbindTexture();
29155
29156	};
29157
29158	this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) {
29159
29160		if ( _this.isWebGL1Renderer ) {
29161
29162			console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' );
29163			return;
29164
29165		}
29166
29167		const width = sourceBox.max.x - sourceBox.min.x + 1;
29168		const height = sourceBox.max.y - sourceBox.min.y + 1;
29169		const depth = sourceBox.max.z - sourceBox.min.z + 1;
29170		const glFormat = utils.convert( dstTexture.format );
29171		const glType = utils.convert( dstTexture.type );
29172		let glTarget;
29173
29174		if ( dstTexture.isData3DTexture ) {
29175
29176			textures.setTexture3D( dstTexture, 0 );
29177			glTarget = 32879;
29178
29179		} else if ( dstTexture.isDataArrayTexture ) {
29180
29181			textures.setTexture2DArray( dstTexture, 0 );
29182			glTarget = 35866;
29183
29184		} else {
29185
29186			console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' );
29187			return;
29188
29189		}
29190
29191		_gl.pixelStorei( 37440, dstTexture.flipY );
29192		_gl.pixelStorei( 37441, dstTexture.premultiplyAlpha );
29193		_gl.pixelStorei( 3317, dstTexture.unpackAlignment );
29194
29195		const unpackRowLen = _gl.getParameter( 3314 );
29196		const unpackImageHeight = _gl.getParameter( 32878 );
29197		const unpackSkipPixels = _gl.getParameter( 3316 );
29198		const unpackSkipRows = _gl.getParameter( 3315 );
29199		const unpackSkipImages = _gl.getParameter( 32877 );
29200
29201		const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ 0 ] : srcTexture.image;
29202
29203		_gl.pixelStorei( 3314, image.width );
29204		_gl.pixelStorei( 32878, image.height );
29205		_gl.pixelStorei( 3316, sourceBox.min.x );
29206		_gl.pixelStorei( 3315, sourceBox.min.y );
29207		_gl.pixelStorei( 32877, sourceBox.min.z );
29208
29209		if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
29210
29211			_gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data );
29212
29213		} else {
29214
29215			if ( srcTexture.isCompressedArrayTexture ) {
29216
29217				console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' );
29218				_gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data );
29219
29220			} else {
29221
29222				_gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image );
29223
29224			}
29225
29226		}
29227
29228		_gl.pixelStorei( 3314, unpackRowLen );
29229		_gl.pixelStorei( 32878, unpackImageHeight );
29230		_gl.pixelStorei( 3316, unpackSkipPixels );
29231		_gl.pixelStorei( 3315, unpackSkipRows );
29232		_gl.pixelStorei( 32877, unpackSkipImages );
29233
29234		// Generate mipmaps only when copying level 0
29235		if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget );
29236
29237		state.unbindTexture();
29238
29239	};
29240
29241	this.initTexture = function ( texture ) {
29242
29243		if ( texture.isCubeTexture ) {
29244
29245			textures.setTextureCube( texture, 0 );
29246
29247		} else if ( texture.isData3DTexture ) {
29248
29249			textures.setTexture3D( texture, 0 );
29250
29251		} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
29252
29253			textures.setTexture2DArray( texture, 0 );
29254
29255		} else {
29256
29257			textures.setTexture2D( texture, 0 );
29258
29259		}
29260
29261		state.unbindTexture();
29262
29263	};
29264
29265	this.resetState = function () {
29266
29267		_currentActiveCubeFace = 0;
29268		_currentActiveMipmapLevel = 0;
29269		_currentRenderTarget = null;
29270
29271		state.reset();
29272		bindingStates.reset();
29273
29274	};
29275
29276	if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
29277
29278		__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
29279
29280	}
29281
29282}
29283
29284Object.defineProperties( WebGLRenderer.prototype, {
29285
29286	// @deprecated since r150
29287
29288	physicallyCorrectLights: {
29289
29290		get: function () {
29291
29292			console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' );
29293			return ! this.useLegacyLights;
29294
29295		},
29296
29297		set: function ( value ) {
29298
29299			console.warn( 'THREE.WebGLRenderer: the property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead.' );
29300			this.useLegacyLights = ! value;
29301
29302		}
29303
29304	}
29305
29306} );
29307
29308class WebGL1Renderer extends WebGLRenderer {}
29309
29310WebGL1Renderer.prototype.isWebGL1Renderer = true;
29311
29312class FogExp2 {
vendor: 10,928 bytes, lines 29313-29960
29313
29314	constructor( color, density = 0.00025 ) {
29315
29316		this.isFogExp2 = true;
29317
29318		this.name = '';
29319
29320		this.color = new Color( color );
29321		this.density = density;
29322
29323	}
29324
29325	clone() {
29326
29327		return new FogExp2( this.color, this.density );
29328
29329	}
29330
29331	toJSON( /* meta */ ) {
29332
29333		return {
29334			type: 'FogExp2',
29335			color: this.color.getHex(),
29336			density: this.density
29337		};
29338
29339	}
29340
29341}
29342
29343class Fog {
29344
29345	constructor( color, near = 1, far = 1000 ) {
29346
29347		this.isFog = true;
29348
29349		this.name = '';
29350
29351		this.color = new Color( color );
29352
29353		this.near = near;
29354		this.far = far;
29355
29356	}
29357
29358	clone() {
29359
29360		return new Fog( this.color, this.near, this.far );
29361
29362	}
29363
29364	toJSON( /* meta */ ) {
29365
29366		return {
29367			type: 'Fog',
29368			color: this.color.getHex(),
29369			near: this.near,
29370			far: this.far
29371		};
29372
29373	}
29374
29375}
29376
29377class Scene extends Object3D {
29378
29379	constructor() {
29380
29381		super();
29382
29383		this.isScene = true;
29384
29385		this.type = 'Scene';
29386
29387		this.background = null;
29388		this.environment = null;
29389		this.fog = null;
29390
29391		this.backgroundBlurriness = 0;
29392		this.backgroundIntensity = 1;
29393
29394		this.overrideMaterial = null;
29395
29396		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
29397
29398			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
29399
29400		}
29401
29402	}
29403
29404	copy( source, recursive ) {
29405
29406		super.copy( source, recursive );
29407
29408		if ( source.background !== null ) this.background = source.background.clone();
29409		if ( source.environment !== null ) this.environment = source.environment.clone();
29410		if ( source.fog !== null ) this.fog = source.fog.clone();
29411
29412		this.backgroundBlurriness = source.backgroundBlurriness;
29413		this.backgroundIntensity = source.backgroundIntensity;
29414
29415		if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
29416
29417		this.matrixAutoUpdate = source.matrixAutoUpdate;
29418
29419		return this;
29420
29421	}
29422
29423	toJSON( meta ) {
29424
29425		const data = super.toJSON( meta );
29426
29427		if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
29428		if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness;
29429		if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity;
29430
29431		return data;
29432
29433	}
29434
29435	// @deprecated
29436
29437	get autoUpdate() {
29438
29439		console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' );
29440		return this.matrixWorldAutoUpdate;
29441
29442	}
29443
29444	set autoUpdate( value ) {
29445
29446		console.warn( 'THREE.Scene: autoUpdate was renamed to matrixWorldAutoUpdate in r144.' );
29447		this.matrixWorldAutoUpdate = value;
29448
29449	}
29450
29451}
29452
29453class InterleavedBuffer {
29454
29455	constructor( array, stride ) {
29456
29457		this.isInterleavedBuffer = true;
29458
29459		this.array = array;
29460		this.stride = stride;
29461		this.count = array !== undefined ? array.length / stride : 0;
29462
29463		this.usage = StaticDrawUsage;
29464		this.updateRange = { offset: 0, count: - 1 };
29465
29466		this.version = 0;
29467
29468		this.uuid = generateUUID();
29469
29470	}
29471
29472	onUploadCallback() {}
29473
29474	set needsUpdate( value ) {
29475
29476		if ( value === true ) this.version ++;
29477
29478	}
29479
29480	setUsage( value ) {
29481
29482		this.usage = value;
29483
29484		return this;
29485
29486	}
29487
29488	copy( source ) {
29489
29490		this.array = new source.array.constructor( source.array );
29491		this.count = source.count;
29492		this.stride = source.stride;
29493		this.usage = source.usage;
29494
29495		return this;
29496
29497	}
29498
29499	copyAt( index1, attribute, index2 ) {
29500
29501		index1 *= this.stride;
29502		index2 *= attribute.stride;
29503
29504		for ( let i = 0, l = this.stride; i < l; i ++ ) {
29505
29506			this.array[ index1 + i ] = attribute.array[ index2 + i ];
29507
29508		}
29509
29510		return this;
29511
29512	}
29513
29514	set( value, offset = 0 ) {
29515
29516		this.array.set( value, offset );
29517
29518		return this;
29519
29520	}
29521
29522	clone( data ) {
29523
29524		if ( data.arrayBuffers === undefined ) {
29525
29526			data.arrayBuffers = {};
29527
29528		}
29529
29530		if ( this.array.buffer._uuid === undefined ) {
29531
29532			this.array.buffer._uuid = generateUUID();
29533
29534		}
29535
29536		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
29537
29538			data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
29539
29540		}
29541
29542		const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
29543
29544		const ib = new this.constructor( array, this.stride );
29545		ib.setUsage( this.usage );
29546
29547		return ib;
29548
29549	}
29550
29551	onUpload( callback ) {
29552
29553		this.onUploadCallback = callback;
29554
29555		return this;
29556
29557	}
29558
29559	toJSON( data ) {
29560
29561		if ( data.arrayBuffers === undefined ) {
29562
29563			data.arrayBuffers = {};
29564
29565		}
29566
29567		// generate UUID for array buffer if necessary
29568
29569		if ( this.array.buffer._uuid === undefined ) {
29570
29571			this.array.buffer._uuid = generateUUID();
29572
29573		}
29574
29575		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
29576
29577			data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) );
29578
29579		}
29580
29581		//
29582
29583		return {
29584			uuid: this.uuid,
29585			buffer: this.array.buffer._uuid,
29586			type: this.array.constructor.name,
29587			stride: this.stride
29588		};
29589
29590	}
29591
29592}
29593
29594const _vector$6 = /*@__PURE__*/ new Vector3();
29595
29596class InterleavedBufferAttribute {
29597
29598	constructor( interleavedBuffer, itemSize, offset, normalized = false ) {
29599
29600		this.isInterleavedBufferAttribute = true;
29601
29602		this.name = '';
29603
29604		this.data = interleavedBuffer;
29605		this.itemSize = itemSize;
29606		this.offset = offset;
29607
29608		this.normalized = normalized;
29609
29610	}
29611
29612	get count() {
29613
29614		return this.data.count;
29615
29616	}
29617
29618	get array() {
29619
29620		return this.data.array;
29621
29622	}
29623
29624	set needsUpdate( value ) {
29625
29626		this.data.needsUpdate = value;
29627
29628	}
29629
29630	applyMatrix4( m ) {
29631
29632		for ( let i = 0, l = this.data.count; i < l; i ++ ) {
29633
29634			_vector$6.fromBufferAttribute( this, i );
29635
29636			_vector$6.applyMatrix4( m );
29637
29638			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
29639
29640		}
29641
29642		return this;
29643
29644	}
29645
29646	applyNormalMatrix( m ) {
29647
29648		for ( let i = 0, l = this.count; i < l; i ++ ) {
29649
29650			_vector$6.fromBufferAttribute( this, i );
29651
29652			_vector$6.applyNormalMatrix( m );
29653
29654			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
29655
29656		}
29657
29658		return this;
29659
29660	}
29661
29662	transformDirection( m ) {
29663
29664		for ( let i = 0, l = this.count; i < l; i ++ ) {
29665
29666			_vector$6.fromBufferAttribute( this, i );
29667
29668			_vector$6.transformDirection( m );
29669
29670			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
29671
29672		}
29673
29674		return this;
29675
29676	}
29677
29678	setX( index, x ) {
29679
29680		if ( this.normalized ) x = normalize( x, this.array );
29681
29682		this.data.array[ index * this.data.stride + this.offset ] = x;
29683
29684		return this;
29685
29686	}
29687
29688	setY( index, y ) {
29689
29690		if ( this.normalized ) y = normalize( y, this.array );
29691
29692		this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
29693
29694		return this;
29695
29696	}
29697
29698	setZ( index, z ) {
29699
29700		if ( this.normalized ) z = normalize( z, this.array );
29701
29702		this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
29703
29704		return this;
29705
29706	}
29707
29708	setW( index, w ) {
29709
29710		if ( this.normalized ) w = normalize( w, this.array );
29711
29712		this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
29713
29714		return this;
29715
29716	}
29717
29718	getX( index ) {
29719
29720		let x = this.data.array[ index * this.data.stride + this.offset ];
29721
29722		if ( this.normalized ) x = denormalize( x, this.array );
29723
29724		return x;
29725
29726	}
29727
29728	getY( index ) {
29729
29730		let y = this.data.array[ index * this.data.stride + this.offset + 1 ];
29731
29732		if ( this.normalized ) y = denormalize( y, this.array );
29733
29734		return y;
29735
29736	}
29737
29738	getZ( index ) {
29739
29740		let z = this.data.array[ index * this.data.stride + this.offset + 2 ];
29741
29742		if ( this.normalized ) z = denormalize( z, this.array );
29743
29744		return z;
29745
29746	}
29747
29748	getW( index ) {
29749
29750		let w = this.data.array[ index * this.data.stride + this.offset + 3 ];
29751
29752		if ( this.normalized ) w = denormalize( w, this.array );
29753
29754		return w;
29755
29756	}
29757
29758	setXY( index, x, y ) {
29759
29760		index = index * this.data.stride + this.offset;
29761
29762		if ( this.normalized ) {
29763
29764			x = normalize( x, this.array );
29765			y = normalize( y, this.array );
29766
29767		}
29768
29769		this.data.array[ index + 0 ] = x;
29770		this.data.array[ index + 1 ] = y;
29771
29772		return this;
29773
29774	}
29775
29776	setXYZ( index, x, y, z ) {
29777
29778		index = index * this.data.stride + this.offset;
29779
29780		if ( this.normalized ) {
29781
29782			x = normalize( x, this.array );
29783			y = normalize( y, this.array );
29784			z = normalize( z, this.array );
29785
29786		}
29787
29788		this.data.array[ index + 0 ] = x;
29789		this.data.array[ index + 1 ] = y;
29790		this.data.array[ index + 2 ] = z;
29791
29792		return this;
29793
29794	}
29795
29796	setXYZW( index, x, y, z, w ) {
29797
29798		index = index * this.data.stride + this.offset;
29799
29800		if ( this.normalized ) {
29801
29802			x = normalize( x, this.array );
29803			y = normalize( y, this.array );
29804			z = normalize( z, this.array );
29805			w = normalize( w, this.array );
29806
29807		}
29808
29809		this.data.array[ index + 0 ] = x;
29810		this.data.array[ index + 1 ] = y;
29811		this.data.array[ index + 2 ] = z;
29812		this.data.array[ index + 3 ] = w;
29813
29814		return this;
29815
29816	}
29817
29818	clone( data ) {
29819
29820		if ( data === undefined ) {
29821
29822			console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' );
29823
29824			const array = [];
29825
29826			for ( let i = 0; i < this.count; i ++ ) {
29827
29828				const index = i * this.data.stride + this.offset;
29829
29830				for ( let j = 0; j < this.itemSize; j ++ ) {
29831
29832					array.push( this.data.array[ index + j ] );
29833
29834				}
29835
29836			}
29837
29838			return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
29839
29840		} else {
29841
29842			if ( data.interleavedBuffers === undefined ) {
29843
29844				data.interleavedBuffers = {};
29845
29846			}
29847
29848			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
29849
29850				data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
29851
29852			}
29853
29854			return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
29855
29856		}
29857
29858	}
29859
29860	toJSON( data ) {
29861
29862		if ( data === undefined ) {
29863
29864			console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' );
29865
29866			const array = [];
29867
29868			for ( let i = 0; i < this.count; i ++ ) {
29869
29870				const index = i * this.data.stride + this.offset;
29871
29872				for ( let j = 0; j < this.itemSize; j ++ ) {
29873
29874					array.push( this.data.array[ index + j ] );
29875
29876				}
29877
29878			}
29879
29880			// de-interleave data and save it as an ordinary buffer attribute for now
29881
29882			return {
29883				itemSize: this.itemSize,
29884				type: this.array.constructor.name,
29885				array: array,
29886				normalized: this.normalized
29887			};
29888
29889		} else {
29890
29891			// save as true interleaved attribute
29892
29893			if ( data.interleavedBuffers === undefined ) {
29894
29895				data.interleavedBuffers = {};
29896
29897			}
29898
29899			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
29900
29901				data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
29902
29903			}
29904
29905			return {
29906				isInterleavedBufferAttribute: true,
29907				itemSize: this.itemSize,
29908				data: this.data.uuid,
29909				offset: this.offset,
29910				normalized: this.normalized
29911			};
29912
29913		}
29914
29915	}
29916
29917}
29918
29919class SpriteMaterial extends Material {
29920
29921	constructor( parameters ) {
29922
29923		super();
29924
29925		this.isSpriteMaterial = true;
29926
29927		this.type = 'SpriteMaterial';
29928
29929		this.color = new Color( 0xffffff );
29930
29931		this.map = null;
29932
29933		this.alphaMap = null;
29934
29935		this.rotation = 0;
29936
29937		this.sizeAttenuation = true;
29938
29939		this.transparent = true;
29940
29941		this.fog = true;
29942
29943		this.setValues( parameters );
29944
29945	}
29946
29947	copy( source ) {
29948
29949		super.copy( source );
29950
29951		this.color.copy( source.color );
29952
29953		this.map = source.map;
29954
29955		this.alphaMap = source.alphaMap;
29956
29957		this.rotation = source.rotation;
29958
29959		this.sizeAttenuation = source.sizeAttenuation;
29960
vendor: 6,754 bytes, lines 29961-30297
29961		this.fog = source.fog;
29962
29963		return this;
29964
29965	}
29966
29967}
29968
29969let _geometry;
29970
29971const _intersectPoint = /*@__PURE__*/ new Vector3();
29972const _worldScale = /*@__PURE__*/ new Vector3();
29973const _mvPosition = /*@__PURE__*/ new Vector3();
29974
29975const _alignedPosition = /*@__PURE__*/ new Vector2();
29976const _rotatedPosition = /*@__PURE__*/ new Vector2();
29977const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
29978
29979const _vA = /*@__PURE__*/ new Vector3();
29980const _vB = /*@__PURE__*/ new Vector3();
29981const _vC = /*@__PURE__*/ new Vector3();
29982
29983const _uvA = /*@__PURE__*/ new Vector2();
29984const _uvB = /*@__PURE__*/ new Vector2();
29985const _uvC = /*@__PURE__*/ new Vector2();
29986
29987class Sprite extends Object3D {
29988
29989	constructor( material ) {
29990
29991		super();
29992
29993		this.isSprite = true;
29994
29995		this.type = 'Sprite';
29996
29997		if ( _geometry === undefined ) {
29998
29999			_geometry = new BufferGeometry();
30000
30001			const float32Array = new Float32Array( [
30002				- 0.5, - 0.5, 0, 0, 0,
30003				0.5, - 0.5, 0, 1, 0,
30004				0.5, 0.5, 0, 1, 1,
30005				- 0.5, 0.5, 0, 0, 1
30006			] );
30007
30008			const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
30009
30010			_geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
30011			_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
30012			_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
30013
30014		}
30015
30016		this.geometry = _geometry;
30017		this.material = ( material !== undefined ) ? material : new SpriteMaterial();
30018
30019		this.center = new Vector2( 0.5, 0.5 );
30020
30021	}
30022
30023	raycast( raycaster, intersects ) {
30024
30025		if ( raycaster.camera === null ) {
30026
30027			console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
30028
30029		}
30030
30031		_worldScale.setFromMatrixScale( this.matrixWorld );
30032
30033		_viewWorldMatrix.copy( raycaster.camera.matrixWorld );
30034		this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
30035
30036		_mvPosition.setFromMatrixPosition( this.modelViewMatrix );
30037
30038		if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
30039
30040			_worldScale.multiplyScalar( - _mvPosition.z );
30041
30042		}
30043
30044		const rotation = this.material.rotation;
30045		let sin, cos;
30046
30047		if ( rotation !== 0 ) {
30048
30049			cos = Math.cos( rotation );
30050			sin = Math.sin( rotation );
30051
30052		}
30053
30054		const center = this.center;
30055
30056		transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30057		transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30058		transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30059
30060		_uvA.set( 0, 0 );
30061		_uvB.set( 1, 0 );
30062		_uvC.set( 1, 1 );
30063
30064		// check first triangle
30065		let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint );
30066
30067		if ( intersect === null ) {
30068
30069			// check second triangle
30070			transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
30071			_uvB.set( 0, 1 );
30072
30073			intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint );
30074			if ( intersect === null ) {
30075
30076				return;
30077
30078			}
30079
30080		}
30081
30082		const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
30083
30084		if ( distance < raycaster.near || distance > raycaster.far ) return;
30085
30086		intersects.push( {
30087
30088			distance: distance,
30089			point: _intersectPoint.clone(),
30090			uv: Triangle.getUV( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ),
30091			face: null,
30092			object: this
30093
30094		} );
30095
30096	}
30097
30098	copy( source, recursive ) {
30099
30100		super.copy( source, recursive );
30101
30102		if ( source.center !== undefined ) this.center.copy( source.center );
30103
30104		this.material = source.material;
30105
30106		return this;
30107
30108	}
30109
30110}
30111
30112function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
30113
30114	// compute position in camera space
30115	_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
30116
30117	// to check if rotation is not zero
30118	if ( sin !== undefined ) {
30119
30120		_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
30121		_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
30122
30123	} else {
30124
30125		_rotatedPosition.copy( _alignedPosition );
30126
30127	}
30128
30129
30130	vertexPosition.copy( mvPosition );
30131	vertexPosition.x += _rotatedPosition.x;
30132	vertexPosition.y += _rotatedPosition.y;
30133
30134	// transform to world space
30135	vertexPosition.applyMatrix4( _viewWorldMatrix );
30136
30137}
30138
30139const _v1$2 = /*@__PURE__*/ new Vector3();
30140const _v2$1 = /*@__PURE__*/ new Vector3();
30141
30142class LOD extends Object3D {
30143
30144	constructor() {
30145
30146		super();
30147
30148		this._currentLevel = 0;
30149
30150		this.type = 'LOD';
30151
30152		Object.defineProperties( this, {
30153			levels: {
30154				enumerable: true,
30155				value: []
30156			},
30157			isLOD: {
30158				value: true,
30159			}
30160		} );
30161
30162		this.autoUpdate = true;
30163
30164	}
30165
30166	copy( source ) {
30167
30168		super.copy( source, false );
30169
30170		const levels = source.levels;
30171
30172		for ( let i = 0, l = levels.length; i < l; i ++ ) {
30173
30174			const level = levels[ i ];
30175
30176			this.addLevel( level.object.clone(), level.distance, level.hysteresis );
30177
30178		}
30179
30180		this.autoUpdate = source.autoUpdate;
30181
30182		return this;
30183
30184	}
30185
30186	addLevel( object, distance = 0, hysteresis = 0 ) {
30187
30188		distance = Math.abs( distance );
30189
30190		const levels = this.levels;
30191
30192		let l;
30193
30194		for ( l = 0; l < levels.length; l ++ ) {
30195
30196			if ( distance < levels[ l ].distance ) {
30197
30198				break;
30199
30200			}
30201
30202		}
30203
30204		levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } );
30205
30206		this.add( object );
30207
30208		return this;
30209
30210	}
30211
30212	getCurrentLevel() {
30213
30214		return this._currentLevel;
30215
30216	}
30217
30218
30219
30220	getObjectForDistance( distance ) {
30221
30222		const levels = this.levels;
30223
30224		if ( levels.length > 0 ) {
30225
30226			let i, l;
30227
30228			for ( i = 1, l = levels.length; i < l; i ++ ) {
30229
30230				let levelDistance = levels[ i ].distance;
30231
30232				if ( levels[ i ].object.visible ) {
30233
30234					levelDistance -= levelDistance * levels[ i ].hysteresis;
30235
30236				}
30237
30238				if ( distance < levelDistance ) {
30239
30240					break;
30241
30242				}
30243
30244			}
30245
30246			return levels[ i - 1 ].object;
30247
30248		}
30249
30250		return null;
30251
30252	}
30253
30254	raycast( raycaster, intersects ) {
30255
30256		const levels = this.levels;
30257
30258		if ( levels.length > 0 ) {
30259
30260			_v1$2.setFromMatrixPosition( this.matrixWorld );
30261
30262			const distance = raycaster.ray.origin.distanceTo( _v1$2 );
30263
30264			this.getObjectForDistance( distance ).raycast( raycaster, intersects );
30265
30266		}
30267
30268	}
30269
30270	update( camera ) {
30271
30272		const levels = this.levels;
30273
30274		if ( levels.length > 1 ) {
30275
30276			_v1$2.setFromMatrixPosition( camera.matrixWorld );
30277			_v2$1.setFromMatrixPosition( this.matrixWorld );
30278
30279			const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom;
30280
30281			levels[ 0 ].object.visible = true;
30282
30283			let i, l;
30284
30285			for ( i = 1, l = levels.length; i < l; i ++ ) {
30286
30287				let levelDistance = levels[ i ].distance;
30288
30289				if ( levels[ i ].object.visible ) {
30290
30291					levelDistance -= levelDistance * levels[ i ].hysteresis;
30292
30293				}
30294
30295				if ( distance >= levelDistance ) {
30296
30297					levels[ i - 1 ].object.visible = false;
vendor: 2,147 bytes, lines 30298-30429
30298					levels[ i ].object.visible = true;
30299
30300				} else {
30301
30302					break;
30303
30304				}
30305
30306			}
30307
30308			this._currentLevel = i - 1;
30309
30310			for ( ; i < l; i ++ ) {
30311
30312				levels[ i ].object.visible = false;
30313
30314			}
30315
30316		}
30317
30318	}
30319
30320	toJSON( meta ) {
30321
30322		const data = super.toJSON( meta );
30323
30324		if ( this.autoUpdate === false ) data.object.autoUpdate = false;
30325
30326		data.object.levels = [];
30327
30328		const levels = this.levels;
30329
30330		for ( let i = 0, l = levels.length; i < l; i ++ ) {
30331
30332			const level = levels[ i ];
30333
30334			data.object.levels.push( {
30335				object: level.object.uuid,
30336				distance: level.distance,
30337				hysteresis: level.hysteresis
30338			} );
30339
30340		}
30341
30342		return data;
30343
30344	}
30345
30346}
30347
30348const _basePosition = /*@__PURE__*/ new Vector3();
30349
30350const _skinIndex = /*@__PURE__*/ new Vector4();
30351const _skinWeight = /*@__PURE__*/ new Vector4();
30352
30353const _vector$5 = /*@__PURE__*/ new Vector3();
30354const _matrix = /*@__PURE__*/ new Matrix4();
30355
30356class SkinnedMesh extends Mesh {
30357
30358	constructor( geometry, material ) {
30359
30360		super( geometry, material );
30361
30362		this.isSkinnedMesh = true;
30363
30364		this.type = 'SkinnedMesh';
30365
30366		this.bindMode = 'attached';
30367		this.bindMatrix = new Matrix4();
30368		this.bindMatrixInverse = new Matrix4();
30369
30370	}
30371
30372	copy( source, recursive ) {
30373
30374		super.copy( source, recursive );
30375
30376		this.bindMode = source.bindMode;
30377		this.bindMatrix.copy( source.bindMatrix );
30378		this.bindMatrixInverse.copy( source.bindMatrixInverse );
30379
30380		this.skeleton = source.skeleton;
30381
30382		return this;
30383
30384	}
30385
30386	bind( skeleton, bindMatrix ) {
30387
30388		this.skeleton = skeleton;
30389
30390		if ( bindMatrix === undefined ) {
30391
30392			this.updateMatrixWorld( true );
30393
30394			this.skeleton.calculateInverses();
30395
30396			bindMatrix = this.matrixWorld;
30397
30398		}
30399
30400		this.bindMatrix.copy( bindMatrix );
30401		this.bindMatrixInverse.copy( bindMatrix ).invert();
30402
30403	}
30404
30405	pose() {
30406
30407		this.skeleton.pose();
30408
30409	}
30410
30411	normalizeSkinWeights() {
30412
30413		const vector = new Vector4();
30414
30415		const skinWeight = this.geometry.attributes.skinWeight;
30416
30417		for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
30418
30419			vector.fromBufferAttribute( skinWeight, i );
30420
30421			const scale = 1.0 / vector.manhattanLength();
30422
30423			if ( scale !== Infinity ) {
30424
30425				vector.multiplyScalar( scale );
30426
30427			} else {
30428
30429				vector.set( 1, 0, 0, 0 );
vendor: 17,414 bytes, lines 30429-31311
30429 // do something reasonable
30430
30431			}
30432
30433			skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
30434
30435		}
30436
30437	}
30438
30439	updateMatrixWorld( force ) {
30440
30441		super.updateMatrixWorld( force );
30442
30443		if ( this.bindMode === 'attached' ) {
30444
30445			this.bindMatrixInverse.copy( this.matrixWorld ).invert();
30446
30447		} else if ( this.bindMode === 'detached' ) {
30448
30449			this.bindMatrixInverse.copy( this.bindMatrix ).invert();
30450
30451		} else {
30452
30453			console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
30454
30455		}
30456
30457	}
30458
30459	boneTransform( index, target ) {
30460
30461		const skeleton = this.skeleton;
30462		const geometry = this.geometry;
30463
30464		_skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
30465		_skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
30466
30467		_basePosition.copy( target ).applyMatrix4( this.bindMatrix );
30468
30469		target.set( 0, 0, 0 );
30470
30471		for ( let i = 0; i < 4; i ++ ) {
30472
30473			const weight = _skinWeight.getComponent( i );
30474
30475			if ( weight !== 0 ) {
30476
30477				const boneIndex = _skinIndex.getComponent( i );
30478
30479				_matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
30480
30481				target.addScaledVector( _vector$5.copy( _basePosition ).applyMatrix4( _matrix ), weight );
30482
30483			}
30484
30485		}
30486
30487		return target.applyMatrix4( this.bindMatrixInverse );
30488
30489	}
30490
30491}
30492
30493class Bone extends Object3D {
30494
30495	constructor() {
30496
30497		super();
30498
30499		this.isBone = true;
30500
30501		this.type = 'Bone';
30502
30503	}
30504
30505}
30506
30507class DataTexture extends Texture {
30508
30509	constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, encoding ) {
30510
30511		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
30512
30513		this.isDataTexture = true;
30514
30515		this.image = { data: data, width: width, height: height };
30516
30517		this.generateMipmaps = false;
30518		this.flipY = false;
30519		this.unpackAlignment = 1;
30520
30521	}
30522
30523}
30524
30525const _offsetMatrix = /*@__PURE__*/ new Matrix4();
30526const _identityMatrix = /*@__PURE__*/ new Matrix4();
30527
30528class Skeleton {
30529
30530	constructor( bones = [], boneInverses = [] ) {
30531
30532		this.uuid = generateUUID();
30533
30534		this.bones = bones.slice( 0 );
30535		this.boneInverses = boneInverses;
30536		this.boneMatrices = null;
30537
30538		this.boneTexture = null;
30539		this.boneTextureSize = 0;
30540
30541		this.frame = - 1;
30542
30543		this.init();
30544
30545	}
30546
30547	init() {
30548
30549		const bones = this.bones;
30550		const boneInverses = this.boneInverses;
30551
30552		this.boneMatrices = new Float32Array( bones.length * 16 );
30553
30554		// calculate inverse bone matrices if necessary
30555
30556		if ( boneInverses.length === 0 ) {
30557
30558			this.calculateInverses();
30559
30560		} else {
30561
30562			// handle special case
30563
30564			if ( bones.length !== boneInverses.length ) {
30565
30566				console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
30567
30568				this.boneInverses = [];
30569
30570				for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30571
30572					this.boneInverses.push( new Matrix4() );
30573
30574				}
30575
30576			}
30577
30578		}
30579
30580	}
30581
30582	calculateInverses() {
30583
30584		this.boneInverses.length = 0;
30585
30586		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30587
30588			const inverse = new Matrix4();
30589
30590			if ( this.bones[ i ] ) {
30591
30592				inverse.copy( this.bones[ i ].matrixWorld ).invert();
30593
30594			}
30595
30596			this.boneInverses.push( inverse );
30597
30598		}
30599
30600	}
30601
30602	pose() {
30603
30604		// recover the bind-time world matrices
30605
30606		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30607
30608			const bone = this.bones[ i ];
30609
30610			if ( bone ) {
30611
30612				bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
30613
30614			}
30615
30616		}
30617
30618		// compute the local matrices, positions, rotations and scales
30619
30620		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30621
30622			const bone = this.bones[ i ];
30623
30624			if ( bone ) {
30625
30626				if ( bone.parent && bone.parent.isBone ) {
30627
30628					bone.matrix.copy( bone.parent.matrixWorld ).invert();
30629					bone.matrix.multiply( bone.matrixWorld );
30630
30631				} else {
30632
30633					bone.matrix.copy( bone.matrixWorld );
30634
30635				}
30636
30637				bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
30638
30639			}
30640
30641		}
30642
30643	}
30644
30645	update() {
30646
30647		const bones = this.bones;
30648		const boneInverses = this.boneInverses;
30649		const boneMatrices = this.boneMatrices;
30650		const boneTexture = this.boneTexture;
30651
30652		// flatten bone matrices to array
30653
30654		for ( let i = 0, il = bones.length; i < il; i ++ ) {
30655
30656			// compute the offset between the current and the original transform
30657
30658			const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
30659
30660			_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
30661			_offsetMatrix.toArray( boneMatrices, i * 16 );
30662
30663		}
30664
30665		if ( boneTexture !== null ) {
30666
30667			boneTexture.needsUpdate = true;
30668
30669		}
30670
30671	}
30672
30673	clone() {
30674
30675		return new Skeleton( this.bones, this.boneInverses );
30676
30677	}
30678
30679	computeBoneTexture() {
30680
30681		// layout (1 matrix = 4 pixels)
30682		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
30683		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
30684		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
30685		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
30686		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
30687
30688		let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
30689		size = ceilPowerOfTwo( size );
30690		size = Math.max( size, 4 );
30691
30692		const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
30693		boneMatrices.set( this.boneMatrices ); // copy current values
30694
30695		const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
30696		boneTexture.needsUpdate = true;
30697
30698		this.boneMatrices = boneMatrices;
30699		this.boneTexture = boneTexture;
30700		this.boneTextureSize = size;
30701
30702		return this;
30703
30704	}
30705
30706	getBoneByName( name ) {
30707
30708		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
30709
30710			const bone = this.bones[ i ];
30711
30712			if ( bone.name === name ) {
30713
30714				return bone;
30715
30716			}
30717
30718		}
30719
30720		return undefined;
30721
30722	}
30723
30724	dispose( ) {
30725
30726		if ( this.boneTexture !== null ) {
30727
30728			this.boneTexture.dispose();
30729
30730			this.boneTexture = null;
30731
30732		}
30733
30734	}
30735
30736	fromJSON( json, bones ) {
30737
30738		this.uuid = json.uuid;
30739
30740		for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
30741
30742			const uuid = json.bones[ i ];
30743			let bone = bones[ uuid ];
30744
30745			if ( bone === undefined ) {
30746
30747				console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid );
30748				bone = new Bone();
30749
30750			}
30751
30752			this.bones.push( bone );
30753			this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
30754
30755		}
30756
30757		this.init();
30758
30759		return this;
30760
30761	}
30762
30763	toJSON() {
30764
30765		const data = {
30766			metadata: {
30767				version: 4.5,
30768				type: 'Skeleton',
30769				generator: 'Skeleton.toJSON'
30770			},
30771			bones: [],
30772			boneInverses: []
30773		};
30774
30775		data.uuid = this.uuid;
30776
30777		const bones = this.bones;
30778		const boneInverses = this.boneInverses;
30779
30780		for ( let i = 0, l = bones.length; i < l; i ++ ) {
30781
30782			const bone = bones[ i ];
30783			data.bones.push( bone.uuid );
30784
30785			const boneInverse = boneInverses[ i ];
30786			data.boneInverses.push( boneInverse.toArray() );
30787
30788		}
30789
30790		return data;
30791
30792	}
30793
30794}
30795
30796class InstancedBufferAttribute extends BufferAttribute {
30797
30798	constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {
30799
30800		super( array, itemSize, normalized );
30801
30802		this.isInstancedBufferAttribute = true;
30803
30804		this.meshPerAttribute = meshPerAttribute;
30805
30806	}
30807
30808	copy( source ) {
30809
30810		super.copy( source );
30811
30812		this.meshPerAttribute = source.meshPerAttribute;
30813
30814		return this;
30815
30816	}
30817
30818	toJSON() {
30819
30820		const data = super.toJSON();
30821
30822		data.meshPerAttribute = this.meshPerAttribute;
30823
30824		data.isInstancedBufferAttribute = true;
30825
30826		return data;
30827
30828	}
30829
30830}
30831
30832const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
30833const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
30834
30835const _instanceIntersects = [];
30836
30837const _identity = /*@__PURE__*/ new Matrix4();
30838const _mesh = /*@__PURE__*/ new Mesh();
30839
30840class InstancedMesh extends Mesh {
30841
30842	constructor( geometry, material, count ) {
30843
30844		super( geometry, material );
30845
30846		this.isInstancedMesh = true;
30847
30848		this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
30849		this.instanceColor = null;
30850
30851		this.count = count;
30852
30853		this.frustumCulled = false;
30854
30855		for ( let i = 0; i < count; i ++ ) {
30856
30857			this.setMatrixAt( i, _identity );
30858
30859		}
30860
30861	}
30862
30863	copy( source, recursive ) {
30864
30865		super.copy( source, recursive );
30866
30867		this.instanceMatrix.copy( source.instanceMatrix );
30868
30869		if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
30870
30871		this.count = source.count;
30872
30873		return this;
30874
30875	}
30876
30877	getColorAt( index, color ) {
30878
30879		color.fromArray( this.instanceColor.array, index * 3 );
30880
30881	}
30882
30883	getMatrixAt( index, matrix ) {
30884
30885		matrix.fromArray( this.instanceMatrix.array, index * 16 );
30886
30887	}
30888
30889	raycast( raycaster, intersects ) {
30890
30891		const matrixWorld = this.matrixWorld;
30892		const raycastTimes = this.count;
30893
30894		_mesh.geometry = this.geometry;
30895		_mesh.material = this.material;
30896
30897		if ( _mesh.material === undefined ) return;
30898
30899		for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
30900
30901			// calculate the world matrix for each instance
30902
30903			this.getMatrixAt( instanceId, _instanceLocalMatrix );
30904
30905			_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
30906
30907			// the mesh represents this single instance
30908
30909			_mesh.matrixWorld = _instanceWorldMatrix;
30910
30911			_mesh.raycast( raycaster, _instanceIntersects );
30912
30913			// process the result of raycast
30914
30915			for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
30916
30917				const intersect = _instanceIntersects[ i ];
30918				intersect.instanceId = instanceId;
30919				intersect.object = this;
30920				intersects.push( intersect );
30921
30922			}
30923
30924			_instanceIntersects.length = 0;
30925
30926		}
30927
30928	}
30929
30930	setColorAt( index, color ) {
30931
30932		if ( this.instanceColor === null ) {
30933
30934			this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 );
30935
30936		}
30937
30938		color.toArray( this.instanceColor.array, index * 3 );
30939
30940	}
30941
30942	setMatrixAt( index, matrix ) {
30943
30944		matrix.toArray( this.instanceMatrix.array, index * 16 );
30945
30946	}
30947
30948	updateMorphTargets() {
30949
30950	}
30951
30952	dispose() {
30953
30954		this.dispatchEvent( { type: 'dispose' } );
30955
30956	}
30957
30958}
30959
30960class LineBasicMaterial extends Material {
30961
30962	constructor( parameters ) {
30963
30964		super();
30965
30966		this.isLineBasicMaterial = true;
30967
30968		this.type = 'LineBasicMaterial';
30969
30970		this.color = new Color( 0xffffff );
30971
30972		this.linewidth = 1;
30973		this.linecap = 'round';
30974		this.linejoin = 'round';
30975
30976		this.fog = true;
30977
30978		this.setValues( parameters );
30979
30980	}
30981
30982
30983	copy( source ) {
30984
30985		super.copy( source );
30986
30987		this.color.copy( source.color );
30988
30989		this.linewidth = source.linewidth;
30990		this.linecap = source.linecap;
30991		this.linejoin = source.linejoin;
30992
30993		this.fog = source.fog;
30994
30995		return this;
30996
30997	}
30998
30999}
31000
31001const _start$1 = /*@__PURE__*/ new Vector3();
31002const _end$1 = /*@__PURE__*/ new Vector3();
31003const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4();
31004const _ray$1 = /*@__PURE__*/ new Ray();
31005const _sphere$1 = /*@__PURE__*/ new Sphere();
31006
31007class Line extends Object3D {
31008
31009	constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
31010
31011		super();
31012
31013		this.isLine = true;
31014
31015		this.type = 'Line';
31016
31017		this.geometry = geometry;
31018		this.material = material;
31019
31020		this.updateMorphTargets();
31021
31022	}
31023
31024	copy( source, recursive ) {
31025
31026		super.copy( source, recursive );
31027
31028		this.material = source.material;
31029		this.geometry = source.geometry;
31030
31031		return this;
31032
31033	}
31034
31035	computeLineDistances() {
31036
31037		const geometry = this.geometry;
31038
31039		// we assume non-indexed geometry
31040
31041		if ( geometry.index === null ) {
31042
31043			const positionAttribute = geometry.attributes.position;
31044			const lineDistances = [ 0 ];
31045
31046			for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
31047
31048				_start$1.fromBufferAttribute( positionAttribute, i - 1 );
31049				_end$1.fromBufferAttribute( positionAttribute, i );
31050
31051				lineDistances[ i ] = lineDistances[ i - 1 ];
31052				lineDistances[ i ] += _start$1.distanceTo( _end$1 );
31053
31054			}
31055
31056			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
31057
31058		} else {
31059
31060			console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
31061
31062		}
31063
31064		return this;
31065
31066	}
31067
31068	raycast( raycaster, intersects ) {
31069
31070		const geometry = this.geometry;
31071		const matrixWorld = this.matrixWorld;
31072		const threshold = raycaster.params.Line.threshold;
31073		const drawRange = geometry.drawRange;
31074
31075		// Checking boundingSphere distance to ray
31076
31077		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
31078
31079		_sphere$1.copy( geometry.boundingSphere );
31080		_sphere$1.applyMatrix4( matrixWorld );
31081		_sphere$1.radius += threshold;
31082
31083		if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return;
31084
31085		//
31086
31087		_inverseMatrix$1.copy( matrixWorld ).invert();
31088		_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
31089
31090		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
31091		const localThresholdSq = localThreshold * localThreshold;
31092
31093		const vStart = new Vector3();
31094		const vEnd = new Vector3();
31095		const interSegment = new Vector3();
31096		const interRay = new Vector3();
31097		const step = this.isLineSegments ? 2 : 1;
31098
31099		const index = geometry.index;
31100		const attributes = geometry.attributes;
31101		const positionAttribute = attributes.position;
31102
31103		if ( index !== null ) {
31104
31105			const start = Math.max( 0, drawRange.start );
31106			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
31107
31108			for ( let i = start, l = end - 1; i < l; i += step ) {
31109
31110				const a = index.getX( i );
31111				const b = index.getX( i + 1 );
31112
31113				vStart.fromBufferAttribute( positionAttribute, a );
31114				vEnd.fromBufferAttribute( positionAttribute, b );
31115
31116				const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
31117
31118				if ( distSq > localThresholdSq ) continue;
31119
31120				interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
31121
31122				const distance = raycaster.ray.origin.distanceTo( interRay );
31123
31124				if ( distance < raycaster.near || distance > raycaster.far ) continue;
31125
31126				intersects.push( {
31127
31128					distance: distance,
31129					// What do we want? intersection point on the ray or on the segment??
31130					// point: raycaster.ray.at( distance ),
31131					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
31132					index: i,
31133					face: null,
31134					faceIndex: null,
31135					object: this
31136
31137				} );
31138
31139			}
31140
31141		} else {
31142
31143			const start = Math.max( 0, drawRange.start );
31144			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
31145
31146			for ( let i = start, l = end - 1; i < l; i += step ) {
31147
31148				vStart.fromBufferAttribute( positionAttribute, i );
31149				vEnd.fromBufferAttribute( positionAttribute, i + 1 );
31150
31151				const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
31152
31153				if ( distSq > localThresholdSq ) continue;
31154
31155				interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
31156
31157				const distance = raycaster.ray.origin.distanceTo( interRay );
31158
31159				if ( distance < raycaster.near || distance > raycaster.far ) continue;
31160
31161				intersects.push( {
31162
31163					distance: distance,
31164					// What do we want? intersection point on the ray or on the segment??
31165					// point: raycaster.ray.at( distance ),
31166					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
31167					index: i,
31168					face: null,
31169					faceIndex: null,
31170					object: this
31171
31172				} );
31173
31174			}
31175
31176		}
31177
31178	}
31179
31180	updateMorphTargets() {
31181
31182		const geometry = this.geometry;
31183
31184		const morphAttributes = geometry.morphAttributes;
31185		const keys = Object.keys( morphAttributes );
31186
31187		if ( keys.length > 0 ) {
31188
31189			const morphAttribute = morphAttributes[ keys[ 0 ] ];
31190
31191			if ( morphAttribute !== undefined ) {
31192
31193				this.morphTargetInfluences = [];
31194				this.morphTargetDictionary = {};
31195
31196				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
31197
31198					const name = morphAttribute[ m ].name || String( m );
31199
31200					this.morphTargetInfluences.push( 0 );
31201					this.morphTargetDictionary[ name ] = m;
31202
31203				}
31204
31205			}
31206
31207		}
31208
31209	}
31210
31211}
31212
31213const _start = /*@__PURE__*/ new Vector3();
31214const _end = /*@__PURE__*/ new Vector3();
31215
31216class LineSegments extends Line {
31217
31218	constructor( geometry, material ) {
31219
31220		super( geometry, material );
31221
31222		this.isLineSegments = true;
31223
31224		this.type = 'LineSegments';
31225
31226	}
31227
31228	computeLineDistances() {
31229
31230		const geometry = this.geometry;
31231
31232		// we assume non-indexed geometry
31233
31234		if ( geometry.index === null ) {
31235
31236			const positionAttribute = geometry.attributes.position;
31237			const lineDistances = [];
31238
31239			for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
31240
31241				_start.fromBufferAttribute( positionAttribute, i );
31242				_end.fromBufferAttribute( positionAttribute, i + 1 );
31243
31244				lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
31245				lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
31246
31247			}
31248
31249			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
31250
31251		} else {
31252
31253			console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
31254
31255		}
31256
31257		return this;
31258
31259	}
31260
31261}
31262
31263class LineLoop extends Line {
31264
31265	constructor( geometry, material ) {
31266
31267		super( geometry, material );
31268
31269		this.isLineLoop = true;
31270
31271		this.type = 'LineLoop';
31272
31273	}
31274
31275}
31276
31277class PointsMaterial extends Material {
31278
31279	constructor( parameters ) {
31280
31281		super();
31282
31283		this.isPointsMaterial = true;
31284
31285		this.type = 'PointsMaterial';
31286
31287		this.color = new Color( 0xffffff );
31288
31289		this.map = null;
31290
31291		this.alphaMap = null;
31292
31293		this.size = 1;
31294		this.sizeAttenuation = true;
31295
31296		this.fog = true;
31297
31298		this.setValues( parameters );
31299
31300	}
31301
31302	copy( source ) {
31303
31304		super.copy( source );
31305
31306		this.color.copy( source.color );
31307
31308		this.map = source.map;
31309
31310		this.alphaMap = source.alphaMap;
31311
vendor: 4,136 bytes, lines 31312-31491
31312		this.size = source.size;
31313		this.sizeAttenuation = source.sizeAttenuation;
31314
31315		this.fog = source.fog;
31316
31317		return this;
31318
31319	}
31320
31321}
31322
31323const _inverseMatrix = /*@__PURE__*/ new Matrix4();
31324const _ray = /*@__PURE__*/ new Ray();
31325const _sphere = /*@__PURE__*/ new Sphere();
31326const _position$2 = /*@__PURE__*/ new Vector3();
31327
31328class Points extends Object3D {
31329
31330	constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
31331
31332		super();
31333
31334		this.isPoints = true;
31335
31336		this.type = 'Points';
31337
31338		this.geometry = geometry;
31339		this.material = material;
31340
31341		this.updateMorphTargets();
31342
31343	}
31344
31345	copy( source, recursive ) {
31346
31347		super.copy( source, recursive );
31348
31349		this.material = source.material;
31350		this.geometry = source.geometry;
31351
31352		return this;
31353
31354	}
31355
31356	raycast( raycaster, intersects ) {
31357
31358		const geometry = this.geometry;
31359		const matrixWorld = this.matrixWorld;
31360		const threshold = raycaster.params.Points.threshold;
31361		const drawRange = geometry.drawRange;
31362
31363		// Checking boundingSphere distance to ray
31364
31365		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
31366
31367		_sphere.copy( geometry.boundingSphere );
31368		_sphere.applyMatrix4( matrixWorld );
31369		_sphere.radius += threshold;
31370
31371		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
31372
31373		//
31374
31375		_inverseMatrix.copy( matrixWorld ).invert();
31376		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
31377
31378		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
31379		const localThresholdSq = localThreshold * localThreshold;
31380
31381		const index = geometry.index;
31382		const attributes = geometry.attributes;
31383		const positionAttribute = attributes.position;
31384
31385		if ( index !== null ) {
31386
31387			const start = Math.max( 0, drawRange.start );
31388			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
31389
31390			for ( let i = start, il = end; i < il; i ++ ) {
31391
31392				const a = index.getX( i );
31393
31394				_position$2.fromBufferAttribute( positionAttribute, a );
31395
31396				testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
31397
31398			}
31399
31400		} else {
31401
31402			const start = Math.max( 0, drawRange.start );
31403			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
31404
31405			for ( let i = start, l = end; i < l; i ++ ) {
31406
31407				_position$2.fromBufferAttribute( positionAttribute, i );
31408
31409				testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
31410
31411			}
31412
31413		}
31414
31415	}
31416
31417	updateMorphTargets() {
31418
31419		const geometry = this.geometry;
31420
31421		const morphAttributes = geometry.morphAttributes;
31422		const keys = Object.keys( morphAttributes );
31423
31424		if ( keys.length > 0 ) {
31425
31426			const morphAttribute = morphAttributes[ keys[ 0 ] ];
31427
31428			if ( morphAttribute !== undefined ) {
31429
31430				this.morphTargetInfluences = [];
31431				this.morphTargetDictionary = {};
31432
31433				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
31434
31435					const name = morphAttribute[ m ].name || String( m );
31436
31437					this.morphTargetInfluences.push( 0 );
31438					this.morphTargetDictionary[ name ] = m;
31439
31440				}
31441
31442			}
31443
31444		}
31445
31446	}
31447
31448}
31449
31450function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
31451
31452	const rayPointDistanceSq = _ray.distanceSqToPoint( point );
31453
31454	if ( rayPointDistanceSq < localThresholdSq ) {
31455
31456		const intersectPoint = new Vector3();
31457
31458		_ray.closestPointToPoint( point, intersectPoint );
31459		intersectPoint.applyMatrix4( matrixWorld );
31460
31461		const distance = raycaster.ray.origin.distanceTo( intersectPoint );
31462
31463		if ( distance < raycaster.near || distance > raycaster.far ) return;
31464
31465		intersects.push( {
31466
31467			distance: distance,
31468			distanceToRay: Math.sqrt( rayPointDistanceSq ),
31469			point: intersectPoint,
31470			index: index,
31471			face: null,
31472			object: object
31473
31474		} );
31475
31476	}
31477
31478}
31479
31480class VideoTexture extends Texture {
31481
31482	constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
31483
31484		super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
31485
31486		this.isVideoTexture = true;
31487
31488		this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
31489		this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
31490
31491		this.generateMipmaps = false;
31492
31493		const scope = this;
31494
31495		function updateVideo() {
31496
31497			scope.needsUpdate = true;
31498			video.requestVideoFrameCallback( updateVideo );
31499
31500		}
31501
31502		if ( 'requestVideoFrameCallback' in video ) {
31503
31504			video.requestVideoFrameCallback( updateVideo );
31505
31506		}
31507
31508	}
31509
31510	clone() {
31511
31512		return new this.constructor( this.image ).copy( this );
31513
31514	}
31515
31516	update() {
31517
31518		const video = this.image;
31519		const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
31520
31521		if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
31522
31523			this.needsUpdate = true;
31524
31525		}
31526
31527	}
31528
31529}
31530
31531class FramebufferTexture extends Texture {
31532
31533	constructor( width, height, format ) {
31534
31535		super( { width, height } );
31536
31537		this.isFramebufferTexture = true;
31538
31539		this.format = format;
31540
31541		this.magFilter = NearestFilter;
31542		this.minFilter = NearestFilter;
31543
31544		this.generateMipmaps = false;
31545
31546		this.needsUpdate = true;
31547
31548	}
31549
31550}
31551
31552class CompressedTexture extends Texture {
31553
31554	constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {
31555
31556		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
31557
31558		this.isCompressedTexture = true;
31559
31560		this.image = { width: width, height: height };
31561		this.mipmaps = mipmaps;
31562
31563		// no flipping for cube textures
31564		// (also flipping doesn't work for compressed textures )
31565
31566		this.flipY = false;
31567
31568		// can't generate mipmaps for compressed textures
31569		// mips must be embedded in DDS files
31570
31571		this.generateMipmaps = false;
31572
31573	}
31574
31575}
31576
31577class CompressedArrayTexture extends CompressedTexture {
31578
31579	constructor( mipmaps, width, height, depth, format, type ) {
31580
31581		super( mipmaps, width, height, format, type );
31582
31583		this.isCompressedArrayTexture = true;
31584		this.image.depth = depth;
31585		this.wrapR = ClampToEdgeWrapping;
31586
31587	}
31588
31589}
31590
31591class CanvasTexture extends Texture {
31592
31593	constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
31594
31595		super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
31596
31597		this.isCanvasTexture = true;
31598
31599		this.needsUpdate = true;
31600
31601	}
31602
31603}
31604
31605/**
31606 * Extensible curve object.
31607 *
31608 * Some common of curve methods:
31609 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
31610 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
31611 * .getPoints(), .getSpacedPoints()
31612 * .getLength()
31613 * .updateArcLengths()
31614 *
31615 * This following curves inherit from THREE.Curve:
31616 *
31617 * -- 2D curves --
31618 * THREE.ArcCurve
31619 * THREE.CubicBezierCurve
31620 * THREE.EllipseCurve
31621 * THREE.LineCurve
31622 * THREE.QuadraticBezierCurve
31623 * THREE.SplineCurve
31624 *
31625 * -- 3D curves --
31626 * THREE.CatmullRomCurve3
31627 * THREE.CubicBezierCurve3
31628 * THREE.LineCurve3
31629 * THREE.QuadraticBezierCurve3
31630 *
31631 * A series of curves can be represented as a THREE.CurvePath.
31632 *
31633 **/
31634
31635class Curve {
31636
31637	constructor() {
31638
31639		this.type = 'Curve';
31640
31641		this.arcLengthDivisions = 200;
31642
31643	}
31644
31645	// Virtual base class method to overwrite and implement in subclasses
31646	//	- t [0 .. 1]
31647
31648	getPoint( /* t, optionalTarget */ ) {
31649
31650		console.warn( 'THREE.Curve: .getPoint() not implemented.' );
31651		return null;
31652
31653	}
31654
31655	// Get point at relative position in curve according to arc length
31656	// - u [0 .. 1]
31657
31658	getPointAt( u, optionalTarget ) {
31659
31660		const t = this.getUtoTmapping( u );
31661		return this.getPoint( t, optionalTarget );
31662
31663	}
31664
31665	// Get sequence of points using getPoint( t )
31666
31667	getPoints( divisions = 5 ) {
31668
31669		const points = [];
31670
31671		for ( let d = 0; d <= divisions; d ++ ) {
31672
31673			points.push( this.getPoint( d / divisions ) );
31674
31675		}
31676
31677		return points;
31678
31679	}
31680
31681	// Get sequence of points using getPointAt( u )
31682
31683	getSpacedPoints( divisions = 5 ) {
31684
31685		const points = [];
31686
31687		for ( let d = 0; d <= divisions; d ++ ) {
31688
31689			points.push( this.getPointAt( d / divisions ) );
31690
31691		}
31692
31693		return points;
31694
31695	}
31696
31697	// Get total curve arc length
31698
31699	getLength() {
31700
31701		const lengths = this.getLengths();
31702		return lengths[ lengths.length - 1 ];
31703
31704	}
31705
31706	// Get list of cumulative segment lengths
31707
31708	getLengths( divisions = this.arcLengthDivisions ) {
31709
31710		if ( this.cacheArcLengths &&
31711			( this.cacheArcLengths.length === divisions + 1 ) &&
31712			! this.needsUpdate ) {
31713
31714			return this.cacheArcLengths;
31715
31716		}
31717
31718		this.needsUpdate = false;
vendor: 7,518 bytes, lines 31719-32110
31719
31720		const cache = [];
31721		let current, last = this.getPoint( 0 );
31722		let sum = 0;
31723
31724		cache.push( 0 );
31725
31726		for ( let p = 1; p <= divisions; p ++ ) {
31727
31728			current = this.getPoint( p / divisions );
31729			sum += current.distanceTo( last );
31730			cache.push( sum );
31731			last = current;
31732
31733		}
31734
31735		this.cacheArcLengths = cache;
31736
31737		return cache; // { sums: cache, sum: sum }; Sum is in the last element.
31738
31739	}
31740
31741	updateArcLengths() {
31742
31743		this.needsUpdate = true;
31744		this.getLengths();
31745
31746	}
31747
31748	// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
31749
31750	getUtoTmapping( u, distance ) {
31751
31752		const arcLengths = this.getLengths();
31753
31754		let i = 0;
31755		const il = arcLengths.length;
31756
31757		let targetArcLength; // The targeted u distance value to get
31758
31759		if ( distance ) {
31760
31761			targetArcLength = distance;
31762
31763		} else {
31764
31765			targetArcLength = u * arcLengths[ il - 1 ];
31766
31767		}
31768
31769		// binary search for the index with largest value smaller than target u distance
31770
31771		let low = 0, high = il - 1, comparison;
31772
31773		while ( low <= high ) {
31774
31775			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
31776
31777			comparison = arcLengths[ i ] - targetArcLength;
31778
31779			if ( comparison < 0 ) {
31780
31781				low = i + 1;
31782
31783			} else if ( comparison > 0 ) {
31784
31785				high = i - 1;
31786
31787			} else {
31788
31789				high = i;
31790				break;
31791
31792				// DONE
31793
31794			}
31795
31796		}
31797
31798		i = high;
31799
31800		if ( arcLengths[ i ] === targetArcLength ) {
31801
31802			return i / ( il - 1 );
31803
31804		}
31805
31806		// we could get finer grain at lengths, or use simple interpolation between two points
31807
31808		const lengthBefore = arcLengths[ i ];
31809		const lengthAfter = arcLengths[ i + 1 ];
31810
31811		const segmentLength = lengthAfter - lengthBefore;
31812
31813		// determine where we are between the 'before' and 'after' points
31814
31815		const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
31816
31817		// add that fractional amount to t
31818
31819		const t = ( i + segmentFraction ) / ( il - 1 );
31820
31821		return t;
31822
31823	}
31824
31825	// Returns a unit vector tangent at t
31826	// In case any sub curve does not implement its tangent derivation,
31827	// 2 points a small delta apart will be used to find its gradient
31828	// which seems to give a reasonable approximation
31829
31830	getTangent( t, optionalTarget ) {
31831
31832		const delta = 0.0001;
31833		let t1 = t - delta;
31834		let t2 = t + delta;
31835
31836		// Capping in case of danger
31837
31838		if ( t1 < 0 ) t1 = 0;
31839		if ( t2 > 1 ) t2 = 1;
31840
31841		const pt1 = this.getPoint( t1 );
31842		const pt2 = this.getPoint( t2 );
31843
31844		const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
31845
31846		tangent.copy( pt2 ).sub( pt1 ).normalize();
31847
31848		return tangent;
31849
31850	}
31851
31852	getTangentAt( u, optionalTarget ) {
31853
31854		const t = this.getUtoTmapping( u );
31855		return this.getTangent( t, optionalTarget );
31856
31857	}
31858
31859	computeFrenetFrames( segments, closed ) {
31860
31861		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
31862
31863		const normal = new Vector3();
31864
31865		const tangents = [];
31866		const normals = [];
31867		const binormals = [];
31868
31869		const vec = new Vector3();
31870		const mat = new Matrix4();
31871
31872		// compute the tangent vectors for each segment on the curve
31873
31874		for ( let i = 0; i <= segments; i ++ ) {
31875
31876			const u = i / segments;
31877
31878			tangents[ i ] = this.getTangentAt( u, new Vector3() );
31879
31880		}
31881
31882		// select an initial normal vector perpendicular to the first tangent vector,
31883		// and in the direction of the minimum tangent xyz component
31884
31885		normals[ 0 ] = new Vector3();
31886		binormals[ 0 ] = new Vector3();
31887		let min = Number.MAX_VALUE;
31888		const tx = Math.abs( tangents[ 0 ].x );
31889		const ty = Math.abs( tangents[ 0 ].y );
31890		const tz = Math.abs( tangents[ 0 ].z );
31891
31892		if ( tx <= min ) {
31893
31894			min = tx;
31895			normal.set( 1, 0, 0 );
31896
31897		}
31898
31899		if ( ty <= min ) {
31900
31901			min = ty;
31902			normal.set( 0, 1, 0 );
31903
31904		}
31905
31906		if ( tz <= min ) {
31907
31908			normal.set( 0, 0, 1 );
31909
31910		}
31911
31912		vec.crossVectors( tangents[ 0 ], normal ).normalize();
31913
31914		normals[ 0 ].crossVectors( tangents[ 0 ], vec );
31915		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
31916
31917
31918		// compute the slowly-varying normal and binormal vectors for each segment on the curve
31919
31920		for ( let i = 1; i <= segments; i ++ ) {
31921
31922			normals[ i ] = normals[ i - 1 ].clone();
31923
31924			binormals[ i ] = binormals[ i - 1 ].clone();
31925
31926			vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
31927
31928			if ( vec.length() > Number.EPSILON ) {
31929
31930				vec.normalize();
31931
31932				const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
31933
31934				normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
31935
31936			}
31937
31938			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31939
31940		}
31941
31942		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
31943
31944		if ( closed === true ) {
31945
31946			let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
31947			theta /= segments;
31948
31949			if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
31950
31951				theta = - theta;
31952
31953			}
31954
31955			for ( let i = 1; i <= segments; i ++ ) {
31956
31957				// twist a little...
31958				normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
31959				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31960
31961			}
31962
31963		}
31964
31965		return {
31966			tangents: tangents,
31967			normals: normals,
31968			binormals: binormals
31969		};
31970
31971	}
31972
31973	clone() {
31974
31975		return new this.constructor().copy( this );
31976
31977	}
31978
31979	copy( source ) {
31980
31981		this.arcLengthDivisions = source.arcLengthDivisions;
31982
31983		return this;
31984
31985	}
31986
31987	toJSON() {
31988
31989		const data = {
31990			metadata: {
31991				version: 4.5,
31992				type: 'Curve',
31993				generator: 'Curve.toJSON'
31994			}
31995		};
31996
31997		data.arcLengthDivisions = this.arcLengthDivisions;
31998		data.type = this.type;
31999
32000		return data;
32001
32002	}
32003
32004	fromJSON( json ) {
32005
32006		this.arcLengthDivisions = json.arcLengthDivisions;
32007
32008		return this;
32009
32010	}
32011
32012}
32013
32014class EllipseCurve extends Curve {
32015
32016	constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) {
32017
32018		super();
32019
32020		this.isEllipseCurve = true;
32021
32022		this.type = 'EllipseCurve';
32023
32024		this.aX = aX;
32025		this.aY = aY;
32026
32027		this.xRadius = xRadius;
32028		this.yRadius = yRadius;
32029
32030		this.aStartAngle = aStartAngle;
32031		this.aEndAngle = aEndAngle;
32032
32033		this.aClockwise = aClockwise;
32034
32035		this.aRotation = aRotation;
32036
32037	}
32038
32039	getPoint( t, optionalTarget ) {
32040
32041		const point = optionalTarget || new Vector2();
32042
32043		const twoPi = Math.PI * 2;
32044		let deltaAngle = this.aEndAngle - this.aStartAngle;
32045		const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
32046
32047		// ensures that deltaAngle is 0 .. 2 PI
32048		while ( deltaAngle < 0 ) deltaAngle += twoPi;
32049		while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
32050
32051		if ( deltaAngle < Number.EPSILON ) {
32052
32053			if ( samePoints ) {
32054
32055				deltaAngle = 0;
32056
32057			} else {
32058
32059				deltaAngle = twoPi;
32060
32061			}
32062
32063		}
32064
32065		if ( this.aClockwise === true && ! samePoints ) {
32066
32067			if ( deltaAngle === twoPi ) {
32068
32069				deltaAngle = - twoPi;
32070
32071			} else {
32072
32073				deltaAngle = deltaAngle - twoPi;
32074
32075			}
32076
32077		}
32078
32079		const angle = this.aStartAngle + t * deltaAngle;
32080		let x = this.aX + this.xRadius * Math.cos( angle );
32081		let y = this.aY + this.yRadius * Math.sin( angle );
32082
32083		if ( this.aRotation !== 0 ) {
32084
32085			const cos = Math.cos( this.aRotation );
32086			const sin = Math.sin( this.aRotation );
32087
32088			const tx = x - this.aX;
32089			const ty = y - this.aY;
32090
32091			// Rotate the point about the center of the ellipse.
32092			x = tx * cos - ty * sin + this.aX;
32093			y = tx * sin + ty * cos + this.aY;
32094
32095		}
32096
32097		return point.set( x, y );
32098
32099	}
32100
32101	copy( source ) {
32102
32103		super.copy( source );
32104
32105		this.aX = source.aX;
32106		this.aY = source.aY;
32107
32108		this.xRadius = source.xRadius;
32109		this.yRadius = source.yRadius;
32110
vendor: 29,506 bytes, lines 32111-33786
32111		this.aStartAngle = source.aStartAngle;
32112		this.aEndAngle = source.aEndAngle;
32113
32114		this.aClockwise = source.aClockwise;
32115
32116		this.aRotation = source.aRotation;
32117
32118		return this;
32119
32120	}
32121
32122	toJSON() {
32123
32124		const data = super.toJSON();
32125
32126		data.aX = this.aX;
32127		data.aY = this.aY;
32128
32129		data.xRadius = this.xRadius;
32130		data.yRadius = this.yRadius;
32131
32132		data.aStartAngle = this.aStartAngle;
32133		data.aEndAngle = this.aEndAngle;
32134
32135		data.aClockwise = this.aClockwise;
32136
32137		data.aRotation = this.aRotation;
32138
32139		return data;
32140
32141	}
32142
32143	fromJSON( json ) {
32144
32145		super.fromJSON( json );
32146
32147		this.aX = json.aX;
32148		this.aY = json.aY;
32149
32150		this.xRadius = json.xRadius;
32151		this.yRadius = json.yRadius;
32152
32153		this.aStartAngle = json.aStartAngle;
32154		this.aEndAngle = json.aEndAngle;
32155
32156		this.aClockwise = json.aClockwise;
32157
32158		this.aRotation = json.aRotation;
32159
32160		return this;
32161
32162	}
32163
32164}
32165
32166class ArcCurve extends EllipseCurve {
32167
32168	constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
32169
32170		super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
32171
32172		this.isArcCurve = true;
32173
32174		this.type = 'ArcCurve';
32175
32176	}
32177
32178}
32179
32180/**
32181 * Centripetal CatmullRom Curve - which is useful for avoiding
32182 * cusps and self-intersections in non-uniform catmull rom curves.
32183 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
32184 *
32185 * curve.type accepts centripetal(default), chordal and catmullrom
32186 * curve.tension is used for catmullrom which defaults to 0.5
32187 */
32188
32189
32190/*
32191Based on an optimized c++ solution in
32192 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
32193 - http://ideone.com/NoEbVM
32194
32195This CubicPoly class could be used for reusing some variables and calculations,
32196but for three.js curve use, it could be possible inlined and flatten into a single function call
32197which can be placed in CurveUtils.
32198*/
32199
32200function CubicPoly() {
32201
32202	let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
32203
32204	/*
32205	 * Compute coefficients for a cubic polynomial
32206	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
32207	 * such that
32208	 *   p(0) = x0, p(1) = x1
32209	 *  and
32210	 *   p'(0) = t0, p'(1) = t1.
32211	 */
32212	function init( x0, x1, t0, t1 ) {
32213
32214		c0 = x0;
32215		c1 = t0;
32216		c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
32217		c3 = 2 * x0 - 2 * x1 + t0 + t1;
32218
32219	}
32220
32221	return {
32222
32223		initCatmullRom: function ( x0, x1, x2, x3, tension ) {
32224
32225			init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
32226
32227		},
32228
32229		initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
32230
32231			// compute tangents when parameterized in [t1,t2]
32232			let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
32233			let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
32234
32235			// rescale tangents for parametrization in [0,1]
32236			t1 *= dt1;
32237			t2 *= dt1;
32238
32239			init( x1, x2, t1, t2 );
32240
32241		},
32242
32243		calc: function ( t ) {
32244
32245			const t2 = t * t;
32246			const t3 = t2 * t;
32247			return c0 + c1 * t + c2 * t2 + c3 * t3;
32248
32249		}
32250
32251	};
32252
32253}
32254
32255//
32256
32257const tmp = /*@__PURE__*/ new Vector3();
32258const px = /*@__PURE__*/ new CubicPoly();
32259const py = /*@__PURE__*/ new CubicPoly();
32260const pz = /*@__PURE__*/ new CubicPoly();
32261
32262class CatmullRomCurve3 extends Curve {
32263
32264	constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
32265
32266		super();
32267
32268		this.isCatmullRomCurve3 = true;
32269
32270		this.type = 'CatmullRomCurve3';
32271
32272		this.points = points;
32273		this.closed = closed;
32274		this.curveType = curveType;
32275		this.tension = tension;
32276
32277	}
32278
32279	getPoint( t, optionalTarget = new Vector3() ) {
32280
32281		const point = optionalTarget;
32282
32283		const points = this.points;
32284		const l = points.length;
32285
32286		const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
32287		let intPoint = Math.floor( p );
32288		let weight = p - intPoint;
32289
32290		if ( this.closed ) {
32291
32292			intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
32293
32294		} else if ( weight === 0 && intPoint === l - 1 ) {
32295
32296			intPoint = l - 2;
32297			weight = 1;
32298
32299		}
32300
32301		let p0, p3; // 4 points (p1 & p2 defined below)
32302
32303		if ( this.closed || intPoint > 0 ) {
32304
32305			p0 = points[ ( intPoint - 1 ) % l ];
32306
32307		} else {
32308
32309			// extrapolate first point
32310			tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
32311			p0 = tmp;
32312
32313		}
32314
32315		const p1 = points[ intPoint % l ];
32316		const p2 = points[ ( intPoint + 1 ) % l ];
32317
32318		if ( this.closed || intPoint + 2 < l ) {
32319
32320			p3 = points[ ( intPoint + 2 ) % l ];
32321
32322		} else {
32323
32324			// extrapolate last point
32325			tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
32326			p3 = tmp;
32327
32328		}
32329
32330		if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
32331
32332			// init Centripetal / Chordal Catmull-Rom
32333			const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
32334			let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
32335			let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
32336			let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
32337
32338			// safety check for repeated points
32339			if ( dt1 < 1e-4 ) dt1 = 1.0;
32340			if ( dt0 < 1e-4 ) dt0 = dt1;
32341			if ( dt2 < 1e-4 ) dt2 = dt1;
32342
32343			px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
32344			py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
32345			pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
32346
32347		} else if ( this.curveType === 'catmullrom' ) {
32348
32349			px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
32350			py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
32351			pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
32352
32353		}
32354
32355		point.set(
32356			px.calc( weight ),
32357			py.calc( weight ),
32358			pz.calc( weight )
32359		);
32360
32361		return point;
32362
32363	}
32364
32365	copy( source ) {
32366
32367		super.copy( source );
32368
32369		this.points = [];
32370
32371		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
32372
32373			const point = source.points[ i ];
32374
32375			this.points.push( point.clone() );
32376
32377		}
32378
32379		this.closed = source.closed;
32380		this.curveType = source.curveType;
32381		this.tension = source.tension;
32382
32383		return this;
32384
32385	}
32386
32387	toJSON() {
32388
32389		const data = super.toJSON();
32390
32391		data.points = [];
32392
32393		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
32394
32395			const point = this.points[ i ];
32396			data.points.push( point.toArray() );
32397
32398		}
32399
32400		data.closed = this.closed;
32401		data.curveType = this.curveType;
32402		data.tension = this.tension;
32403
32404		return data;
32405
32406	}
32407
32408	fromJSON( json ) {
32409
32410		super.fromJSON( json );
32411
32412		this.points = [];
32413
32414		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
32415
32416			const point = json.points[ i ];
32417			this.points.push( new Vector3().fromArray( point ) );
32418
32419		}
32420
32421		this.closed = json.closed;
32422		this.curveType = json.curveType;
32423		this.tension = json.tension;
32424
32425		return this;
32426
32427	}
32428
32429}
32430
32431/**
32432 * Bezier Curves formulas obtained from
32433 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
32434 */
32435
32436function CatmullRom( t, p0, p1, p2, p3 ) {
32437
32438	const v0 = ( p2 - p0 ) * 0.5;
32439	const v1 = ( p3 - p1 ) * 0.5;
32440	const t2 = t * t;
32441	const t3 = t * t2;
32442	return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
32443
32444}
32445
32446//
32447
32448function QuadraticBezierP0( t, p ) {
32449
32450	const k = 1 - t;
32451	return k * k * p;
32452
32453}
32454
32455function QuadraticBezierP1( t, p ) {
32456
32457	return 2 * ( 1 - t ) * t * p;
32458
32459}
32460
32461function QuadraticBezierP2( t, p ) {
32462
32463	return t * t * p;
32464
32465}
32466
32467function QuadraticBezier( t, p0, p1, p2 ) {
32468
32469	return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
32470		QuadraticBezierP2( t, p2 );
32471
32472}
32473
32474//
32475
32476function CubicBezierP0( t, p ) {
32477
32478	const k = 1 - t;
32479	return k * k * k * p;
32480
32481}
32482
32483function CubicBezierP1( t, p ) {
32484
32485	const k = 1 - t;
32486	return 3 * k * k * t * p;
32487
32488}
32489
32490function CubicBezierP2( t, p ) {
32491
32492	return 3 * ( 1 - t ) * t * t * p;
32493
32494}
32495
32496function CubicBezierP3( t, p ) {
32497
32498	return t * t * t * p;
32499
32500}
32501
32502function CubicBezier( t, p0, p1, p2, p3 ) {
32503
32504	return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
32505		CubicBezierP3( t, p3 );
32506
32507}
32508
32509class CubicBezierCurve extends Curve {
32510
32511	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
32512
32513		super();
32514
32515		this.isCubicBezierCurve = true;
32516
32517		this.type = 'CubicBezierCurve';
32518
32519		this.v0 = v0;
32520		this.v1 = v1;
32521		this.v2 = v2;
32522		this.v3 = v3;
32523
32524	}
32525
32526	getPoint( t, optionalTarget = new Vector2() ) {
32527
32528		const point = optionalTarget;
32529
32530		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32531
32532		point.set(
32533			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32534			CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
32535		);
32536
32537		return point;
32538
32539	}
32540
32541	copy( source ) {
32542
32543		super.copy( source );
32544
32545		this.v0.copy( source.v0 );
32546		this.v1.copy( source.v1 );
32547		this.v2.copy( source.v2 );
32548		this.v3.copy( source.v3 );
32549
32550		return this;
32551
32552	}
32553
32554	toJSON() {
32555
32556		const data = super.toJSON();
32557
32558		data.v0 = this.v0.toArray();
32559		data.v1 = this.v1.toArray();
32560		data.v2 = this.v2.toArray();
32561		data.v3 = this.v3.toArray();
32562
32563		return data;
32564
32565	}
32566
32567	fromJSON( json ) {
32568
32569		super.fromJSON( json );
32570
32571		this.v0.fromArray( json.v0 );
32572		this.v1.fromArray( json.v1 );
32573		this.v2.fromArray( json.v2 );
32574		this.v3.fromArray( json.v3 );
32575
32576		return this;
32577
32578	}
32579
32580}
32581
32582class CubicBezierCurve3 extends Curve {
32583
32584	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
32585
32586		super();
32587
32588		this.isCubicBezierCurve3 = true;
32589
32590		this.type = 'CubicBezierCurve3';
32591
32592		this.v0 = v0;
32593		this.v1 = v1;
32594		this.v2 = v2;
32595		this.v3 = v3;
32596
32597	}
32598
32599	getPoint( t, optionalTarget = new Vector3() ) {
32600
32601		const point = optionalTarget;
32602
32603		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32604
32605		point.set(
32606			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32607			CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
32608			CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
32609		);
32610
32611		return point;
32612
32613	}
32614
32615	copy( source ) {
32616
32617		super.copy( source );
32618
32619		this.v0.copy( source.v0 );
32620		this.v1.copy( source.v1 );
32621		this.v2.copy( source.v2 );
32622		this.v3.copy( source.v3 );
32623
32624		return this;
32625
32626	}
32627
32628	toJSON() {
32629
32630		const data = super.toJSON();
32631
32632		data.v0 = this.v0.toArray();
32633		data.v1 = this.v1.toArray();
32634		data.v2 = this.v2.toArray();
32635		data.v3 = this.v3.toArray();
32636
32637		return data;
32638
32639	}
32640
32641	fromJSON( json ) {
32642
32643		super.fromJSON( json );
32644
32645		this.v0.fromArray( json.v0 );
32646		this.v1.fromArray( json.v1 );
32647		this.v2.fromArray( json.v2 );
32648		this.v3.fromArray( json.v3 );
32649
32650		return this;
32651
32652	}
32653
32654}
32655
32656class LineCurve extends Curve {
32657
32658	constructor( v1 = new Vector2(), v2 = new Vector2() ) {
32659
32660		super();
32661
32662		this.isLineCurve = true;
32663
32664		this.type = 'LineCurve';
32665
32666		this.v1 = v1;
32667		this.v2 = v2;
32668
32669	}
32670
32671	getPoint( t, optionalTarget = new Vector2() ) {
32672
32673		const point = optionalTarget;
32674
32675		if ( t === 1 ) {
32676
32677			point.copy( this.v2 );
32678
32679		} else {
32680
32681			point.copy( this.v2 ).sub( this.v1 );
32682			point.multiplyScalar( t ).add( this.v1 );
32683
32684		}
32685
32686		return point;
32687
32688	}
32689
32690	// Line curve is linear, so we can overwrite default getPointAt
32691	getPointAt( u, optionalTarget ) {
32692
32693		return this.getPoint( u, optionalTarget );
32694
32695	}
32696
32697	getTangent( t, optionalTarget = new Vector2() ) {
32698
32699		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
32700
32701	}
32702
32703	getTangentAt( u, optionalTarget ) {
32704
32705		return this.getTangent( u, optionalTarget );
32706
32707	}
32708
32709	copy( source ) {
32710
32711		super.copy( source );
32712
32713		this.v1.copy( source.v1 );
32714		this.v2.copy( source.v2 );
32715
32716		return this;
32717
32718	}
32719
32720	toJSON() {
32721
32722		const data = super.toJSON();
32723
32724		data.v1 = this.v1.toArray();
32725		data.v2 = this.v2.toArray();
32726
32727		return data;
32728
32729	}
32730
32731	fromJSON( json ) {
32732
32733		super.fromJSON( json );
32734
32735		this.v1.fromArray( json.v1 );
32736		this.v2.fromArray( json.v2 );
32737
32738		return this;
32739
32740	}
32741
32742}
32743
32744class LineCurve3 extends Curve {
32745
32746	constructor( v1 = new Vector3(), v2 = new Vector3() ) {
32747
32748		super();
32749
32750		this.isLineCurve3 = true;
32751
32752		this.type = 'LineCurve3';
32753
32754		this.v1 = v1;
32755		this.v2 = v2;
32756
32757	}
32758	getPoint( t, optionalTarget = new Vector3() ) {
32759
32760		const point = optionalTarget;
32761
32762		if ( t === 1 ) {
32763
32764			point.copy( this.v2 );
32765
32766		} else {
32767
32768			point.copy( this.v2 ).sub( this.v1 );
32769			point.multiplyScalar( t ).add( this.v1 );
32770
32771		}
32772
32773		return point;
32774
32775	}
32776	// Line curve is linear, so we can overwrite default getPointAt
32777	getPointAt( u, optionalTarget ) {
32778
32779		return this.getPoint( u, optionalTarget );
32780
32781	}
32782
32783	getTangent( t, optionalTarget = new Vector3() ) {
32784
32785		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
32786
32787	}
32788
32789	getTangentAt( u, optionalTarget ) {
32790
32791		return this.getTangent( u, optionalTarget );
32792
32793	}
32794
32795	copy( source ) {
32796
32797		super.copy( source );
32798
32799		this.v1.copy( source.v1 );
32800		this.v2.copy( source.v2 );
32801
32802		return this;
32803
32804	}
32805	toJSON() {
32806
32807		const data = super.toJSON();
32808
32809		data.v1 = this.v1.toArray();
32810		data.v2 = this.v2.toArray();
32811
32812		return data;
32813
32814	}
32815	fromJSON( json ) {
32816
32817		super.fromJSON( json );
32818
32819		this.v1.fromArray( json.v1 );
32820		this.v2.fromArray( json.v2 );
32821
32822		return this;
32823
32824	}
32825
32826}
32827
32828class QuadraticBezierCurve extends Curve {
32829
32830	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
32831
32832		super();
32833
32834		this.isQuadraticBezierCurve = true;
32835
32836		this.type = 'QuadraticBezierCurve';
32837
32838		this.v0 = v0;
32839		this.v1 = v1;
32840		this.v2 = v2;
32841
32842	}
32843
32844	getPoint( t, optionalTarget = new Vector2() ) {
32845
32846		const point = optionalTarget;
32847
32848		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
32849
32850		point.set(
32851			QuadraticBezier( t, v0.x, v1.x, v2.x ),
32852			QuadraticBezier( t, v0.y, v1.y, v2.y )
32853		);
32854
32855		return point;
32856
32857	}
32858
32859	copy( source ) {
32860
32861		super.copy( source );
32862
32863		this.v0.copy( source.v0 );
32864		this.v1.copy( source.v1 );
32865		this.v2.copy( source.v2 );
32866
32867		return this;
32868
32869	}
32870
32871	toJSON() {
32872
32873		const data = super.toJSON();
32874
32875		data.v0 = this.v0.toArray();
32876		data.v1 = this.v1.toArray();
32877		data.v2 = this.v2.toArray();
32878
32879		return data;
32880
32881	}
32882
32883	fromJSON( json ) {
32884
32885		super.fromJSON( json );
32886
32887		this.v0.fromArray( json.v0 );
32888		this.v1.fromArray( json.v1 );
32889		this.v2.fromArray( json.v2 );
32890
32891		return this;
32892
32893	}
32894
32895}
32896
32897class QuadraticBezierCurve3 extends Curve {
32898
32899	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
32900
32901		super();
32902
32903		this.isQuadraticBezierCurve3 = true;
32904
32905		this.type = 'QuadraticBezierCurve3';
32906
32907		this.v0 = v0;
32908		this.v1 = v1;
32909		this.v2 = v2;
32910
32911	}
32912
32913	getPoint( t, optionalTarget = new Vector3() ) {
32914
32915		const point = optionalTarget;
32916
32917		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
32918
32919		point.set(
32920			QuadraticBezier( t, v0.x, v1.x, v2.x ),
32921			QuadraticBezier( t, v0.y, v1.y, v2.y ),
32922			QuadraticBezier( t, v0.z, v1.z, v2.z )
32923		);
32924
32925		return point;
32926
32927	}
32928
32929	copy( source ) {
32930
32931		super.copy( source );
32932
32933		this.v0.copy( source.v0 );
32934		this.v1.copy( source.v1 );
32935		this.v2.copy( source.v2 );
32936
32937		return this;
32938
32939	}
32940
32941	toJSON() {
32942
32943		const data = super.toJSON();
32944
32945		data.v0 = this.v0.toArray();
32946		data.v1 = this.v1.toArray();
32947		data.v2 = this.v2.toArray();
32948
32949		return data;
32950
32951	}
32952
32953	fromJSON( json ) {
32954
32955		super.fromJSON( json );
32956
32957		this.v0.fromArray( json.v0 );
32958		this.v1.fromArray( json.v1 );
32959		this.v2.fromArray( json.v2 );
32960
32961		return this;
32962
32963	}
32964
32965}
32966
32967class SplineCurve extends Curve {
32968
32969	constructor( points = [] ) {
32970
32971		super();
32972
32973		this.isSplineCurve = true;
32974
32975		this.type = 'SplineCurve';
32976
32977		this.points = points;
32978
32979	}
32980
32981	getPoint( t, optionalTarget = new Vector2() ) {
32982
32983		const point = optionalTarget;
32984
32985		const points = this.points;
32986		const p = ( points.length - 1 ) * t;
32987
32988		const intPoint = Math.floor( p );
32989		const weight = p - intPoint;
32990
32991		const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
32992		const p1 = points[ intPoint ];
32993		const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
32994		const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
32995
32996		point.set(
32997			CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
32998			CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
32999		);
33000
33001		return point;
33002
33003	}
33004
33005	copy( source ) {
33006
33007		super.copy( source );
33008
33009		this.points = [];
33010
33011		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
33012
33013			const point = source.points[ i ];
33014
33015			this.points.push( point.clone() );
33016
33017		}
33018
33019		return this;
33020
33021	}
33022
33023	toJSON() {
33024
33025		const data = super.toJSON();
33026
33027		data.points = [];
33028
33029		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
33030
33031			const point = this.points[ i ];
33032			data.points.push( point.toArray() );
33033
33034		}
33035
33036		return data;
33037
33038	}
33039
33040	fromJSON( json ) {
33041
33042		super.fromJSON( json );
33043
33044		this.points = [];
33045
33046		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
33047
33048			const point = json.points[ i ];
33049			this.points.push( new Vector2().fromArray( point ) );
33050
33051		}
33052
33053		return this;
33054
33055	}
33056
33057}
33058
33059var Curves = /*#__PURE__*/Object.freeze({
33060	__proto__: null,
33061	ArcCurve: ArcCurve,
33062	CatmullRomCurve3: CatmullRomCurve3,
33063	CubicBezierCurve: CubicBezierCurve,
33064	CubicBezierCurve3: CubicBezierCurve3,
33065	EllipseCurve: EllipseCurve,
33066	LineCurve: LineCurve,
33067	LineCurve3: LineCurve3,
33068	QuadraticBezierCurve: QuadraticBezierCurve,
33069	QuadraticBezierCurve3: QuadraticBezierCurve3,
33070	SplineCurve: SplineCurve
33071});
33072
33073/**************************************************************
33074 *	Curved Path - a curve path is simply a array of connected
33075 *  curves, but retains the api of a curve
33076 **************************************************************/
33077
33078class CurvePath extends Curve {
33079
33080	constructor() {
33081
33082		super();
33083
33084		this.type = 'CurvePath';
33085
33086		this.curves = [];
33087		this.autoClose = false; // Automatically closes the path
33088
33089	}
33090
33091	add( curve ) {
33092
33093		this.curves.push( curve );
33094
33095	}
33096
33097	closePath() {
33098
33099		// Add a line curve if start and end of lines are not connected
33100		const startPoint = this.curves[ 0 ].getPoint( 0 );
33101		const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
33102
33103		if ( ! startPoint.equals( endPoint ) ) {
33104
33105			this.curves.push( new LineCurve( endPoint, startPoint ) );
33106
33107		}
33108
33109	}
33110
33111	// To get accurate point with reference to
33112	// entire path distance at time t,
33113	// following has to be done:
33114
33115	// 1. Length of each sub path have to be known
33116	// 2. Locate and identify type of curve
33117	// 3. Get t for the curve
33118	// 4. Return curve.getPointAt(t')
33119
33120	getPoint( t, optionalTarget ) {
33121
33122		const d = t * this.getLength();
33123		const curveLengths = this.getCurveLengths();
33124		let i = 0;
33125
33126		// To think about boundaries points.
33127
33128		while ( i < curveLengths.length ) {
33129
33130			if ( curveLengths[ i ] >= d ) {
33131
33132				const diff = curveLengths[ i ] - d;
33133				const curve = this.curves[ i ];
33134
33135				const segmentLength = curve.getLength();
33136				const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
33137
33138				return curve.getPointAt( u, optionalTarget );
33139
33140			}
33141
33142			i ++;
33143
33144		}
33145
33146		return null;
33147
33148		// loop where sum != 0, sum > d , sum+1 <d
33149
33150	}
33151
33152	// We cannot use the default THREE.Curve getPoint() with getLength() because in
33153	// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
33154	// getPoint() depends on getLength
33155
33156	getLength() {
33157
33158		const lens = this.getCurveLengths();
33159		return lens[ lens.length - 1 ];
33160
33161	}
33162
33163	// cacheLengths must be recalculated.
33164	updateArcLengths() {
33165
33166		this.needsUpdate = true;
33167		this.cacheLengths = null;
33168		this.getCurveLengths();
33169
33170	}
33171
33172	// Compute lengths and cache them
33173	// We cannot overwrite getLengths() because UtoT mapping uses it.
33174
33175	getCurveLengths() {
33176
33177		// We use cache values if curves and cache array are same length
33178
33179		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
33180
33181			return this.cacheLengths;
33182
33183		}
33184
33185		// Get length of sub-curve
33186		// Push sums into cached array
33187
33188		const lengths = [];
33189		let sums = 0;
33190
33191		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33192
33193			sums += this.curves[ i ].getLength();
33194			lengths.push( sums );
33195
33196		}
33197
33198		this.cacheLengths = lengths;
33199
33200		return lengths;
33201
33202	}
33203
33204	getSpacedPoints( divisions = 40 ) {
33205
33206		const points = [];
33207
33208		for ( let i = 0; i <= divisions; i ++ ) {
33209
33210			points.push( this.getPoint( i / divisions ) );
33211
33212		}
33213
33214		if ( this.autoClose ) {
33215
33216			points.push( points[ 0 ] );
33217
33218		}
33219
33220		return points;
33221
33222	}
33223
33224	getPoints( divisions = 12 ) {
33225
33226		const points = [];
33227		let last;
33228
33229		for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
33230
33231			const curve = curves[ i ];
33232			const resolution = curve.isEllipseCurve ? divisions * 2
33233				: ( curve.isLineCurve || curve.isLineCurve3 ) ? 1
33234					: curve.isSplineCurve ? divisions * curve.points.length
33235						: divisions;
33236
33237			const pts = curve.getPoints( resolution );
33238
33239			for ( let j = 0; j < pts.length; j ++ ) {
33240
33241				const point = pts[ j ];
33242
33243				if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
33244
33245				points.push( point );
33246				last = point;
33247
33248			}
33249
33250		}
33251
33252		if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
33253
33254			points.push( points[ 0 ] );
33255
33256		}
33257
33258		return points;
33259
33260	}
33261
33262	copy( source ) {
33263
33264		super.copy( source );
33265
33266		this.curves = [];
33267
33268		for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
33269
33270			const curve = source.curves[ i ];
33271
33272			this.curves.push( curve.clone() );
33273
33274		}
33275
33276		this.autoClose = source.autoClose;
33277
33278		return this;
33279
33280	}
33281
33282	toJSON() {
33283
33284		const data = super.toJSON();
33285
33286		data.autoClose = this.autoClose;
33287		data.curves = [];
33288
33289		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33290
33291			const curve = this.curves[ i ];
33292			data.curves.push( curve.toJSON() );
33293
33294		}
33295
33296		return data;
33297
33298	}
33299
33300	fromJSON( json ) {
33301
33302		super.fromJSON( json );
33303
33304		this.autoClose = json.autoClose;
33305		this.curves = [];
33306
33307		for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
33308
33309			const curve = json.curves[ i ];
33310			this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
33311
33312		}
33313
33314		return this;
33315
33316	}
33317
33318}
33319
33320class Path extends CurvePath {
33321
33322	constructor( points ) {
33323
33324		super();
33325
33326		this.type = 'Path';
33327
33328		this.currentPoint = new Vector2();
33329
33330		if ( points ) {
33331
33332			this.setFromPoints( points );
33333
33334		}
33335
33336	}
33337
33338	setFromPoints( points ) {
33339
33340		this.moveTo( points[ 0 ].x, points[ 0 ].y );
33341
33342		for ( let i = 1, l = points.length; i < l; i ++ ) {
33343
33344			this.lineTo( points[ i ].x, points[ i ].y );
33345
33346		}
33347
33348		return this;
33349
33350	}
33351
33352	moveTo( x, y ) {
33353
33354		this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
33355
33356		return this;
33357
33358	}
33359
33360	lineTo( x, y ) {
33361
33362		const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
33363		this.curves.push( curve );
33364
33365		this.currentPoint.set( x, y );
33366
33367		return this;
33368
33369	}
33370
33371	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
33372
33373		const curve = new QuadraticBezierCurve(
33374			this.currentPoint.clone(),
33375			new Vector2( aCPx, aCPy ),
33376			new Vector2( aX, aY )
33377		);
33378
33379		this.curves.push( curve );
33380
33381		this.currentPoint.set( aX, aY );
33382
33383		return this;
33384
33385	}
33386
33387	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
33388
33389		const curve = new CubicBezierCurve(
33390			this.currentPoint.clone(),
33391			new Vector2( aCP1x, aCP1y ),
33392			new Vector2( aCP2x, aCP2y ),
33393			new Vector2( aX, aY )
33394		);
33395
33396		this.curves.push( curve );
33397
33398		this.currentPoint.set( aX, aY );
33399
33400		return this;
33401
33402	}
33403
33404	splineThru( pts /*Array of Vector*/ ) {
33405
33406		const npts = [ this.currentPoint.clone() ].concat( pts );
33407
33408		const curve = new SplineCurve( npts );
33409		this.curves.push( curve );
33410
33411		this.currentPoint.copy( pts[ pts.length - 1 ] );
33412
33413		return this;
33414
33415	}
33416
33417	arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33418
33419		const x0 = this.currentPoint.x;
33420		const y0 = this.currentPoint.y;
33421
33422		this.absarc( aX + x0, aY + y0, aRadius,
33423			aStartAngle, aEndAngle, aClockwise );
33424
33425		return this;
33426
33427	}
33428
33429	absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
33430
33431		this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
33432
33433		return this;
33434
33435	}
33436
33437	ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33438
33439		const x0 = this.currentPoint.x;
33440		const y0 = this.currentPoint.y;
33441
33442		this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33443
33444		return this;
33445
33446	}
33447
33448	absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
33449
33450		const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
33451
33452		if ( this.curves.length > 0 ) {
33453
33454			// if a previous curve is present, attempt to join
33455			const firstPoint = curve.getPoint( 0 );
33456
33457			if ( ! firstPoint.equals( this.currentPoint ) ) {
33458
33459				this.lineTo( firstPoint.x, firstPoint.y );
33460
33461			}
33462
33463		}
33464
33465		this.curves.push( curve );
33466
33467		const lastPoint = curve.getPoint( 1 );
33468		this.currentPoint.copy( lastPoint );
33469
33470		return this;
33471
33472	}
33473
33474	copy( source ) {
33475
33476		super.copy( source );
33477
33478		this.currentPoint.copy( source.currentPoint );
33479
33480		return this;
33481
33482	}
33483
33484	toJSON() {
33485
33486		const data = super.toJSON();
33487
33488		data.currentPoint = this.currentPoint.toArray();
33489
33490		return data;
33491
33492	}
33493
33494	fromJSON( json ) {
33495
33496		super.fromJSON( json );
33497
33498		this.currentPoint.fromArray( json.currentPoint );
33499
33500		return this;
33501
33502	}
33503
33504}
33505
33506class LatheGeometry extends BufferGeometry {
33507
33508	constructor( points = [ new Vector2( 0, - 0.5 ), new Vector2( 0.5, 0 ), new Vector2( 0, 0.5 ) ], segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) {
33509
33510		super();
33511
33512		this.type = 'LatheGeometry';
33513
33514		this.parameters = {
33515			points: points,
33516			segments: segments,
33517			phiStart: phiStart,
33518			phiLength: phiLength
33519		};
33520
33521		segments = Math.floor( segments );
33522
33523		// clamp phiLength so it's in range of [ 0, 2PI ]
33524
33525		phiLength = clamp( phiLength, 0, Math.PI * 2 );
33526
33527		// buffers
33528
33529		const indices = [];
33530		const vertices = [];
33531		const uvs = [];
33532		const initNormals = [];
33533		const normals = [];
33534
33535		// helper variables
33536
33537		const inverseSegments = 1.0 / segments;
33538		const vertex = new Vector3();
33539		const uv = new Vector2();
33540		const normal = new Vector3();
33541		const curNormal = new Vector3();
33542		const prevNormal = new Vector3();
33543		let dx = 0;
33544		let dy = 0;
33545
33546		// pre-compute normals for initial "meridian"
33547
33548		for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
33549
33550			switch ( j ) {
33551
33552				case 0:				// special handling for 1st vertex on path
33553
33554					dx = points[ j + 1 ].x - points[ j ].x;
33555					dy = points[ j + 1 ].y - points[ j ].y;
33556
33557					normal.x = dy * 1.0;
33558					normal.y = - dx;
33559					normal.z = dy * 0.0;
33560
33561					prevNormal.copy( normal );
33562
33563					normal.normalize();
33564
33565					initNormals.push( normal.x, normal.y, normal.z );
33566
33567					break;
33568
33569				case ( points.length - 1 ):	// special handling for last Vertex on path
33570
33571					initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z );
33572
33573					break;
33574
33575				default:			// default handling for all vertices in between
33576
33577					dx = points[ j + 1 ].x - points[ j ].x;
33578					dy = points[ j + 1 ].y - points[ j ].y;
33579
33580					normal.x = dy * 1.0;
33581					normal.y = - dx;
33582					normal.z = dy * 0.0;
33583
33584					curNormal.copy( normal );
33585
33586					normal.x += prevNormal.x;
33587					normal.y += prevNormal.y;
33588					normal.z += prevNormal.z;
33589
33590					normal.normalize();
33591
33592					initNormals.push( normal.x, normal.y, normal.z );
33593
33594					prevNormal.copy( curNormal );
33595
33596			}
33597
33598		}
33599
33600		// generate vertices, uvs and normals
33601
33602		for ( let i = 0; i <= segments; i ++ ) {
33603
33604			const phi = phiStart + i * inverseSegments * phiLength;
33605
33606			const sin = Math.sin( phi );
33607			const cos = Math.cos( phi );
33608
33609			for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
33610
33611				// vertex
33612
33613				vertex.x = points[ j ].x * sin;
33614				vertex.y = points[ j ].y;
33615				vertex.z = points[ j ].x * cos;
33616
33617				vertices.push( vertex.x, vertex.y, vertex.z );
33618
33619				// uv
33620
33621				uv.x = i / segments;
33622				uv.y = j / ( points.length - 1 );
33623
33624				uvs.push( uv.x, uv.y );
33625
33626				// normal
33627
33628				const x = initNormals[ 3 * j + 0 ] * sin;
33629				const y = initNormals[ 3 * j + 1 ];
33630				const z = initNormals[ 3 * j + 0 ] * cos;
33631
33632				normals.push( x, y, z );
33633
33634			}
33635
33636		}
33637
33638		// indices
33639
33640		for ( let i = 0; i < segments; i ++ ) {
33641
33642			for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
33643
33644				const base = j + i * points.length;
33645
33646				const a = base;
33647				const b = base + points.length;
33648				const c = base + points.length + 1;
33649				const d = base + 1;
33650
33651				// faces
33652
33653				indices.push( a, b, d );
33654				indices.push( c, d, b );
33655
33656			}
33657
33658		}
33659
33660		// build geometry
33661
33662		this.setIndex( indices );
33663		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
33664		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
33665		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
33666
33667	}
33668
33669	copy( source ) {
33670
33671		super.copy( source );
33672
33673		this.parameters = Object.assign( {}, source.parameters );
33674
33675		return this;
33676
33677	}
33678
33679	static fromJSON( data ) {
33680
33681		return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength );
33682
33683	}
33684
33685}
33686
33687class CapsuleGeometry extends LatheGeometry {
33688
33689	constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) {
33690
33691		const path = new Path();
33692		path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 );
33693		path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 );
33694
33695		super( path.getPoints( capSegments ), radialSegments );
33696
33697		this.type = 'CapsuleGeometry';
33698
33699		this.parameters = {
33700			radius: radius,
33701			height: length,
33702			capSegments: capSegments,
33703			radialSegments: radialSegments,
33704		};
33705
33706	}
33707
33708	static fromJSON( data ) {
33709
33710		return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments );
33711
33712	}
33713
33714}
33715
33716class CircleGeometry extends BufferGeometry {
33717
33718	constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) {
33719
33720		super();
33721
33722		this.type = 'CircleGeometry';
33723
33724		this.parameters = {
33725			radius: radius,
33726			segments: segments,
33727			thetaStart: thetaStart,
33728			thetaLength: thetaLength
33729		};
33730
33731		segments = Math.max( 3, segments );
33732
33733		// buffers
33734
33735		const indices = [];
33736		const vertices = [];
33737		const normals = [];
33738		const uvs = [];
33739
33740		// helper variables
33741
33742		const vertex = new Vector3();
33743		const uv = new Vector2();
33744
33745		// center point
33746
33747		vertices.push( 0, 0, 0 );
33748		normals.push( 0, 0, 1 );
33749		uvs.push( 0.5, 0.5 );
33750
33751		for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
33752
33753			const segment = thetaStart + s / segments * thetaLength;
33754
33755			// vertex
33756
33757			vertex.x = radius * Math.cos( segment );
33758			vertex.y = radius * Math.sin( segment );
33759
33760			vertices.push( vertex.x, vertex.y, vertex.z );
33761
33762			// normal
33763
33764			normals.push( 0, 0, 1 );
33765
33766			// uvs
33767
33768			uv.x = ( vertices[ i ] / radius + 1 ) / 2;
33769			uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
33770
33771			uvs.push( uv.x, uv.y );
33772
33773		}
33774
33775		// indices
33776
33777		for ( let i = 1; i <= segments; i ++ ) {
33778
33779			indices.push( i, i + 1, 0 );
33780
33781		}
33782
33783		// build geometry
33784
33785		this.setIndex( indices );
33786		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,756 bytes, lines 33787-34012
33787		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
33788		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
33789
33790	}
33791
33792	copy( source ) {
33793
33794		super.copy( source );
33795
33796		this.parameters = Object.assign( {}, source.parameters );
33797
33798		return this;
33799
33800	}
33801
33802	static fromJSON( data ) {
33803
33804		return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength );
33805
33806	}
33807
33808}
33809
33810class CylinderGeometry extends BufferGeometry {
33811
33812	constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
33813
33814		super();
33815
33816		this.type = 'CylinderGeometry';
33817
33818		this.parameters = {
33819			radiusTop: radiusTop,
33820			radiusBottom: radiusBottom,
33821			height: height,
33822			radialSegments: radialSegments,
33823			heightSegments: heightSegments,
33824			openEnded: openEnded,
33825			thetaStart: thetaStart,
33826			thetaLength: thetaLength
33827		};
33828
33829		const scope = this;
33830
33831		radialSegments = Math.floor( radialSegments );
33832		heightSegments = Math.floor( heightSegments );
33833
33834		// buffers
33835
33836		const indices = [];
33837		const vertices = [];
33838		const normals = [];
33839		const uvs = [];
33840
33841		// helper variables
33842
33843		let index = 0;
33844		const indexArray = [];
33845		const halfHeight = height / 2;
33846		let groupStart = 0;
33847
33848		// generate geometry
33849
33850		generateTorso();
33851
33852		if ( openEnded === false ) {
33853
33854			if ( radiusTop > 0 ) generateCap( true );
33855			if ( radiusBottom > 0 ) generateCap( false );
33856
33857		}
33858
33859		// build geometry
33860
33861		this.setIndex( indices );
33862		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
33863		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
33864		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
33865
33866		function generateTorso() {
33867
33868			const normal = new Vector3();
33869			const vertex = new Vector3();
33870
33871			let groupCount = 0;
33872
33873			// this will be used to calculate the normal
33874			const slope = ( radiusBottom - radiusTop ) / height;
33875
33876			// generate vertices, normals and uvs
33877
33878			for ( let y = 0; y <= heightSegments; y ++ ) {
33879
33880				const indexRow = [];
33881
33882				const v = y / heightSegments;
33883
33884				// calculate the radius of the current row
33885
33886				const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
33887
33888				for ( let x = 0; x <= radialSegments; x ++ ) {
33889
33890					const u = x / radialSegments;
33891
33892					const theta = u * thetaLength + thetaStart;
33893
33894					const sinTheta = Math.sin( theta );
33895					const cosTheta = Math.cos( theta );
33896
33897					// vertex
33898
33899					vertex.x = radius * sinTheta;
33900					vertex.y = - v * height + halfHeight;
33901					vertex.z = radius * cosTheta;
33902					vertices.push( vertex.x, vertex.y, vertex.z );
33903
33904					// normal
33905
33906					normal.set( sinTheta, slope, cosTheta ).normalize();
33907					normals.push( normal.x, normal.y, normal.z );
33908
33909					// uv
33910
33911					uvs.push( u, 1 - v );
33912
33913					// save index of vertex in respective row
33914
33915					indexRow.push( index ++ );
33916
33917				}
33918
33919				// now save vertices of the row in our index array
33920
33921				indexArray.push( indexRow );
33922
33923			}
33924
33925			// generate indices
33926
33927			for ( let x = 0; x < radialSegments; x ++ ) {
33928
33929				for ( let y = 0; y < heightSegments; y ++ ) {
33930
33931					// we use the index array to access the correct indices
33932
33933					const a = indexArray[ y ][ x ];
33934					const b = indexArray[ y + 1 ][ x ];
33935					const c = indexArray[ y + 1 ][ x + 1 ];
33936					const d = indexArray[ y ][ x + 1 ];
33937
33938					// faces
33939
33940					indices.push( a, b, d );
33941					indices.push( b, c, d );
33942
33943					// update group counter
33944
33945					groupCount += 6;
33946
33947				}
33948
33949			}
33950
33951			// add a group to the geometry. this will ensure multi material support
33952
33953			scope.addGroup( groupStart, groupCount, 0 );
33954
33955			// calculate new start value for groups
33956
33957			groupStart += groupCount;
33958
33959		}
33960
33961		function generateCap( top ) {
33962
33963			// save the index of the first center vertex
33964			const centerIndexStart = index;
33965
33966			const uv = new Vector2();
33967			const vertex = new Vector3();
33968
33969			let groupCount = 0;
33970
33971			const radius = ( top === true ) ? radiusTop : radiusBottom;
33972			const sign = ( top === true ) ? 1 : - 1;
33973
33974			// first we generate the center vertex data of the cap.
33975			// because the geometry needs one set of uvs per face,
33976			// we must generate a center vertex per face/segment
33977
33978			for ( let x = 1; x <= radialSegments; x ++ ) {
33979
33980				// vertex
33981
33982				vertices.push( 0, halfHeight * sign, 0 );
33983
33984				// normal
33985
33986				normals.push( 0, sign, 0 );
33987
33988				// uv
33989
33990				uvs.push( 0.5, 0.5 );
33991
33992				// increase index
33993
33994				index ++;
33995
33996			}
33997
33998			// save the index of the last center vertex
33999			const centerIndexEnd = index;
34000
34001			// now we generate the surrounding vertices, normals and uvs
34002
34003			for ( let x = 0; x <= radialSegments; x ++ ) {
34004
34005				const u = x / radialSegments;
34006				const theta = u * thetaLength + thetaStart;
34007
34008				const cosTheta = Math.cos( theta );
34009				const sinTheta = Math.sin( theta );
34010
34011				// vertex
34012
vendor: 16,069 bytes, lines 34013-34791
34013				vertex.x = radius * sinTheta;
34014				vertex.y = halfHeight * sign;
34015				vertex.z = radius * cosTheta;
34016				vertices.push( vertex.x, vertex.y, vertex.z );
34017
34018				// normal
34019
34020				normals.push( 0, sign, 0 );
34021
34022				// uv
34023
34024				uv.x = ( cosTheta * 0.5 ) + 0.5;
34025				uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
34026				uvs.push( uv.x, uv.y );
34027
34028				// increase index
34029
34030				index ++;
34031
34032			}
34033
34034			// generate indices
34035
34036			for ( let x = 0; x < radialSegments; x ++ ) {
34037
34038				const c = centerIndexStart + x;
34039				const i = centerIndexEnd + x;
34040
34041				if ( top === true ) {
34042
34043					// face top
34044
34045					indices.push( i, i + 1, c );
34046
34047				} else {
34048
34049					// face bottom
34050
34051					indices.push( i + 1, i, c );
34052
34053				}
34054
34055				groupCount += 3;
34056
34057			}
34058
34059			// add a group to the geometry. this will ensure multi material support
34060
34061			scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
34062
34063			// calculate new start value for groups
34064
34065			groupStart += groupCount;
34066
34067		}
34068
34069	}
34070
34071	copy( source ) {
34072
34073		super.copy( source );
34074
34075		this.parameters = Object.assign( {}, source.parameters );
34076
34077		return this;
34078
34079	}
34080
34081	static fromJSON( data ) {
34082
34083		return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
34084
34085	}
34086
34087}
34088
34089class ConeGeometry extends CylinderGeometry {
34090
34091	constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
34092
34093		super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
34094
34095		this.type = 'ConeGeometry';
34096
34097		this.parameters = {
34098			radius: radius,
34099			height: height,
34100			radialSegments: radialSegments,
34101			heightSegments: heightSegments,
34102			openEnded: openEnded,
34103			thetaStart: thetaStart,
34104			thetaLength: thetaLength
34105		};
34106
34107	}
34108
34109	static fromJSON( data ) {
34110
34111		return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
34112
34113	}
34114
34115}
34116
34117class PolyhedronGeometry extends BufferGeometry {
34118
34119	constructor( vertices = [], indices = [], radius = 1, detail = 0 ) {
34120
34121		super();
34122
34123		this.type = 'PolyhedronGeometry';
34124
34125		this.parameters = {
34126			vertices: vertices,
34127			indices: indices,
34128			radius: radius,
34129			detail: detail
34130		};
34131
34132		// default buffer data
34133
34134		const vertexBuffer = [];
34135		const uvBuffer = [];
34136
34137		// the subdivision creates the vertex buffer data
34138
34139		subdivide( detail );
34140
34141		// all vertices should lie on a conceptual sphere with a given radius
34142
34143		applyRadius( radius );
34144
34145		// finally, create the uv data
34146
34147		generateUVs();
34148
34149		// build non-indexed geometry
34150
34151		this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
34152		this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
34153		this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
34154
34155		if ( detail === 0 ) {
34156
34157			this.computeVertexNormals(); // flat normals
34158
34159		} else {
34160
34161			this.normalizeNormals(); // smooth normals
34162
34163		}
34164
34165		// helper functions
34166
34167		function subdivide( detail ) {
34168
34169			const a = new Vector3();
34170			const b = new Vector3();
34171			const c = new Vector3();
34172
34173			// iterate over all faces and apply a subdivision with the given detail value
34174
34175			for ( let i = 0; i < indices.length; i += 3 ) {
34176
34177				// get the vertices of the face
34178
34179				getVertexByIndex( indices[ i + 0 ], a );
34180				getVertexByIndex( indices[ i + 1 ], b );
34181				getVertexByIndex( indices[ i + 2 ], c );
34182
34183				// perform subdivision
34184
34185				subdivideFace( a, b, c, detail );
34186
34187			}
34188
34189		}
34190
34191		function subdivideFace( a, b, c, detail ) {
34192
34193			const cols = detail + 1;
34194
34195			// we use this multidimensional array as a data structure for creating the subdivision
34196
34197			const v = [];
34198
34199			// construct all of the vertices for this subdivision
34200
34201			for ( let i = 0; i <= cols; i ++ ) {
34202
34203				v[ i ] = [];
34204
34205				const aj = a.clone().lerp( c, i / cols );
34206				const bj = b.clone().lerp( c, i / cols );
34207
34208				const rows = cols - i;
34209
34210				for ( let j = 0; j <= rows; j ++ ) {
34211
34212					if ( j === 0 && i === cols ) {
34213
34214						v[ i ][ j ] = aj;
34215
34216					} else {
34217
34218						v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
34219
34220					}
34221
34222				}
34223
34224			}
34225
34226			// construct all of the faces
34227
34228			for ( let i = 0; i < cols; i ++ ) {
34229
34230				for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
34231
34232					const k = Math.floor( j / 2 );
34233
34234					if ( j % 2 === 0 ) {
34235
34236						pushVertex( v[ i ][ k + 1 ] );
34237						pushVertex( v[ i + 1 ][ k ] );
34238						pushVertex( v[ i ][ k ] );
34239
34240					} else {
34241
34242						pushVertex( v[ i ][ k + 1 ] );
34243						pushVertex( v[ i + 1 ][ k + 1 ] );
34244						pushVertex( v[ i + 1 ][ k ] );
34245
34246					}
34247
34248				}
34249
34250			}
34251
34252		}
34253
34254		function applyRadius( radius ) {
34255
34256			const vertex = new Vector3();
34257
34258			// iterate over the entire buffer and apply the radius to each vertex
34259
34260			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
34261
34262				vertex.x = vertexBuffer[ i + 0 ];
34263				vertex.y = vertexBuffer[ i + 1 ];
34264				vertex.z = vertexBuffer[ i + 2 ];
34265
34266				vertex.normalize().multiplyScalar( radius );
34267
34268				vertexBuffer[ i + 0 ] = vertex.x;
34269				vertexBuffer[ i + 1 ] = vertex.y;
34270				vertexBuffer[ i + 2 ] = vertex.z;
34271
34272			}
34273
34274		}
34275
34276		function generateUVs() {
34277
34278			const vertex = new Vector3();
34279
34280			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
34281
34282				vertex.x = vertexBuffer[ i + 0 ];
34283				vertex.y = vertexBuffer[ i + 1 ];
34284				vertex.z = vertexBuffer[ i + 2 ];
34285
34286				const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
34287				const v = inclination( vertex ) / Math.PI + 0.5;
34288				uvBuffer.push( u, 1 - v );
34289
34290			}
34291
34292			correctUVs();
34293
34294			correctSeam();
34295
34296		}
34297
34298		function correctSeam() {
34299
34300			// handle case when face straddles the seam, see #3269
34301
34302			for ( let i = 0; i < uvBuffer.length; i += 6 ) {
34303
34304				// uv data of a single face
34305
34306				const x0 = uvBuffer[ i + 0 ];
34307				const x1 = uvBuffer[ i + 2 ];
34308				const x2 = uvBuffer[ i + 4 ];
34309
34310				const max = Math.max( x0, x1, x2 );
34311				const min = Math.min( x0, x1, x2 );
34312
34313				// 0.9 is somewhat arbitrary
34314
34315				if ( max > 0.9 && min < 0.1 ) {
34316
34317					if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
34318					if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
34319					if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
34320
34321				}
34322
34323			}
34324
34325		}
34326
34327		function pushVertex( vertex ) {
34328
34329			vertexBuffer.push( vertex.x, vertex.y, vertex.z );
34330
34331		}
34332
34333		function getVertexByIndex( index, vertex ) {
34334
34335			const stride = index * 3;
34336
34337			vertex.x = vertices[ stride + 0 ];
34338			vertex.y = vertices[ stride + 1 ];
34339			vertex.z = vertices[ stride + 2 ];
34340
34341		}
34342
34343		function correctUVs() {
34344
34345			const a = new Vector3();
34346			const b = new Vector3();
34347			const c = new Vector3();
34348
34349			const centroid = new Vector3();
34350
34351			const uvA = new Vector2();
34352			const uvB = new Vector2();
34353			const uvC = new Vector2();
34354
34355			for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
34356
34357				a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
34358				b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
34359				c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
34360
34361				uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
34362				uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
34363				uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
34364
34365				centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
34366
34367				const azi = azimuth( centroid );
34368
34369				correctUV( uvA, j + 0, a, azi );
34370				correctUV( uvB, j + 2, b, azi );
34371				correctUV( uvC, j + 4, c, azi );
34372
34373			}
34374
34375		}
34376
34377		function correctUV( uv, stride, vector, azimuth ) {
34378
34379			if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
34380
34381				uvBuffer[ stride ] = uv.x - 1;
34382
34383			}
34384
34385			if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
34386
34387				uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
34388
34389			}
34390
34391		}
34392
34393		// Angle around the Y axis, counter-clockwise when looking from above.
34394
34395		function azimuth( vector ) {
34396
34397			return Math.atan2( vector.z, - vector.x );
34398
34399		}
34400
34401
34402		// Angle above the XZ plane.
34403
34404		function inclination( vector ) {
34405
34406			return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
34407
34408		}
34409
34410	}
34411
34412	copy( source ) {
34413
34414		super.copy( source );
34415
34416		this.parameters = Object.assign( {}, source.parameters );
34417
34418		return this;
34419
34420	}
34421
34422	static fromJSON( data ) {
34423
34424		return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details );
34425
34426	}
34427
34428}
34429
34430class DodecahedronGeometry extends PolyhedronGeometry {
34431
34432	constructor( radius = 1, detail = 0 ) {
34433
34434		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
34435		const r = 1 / t;
34436
34437		const vertices = [
34438
34439			// (±1, ±1, ±1)
34440			- 1, - 1, - 1,	- 1, - 1, 1,
34441			- 1, 1, - 1, - 1, 1, 1,
34442			1, - 1, - 1, 1, - 1, 1,
34443			1, 1, - 1, 1, 1, 1,
34444
34445			// (0, ±1/φ, ±φ)
34446			0, - r, - t, 0, - r, t,
34447			0, r, - t, 0, r, t,
34448
34449			// (±1/φ, ±φ, 0)
34450			- r, - t, 0, - r, t, 0,
34451			r, - t, 0, r, t, 0,
34452
34453			// (±φ, 0, ±1/φ)
34454			- t, 0, - r, t, 0, - r,
34455			- t, 0, r, t, 0, r
34456		];
34457
34458		const indices = [
34459			3, 11, 7, 	3, 7, 15, 	3, 15, 13,
34460			7, 19, 17, 	7, 17, 6, 	7, 6, 15,
34461			17, 4, 8, 	17, 8, 10, 	17, 10, 6,
34462			8, 0, 16, 	8, 16, 2, 	8, 2, 10,
34463			0, 12, 1, 	0, 1, 18, 	0, 18, 16,
34464			6, 10, 2, 	6, 2, 13, 	6, 13, 15,
34465			2, 16, 18, 	2, 18, 3, 	2, 3, 13,
34466			18, 1, 9, 	18, 9, 11, 	18, 11, 3,
34467			4, 14, 12, 	4, 12, 0, 	4, 0, 8,
34468			11, 9, 5, 	11, 5, 19, 	11, 19, 7,
34469			19, 5, 14, 	19, 14, 4, 	19, 4, 17,
34470			1, 12, 14, 	1, 14, 5, 	1, 5, 9
34471		];
34472
34473		super( vertices, indices, radius, detail );
34474
34475		this.type = 'DodecahedronGeometry';
34476
34477		this.parameters = {
34478			radius: radius,
34479			detail: detail
34480		};
34481
34482	}
34483
34484	static fromJSON( data ) {
34485
34486		return new DodecahedronGeometry( data.radius, data.detail );
34487
34488	}
34489
34490}
34491
34492const _v0 = /*@__PURE__*/ new Vector3();
34493const _v1$1 = /*@__PURE__*/ new Vector3();
34494const _normal = /*@__PURE__*/ new Vector3();
34495const _triangle = /*@__PURE__*/ new Triangle();
34496
34497class EdgesGeometry extends BufferGeometry {
34498
34499	constructor( geometry = null, thresholdAngle = 1 ) {
34500
34501		super();
34502
34503		this.type = 'EdgesGeometry';
34504
34505		this.parameters = {
34506			geometry: geometry,
34507			thresholdAngle: thresholdAngle
34508		};
34509
34510		if ( geometry !== null ) {
34511
34512			const precisionPoints = 4;
34513			const precision = Math.pow( 10, precisionPoints );
34514			const thresholdDot = Math.cos( DEG2RAD * thresholdAngle );
34515
34516			const indexAttr = geometry.getIndex();
34517			const positionAttr = geometry.getAttribute( 'position' );
34518			const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
34519
34520			const indexArr = [ 0, 0, 0 ];
34521			const vertKeys = [ 'a', 'b', 'c' ];
34522			const hashes = new Array( 3 );
34523
34524			const edgeData = {};
34525			const vertices = [];
34526			for ( let i = 0; i < indexCount; i += 3 ) {
34527
34528				if ( indexAttr ) {
34529
34530					indexArr[ 0 ] = indexAttr.getX( i );
34531					indexArr[ 1 ] = indexAttr.getX( i + 1 );
34532					indexArr[ 2 ] = indexAttr.getX( i + 2 );
34533
34534				} else {
34535
34536					indexArr[ 0 ] = i;
34537					indexArr[ 1 ] = i + 1;
34538					indexArr[ 2 ] = i + 2;
34539
34540				}
34541
34542				const { a, b, c } = _triangle;
34543				a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
34544				b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
34545				c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
34546				_triangle.getNormal( _normal );
34547
34548				// create hashes for the edge from the vertices
34549				hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
34550				hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
34551				hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
34552
34553				// skip degenerate triangles
34554				if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
34555
34556					continue;
34557
34558				}
34559
34560				// iterate over every edge
34561				for ( let j = 0; j < 3; j ++ ) {
34562
34563					// get the first and next vertex making up the edge
34564					const jNext = ( j + 1 ) % 3;
34565					const vecHash0 = hashes[ j ];
34566					const vecHash1 = hashes[ jNext ];
34567					const v0 = _triangle[ vertKeys[ j ] ];
34568					const v1 = _triangle[ vertKeys[ jNext ] ];
34569
34570					const hash = `${ vecHash0 }_${ vecHash1 }`;
34571					const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
34572
34573					if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
34574
34575						// if we found a sibling edge add it into the vertex array if
34576						// it meets the angle threshold and delete the edge from the map.
34577						if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
34578
34579							vertices.push( v0.x, v0.y, v0.z );
34580							vertices.push( v1.x, v1.y, v1.z );
34581
34582						}
34583
34584						edgeData[ reverseHash ] = null;
34585
34586					} else if ( ! ( hash in edgeData ) ) {
34587
34588						// if we've already got an edge here then skip adding a new one
34589						edgeData[ hash ] = {
34590
34591							index0: indexArr[ j ],
34592							index1: indexArr[ jNext ],
34593							normal: _normal.clone(),
34594
34595						};
34596
34597					}
34598
34599				}
34600
34601			}
34602
34603			// iterate over all remaining, unmatched edges and add them to the vertex array
34604			for ( const key in edgeData ) {
34605
34606				if ( edgeData[ key ] ) {
34607
34608					const { index0, index1 } = edgeData[ key ];
34609					_v0.fromBufferAttribute( positionAttr, index0 );
34610					_v1$1.fromBufferAttribute( positionAttr, index1 );
34611
34612					vertices.push( _v0.x, _v0.y, _v0.z );
34613					vertices.push( _v1$1.x, _v1$1.y, _v1$1.z );
34614
34615				}
34616
34617			}
34618
34619			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
34620
34621		}
34622
34623	}
34624
34625	copy( source ) {
34626
34627		super.copy( source );
34628
34629		this.parameters = Object.assign( {}, source.parameters );
34630
34631		return this;
34632
34633	}
34634
34635}
34636
34637class Shape extends Path {
34638
34639	constructor( points ) {
34640
34641		super( points );
34642
34643		this.uuid = generateUUID();
34644
34645		this.type = 'Shape';
34646
34647		this.holes = [];
34648
34649	}
34650
34651	getPointsHoles( divisions ) {
34652
34653		const holesPts = [];
34654
34655		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
34656
34657			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
34658
34659		}
34660
34661		return holesPts;
34662
34663	}
34664
34665	// get points of shape and holes (keypoints based on segments parameter)
34666
34667	extractPoints( divisions ) {
34668
34669		return {
34670
34671			shape: this.getPoints( divisions ),
34672			holes: this.getPointsHoles( divisions )
34673
34674		};
34675
34676	}
34677
34678	copy( source ) {
34679
34680		super.copy( source );
34681
34682		this.holes = [];
34683
34684		for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
34685
34686			const hole = source.holes[ i ];
34687
34688			this.holes.push( hole.clone() );
34689
34690		}
34691
34692		return this;
34693
34694	}
34695
34696	toJSON() {
34697
34698		const data = super.toJSON();
34699
34700		data.uuid = this.uuid;
34701		data.holes = [];
34702
34703		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
34704
34705			const hole = this.holes[ i ];
34706			data.holes.push( hole.toJSON() );
34707
34708		}
34709
34710		return data;
34711
34712	}
34713
34714	fromJSON( json ) {
34715
34716		super.fromJSON( json );
34717
34718		this.uuid = json.uuid;
34719		this.holes = [];
34720
34721		for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
34722
34723			const hole = json.holes[ i ];
34724			this.holes.push( new Path().fromJSON( hole ) );
34725
34726		}
34727
34728		return this;
34729
34730	}
34731
34732}
34733
34734/**
34735 * Port from https://github.com/mapbox/earcut (v2.2.4)
34736 */
34737
34738const Earcut = {
34739
34740	triangulate: function ( data, holeIndices, dim = 2 ) {
34741
34742		const hasHoles = holeIndices && holeIndices.length;
34743		const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
34744		let outerNode = linkedList( data, 0, outerLen, dim, true );
34745		const triangles = [];
34746
34747		if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
34748
34749		let minX, minY, maxX, maxY, x, y, invSize;
34750
34751		if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
34752
34753		// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
34754		if ( data.length > 80 * dim ) {
34755
34756			minX = maxX = data[ 0 ];
34757			minY = maxY = data[ 1 ];
34758
34759			for ( let i = dim; i < outerLen; i += dim ) {
34760
34761				x = data[ i ];
34762				y = data[ i + 1 ];
34763				if ( x < minX ) minX = x;
34764				if ( y < minY ) minY = y;
34765				if ( x > maxX ) maxX = x;
34766				if ( y > maxY ) maxY = y;
34767
34768			}
34769
34770			// minX, minY and invSize are later used to transform coords into integers for z-order calculation
34771			invSize = Math.max( maxX - minX, maxY - minY );
34772			invSize = invSize !== 0 ? 32767 / invSize : 0;
34773
34774		}
34775
34776		earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 );
34777
34778		return triangles;
34779
34780	}
34781
34782};
34783
34784// create a circular doubly linked list from polygon points in the specified winding order
34785function linkedList( data, start, end, dim, clockwise ) {
34786
34787	let i, last;
34788
34789	if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
34790
34791		for ( i = start; i < end;
vendor: 10,405 bytes, lines 34791-35264
34791 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
34792
34793	} else {
34794
34795		for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
34796
34797	}
34798
34799	if ( last && equals( last, last.next ) ) {
34800
34801		removeNode( last );
34802		last = last.next;
34803
34804	}
34805
34806	return last;
34807
34808}
34809
34810// eliminate colinear or duplicate points
34811function filterPoints( start, end ) {
34812
34813	if ( ! start ) return start;
34814	if ( ! end ) end = start;
34815
34816	let p = start,
34817		again;
34818	do {
34819
34820		again = false;
34821
34822		if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
34823
34824			removeNode( p );
34825			p = end = p.prev;
34826			if ( p === p.next ) break;
34827			again = true;
34828
34829		} else {
34830
34831			p = p.next;
34832
34833		}
34834
34835	} while ( again || p !== end );
34836
34837	return end;
34838
34839}
34840
34841// main ear slicing loop which triangulates a polygon (given as a linked list)
34842function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
34843
34844	if ( ! ear ) return;
34845
34846	// interlink polygon nodes in z-order
34847	if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
34848
34849	let stop = ear,
34850		prev, next;
34851
34852	// iterate through ears, slicing them one by one
34853	while ( ear.prev !== ear.next ) {
34854
34855		prev = ear.prev;
34856		next = ear.next;
34857
34858		if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
34859
34860			// cut off the triangle
34861			triangles.push( prev.i / dim | 0 );
34862			triangles.push( ear.i / dim | 0 );
34863			triangles.push( next.i / dim | 0 );
34864
34865			removeNode( ear );
34866
34867			// skipping the next vertex leads to less sliver triangles
34868			ear = next.next;
34869			stop = next.next;
34870
34871			continue;
34872
34873		}
34874
34875		ear = next;
34876
34877		// if we looped through the whole remaining polygon and can't find any more ears
34878		if ( ear === stop ) {
34879
34880			// try filtering points and slicing again
34881			if ( ! pass ) {
34882
34883				earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
34884
34885				// if this didn't work, try curing all small self-intersections locally
34886
34887			} else if ( pass === 1 ) {
34888
34889				ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
34890				earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
34891
34892				// as a last resort, try splitting the remaining polygon into two
34893
34894			} else if ( pass === 2 ) {
34895
34896				splitEarcut( ear, triangles, dim, minX, minY, invSize );
34897
34898			}
34899
34900			break;
34901
34902		}
34903
34904	}
34905
34906}
34907
34908// check whether a polygon node forms a valid ear with adjacent nodes
34909function isEar( ear ) {
34910
34911	const a = ear.prev,
34912		b = ear,
34913		c = ear.next;
34914
34915	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
34916
34917	// now make sure we don't have other points inside the potential ear
34918	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
34919
34920	// triangle bbox; min & max are calculated like this for speed
34921	const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
34922		y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
34923		x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
34924		y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
34925
34926	let p = c.next;
34927	while ( p !== a ) {
34928
34929		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
34930			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) &&
34931			area( p.prev, p, p.next ) >= 0 ) return false;
34932		p = p.next;
34933
34934	}
34935
34936	return true;
34937
34938}
34939
34940function isEarHashed( ear, minX, minY, invSize ) {
34941
34942	const a = ear.prev,
34943		b = ear,
34944		c = ear.next;
34945
34946	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
34947
34948	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
34949
34950	// triangle bbox; min & max are calculated like this for speed
34951	const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
34952		y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
34953		x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
34954		y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
34955
34956	// z-order range for the current triangle bbox;
34957	const minZ = zOrder( x0, y0, minX, minY, invSize ),
34958		maxZ = zOrder( x1, y1, minX, minY, invSize );
34959
34960	let p = ear.prevZ,
34961		n = ear.nextZ;
34962
34963	// look for points inside the triangle in both directions
34964	while ( p && p.z >= minZ && n && n.z <= maxZ ) {
34965
34966		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
34967			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
34968		p = p.prevZ;
34969
34970		if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
34971			pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
34972		n = n.nextZ;
34973
34974	}
34975
34976	// look for remaining points in decreasing z-order
34977	while ( p && p.z >= minZ ) {
34978
34979		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
34980			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
34981		p = p.prevZ;
34982
34983	}
34984
34985	// look for remaining points in increasing z-order
34986	while ( n && n.z <= maxZ ) {
34987
34988		if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
34989			pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
34990		n = n.nextZ;
34991
34992	}
34993
34994	return true;
34995
34996}
34997
34998// go through all polygon nodes and cure small local self-intersections
34999function cureLocalIntersections( start, triangles, dim ) {
35000
35001	let p = start;
35002	do {
35003
35004		const a = p.prev,
35005			b = p.next.next;
35006
35007		if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
35008
35009			triangles.push( a.i / dim | 0 );
35010			triangles.push( p.i / dim | 0 );
35011			triangles.push( b.i / dim | 0 );
35012
35013			// remove two nodes involved
35014			removeNode( p );
35015			removeNode( p.next );
35016
35017			p = start = b;
35018
35019		}
35020
35021		p = p.next;
35022
35023	} while ( p !== start );
35024
35025	return filterPoints( p );
35026
35027}
35028
35029// try splitting polygon into two and triangulate them independently
35030function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
35031
35032	// look for a valid diagonal that divides the polygon into two
35033	let a = start;
35034	do {
35035
35036		let b = a.next.next;
35037		while ( b !== a.prev ) {
35038
35039			if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
35040
35041				// split the polygon in two by the diagonal
35042				let c = splitPolygon( a, b );
35043
35044				// filter colinear points around the cuts
35045				a = filterPoints( a, a.next );
35046				c = filterPoints( c, c.next );
35047
35048				// run earcut on each half
35049				earcutLinked( a, triangles, dim, minX, minY, invSize, 0 );
35050				earcutLinked( c, triangles, dim, minX, minY, invSize, 0 );
35051				return;
35052
35053			}
35054
35055			b = b.next;
35056
35057		}
35058
35059		a = a.next;
35060
35061	} while ( a !== start );
35062
35063}
35064
35065// link every hole into the outer loop, producing a single-ring polygon without holes
35066function eliminateHoles( data, holeIndices, outerNode, dim ) {
35067
35068	const queue = [];
35069	let i, len, start, end, list;
35070
35071	for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
35072
35073		start = holeIndices[ i ] * dim;
35074		end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
35075		list = linkedList( data, start, end, dim, false );
35076		if ( list === list.next ) list.steiner = true;
35077		queue.push( getLeftmost( list ) );
35078
35079	}
35080
35081	queue.sort( compareX );
35082
35083	// process holes from left to right
35084	for ( i = 0; i < queue.length; i ++ ) {
35085
35086		outerNode = eliminateHole( queue[ i ], outerNode );
35087
35088	}
35089
35090	return outerNode;
35091
35092}
35093
35094function compareX( a, b ) {
35095
35096	return a.x - b.x;
35097
35098}
35099
35100// find a bridge between vertices that connects hole with an outer ring and link it
35101function eliminateHole( hole, outerNode ) {
35102
35103	const bridge = findHoleBridge( hole, outerNode );
35104	if ( ! bridge ) {
35105
35106		return outerNode;
35107
35108	}
35109
35110	const bridgeReverse = splitPolygon( bridge, hole );
35111
35112	// filter collinear points around the cuts
35113	filterPoints( bridgeReverse, bridgeReverse.next );
35114	return filterPoints( bridge, bridge.next );
35115
35116}
35117
35118// David Eberly's algorithm for finding a bridge between hole and outer polygon
35119function findHoleBridge( hole, outerNode ) {
35120
35121	let p = outerNode,
35122		qx = - Infinity,
35123		m;
35124
35125	const hx = hole.x, hy = hole.y;
35126
35127	// find a segment intersected by a ray from the hole's leftmost point to the left;
35128	// segment's endpoint with lesser x will be potential connection point
35129	do {
35130
35131		if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
35132
35133			const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
35134			if ( x <= hx && x > qx ) {
35135
35136				qx = x;
35137				m = p.x < p.next.x ? p : p.next;
35138				if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint
35139
35140			}
35141
35142		}
35143
35144		p = p.next;
35145
35146	} while ( p !== outerNode );
35147
35148	if ( ! m ) return null;
35149
35150	// look for points inside the triangle of hole point, segment intersection and endpoint;
35151	// if there are no points found, we have a valid connection;
35152	// otherwise choose the point of the minimum angle with the ray as connection point
35153
35154	const stop = m,
35155		mx = m.x,
35156		my = m.y;
35157	let tanMin = Infinity, tan;
35158
35159	p = m;
35160
35161	do {
35162
35163		if ( hx >= p.x && p.x >= mx && hx !== p.x &&
35164				pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
35165
35166			tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
35167
35168			if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
35169
35170				m = p;
35171				tanMin = tan;
35172
35173			}
35174
35175		}
35176
35177		p = p.next;
35178
35179	} while ( p !== stop );
35180
35181	return m;
35182
35183}
35184
35185// whether sector in vertex m contains sector in vertex p in the same coordinates
35186function sectorContainsSector( m, p ) {
35187
35188	return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
35189
35190}
35191
35192// interlink polygon nodes in z-order
35193function indexCurve( start, minX, minY, invSize ) {
35194
35195	let p = start;
35196	do {
35197
35198		if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
35199		p.prevZ = p.prev;
35200		p.nextZ = p.next;
35201		p = p.next;
35202
35203	} while ( p !== start );
35204
35205	p.prevZ.nextZ = null;
35206	p.prevZ = null;
35207
35208	sortLinked( p );
35209
35210}
35211
35212// Simon Tatham's linked list merge sort algorithm
35213// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
35214function sortLinked( list ) {
35215
35216	let i, p, q, e, tail, numMerges, pSize, qSize,
35217		inSize = 1;
35218
35219	do {
35220
35221		p = list;
35222		list = null;
35223		tail = null;
35224		numMerges = 0;
35225
35226		while ( p ) {
35227
35228			numMerges ++;
35229			q = p;
35230			pSize = 0;
35231			for ( i = 0; i < inSize; i ++ ) {
35232
35233				pSize ++;
35234				q = q.nextZ;
35235				if ( ! q ) break;
35236
35237			}
35238
35239			qSize = inSize;
35240
35241			while ( pSize > 0 || ( qSize > 0 && q ) ) {
35242
35243				if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
35244
35245					e = p;
35246					p = p.nextZ;
35247					pSize --;
35248
35249				} else {
35250
35251					e = q;
35252					q = q.nextZ;
35253					qSize --;
35254
35255				}
35256
35257				if ( tail ) tail.nextZ = e;
35258				else list = e;
35259
35260				e.prevZ = tail;
35261				tail = e;
35262
35263			}
35264
vendor: 9,706 bytes, lines 35265-35691
35265			p = q;
35266
35267		}
35268
35269		tail.nextZ = null;
35270		inSize *= 2;
35271
35272	} while ( numMerges > 1 );
35273
35274	return list;
35275
35276}
35277
35278// z-order of a point given coords and inverse of the longer side of data bbox
35279function zOrder( x, y, minX, minY, invSize ) {
35280
35281	// coords are transformed into non-negative 15-bit integer range
35282	x = ( x - minX ) * invSize | 0;
35283	y = ( y - minY ) * invSize | 0;
35284
35285	x = ( x | ( x << 8 ) ) & 0x00FF00FF;
35286	x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
35287	x = ( x | ( x << 2 ) ) & 0x33333333;
35288	x = ( x | ( x << 1 ) ) & 0x55555555;
35289
35290	y = ( y | ( y << 8 ) ) & 0x00FF00FF;
35291	y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
35292	y = ( y | ( y << 2 ) ) & 0x33333333;
35293	y = ( y | ( y << 1 ) ) & 0x55555555;
35294
35295	return x | ( y << 1 );
35296
35297}
35298
35299// find the leftmost node of a polygon ring
35300function getLeftmost( start ) {
35301
35302	let p = start,
35303		leftmost = start;
35304	do {
35305
35306		if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
35307		p = p.next;
35308
35309	} while ( p !== start );
35310
35311	return leftmost;
35312
35313}
35314
35315// check if a point lies within a convex triangle
35316function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
35317
35318	return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) &&
35319           ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) &&
35320           ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py );
35321
35322}
35323
35324// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
35325function isValidDiagonal( a, b ) {
35326
35327	return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges
35328           ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
35329            ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
35330            equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
35331
35332}
35333
35334// signed area of a triangle
35335function area( p, q, r ) {
35336
35337	return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
35338
35339}
35340
35341// check if two points are equal
35342function equals( p1, p2 ) {
35343
35344	return p1.x === p2.x && p1.y === p2.y;
35345
35346}
35347
35348// check if two segments intersect
35349function intersects( p1, q1, p2, q2 ) {
35350
35351	const o1 = sign( area( p1, q1, p2 ) );
35352	const o2 = sign( area( p1, q1, q2 ) );
35353	const o3 = sign( area( p2, q2, p1 ) );
35354	const o4 = sign( area( p2, q2, q1 ) );
35355
35356	if ( o1 !== o2 && o3 !== o4 ) return true; // general case
35357
35358	if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
35359	if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
35360	if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
35361	if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
35362
35363	return false;
35364
35365}
35366
35367// for collinear points p, q, r, check if point q lies on segment pr
35368function onSegment( p, q, r ) {
35369
35370	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 );
35371
35372}
35373
35374function sign( num ) {
35375
35376	return num > 0 ? 1 : num < 0 ? - 1 : 0;
35377
35378}
35379
35380// check if a polygon diagonal intersects any polygon segments
35381function intersectsPolygon( a, b ) {
35382
35383	let p = a;
35384	do {
35385
35386		if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
35387			intersects( p, p.next, a, b ) ) return true;
35388		p = p.next;
35389
35390	} while ( p !== a );
35391
35392	return false;
35393
35394}
35395
35396// check if a polygon diagonal is locally inside the polygon
35397function locallyInside( a, b ) {
35398
35399	return area( a.prev, a, a.next ) < 0 ?
35400		area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
35401		area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
35402
35403}
35404
35405// check if the middle point of a polygon diagonal is inside the polygon
35406function middleInside( a, b ) {
35407
35408	let p = a,
35409		inside = false;
35410	const px = ( a.x + b.x ) / 2,
35411		py = ( a.y + b.y ) / 2;
35412	do {
35413
35414		if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
35415			( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
35416			inside = ! inside;
35417		p = p.next;
35418
35419	} while ( p !== a );
35420
35421	return inside;
35422
35423}
35424
35425// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
35426// if one belongs to the outer ring and another to a hole, it merges it into a single ring
35427function splitPolygon( a, b ) {
35428
35429	const a2 = new Node( a.i, a.x, a.y ),
35430		b2 = new Node( b.i, b.x, b.y ),
35431		an = a.next,
35432		bp = b.prev;
35433
35434	a.next = b;
35435	b.prev = a;
35436
35437	a2.next = an;
35438	an.prev = a2;
35439
35440	b2.next = a2;
35441	a2.prev = b2;
35442
35443	bp.next = b2;
35444	b2.prev = bp;
35445
35446	return b2;
35447
35448}
35449
35450// create a node and optionally link it with previous one (in a circular doubly linked list)
35451function insertNode( i, x, y, last ) {
35452
35453	const p = new Node( i, x, y );
35454
35455	if ( ! last ) {
35456
35457		p.prev = p;
35458		p.next = p;
35459
35460	} else {
35461
35462		p.next = last.next;
35463		p.prev = last;
35464		last.next.prev = p;
35465		last.next = p;
35466
35467	}
35468
35469	return p;
35470
35471}
35472
35473function removeNode( p ) {
35474
35475	p.next.prev = p.prev;
35476	p.prev.next = p.next;
35477
35478	if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
35479	if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
35480
35481}
35482
35483function Node( i, x, y ) {
35484
35485	// vertex index in coordinates array
35486	this.i = i;
35487
35488	// vertex coordinates
35489	this.x = x;
35490	this.y = y;
35491
35492	// previous and next vertex nodes in a polygon ring
35493	this.prev = null;
35494	this.next = null;
35495
35496	// z-order curve value
35497	this.z = 0;
35498
35499	// previous and next nodes in z-order
35500	this.prevZ = null;
35501	this.nextZ = null;
35502
35503	// indicates whether this is a steiner point
35504	this.steiner = false;
35505
35506}
35507
35508function signedArea( data, start, end, dim ) {
35509
35510	let sum = 0;
35511	for ( let i = start, j = end - dim; i < end; i += dim ) {
35512
35513		sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
35514		j = i;
35515
35516	}
35517
35518	return sum;
35519
35520}
35521
35522class ShapeUtils {
35523
35524	// calculate area of the contour polygon
35525
35526	static area( contour ) {
35527
35528		const n = contour.length;
35529		let a = 0.0;
35530
35531		for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
35532
35533			a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
35534
35535		}
35536
35537		return a * 0.5;
35538
35539	}
35540
35541	static isClockWise( pts ) {
35542
35543		return ShapeUtils.area( pts ) < 0;
35544
35545	}
35546
35547	static triangulateShape( contour, holes ) {
35548
35549		const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
35550		const holeIndices = []; // array of hole indices
35551		const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
35552
35553		removeDupEndPts( contour );
35554		addContour( vertices, contour );
35555
35556		//
35557
35558		let holeIndex = contour.length;
35559
35560		holes.forEach( removeDupEndPts );
35561
35562		for ( let i = 0; i < holes.length; i ++ ) {
35563
35564			holeIndices.push( holeIndex );
35565			holeIndex += holes[ i ].length;
35566			addContour( vertices, holes[ i ] );
35567
35568		}
35569
35570		//
35571
35572		const triangles = Earcut.triangulate( vertices, holeIndices );
35573
35574		//
35575
35576		for ( let i = 0; i < triangles.length; i += 3 ) {
35577
35578			faces.push( triangles.slice( i, i + 3 ) );
35579
35580		}
35581
35582		return faces;
35583
35584	}
35585
35586}
35587
35588function removeDupEndPts( points ) {
35589
35590	const l = points.length;
35591
35592	if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
35593
35594		points.pop();
35595
35596	}
35597
35598}
35599
35600function addContour( vertices, contour ) {
35601
35602	for ( let i = 0; i < contour.length; i ++ ) {
35603
35604		vertices.push( contour[ i ].x );
35605		vertices.push( contour[ i ].y );
35606
35607	}
35608
35609}
35610
35611/**
35612 * Creates extruded geometry from a path shape.
35613 *
35614 * parameters = {
35615 *
35616 *  curveSegments: <int>, // number of points on the curves
35617 *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
35618 *  depth: <float>, // Depth to extrude the shape
35619 *
35620 *  bevelEnabled: <bool>, // turn on bevel
35621 *  bevelThickness: <float>, // how deep into the original shape bevel goes
35622 *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
35623 *  bevelOffset: <float>, // how far from shape outline does bevel start
35624 *  bevelSegments: <int>, // number of bevel layers
35625 *
35626 *  extrudePath: <THREE.Curve> // curve to extrude shape along
35627 *
35628 *  UVGenerator: <Object> // object that provides UV generator functions
35629 *
35630 * }
35631 */
35632
35633class ExtrudeGeometry extends BufferGeometry {
35634
35635	constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) {
35636
35637		super();
35638
35639		this.type = 'ExtrudeGeometry';
35640
35641		this.parameters = {
35642			shapes: shapes,
35643			options: options
35644		};
35645
35646		shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
35647
35648		const scope = this;
35649
35650		const verticesArray = [];
35651		const uvArray = [];
35652
35653		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
35654
35655			const shape = shapes[ i ];
35656			addShape( shape );
35657
35658		}
35659
35660		// build geometry
35661
35662		this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
35663		this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
35664
35665		this.computeVertexNormals();
35666
35667		// functions
35668
35669		function addShape( shape ) {
35670
35671			const placeholder = [];
35672
35673			// options
35674
35675			const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
35676			const steps = options.steps !== undefined ? options.steps : 1;
35677			const depth = options.depth !== undefined ? options.depth : 1;
35678
35679			let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
35680			let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
35681			let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
35682			let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
35683			let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
35684
35685			const extrudePath = options.extrudePath;
35686
35687			const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
35688
35689			//
35690
35691			let extrudePts, extrudeByPath = false;
vendor: 2,791 bytes, lines 35692-35805
35692			let splineTube, binormal, normal, position2;
35693
35694			if ( extrudePath ) {
35695
35696				extrudePts = extrudePath.getSpacedPoints( steps );
35697
35698				extrudeByPath = true;
35699				bevelEnabled = false; // bevels not supported for path extrusion
35700
35701				// SETUP TNB variables
35702
35703				// TODO1 - have a .isClosed in spline?
35704
35705				splineTube = extrudePath.computeFrenetFrames( steps, false );
35706
35707				// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
35708
35709				binormal = new Vector3();
35710				normal = new Vector3();
35711				position2 = new Vector3();
35712
35713			}
35714
35715			// Safeguards if bevels are not enabled
35716
35717			if ( ! bevelEnabled ) {
35718
35719				bevelSegments = 0;
35720				bevelThickness = 0;
35721				bevelSize = 0;
35722				bevelOffset = 0;
35723
35724			}
35725
35726			// Variables initialization
35727
35728			const shapePoints = shape.extractPoints( curveSegments );
35729
35730			let vertices = shapePoints.shape;
35731			const holes = shapePoints.holes;
35732
35733			const reverse = ! ShapeUtils.isClockWise( vertices );
35734
35735			if ( reverse ) {
35736
35737				vertices = vertices.reverse();
35738
35739				// Maybe we should also check if holes are in the opposite direction, just to be safe ...
35740
35741				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35742
35743					const ahole = holes[ h ];
35744
35745					if ( ShapeUtils.isClockWise( ahole ) ) {
35746
35747						holes[ h ] = ahole.reverse();
35748
35749					}
35750
35751				}
35752
35753			}
35754
35755
35756			const faces = ShapeUtils.triangulateShape( vertices, holes );
35757
35758			/* Vertices */
35759
35760			const contour = vertices; // vertices has all points but contour has only points of circumference
35761
35762			for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35763
35764				const ahole = holes[ h ];
35765
35766				vertices = vertices.concat( ahole );
35767
35768			}
35769
35770
35771			function scalePt2( pt, vec, size ) {
35772
35773				if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
35774
35775				return pt.clone().addScaledVector( vec, size );
35776
35777			}
35778
35779			const vlen = vertices.length, flen = faces.length;
35780
35781
35782			// Find directions for point movement
35783
35784
35785			function getBevelVec( inPt, inPrev, inNext ) {
35786
35787				// computes for inPt the corresponding point inPt' on a new contour
35788				//   shifted by 1 unit (length of normalized vector) to the left
35789				// if we walk along contour clockwise, this new contour is outside the old one
35790				//
35791				// inPt' is the intersection of the two lines parallel to the two
35792				//  adjacent edges of inPt at a distance of 1 unit on the left side.
35793
35794				let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
35795
35796				// good reading for geometry algorithms (here: line-line intersection)
35797				// http://geomalgorithms.com/a05-_intersect-1.html
35798
35799				const v_prev_x = inPt.x - inPrev.x,
35800					v_prev_y = inPt.y - inPrev.y;
35801				const v_next_x = inNext.x - inPt.x,
35802					v_next_y = inNext.y - inPt.y;
35803
35804				const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
35805
vendor: 17,452 bytes, lines 35806-36657
35806				// check for collinear edges
35807				const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
35808
35809				if ( Math.abs( collinear0 ) > Number.EPSILON ) {
35810
35811					// not collinear
35812
35813					// length of vectors for normalizing
35814
35815					const v_prev_len = Math.sqrt( v_prev_lensq );
35816					const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
35817
35818					// shift adjacent points by unit vectors to the left
35819
35820					const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
35821					const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
35822
35823					const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
35824					const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
35825
35826					// scaling factor for v_prev to intersection point
35827
35828					const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
35829							( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
35830						( v_prev_x * v_next_y - v_prev_y * v_next_x );
35831
35832					// vector from inPt to intersection point
35833
35834					v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
35835					v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
35836
35837					// Don't normalize!, otherwise sharp corners become ugly
35838					//  but prevent crazy spikes
35839					const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
35840					if ( v_trans_lensq <= 2 ) {
35841
35842						return new Vector2( v_trans_x, v_trans_y );
35843
35844					} else {
35845
35846						shrink_by = Math.sqrt( v_trans_lensq / 2 );
35847
35848					}
35849
35850				} else {
35851
35852					// handle special case of collinear edges
35853
35854					let direction_eq = false; // assumes: opposite
35855
35856					if ( v_prev_x > Number.EPSILON ) {
35857
35858						if ( v_next_x > Number.EPSILON ) {
35859
35860							direction_eq = true;
35861
35862						}
35863
35864					} else {
35865
35866						if ( v_prev_x < - Number.EPSILON ) {
35867
35868							if ( v_next_x < - Number.EPSILON ) {
35869
35870								direction_eq = true;
35871
35872							}
35873
35874						} else {
35875
35876							if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
35877
35878								direction_eq = true;
35879
35880							}
35881
35882						}
35883
35884					}
35885
35886					if ( direction_eq ) {
35887
35888						// console.log("Warning: lines are a straight sequence");
35889						v_trans_x = - v_prev_y;
35890						v_trans_y = v_prev_x;
35891						shrink_by = Math.sqrt( v_prev_lensq );
35892
35893					} else {
35894
35895						// console.log("Warning: lines are a straight spike");
35896						v_trans_x = v_prev_x;
35897						v_trans_y = v_prev_y;
35898						shrink_by = Math.sqrt( v_prev_lensq / 2 );
35899
35900					}
35901
35902				}
35903
35904				return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
35905
35906			}
35907
35908
35909			const contourMovements = [];
35910
35911			for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
35912
35913				if ( j === il ) j = 0;
35914				if ( k === il ) k = 0;
35915
35916				//  (j)---(i)---(k)
35917				// console.log('i,j,k', i, j , k)
35918
35919				contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
35920
35921			}
35922
35923			const holesMovements = [];
35924			let oneHoleMovements, verticesMovements = contourMovements.concat();
35925
35926			for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35927
35928				const ahole = holes[ h ];
35929
35930				oneHoleMovements = [];
35931
35932				for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
35933
35934					if ( j === il ) j = 0;
35935					if ( k === il ) k = 0;
35936
35937					//  (j)---(i)---(k)
35938					oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
35939
35940				}
35941
35942				holesMovements.push( oneHoleMovements );
35943				verticesMovements = verticesMovements.concat( oneHoleMovements );
35944
35945			}
35946
35947
35948			// Loop bevelSegments, 1 for the front, 1 for the back
35949
35950			for ( let b = 0; b < bevelSegments; b ++ ) {
35951
35952				//for ( b = bevelSegments; b > 0; b -- ) {
35953
35954				const t = b / bevelSegments;
35955				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
35956				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
35957
35958				// contract shape
35959
35960				for ( let i = 0, il = contour.length; i < il; i ++ ) {
35961
35962					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
35963
35964					v( vert.x, vert.y, - z );
35965
35966				}
35967
35968				// expand holes
35969
35970				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35971
35972					const ahole = holes[ h ];
35973					oneHoleMovements = holesMovements[ h ];
35974
35975					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
35976
35977						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
35978
35979						v( vert.x, vert.y, - z );
35980
35981					}
35982
35983				}
35984
35985			}
35986
35987			const bs = bevelSize + bevelOffset;
35988
35989			// Back facing vertices
35990
35991			for ( let i = 0; i < vlen; i ++ ) {
35992
35993				const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
35994
35995				if ( ! extrudeByPath ) {
35996
35997					v( vert.x, vert.y, 0 );
35998
35999				} else {
36000
36001					// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
36002
36003					normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
36004					binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
36005
36006					position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
36007
36008					v( position2.x, position2.y, position2.z );
36009
36010				}
36011
36012			}
36013
36014			// Add stepped vertices...
36015			// Including front facing vertices
36016
36017			for ( let s = 1; s <= steps; s ++ ) {
36018
36019				for ( let i = 0; i < vlen; i ++ ) {
36020
36021					const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
36022
36023					if ( ! extrudeByPath ) {
36024
36025						v( vert.x, vert.y, depth / steps * s );
36026
36027					} else {
36028
36029						// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
36030
36031						normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
36032						binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
36033
36034						position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
36035
36036						v( position2.x, position2.y, position2.z );
36037
36038					}
36039
36040				}
36041
36042			}
36043
36044
36045			// Add bevel segments planes
36046
36047			//for ( b = 1; b <= bevelSegments; b ++ ) {
36048			for ( let b = bevelSegments - 1; b >= 0; b -- ) {
36049
36050				const t = b / bevelSegments;
36051				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
36052				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
36053
36054				// contract shape
36055
36056				for ( let i = 0, il = contour.length; i < il; i ++ ) {
36057
36058					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
36059					v( vert.x, vert.y, depth + z );
36060
36061				}
36062
36063				// expand holes
36064
36065				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
36066
36067					const ahole = holes[ h ];
36068					oneHoleMovements = holesMovements[ h ];
36069
36070					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
36071
36072						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
36073
36074						if ( ! extrudeByPath ) {
36075
36076							v( vert.x, vert.y, depth + z );
36077
36078						} else {
36079
36080							v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
36081
36082						}
36083
36084					}
36085
36086				}
36087
36088			}
36089
36090			/* Faces */
36091
36092			// Top and bottom faces
36093
36094			buildLidFaces();
36095
36096			// Sides faces
36097
36098			buildSideFaces();
36099
36100
36101			/////  Internal functions
36102
36103			function buildLidFaces() {
36104
36105				const start = verticesArray.length / 3;
36106
36107				if ( bevelEnabled ) {
36108
36109					let layer = 0; // steps + 1
36110					let offset = vlen * layer;
36111
36112					// Bottom faces
36113
36114					for ( let i = 0; i < flen; i ++ ) {
36115
36116						const face = faces[ i ];
36117						f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
36118
36119					}
36120
36121					layer = steps + bevelSegments * 2;
36122					offset = vlen * layer;
36123
36124					// Top faces
36125
36126					for ( let i = 0; i < flen; i ++ ) {
36127
36128						const face = faces[ i ];
36129						f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
36130
36131					}
36132
36133				} else {
36134
36135					// Bottom faces
36136
36137					for ( let i = 0; i < flen; i ++ ) {
36138
36139						const face = faces[ i ];
36140						f3( face[ 2 ], face[ 1 ], face[ 0 ] );
36141
36142					}
36143
36144					// Top faces
36145
36146					for ( let i = 0; i < flen; i ++ ) {
36147
36148						const face = faces[ i ];
36149						f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
36150
36151					}
36152
36153				}
36154
36155				scope.addGroup( start, verticesArray.length / 3 - start, 0 );
36156
36157			}
36158
36159			// Create faces for the z-sides of the shape
36160
36161			function buildSideFaces() {
36162
36163				const start = verticesArray.length / 3;
36164				let layeroffset = 0;
36165				sidewalls( contour, layeroffset );
36166				layeroffset += contour.length;
36167
36168				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
36169
36170					const ahole = holes[ h ];
36171					sidewalls( ahole, layeroffset );
36172
36173					//, true
36174					layeroffset += ahole.length;
36175
36176				}
36177
36178
36179				scope.addGroup( start, verticesArray.length / 3 - start, 1 );
36180
36181
36182			}
36183
36184			function sidewalls( contour, layeroffset ) {
36185
36186				let i = contour.length;
36187
36188				while ( -- i >= 0 ) {
36189
36190					const j = i;
36191					let k = i - 1;
36192					if ( k < 0 ) k = contour.length - 1;
36193
36194					//console.log('b', i,j, i-1, k,vertices.length);
36195
36196					for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
36197
36198						const slen1 = vlen * s;
36199						const slen2 = vlen * ( s + 1 );
36200
36201						const a = layeroffset + j + slen1,
36202							b = layeroffset + k + slen1,
36203							c = layeroffset + k + slen2,
36204							d = layeroffset + j + slen2;
36205
36206						f4( a, b, c, d );
36207
36208					}
36209
36210				}
36211
36212			}
36213
36214			function v( x, y, z ) {
36215
36216				placeholder.push( x );
36217				placeholder.push( y );
36218				placeholder.push( z );
36219
36220			}
36221
36222
36223			function f3( a, b, c ) {
36224
36225				addVertex( a );
36226				addVertex( b );
36227				addVertex( c );
36228
36229				const nextIndex = verticesArray.length / 3;
36230				const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
36231
36232				addUV( uvs[ 0 ] );
36233				addUV( uvs[ 1 ] );
36234				addUV( uvs[ 2 ] );
36235
36236			}
36237
36238			function f4( a, b, c, d ) {
36239
36240				addVertex( a );
36241				addVertex( b );
36242				addVertex( d );
36243
36244				addVertex( b );
36245				addVertex( c );
36246				addVertex( d );
36247
36248
36249				const nextIndex = verticesArray.length / 3;
36250				const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
36251
36252				addUV( uvs[ 0 ] );
36253				addUV( uvs[ 1 ] );
36254				addUV( uvs[ 3 ] );
36255
36256				addUV( uvs[ 1 ] );
36257				addUV( uvs[ 2 ] );
36258				addUV( uvs[ 3 ] );
36259
36260			}
36261
36262			function addVertex( index ) {
36263
36264				verticesArray.push( placeholder[ index * 3 + 0 ] );
36265				verticesArray.push( placeholder[ index * 3 + 1 ] );
36266				verticesArray.push( placeholder[ index * 3 + 2 ] );
36267
36268			}
36269
36270
36271			function addUV( vector2 ) {
36272
36273				uvArray.push( vector2.x );
36274				uvArray.push( vector2.y );
36275
36276			}
36277
36278		}
36279
36280	}
36281
36282	copy( source ) {
36283
36284		super.copy( source );
36285
36286		this.parameters = Object.assign( {}, source.parameters );
36287
36288		return this;
36289
36290	}
36291
36292	toJSON() {
36293
36294		const data = super.toJSON();
36295
36296		const shapes = this.parameters.shapes;
36297		const options = this.parameters.options;
36298
36299		return toJSON$1( shapes, options, data );
36300
36301	}
36302
36303	static fromJSON( data, shapes ) {
36304
36305		const geometryShapes = [];
36306
36307		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
36308
36309			const shape = shapes[ data.shapes[ j ] ];
36310
36311			geometryShapes.push( shape );
36312
36313		}
36314
36315		const extrudePath = data.options.extrudePath;
36316
36317		if ( extrudePath !== undefined ) {
36318
36319			data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
36320
36321		}
36322
36323		return new ExtrudeGeometry( geometryShapes, data.options );
36324
36325	}
36326
36327}
36328
36329const WorldUVGenerator = {
36330
36331	generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
36332
36333		const a_x = vertices[ indexA * 3 ];
36334		const a_y = vertices[ indexA * 3 + 1 ];
36335		const b_x = vertices[ indexB * 3 ];
36336		const b_y = vertices[ indexB * 3 + 1 ];
36337		const c_x = vertices[ indexC * 3 ];
36338		const c_y = vertices[ indexC * 3 + 1 ];
36339
36340		return [
36341			new Vector2( a_x, a_y ),
36342			new Vector2( b_x, b_y ),
36343			new Vector2( c_x, c_y )
36344		];
36345
36346	},
36347
36348	generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
36349
36350		const a_x = vertices[ indexA * 3 ];
36351		const a_y = vertices[ indexA * 3 + 1 ];
36352		const a_z = vertices[ indexA * 3 + 2 ];
36353		const b_x = vertices[ indexB * 3 ];
36354		const b_y = vertices[ indexB * 3 + 1 ];
36355		const b_z = vertices[ indexB * 3 + 2 ];
36356		const c_x = vertices[ indexC * 3 ];
36357		const c_y = vertices[ indexC * 3 + 1 ];
36358		const c_z = vertices[ indexC * 3 + 2 ];
36359		const d_x = vertices[ indexD * 3 ];
36360		const d_y = vertices[ indexD * 3 + 1 ];
36361		const d_z = vertices[ indexD * 3 + 2 ];
36362
36363		if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) {
36364
36365			return [
36366				new Vector2( a_x, 1 - a_z ),
36367				new Vector2( b_x, 1 - b_z ),
36368				new Vector2( c_x, 1 - c_z ),
36369				new Vector2( d_x, 1 - d_z )
36370			];
36371
36372		} else {
36373
36374			return [
36375				new Vector2( a_y, 1 - a_z ),
36376				new Vector2( b_y, 1 - b_z ),
36377				new Vector2( c_y, 1 - c_z ),
36378				new Vector2( d_y, 1 - d_z )
36379			];
36380
36381		}
36382
36383	}
36384
36385};
36386
36387function toJSON$1( shapes, options, data ) {
36388
36389	data.shapes = [];
36390
36391	if ( Array.isArray( shapes ) ) {
36392
36393		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
36394
36395			const shape = shapes[ i ];
36396
36397			data.shapes.push( shape.uuid );
36398
36399		}
36400
36401	} else {
36402
36403		data.shapes.push( shapes.uuid );
36404
36405	}
36406
36407	data.options = Object.assign( {}, options );
36408
36409	if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
36410
36411	return data;
36412
36413}
36414
36415class IcosahedronGeometry extends PolyhedronGeometry {
36416
36417	constructor( radius = 1, detail = 0 ) {
36418
36419		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
36420
36421		const vertices = [
36422			- 1, t, 0, 	1, t, 0, 	- 1, - t, 0, 	1, - t, 0,
36423			0, - 1, t, 	0, 1, t,	0, - 1, - t, 	0, 1, - t,
36424			t, 0, - 1, 	t, 0, 1, 	- t, 0, - 1, 	- t, 0, 1
36425		];
36426
36427		const indices = [
36428			0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
36429			1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
36430			3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
36431			4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
36432		];
36433
36434		super( vertices, indices, radius, detail );
36435
36436		this.type = 'IcosahedronGeometry';
36437
36438		this.parameters = {
36439			radius: radius,
36440			detail: detail
36441		};
36442
36443	}
36444
36445	static fromJSON( data ) {
36446
36447		return new IcosahedronGeometry( data.radius, data.detail );
36448
36449	}
36450
36451}
36452
36453class OctahedronGeometry extends PolyhedronGeometry {
36454
36455	constructor( radius = 1, detail = 0 ) {
36456
36457		const vertices = [
36458			1, 0, 0, 	- 1, 0, 0,	0, 1, 0,
36459			0, - 1, 0, 	0, 0, 1,	0, 0, - 1
36460		];
36461
36462		const indices = [
36463			0, 2, 4,	0, 4, 3,	0, 3, 5,
36464			0, 5, 2,	1, 2, 5,	1, 5, 3,
36465			1, 3, 4,	1, 4, 2
36466		];
36467
36468		super( vertices, indices, radius, detail );
36469
36470		this.type = 'OctahedronGeometry';
36471
36472		this.parameters = {
36473			radius: radius,
36474			detail: detail
36475		};
36476
36477	}
36478
36479	static fromJSON( data ) {
36480
36481		return new OctahedronGeometry( data.radius, data.detail );
36482
36483	}
36484
36485}
36486
36487class RingGeometry extends BufferGeometry {
36488
36489	constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
36490
36491		super();
36492
36493		this.type = 'RingGeometry';
36494
36495		this.parameters = {
36496			innerRadius: innerRadius,
36497			outerRadius: outerRadius,
36498			thetaSegments: thetaSegments,
36499			phiSegments: phiSegments,
36500			thetaStart: thetaStart,
36501			thetaLength: thetaLength
36502		};
36503
36504		thetaSegments = Math.max( 3, thetaSegments );
36505		phiSegments = Math.max( 1, phiSegments );
36506
36507		// buffers
36508
36509		const indices = [];
36510		const vertices = [];
36511		const normals = [];
36512		const uvs = [];
36513
36514		// some helper variables
36515
36516		let radius = innerRadius;
36517		const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
36518		const vertex = new Vector3();
36519		const uv = new Vector2();
36520
36521		// generate vertices, normals and uvs
36522
36523		for ( let j = 0; j <= phiSegments; j ++ ) {
36524
36525			for ( let i = 0; i <= thetaSegments; i ++ ) {
36526
36527				// values are generate from the inside of the ring to the outside
36528
36529				const segment = thetaStart + i / thetaSegments * thetaLength;
36530
36531				// vertex
36532
36533				vertex.x = radius * Math.cos( segment );
36534				vertex.y = radius * Math.sin( segment );
36535
36536				vertices.push( vertex.x, vertex.y, vertex.z );
36537
36538				// normal
36539
36540				normals.push( 0, 0, 1 );
36541
36542				// uv
36543
36544				uv.x = ( vertex.x / outerRadius + 1 ) / 2;
36545				uv.y = ( vertex.y / outerRadius + 1 ) / 2;
36546
36547				uvs.push( uv.x, uv.y );
36548
36549			}
36550
36551			// increase the radius for next row of vertices
36552
36553			radius += radiusStep;
36554
36555		}
36556
36557		// indices
36558
36559		for ( let j = 0; j < phiSegments; j ++ ) {
36560
36561			const thetaSegmentLevel = j * ( thetaSegments + 1 );
36562
36563			for ( let i = 0; i < thetaSegments; i ++ ) {
36564
36565				const segment = i + thetaSegmentLevel;
36566
36567				const a = segment;
36568				const b = segment + thetaSegments + 1;
36569				const c = segment + thetaSegments + 2;
36570				const d = segment + 1;
36571
36572				// faces
36573
36574				indices.push( a, b, d );
36575				indices.push( b, c, d );
36576
36577			}
36578
36579		}
36580
36581		// build geometry
36582
36583		this.setIndex( indices );
36584		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36585		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36586		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36587
36588	}
36589
36590	copy( source ) {
36591
36592		super.copy( source );
36593
36594		this.parameters = Object.assign( {}, source.parameters );
36595
36596		return this;
36597
36598	}
36599
36600	static fromJSON( data ) {
36601
36602		return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength );
36603
36604	}
36605
36606}
36607
36608class ShapeGeometry extends BufferGeometry {
36609
36610	constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) {
36611
36612		super();
36613
36614		this.type = 'ShapeGeometry';
36615
36616		this.parameters = {
36617			shapes: shapes,
36618			curveSegments: curveSegments
36619		};
36620
36621		// buffers
36622
36623		const indices = [];
36624		const vertices = [];
36625		const normals = [];
36626		const uvs = [];
36627
36628		// helper variables
36629
36630		let groupStart = 0;
36631		let groupCount = 0;
36632
36633		// allow single and array values for "shapes" parameter
36634
36635		if ( Array.isArray( shapes ) === false ) {
36636
36637			addShape( shapes );
36638
36639		} else {
36640
36641			for ( let i = 0; i < shapes.length; i ++ ) {
36642
36643				addShape( shapes[ i ] );
36644
36645				this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
36646
36647				groupStart += groupCount;
36648				groupCount = 0;
36649
36650			}
36651
36652		}
36653
36654		// build geometry
36655
36656		this.setIndex( indices );
36657		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,874 bytes, lines 36658-36904
36658		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36659		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36660
36661
36662		// helper functions
36663
36664		function addShape( shape ) {
36665
36666			const indexOffset = vertices.length / 3;
36667			const points = shape.extractPoints( curveSegments );
36668
36669			let shapeVertices = points.shape;
36670			const shapeHoles = points.holes;
36671
36672			// check direction of vertices
36673
36674			if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
36675
36676				shapeVertices = shapeVertices.reverse();
36677
36678			}
36679
36680			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
36681
36682				const shapeHole = shapeHoles[ i ];
36683
36684				if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
36685
36686					shapeHoles[ i ] = shapeHole.reverse();
36687
36688				}
36689
36690			}
36691
36692			const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
36693
36694			// join vertices of inner and outer paths to a single array
36695
36696			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
36697
36698				const shapeHole = shapeHoles[ i ];
36699				shapeVertices = shapeVertices.concat( shapeHole );
36700
36701			}
36702
36703			// vertices, normals, uvs
36704
36705			for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
36706
36707				const vertex = shapeVertices[ i ];
36708
36709				vertices.push( vertex.x, vertex.y, 0 );
36710				normals.push( 0, 0, 1 );
36711				uvs.push( vertex.x, vertex.y ); // world uvs
36712
36713			}
36714
36715			// indices
36716
36717			for ( let i = 0, l = faces.length; i < l; i ++ ) {
36718
36719				const face = faces[ i ];
36720
36721				const a = face[ 0 ] + indexOffset;
36722				const b = face[ 1 ] + indexOffset;
36723				const c = face[ 2 ] + indexOffset;
36724
36725				indices.push( a, b, c );
36726				groupCount += 3;
36727
36728			}
36729
36730		}
36731
36732	}
36733
36734	copy( source ) {
36735
36736		super.copy( source );
36737
36738		this.parameters = Object.assign( {}, source.parameters );
36739
36740		return this;
36741
36742	}
36743
36744	toJSON() {
36745
36746		const data = super.toJSON();
36747
36748		const shapes = this.parameters.shapes;
36749
36750		return toJSON( shapes, data );
36751
36752	}
36753
36754	static fromJSON( data, shapes ) {
36755
36756		const geometryShapes = [];
36757
36758		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
36759
36760			const shape = shapes[ data.shapes[ j ] ];
36761
36762			geometryShapes.push( shape );
36763
36764		}
36765
36766		return new ShapeGeometry( geometryShapes, data.curveSegments );
36767
36768	}
36769
36770}
36771
36772function toJSON( shapes, data ) {
36773
36774	data.shapes = [];
36775
36776	if ( Array.isArray( shapes ) ) {
36777
36778		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
36779
36780			const shape = shapes[ i ];
36781
36782			data.shapes.push( shape.uuid );
36783
36784		}
36785
36786	} else {
36787
36788		data.shapes.push( shapes.uuid );
36789
36790	}
36791
36792	return data;
36793
36794}
36795
36796class SphereGeometry extends BufferGeometry {
36797
36798	constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
36799
36800		super();
36801
36802		this.type = 'SphereGeometry';
36803
36804		this.parameters = {
36805			radius: radius,
36806			widthSegments: widthSegments,
36807			heightSegments: heightSegments,
36808			phiStart: phiStart,
36809			phiLength: phiLength,
36810			thetaStart: thetaStart,
36811			thetaLength: thetaLength
36812		};
36813
36814		widthSegments = Math.max( 3, Math.floor( widthSegments ) );
36815		heightSegments = Math.max( 2, Math.floor( heightSegments ) );
36816
36817		const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
36818
36819		let index = 0;
36820		const grid = [];
36821
36822		const vertex = new Vector3();
36823		const normal = new Vector3();
36824
36825		// buffers
36826
36827		const indices = [];
36828		const vertices = [];
36829		const normals = [];
36830		const uvs = [];
36831
36832		// generate vertices, normals and uvs
36833
36834		for ( let iy = 0; iy <= heightSegments; iy ++ ) {
36835
36836			const verticesRow = [];
36837
36838			const v = iy / heightSegments;
36839
36840			// special case for the poles
36841
36842			let uOffset = 0;
36843
36844			if ( iy == 0 && thetaStart == 0 ) {
36845
36846				uOffset = 0.5 / widthSegments;
36847
36848			} else if ( iy == heightSegments && thetaEnd == Math.PI ) {
36849
36850				uOffset = - 0.5 / widthSegments;
36851
36852			}
36853
36854			for ( let ix = 0; ix <= widthSegments; ix ++ ) {
36855
36856				const u = ix / widthSegments;
36857
36858				// vertex
36859
36860				vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
36861				vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
36862				vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
36863
36864				vertices.push( vertex.x, vertex.y, vertex.z );
36865
36866				// normal
36867
36868				normal.copy( vertex ).normalize();
36869				normals.push( normal.x, normal.y, normal.z );
36870
36871				// uv
36872
36873				uvs.push( u + uOffset, 1 - v );
36874
36875				verticesRow.push( index ++ );
36876
36877			}
36878
36879			grid.push( verticesRow );
36880
36881		}
36882
36883		// indices
36884
36885		for ( let iy = 0; iy < heightSegments; iy ++ ) {
36886
36887			for ( let ix = 0; ix < widthSegments; ix ++ ) {
36888
36889				const a = grid[ iy ][ ix + 1 ];
36890				const b = grid[ iy ][ ix ];
36891				const c = grid[ iy + 1 ][ ix ];
36892				const d = grid[ iy + 1 ][ ix + 1 ];
36893
36894				if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
36895				if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
36896
36897			}
36898
36899		}
36900
36901		// build geometry
36902
36903		this.setIndex( indices );
36904		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 6,566 bytes, lines 36905-37197
36905		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36906		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36907
36908	}
36909
36910	copy( source ) {
36911
36912		super.copy( source );
36913
36914		this.parameters = Object.assign( {}, source.parameters );
36915
36916		return this;
36917
36918	}
36919
36920	static fromJSON( data ) {
36921
36922		return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength );
36923
36924	}
36925
36926}
36927
36928class TetrahedronGeometry extends PolyhedronGeometry {
36929
36930	constructor( radius = 1, detail = 0 ) {
36931
36932		const vertices = [
36933			1, 1, 1, 	- 1, - 1, 1, 	- 1, 1, - 1, 	1, - 1, - 1
36934		];
36935
36936		const indices = [
36937			2, 1, 0, 	0, 3, 2,	1, 3, 0,	2, 3, 1
36938		];
36939
36940		super( vertices, indices, radius, detail );
36941
36942		this.type = 'TetrahedronGeometry';
36943
36944		this.parameters = {
36945			radius: radius,
36946			detail: detail
36947		};
36948
36949	}
36950
36951	static fromJSON( data ) {
36952
36953		return new TetrahedronGeometry( data.radius, data.detail );
36954
36955	}
36956
36957}
36958
36959class TorusGeometry extends BufferGeometry {
36960
36961	constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) {
36962
36963		super();
36964
36965		this.type = 'TorusGeometry';
36966
36967		this.parameters = {
36968			radius: radius,
36969			tube: tube,
36970			radialSegments: radialSegments,
36971			tubularSegments: tubularSegments,
36972			arc: arc
36973		};
36974
36975		radialSegments = Math.floor( radialSegments );
36976		tubularSegments = Math.floor( tubularSegments );
36977
36978		// buffers
36979
36980		const indices = [];
36981		const vertices = [];
36982		const normals = [];
36983		const uvs = [];
36984
36985		// helper variables
36986
36987		const center = new Vector3();
36988		const vertex = new Vector3();
36989		const normal = new Vector3();
36990
36991		// generate vertices, normals and uvs
36992
36993		for ( let j = 0; j <= radialSegments; j ++ ) {
36994
36995			for ( let i = 0; i <= tubularSegments; i ++ ) {
36996
36997				const u = i / tubularSegments * arc;
36998				const v = j / radialSegments * Math.PI * 2;
36999
37000				// vertex
37001
37002				vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
37003				vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
37004				vertex.z = tube * Math.sin( v );
37005
37006				vertices.push( vertex.x, vertex.y, vertex.z );
37007
37008				// normal
37009
37010				center.x = radius * Math.cos( u );
37011				center.y = radius * Math.sin( u );
37012				normal.subVectors( vertex, center ).normalize();
37013
37014				normals.push( normal.x, normal.y, normal.z );
37015
37016				// uv
37017
37018				uvs.push( i / tubularSegments );
37019				uvs.push( j / radialSegments );
37020
37021			}
37022
37023		}
37024
37025		// generate indices
37026
37027		for ( let j = 1; j <= radialSegments; j ++ ) {
37028
37029			for ( let i = 1; i <= tubularSegments; i ++ ) {
37030
37031				// indices
37032
37033				const a = ( tubularSegments + 1 ) * j + i - 1;
37034				const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
37035				const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
37036				const d = ( tubularSegments + 1 ) * j + i;
37037
37038				// faces
37039
37040				indices.push( a, b, d );
37041				indices.push( b, c, d );
37042
37043			}
37044
37045		}
37046
37047		// build geometry
37048
37049		this.setIndex( indices );
37050		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37051		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37052		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37053
37054	}
37055
37056	copy( source ) {
37057
37058		super.copy( source );
37059
37060		this.parameters = Object.assign( {}, source.parameters );
37061
37062		return this;
37063
37064	}
37065
37066	static fromJSON( data ) {
37067
37068		return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc );
37069
37070	}
37071
37072}
37073
37074class TorusKnotGeometry extends BufferGeometry {
37075
37076	constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
37077
37078		super();
37079
37080		this.type = 'TorusKnotGeometry';
37081
37082		this.parameters = {
37083			radius: radius,
37084			tube: tube,
37085			tubularSegments: tubularSegments,
37086			radialSegments: radialSegments,
37087			p: p,
37088			q: q
37089		};
37090
37091		tubularSegments = Math.floor( tubularSegments );
37092		radialSegments = Math.floor( radialSegments );
37093
37094		// buffers
37095
37096		const indices = [];
37097		const vertices = [];
37098		const normals = [];
37099		const uvs = [];
37100
37101		// helper variables
37102
37103		const vertex = new Vector3();
37104		const normal = new Vector3();
37105
37106		const P1 = new Vector3();
37107		const P2 = new Vector3();
37108
37109		const B = new Vector3();
37110		const T = new Vector3();
37111		const N = new Vector3();
37112
37113		// generate vertices, normals and uvs
37114
37115		for ( let i = 0; i <= tubularSegments; ++ i ) {
37116
37117			// the radian "u" is used to calculate the position on the torus curve of the current tubular segment
37118
37119			const u = i / tubularSegments * p * Math.PI * 2;
37120
37121			// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
37122			// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
37123
37124			calculatePositionOnCurve( u, p, q, radius, P1 );
37125			calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
37126
37127			// calculate orthonormal basis
37128
37129			T.subVectors( P2, P1 );
37130			N.addVectors( P2, P1 );
37131			B.crossVectors( T, N );
37132			N.crossVectors( B, T );
37133
37134			// normalize B, N. T can be ignored, we don't use it
37135
37136			B.normalize();
37137			N.normalize();
37138
37139			for ( let j = 0; j <= radialSegments; ++ j ) {
37140
37141				// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
37142				// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
37143
37144				const v = j / radialSegments * Math.PI * 2;
37145				const cx = - tube * Math.cos( v );
37146				const cy = tube * Math.sin( v );
37147
37148				// now calculate the final vertex position.
37149				// first we orient the extrusion with our basis vectors, then we add it to the current position on the curve
37150
37151				vertex.x = P1.x + ( cx * N.x + cy * B.x );
37152				vertex.y = P1.y + ( cx * N.y + cy * B.y );
37153				vertex.z = P1.z + ( cx * N.z + cy * B.z );
37154
37155				vertices.push( vertex.x, vertex.y, vertex.z );
37156
37157				// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
37158
37159				normal.subVectors( vertex, P1 ).normalize();
37160
37161				normals.push( normal.x, normal.y, normal.z );
37162
37163				// uv
37164
37165				uvs.push( i / tubularSegments );
37166				uvs.push( j / radialSegments );
37167
37168			}
37169
37170		}
37171
37172		// generate indices
37173
37174		for ( let j = 1; j <= tubularSegments; j ++ ) {
37175
37176			for ( let i = 1; i <= radialSegments; i ++ ) {
37177
37178				// indices
37179
37180				const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
37181				const b = ( radialSegments + 1 ) * j + ( i - 1 );
37182				const c = ( radialSegments + 1 ) * j + i;
37183				const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
37184
37185				// faces
37186
37187				indices.push( a, b, d );
37188				indices.push( b, c, d );
37189
37190			}
37191
37192		}
37193
37194		// build geometry
37195
37196		this.setIndex( indices );
37197		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 7,450 bytes, lines 37198-37556
37198		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37199		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37200
37201		// this function calculates the current position on the torus curve
37202
37203		function calculatePositionOnCurve( u, p, q, radius, position ) {
37204
37205			const cu = Math.cos( u );
37206			const su = Math.sin( u );
37207			const quOverP = q / p * u;
37208			const cs = Math.cos( quOverP );
37209
37210			position.x = radius * ( 2 + cs ) * 0.5 * cu;
37211			position.y = radius * ( 2 + cs ) * su * 0.5;
37212			position.z = radius * Math.sin( quOverP ) * 0.5;
37213
37214		}
37215
37216	}
37217
37218	copy( source ) {
37219
37220		super.copy( source );
37221
37222		this.parameters = Object.assign( {}, source.parameters );
37223
37224		return this;
37225
37226	}
37227
37228	static fromJSON( data ) {
37229
37230		return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q );
37231
37232	}
37233
37234}
37235
37236class TubeGeometry extends BufferGeometry {
37237
37238	constructor( path = new QuadraticBezierCurve3( new Vector3( - 1, - 1, 0 ), new Vector3( - 1, 1, 0 ), new Vector3( 1, 1, 0 ) ), tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) {
37239
37240		super();
37241
37242		this.type = 'TubeGeometry';
37243
37244		this.parameters = {
37245			path: path,
37246			tubularSegments: tubularSegments,
37247			radius: radius,
37248			radialSegments: radialSegments,
37249			closed: closed
37250		};
37251
37252		const frames = path.computeFrenetFrames( tubularSegments, closed );
37253
37254		// expose internals
37255
37256		this.tangents = frames.tangents;
37257		this.normals = frames.normals;
37258		this.binormals = frames.binormals;
37259
37260		// helper variables
37261
37262		const vertex = new Vector3();
37263		const normal = new Vector3();
37264		const uv = new Vector2();
37265		let P = new Vector3();
37266
37267		// buffer
37268
37269		const vertices = [];
37270		const normals = [];
37271		const uvs = [];
37272		const indices = [];
37273
37274		// create buffer data
37275
37276		generateBufferData();
37277
37278		// build geometry
37279
37280		this.setIndex( indices );
37281		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37282		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37283		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37284
37285		// functions
37286
37287		function generateBufferData() {
37288
37289			for ( let i = 0; i < tubularSegments; i ++ ) {
37290
37291				generateSegment( i );
37292
37293			}
37294
37295			// if the geometry is not closed, generate the last row of vertices and normals
37296			// at the regular position on the given path
37297			//
37298			// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
37299
37300			generateSegment( ( closed === false ) ? tubularSegments : 0 );
37301
37302			// uvs are generated in a separate function.
37303			// this makes it easy compute correct values for closed geometries
37304
37305			generateUVs();
37306
37307			// finally create faces
37308
37309			generateIndices();
37310
37311		}
37312
37313		function generateSegment( i ) {
37314
37315			// we use getPointAt to sample evenly distributed points from the given path
37316
37317			P = path.getPointAt( i / tubularSegments, P );
37318
37319			// retrieve corresponding normal and binormal
37320
37321			const N = frames.normals[ i ];
37322			const B = frames.binormals[ i ];
37323
37324			// generate normals and vertices for the current segment
37325
37326			for ( let j = 0; j <= radialSegments; j ++ ) {
37327
37328				const v = j / radialSegments * Math.PI * 2;
37329
37330				const sin = Math.sin( v );
37331				const cos = - Math.cos( v );
37332
37333				// normal
37334
37335				normal.x = ( cos * N.x + sin * B.x );
37336				normal.y = ( cos * N.y + sin * B.y );
37337				normal.z = ( cos * N.z + sin * B.z );
37338				normal.normalize();
37339
37340				normals.push( normal.x, normal.y, normal.z );
37341
37342				// vertex
37343
37344				vertex.x = P.x + radius * normal.x;
37345				vertex.y = P.y + radius * normal.y;
37346				vertex.z = P.z + radius * normal.z;
37347
37348				vertices.push( vertex.x, vertex.y, vertex.z );
37349
37350			}
37351
37352		}
37353
37354		function generateIndices() {
37355
37356			for ( let j = 1; j <= tubularSegments; j ++ ) {
37357
37358				for ( let i = 1; i <= radialSegments; i ++ ) {
37359
37360					const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
37361					const b = ( radialSegments + 1 ) * j + ( i - 1 );
37362					const c = ( radialSegments + 1 ) * j + i;
37363					const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
37364
37365					// faces
37366
37367					indices.push( a, b, d );
37368					indices.push( b, c, d );
37369
37370				}
37371
37372			}
37373
37374		}
37375
37376		function generateUVs() {
37377
37378			for ( let i = 0; i <= tubularSegments; i ++ ) {
37379
37380				for ( let j = 0; j <= radialSegments; j ++ ) {
37381
37382					uv.x = i / tubularSegments;
37383					uv.y = j / radialSegments;
37384
37385					uvs.push( uv.x, uv.y );
37386
37387				}
37388
37389			}
37390
37391		}
37392
37393	}
37394
37395	copy( source ) {
37396
37397		super.copy( source );
37398
37399		this.parameters = Object.assign( {}, source.parameters );
37400
37401		return this;
37402
37403	}
37404
37405	toJSON() {
37406
37407		const data = super.toJSON();
37408
37409		data.path = this.parameters.path.toJSON();
37410
37411		return data;
37412
37413	}
37414
37415	static fromJSON( data ) {
37416
37417		// This only works for built-in curves (e.g. CatmullRomCurve3).
37418		// User defined curves or instances of CurvePath will not be deserialized.
37419		return new TubeGeometry(
37420			new Curves[ data.path.type ]().fromJSON( data.path ),
37421			data.tubularSegments,
37422			data.radius,
37423			data.radialSegments,
37424			data.closed
37425		);
37426
37427	}
37428
37429}
37430
37431class WireframeGeometry extends BufferGeometry {
37432
37433	constructor( geometry = null ) {
37434
37435		super();
37436
37437		this.type = 'WireframeGeometry';
37438
37439		this.parameters = {
37440			geometry: geometry
37441		};
37442
37443		if ( geometry !== null ) {
37444
37445			// buffer
37446
37447			const vertices = [];
37448			const edges = new Set();
37449
37450			// helper variables
37451
37452			const start = new Vector3();
37453			const end = new Vector3();
37454
37455			if ( geometry.index !== null ) {
37456
37457				// indexed BufferGeometry
37458
37459				const position = geometry.attributes.position;
37460				const indices = geometry.index;
37461				let groups = geometry.groups;
37462
37463				if ( groups.length === 0 ) {
37464
37465					groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
37466
37467				}
37468
37469				// create a data structure that contains all edges without duplicates
37470
37471				for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
37472
37473					const group = groups[ o ];
37474
37475					const groupStart = group.start;
37476					const groupCount = group.count;
37477
37478					for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) {
37479
37480						for ( let j = 0; j < 3; j ++ ) {
37481
37482							const index1 = indices.getX( i + j );
37483							const index2 = indices.getX( i + ( j + 1 ) % 3 );
37484
37485							start.fromBufferAttribute( position, index1 );
37486							end.fromBufferAttribute( position, index2 );
37487
37488							if ( isUniqueEdge( start, end, edges ) === true ) {
37489
37490								vertices.push( start.x, start.y, start.z );
37491								vertices.push( end.x, end.y, end.z );
37492
37493							}
37494
37495						}
37496
37497					}
37498
37499				}
37500
37501			} else {
37502
37503				// non-indexed BufferGeometry
37504
37505				const position = geometry.attributes.position;
37506
37507				for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
37508
37509					for ( let j = 0; j < 3; j ++ ) {
37510
37511						// three edges per triangle, an edge is represented as (index1, index2)
37512						// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
37513
37514						const index1 = 3 * i + j;
37515						const index2 = 3 * i + ( ( j + 1 ) % 3 );
37516
37517						start.fromBufferAttribute( position, index1 );
37518						end.fromBufferAttribute( position, index2 );
37519
37520						if ( isUniqueEdge( start, end, edges ) === true ) {
37521
37522							vertices.push( start.x, start.y, start.z );
37523							vertices.push( end.x, end.y, end.z );
37524
37525						}
37526
37527					}
37528
37529				}
37530
37531			}
37532
37533			// build geometry
37534
37535			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37536
37537		}
37538
37539	}
37540
37541	copy( source ) {
37542
37543		super.copy( source );
37544
37545		this.parameters = Object.assign( {}, source.parameters );
37546
37547		return this;
37548
37549	}
37550
37551}
37552
37553function isUniqueEdge( start, end, edges ) {
37554
37555	const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`;
37556	const hash2 = `${end.x}
37556,${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge
37557
37558	if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) {
37559
37560		return false;
37561
37562	} else {
37563
37564		edges.add( hash1 );
37565		edges.add( hash2 );
37566		return true;
37567
37568	}
37569
37570}
37571
37572var Geometries = /*#__PURE__*/Object.freeze({
37573	__proto__: null,
37574	BoxGeometry: BoxGeometry,
37575	CapsuleGeometry: CapsuleGeometry,
37576	CircleGeometry: CircleGeometry,
37577	ConeGeometry: ConeGeometry,
37578	CylinderGeometry: CylinderGeometry,
37579	DodecahedronGeometry: DodecahedronGeometry,
37580	EdgesGeometry: EdgesGeometry,
37581	ExtrudeGeometry: ExtrudeGeometry,
37582	IcosahedronGeometry: IcosahedronGeometry,
37583	LatheGeometry: LatheGeometry,
37584	OctahedronGeometry: OctahedronGeometry,
37585	PlaneGeometry: PlaneGeometry,
37586	PolyhedronGeometry: PolyhedronGeometry,
37587	RingGeometry: RingGeometry,
37588	ShapeGeometry: ShapeGeometry,
37589	SphereGeometry: SphereGeometry,
37590	TetrahedronGeometry: TetrahedronGeometry,
37591	TorusGeometry: TorusGeometry,
37592	TorusKnotGeometry: TorusKnotGeometry,
37593	TubeGeometry: TubeGeometry,
37594	WireframeGeometry: WireframeGeometry
37595});
37596
37597class ShadowMaterial extends Material {
37598
37599	constructor( parameters ) {
37600
37601		super();
37602
37603		this.isShadowMaterial = true;
37604
37605		this.type = 'ShadowMaterial';
37606
37607		this.color = new Color( 0x000000 );
37608		this.transparent = true;
37609
37610		this.fog = true;
37611
37612		this.setValues( parameters );
37613
37614	}
37615
37616	copy( source ) {
37617
37618		super.copy( source );
37619
37620		this.color.copy( source.color );
37621
37622		this.fog = source.fog;
37623
37624		return this;
37625
37626	}
37627
37628}
37629
37630class RawShaderMaterial extends ShaderMaterial {
37631
37632	constructor( parameters ) {
37633
37634		super( parameters );
37635
37636		this.isRawShaderMaterial = true;
37637
37638		this.type = 'RawShaderMaterial';
37639
37640	}
37641
37642}
37643
37644class MeshStandardMaterial extends Material {
37645
37646	constructor( parameters ) {
37647
37648		super();
37649
37650		this.isMeshStandardMaterial = true;
37651
37652		this.defines = { 'STANDARD': '' };
37653
37654		this.type = 'MeshStandardMaterial';
37655
37656		this.color = new Color( 0xffffff ); // diffuse
37657		this.roughness = 1.0;
37658		this.metalness = 0.0;
37659
37660		this.map = null;
37661
37662		this.lightMap = null;
37663		this.lightMapIntensity = 1.0;
37664
37665		this.aoMap = null;
37666		this.aoMapIntensity = 1.0;
37667
37668		this.emissive = new Color( 0x000000 );
37669		this.emissiveIntensity = 1.0;
37670		this.emissiveMap = null;
37671
37672		this.bumpMap = null;
37673		this.bumpScale = 1;
37674
37675		this.normalMap = null;
37676		this.normalMapType = TangentSpaceNormalMap;
37677		this.normalScale = new Vector2( 1, 1 );
37678
37679		this.displacementMap = null;
37680		this.displacementScale = 1;
37681		this.displacementBias = 0;
37682
37683		this.roughnessMap = null;
37684
37685		this.metalnessMap = null;
37686
37687		this.alphaMap = null;
37688
37689		this.envMap = null;
37690		this.envMapIntensity = 1.0;
37691
37692		this.wireframe = false;
37693		this.wireframeLinewidth = 1;
37694		this.wireframeLinecap = 'round';
37695		this.wireframeLinejoin = 'round';
37696
37697		this.flatShading = false;
37698
37699		this.fog = true;
37700
37701		this.setValues( parameters );
37702
37703	}
37704
37705	copy( source ) {
37706
37707		super.copy( source );
37708
37709		this.defines = { 'STANDARD': '' };
37710
37711		this.color.copy( source.color );
37712		this.roughness = source.roughness;
37713		this.metalness = source.metalness;
37714
37715		this.map = source.map;
37716
37717		this.lightMap = source.lightMap;
37718		this.lightMapIntensity = source.lightMapIntensity;
37719
37720		this.aoMap = source.aoMap;
37721		this.aoMapIntensity = source.aoMapIntensity;
37722
37723		this.emissive.copy( source.emissive );
37724		this.emissiveMap = source.emissiveMap;
37725		this.emissiveIntensity = source.emissiveIntensity;
37726
37727		this.bumpMap = source.bumpMap;
37728		this.bumpScale = source.bumpScale;
37729
37730		this.normalMap = source.normalMap;
37731		this.normalMapType = source.normalMapType;
37732		this.normalScale.copy( source.normalScale );
37733
37734		this.displacementMap = source.displacementMap;
37735		this.displacementScale = source.displacementScale;
37736		this.displacementBias = source.displacementBias;
37737
37738		this.roughnessMap = source.roughnessMap;
37739
37740		this.metalnessMap = source.metalnessMap;
37741
37742		this.alphaMap = source.alphaMap;
37743
37744		this.envMap = source.envMap;
37745		this.envMapIntensity = source.envMapIntensity;
37746
37747		this.wireframe = source.wireframe;
37748		this.wireframeLinewidth = source.wireframeLinewidth;
37749		this.wireframeLinecap = source.wireframeLinecap;
37750		this.wireframeLinejoin = source.wireframeLinejoin;
37751
37752		this.flatShading = source.flatShading;
37753
37754		this.fog = source.fog;
37755
37756		return this;
37757
37758	}
37759
37760}
37761
37762class MeshPhysicalMaterial extends MeshStandardMaterial {
37763
37764	constructor( parameters ) {
37765
37766		super();
37767
37768		this.isMeshPhysicalMaterial = true;
37769
37770		this.defines = {
37771
37772			'STANDARD': '',
37773			'PHYSICAL': ''
37774
37775		};
37776
37777		this.type = 'MeshPhysicalMaterial';
37778
37779		this.clearcoatMap = null;
37780		this.clearcoatRoughness = 0.0;
37781		this.clearcoatRoughnessMap = null;
37782		this.clearcoatNormalScale = new Vector2( 1, 1 );
37783		this.clearcoatNormalMap = null;
37784
37785		this.ior = 1.5;
37786
37787		Object.defineProperty( this, 'reflectivity', {
37788			get: function () {
37789
37790				return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) );
37791
37792			},
vendor: 8,621 bytes, lines 37793-38211
37793			set: function ( reflectivity ) {
37794
37795				this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity );
37796
37797			}
37798		} );
37799
37800		this.iridescenceMap = null;
37801		this.iridescenceIOR = 1.3;
37802		this.iridescenceThicknessRange = [ 100, 400 ];
37803		this.iridescenceThicknessMap = null;
37804
37805		this.sheenColor = new Color( 0x000000 );
37806		this.sheenColorMap = null;
37807		this.sheenRoughness = 1.0;
37808		this.sheenRoughnessMap = null;
37809
37810		this.transmissionMap = null;
37811
37812		this.thickness = 0;
37813		this.thicknessMap = null;
37814		this.attenuationDistance = Infinity;
37815		this.attenuationColor = new Color( 1, 1, 1 );
37816
37817		this.specularIntensity = 1.0;
37818		this.specularIntensityMap = null;
37819		this.specularColor = new Color( 1, 1, 1 );
37820		this.specularColorMap = null;
37821
37822		this._sheen = 0.0;
37823		this._clearcoat = 0;
37824		this._iridescence = 0;
37825		this._transmission = 0;
37826
37827		this.setValues( parameters );
37828
37829	}
37830
37831	get sheen() {
37832
37833		return this._sheen;
37834
37835	}
37836
37837	set sheen( value ) {
37838
37839		if ( this._sheen > 0 !== value > 0 ) {
37840
37841			this.version ++;
37842
37843		}
37844
37845		this._sheen = value;
37846
37847	}
37848
37849	get clearcoat() {
37850
37851		return this._clearcoat;
37852
37853	}
37854
37855	set clearcoat( value ) {
37856
37857		if ( this._clearcoat > 0 !== value > 0 ) {
37858
37859			this.version ++;
37860
37861		}
37862
37863		this._clearcoat = value;
37864
37865	}
37866
37867	get iridescence() {
37868
37869		return this._iridescence;
37870
37871	}
37872
37873	set iridescence( value ) {
37874
37875		if ( this._iridescence > 0 !== value > 0 ) {
37876
37877			this.version ++;
37878
37879		}
37880
37881		this._iridescence = value;
37882
37883	}
37884
37885	get transmission() {
37886
37887		return this._transmission;
37888
37889	}
37890
37891	set transmission( value ) {
37892
37893		if ( this._transmission > 0 !== value > 0 ) {
37894
37895			this.version ++;
37896
37897		}
37898
37899		this._transmission = value;
37900
37901	}
37902
37903	copy( source ) {
37904
37905		super.copy( source );
37906
37907		this.defines = {
37908
37909			'STANDARD': '',
37910			'PHYSICAL': ''
37911
37912		};
37913
37914		this.clearcoat = source.clearcoat;
37915		this.clearcoatMap = source.clearcoatMap;
37916		this.clearcoatRoughness = source.clearcoatRoughness;
37917		this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
37918		this.clearcoatNormalMap = source.clearcoatNormalMap;
37919		this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
37920
37921		this.ior = source.ior;
37922
37923		this.iridescence = source.iridescence;
37924		this.iridescenceMap = source.iridescenceMap;
37925		this.iridescenceIOR = source.iridescenceIOR;
37926		this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ];
37927		this.iridescenceThicknessMap = source.iridescenceThicknessMap;
37928
37929		this.sheen = source.sheen;
37930		this.sheenColor.copy( source.sheenColor );
37931		this.sheenColorMap = source.sheenColorMap;
37932		this.sheenRoughness = source.sheenRoughness;
37933		this.sheenRoughnessMap = source.sheenRoughnessMap;
37934
37935		this.transmission = source.transmission;
37936		this.transmissionMap = source.transmissionMap;
37937
37938		this.thickness = source.thickness;
37939		this.thicknessMap = source.thicknessMap;
37940		this.attenuationDistance = source.attenuationDistance;
37941		this.attenuationColor.copy( source.attenuationColor );
37942
37943		this.specularIntensity = source.specularIntensity;
37944		this.specularIntensityMap = source.specularIntensityMap;
37945		this.specularColor.copy( source.specularColor );
37946		this.specularColorMap = source.specularColorMap;
37947
37948		return this;
37949
37950	}
37951
37952}
37953
37954class MeshPhongMaterial extends Material {
37955
37956	constructor( parameters ) {
37957
37958		super();
37959
37960		this.isMeshPhongMaterial = true;
37961
37962		this.type = 'MeshPhongMaterial';
37963
37964		this.color = new Color( 0xffffff ); // diffuse
37965		this.specular = new Color( 0x111111 );
37966		this.shininess = 30;
37967
37968		this.map = null;
37969
37970		this.lightMap = null;
37971		this.lightMapIntensity = 1.0;
37972
37973		this.aoMap = null;
37974		this.aoMapIntensity = 1.0;
37975
37976		this.emissive = new Color( 0x000000 );
37977		this.emissiveIntensity = 1.0;
37978		this.emissiveMap = null;
37979
37980		this.bumpMap = null;
37981		this.bumpScale = 1;
37982
37983		this.normalMap = null;
37984		this.normalMapType = TangentSpaceNormalMap;
37985		this.normalScale = new Vector2( 1, 1 );
37986
37987		this.displacementMap = null;
37988		this.displacementScale = 1;
37989		this.displacementBias = 0;
37990
37991		this.specularMap = null;
37992
37993		this.alphaMap = null;
37994
37995		this.envMap = null;
37996		this.combine = MultiplyOperation;
37997		this.reflectivity = 1;
37998		this.refractionRatio = 0.98;
37999
38000		this.wireframe = false;
38001		this.wireframeLinewidth = 1;
38002		this.wireframeLinecap = 'round';
38003		this.wireframeLinejoin = 'round';
38004
38005		this.flatShading = false;
38006
38007		this.fog = true;
38008
38009		this.setValues( parameters );
38010
38011	}
38012
38013	copy( source ) {
38014
38015		super.copy( source );
38016
38017		this.color.copy( source.color );
38018		this.specular.copy( source.specular );
38019		this.shininess = source.shininess;
38020
38021		this.map = source.map;
38022
38023		this.lightMap = source.lightMap;
38024		this.lightMapIntensity = source.lightMapIntensity;
38025
38026		this.aoMap = source.aoMap;
38027		this.aoMapIntensity = source.aoMapIntensity;
38028
38029		this.emissive.copy( source.emissive );
38030		this.emissiveMap = source.emissiveMap;
38031		this.emissiveIntensity = source.emissiveIntensity;
38032
38033		this.bumpMap = source.bumpMap;
38034		this.bumpScale = source.bumpScale;
38035
38036		this.normalMap = source.normalMap;
38037		this.normalMapType = source.normalMapType;
38038		this.normalScale.copy( source.normalScale );
38039
38040		this.displacementMap = source.displacementMap;
38041		this.displacementScale = source.displacementScale;
38042		this.displacementBias = source.displacementBias;
38043
38044		this.specularMap = source.specularMap;
38045
38046		this.alphaMap = source.alphaMap;
38047
38048		this.envMap = source.envMap;
38049		this.combine = source.combine;
38050		this.reflectivity = source.reflectivity;
38051		this.refractionRatio = source.refractionRatio;
38052
38053		this.wireframe = source.wireframe;
38054		this.wireframeLinewidth = source.wireframeLinewidth;
38055		this.wireframeLinecap = source.wireframeLinecap;
38056		this.wireframeLinejoin = source.wireframeLinejoin;
38057
38058		this.flatShading = source.flatShading;
38059
38060		this.fog = source.fog;
38061
38062		return this;
38063
38064	}
38065
38066}
38067
38068class MeshToonMaterial extends Material {
38069
38070	constructor( parameters ) {
38071
38072		super();
38073
38074		this.isMeshToonMaterial = true;
38075
38076		this.defines = { 'TOON': '' };
38077
38078		this.type = 'MeshToonMaterial';
38079
38080		this.color = new Color( 0xffffff );
38081
38082		this.map = null;
38083		this.gradientMap = null;
38084
38085		this.lightMap = null;
38086		this.lightMapIntensity = 1.0;
38087
38088		this.aoMap = null;
38089		this.aoMapIntensity = 1.0;
38090
38091		this.emissive = new Color( 0x000000 );
38092		this.emissiveIntensity = 1.0;
38093		this.emissiveMap = null;
38094
38095		this.bumpMap = null;
38096		this.bumpScale = 1;
38097
38098		this.normalMap = null;
38099		this.normalMapType = TangentSpaceNormalMap;
38100		this.normalScale = new Vector2( 1, 1 );
38101
38102		this.displacementMap = null;
38103		this.displacementScale = 1;
38104		this.displacementBias = 0;
38105
38106		this.alphaMap = null;
38107
38108		this.wireframe = false;
38109		this.wireframeLinewidth = 1;
38110		this.wireframeLinecap = 'round';
38111		this.wireframeLinejoin = 'round';
38112
38113		this.fog = true;
38114
38115		this.setValues( parameters );
38116
38117	}
38118
38119	copy( source ) {
38120
38121		super.copy( source );
38122
38123		this.color.copy( source.color );
38124
38125		this.map = source.map;
38126		this.gradientMap = source.gradientMap;
38127
38128		this.lightMap = source.lightMap;
38129		this.lightMapIntensity = source.lightMapIntensity;
38130
38131		this.aoMap = source.aoMap;
38132		this.aoMapIntensity = source.aoMapIntensity;
38133
38134		this.emissive.copy( source.emissive );
38135		this.emissiveMap = source.emissiveMap;
38136		this.emissiveIntensity = source.emissiveIntensity;
38137
38138		this.bumpMap = source.bumpMap;
38139		this.bumpScale = source.bumpScale;
38140
38141		this.normalMap = source.normalMap;
38142		this.normalMapType = source.normalMapType;
38143		this.normalScale.copy( source.normalScale );
38144
38145		this.displacementMap = source.displacementMap;
38146		this.displacementScale = source.displacementScale;
38147		this.displacementBias = source.displacementBias;
38148
38149		this.alphaMap = source.alphaMap;
38150
38151		this.wireframe = source.wireframe;
38152		this.wireframeLinewidth = source.wireframeLinewidth;
38153		this.wireframeLinecap = source.wireframeLinecap;
38154		this.wireframeLinejoin = source.wireframeLinejoin;
38155
38156		this.fog = source.fog;
38157
38158		return this;
38159
38160	}
38161
38162}
38163
38164class MeshNormalMaterial extends Material {
38165
38166	constructor( parameters ) {
38167
38168		super();
38169
38170		this.isMeshNormalMaterial = true;
38171
38172		this.type = 'MeshNormalMaterial';
38173
38174		this.bumpMap = null;
38175		this.bumpScale = 1;
38176
38177		this.normalMap = null;
38178		this.normalMapType = TangentSpaceNormalMap;
38179		this.normalScale = new Vector2( 1, 1 );
38180
38181		this.displacementMap = null;
38182		this.displacementScale = 1;
38183		this.displacementBias = 0;
38184
38185		this.wireframe = false;
38186		this.wireframeLinewidth = 1;
38187
38188		this.flatShading = false;
38189
38190		this.setValues( parameters );
38191
38192	}
38193
38194	copy( source ) {
38195
38196		super.copy( source );
38197
38198		this.bumpMap = source.bumpMap;
38199		this.bumpScale = source.bumpScale;
38200
38201		this.normalMap = source.normalMap;
38202		this.normalMapType = source.normalMapType;
38203		this.normalScale.copy( source.normalScale );
38204
38205		this.displacementMap = source.displacementMap;
38206		this.displacementScale = source.displacementScale;
38207		this.displacementBias = source.displacementBias;
38208
38209		this.wireframe = source.wireframe;
38210		this.wireframeLinewidth = source.wireframeLinewidth;
38211
38212		this.flatShading = source.flatShading;
38213
38214		return this;
38215
38216	}
38217
38218}
38219
38220class MeshLambertMaterial extends Material {
38221
38222	constructor( parameters ) {
38223
38224		super();
38225
38226		this.isMeshLambertMaterial = true;
38227
38228		this.type = 'MeshLambertMaterial';
38229
38230		this.color = new Color( 0xffffff ); // diffuse
38231
38232		this.map = null;
38233
38234		this.lightMap = null;
38235		this.lightMapIntensity = 1.0;
38236
38237		this.aoMap = null;
38238		this.aoMapIntensity = 1.0;
38239
38240		this.emissive = new Color( 0x000000 );
38241		this.emissiveIntensity = 1.0;
38242		this.emissiveMap = null;
38243
38244		this.bumpMap = null;
38245		this.bumpScale = 1;
38246
38247		this.normalMap = null;
38248		this.normalMapType = TangentSpaceNormalMap;
38249		this.normalScale = new Vector2( 1, 1 );
38250
38251		this.displacementMap = null;
38252		this.displacementScale = 1;
38253		this.displacementBias = 0;
38254
38255		this.specularMap = null;
38256
38257		this.alphaMap = null;
38258
38259		this.envMap = null;
38260		this.combine = MultiplyOperation;
38261		this.reflectivity = 1;
38262		this.refractionRatio = 0.98;
38263
38264		this.wireframe = false;
38265		this.wireframeLinewidth = 1;
38266		this.wireframeLinecap = 'round';
38267		this.wireframeLinejoin = 'round';
38268
38269		this.flatShading = false;
38270
38271		this.fog = true;
38272
38273		this.setValues( parameters );
38274
38275	}
38276
38277	copy( source ) {
38278
38279		super.copy( source );
38280
38281		this.color.copy( source.color );
38282
38283		this.map = source.map;
38284
38285		this.lightMap = source.lightMap;
38286		this.lightMapIntensity = source.lightMapIntensity;
38287
38288		this.aoMap = source.aoMap;
38289		this.aoMapIntensity = source.aoMapIntensity;
38290
38291		this.emissive.copy( source.emissive );
38292		this.emissiveMap = source.emissiveMap;
38293		this.emissiveIntensity = source.emissiveIntensity;
38294
38295		this.bumpMap = source.bumpMap;
38296		this.bumpScale = source.bumpScale;
38297
38298		this.normalMap = source.normalMap;
38299		this.normalMapType = source.normalMapType;
38300		this.normalScale.copy( source.normalScale );
38301
38302		this.displacementMap = source.displacementMap;
38303		this.displacementScale = source.displacementScale;
38304		this.displacementBias = source.displacementBias;
38305
38306		this.specularMap = source.specularMap;
38307
38308		this.alphaMap = source.alphaMap;
38309
38310		this.envMap = source.envMap;
38311		this.combine = source.combine;
38312		this.reflectivity = source.reflectivity;
38313		this.refractionRatio = source.refractionRatio;
38314
38315		this.wireframe = source.wireframe;
38316		this.wireframeLinewidth = source.wireframeLinewidth;
38317		this.wireframeLinecap = source.wireframeLinecap;
38318		this.wireframeLinejoin = source.wireframeLinejoin;
38319
38320		this.flatShading = source.flatShading;
38321
38322		this.fog = source.fog;
38323
38324		return this;
38325
38326	}
38327
38328}
38329
38330class MeshMatcapMaterial extends Material {
38331
38332	constructor( parameters ) {
38333
38334		super();
38335
38336		this.isMeshMatcapMaterial = true;
38337
38338		this.defines = { 'MATCAP': '' };
38339
38340		this.type = 'MeshMatcapMaterial';
38341
38342		this.color = new Color( 0xffffff ); // diffuse
38343
38344		this.matcap = null;
38345
38346		this.map = null;
38347
38348		this.bumpMap = null;
38349		this.bumpScale = 1;
38350
38351		this.normalMap = null;
38352		this.normalMapType = TangentSpaceNormalMap;
38353		this.normalScale = new Vector2( 1, 1 );
38354
38355		this.displacementMap = null;
38356		this.displacementScale = 1;
38357		this.displacementBias = 0;
38358
38359		this.alphaMap = null;
38360
38361		this.flatShading = false;
38362
38363		this.fog = true;
38364
38365		this.setValues( parameters );
38366
38367	}
38368
38369
38370	copy( source ) {
38371
38372		super.copy( source );
38373
38374		this.defines = { 'MATCAP': '' };
38375
38376		this.color.copy( source.color );
38377
38378		this.matcap = source.matcap;
38379
38380		this.map = source.map;
38381
38382		this.bumpMap = source.bumpMap;
38383		this.bumpScale = source.bumpScale;
38384
38385		this.normalMap = source.normalMap;
38386		this.normalMapType = source.normalMapType;
38387		this.normalScale.copy( source.normalScale );
38388
38389		this.displacementMap = source.displacementMap;
38390		this.displacementScale = source.displacementScale;
38391		this.displacementBias = source.displacementBias;
38392
38393		this.alphaMap = source.alphaMap;
38394
38395		this.flatShading = source.flatShading;
38396
38397		this.fog = source.fog;
38398
38399		return this;
38400
38401	}
38402
38403}
38404
38405class LineDashedMaterial extends LineBasicMaterial {
38406
38407	constructor( parameters ) {
38408
38409		super();
38410
38411		this.isLineDashedMaterial = true;
38412
38413		this.type = 'LineDashedMaterial';
38414
38415		this.scale = 1;
38416		this.dashSize = 3;
38417		this.gapSize = 1;
38418
38419		this.setValues( parameters );
38420
38421	}
38422
38423	copy( source ) {
38424
38425		super.copy( source );
38426
38427		this.scale = source.scale;
38428		this.dashSize = source.dashSize;
38429		this.gapSize = source.gapSize;
38430
38431		return this;
38432
38433	}
38434
38435}
38436
38437// same as Array.prototype.slice, but also works on typed arrays
38438function arraySlice( array, from, to ) {
38439
38440	if ( isTypedArray( array ) ) {
38441
38442		// in ios9 array.subarray(from, undefined) will return empty array
38443		// but array.subarray(from) or array.subarray(from, len) is correct
38444		return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );
38445
38446	}
38447
38448	return array.slice( from, to );
38449
38450}
38451
38452// converts an array to a specific type
38453function convertArray( array, type, forceClone ) {
38454
38455	if ( ! array || // let 'undefined' and 'null' pass
vendor: 15,766 bytes, lines 38456-39243
38456		! forceClone && array.constructor === type ) return array;
38457
38458	if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
38459
38460		return new type( array ); // create typed array
38461
38462	}
38463
38464	return Array.prototype.slice.call( array ); // create Array
38465
38466}
38467
38468function isTypedArray( object ) {
38469
38470	return ArrayBuffer.isView( object ) &&
38471		! ( object instanceof DataView );
38472
38473}
38474
38475// returns an array by which times and values can be sorted
38476function getKeyframeOrder( times ) {
38477
38478	function compareTime( i, j ) {
38479
38480		return times[ i ] - times[ j ];
38481
38482	}
38483
38484	const n = times.length;
38485	const result = new Array( n );
38486	for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
38487
38488	result.sort( compareTime );
38489
38490	return result;
38491
38492}
38493
38494// uses the array previously returned by 'getKeyframeOrder' to sort data
38495function sortedArray( values, stride, order ) {
38496
38497	const nValues = values.length;
38498	const result = new values.constructor( nValues );
38499
38500	for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
38501
38502		const srcOffset = order[ i ] * stride;
38503
38504		for ( let j = 0; j !== stride; ++ j ) {
38505
38506			result[ dstOffset ++ ] = values[ srcOffset + j ];
38507
38508		}
38509
38510	}
38511
38512	return result;
38513
38514}
38515
38516// function for parsing AOS keyframe formats
38517function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
38518
38519	let i = 1, key = jsonKeys[ 0 ];
38520
38521	while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
38522
38523		key = jsonKeys[ i ++ ];
38524
38525	}
38526
38527	if ( key === undefined ) return; // no data
38528
38529	let value = key[ valuePropertyName ];
38530	if ( value === undefined ) return; // no data
38531
38532	if ( Array.isArray( value ) ) {
38533
38534		do {
38535
38536			value = key[ valuePropertyName ];
38537
38538			if ( value !== undefined ) {
38539
38540				times.push( key.time );
38541				values.push.apply( values, value ); // push all elements
38542
38543			}
38544
38545			key = jsonKeys[ i ++ ];
38546
38547		} while ( key !== undefined );
38548
38549	} else if ( value.toArray !== undefined ) {
38550
38551		// ...assume THREE.Math-ish
38552
38553		do {
38554
38555			value = key[ valuePropertyName ];
38556
38557			if ( value !== undefined ) {
38558
38559				times.push( key.time );
38560				value.toArray( values, values.length );
38561
38562			}
38563
38564			key = jsonKeys[ i ++ ];
38565
38566		} while ( key !== undefined );
38567
38568	} else {
38569
38570		// otherwise push as-is
38571
38572		do {
38573
38574			value = key[ valuePropertyName ];
38575
38576			if ( value !== undefined ) {
38577
38578				times.push( key.time );
38579				values.push( value );
38580
38581			}
38582
38583			key = jsonKeys[ i ++ ];
38584
38585		} while ( key !== undefined );
38586
38587	}
38588
38589}
38590
38591function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
38592
38593	const clip = sourceClip.clone();
38594
38595	clip.name = name;
38596
38597	const tracks = [];
38598
38599	for ( let i = 0; i < clip.tracks.length; ++ i ) {
38600
38601		const track = clip.tracks[ i ];
38602		const valueSize = track.getValueSize();
38603
38604		const times = [];
38605		const values = [];
38606
38607		for ( let j = 0; j < track.times.length; ++ j ) {
38608
38609			const frame = track.times[ j ] * fps;
38610
38611			if ( frame < startFrame || frame >= endFrame ) continue;
38612
38613			times.push( track.times[ j ] );
38614
38615			for ( let k = 0; k < valueSize; ++ k ) {
38616
38617				values.push( track.values[ j * valueSize + k ] );
38618
38619			}
38620
38621		}
38622
38623		if ( times.length === 0 ) continue;
38624
38625		track.times = convertArray( times, track.times.constructor );
38626		track.values = convertArray( values, track.values.constructor );
38627
38628		tracks.push( track );
38629
38630	}
38631
38632	clip.tracks = tracks;
38633
38634	// find minimum .times value across all tracks in the trimmed clip
38635
38636	let minStartTime = Infinity;
38637
38638	for ( let i = 0; i < clip.tracks.length; ++ i ) {
38639
38640		if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
38641
38642			minStartTime = clip.tracks[ i ].times[ 0 ];
38643
38644		}
38645
38646	}
38647
38648	// shift all tracks such that clip begins at t=0
38649
38650	for ( let i = 0; i < clip.tracks.length; ++ i ) {
38651
38652		clip.tracks[ i ].shift( - 1 * minStartTime );
38653
38654	}
38655
38656	clip.resetDuration();
38657
38658	return clip;
38659
38660}
38661
38662function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
38663
38664	if ( fps <= 0 ) fps = 30;
38665
38666	const numTracks = referenceClip.tracks.length;
38667	const referenceTime = referenceFrame / fps;
38668
38669	// Make each track's values relative to the values at the reference frame
38670	for ( let i = 0; i < numTracks; ++ i ) {
38671
38672		const referenceTrack = referenceClip.tracks[ i ];
38673		const referenceTrackType = referenceTrack.ValueTypeName;
38674
38675		// Skip this track if it's non-numeric
38676		if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
38677
38678		// Find the track in the target clip whose name and type matches the reference track
38679		const targetTrack = targetClip.tracks.find( function ( track ) {
38680
38681			return track.name === referenceTrack.name
38682				&& track.ValueTypeName === referenceTrackType;
38683
38684		} );
38685
38686		if ( targetTrack === undefined ) continue;
38687
38688		let referenceOffset = 0;
38689		const referenceValueSize = referenceTrack.getValueSize();
38690
38691		if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
38692
38693			referenceOffset = referenceValueSize / 3;
38694
38695		}
38696
38697		let targetOffset = 0;
38698		const targetValueSize = targetTrack.getValueSize();
38699
38700		if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
38701
38702			targetOffset = targetValueSize / 3;
38703
38704		}
38705
38706		const lastIndex = referenceTrack.times.length - 1;
38707		let referenceValue;
38708
38709		// Find the value to subtract out of the track
38710		if ( referenceTime <= referenceTrack.times[ 0 ] ) {
38711
38712			// Reference frame is earlier than the first keyframe, so just use the first keyframe
38713			const startIndex = referenceOffset;
38714			const endIndex = referenceValueSize - referenceOffset;
38715			referenceValue = arraySlice( referenceTrack.values, startIndex, endIndex );
38716
38717		} else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
38718
38719			// Reference frame is after the last keyframe, so just use the last keyframe
38720			const startIndex = lastIndex * referenceValueSize + referenceOffset;
38721			const endIndex = startIndex + referenceValueSize - referenceOffset;
38722			referenceValue = arraySlice( referenceTrack.values, startIndex, endIndex );
38723
38724		} else {
38725
38726			// Interpolate to the reference value
38727			const interpolant = referenceTrack.createInterpolant();
38728			const startIndex = referenceOffset;
38729			const endIndex = referenceValueSize - referenceOffset;
38730			interpolant.evaluate( referenceTime );
38731			referenceValue = arraySlice( interpolant.resultBuffer, startIndex, endIndex );
38732
38733		}
38734
38735		// Conjugate the quaternion
38736		if ( referenceTrackType === 'quaternion' ) {
38737
38738			const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
38739			referenceQuat.toArray( referenceValue );
38740
38741		}
38742
38743		// Subtract the reference value from all of the track values
38744
38745		const numTimes = targetTrack.times.length;
38746		for ( let j = 0; j < numTimes; ++ j ) {
38747
38748			const valueStart = j * targetValueSize + targetOffset;
38749
38750			if ( referenceTrackType === 'quaternion' ) {
38751
38752				// Multiply the conjugate for quaternion track types
38753				Quaternion.multiplyQuaternionsFlat(
38754					targetTrack.values,
38755					valueStart,
38756					referenceValue,
38757					0,
38758					targetTrack.values,
38759					valueStart
38760				);
38761
38762			} else {
38763
38764				const valueEnd = targetValueSize - targetOffset * 2;
38765
38766				// Subtract each value for all other numeric track types
38767				for ( let k = 0; k < valueEnd; ++ k ) {
38768
38769					targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
38770
38771				}
38772
38773			}
38774
38775		}
38776
38777	}
38778
38779	targetClip.blendMode = AdditiveAnimationBlendMode;
38780
38781	return targetClip;
38782
38783}
38784
38785const AnimationUtils = {
38786	arraySlice: arraySlice,
38787	convertArray: convertArray,
38788	isTypedArray: isTypedArray,
38789	getKeyframeOrder: getKeyframeOrder,
38790	sortedArray: sortedArray,
38791	flattenJSON: flattenJSON,
38792	subclip: subclip,
38793	makeClipAdditive: makeClipAdditive
38794};
38795
38796/**
38797 * Abstract base class of interpolants over parametric samples.
38798 *
38799 * The parameter domain is one dimensional, typically the time or a path
38800 * along a curve defined by the data.
38801 *
38802 * The sample values can have any dimensionality and derived classes may
38803 * apply special interpretations to the data.
38804 *
38805 * This class provides the interval seek in a Template Method, deferring
38806 * the actual interpolation to derived classes.
38807 *
38808 * Time complexity is O(1) for linear access crossing at most two points
38809 * and O(log N) for random access, where N is the number of positions.
38810 *
38811 * References:
38812 *
38813 * 		http://www.oodesign.com/template-method-pattern.html
38814 *
38815 */
38816
38817class Interpolant {
38818
38819	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
38820
38821		this.parameterPositions = parameterPositions;
38822		this._cachedIndex = 0;
38823
38824		this.resultBuffer = resultBuffer !== undefined ?
38825			resultBuffer : new sampleValues.constructor( sampleSize );
38826		this.sampleValues = sampleValues;
38827		this.valueSize = sampleSize;
38828
38829		this.settings = null;
38830		this.DefaultSettings_ = {};
38831
38832	}
38833
38834	evaluate( t ) {
38835
38836		const pp = this.parameterPositions;
38837		let i1 = this._cachedIndex,
38838			t1 = pp[ i1 ],
38839			t0 = pp[ i1 - 1 ];
38840
38841		validate_interval: {
38842
38843			seek: {
38844
38845				let right;
38846
38847				linear_scan: {
38848
38849					//- See http://jsperf.com/comparison-to-undefined/3
38850					//- slower code:
38851					//-
38852					//- 				if ( t >= t1 || t1 === undefined ) {
38853					forward_scan: if ( ! ( t < t1 ) ) {
38854
38855						for ( let giveUpAt = i1 + 2; ; ) {
38856
38857							if ( t1 === undefined ) {
38858
38859								if ( t < t0 ) break forward_scan;
38860
38861								// after end
38862
38863								i1 = pp.length;
38864								this._cachedIndex = i1;
38865								return this.copySampleValue_( i1 - 1 );
38866
38867							}
38868
38869							if ( i1 === giveUpAt ) break; // this loop
38870
38871							t0 = t1;
38872							t1 = pp[ ++ i1 ];
38873
38874							if ( t < t1 ) {
38875
38876								// we have arrived at the sought interval
38877								break seek;
38878
38879							}
38880
38881						}
38882
38883						// prepare binary search on the right side of the index
38884						right = pp.length;
38885						break linear_scan;
38886
38887					}
38888
38889					//- slower code:
38890					//-					if ( t < t0 || t0 === undefined ) {
38891					if ( ! ( t >= t0 ) ) {
38892
38893						// looping?
38894
38895						const t1global = pp[ 1 ];
38896
38897						if ( t < t1global ) {
38898
38899							i1 = 2; // + 1, using the scan for the details
38900							t0 = t1global;
38901
38902						}
38903
38904						// linear reverse scan
38905
38906						for ( let giveUpAt = i1 - 2; ; ) {
38907
38908							if ( t0 === undefined ) {
38909
38910								// before start
38911
38912								this._cachedIndex = 0;
38913								return this.copySampleValue_( 0 );
38914
38915							}
38916
38917							if ( i1 === giveUpAt ) break; // this loop
38918
38919							t1 = t0;
38920							t0 = pp[ -- i1 - 1 ];
38921
38922							if ( t >= t0 ) {
38923
38924								// we have arrived at the sought interval
38925								break seek;
38926
38927							}
38928
38929						}
38930
38931						// prepare binary search on the left side of the index
38932						right = i1;
38933						i1 = 0;
38934						break linear_scan;
38935
38936					}
38937
38938					// the interval is valid
38939
38940					break validate_interval;
38941
38942				} // linear scan
38943
38944				// binary search
38945
38946				while ( i1 < right ) {
38947
38948					const mid = ( i1 + right ) >>> 1;
38949
38950					if ( t < pp[ mid ] ) {
38951
38952						right = mid;
38953
38954					} else {
38955
38956						i1 = mid + 1;
38957
38958					}
38959
38960				}
38961
38962				t1 = pp[ i1 ];
38963				t0 = pp[ i1 - 1 ];
38964
38965				// check boundary cases, again
38966
38967				if ( t0 === undefined ) {
38968
38969					this._cachedIndex = 0;
38970					return this.copySampleValue_( 0 );
38971
38972				}
38973
38974				if ( t1 === undefined ) {
38975
38976					i1 = pp.length;
38977					this._cachedIndex = i1;
38978					return this.copySampleValue_( i1 - 1 );
38979
38980				}
38981
38982			} // seek
38983
38984			this._cachedIndex = i1;
38985
38986			this.intervalChanged_( i1, t0, t1 );
38987
38988		} // validate_interval
38989
38990		return this.interpolate_( i1, t0, t, t1 );
38991
38992	}
38993
38994	getSettings_() {
38995
38996		return this.settings || this.DefaultSettings_;
38997
38998	}
38999
39000	copySampleValue_( index ) {
39001
39002		// copies a sample value to the result buffer
39003
39004		const result = this.resultBuffer,
39005			values = this.sampleValues,
39006			stride = this.valueSize,
39007			offset = index * stride;
39008
39009		for ( let i = 0; i !== stride; ++ i ) {
39010
39011			result[ i ] = values[ offset + i ];
39012
39013		}
39014
39015		return result;
39016
39017	}
39018
39019	// Template methods for derived classes:
39020
39021	interpolate_( /* i1, t0, t, t1 */ ) {
39022
39023		throw new Error( 'call to abstract method' );
39024		// implementations shall return this.resultBuffer
39025
39026	}
39027
39028	intervalChanged_( /* i1, t0, t1 */ ) {
39029
39030		// empty
39031
39032	}
39033
39034}
39035
39036/**
39037 * Fast and simple cubic spline interpolant.
39038 *
39039 * It was derived from a Hermitian construction setting the first derivative
39040 * at each sample position to the linear slope between neighboring positions
39041 * over their parameter interval.
39042 */
39043
39044class CubicInterpolant extends Interpolant {
39045
39046	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
39047
39048		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
39049
39050		this._weightPrev = - 0;
39051		this._offsetPrev = - 0;
39052		this._weightNext = - 0;
39053		this._offsetNext = - 0;
39054
39055		this.DefaultSettings_ = {
39056
39057			endingStart: ZeroCurvatureEnding,
39058			endingEnd: ZeroCurvatureEnding
39059
39060		};
39061
39062	}
39063
39064	intervalChanged_( i1, t0, t1 ) {
39065
39066		const pp = this.parameterPositions;
39067		let iPrev = i1 - 2,
39068			iNext = i1 + 1,
39069
39070			tPrev = pp[ iPrev ],
39071			tNext = pp[ iNext ];
39072
39073		if ( tPrev === undefined ) {
39074
39075			switch ( this.getSettings_().endingStart ) {
39076
39077				case ZeroSlopeEnding:
39078
39079					// f'(t0) = 0
39080					iPrev = i1;
39081					tPrev = 2 * t0 - t1;
39082
39083					break;
39084
39085				case WrapAroundEnding:
39086
39087					// use the other end of the curve
39088					iPrev = pp.length - 2;
39089					tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
39090
39091					break;
39092
39093				default: // ZeroCurvatureEnding
39094
39095					// f''(t0) = 0 a.k.a. Natural Spline
39096					iPrev = i1;
39097					tPrev = t1;
39098
39099			}
39100
39101		}
39102
39103		if ( tNext === undefined ) {
39104
39105			switch ( this.getSettings_().endingEnd ) {
39106
39107				case ZeroSlopeEnding:
39108
39109					// f'(tN) = 0
39110					iNext = i1;
39111					tNext = 2 * t1 - t0;
39112
39113					break;
39114
39115				case WrapAroundEnding:
39116
39117					// use the other end of the curve
39118					iNext = 1;
39119					tNext = t1 + pp[ 1 ] - pp[ 0 ];
39120
39121					break;
39122
39123				default: // ZeroCurvatureEnding
39124
39125					// f''(tN) = 0, a.k.a. Natural Spline
39126					iNext = i1 - 1;
39127					tNext = t0;
39128
39129			}
39130
39131		}
39132
39133		const halfDt = ( t1 - t0 ) * 0.5,
39134			stride = this.valueSize;
39135
39136		this._weightPrev = halfDt / ( t0 - tPrev );
39137		this._weightNext = halfDt / ( tNext - t1 );
39138		this._offsetPrev = iPrev * stride;
39139		this._offsetNext = iNext * stride;
39140
39141	}
39142
39143	interpolate_( i1, t0, t, t1 ) {
39144
39145		const result = this.resultBuffer,
39146			values = this.sampleValues,
39147			stride = this.valueSize,
39148
39149			o1 = i1 * stride,		o0 = o1 - stride,
39150			oP = this._offsetPrev, 	oN = this._offsetNext,
39151			wP = this._weightPrev,	wN = this._weightNext,
39152
39153			p = ( t - t0 ) / ( t1 - t0 ),
39154			pp = p * p,
39155			ppp = pp * p;
39156
39157		// evaluate polynomials
39158
39159		const sP = - wP * ppp + 2 * wP * pp - wP * p;
39160		const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
39161		const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
39162		const sN = wN * ppp - wN * pp;
39163
39164		// combine data linearly
39165
39166		for ( let i = 0; i !== stride; ++ i ) {
39167
39168			result[ i ] =
39169					sP * values[ oP + i ] +
39170					s0 * values[ o0 + i ] +
39171					s1 * values[ o1 + i ] +
39172					sN * values[ oN + i ];
39173
39174		}
39175
39176		return result;
39177
39178	}
39179
39180}
39181
39182class LinearInterpolant extends Interpolant {
39183
39184	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
39185
39186		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
39187
39188	}
39189
39190	interpolate_( i1, t0, t, t1 ) {
39191
39192		const result = this.resultBuffer,
39193			values = this.sampleValues,
39194			stride = this.valueSize,
39195
39196			offset1 = i1 * stride,
39197			offset0 = offset1 - stride,
39198
39199			weight1 = ( t - t0 ) / ( t1 - t0 ),
39200			weight0 = 1 - weight1;
39201
39202		for ( let i = 0; i !== stride; ++ i ) {
39203
39204			result[ i ] =
39205					values[ offset0 + i ] * weight0 +
39206					values[ offset1 + i ] * weight1;
39207
39208		}
39209
39210		return result;
39211
39212	}
39213
39214}
39215
39216/**
39217 *
39218 * Interpolant that evaluates to the sample value at the position preceding
39219 * the parameter.
39220 */
39221
39222class DiscreteInterpolant extends Interpolant {
39223
39224	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
39225
39226		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
39227
39228	}
39229
39230	interpolate_( i1 /*, t0, t, t1 */ ) {
39231
39232		return this.copySampleValue_( i1 - 1 );
39233
39234	}
39235
39236}
39237
39238class KeyframeTrack {
39239
39240	constructor( name, times, values, interpolation ) {
39241
39242		if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
39243		if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 4,615 bytes, lines 39243-39487
39243ame );
39244
39245		this.name = name;
39246
39247		this.times = convertArray( times, this.TimeBufferType );
39248		this.values = convertArray( values, this.ValueBufferType );
39249
39250		this.setInterpolation( interpolation || this.DefaultInterpolation );
39251
39252	}
39253
39254	// Serialization (in static context, because of constructor invocation
39255	// and automatic invocation of .toJSON):
39256
39257	static toJSON( track ) {
39258
39259		const trackType = track.constructor;
39260
39261		let json;
39262
39263		// derived classes can define a static toJSON method
39264		if ( trackType.toJSON !== this.toJSON ) {
39265
39266			json = trackType.toJSON( track );
39267
39268		} else {
39269
39270			// by default, we assume the data can be serialized as-is
39271			json = {
39272
39273				'name': track.name,
39274				'times': convertArray( track.times, Array ),
39275				'values': convertArray( track.values, Array )
39276
39277			};
39278
39279			const interpolation = track.getInterpolation();
39280
39281			if ( interpolation !== track.DefaultInterpolation ) {
39282
39283				json.interpolation = interpolation;
39284
39285			}
39286
39287		}
39288
39289		json.type = track.ValueTypeName; // mandatory
39290
39291		return json;
39292
39293	}
39294
39295	InterpolantFactoryMethodDiscrete( result ) {
39296
39297		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
39298
39299	}
39300
39301	InterpolantFactoryMethodLinear( result ) {
39302
39303		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
39304
39305	}
39306
39307	InterpolantFactoryMethodSmooth( result ) {
39308
39309		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
39310
39311	}
39312
39313	setInterpolation( interpolation ) {
39314
39315		let factoryMethod;
39316
39317		switch ( interpolation ) {
39318
39319			case InterpolateDiscrete:
39320
39321				factoryMethod = this.InterpolantFactoryMethodDiscrete;
39322
39323				break;
39324
39325			case InterpolateLinear:
39326
39327				factoryMethod = this.InterpolantFactoryMethodLinear;
39328
39329				break;
39330
39331			case InterpolateSmooth:
39332
39333				factoryMethod = this.InterpolantFactoryMethodSmooth;
39334
39335				break;
39336
39337		}
39338
39339		if ( factoryMethod === undefined ) {
39340
39341			const message = 'unsupported interpolation for ' +
39342				this.ValueTypeName + ' keyframe track named ' + this.name;
39343
39344			if ( this.createInterpolant === undefined ) {
39345
39346				// fall back to default, unless the default itself is messed up
39347				if ( interpolation !== this.DefaultInterpolation ) {
39348
39349					this.setInterpolation( this.DefaultInterpolation );
39350
39351				} else {
39352
39353					throw new Error( message ); // fatal, in this case
39354
39355				}
39356
39357			}
39358
39359			console.warn( 'THREE.KeyframeTrack:', message );
39360			return this;
39361
39362		}
39363
39364		this.createInterpolant = factoryMethod;
39365
39366		return this;
39367
39368	}
39369
39370	getInterpolation() {
39371
39372		switch ( this.createInterpolant ) {
39373
39374			case this.InterpolantFactoryMethodDiscrete:
39375
39376				return InterpolateDiscrete;
39377
39378			case this.InterpolantFactoryMethodLinear:
39379
39380				return InterpolateLinear;
39381
39382			case this.InterpolantFactoryMethodSmooth:
39383
39384				return InterpolateSmooth;
39385
39386		}
39387
39388	}
39389
39390	getValueSize() {
39391
39392		return this.values.length / this.times.length;
39393
39394	}
39395
39396	// move all keyframes either forwards or backwards in time
39397	shift( timeOffset ) {
39398
39399		if ( timeOffset !== 0.0 ) {
39400
39401			const times = this.times;
39402
39403			for ( let i = 0, n = times.length; i !== n; ++ i ) {
39404
39405				times[ i ] += timeOffset;
39406
39407			}
39408
39409		}
39410
39411		return this;
39412
39413	}
39414
39415	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
39416	scale( timeScale ) {
39417
39418		if ( timeScale !== 1.0 ) {
39419
39420			const times = this.times;
39421
39422			for ( let i = 0, n = times.length; i !== n; ++ i ) {
39423
39424				times[ i ] *= timeScale;
39425
39426			}
39427
39428		}
39429
39430		return this;
39431
39432	}
39433
39434	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
39435	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
39436	trim( startTime, endTime ) {
39437
39438		const times = this.times,
39439			nKeys = times.length;
39440
39441		let from = 0,
39442			to = nKeys - 1;
39443
39444		while ( from !== nKeys && times[ from ] < startTime ) {
39445
39446			++ from;
39447
39448		}
39449
39450		while ( to !== - 1 && times[ to ] > endTime ) {
39451
39452			-- to;
39453
39454		}
39455
39456		++ to; // inclusive -> exclusive bound
39457
39458		if ( from !== 0 || to !== nKeys ) {
39459
39460			// empty tracks are forbidden, so keep at least one keyframe
39461			if ( from >= to ) {
39462
39463				to = Math.max( to, 1 );
39464				from = to - 1;
39465
39466			}
39467
39468			const stride = this.getValueSize();
39469			this.times = arraySlice( times, from, to );
39470			this.values = arraySlice( this.values, from * stride, to * stride );
39471
39472		}
39473
39474		return this;
39475
39476	}
39477
39478	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
39479	validate() {
39480
39481		let valid = true;
39482
39483		const valueSize = this.getValueSize();
39484		if ( valueSize - Math.floor( valueSize ) !== 0 ) {
39485
39486			console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
39487			valid = false;
39488
39489		}
39490
39491		const times = this.times,
39492			values = this.values,
39493
39494			nKeys = times.length;
39495
39496		if ( nKeys === 0 ) {
39497
39498			console.error( 'THREE.KeyframeTrack: Track is empty.', this );
39499			valid = false;
39500
39501		}
39502
39503		let prevTime = null;
39504
39505		for ( let i = 0; i !== nKeys; i ++ ) {
39506
39507			const currTime = times[ i ];
39508
39509			if ( typeof currTime === 'number' && isNaN( currTime ) ) {
39510
39511				console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
39512				valid = false;
39513				break;
39514
39515			}
39516
39517			if ( prevTime !== null && prevTime > currTime ) {
39518
39519				console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
39520				valid = false;
39521				break;
39522
39523			}
39524
39525			prevTime = currTime;
39526
39527		}
39528
39529		if ( values !== undefined ) {
39530
39531			if ( isTypedArray( values ) ) {
39532
39533				for ( let i = 0, n = values.length; i !== n; ++ i ) {
39534
39535					const value = values[ i ];
39536
39537					if ( isNaN( value ) ) {
39538
39539						console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
39540						valid = false;
39541						break;
39542
39543					}
39544
39545				}
39546
39547			}
39548
39549		}
39550
39551		return valid;
39552
39553	}
39554
39555	// removes equivalent sequential keys as common in morph target sequences
39556	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
39557	optimize() {
39558
39559		// times or values may be shared with other tracks, so overwriting is unsafe
39560		const times = arraySlice( this.times ),
39561			values = arraySlice( this.values ),
39562			stride = this.getValueSize(),
39563
39564			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
39565
39566			lastIndex = times.length - 1;
39567
39568		let writeIndex = 1;
39569
39570		for ( let i = 1; i < lastIndex; ++ i ) {
39571
39572			let keep = false;
39573
39574			const time = times[ i ];
39575			const timeNext = times[ i + 1 ];
39576
39577			// remove adjacent keyframes scheduled at the same time
39578
39579			if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
39580
39581				if ( ! smoothInterpolation ) {
39582
39583					// remove unnecessary keyframes same as their neighbors
39584
39585					const offset = i * stride,
39586						offsetP = offset - stride,
39587						offsetN = offset + stride;
39588
39589					for ( let j = 0; j !== stride; ++ j ) {
39590
39591						const value = values[ offset + j ];
39592
39593						if ( value !== values[ offsetP + j ] ||
39594							value !== values[ offsetN + j ] ) {
39595
39596							keep = true;
39597							break;
39598
39599						}
39600
39601					}
39602
39603				} else {
39604
39605					keep = true;
39606
39607				}
39608
39609			}
39610
39611			// in-place compaction
39612
39613			if ( keep ) {
39614
39615				if ( i !== writeIndex ) {
39616
39617					times[ writeIndex ] = times[ i ];
39618
39619					const readOffset = i * stride,
39620						writeOffset = writeIndex * stride;
39621
39622					for ( let j = 0; j !== stride; ++ j ) {
39623
39624						values[ writeOffset + j ] = values[ readOffset + j ];
39625
39626					}
39627
39628				}
39629
39630				++ writeIndex;
39631
39632			}
39633
39634		}
39635
39636		// flush last keyframe (compaction looks ahead)
39637
39638		if ( lastIndex > 0 ) {
39639
39640			times[ writeIndex ] = times[ lastIndex ];
39641
39642			for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
39643
39644				values[ writeOffset + j ] = values[ readOffset + j ];
39645
39646			}
39647
39648			++ writeIndex;
39649
39650		}
39651
39652		if ( writeIndex !== times.length ) {
39653
39654			this.times = arraySlice( times, 0, writeIndex );
39655			this.values = arraySlice( values, 0, writeIndex * stride );
39656
39657		} else {
39658
39659			this.times = times;
39660			this.values = values;
39661
39662		}
39663
39664		return this;
39665
39666	}
39667
39668	clone() {
39669
39670		const times = arraySlice( this.times, 0 );
39671		const values = arraySlice( this.values, 0 );
39672
39673		const TypedKeyframeTrack = this.constructor;
39674		const track = new TypedKeyframeTrack( this.name, times, values );
39675
39676		// Interpolant argument to constructor is not saved, so copy the factory method directly.
39677		track.createInterpolant = this.createInterpolant;
39678
39679		return track;
39680
39681	}
39682
39683}
39684
39685KeyframeTrack.prototype.TimeBufferType = Float32Array;
39686KeyframeTrack.prototype.ValueBufferType = Float32Array;
39687KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
39688
39689/**
39690 * A Track of Boolean keyframe values.
39691 */
39692class BooleanKeyframeTrack extends KeyframeTrack {}
39693
39694BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
39695BooleanKeyframeTrack.prototype.ValueBufferType = Array;
39696BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
39697BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
39698BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
39699
39700/**
39701 * A Track of keyframe values that represent color.
39702 */
39703class ColorKeyframeTrack extends KeyframeTrack {}
39704
39705ColorKeyframeTrack.prototype.ValueTypeName = 'color';
39706
39707/**
39708 * A Track of numeric keyframe values.
39709 */
39710class NumberKeyframeTrack extends KeyframeTrack {}
39711
39712NumberKeyframeTrack.prototype.ValueTypeName = 'number';
39713
39714/**
39715 * Spherical linear unit quaternion interpolant.
39716 */
39717
39718class QuaternionLinearInterpolant extends Interpolant {
39719
39720	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
39721
39722		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
39723
39724	}
39725
39726	interpolate_( i1, t0, t, t1 ) {
39727
39728		const result = this.resultBuffer,
39729			values = this.sampleValues,
39730			stride = this.valueSize,
39731
39732			alpha = ( t - t0 ) / ( t1 - t0 );
39733
39734		let offset = i1 * stride;
39735
39736		for ( let end = offset + stride; offset !== end; offset += 4 ) {
39737
39738			Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
39739
39740		}
39741
39742		return result;
39743
39744	}
39745
39746}
39747
39748/**
39749 * A Track of quaternion keyframe values.
39750 */
39751class QuaternionKeyframeTrack extends KeyframeTrack {
39752
39753	InterpolantFactoryMethodLinear( result ) {
39754
39755		return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
39756
39757	}
39758
39759}
39760
39761QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
vendor: 12,201 bytes, lines 39762-40433
39762// ValueBufferType is inherited
39763QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
39764QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
39765
39766/**
39767 * A Track that interpolates Strings
39768 */
39769class StringKeyframeTrack extends KeyframeTrack {}
39770
39771StringKeyframeTrack.prototype.ValueTypeName = 'string';
39772StringKeyframeTrack.prototype.ValueBufferType = Array;
39773StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
39774StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
39775StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
39776
39777/**
39778 * A Track of vectored keyframe values.
39779 */
39780class VectorKeyframeTrack extends KeyframeTrack {}
39781
39782VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
39783
39784class AnimationClip {
39785
39786	constructor( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) {
39787
39788		this.name = name;
39789		this.tracks = tracks;
39790		this.duration = duration;
39791		this.blendMode = blendMode;
39792
39793		this.uuid = generateUUID();
39794
39795		// this means it should figure out its duration by scanning the tracks
39796		if ( this.duration < 0 ) {
39797
39798			this.resetDuration();
39799
39800		}
39801
39802	}
39803
39804
39805	static parse( json ) {
39806
39807		const tracks = [],
39808			jsonTracks = json.tracks,
39809			frameTime = 1.0 / ( json.fps || 1.0 );
39810
39811		for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
39812
39813			tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
39814
39815		}
39816
39817		const clip = new this( json.name, json.duration, tracks, json.blendMode );
39818		clip.uuid = json.uuid;
39819
39820		return clip;
39821
39822	}
39823
39824	static toJSON( clip ) {
39825
39826		const tracks = [],
39827			clipTracks = clip.tracks;
39828
39829		const json = {
39830
39831			'name': clip.name,
39832			'duration': clip.duration,
39833			'tracks': tracks,
39834			'uuid': clip.uuid,
39835			'blendMode': clip.blendMode
39836
39837		};
39838
39839		for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
39840
39841			tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
39842
39843		}
39844
39845		return json;
39846
39847	}
39848
39849	static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
39850
39851		const numMorphTargets = morphTargetSequence.length;
39852		const tracks = [];
39853
39854		for ( let i = 0; i < numMorphTargets; i ++ ) {
39855
39856			let times = [];
39857			let values = [];
39858
39859			times.push(
39860				( i + numMorphTargets - 1 ) % numMorphTargets,
39861				i,
39862				( i + 1 ) % numMorphTargets );
39863
39864			values.push( 0, 1, 0 );
39865
39866			const order = getKeyframeOrder( times );
39867			times = sortedArray( times, 1, order );
39868			values = sortedArray( values, 1, order );
39869
39870			// if there is a key at the first frame, duplicate it as the
39871			// last frame as well for perfect loop.
39872			if ( ! noLoop && times[ 0 ] === 0 ) {
39873
39874				times.push( numMorphTargets );
39875				values.push( values[ 0 ] );
39876
39877			}
39878
39879			tracks.push(
39880				new NumberKeyframeTrack(
39881					'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
39882					times, values
39883				).scale( 1.0 / fps ) );
39884
39885		}
39886
39887		return new this( name, - 1, tracks );
39888
39889	}
39890
39891	static findByName( objectOrClipArray, name ) {
39892
39893		let clipArray = objectOrClipArray;
39894
39895		if ( ! Array.isArray( objectOrClipArray ) ) {
39896
39897			const o = objectOrClipArray;
39898			clipArray = o.geometry && o.geometry.animations || o.animations;
39899
39900		}
39901
39902		for ( let i = 0; i < clipArray.length; i ++ ) {
39903
39904			if ( clipArray[ i ].name === name ) {
39905
39906				return clipArray[ i ];
39907
39908			}
39909
39910		}
39911
39912		return null;
39913
39914	}
39915
39916	static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
39917
39918		const animationToMorphTargets = {};
39919
39920		// tested with https://regex101.com/ on trick sequences
39921		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
39922		const pattern = /^([\w-]*?)([\d]+)$/;
39923
39924		// sort morph target names into animation groups based
39925		// patterns like Walk_001, Walk_002, Run_001, Run_002
39926		for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
39927
39928			const morphTarget = morphTargets[ i ];
39929			const parts = morphTarget.name.match( pattern );
39930
39931			if ( parts && parts.length > 1 ) {
39932
39933				const name = parts[ 1 ];
39934
39935				let animationMorphTargets = animationToMorphTargets[ name ];
39936
39937				if ( ! animationMorphTargets ) {
39938
39939					animationToMorphTargets[ name ] = animationMorphTargets = [];
39940
39941				}
39942
39943				animationMorphTargets.push( morphTarget );
39944
39945			}
39946
39947		}
39948
39949		const clips = [];
39950
39951		for ( const name in animationToMorphTargets ) {
39952
39953			clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
39954
39955		}
39956
39957		return clips;
39958
39959	}
39960
39961	// parse the animation.hierarchy format
39962	static parseAnimation( animation, bones ) {
39963
39964		if ( ! animation ) {
39965
39966			console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
39967			return null;
39968
39969		}
39970
39971		const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
39972
39973			// only return track if there are actually keys.
39974			if ( animationKeys.length !== 0 ) {
39975
39976				const times = [];
39977				const values = [];
39978
39979				flattenJSON( animationKeys, times, values, propertyName );
39980
39981				// empty keys are filtered out, so check again
39982				if ( times.length !== 0 ) {
39983
39984					destTracks.push( new trackType( trackName, times, values ) );
39985
39986				}
39987
39988			}
39989
39990		};
39991
39992		const tracks = [];
39993
39994		const clipName = animation.name || 'default';
39995		const fps = animation.fps || 30;
39996		const blendMode = animation.blendMode;
39997
39998		// automatic length determination in AnimationClip.
39999		let duration = animation.length || - 1;
40000
40001		const hierarchyTracks = animation.hierarchy || [];
40002
40003		for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
40004
40005			const animationKeys = hierarchyTracks[ h ].keys;
40006
40007			// skip empty tracks
40008			if ( ! animationKeys || animationKeys.length === 0 ) continue;
40009
40010			// process morph targets
40011			if ( animationKeys[ 0 ].morphTargets ) {
40012
40013				// figure out all morph targets used in this track
40014				const morphTargetNames = {};
40015
40016				let k;
40017
40018				for ( k = 0; k < animationKeys.length; k ++ ) {
40019
40020					if ( animationKeys[ k ].morphTargets ) {
40021
40022						for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
40023
40024							morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
40025
40026						}
40027
40028					}
40029
40030				}
40031
40032				// create a track for each morph target with all zero
40033				// morphTargetInfluences except for the keys in which
40034				// the morphTarget is named.
40035				for ( const morphTargetName in morphTargetNames ) {
40036
40037					const times = [];
40038					const values = [];
40039
40040					for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
40041
40042						const animationKey = animationKeys[ k ];
40043
40044						times.push( animationKey.time );
40045						values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
40046
40047					}
40048
40049					tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
40050
40051				}
40052
40053				duration = morphTargetNames.length * fps;
40054
40055			} else {
40056
40057				// ...assume skeletal animation
40058
40059				const boneName = '.bones[' + bones[ h ].name + ']';
40060
40061				addNonemptyTrack(
40062					VectorKeyframeTrack, boneName + '.position',
40063					animationKeys, 'pos', tracks );
40064
40065				addNonemptyTrack(
40066					QuaternionKeyframeTrack, boneName + '.quaternion',
40067					animationKeys, 'rot', tracks );
40068
40069				addNonemptyTrack(
40070					VectorKeyframeTrack, boneName + '.scale',
40071					animationKeys, 'scl', tracks );
40072
40073			}
40074
40075		}
40076
40077		if ( tracks.length === 0 ) {
40078
40079			return null;
40080
40081		}
40082
40083		const clip = new this( clipName, duration, tracks, blendMode );
40084
40085		return clip;
40086
40087	}
40088
40089	resetDuration() {
40090
40091		const tracks = this.tracks;
40092		let duration = 0;
40093
40094		for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
40095
40096			const track = this.tracks[ i ];
40097
40098			duration = Math.max( duration, track.times[ track.times.length - 1 ] );
40099
40100		}
40101
40102		this.duration = duration;
40103
40104		return this;
40105
40106	}
40107
40108	trim() {
40109
40110		for ( let i = 0; i < this.tracks.length; i ++ ) {
40111
40112			this.tracks[ i ].trim( 0, this.duration );
40113
40114		}
40115
40116		return this;
40117
40118	}
40119
40120	validate() {
40121
40122		let valid = true;
40123
40124		for ( let i = 0; i < this.tracks.length; i ++ ) {
40125
40126			valid = valid && this.tracks[ i ].validate();
40127
40128		}
40129
40130		return valid;
40131
40132	}
40133
40134	optimize() {
40135
40136		for ( let i = 0; i < this.tracks.length; i ++ ) {
40137
40138			this.tracks[ i ].optimize();
40139
40140		}
40141
40142		return this;
40143
40144	}
40145
40146	clone() {
40147
40148		const tracks = [];
40149
40150		for ( let i = 0; i < this.tracks.length; i ++ ) {
40151
40152			tracks.push( this.tracks[ i ].clone() );
40153
40154		}
40155
40156		return new this.constructor( this.name, this.duration, tracks, this.blendMode );
40157
40158	}
40159
40160	toJSON() {
40161
40162		return this.constructor.toJSON( this );
40163
40164	}
40165
40166}
40167
40168function getTrackTypeForValueTypeName( typeName ) {
40169
40170	switch ( typeName.toLowerCase() ) {
40171
40172		case 'scalar':
40173		case 'double':
40174		case 'float':
40175		case 'number':
40176		case 'integer':
40177
40178			return NumberKeyframeTrack;
40179
40180		case 'vector':
40181		case 'vector2':
40182		case 'vector3':
40183		case 'vector4':
40184
40185			return VectorKeyframeTrack;
40186
40187		case 'color':
40188
40189			return ColorKeyframeTrack;
40190
40191		case 'quaternion':
40192
40193			return QuaternionKeyframeTrack;
40194
40195		case 'bool':
40196		case 'boolean':
40197
40198			return BooleanKeyframeTrack;
40199
40200		case 'string':
40201
40202			return StringKeyframeTrack;
40203
40204	}
40205
40206	throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
40207
40208}
40209
40210function parseKeyframeTrack( json ) {
40211
40212	if ( json.type === undefined ) {
40213
40214		throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
40215
40216	}
40217
40218	const trackType = getTrackTypeForValueTypeName( json.type );
40219
40220	if ( json.times === undefined ) {
40221
40222		const times = [], values = [];
40223
40224		flattenJSON( json.keys, times, values, 'value' );
40225
40226		json.times = times;
40227		json.values = values;
40228
40229	}
40230
40231	// derived classes can define a static parse method
40232	if ( trackType.parse !== undefined ) {
40233
40234		return trackType.parse( json );
40235
40236	} else {
40237
40238		// by default, we assume a constructor compatible with the base
40239		return new trackType( json.name, json.times, json.values, json.interpolation );
40240
40241	}
40242
40243}
40244
40245const Cache = {
40246
40247	enabled: false,
40248
40249	files: {},
40250
40251	add: function ( key, file ) {
40252
40253		if ( this.enabled === false ) return;
40254
40255		// console.log( 'THREE.Cache', 'Adding key:', key );
40256
40257		this.files[ key ] = file;
40258
40259	},
40260
40261	get: function ( key ) {
40262
40263		if ( this.enabled === false ) return;
40264
40265		// console.log( 'THREE.Cache', 'Checking key:', key );
40266
40267		return this.files[ key ];
40268
40269	},
40270
40271	remove: function ( key ) {
40272
40273		delete this.files[ key ];
40274
40275	},
40276
40277	clear: function () {
40278
40279		this.files = {};
40280
40281	}
40282
40283};
40284
40285class LoadingManager {
40286
40287	constructor( onLoad, onProgress, onError ) {
40288
40289		const scope = this;
40290
40291		let isLoading = false;
40292		let itemsLoaded = 0;
40293		let itemsTotal = 0;
40294		let urlModifier = undefined;
40295		const handlers = [];
40296
40297		// Refer to #5689 for the reason why we don't set .onStart
40298		// in the constructor
40299
40300		this.onStart = undefined;
40301		this.onLoad = onLoad;
40302		this.onProgress = onProgress;
40303		this.onError = onError;
40304
40305		this.itemStart = function ( url ) {
40306
40307			itemsTotal ++;
40308
40309			if ( isLoading === false ) {
40310
40311				if ( scope.onStart !== undefined ) {
40312
40313					scope.onStart( url, itemsLoaded, itemsTotal );
40314
40315				}
40316
40317			}
40318
40319			isLoading = true;
40320
40321		};
40322
40323		this.itemEnd = function ( url ) {
40324
40325			itemsLoaded ++;
40326
40327			if ( scope.onProgress !== undefined ) {
40328
40329				scope.onProgress( url, itemsLoaded, itemsTotal );
40330
40331			}
40332
40333			if ( itemsLoaded === itemsTotal ) {
40334
40335				isLoading = false;
40336
40337				if ( scope.onLoad !== undefined ) {
40338
40339					scope.onLoad();
40340
40341				}
40342
40343			}
40344
40345		};
40346
40347		this.itemError = function ( url ) {
40348
40349			if ( scope.onError !== undefined ) {
40350
40351				scope.onError( url );
40352
40353			}
40354
40355		};
40356
40357		this.resolveURL = function ( url ) {
40358
40359			if ( urlModifier ) {
40360
40361				return urlModifier( url );
40362
40363			}
40364
40365			return url;
40366
40367		};
40368
40369		this.setURLModifier = function ( transform ) {
40370
40371			urlModifier = transform;
40372
40373			return this;
40374
40375		};
40376
40377		this.addHandler = function ( regex, loader ) {
40378
40379			handlers.push( regex, loader );
40380
40381			return this;
40382
40383		};
40384
40385		this.removeHandler = function ( regex ) {
40386
40387			const index = handlers.indexOf( regex );
40388
40389			if ( index !== - 1 ) {
40390
40391				handlers.splice( index, 2 );
40392
40393			}
40394
40395			return this;
40396
40397		};
40398
40399		this.getHandler = function ( file ) {
40400
40401			for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
40402
40403				const regex = handlers[ i ];
40404				const loader = handlers[ i + 1 ];
40405
40406				if ( regex.global ) regex.lastIndex = 0; // see #17920
40407
40408				if ( regex.test( file ) ) {
40409
40410					return loader;
40411
40412				}
40413
40414			}
40415
40416			return null;
40417
40418		};
40419
40420	}
40421
40422}
40423
40424const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager();
40425
40426class Loader {
40427
40428	constructor( manager ) {
40429
40430		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
40431
40432		this.crossOrigin = 'anonymous';
40433		this.withCredentials = false;
vendor: 12,657 bytes, lines 40434-41139
40434		this.path = '';
40435		this.resourcePath = '';
40436		this.requestHeader = {};
40437
40438	}
40439
40440	load( /* url, onLoad, onProgress, onError */ ) {}
40441
40442	loadAsync( url, onProgress ) {
40443
40444		const scope = this;
40445
40446		return new Promise( function ( resolve, reject ) {
40447
40448			scope.load( url, resolve, onProgress, reject );
40449
40450		} );
40451
40452	}
40453
40454	parse( /* data */ ) {}
40455
40456	setCrossOrigin( crossOrigin ) {
40457
40458		this.crossOrigin = crossOrigin;
40459		return this;
40460
40461	}
40462
40463	setWithCredentials( value ) {
40464
40465		this.withCredentials = value;
40466		return this;
40467
40468	}
40469
40470	setPath( path ) {
40471
40472		this.path = path;
40473		return this;
40474
40475	}
40476
40477	setResourcePath( resourcePath ) {
40478
40479		this.resourcePath = resourcePath;
40480		return this;
40481
40482	}
40483
40484	setRequestHeader( requestHeader ) {
40485
40486		this.requestHeader = requestHeader;
40487		return this;
40488
40489	}
40490
40491}
40492
40493const loading = {};
40494
40495class HttpError extends Error {
40496
40497	constructor( message, response ) {
40498
40499		super( message );
40500		this.response = response;
40501
40502	}
40503
40504}
40505
40506class FileLoader extends Loader {
40507
40508	constructor( manager ) {
40509
40510		super( manager );
40511
40512	}
40513
40514	load( url, onLoad, onProgress, onError ) {
40515
40516		if ( url === undefined ) url = '';
40517
40518		if ( this.path !== undefined ) url = this.path + url;
40519
40520		url = this.manager.resolveURL( url );
40521
40522		const cached = Cache.get( url );
40523
40524		if ( cached !== undefined ) {
40525
40526			this.manager.itemStart( url );
40527
40528			setTimeout( () => {
40529
40530				if ( onLoad ) onLoad( cached );
40531
40532				this.manager.itemEnd( url );
40533
40534			}, 0 );
40535
40536			return cached;
40537
40538		}
40539
40540		// Check if request is duplicate
40541
40542		if ( loading[ url ] !== undefined ) {
40543
40544			loading[ url ].push( {
40545
40546				onLoad: onLoad,
40547				onProgress: onProgress,
40548				onError: onError
40549
40550			} );
40551
40552			return;
40553
40554		}
40555
40556		// Initialise array for duplicate requests
40557		loading[ url ] = [];
40558
40559		loading[ url ].push( {
40560			onLoad: onLoad,
40561			onProgress: onProgress,
40562			onError: onError,
40563		} );
40564
40565		// create request
40566		const req = new Request( url, {
40567			headers: new Headers( this.requestHeader ),
40568			credentials: this.withCredentials ? 'include' : 'same-origin',
40569			// An abort controller could be added within a future PR
40570		} );
40571
40572		// record states ( avoid data race )
40573		const mimeType = this.mimeType;
40574		const responseType = this.responseType;
40575
40576		// start the fetch
40577		fetch( req )
40578			.then( response => {
40579
40580				if ( response.status === 200 || response.status === 0 ) {
40581
40582					// Some browsers return HTTP Status 0 when using non-http protocol
40583					// e.g. 'file://' or 'data://'. Handle as success.
40584
40585					if ( response.status === 0 ) {
40586
40587						console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
40588
40589					}
40590
40591					// Workaround: Checking if response.body === undefined for Alipay browser #23548
40592
40593					if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) {
40594
40595						return response;
40596
40597					}
40598
40599					const callbacks = loading[ url ];
40600					const reader = response.body.getReader();
40601
40602					// Nginx needs X-File-Size check
40603					// https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content
40604					const contentLength = response.headers.get( 'Content-Length' ) || response.headers.get( 'X-File-Size' );
40605					const total = contentLength ? parseInt( contentLength ) : 0;
40606					const lengthComputable = total !== 0;
40607					let loaded = 0;
40608
40609					// periodically read data into the new stream tracking while download progress
40610					const stream = new ReadableStream( {
40611						start( controller ) {
40612
40613							readData();
40614
40615							function readData() {
40616
40617								reader.read().then( ( { done, value } ) => {
40618
40619									if ( done ) {
40620
40621										controller.close();
40622
40623									} else {
40624
40625										loaded += value.byteLength;
40626
40627										const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } );
40628										for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
40629
40630											const callback = callbacks[ i ];
40631											if ( callback.onProgress ) callback.onProgress( event );
40632
40633										}
40634
40635										controller.enqueue( value );
40636										readData();
40637
40638									}
40639
40640								} );
40641
40642							}
40643
40644						}
40645
40646					} );
40647
40648					return new Response( stream );
40649
40650				} else {
40651
40652					throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response );
40653
40654				}
40655
40656			} )
40657			.then( response => {
40658
40659				switch ( responseType ) {
40660
40661					case 'arraybuffer':
40662
40663						return response.arrayBuffer();
40664
40665					case 'blob':
40666
40667						return response.blob();
40668
40669					case 'document':
40670
40671						return response.text()
40672							.then( text => {
40673
40674								const parser = new DOMParser();
40675								return parser.parseFromString( text, mimeType );
40676
40677							} );
40678
40679					case 'json':
40680
40681						return response.json();
40682
40683					default:
40684
40685						if ( mimeType === undefined ) {
40686
40687							return response.text();
40688
40689						} else {
40690
40691							// sniff encoding
40692							const re = /charset="?([^;"\s]*)"?/i;
40693							const exec = re.exec( mimeType );
40694							const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined;
40695							const decoder = new TextDecoder( label );
40696							return response.arrayBuffer().then( ab => decoder.decode( ab ) );
40697
40698						}
40699
40700				}
40701
40702			} )
40703			.then( data => {
40704
40705				// Add to cache only on HTTP success, so that we do not cache
40706				// error response bodies as proper responses to requests.
40707				Cache.add( url, data );
40708
40709				const callbacks = loading[ url ];
40710				delete loading[ url ];
40711
40712				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
40713
40714					const callback = callbacks[ i ];
40715					if ( callback.onLoad ) callback.onLoad( data );
40716
40717				}
40718
40719			} )
40720			.catch( err => {
40721
40722				// Abort errors and other errors are handled the same
40723
40724				const callbacks = loading[ url ];
40725
40726				if ( callbacks === undefined ) {
40727
40728					// When onLoad was called and url was deleted in `loading`
40729					this.manager.itemError( url );
40730					throw err;
40731
40732				}
40733
40734				delete loading[ url ];
40735
40736				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
40737
40738					const callback = callbacks[ i ];
40739					if ( callback.onError ) callback.onError( err );
40740
40741				}
40742
40743				this.manager.itemError( url );
40744
40745			} )
40746			.finally( () => {
40747
40748				this.manager.itemEnd( url );
40749
40750			} );
40751
40752		this.manager.itemStart( url );
40753
40754	}
40755
40756	setResponseType( value ) {
40757
40758		this.responseType = value;
40759		return this;
40760
40761	}
40762
40763	setMimeType( value ) {
40764
40765		this.mimeType = value;
40766		return this;
40767
40768	}
40769
40770}
40771
40772class AnimationLoader extends Loader {
40773
40774	constructor( manager ) {
40775
40776		super( manager );
40777
40778	}
40779
40780	load( url, onLoad, onProgress, onError ) {
40781
40782		const scope = this;
40783
40784		const loader = new FileLoader( this.manager );
40785		loader.setPath( this.path );
40786		loader.setRequestHeader( this.requestHeader );
40787		loader.setWithCredentials( this.withCredentials );
40788		loader.load( url, function ( text ) {
40789
40790			try {
40791
40792				onLoad( scope.parse( JSON.parse( text ) ) );
40793
40794			} catch ( e ) {
40795
40796				if ( onError ) {
40797
40798					onError( e );
40799
40800				} else {
40801
40802					console.error( e );
40803
40804				}
40805
40806				scope.manager.itemError( url );
40807
40808			}
40809
40810		}, onProgress, onError );
40811
40812	}
40813
40814	parse( json ) {
40815
40816		const animations = [];
40817
40818		for ( let i = 0; i < json.length; i ++ ) {
40819
40820			const clip = AnimationClip.parse( json[ i ] );
40821
40822			animations.push( clip );
40823
40824		}
40825
40826		return animations;
40827
40828	}
40829
40830}
40831
40832/**
40833 * Abstract Base class to block based textures loader (dds, pvr, ...)
40834 *
40835 * Sub classes have to implement the parse() method which will be used in load().
40836 */
40837
40838class CompressedTextureLoader extends Loader {
40839
40840	constructor( manager ) {
40841
40842		super( manager );
40843
40844	}
40845
40846	load( url, onLoad, onProgress, onError ) {
40847
40848		const scope = this;
40849
40850		const images = [];
40851
40852		const texture = new CompressedTexture();
40853
40854		const loader = new FileLoader( this.manager );
40855		loader.setPath( this.path );
40856		loader.setResponseType( 'arraybuffer' );
40857		loader.setRequestHeader( this.requestHeader );
40858		loader.setWithCredentials( scope.withCredentials );
40859
40860		let loaded = 0;
40861
40862		function loadTexture( i ) {
40863
40864			loader.load( url[ i ], function ( buffer ) {
40865
40866				const texDatas = scope.parse( buffer, true );
40867
40868				images[ i ] = {
40869					width: texDatas.width,
40870					height: texDatas.height,
40871					format: texDatas.format,
40872					mipmaps: texDatas.mipmaps
40873				};
40874
40875				loaded += 1;
40876
40877				if ( loaded === 6 ) {
40878
40879					if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
40880
40881					texture.image = images;
40882					texture.format = texDatas.format;
40883					texture.needsUpdate = true;
40884
40885					if ( onLoad ) onLoad( texture );
40886
40887				}
40888
40889			}, onProgress, onError );
40890
40891		}
40892
40893		if ( Array.isArray( url ) ) {
40894
40895			for ( let i = 0, il = url.length; i < il; ++ i ) {
40896
40897				loadTexture( i );
40898
40899			}
40900
40901		} else {
40902
40903			// compressed cubemap texture stored in a single DDS file
40904
40905			loader.load( url, function ( buffer ) {
40906
40907				const texDatas = scope.parse( buffer, true );
40908
40909				if ( texDatas.isCubemap ) {
40910
40911					const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
40912
40913					for ( let f = 0; f < faces; f ++ ) {
40914
40915						images[ f ] = { mipmaps: [] };
40916
40917						for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
40918
40919							images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
40920							images[ f ].format = texDatas.format;
40921							images[ f ].width = texDatas.width;
40922							images[ f ].height = texDatas.height;
40923
40924						}
40925
40926					}
40927
40928					texture.image = images;
40929
40930				} else {
40931
40932					texture.image.width = texDatas.width;
40933					texture.image.height = texDatas.height;
40934					texture.mipmaps = texDatas.mipmaps;
40935
40936				}
40937
40938				if ( texDatas.mipmapCount === 1 ) {
40939
40940					texture.minFilter = LinearFilter;
40941
40942				}
40943
40944				texture.format = texDatas.format;
40945				texture.needsUpdate = true;
40946
40947				if ( onLoad ) onLoad( texture );
40948
40949			}, onProgress, onError );
40950
40951		}
40952
40953		return texture;
40954
40955	}
40956
40957}
40958
40959class ImageLoader extends Loader {
40960
40961	constructor( manager ) {
40962
40963		super( manager );
40964
40965	}
40966
40967	load( url, onLoad, onProgress, onError ) {
40968
40969		if ( this.path !== undefined ) url = this.path + url;
40970
40971		url = this.manager.resolveURL( url );
40972
40973		const scope = this;
40974
40975		const cached = Cache.get( url );
40976
40977		if ( cached !== undefined ) {
40978
40979			scope.manager.itemStart( url );
40980
40981			setTimeout( function () {
40982
40983				if ( onLoad ) onLoad( cached );
40984
40985				scope.manager.itemEnd( url );
40986
40987			}, 0 );
40988
40989			return cached;
40990
40991		}
40992
40993		const image = createElementNS( 'img' );
40994
40995		function onImageLoad() {
40996
40997			removeEventListeners();
40998
40999			Cache.add( url, this );
41000
41001			if ( onLoad ) onLoad( this );
41002
41003			scope.manager.itemEnd( url );
41004
41005		}
41006
41007		function onImageError( event ) {
41008
41009			removeEventListeners();
41010
41011			if ( onError ) onError( event );
41012
41013			scope.manager.itemError( url );
41014			scope.manager.itemEnd( url );
41015
41016		}
41017
41018		function removeEventListeners() {
41019
41020			image.removeEventListener( 'load', onImageLoad, false );
41021			image.removeEventListener( 'error', onImageError, false );
41022
41023		}
41024
41025		image.addEventListener( 'load', onImageLoad, false );
41026		image.addEventListener( 'error', onImageError, false );
41027
41028		if ( url.slice( 0, 5 ) !== 'data:' ) {
41029
41030			if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
41031
41032		}
41033
41034		scope.manager.itemStart( url );
41035
41036		image.src = url;
41037
41038		return image;
41039
41040	}
41041
41042}
41043
41044class CubeTextureLoader extends Loader {
41045
41046	constructor( manager ) {
41047
41048		super( manager );
41049
41050	}
41051
41052	load( urls, onLoad, onProgress, onError ) {
41053
41054		const texture = new CubeTexture();
41055
41056		const loader = new ImageLoader( this.manager );
41057		loader.setCrossOrigin( this.crossOrigin );
41058		loader.setPath( this.path );
41059
41060		let loaded = 0;
41061
41062		function loadTexture( i ) {
41063
41064			loader.load( urls[ i ], function ( image ) {
41065
41066				texture.images[ i ] = image;
41067
41068				loaded ++;
41069
41070				if ( loaded === 6 ) {
41071
41072					texture.needsUpdate = true;
41073
41074					if ( onLoad ) onLoad( texture );
41075
41076				}
41077
41078			}, undefined, onError );
41079
41080		}
41081
41082		for ( let i = 0; i < urls.length; ++ i ) {
41083
41084			loadTexture( i );
41085
41086		}
41087
41088		return texture;
41089
41090	}
41091
41092}
41093
41094/**
41095 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
41096 *
41097 * Sub classes have to implement the parse() method which will be used in load().
41098 */
41099
41100class DataTextureLoader extends Loader {
41101
41102	constructor( manager ) {
41103
41104		super( manager );
41105
41106	}
41107
41108	load( url, onLoad, onProgress, onError ) {
41109
41110		const scope = this;
41111
41112		const texture = new DataTexture();
41113
41114		const loader = new FileLoader( this.manager );
41115		loader.setResponseType( 'arraybuffer' );
41116		loader.setRequestHeader( this.requestHeader );
41117		loader.setPath( this.path );
41118		loader.setWithCredentials( scope.withCredentials );
41119		loader.load( url, function ( buffer ) {
41120
41121			const texData = scope.parse( buffer );
41122
41123			if ( ! texData ) return;
41124
41125			if ( texData.image !== undefined ) {
41126
41127				texture.image = texData.image;
41128
41129			} else if ( texData.data !== undefined ) {
41130
41131				texture.image.width = texData.width;
41132				texture.image.height = texData.height;
41133				texture.image.data = texData.data;
41134
41135			}
41136
41137			texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
41138			texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
41139
vendor: 4,947 bytes, lines 41140-41426
41140			texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
41141			texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
41142
41143			texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
41144
41145			if ( texData.encoding !== undefined ) {
41146
41147				texture.encoding = texData.encoding;
41148
41149			}
41150
41151			if ( texData.flipY !== undefined ) {
41152
41153				texture.flipY = texData.flipY;
41154
41155			}
41156
41157			if ( texData.format !== undefined ) {
41158
41159				texture.format = texData.format;
41160
41161			}
41162
41163			if ( texData.type !== undefined ) {
41164
41165				texture.type = texData.type;
41166
41167			}
41168
41169			if ( texData.mipmaps !== undefined ) {
41170
41171				texture.mipmaps = texData.mipmaps;
41172				texture.minFilter = LinearMipmapLinearFilter; // presumably...
41173
41174			}
41175
41176			if ( texData.mipmapCount === 1 ) {
41177
41178				texture.minFilter = LinearFilter;
41179
41180			}
41181
41182			if ( texData.generateMipmaps !== undefined ) {
41183
41184				texture.generateMipmaps = texData.generateMipmaps;
41185
41186			}
41187
41188			texture.needsUpdate = true;
41189
41190			if ( onLoad ) onLoad( texture, texData );
41191
41192		}, onProgress, onError );
41193
41194
41195		return texture;
41196
41197	}
41198
41199}
41200
41201class TextureLoader extends Loader {
41202
41203	constructor( manager ) {
41204
41205		super( manager );
41206
41207	}
41208
41209	load( url, onLoad, onProgress, onError ) {
41210
41211		const texture = new Texture();
41212
41213		const loader = new ImageLoader( this.manager );
41214		loader.setCrossOrigin( this.crossOrigin );
41215		loader.setPath( this.path );
41216
41217		loader.load( url, function ( image ) {
41218
41219			texture.image = image;
41220			texture.needsUpdate = true;
41221
41222			if ( onLoad !== undefined ) {
41223
41224				onLoad( texture );
41225
41226			}
41227
41228		}, onProgress, onError );
41229
41230		return texture;
41231
41232	}
41233
41234}
41235
41236class Light extends Object3D {
41237
41238	constructor( color, intensity = 1 ) {
41239
41240		super();
41241
41242		this.isLight = true;
41243
41244		this.type = 'Light';
41245
41246		this.color = new Color( color );
41247		this.intensity = intensity;
41248
41249	}
41250
41251	dispose() {
41252
41253		// Empty here in base class; some subclasses override.
41254
41255	}
41256
41257	copy( source, recursive ) {
41258
41259		super.copy( source, recursive );
41260
41261		this.color.copy( source.color );
41262		this.intensity = source.intensity;
41263
41264		return this;
41265
41266	}
41267
41268	toJSON( meta ) {
41269
41270		const data = super.toJSON( meta );
41271
41272		data.object.color = this.color.getHex();
41273		data.object.intensity = this.intensity;
41274
41275		if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
41276
41277		if ( this.distance !== undefined ) data.object.distance = this.distance;
41278		if ( this.angle !== undefined ) data.object.angle = this.angle;
41279		if ( this.decay !== undefined ) data.object.decay = this.decay;
41280		if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
41281
41282		if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
41283
41284		return data;
41285
41286	}
41287
41288}
41289
41290class HemisphereLight extends Light {
41291
41292	constructor( skyColor, groundColor, intensity ) {
41293
41294		super( skyColor, intensity );
41295
41296		this.isHemisphereLight = true;
41297
41298		this.type = 'HemisphereLight';
41299
41300		this.position.copy( Object3D.DEFAULT_UP );
41301		this.updateMatrix();
41302
41303		this.groundColor = new Color( groundColor );
41304
41305	}
41306
41307	copy( source, recursive ) {
41308
41309		super.copy( source, recursive );
41310
41311		this.groundColor.copy( source.groundColor );
41312
41313		return this;
41314
41315	}
41316
41317}
41318
41319const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
41320const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3();
41321const _lookTarget$1 = /*@__PURE__*/ new Vector3();
41322
41323class LightShadow {
41324
41325	constructor( camera ) {
41326
41327		this.camera = camera;
41328
41329		this.bias = 0;
41330		this.normalBias = 0;
41331		this.radius = 1;
41332		this.blurSamples = 8;
41333
41334		this.mapSize = new Vector2( 512, 512 );
41335
41336		this.map = null;
41337		this.mapPass = null;
41338		this.matrix = new Matrix4();
41339
41340		this.autoUpdate = true;
41341		this.needsUpdate = false;
41342
41343		this._frustum = new Frustum();
41344		this._frameExtents = new Vector2( 1, 1 );
41345
41346		this._viewportCount = 1;
41347
41348		this._viewports = [
41349
41350			new Vector4( 0, 0, 1, 1 )
41351
41352		];
41353
41354	}
41355
41356	getViewportCount() {
41357
41358		return this._viewportCount;
41359
41360	}
41361
41362	getFrustum() {
41363
41364		return this._frustum;
41365
41366	}
41367
41368	updateMatrices( light ) {
41369
41370		const shadowCamera = this.camera;
41371		const shadowMatrix = this.matrix;
41372
41373		_lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld );
41374		shadowCamera.position.copy( _lightPositionWorld$1 );
41375
41376		_lookTarget$1.setFromMatrixPosition( light.target.matrixWorld );
41377		shadowCamera.lookAt( _lookTarget$1 );
41378		shadowCamera.updateMatrixWorld();
41379
41380		_projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
41381		this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 );
41382
41383		shadowMatrix.set(
41384			0.5, 0.0, 0.0, 0.5,
41385			0.0, 0.5, 0.0, 0.5,
41386			0.0, 0.0, 0.5, 0.5,
41387			0.0, 0.0, 0.0, 1.0
41388		);
41389
41390		shadowMatrix.multiply( _projScreenMatrix$1 );
41391
41392	}
41393
41394	getViewport( viewportIndex ) {
41395
41396		return this._viewports[ viewportIndex ];
41397
41398	}
41399
41400	getFrameExtents() {
41401
41402		return this._frameExtents;
41403
41404	}
41405
41406	dispose() {
41407
41408		if ( this.map ) {
41409
41410			this.map.dispose();
41411
41412		}
41413
41414		if ( this.mapPass ) {
41415
41416			this.mapPass.dispose();
41417
41418		}
41419
41420	}
41421
41422	copy( source ) {
41423
41424		this.camera = source.camera.clone();
41425
41426		this.bias = source.bias;
vendor: 5,709 bytes, lines 41427-41714
41427		this.radius = source.radius;
41428
41429		this.mapSize.copy( source.mapSize );
41430
41431		return this;
41432
41433	}
41434
41435	clone() {
41436
41437		return new this.constructor().copy( this );
41438
41439	}
41440
41441	toJSON() {
41442
41443		const object = {};
41444
41445		if ( this.bias !== 0 ) object.bias = this.bias;
41446		if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
41447		if ( this.radius !== 1 ) object.radius = this.radius;
41448		if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
41449
41450		object.camera = this.camera.toJSON( false ).object;
41451		delete object.camera.matrix;
41452
41453		return object;
41454
41455	}
41456
41457}
41458
41459class SpotLightShadow extends LightShadow {
41460
41461	constructor() {
41462
41463		super( new PerspectiveCamera( 50, 1, 0.5, 500 ) );
41464
41465		this.isSpotLightShadow = true;
41466
41467		this.focus = 1;
41468
41469	}
41470
41471	updateMatrices( light ) {
41472
41473		const camera = this.camera;
41474
41475		const fov = RAD2DEG * 2 * light.angle * this.focus;
41476		const aspect = this.mapSize.width / this.mapSize.height;
41477		const far = light.distance || camera.far;
41478
41479		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
41480
41481			camera.fov = fov;
41482			camera.aspect = aspect;
41483			camera.far = far;
41484			camera.updateProjectionMatrix();
41485
41486		}
41487
41488		super.updateMatrices( light );
41489
41490	}
41491
41492	copy( source ) {
41493
41494		super.copy( source );
41495
41496		this.focus = source.focus;
41497
41498		return this;
41499
41500	}
41501
41502}
41503
41504class SpotLight extends Light {
41505
41506	constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) {
41507
41508		super( color, intensity );
41509
41510		this.isSpotLight = true;
41511
41512		this.type = 'SpotLight';
41513
41514		this.position.copy( Object3D.DEFAULT_UP );
41515		this.updateMatrix();
41516
41517		this.target = new Object3D();
41518
41519		this.distance = distance;
41520		this.angle = angle;
41521		this.penumbra = penumbra;
41522		this.decay = decay;
41523
41524		this.map = null;
41525
41526		this.shadow = new SpotLightShadow();
41527
41528	}
41529
41530	get power() {
41531
41532		// compute the light's luminous power (in lumens) from its intensity (in candela)
41533		// by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
41534		return this.intensity * Math.PI;
41535
41536	}
41537
41538	set power( power ) {
41539
41540		// set the light's intensity (in candela) from the desired luminous power (in lumens)
41541		this.intensity = power / Math.PI;
41542
41543	}
41544
41545	dispose() {
41546
41547		this.shadow.dispose();
41548
41549	}
41550
41551	copy( source, recursive ) {
41552
41553		super.copy( source, recursive );
41554
41555		this.distance = source.distance;
41556		this.angle = source.angle;
41557		this.penumbra = source.penumbra;
41558		this.decay = source.decay;
41559
41560		this.target = source.target.clone();
41561
41562		this.shadow = source.shadow.clone();
41563
41564		return this;
41565
41566	}
41567
41568}
41569
41570const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
41571const _lightPositionWorld = /*@__PURE__*/ new Vector3();
41572const _lookTarget = /*@__PURE__*/ new Vector3();
41573
41574class PointLightShadow extends LightShadow {
41575
41576	constructor() {
41577
41578		super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
41579
41580		this.isPointLightShadow = true;
41581
41582		this._frameExtents = new Vector2( 4, 2 );
41583
41584		this._viewportCount = 6;
41585
41586		this._viewports = [
41587			// These viewports map a cube-map onto a 2D texture with the
41588			// following orientation:
41589			//
41590			//  xzXZ
41591			//   y Y
41592			//
41593			// X - Positive x direction
41594			// x - Negative x direction
41595			// Y - Positive y direction
41596			// y - Negative y direction
41597			// Z - Positive z direction
41598			// z - Negative z direction
41599
41600			// positive X
41601			new Vector4( 2, 1, 1, 1 ),
41602			// negative X
41603			new Vector4( 0, 1, 1, 1 ),
41604			// positive Z
41605			new Vector4( 3, 1, 1, 1 ),
41606			// negative Z
41607			new Vector4( 1, 1, 1, 1 ),
41608			// positive Y
41609			new Vector4( 3, 0, 1, 1 ),
41610			// negative Y
41611			new Vector4( 1, 0, 1, 1 )
41612		];
41613
41614		this._cubeDirections = [
41615			new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
41616			new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
41617		];
41618
41619		this._cubeUps = [
41620			new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
41621			new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),	new Vector3( 0, 0, - 1 )
41622		];
41623
41624	}
41625
41626	updateMatrices( light, viewportIndex = 0 ) {
41627
41628		const camera = this.camera;
41629		const shadowMatrix = this.matrix;
41630
41631		const far = light.distance || camera.far;
41632
41633		if ( far !== camera.far ) {
41634
41635			camera.far = far;
41636			camera.updateProjectionMatrix();
41637
41638		}
41639
41640		_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
41641		camera.position.copy( _lightPositionWorld );
41642
41643		_lookTarget.copy( camera.position );
41644		_lookTarget.add( this._cubeDirections[ viewportIndex ] );
41645		camera.up.copy( this._cubeUps[ viewportIndex ] );
41646		camera.lookAt( _lookTarget );
41647		camera.updateMatrixWorld();
41648
41649		shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
41650
41651		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
41652		this._frustum.setFromProjectionMatrix( _projScreenMatrix );
41653
41654	}
41655
41656}
41657
41658class PointLight extends Light {
41659
41660	constructor( color, intensity, distance = 0, decay = 2 ) {
41661
41662		super( color, intensity );
41663
41664		this.isPointLight = true;
41665
41666		this.type = 'PointLight';
41667
41668		this.distance = distance;
41669		this.decay = decay;
41670
41671		this.shadow = new PointLightShadow();
41672
41673	}
41674
41675	get power() {
41676
41677		// compute the light's luminous power (in lumens) from its intensity (in candela)
41678		// for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
41679		return this.intensity * 4 * Math.PI;
41680
41681	}
41682
41683	set power( power ) {
41684
41685		// set the light's intensity (in candela) from the desired luminous power (in lumens)
41686		this.intensity = power / ( 4 * Math.PI );
41687
41688	}
41689
41690	dispose() {
41691
41692		this.shadow.dispose();
41693
41694	}
41695
41696	copy( source, recursive ) {
41697
41698		super.copy( source, recursive );
41699
41700		this.distance = source.distance;
41701		this.decay = source.decay;
41702
41703		this.shadow = source.shadow.clone();
41704
41705		return this;
41706
41707	}
41708
41709}
41710
41711class DirectionalLightShadow extends LightShadow {
41712
41713	constructor() {
41714
vendor: 4,273 bytes, lines 41715-41936
41715		super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
41716
41717		this.isDirectionalLightShadow = true;
41718
41719	}
41720
41721}
41722
41723class DirectionalLight extends Light {
41724
41725	constructor( color, intensity ) {
41726
41727		super( color, intensity );
41728
41729		this.isDirectionalLight = true;
41730
41731		this.type = 'DirectionalLight';
41732
41733		this.position.copy( Object3D.DEFAULT_UP );
41734		this.updateMatrix();
41735
41736		this.target = new Object3D();
41737
41738		this.shadow = new DirectionalLightShadow();
41739
41740	}
41741
41742	dispose() {
41743
41744		this.shadow.dispose();
41745
41746	}
41747
41748	copy( source ) {
41749
41750		super.copy( source );
41751
41752		this.target = source.target.clone();
41753		this.shadow = source.shadow.clone();
41754
41755		return this;
41756
41757	}
41758
41759}
41760
41761class AmbientLight extends Light {
41762
41763	constructor( color, intensity ) {
41764
41765		super( color, intensity );
41766
41767		this.isAmbientLight = true;
41768
41769		this.type = 'AmbientLight';
41770
41771	}
41772
41773}
41774
41775class RectAreaLight extends Light {
41776
41777	constructor( color, intensity, width = 10, height = 10 ) {
41778
41779		super( color, intensity );
41780
41781		this.isRectAreaLight = true;
41782
41783		this.type = 'RectAreaLight';
41784
41785		this.width = width;
41786		this.height = height;
41787
41788	}
41789
41790	get power() {
41791
41792		// compute the light's luminous power (in lumens) from its intensity (in nits)
41793		return this.intensity * this.width * this.height * Math.PI;
41794
41795	}
41796
41797	set power( power ) {
41798
41799		// set the light's intensity (in nits) from the desired luminous power (in lumens)
41800		this.intensity = power / ( this.width * this.height * Math.PI );
41801
41802	}
41803
41804	copy( source ) {
41805
41806		super.copy( source );
41807
41808		this.width = source.width;
41809		this.height = source.height;
41810
41811		return this;
41812
41813	}
41814
41815	toJSON( meta ) {
41816
41817		const data = super.toJSON( meta );
41818
41819		data.object.width = this.width;
41820		data.object.height = this.height;
41821
41822		return data;
41823
41824	}
41825
41826}
41827
41828/**
41829 * Primary reference:
41830 *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
41831 *
41832 * Secondary reference:
41833 *   https://www.ppsloan.org/publications/StupidSH36.pdf
41834 */
41835
41836// 3-band SH defined by 9 coefficients
41837
41838class SphericalHarmonics3 {
41839
41840	constructor() {
41841
41842		this.isSphericalHarmonics3 = true;
41843
41844		this.coefficients = [];
41845
41846		for ( let i = 0; i < 9; i ++ ) {
41847
41848			this.coefficients.push( new Vector3() );
41849
41850		}
41851
41852	}
41853
41854	set( coefficients ) {
41855
41856		for ( let i = 0; i < 9; i ++ ) {
41857
41858			this.coefficients[ i ].copy( coefficients[ i ] );
41859
41860		}
41861
41862		return this;
41863
41864	}
41865
41866	zero() {
41867
41868		for ( let i = 0; i < 9; i ++ ) {
41869
41870			this.coefficients[ i ].set( 0, 0, 0 );
41871
41872		}
41873
41874		return this;
41875
41876	}
41877
41878	// get the radiance in the direction of the normal
41879	// target is a Vector3
41880	getAt( normal, target ) {
41881
41882		// normal is assumed to be unit length
41883
41884		const x = normal.x, y = normal.y, z = normal.z;
41885
41886		const coeff = this.coefficients;
41887
41888		// band 0
41889		target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
41890
41891		// band 1
41892		target.addScaledVector( coeff[ 1 ], 0.488603 * y );
41893		target.addScaledVector( coeff[ 2 ], 0.488603 * z );
41894		target.addScaledVector( coeff[ 3 ], 0.488603 * x );
41895
41896		// band 2
41897		target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
41898		target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
41899		target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
41900		target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
41901		target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
41902
41903		return target;
41904
41905	}
41906
41907	// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
41908	// target is a Vector3
41909	// https://graphics.stanford.edu/papers/envmap/envmap.pdf
41910	getIrradianceAt( normal, target ) {
41911
41912		// normal is assumed to be unit length
41913
41914		const x = normal.x, y = normal.y, z = normal.z;
41915
41916		const coeff = this.coefficients;
41917
41918		// band 0
41919		target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
41920
41921		// band 1
41922		target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
41923		target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
41924		target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
41925
41926		// band 2
41927		target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
41928		target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
41929		target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
41930		target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
41931		target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
41932
41933		return target;
41934
41935	}
41936
vendor: 38,021 bytes, lines 41937-43558
41937	add( sh ) {
41938
41939		for ( let i = 0; i < 9; i ++ ) {
41940
41941			this.coefficients[ i ].add( sh.coefficients[ i ] );
41942
41943		}
41944
41945		return this;
41946
41947	}
41948
41949	addScaledSH( sh, s ) {
41950
41951		for ( let i = 0; i < 9; i ++ ) {
41952
41953			this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
41954
41955		}
41956
41957		return this;
41958
41959	}
41960
41961	scale( s ) {
41962
41963		for ( let i = 0; i < 9; i ++ ) {
41964
41965			this.coefficients[ i ].multiplyScalar( s );
41966
41967		}
41968
41969		return this;
41970
41971	}
41972
41973	lerp( sh, alpha ) {
41974
41975		for ( let i = 0; i < 9; i ++ ) {
41976
41977			this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
41978
41979		}
41980
41981		return this;
41982
41983	}
41984
41985	equals( sh ) {
41986
41987		for ( let i = 0; i < 9; i ++ ) {
41988
41989			if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
41990
41991				return false;
41992
41993			}
41994
41995		}
41996
41997		return true;
41998
41999	}
42000
42001	copy( sh ) {
42002
42003		return this.set( sh.coefficients );
42004
42005	}
42006
42007	clone() {
42008
42009		return new this.constructor().copy( this );
42010
42011	}
42012
42013	fromArray( array, offset = 0 ) {
42014
42015		const coefficients = this.coefficients;
42016
42017		for ( let i = 0; i < 9; i ++ ) {
42018
42019			coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
42020
42021		}
42022
42023		return this;
42024
42025	}
42026
42027	toArray( array = [], offset = 0 ) {
42028
42029		const coefficients = this.coefficients;
42030
42031		for ( let i = 0; i < 9; i ++ ) {
42032
42033			coefficients[ i ].toArray( array, offset + ( i * 3 ) );
42034
42035		}
42036
42037		return array;
42038
42039	}
42040
42041	// evaluate the basis functions
42042	// shBasis is an Array[ 9 ]
42043	static getBasisAt( normal, shBasis ) {
42044
42045		// normal is assumed to be unit length
42046
42047		const x = normal.x, y = normal.y, z = normal.z;
42048
42049		// band 0
42050		shBasis[ 0 ] = 0.282095;
42051
42052		// band 1
42053		shBasis[ 1 ] = 0.488603 * y;
42054		shBasis[ 2 ] = 0.488603 * z;
42055		shBasis[ 3 ] = 0.488603 * x;
42056
42057		// band 2
42058		shBasis[ 4 ] = 1.092548 * x * y;
42059		shBasis[ 5 ] = 1.092548 * y * z;
42060		shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
42061		shBasis[ 7 ] = 1.092548 * x * z;
42062		shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
42063
42064	}
42065
42066}
42067
42068class LightProbe extends Light {
42069
42070	constructor( sh = new SphericalHarmonics3(), intensity = 1 ) {
42071
42072		super( undefined, intensity );
42073
42074		this.isLightProbe = true;
42075
42076		this.sh = sh;
42077
42078	}
42079
42080	copy( source ) {
42081
42082		super.copy( source );
42083
42084		this.sh.copy( source.sh );
42085
42086		return this;
42087
42088	}
42089
42090	fromJSON( json ) {
42091
42092		this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
42093		this.sh.fromArray( json.sh );
42094
42095		return this;
42096
42097	}
42098
42099	toJSON( meta ) {
42100
42101		const data = super.toJSON( meta );
42102
42103		data.object.sh = this.sh.toArray();
42104
42105		return data;
42106
42107	}
42108
42109}
42110
42111class MaterialLoader extends Loader {
42112
42113	constructor( manager ) {
42114
42115		super( manager );
42116		this.textures = {};
42117
42118	}
42119
42120	load( url, onLoad, onProgress, onError ) {
42121
42122		const scope = this;
42123
42124		const loader = new FileLoader( scope.manager );
42125		loader.setPath( scope.path );
42126		loader.setRequestHeader( scope.requestHeader );
42127		loader.setWithCredentials( scope.withCredentials );
42128		loader.load( url, function ( text ) {
42129
42130			try {
42131
42132				onLoad( scope.parse( JSON.parse( text ) ) );
42133
42134			} catch ( e ) {
42135
42136				if ( onError ) {
42137
42138					onError( e );
42139
42140				} else {
42141
42142					console.error( e );
42143
42144				}
42145
42146				scope.manager.itemError( url );
42147
42148			}
42149
42150		}, onProgress, onError );
42151
42152	}
42153
42154	parse( json ) {
42155
42156		const textures = this.textures;
42157
42158		function getTexture( name ) {
42159
42160			if ( textures[ name ] === undefined ) {
42161
42162				console.warn( 'THREE.MaterialLoader: Undefined texture', name );
42163
42164			}
42165
42166			return textures[ name ];
42167
42168		}
42169
42170		const material = MaterialLoader.createMaterialFromType( json.type );
42171
42172		if ( json.uuid !== undefined ) material.uuid = json.uuid;
42173		if ( json.name !== undefined ) material.name = json.name;
42174		if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
42175		if ( json.roughness !== undefined ) material.roughness = json.roughness;
42176		if ( json.metalness !== undefined ) material.metalness = json.metalness;
42177		if ( json.sheen !== undefined ) material.sheen = json.sheen;
42178		if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor );
42179		if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness;
42180		if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
42181		if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
42182		if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity;
42183		if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor );
42184		if ( json.shininess !== undefined ) material.shininess = json.shininess;
42185		if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
42186		if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
42187		if ( json.iridescence !== undefined ) material.iridescence = json.iridescence;
42188		if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR;
42189		if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange;
42190		if ( json.transmission !== undefined ) material.transmission = json.transmission;
42191		if ( json.thickness !== undefined ) material.thickness = json.thickness;
42192		if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance;
42193		if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor );
42194		if ( json.fog !== undefined ) material.fog = json.fog;
42195		if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
42196		if ( json.blending !== undefined ) material.blending = json.blending;
42197		if ( json.combine !== undefined ) material.combine = json.combine;
42198		if ( json.side !== undefined ) material.side = json.side;
42199		if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide;
42200		if ( json.opacity !== undefined ) material.opacity = json.opacity;
42201		if ( json.transparent !== undefined ) material.transparent = json.transparent;
42202		if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
42203		if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
42204		if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
42205		if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
42206
42207		if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
42208		if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
42209		if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
42210		if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
42211		if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
42212		if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
42213		if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
42214		if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
42215
42216		if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
42217		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
42218		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
42219		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
42220
42221		if ( json.rotation !== undefined ) material.rotation = json.rotation;
42222
42223		if ( json.linewidth !== 1 ) material.linewidth = json.linewidth;
42224		if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
42225		if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
42226		if ( json.scale !== undefined ) material.scale = json.scale;
42227
42228		if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
42229		if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
42230		if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
42231
42232		if ( json.dithering !== undefined ) material.dithering = json.dithering;
42233
42234		if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage;
42235		if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha;
42236		if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass;
42237
42238		if ( json.visible !== undefined ) material.visible = json.visible;
42239
42240		if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
42241
42242		if ( json.userData !== undefined ) material.userData = json.userData;
42243
42244		if ( json.vertexColors !== undefined ) {
42245
42246			if ( typeof json.vertexColors === 'number' ) {
42247
42248				material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
42249
42250			} else {
42251
42252				material.vertexColors = json.vertexColors;
42253
42254			}
42255
42256		}
42257
42258		// Shader Material
42259
42260		if ( json.uniforms !== undefined ) {
42261
42262			for ( const name in json.uniforms ) {
42263
42264				const uniform = json.uniforms[ name ];
42265
42266				material.uniforms[ name ] = {};
42267
42268				switch ( uniform.type ) {
42269
42270					case 't':
42271						material.uniforms[ name ].value = getTexture( uniform.value );
42272						break;
42273
42274					case 'c':
42275						material.uniforms[ name ].value = new Color().setHex( uniform.value );
42276						break;
42277
42278					case 'v2':
42279						material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
42280						break;
42281
42282					case 'v3':
42283						material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
42284						break;
42285
42286					case 'v4':
42287						material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
42288						break;
42289
42290					case 'm3':
42291						material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
42292						break;
42293
42294					case 'm4':
42295						material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
42296						break;
42297
42298					default:
42299						material.uniforms[ name ].value = uniform.value;
42300
42301				}
42302
42303			}
42304
42305		}
42306
42307		if ( json.defines !== undefined ) material.defines = json.defines;
42308		if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
42309		if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
42310		if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion;
42311
42312		if ( json.extensions !== undefined ) {
42313
42314			for ( const key in json.extensions ) {
42315
42316				material.extensions[ key ] = json.extensions[ key ];
42317
42318			}
42319
42320		}
42321
42322		// for PointsMaterial
42323
42324		if ( json.size !== undefined ) material.size = json.size;
42325		if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
42326
42327		// maps
42328
42329		if ( json.map !== undefined ) material.map = getTexture( json.map );
42330		if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
42331
42332		if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
42333
42334		if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
42335		if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
42336
42337		if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
42338		if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
42339		if ( json.normalScale !== undefined ) {
42340
42341			let normalScale = json.normalScale;
42342
42343			if ( Array.isArray( normalScale ) === false ) {
42344
42345				// Blender exporter used to export a scalar. See #7459
42346
42347				normalScale = [ normalScale, normalScale ];
42348
42349			}
42350
42351			material.normalScale = new Vector2().fromArray( normalScale );
42352
42353		}
42354
42355		if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
42356		if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
42357		if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
42358
42359		if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
42360		if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
42361
42362		if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
42363		if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
42364
42365		if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
42366		if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap );
42367		if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap );
42368
42369		if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
42370		if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
42371
42372		if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
42373		if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
42374
42375		if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
42376		if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
42377
42378		if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
42379		if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
42380
42381		if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
42382
42383		if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
42384		if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
42385		if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
42386		if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
42387
42388		if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap );
42389		if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap );
42390
42391		if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
42392		if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap );
42393
42394		if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap );
42395		if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap );
42396
42397		return material;
42398
42399	}
42400
42401	setTextures( value ) {
42402
42403		this.textures = value;
42404		return this;
42405
42406	}
42407
42408	static createMaterialFromType( type ) {
42409
42410		const materialLib = {
42411			ShadowMaterial,
42412			SpriteMaterial,
42413			RawShaderMaterial,
42414			ShaderMaterial,
42415			PointsMaterial,
42416			MeshPhysicalMaterial,
42417			MeshStandardMaterial,
42418			MeshPhongMaterial,
42419			MeshToonMaterial,
42420			MeshNormalMaterial,
42421			MeshLambertMaterial,
42422			MeshDepthMaterial,
42423			MeshDistanceMaterial,
42424			MeshBasicMaterial,
42425			MeshMatcapMaterial,
42426			LineDashedMaterial,
42427			LineBasicMaterial,
42428			Material
42429		};
42430
42431		return new materialLib[ type ]();
42432
42433	}
42434
42435}
42436
42437class LoaderUtils {
42438
42439	static decodeText( array ) {
42440
42441		if ( typeof TextDecoder !== 'undefined' ) {
42442
42443			return new TextDecoder().decode( array );
42444
42445		}
42446
42447		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
42448		// throws a "maximum call stack size exceeded" error for large arrays.
42449
42450		let s = '';
42451
42452		for ( let i = 0, il = array.length; i < il; i ++ ) {
42453
42454			// Implicitly assumes little-endian.
42455			s += String.fromCharCode( array[ i ] );
42456
42457		}
42458
42459		try {
42460
42461			// merges multi-byte utf-8 characters.
42462
42463			return decodeURIComponent( escape( s ) );
42464
42465		} catch ( e ) { // see #16358
42466
42467			return s;
42468
42469		}
42470
42471	}
42472
42473	static extractUrlBase( url ) {
42474
42475		const index = url.lastIndexOf( '/' );
42476
42477		if ( index === - 1 ) return './';
42478
42479		return url.slice( 0, index + 1 );
42480
42481	}
42482
42483	static resolveURL( url, path ) {
42484
42485		// Invalid URL
42486		if ( typeof url !== 'string' || url === '' ) return '';
42487
42488		// Host Relative URL
42489		if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
42490
42491			path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
42492
42493		}
42494
42495		// Absolute URL http://,https://,//
42496		if ( /^(https?:)?\/\//i.test( url ) ) return url;
42497
42498		// Data URI
42499		if ( /^data:.*,.*$/i.test( url ) ) return url;
42500
42501		// Blob URL
42502		if ( /^blob:.*$/i.test( url ) ) return url;
42503
42504		// Relative URL
42505		return path + url;
42506
42507	}
42508
42509}
42510
42511class InstancedBufferGeometry extends BufferGeometry {
42512
42513	constructor() {
42514
42515		super();
42516
42517		this.isInstancedBufferGeometry = true;
42518
42519		this.type = 'InstancedBufferGeometry';
42520		this.instanceCount = Infinity;
42521
42522	}
42523
42524	copy( source ) {
42525
42526		super.copy( source );
42527
42528		this.instanceCount = source.instanceCount;
42529
42530		return this;
42531
42532	}
42533
42534	toJSON() {
42535
42536		const data = super.toJSON();
42537
42538		data.instanceCount = this.instanceCount;
42539
42540		data.isInstancedBufferGeometry = true;
42541
42542		return data;
42543
42544	}
42545
42546}
42547
42548class BufferGeometryLoader extends Loader {
42549
42550	constructor( manager ) {
42551
42552		super( manager );
42553
42554	}
42555
42556	load( url, onLoad, onProgress, onError ) {
42557
42558		const scope = this;
42559
42560		const loader = new FileLoader( scope.manager );
42561		loader.setPath( scope.path );
42562		loader.setRequestHeader( scope.requestHeader );
42563		loader.setWithCredentials( scope.withCredentials );
42564		loader.load( url, function ( text ) {
42565
42566			try {
42567
42568				onLoad( scope.parse( JSON.parse( text ) ) );
42569
42570			} catch ( e ) {
42571
42572				if ( onError ) {
42573
42574					onError( e );
42575
42576				} else {
42577
42578					console.error( e );
42579
42580				}
42581
42582				scope.manager.itemError( url );
42583
42584			}
42585
42586		}, onProgress, onError );
42587
42588	}
42589
42590	parse( json ) {
42591
42592		const interleavedBufferMap = {};
42593		const arrayBufferMap = {};
42594
42595		function getInterleavedBuffer( json, uuid ) {
42596
42597			if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
42598
42599			const interleavedBuffers = json.interleavedBuffers;
42600			const interleavedBuffer = interleavedBuffers[ uuid ];
42601
42602			const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
42603
42604			const array = getTypedArray( interleavedBuffer.type, buffer );
42605			const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
42606			ib.uuid = interleavedBuffer.uuid;
42607
42608			interleavedBufferMap[ uuid ] = ib;
42609
42610			return ib;
42611
42612		}
42613
42614		function getArrayBuffer( json, uuid ) {
42615
42616			if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
42617
42618			const arrayBuffers = json.arrayBuffers;
42619			const arrayBuffer = arrayBuffers[ uuid ];
42620
42621			const ab = new Uint32Array( arrayBuffer ).buffer;
42622
42623			arrayBufferMap[ uuid ] = ab;
42624
42625			return ab;
42626
42627		}
42628
42629		const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
42630
42631		const index = json.data.index;
42632
42633		if ( index !== undefined ) {
42634
42635			const typedArray = getTypedArray( index.type, index.array );
42636			geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
42637
42638		}
42639
42640		const attributes = json.data.attributes;
42641
42642		for ( const key in attributes ) {
42643
42644			const attribute = attributes[ key ];
42645			let bufferAttribute;
42646
42647			if ( attribute.isInterleavedBufferAttribute ) {
42648
42649				const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
42650				bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
42651
42652			} else {
42653
42654				const typedArray = getTypedArray( attribute.type, attribute.array );
42655				const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
42656				bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
42657
42658			}
42659
42660			if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
42661			if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
42662
42663			if ( attribute.updateRange !== undefined ) {
42664
42665				bufferAttribute.updateRange.offset = attribute.updateRange.offset;
42666				bufferAttribute.updateRange.count = attribute.updateRange.count;
42667
42668			}
42669
42670			geometry.setAttribute( key, bufferAttribute );
42671
42672		}
42673
42674		const morphAttributes = json.data.morphAttributes;
42675
42676		if ( morphAttributes ) {
42677
42678			for ( const key in morphAttributes ) {
42679
42680				const attributeArray = morphAttributes[ key ];
42681
42682				const array = [];
42683
42684				for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
42685
42686					const attribute = attributeArray[ i ];
42687					let bufferAttribute;
42688
42689					if ( attribute.isInterleavedBufferAttribute ) {
42690
42691						const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
42692						bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
42693
42694					} else {
42695
42696						const typedArray = getTypedArray( attribute.type, attribute.array );
42697						bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
42698
42699					}
42700
42701					if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
42702					array.push( bufferAttribute );
42703
42704				}
42705
42706				geometry.morphAttributes[ key ] = array;
42707
42708			}
42709
42710		}
42711
42712		const morphTargetsRelative = json.data.morphTargetsRelative;
42713
42714		if ( morphTargetsRelative ) {
42715
42716			geometry.morphTargetsRelative = true;
42717
42718		}
42719
42720		const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
42721
42722		if ( groups !== undefined ) {
42723
42724			for ( let i = 0, n = groups.length; i !== n; ++ i ) {
42725
42726				const group = groups[ i ];
42727
42728				geometry.addGroup( group.start, group.count, group.materialIndex );
42729
42730			}
42731
42732		}
42733
42734		const boundingSphere = json.data.boundingSphere;
42735
42736		if ( boundingSphere !== undefined ) {
42737
42738			const center = new Vector3();
42739
42740			if ( boundingSphere.center !== undefined ) {
42741
42742				center.fromArray( boundingSphere.center );
42743
42744			}
42745
42746			geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
42747
42748		}
42749
42750		if ( json.name ) geometry.name = json.name;
42751		if ( json.userData ) geometry.userData = json.userData;
42752
42753		return geometry;
42754
42755	}
42756
42757}
42758
42759class ObjectLoader extends Loader {
42760
42761	constructor( manager ) {
42762
42763		super( manager );
42764
42765	}
42766
42767	load( url, onLoad, onProgress, onError ) {
42768
42769		const scope = this;
42770
42771		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
42772		this.resourcePath = this.resourcePath || path;
42773
42774		const loader = new FileLoader( this.manager );
42775		loader.setPath( this.path );
42776		loader.setRequestHeader( this.requestHeader );
42777		loader.setWithCredentials( this.withCredentials );
42778		loader.load( url, function ( text ) {
42779
42780			let json = null;
42781
42782			try {
42783
42784				json = JSON.parse( text );
42785
42786			} catch ( error ) {
42787
42788				if ( onError !== undefined ) onError( error );
42789
42790				console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
42791
42792				return;
42793
42794			}
42795
42796			const metadata = json.metadata;
42797
42798			if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
42799
42800				if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) );
42801
42802				console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
42803				return;
42804
42805			}
42806
42807			scope.parse( json, onLoad );
42808
42809		}, onProgress, onError );
42810
42811	}
42812
42813	async loadAsync( url, onProgress ) {
42814
42815		const scope = this;
42816
42817		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
42818		this.resourcePath = this.resourcePath || path;
42819
42820		const loader = new FileLoader( this.manager );
42821		loader.setPath( this.path );
42822		loader.setRequestHeader( this.requestHeader );
42823		loader.setWithCredentials( this.withCredentials );
42824
42825		const text = await loader.loadAsync( url, onProgress );
42826
42827		const json = JSON.parse( text );
42828
42829		const metadata = json.metadata;
42830
42831		if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
42832
42833			throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url );
42834
42835		}
42836
42837		return await scope.parseAsync( json );
42838
42839	}
42840
42841	parse( json, onLoad ) {
42842
42843		const animations = this.parseAnimations( json.animations );
42844		const shapes = this.parseShapes( json.shapes );
42845		const geometries = this.parseGeometries( json.geometries, shapes );
42846
42847		const images = this.parseImages( json.images, function () {
42848
42849			if ( onLoad !== undefined ) onLoad( object );
42850
42851		} );
42852
42853		const textures = this.parseTextures( json.textures, images );
42854		const materials = this.parseMaterials( json.materials, textures );
42855
42856		const object = this.parseObject( json.object, geometries, materials, textures, animations );
42857		const skeletons = this.parseSkeletons( json.skeletons, object );
42858
42859		this.bindSkeletons( object, skeletons );
42860
42861		//
42862
42863		if ( onLoad !== undefined ) {
42864
42865			let hasImages = false;
42866
42867			for ( const uuid in images ) {
42868
42869				if ( images[ uuid ].data instanceof HTMLImageElement ) {
42870
42871					hasImages = true;
42872					break;
42873
42874				}
42875
42876			}
42877
42878			if ( hasImages === false ) onLoad( object );
42879
42880		}
42881
42882		return object;
42883
42884	}
42885
42886	async parseAsync( json ) {
42887
42888		const animations = this.parseAnimations( json.animations );
42889		const shapes = this.parseShapes( json.shapes );
42890		const geometries = this.parseGeometries( json.geometries, shapes );
42891
42892		const images = await this.parseImagesAsync( json.images );
42893
42894		const textures = this.parseTextures( json.textures, images );
42895		const materials = this.parseMaterials( json.materials, textures );
42896
42897		const object = this.parseObject( json.object, geometries, materials, textures, animations );
42898		const skeletons = this.parseSkeletons( json.skeletons, object );
42899
42900		this.bindSkeletons( object, skeletons );
42901
42902		return object;
42903
42904	}
42905
42906	parseShapes( json ) {
42907
42908		const shapes = {};
42909
42910		if ( json !== undefined ) {
42911
42912			for ( let i = 0, l = json.length; i < l; i ++ ) {
42913
42914				const shape = new Shape().fromJSON( json[ i ] );
42915
42916				shapes[ shape.uuid ] = shape;
42917
42918			}
42919
42920		}
42921
42922		return shapes;
42923
42924	}
42925
42926	parseSkeletons( json, object ) {
42927
42928		const skeletons = {};
42929		const bones = {};
42930
42931		// generate bone lookup table
42932
42933		object.traverse( function ( child ) {
42934
42935			if ( child.isBone ) bones[ child.uuid ] = child;
42936
42937		} );
42938
42939		// create skeletons
42940
42941		if ( json !== undefined ) {
42942
42943			for ( let i = 0, l = json.length; i < l; i ++ ) {
42944
42945				const skeleton = new Skeleton().fromJSON( json[ i ], bones );
42946
42947				skeletons[ skeleton.uuid ] = skeleton;
42948
42949			}
42950
42951		}
42952
42953		return skeletons;
42954
42955	}
42956
42957	parseGeometries( json, shapes ) {
42958
42959		const geometries = {};
42960
42961		if ( json !== undefined ) {
42962
42963			const bufferGeometryLoader = new BufferGeometryLoader();
42964
42965			for ( let i = 0, l = json.length; i < l; i ++ ) {
42966
42967				let geometry;
42968				const data = json[ i ];
42969
42970				switch ( data.type ) {
42971
42972					case 'BufferGeometry':
42973					case 'InstancedBufferGeometry':
42974
42975						geometry = bufferGeometryLoader.parse( data );
42976						break;
42977
42978					default:
42979
42980						if ( data.type in Geometries ) {
42981
42982							geometry = Geometries[ data.type ].fromJSON( data, shapes );
42983
42984						} else {
42985
42986							console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` );
42987
42988						}
42989
42990				}
42991
42992				geometry.uuid = data.uuid;
42993
42994				if ( data.name !== undefined ) geometry.name = data.name;
42995				if ( data.userData !== undefined ) geometry.userData = data.userData;
42996
42997				geometries[ data.uuid ] = geometry;
42998
42999			}
43000
43001		}
43002
43003		return geometries;
43004
43005	}
43006
43007	parseMaterials( json, textures ) {
43008
43009		const cache = {}; // MultiMaterial
43010		const materials = {};
43011
43012		if ( json !== undefined ) {
43013
43014			const loader = new MaterialLoader();
43015			loader.setTextures( textures );
43016
43017			for ( let i = 0, l = json.length; i < l; i ++ ) {
43018
43019				const data = json[ i ];
43020
43021				if ( cache[ data.uuid ] === undefined ) {
43022
43023					cache[ data.uuid ] = loader.parse( data );
43024
43025				}
43026
43027				materials[ data.uuid ] = cache[ data.uuid ];
43028
43029			}
43030
43031		}
43032
43033		return materials;
43034
43035	}
43036
43037	parseAnimations( json ) {
43038
43039		const animations = {};
43040
43041		if ( json !== undefined ) {
43042
43043			for ( let i = 0; i < json.length; i ++ ) {
43044
43045				const data = json[ i ];
43046
43047				const clip = AnimationClip.parse( data );
43048
43049				animations[ clip.uuid ] = clip;
43050
43051			}
43052
43053		}
43054
43055		return animations;
43056
43057	}
43058
43059	parseImages( json, onLoad ) {
43060
43061		const scope = this;
43062		const images = {};
43063
43064		let loader;
43065
43066		function loadImage( url ) {
43067
43068			scope.manager.itemStart( url );
43069
43070			return loader.load( url, function () {
43071
43072				scope.manager.itemEnd( url );
43073
43074			}, undefined, function () {
43075
43076				scope.manager.itemError( url );
43077				scope.manager.itemEnd( url );
43078
43079			} );
43080
43081		}
43082
43083		function deserializeImage( image ) {
43084
43085			if ( typeof image === 'string' ) {
43086
43087				const url = image;
43088
43089				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
43090
43091				return loadImage( path );
43092
43093			} else {
43094
43095				if ( image.data ) {
43096
43097					return {
43098						data: getTypedArray( image.type, image.data ),
43099						width: image.width,
43100						height: image.height
43101					};
43102
43103				} else {
43104
43105					return null;
43106
43107				}
43108
43109			}
43110
43111		}
43112
43113		if ( json !== undefined && json.length > 0 ) {
43114
43115			const manager = new LoadingManager( onLoad );
43116
43117			loader = new ImageLoader( manager );
43118			loader.setCrossOrigin( this.crossOrigin );
43119
43120			for ( let i = 0, il = json.length; i < il; i ++ ) {
43121
43122				const image = json[ i ];
43123				const url = image.url;
43124
43125				if ( Array.isArray( url ) ) {
43126
43127					// load array of images e.g CubeTexture
43128
43129					const imageArray = [];
43130
43131					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
43132
43133						const currentUrl = url[ j ];
43134
43135						const deserializedImage = deserializeImage( currentUrl );
43136
43137						if ( deserializedImage !== null ) {
43138
43139							if ( deserializedImage instanceof HTMLImageElement ) {
43140
43141								imageArray.push( deserializedImage );
43142
43143							} else {
43144
43145								// special case: handle array of data textures for cube textures
43146
43147								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
43148
43149							}
43150
43151						}
43152
43153					}
43154
43155					images[ image.uuid ] = new Source( imageArray );
43156
43157				} else {
43158
43159					// load single image
43160
43161					const deserializedImage = deserializeImage( image.url );
43162					images[ image.uuid ] = new Source( deserializedImage );
43163
43164
43165				}
43166
43167			}
43168
43169		}
43170
43171		return images;
43172
43173	}
43174
43175	async parseImagesAsync( json ) {
43176
43177		const scope = this;
43178		const images = {};
43179
43180		let loader;
43181
43182		async function deserializeImage( image ) {
43183
43184			if ( typeof image === 'string' ) {
43185
43186				const url = image;
43187
43188				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
43189
43190				return await loader.loadAsync( path );
43191
43192			} else {
43193
43194				if ( image.data ) {
43195
43196					return {
43197						data: getTypedArray( image.type, image.data ),
43198						width: image.width,
43199						height: image.height
43200					};
43201
43202				} else {
43203
43204					return null;
43205
43206				}
43207
43208			}
43209
43210		}
43211
43212		if ( json !== undefined && json.length > 0 ) {
43213
43214			loader = new ImageLoader( this.manager );
43215			loader.setCrossOrigin( this.crossOrigin );
43216
43217			for ( let i = 0, il = json.length; i < il; i ++ ) {
43218
43219				const image = json[ i ];
43220				const url = image.url;
43221
43222				if ( Array.isArray( url ) ) {
43223
43224					// load array of images e.g CubeTexture
43225
43226					const imageArray = [];
43227
43228					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
43229
43230						const currentUrl = url[ j ];
43231
43232						const deserializedImage = await deserializeImage( currentUrl );
43233
43234						if ( deserializedImage !== null ) {
43235
43236							if ( deserializedImage instanceof HTMLImageElement ) {
43237
43238								imageArray.push( deserializedImage );
43239
43240							} else {
43241
43242								// special case: handle array of data textures for cube textures
43243
43244								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
43245
43246							}
43247
43248						}
43249
43250					}
43251
43252					images[ image.uuid ] = new Source( imageArray );
43253
43254				} else {
43255
43256					// load single image
43257
43258					const deserializedImage = await deserializeImage( image.url );
43259					images[ image.uuid ] = new Source( deserializedImage );
43260
43261				}
43262
43263			}
43264
43265		}
43266
43267		return images;
43268
43269	}
43270
43271	parseTextures( json, images ) {
43272
43273		function parseConstant( value, type ) {
43274
43275			if ( typeof value === 'number' ) return value;
43276
43277			console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
43278
43279			return type[ value ];
43280
43281		}
43282
43283		const textures = {};
43284
43285		if ( json !== undefined ) {
43286
43287			for ( let i = 0, l = json.length; i < l; i ++ ) {
43288
43289				const data = json[ i ];
43290
43291				if ( data.image === undefined ) {
43292
43293					console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
43294
43295				}
43296
43297				if ( images[ data.image ] === undefined ) {
43298
43299					console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
43300
43301				}
43302
43303				const source = images[ data.image ];
43304				const image = source.data;
43305
43306				let texture;
43307
43308				if ( Array.isArray( image ) ) {
43309
43310					texture = new CubeTexture();
43311
43312					if ( image.length === 6 ) texture.needsUpdate = true;
43313
43314				} else {
43315
43316					if ( image && image.data ) {
43317
43318						texture = new DataTexture();
43319
43320					} else {
43321
43322						texture = new Texture();
43323
43324					}
43325
43326					if ( image ) texture.needsUpdate = true; // textures can have undefined image data
43327
43328				}
43329
43330				texture.source = source;
43331
43332				texture.uuid = data.uuid;
43333
43334				if ( data.name !== undefined ) texture.name = data.name;
43335
43336				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
43337
43338				if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
43339				if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
43340				if ( data.center !== undefined ) texture.center.fromArray( data.center );
43341				if ( data.rotation !== undefined ) texture.rotation = data.rotation;
43342
43343				if ( data.wrap !== undefined ) {
43344
43345					texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
43346					texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
43347
43348				}
43349
43350				if ( data.format !== undefined ) texture.format = data.format;
43351				if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat;
43352				if ( data.type !== undefined ) texture.type = data.type;
43353				if ( data.encoding !== undefined ) texture.encoding = data.encoding;
43354
43355				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
43356				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
43357				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
43358
43359				if ( data.flipY !== undefined ) texture.flipY = data.flipY;
43360
43361				if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps;
43362				if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
43363				if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
43364
43365				if ( data.userData !== undefined ) texture.userData = data.userData;
43366
43367				textures[ data.uuid ] = texture;
43368
43369			}
43370
43371		}
43372
43373		return textures;
43374
43375	}
43376
43377	parseObject( data, geometries, materials, textures, animations ) {
43378
43379		let object;
43380
43381		function getGeometry( name ) {
43382
43383			if ( geometries[ name ] === undefined ) {
43384
43385				console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
43386
43387			}
43388
43389			return geometries[ name ];
43390
43391		}
43392
43393		function getMaterial( name ) {
43394
43395			if ( name === undefined ) return undefined;
43396
43397			if ( Array.isArray( name ) ) {
43398
43399				const array = [];
43400
43401				for ( let i = 0, l = name.length; i < l; i ++ ) {
43402
43403					const uuid = name[ i ];
43404
43405					if ( materials[ uuid ] === undefined ) {
43406
43407						console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
43408
43409					}
43410
43411					array.push( materials[ uuid ] );
43412
43413				}
43414
43415				return array;
43416
43417			}
43418
43419			if ( materials[ name ] === undefined ) {
43420
43421				console.warn( 'THREE.ObjectLoader: Undefined material', name );
43422
43423			}
43424
43425			return materials[ name ];
43426
43427		}
43428
43429		function getTexture( uuid ) {
43430
43431			if ( textures[ uuid ] === undefined ) {
43432
43433				console.warn( 'THREE.ObjectLoader: Undefined texture', uuid );
43434
43435			}
43436
43437			return textures[ uuid ];
43438
43439		}
43440
43441		let geometry, material;
43442
43443		switch ( data.type ) {
43444
43445			case 'Scene':
43446
43447				object = new Scene();
43448
43449				if ( data.background !== undefined ) {
43450
43451					if ( Number.isInteger( data.background ) ) {
43452
43453						object.background = new Color( data.background );
43454
43455					} else {
43456
43457						object.background = getTexture( data.background );
43458
43459					}
43460
43461				}
43462
43463				if ( data.environment !== undefined ) {
43464
43465					object.environment = getTexture( data.environment );
43466
43467				}
43468
43469				if ( data.fog !== undefined ) {
43470
43471					if ( data.fog.type === 'Fog' ) {
43472
43473						object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
43474
43475					} else if ( data.fog.type === 'FogExp2' ) {
43476
43477						object.fog = new FogExp2( data.fog.color, data.fog.density );
43478
43479					}
43480
43481				}
43482
43483				if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness;
43484				if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity;
43485
43486				break;
43487
43488			case 'PerspectiveCamera':
43489
43490				object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
43491
43492				if ( data.focus !== undefined ) object.focus = data.focus;
43493				if ( data.zoom !== undefined ) object.zoom = data.zoom;
43494				if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
43495				if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
43496				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
43497
43498				break;
43499
43500			case 'OrthographicCamera':
43501
43502				object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
43503
43504				if ( data.zoom !== undefined ) object.zoom = data.zoom;
43505				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
43506
43507				break;
43508
43509			case 'AmbientLight':
43510
43511				object = new AmbientLight( data.color, data.intensity );
43512
43513				break;
43514
43515			case 'DirectionalLight':
43516
43517				object = new DirectionalLight( data.color, data.intensity );
43518
43519				break;
43520
43521			case 'PointLight':
43522
43523				object = new PointLight( data.color, data.intensity, data.distance, data.decay );
43524
43525				break;
43526
43527			case 'RectAreaLight':
43528
43529				object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
43530
43531				break;
43532
43533			case 'SpotLight':
43534
43535				object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
43536
43537				break;
43538
43539			case 'HemisphereLight':
43540
43541				object = new HemisphereLight( data.color, data.groundColor, data.intensity );
43542
43543				break;
43544
43545			case 'LightProbe':
43546
43547				object = new LightProbe().fromJSON( data );
43548
43549				break;
43550
43551			case 'SkinnedMesh':
43552
43553				geometry = getGeometry( data.geometry );
43554			 	material = getMaterial( data.material );
43555
43556				object = new SkinnedMesh( geometry, material );
43557
43558				if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
vendor: 8,329 bytes, lines 43559-43930
43559				if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
43560				if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
43561
43562				break;
43563
43564			case 'Mesh':
43565
43566				geometry = getGeometry( data.geometry );
43567				material = getMaterial( data.material );
43568
43569				object = new Mesh( geometry, material );
43570
43571				break;
43572
43573			case 'InstancedMesh':
43574
43575				geometry = getGeometry( data.geometry );
43576				material = getMaterial( data.material );
43577				const count = data.count;
43578				const instanceMatrix = data.instanceMatrix;
43579				const instanceColor = data.instanceColor;
43580
43581				object = new InstancedMesh( geometry, material, count );
43582				object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
43583				if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
43584
43585				break;
43586
43587			case 'LOD':
43588
43589				object = new LOD();
43590
43591				break;
43592
43593			case 'Line':
43594
43595				object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
43596
43597				break;
43598
43599			case 'LineLoop':
43600
43601				object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
43602
43603				break;
43604
43605			case 'LineSegments':
43606
43607				object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
43608
43609				break;
43610
43611			case 'PointCloud':
43612			case 'Points':
43613
43614				object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
43615
43616				break;
43617
43618			case 'Sprite':
43619
43620				object = new Sprite( getMaterial( data.material ) );
43621
43622				break;
43623
43624			case 'Group':
43625
43626				object = new Group();
43627
43628				break;
43629
43630			case 'Bone':
43631
43632				object = new Bone();
43633
43634				break;
43635
43636			default:
43637
43638				object = new Object3D();
43639
43640		}
43641
43642		object.uuid = data.uuid;
43643
43644		if ( data.name !== undefined ) object.name = data.name;
43645
43646		if ( data.matrix !== undefined ) {
43647
43648			object.matrix.fromArray( data.matrix );
43649
43650			if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
43651			if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
43652
43653		} else {
43654
43655			if ( data.position !== undefined ) object.position.fromArray( data.position );
43656			if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
43657			if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
43658			if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
43659
43660		}
43661
43662		if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
43663		if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
43664
43665		if ( data.shadow ) {
43666
43667			if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
43668			if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
43669			if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
43670			if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
43671			if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
43672
43673		}
43674
43675		if ( data.visible !== undefined ) object.visible = data.visible;
43676		if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
43677		if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
43678		if ( data.userData !== undefined ) object.userData = data.userData;
43679		if ( data.layers !== undefined ) object.layers.mask = data.layers;
43680
43681		if ( data.children !== undefined ) {
43682
43683			const children = data.children;
43684
43685			for ( let i = 0; i < children.length; i ++ ) {
43686
43687				object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) );
43688
43689			}
43690
43691		}
43692
43693		if ( data.animations !== undefined ) {
43694
43695			const objectAnimations = data.animations;
43696
43697			for ( let i = 0; i < objectAnimations.length; i ++ ) {
43698
43699				const uuid = objectAnimations[ i ];
43700
43701				object.animations.push( animations[ uuid ] );
43702
43703			}
43704
43705		}
43706
43707		if ( data.type === 'LOD' ) {
43708
43709			if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
43710
43711			const levels = data.levels;
43712
43713			for ( let l = 0; l < levels.length; l ++ ) {
43714
43715				const level = levels[ l ];
43716				const child = object.getObjectByProperty( 'uuid', level.object );
43717
43718				if ( child !== undefined ) {
43719
43720					object.addLevel( child, level.distance, level.hysteresis );
43721
43722				}
43723
43724			}
43725
43726		}
43727
43728		return object;
43729
43730	}
43731
43732	bindSkeletons( object, skeletons ) {
43733
43734		if ( Object.keys( skeletons ).length === 0 ) return;
43735
43736		object.traverse( function ( child ) {
43737
43738			if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
43739
43740				const skeleton = skeletons[ child.skeleton ];
43741
43742				if ( skeleton === undefined ) {
43743
43744					console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton );
43745
43746				} else {
43747
43748					child.bind( skeleton, child.bindMatrix );
43749
43750				}
43751
43752			}
43753
43754		} );
43755
43756	}
43757
43758}
43759
43760const TEXTURE_MAPPING = {
43761	UVMapping: UVMapping,
43762	CubeReflectionMapping: CubeReflectionMapping,
43763	CubeRefractionMapping: CubeRefractionMapping,
43764	EquirectangularReflectionMapping: EquirectangularReflectionMapping,
43765	EquirectangularRefractionMapping: EquirectangularRefractionMapping,
43766	CubeUVReflectionMapping: CubeUVReflectionMapping
43767};
43768
43769const TEXTURE_WRAPPING = {
43770	RepeatWrapping: RepeatWrapping,
43771	ClampToEdgeWrapping: ClampToEdgeWrapping,
43772	MirroredRepeatWrapping: MirroredRepeatWrapping
43773};
43774
43775const TEXTURE_FILTER = {
43776	NearestFilter: NearestFilter,
43777	NearestMipmapNearestFilter: NearestMipmapNearestFilter,
43778	NearestMipmapLinearFilter: NearestMipmapLinearFilter,
43779	LinearFilter: LinearFilter,
43780	LinearMipmapNearestFilter: LinearMipmapNearestFilter,
43781	LinearMipmapLinearFilter: LinearMipmapLinearFilter
43782};
43783
43784class ImageBitmapLoader extends Loader {
43785
43786	constructor( manager ) {
43787
43788		super( manager );
43789
43790		this.isImageBitmapLoader = true;
43791
43792		if ( typeof createImageBitmap === 'undefined' ) {
43793
43794			console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
43795
43796		}
43797
43798		if ( typeof fetch === 'undefined' ) {
43799
43800			console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
43801
43802		}
43803
43804		this.options = { premultiplyAlpha: 'none' };
43805
43806	}
43807
43808	setOptions( options ) {
43809
43810		this.options = options;
43811
43812		return this;
43813
43814	}
43815
43816	load( url, onLoad, onProgress, onError ) {
43817
43818		if ( url === undefined ) url = '';
43819
43820		if ( this.path !== undefined ) url = this.path + url;
43821
43822		url = this.manager.resolveURL( url );
43823
43824		const scope = this;
43825
43826		const cached = Cache.get( url );
43827
43828		if ( cached !== undefined ) {
43829
43830			scope.manager.itemStart( url );
43831
43832			setTimeout( function () {
43833
43834				if ( onLoad ) onLoad( cached );
43835
43836				scope.manager.itemEnd( url );
43837
43838			}, 0 );
43839
43840			return cached;
43841
43842		}
43843
43844		const fetchOptions = {};
43845		fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
43846		fetchOptions.headers = this.requestHeader;
43847
43848		fetch( url, fetchOptions ).then( function ( res ) {
43849
43850			return res.blob();
43851
43852		} ).then( function ( blob ) {
43853
43854			return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) );
43855
43856		} ).then( function ( imageBitmap ) {
43857
43858			Cache.add( url, imageBitmap );
43859
43860			if ( onLoad ) onLoad( imageBitmap );
43861
43862			scope.manager.itemEnd( url );
43863
43864		} ).catch( function ( e ) {
43865
43866			if ( onError ) onError( e );
43867
43868			scope.manager.itemError( url );
43869			scope.manager.itemEnd( url );
43870
43871		} );
43872
43873		scope.manager.itemStart( url );
43874
43875	}
43876
43877}
43878
43879let _context;
43880
43881class AudioContext {
43882
43883	static getContext() {
43884
43885		if ( _context === undefined ) {
43886
43887			_context = new ( window.AudioContext || window.webkitAudioContext )();
43888
43889		}
43890
43891		return _context;
43892
43893	}
43894
43895	static setContext( value ) {
43896
43897		_context = value;
43898
43899	}
43900
43901}
43902
43903class AudioLoader extends Loader {
43904
43905	constructor( manager ) {
43906
43907		super( manager );
43908
43909	}
43910
43911	load( url, onLoad, onProgress, onError ) {
43912
43913		const scope = this;
43914
43915		const loader = new FileLoader( this.manager );
43916		loader.setResponseType( 'arraybuffer' );
43917		loader.setPath( this.path );
43918		loader.setRequestHeader( this.requestHeader );
43919		loader.setWithCredentials( this.withCredentials );
43920		loader.load( url, function ( buffer ) {
43921
43922			try {
43923
43924				// Create a copy of the buffer. The `decodeAudioData` method
43925				// detaches the buffer when complete, preventing reuse.
43926				const bufferCopy = buffer.slice( 0 );
43927
43928				const context = AudioContext.getContext();
43929				context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
43930
43931					onLoad( audioBuffer );
43932
43933				} );
43934
43935			} catch ( e ) {
43936
43937				if ( onError ) {
43938
43939					onError( e );
43940
43941				} else {
43942
43943					console.error( e );
43944
43945				}
43946
43947				scope.manager.itemError( url );
43948
43949			}
43950
43951		}, onProgress, onError );
43952
43953	}
43954
43955}
43956
43957class HemisphereLightProbe extends LightProbe {
43958
43959	constructor( skyColor, groundColor, intensity = 1 ) {
43960
43961		super( undefined, intensity );
43962
43963		this.isHemisphereLightProbe = true;
43964
43965		const color1 = new Color().set( skyColor );
43966		const color2 = new Color().set( groundColor );
43967
43968		const sky = new Vector3( color1.r, color1.g, color1.b );
43969		const ground = new Vector3( color2.r, color2.g, color2.b );
43970
43971		// without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
43972		const c0 = Math.sqrt( Math.PI );
43973		const c1 = c0 * Math.sqrt( 0.75 );
43974
43975		this.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
43976		this.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
43977
43978	}
43979
43980}
43981
43982class AmbientLightProbe extends LightProbe {
43983
43984	constructor( color, intensity = 1 ) {
43985
43986		super( undefined, intensity );
43987
43988		this.isAmbientLightProbe = true;
43989
43990		const color1 = new Color().set( color );
43991
43992		// without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
43993		this.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
43994
43995	}
43996
43997}
43998
43999const _eyeRight = /*@__PURE__*/ new Matrix4();
44000const _eyeLeft = /*@__PURE__*/ new Matrix4();
44001const _projectionMatrix = /*@__PURE__*/ new Matrix4();
44002
44003class StereoCamera {
44004
44005	constructor() {
44006
44007		this.type = 'StereoCamera';
44008
44009		this.aspect = 1;
44010
44011		this.eyeSep = 0.064;
44012
44013		this.cameraL = new PerspectiveCamera();
44014		this.cameraL.layers.enable( 1 );
44015		this.cameraL.matrixAutoUpdate = false;
44016
44017		this.cameraR = new PerspectiveCamera();
44018		this.cameraR.layers.enable( 2 );
44019		this.cameraR.matrixAutoUpdate = false;
44020
44021		this._cache = {
44022			focus: null,
44023			fov: null,
44024			aspect: null,
44025			near: null,
44026			far: null,
44027			zoom: null,
44028			eyeSep: null
44029		};
44030
44031	}
44032
44033	update( camera ) {
44034
44035		const cache = this._cache;
44036
44037		const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
44038			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
44039			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
44040
44041		if ( needsUpdate ) {
44042
44043			cache.focus = camera.focus;
44044			cache.fov = camera.fov;
44045			cache.aspect = camera.aspect * this.aspect;
44046			cache.near = camera.near;
44047			cache.far = camera.far;
44048			cache.zoom = camera.zoom;
44049			cache.eyeSep = this.eyeSep;
44050
44051			// Off-axis stereoscopic effect based on
44052			// http://paulbourke.net/stereographics/stereorender/
44053
44054			_projectionMatrix.copy( camera.projectionMatrix );
44055			const eyeSepHalf = cache.eyeSep / 2;
44056			const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
44057			const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
44058			let xmin, xmax;
44059
44060			// translate xOffset
44061
44062			_eyeLeft.elements[ 12 ] = - eyeSepHalf;
44063			_eyeRight.elements[ 12 ] = eyeSepHalf;
44064
44065			// for left eye
44066
44067			xmin = - ymax * cache.aspect + eyeSepOnProjection;
44068			xmax = ymax * cache.aspect + eyeSepOnProjection;
44069
44070			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
44071			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
44072
44073			this.cameraL.projectionMatrix.copy( _projectionMatrix );
44074
44075			// for right eye
44076
44077			xmin = - ymax * cache.aspect - eyeSepOnProjection;
44078			xmax = ymax * cache.aspect - eyeSepOnProjection;
44079
44080			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
44081			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
44082
44083			this.cameraR.projectionMatrix.copy( _projectionMatrix );
44084
44085		}
44086
44087		this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
44088		this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
44089
44090	}
44091
44092}
44093
44094class Clock {
44095
44096	constructor( autoStart = true ) {
44097
44098		this.autoStart = autoStart;
44099
44100		this.startTime = 0;
44101		this.oldTime = 0;
44102		this.elapsedTime = 0;
44103
44104		this.running = false;
44105
44106	}
44107
44108	start() {
44109
44110		this.startTime = now();
44111
44112		this.oldTime = this.startTime;
44113		this.elapsedTime = 0;
44114		this.running = true;
44115
44116	}
44117
44118	stop() {
44119
44120		this.getElapsedTime();
44121		this.running = false;
vendor: 4,123 bytes, lines 44122-44353
44122		this.autoStart = false;
44123
44124	}
44125
44126	getElapsedTime() {
44127
44128		this.getDelta();
44129		return this.elapsedTime;
44130
44131	}
44132
44133	getDelta() {
44134
44135		let diff = 0;
44136
44137		if ( this.autoStart && ! this.running ) {
44138
44139			this.start();
44140			return 0;
44141
44142		}
44143
44144		if ( this.running ) {
44145
44146			const newTime = now();
44147
44148			diff = ( newTime - this.oldTime ) / 1000;
44149			this.oldTime = newTime;
44150
44151			this.elapsedTime += diff;
44152
44153		}
44154
44155		return diff;
44156
44157	}
44158
44159}
44160
44161function now() {
44162
44163	return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
44164
44165}
44166
44167const _position$1 = /*@__PURE__*/ new Vector3();
44168const _quaternion$1 = /*@__PURE__*/ new Quaternion();
44169const _scale$1 = /*@__PURE__*/ new Vector3();
44170const _orientation$1 = /*@__PURE__*/ new Vector3();
44171
44172class AudioListener extends Object3D {
44173
44174	constructor() {
44175
44176		super();
44177
44178		this.type = 'AudioListener';
44179
44180		this.context = AudioContext.getContext();
44181
44182		this.gain = this.context.createGain();
44183		this.gain.connect( this.context.destination );
44184
44185		this.filter = null;
44186
44187		this.timeDelta = 0;
44188
44189		// private
44190
44191		this._clock = new Clock();
44192
44193	}
44194
44195	getInput() {
44196
44197		return this.gain;
44198
44199	}
44200
44201	removeFilter() {
44202
44203		if ( this.filter !== null ) {
44204
44205			this.gain.disconnect( this.filter );
44206			this.filter.disconnect( this.context.destination );
44207			this.gain.connect( this.context.destination );
44208			this.filter = null;
44209
44210		}
44211
44212		return this;
44213
44214	}
44215
44216	getFilter() {
44217
44218		return this.filter;
44219
44220	}
44221
44222	setFilter( value ) {
44223
44224		if ( this.filter !== null ) {
44225
44226			this.gain.disconnect( this.filter );
44227			this.filter.disconnect( this.context.destination );
44228
44229		} else {
44230
44231			this.gain.disconnect( this.context.destination );
44232
44233		}
44234
44235		this.filter = value;
44236		this.gain.connect( this.filter );
44237		this.filter.connect( this.context.destination );
44238
44239		return this;
44240
44241	}
44242
44243	getMasterVolume() {
44244
44245		return this.gain.gain.value;
44246
44247	}
44248
44249	setMasterVolume( value ) {
44250
44251		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
44252
44253		return this;
44254
44255	}
44256
44257	updateMatrixWorld( force ) {
44258
44259		super.updateMatrixWorld( force );
44260
44261		const listener = this.context.listener;
44262		const up = this.up;
44263
44264		this.timeDelta = this._clock.getDelta();
44265
44266		this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 );
44267
44268		_orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 );
44269
44270		if ( listener.positionX ) {
44271
44272			// code path for Chrome (see #14393)
44273
44274			const endTime = this.context.currentTime + this.timeDelta;
44275
44276			listener.positionX.linearRampToValueAtTime( _position$1.x, endTime );
44277			listener.positionY.linearRampToValueAtTime( _position$1.y, endTime );
44278			listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime );
44279			listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime );
44280			listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime );
44281			listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime );
44282			listener.upX.linearRampToValueAtTime( up.x, endTime );
44283			listener.upY.linearRampToValueAtTime( up.y, endTime );
44284			listener.upZ.linearRampToValueAtTime( up.z, endTime );
44285
44286		} else {
44287
44288			listener.setPosition( _position$1.x, _position$1.y, _position$1.z );
44289			listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z );
44290
44291		}
44292
44293	}
44294
44295}
44296
44297class Audio extends Object3D {
44298
44299	constructor( listener ) {
44300
44301		super();
44302
44303		this.type = 'Audio';
44304
44305		this.listener = listener;
44306		this.context = listener.context;
44307
44308		this.gain = this.context.createGain();
44309		this.gain.connect( listener.getInput() );
44310
44311		this.autoplay = false;
44312
44313		this.buffer = null;
44314		this.detune = 0;
44315		this.loop = false;
44316		this.loopStart = 0;
44317		this.loopEnd = 0;
44318		this.offset = 0;
44319		this.duration = undefined;
44320		this.playbackRate = 1;
44321		this.isPlaying = false;
44322		this.hasPlaybackControl = true;
44323		this.source = null;
44324		this.sourceType = 'empty';
44325
44326		this._startedAt = 0;
44327		this._progress = 0;
44328		this._connected = false;
44329
44330		this.filters = [];
44331
44332	}
44333
44334	getOutput() {
44335
44336		return this.gain;
44337
44338	}
44339
44340	setNodeSource( audioNode ) {
44341
44342		this.hasPlaybackControl = false;
44343		this.sourceType = 'audioNode';
44344		this.source = audioNode;
44345		this.connect();
44346
44347		return this;
44348
44349	}
44350
44351	setMediaElementSource( mediaElement ) {
44352
44353		this.hasPlaybackControl = false;
vendor: 4,234 bytes, lines 44354-44620
44354		this.sourceType = 'mediaNode';
44355		this.source = this.context.createMediaElementSource( mediaElement );
44356		this.connect();
44357
44358		return this;
44359
44360	}
44361
44362	setMediaStreamSource( mediaStream ) {
44363
44364		this.hasPlaybackControl = false;
44365		this.sourceType = 'mediaStreamNode';
44366		this.source = this.context.createMediaStreamSource( mediaStream );
44367		this.connect();
44368
44369		return this;
44370
44371	}
44372
44373	setBuffer( audioBuffer ) {
44374
44375		this.buffer = audioBuffer;
44376		this.sourceType = 'buffer';
44377
44378		if ( this.autoplay ) this.play();
44379
44380		return this;
44381
44382	}
44383
44384	play( delay = 0 ) {
44385
44386		if ( this.isPlaying === true ) {
44387
44388			console.warn( 'THREE.Audio: Audio is already playing.' );
44389			return;
44390
44391		}
44392
44393		if ( this.hasPlaybackControl === false ) {
44394
44395			console.warn( 'THREE.Audio: this Audio has no playback control.' );
44396			return;
44397
44398		}
44399
44400		this._startedAt = this.context.currentTime + delay;
44401
44402		const source = this.context.createBufferSource();
44403		source.buffer = this.buffer;
44404		source.loop = this.loop;
44405		source.loopStart = this.loopStart;
44406		source.loopEnd = this.loopEnd;
44407		source.onended = this.onEnded.bind( this );
44408		source.start( this._startedAt, this._progress + this.offset, this.duration );
44409
44410		this.isPlaying = true;
44411
44412		this.source = source;
44413
44414		this.setDetune( this.detune );
44415		this.setPlaybackRate( this.playbackRate );
44416
44417		return this.connect();
44418
44419	}
44420
44421	pause() {
44422
44423		if ( this.hasPlaybackControl === false ) {
44424
44425			console.warn( 'THREE.Audio: this Audio has no playback control.' );
44426			return;
44427
44428		}
44429
44430		if ( this.isPlaying === true ) {
44431
44432			// update current progress
44433
44434			this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
44435
44436			if ( this.loop === true ) {
44437
44438				// ensure _progress does not exceed duration with looped audios
44439
44440				this._progress = this._progress % ( this.duration || this.buffer.duration );
44441
44442			}
44443
44444			this.source.stop();
44445			this.source.onended = null;
44446
44447			this.isPlaying = false;
44448
44449		}
44450
44451		return this;
44452
44453	}
44454
44455	stop() {
44456
44457		if ( this.hasPlaybackControl === false ) {
44458
44459			console.warn( 'THREE.Audio: this Audio has no playback control.' );
44460			return;
44461
44462		}
44463
44464		this._progress = 0;
44465
44466		if ( this.source !== null ) {
44467
44468			this.source.stop();
44469			this.source.onended = null;
44470
44471		}
44472
44473		this.isPlaying = false;
44474
44475		return this;
44476
44477	}
44478
44479	connect() {
44480
44481		if ( this.filters.length > 0 ) {
44482
44483			this.source.connect( this.filters[ 0 ] );
44484
44485			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
44486
44487				this.filters[ i - 1 ].connect( this.filters[ i ] );
44488
44489			}
44490
44491			this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
44492
44493		} else {
44494
44495			this.source.connect( this.getOutput() );
44496
44497		}
44498
44499		this._connected = true;
44500
44501		return this;
44502
44503	}
44504
44505	disconnect() {
44506
44507		if ( this.filters.length > 0 ) {
44508
44509			this.source.disconnect( this.filters[ 0 ] );
44510
44511			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
44512
44513				this.filters[ i - 1 ].disconnect( this.filters[ i ] );
44514
44515			}
44516
44517			this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
44518
44519		} else {
44520
44521			this.source.disconnect( this.getOutput() );
44522
44523		}
44524
44525		this._connected = false;
44526
44527		return this;
44528
44529	}
44530
44531	getFilters() {
44532
44533		return this.filters;
44534
44535	}
44536
44537	setFilters( value ) {
44538
44539		if ( ! value ) value = [];
44540
44541		if ( this._connected === true ) {
44542
44543			this.disconnect();
44544			this.filters = value.slice();
44545			this.connect();
44546
44547		} else {
44548
44549			this.filters = value.slice();
44550
44551		}
44552
44553		return this;
44554
44555	}
44556
44557	setDetune( value ) {
44558
44559		this.detune = value;
44560
44561		if ( this.source.detune === undefined ) return; // only set detune when available
44562
44563		if ( this.isPlaying === true ) {
44564
44565			this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
44566
44567		}
44568
44569		return this;
44570
44571	}
44572
44573	getDetune() {
44574
44575		return this.detune;
44576
44577	}
44578
44579	getFilter() {
44580
44581		return this.getFilters()[ 0 ];
44582
44583	}
44584
44585	setFilter( filter ) {
44586
44587		return this.setFilters( filter ? [ filter ] : [] );
44588
44589	}
44590
44591	setPlaybackRate( value ) {
44592
44593		if ( this.hasPlaybackControl === false ) {
44594
44595			console.warn( 'THREE.Audio: this Audio has no playback control.' );
44596			return;
44597
44598		}
44599
44600		this.playbackRate = value;
44601
44602		if ( this.isPlaying === true ) {
44603
44604			this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
44605
44606		}
44607
44608		return this;
44609
44610	}
44611
44612	getPlaybackRate() {
44613
44614		return this.playbackRate;
44615
44616	}
44617
44618	onEnded() {
44619
44620		this.isPlaying = false;
vendor: 4,367 bytes, lines 44621-44885
44621
44622	}
44623
44624	getLoop() {
44625
44626		if ( this.hasPlaybackControl === false ) {
44627
44628			console.warn( 'THREE.Audio: this Audio has no playback control.' );
44629			return false;
44630
44631		}
44632
44633		return this.loop;
44634
44635	}
44636
44637	setLoop( value ) {
44638
44639		if ( this.hasPlaybackControl === false ) {
44640
44641			console.warn( 'THREE.Audio: this Audio has no playback control.' );
44642			return;
44643
44644		}
44645
44646		this.loop = value;
44647
44648		if ( this.isPlaying === true ) {
44649
44650			this.source.loop = this.loop;
44651
44652		}
44653
44654		return this;
44655
44656	}
44657
44658	setLoopStart( value ) {
44659
44660		this.loopStart = value;
44661
44662		return this;
44663
44664	}
44665
44666	setLoopEnd( value ) {
44667
44668		this.loopEnd = value;
44669
44670		return this;
44671
44672	}
44673
44674	getVolume() {
44675
44676		return this.gain.gain.value;
44677
44678	}
44679
44680	setVolume( value ) {
44681
44682		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
44683
44684		return this;
44685
44686	}
44687
44688}
44689
44690const _position = /*@__PURE__*/ new Vector3();
44691const _quaternion = /*@__PURE__*/ new Quaternion();
44692const _scale = /*@__PURE__*/ new Vector3();
44693const _orientation = /*@__PURE__*/ new Vector3();
44694
44695class PositionalAudio extends Audio {
44696
44697	constructor( listener ) {
44698
44699		super( listener );
44700
44701		this.panner = this.context.createPanner();
44702		this.panner.panningModel = 'HRTF';
44703		this.panner.connect( this.gain );
44704
44705	}
44706
44707	disconnect() {
44708
44709		super.disconnect();
44710
44711		this.panner.disconnect( this.gain );
44712
44713	}
44714
44715	getOutput() {
44716
44717		return this.panner;
44718
44719	}
44720
44721	getRefDistance() {
44722
44723		return this.panner.refDistance;
44724
44725	}
44726
44727	setRefDistance( value ) {
44728
44729		this.panner.refDistance = value;
44730
44731		return this;
44732
44733	}
44734
44735	getRolloffFactor() {
44736
44737		return this.panner.rolloffFactor;
44738
44739	}
44740
44741	setRolloffFactor( value ) {
44742
44743		this.panner.rolloffFactor = value;
44744
44745		return this;
44746
44747	}
44748
44749	getDistanceModel() {
44750
44751		return this.panner.distanceModel;
44752
44753	}
44754
44755	setDistanceModel( value ) {
44756
44757		this.panner.distanceModel = value;
44758
44759		return this;
44760
44761	}
44762
44763	getMaxDistance() {
44764
44765		return this.panner.maxDistance;
44766
44767	}
44768
44769	setMaxDistance( value ) {
44770
44771		this.panner.maxDistance = value;
44772
44773		return this;
44774
44775	}
44776
44777	setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
44778
44779		this.panner.coneInnerAngle = coneInnerAngle;
44780		this.panner.coneOuterAngle = coneOuterAngle;
44781		this.panner.coneOuterGain = coneOuterGain;
44782
44783		return this;
44784
44785	}
44786
44787	updateMatrixWorld( force ) {
44788
44789		super.updateMatrixWorld( force );
44790
44791		if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
44792
44793		this.matrixWorld.decompose( _position, _quaternion, _scale );
44794
44795		_orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
44796
44797		const panner = this.panner;
44798
44799		if ( panner.positionX ) {
44800
44801			// code path for Chrome and Firefox (see #14393)
44802
44803			const endTime = this.context.currentTime + this.listener.timeDelta;
44804
44805			panner.positionX.linearRampToValueAtTime( _position.x, endTime );
44806			panner.positionY.linearRampToValueAtTime( _position.y, endTime );
44807			panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
44808			panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
44809			panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
44810			panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
44811
44812		} else {
44813
44814			panner.setPosition( _position.x, _position.y, _position.z );
44815			panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
44816
44817		}
44818
44819	}
44820
44821}
44822
44823class AudioAnalyser {
44824
44825	constructor( audio, fftSize = 2048 ) {
44826
44827		this.analyser = audio.context.createAnalyser();
44828		this.analyser.fftSize = fftSize;
44829
44830		this.data = new Uint8Array( this.analyser.frequencyBinCount );
44831
44832		audio.getOutput().connect( this.analyser );
44833
44834	}
44835
44836
44837	getFrequencyData() {
44838
44839		this.analyser.getByteFrequencyData( this.data );
44840
44841		return this.data;
44842
44843	}
44844
44845	getAverageFrequency() {
44846
44847		let value = 0;
44848		const data = this.getFrequencyData();
44849
44850		for ( let i = 0; i < data.length; i ++ ) {
44851
44852			value += data[ i ];
44853
44854		}
44855
44856		return value / data.length;
44857
44858	}
44859
44860}
44861
44862class PropertyMixer {
44863
44864	constructor( binding, typeName, valueSize ) {
44865
44866		this.binding = binding;
44867		this.valueSize = valueSize;
44868
44869		let mixFunction,
44870			mixFunctionAdditive,
44871			setIdentity;
44872
44873		// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
44874		//
44875		// interpolators can use .buffer as their .result
44876		// the data then goes to 'incoming'
44877		//
44878		// 'accu0' and 'accu1' are used frame-interleaved for
44879		// the cumulative result and are compared to detect
44880		// changes
44881		//
44882		// 'orig' stores the original state of the property
44883		//
44884		// 'add' is used for additive cumulative results
44885		//
vendor: 13,778 bytes, lines 44886-45516
44886		// 'work' is optional and is only present for quaternion types. It is used
44887		// to store intermediate quaternion multiplication results
44888
44889		switch ( typeName ) {
44890
44891			case 'quaternion':
44892				mixFunction = this._slerp;
44893				mixFunctionAdditive = this._slerpAdditive;
44894				setIdentity = this._setAdditiveIdentityQuaternion;
44895
44896				this.buffer = new Float64Array( valueSize * 6 );
44897				this._workIndex = 5;
44898				break;
44899
44900			case 'string':
44901			case 'bool':
44902				mixFunction = this._select;
44903
44904				// Use the regular mix function and for additive on these types,
44905				// additive is not relevant for non-numeric types
44906				mixFunctionAdditive = this._select;
44907
44908				setIdentity = this._setAdditiveIdentityOther;
44909
44910				this.buffer = new Array( valueSize * 5 );
44911				break;
44912
44913			default:
44914				mixFunction = this._lerp;
44915				mixFunctionAdditive = this._lerpAdditive;
44916				setIdentity = this._setAdditiveIdentityNumeric;
44917
44918				this.buffer = new Float64Array( valueSize * 5 );
44919
44920		}
44921
44922		this._mixBufferRegion = mixFunction;
44923		this._mixBufferRegionAdditive = mixFunctionAdditive;
44924		this._setIdentity = setIdentity;
44925		this._origIndex = 3;
44926		this._addIndex = 4;
44927
44928		this.cumulativeWeight = 0;
44929		this.cumulativeWeightAdditive = 0;
44930
44931		this.useCount = 0;
44932		this.referenceCount = 0;
44933
44934	}
44935
44936	// accumulate data in the 'incoming' region into 'accu<i>'
44937	accumulate( accuIndex, weight ) {
44938
44939		// note: happily accumulating nothing when weight = 0, the caller knows
44940		// the weight and shouldn't have made the call in the first place
44941
44942		const buffer = this.buffer,
44943			stride = this.valueSize,
44944			offset = accuIndex * stride + stride;
44945
44946		let currentWeight = this.cumulativeWeight;
44947
44948		if ( currentWeight === 0 ) {
44949
44950			// accuN := incoming * weight
44951
44952			for ( let i = 0; i !== stride; ++ i ) {
44953
44954				buffer[ offset + i ] = buffer[ i ];
44955
44956			}
44957
44958			currentWeight = weight;
44959
44960		} else {
44961
44962			// accuN := accuN + incoming * weight
44963
44964			currentWeight += weight;
44965			const mix = weight / currentWeight;
44966			this._mixBufferRegion( buffer, offset, 0, mix, stride );
44967
44968		}
44969
44970		this.cumulativeWeight = currentWeight;
44971
44972	}
44973
44974	// accumulate data in the 'incoming' region into 'add'
44975	accumulateAdditive( weight ) {
44976
44977		const buffer = this.buffer,
44978			stride = this.valueSize,
44979			offset = stride * this._addIndex;
44980
44981		if ( this.cumulativeWeightAdditive === 0 ) {
44982
44983			// add = identity
44984
44985			this._setIdentity();
44986
44987		}
44988
44989		// add := add + incoming * weight
44990
44991		this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
44992		this.cumulativeWeightAdditive += weight;
44993
44994	}
44995
44996	// apply the state of 'accu<i>' to the binding when accus differ
44997	apply( accuIndex ) {
44998
44999		const stride = this.valueSize,
45000			buffer = this.buffer,
45001			offset = accuIndex * stride + stride,
45002
45003			weight = this.cumulativeWeight,
45004			weightAdditive = this.cumulativeWeightAdditive,
45005
45006			binding = this.binding;
45007
45008		this.cumulativeWeight = 0;
45009		this.cumulativeWeightAdditive = 0;
45010
45011		if ( weight < 1 ) {
45012
45013			// accuN := accuN + original * ( 1 - cumulativeWeight )
45014
45015			const originalValueOffset = stride * this._origIndex;
45016
45017			this._mixBufferRegion(
45018				buffer, offset, originalValueOffset, 1 - weight, stride );
45019
45020		}
45021
45022		if ( weightAdditive > 0 ) {
45023
45024			// accuN := accuN + additive accuN
45025
45026			this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
45027
45028		}
45029
45030		for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
45031
45032			if ( buffer[ i ] !== buffer[ i + stride ] ) {
45033
45034				// value has changed -> update scene graph
45035
45036				binding.setValue( buffer, offset );
45037				break;
45038
45039			}
45040
45041		}
45042
45043	}
45044
45045	// remember the state of the bound property and copy it to both accus
45046	saveOriginalState() {
45047
45048		const binding = this.binding;
45049
45050		const buffer = this.buffer,
45051			stride = this.valueSize,
45052
45053			originalValueOffset = stride * this._origIndex;
45054
45055		binding.getValue( buffer, originalValueOffset );
45056
45057		// accu[0..1] := orig -- initially detect changes against the original
45058		for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
45059
45060			buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
45061
45062		}
45063
45064		// Add to identity for additive
45065		this._setIdentity();
45066
45067		this.cumulativeWeight = 0;
45068		this.cumulativeWeightAdditive = 0;
45069
45070	}
45071
45072	// apply the state previously taken via 'saveOriginalState' to the binding
45073	restoreOriginalState() {
45074
45075		const originalValueOffset = this.valueSize * 3;
45076		this.binding.setValue( this.buffer, originalValueOffset );
45077
45078	}
45079
45080	_setAdditiveIdentityNumeric() {
45081
45082		const startIndex = this._addIndex * this.valueSize;
45083		const endIndex = startIndex + this.valueSize;
45084
45085		for ( let i = startIndex; i < endIndex; i ++ ) {
45086
45087			this.buffer[ i ] = 0;
45088
45089		}
45090
45091	}
45092
45093	_setAdditiveIdentityQuaternion() {
45094
45095		this._setAdditiveIdentityNumeric();
45096		this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
45097
45098	}
45099
45100	_setAdditiveIdentityOther() {
45101
45102		const startIndex = this._origIndex * this.valueSize;
45103		const targetIndex = this._addIndex * this.valueSize;
45104
45105		for ( let i = 0; i < this.valueSize; i ++ ) {
45106
45107			this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
45108
45109		}
45110
45111	}
45112
45113
45114	// mix functions
45115
45116	_select( buffer, dstOffset, srcOffset, t, stride ) {
45117
45118		if ( t >= 0.5 ) {
45119
45120			for ( let i = 0; i !== stride; ++ i ) {
45121
45122				buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
45123
45124			}
45125
45126		}
45127
45128	}
45129
45130	_slerp( buffer, dstOffset, srcOffset, t ) {
45131
45132		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
45133
45134	}
45135
45136	_slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
45137
45138		const workOffset = this._workIndex * stride;
45139
45140		// Store result in intermediate buffer offset
45141		Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
45142
45143		// Slerp to the intermediate result
45144		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
45145
45146	}
45147
45148	_lerp( buffer, dstOffset, srcOffset, t, stride ) {
45149
45150		const s = 1 - t;
45151
45152		for ( let i = 0; i !== stride; ++ i ) {
45153
45154			const j = dstOffset + i;
45155
45156			buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
45157
45158		}
45159
45160	}
45161
45162	_lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
45163
45164		for ( let i = 0; i !== stride; ++ i ) {
45165
45166			const j = dstOffset + i;
45167
45168			buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
45169
45170		}
45171
45172	}
45173
45174}
45175
45176// Characters [].:/ are reserved for track binding syntax.
45177const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
45178const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
45179
45180// Attempts to allow node names from any language. ES5's `\w` regexp matches
45181// only latin characters, and the unicode \p{L} is not yet supported. So
45182// instead, we exclude reserved characters and match everything else.
45183const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
45184const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
45185
45186// Parent directories, delimited by '/' or ':'. Currently unused, but must
45187// be matched to parse the rest of the track name.
45188const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
45189
45190// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
45191const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
45192
45193// Object on target node, and accessor. May not contain reserved
45194// characters. Accessor may contain any character except closing bracket.
45195const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
45196
45197// Property and accessor. May not contain reserved characters. Accessor may
45198// contain any non-bracket characters.
45199const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
45200
45201const _trackRe = new RegExp( ''
45202	+ '^'
45203	+ _directoryRe
45204	+ _nodeRe
45205	+ _objectRe
45206	+ _propertyRe
45207	+ '$'
45208);
45209
45210const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ];
45211
45212class Composite {
45213
45214	constructor( targetGroup, path, optionalParsedPath ) {
45215
45216		const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
45217
45218		this._targetGroup = targetGroup;
45219		this._bindings = targetGroup.subscribe_( path, parsedPath );
45220
45221	}
45222
45223	getValue( array, offset ) {
45224
45225		this.bind(); // bind all binding
45226
45227		const firstValidIndex = this._targetGroup.nCachedObjects_,
45228			binding = this._bindings[ firstValidIndex ];
45229
45230		// and only call .getValue on the first
45231		if ( binding !== undefined ) binding.getValue( array, offset );
45232
45233	}
45234
45235	setValue( array, offset ) {
45236
45237		const bindings = this._bindings;
45238
45239		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
45240
45241			bindings[ i ].setValue( array, offset );
45242
45243		}
45244
45245	}
45246
45247	bind() {
45248
45249		const bindings = this._bindings;
45250
45251		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
45252
45253			bindings[ i ].bind();
45254
45255		}
45256
45257	}
45258
45259	unbind() {
45260
45261		const bindings = this._bindings;
45262
45263		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
45264
45265			bindings[ i ].unbind();
45266
45267		}
45268
45269	}
45270
45271}
45272
45273// Note: This class uses a State pattern on a per-method basis:
45274// 'bind' sets 'this.getValue' / 'setValue' and shadows the
45275// prototype version of these methods with one that represents
45276// the bound state. When the property is not found, the methods
45277// become no-ops.
45278class PropertyBinding {
45279
45280	constructor( rootNode, path, parsedPath ) {
45281
45282		this.path = path;
45283		this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
45284
45285		this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
45286
45287		this.rootNode = rootNode;
45288
45289		// initial state of these methods that calls 'bind'
45290		this.getValue = this._getValue_unbound;
45291		this.setValue = this._setValue_unbound;
45292
45293	}
45294
45295
45296	static create( root, path, parsedPath ) {
45297
45298		if ( ! ( root && root.isAnimationObjectGroup ) ) {
45299
45300			return new PropertyBinding( root, path, parsedPath );
45301
45302		} else {
45303
45304			return new PropertyBinding.Composite( root, path, parsedPath );
45305
45306		}
45307
45308	}
45309
45310	/**
45311	 * Replaces spaces with underscores and removes unsupported characters from
45312	 * node names, to ensure compatibility with parseTrackName().
45313	 *
45314	 * @param {string} name Node name to be sanitized.
45315	 * @return {string}
45316	 */
45317	static sanitizeNodeName( name ) {
45318
45319		return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
45320
45321	}
45322
45323	static parseTrackName( trackName ) {
45324
45325		const matches = _trackRe.exec( trackName );
45326
45327		if ( matches === null ) {
45328
45329			throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
45330
45331		}
45332
45333		const results = {
45334			// directoryName: matches[ 1 ], // (tschw) currently unused
45335			nodeName: matches[ 2 ],
45336			objectName: matches[ 3 ],
45337			objectIndex: matches[ 4 ],
45338			propertyName: matches[ 5 ], // required
45339			propertyIndex: matches[ 6 ]
45340		};
45341
45342		const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
45343
45344		if ( lastDot !== undefined && lastDot !== - 1 ) {
45345
45346			const objectName = results.nodeName.substring( lastDot + 1 );
45347
45348			// Object names must be checked against an allowlist. Otherwise, there
45349			// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
45350			// 'bar' could be the objectName, or part of a nodeName (which can
45351			// include '.' characters).
45352			if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
45353
45354				results.nodeName = results.nodeName.substring( 0, lastDot );
45355				results.objectName = objectName;
45356
45357			}
45358
45359		}
45360
45361		if ( results.propertyName === null || results.propertyName.length === 0 ) {
45362
45363			throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
45364
45365		}
45366
45367		return results;
45368
45369	}
45370
45371	static findNode( root, nodeName ) {
45372
45373		if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
45374
45375			return root;
45376
45377		}
45378
45379		// search into skeleton bones.
45380		if ( root.skeleton ) {
45381
45382			const bone = root.skeleton.getBoneByName( nodeName );
45383
45384			if ( bone !== undefined ) {
45385
45386				return bone;
45387
45388			}
45389
45390		}
45391
45392		// search into node subtree.
45393		if ( root.children ) {
45394
45395			const searchNodeSubtree = function ( children ) {
45396
45397				for ( let i = 0; i < children.length; i ++ ) {
45398
45399					const childNode = children[ i ];
45400
45401					if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
45402
45403						return childNode;
45404
45405					}
45406
45407					const result = searchNodeSubtree( childNode.children );
45408
45409					if ( result ) return result;
45410
45411				}
45412
45413				return null;
45414
45415			};
45416
45417			const subTreeNode = searchNodeSubtree( root.children );
45418
45419			if ( subTreeNode ) {
45420
45421				return subTreeNode;
45422
45423			}
45424
45425		}
45426
45427		return null;
45428
45429	}
45430
45431	// these are used to "bind" a nonexistent property
45432	_getValue_unavailable() {}
45433	_setValue_unavailable() {}
45434
45435	// Getters
45436
45437	_getValue_direct( buffer, offset ) {
45438
45439		buffer[ offset ] = this.targetObject[ this.propertyName ];
45440
45441	}
45442
45443	_getValue_array( buffer, offset ) {
45444
45445		const source = this.resolvedProperty;
45446
45447		for ( let i = 0, n = source.length; i !== n; ++ i ) {
45448
45449			buffer[ offset ++ ] = source[ i ];
45450
45451		}
45452
45453	}
45454
45455	_getValue_arrayElement( buffer, offset ) {
45456
45457		buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
45458
45459	}
45460
45461	_getValue_toArray( buffer, offset ) {
45462
45463		this.resolvedProperty.toArray( buffer, offset );
45464
45465	}
45466
45467	// Direct
45468
45469	_setValue_direct( buffer, offset ) {
45470
45471		this.targetObject[ this.propertyName ] = buffer[ offset ];
45472
45473	}
45474
45475	_setValue_direct_setNeedsUpdate( buffer, offset ) {
45476
45477		this.targetObject[ this.propertyName ] = buffer[ offset ];
45478		this.targetObject.needsUpdate = true;
45479
45480	}
45481
45482	_setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
45483
45484		this.targetObject[ this.propertyName ] = buffer[ offset ];
45485		this.targetObject.matrixWorldNeedsUpdate = true;
45486
45487	}
45488
45489	// EntireArray
45490
45491	_setValue_array( buffer, offset ) {
45492
45493		const dest = this.resolvedProperty;
45494
45495		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
45496
45497			dest[ i ] = buffer[ offset ++ ];
45498
45499		}
45500
45501	}
45502
45503	_setValue_array_setNeedsUpdate( buffer, offset ) {
45504
45505		const dest = this.resolvedProperty;
45506
45507		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
45508
45509			dest[ i ] = buffer[ offset ++ ];
45510
45511		}
45512
45513		this.targetObject.needsUpdate = true;
45514
45515	}
45516
vendor: 8,208 bytes, lines 45517-45872
45517	_setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
45518
45519		const dest = this.resolvedProperty;
45520
45521		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
45522
45523			dest[ i ] = buffer[ offset ++ ];
45524
45525		}
45526
45527		this.targetObject.matrixWorldNeedsUpdate = true;
45528
45529	}
45530
45531	// ArrayElement
45532
45533	_setValue_arrayElement( buffer, offset ) {
45534
45535		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
45536
45537	}
45538
45539	_setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
45540
45541		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
45542		this.targetObject.needsUpdate = true;
45543
45544	}
45545
45546	_setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
45547
45548		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
45549		this.targetObject.matrixWorldNeedsUpdate = true;
45550
45551	}
45552
45553	// HasToFromArray
45554
45555	_setValue_fromArray( buffer, offset ) {
45556
45557		this.resolvedProperty.fromArray( buffer, offset );
45558
45559	}
45560
45561	_setValue_fromArray_setNeedsUpdate( buffer, offset ) {
45562
45563		this.resolvedProperty.fromArray( buffer, offset );
45564		this.targetObject.needsUpdate = true;
45565
45566	}
45567
45568	_setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
45569
45570		this.resolvedProperty.fromArray( buffer, offset );
45571		this.targetObject.matrixWorldNeedsUpdate = true;
45572
45573	}
45574
45575	_getValue_unbound( targetArray, offset ) {
45576
45577		this.bind();
45578		this.getValue( targetArray, offset );
45579
45580	}
45581
45582	_setValue_unbound( sourceArray, offset ) {
45583
45584		this.bind();
45585		this.setValue( sourceArray, offset );
45586
45587	}
45588
45589	// create getter / setter pair for a property in the scene graph
45590	bind() {
45591
45592		let targetObject = this.node;
45593		const parsedPath = this.parsedPath;
45594
45595		const objectName = parsedPath.objectName;
45596		const propertyName = parsedPath.propertyName;
45597		let propertyIndex = parsedPath.propertyIndex;
45598
45599		if ( ! targetObject ) {
45600
45601			targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName );
45602
45603			this.node = targetObject;
45604
45605		}
45606
45607		// set fail state so we can just 'return' on error
45608		this.getValue = this._getValue_unavailable;
45609		this.setValue = this._setValue_unavailable;
45610
45611		// ensure there is a value node
45612		if ( ! targetObject ) {
45613
45614			console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
45615			return;
45616
45617		}
45618
45619		if ( objectName ) {
45620
45621			let objectIndex = parsedPath.objectIndex;
45622
45623			// special cases were we need to reach deeper into the hierarchy to get the face materials....
45624			switch ( objectName ) {
45625
45626				case 'materials':
45627
45628					if ( ! targetObject.material ) {
45629
45630						console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
45631						return;
45632
45633					}
45634
45635					if ( ! targetObject.material.materials ) {
45636
45637						console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
45638						return;
45639
45640					}
45641
45642					targetObject = targetObject.material.materials;
45643
45644					break;
45645
45646				case 'bones':
45647
45648					if ( ! targetObject.skeleton ) {
45649
45650						console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
45651						return;
45652
45653					}
45654
45655					// potential future optimization: skip this if propertyIndex is already an integer
45656					// and convert the integer string to a true integer.
45657
45658					targetObject = targetObject.skeleton.bones;
45659
45660					// support resolving morphTarget names into indices.
45661					for ( let i = 0; i < targetObject.length; i ++ ) {
45662
45663						if ( targetObject[ i ].name === objectIndex ) {
45664
45665							objectIndex = i;
45666							break;
45667
45668						}
45669
45670					}
45671
45672					break;
45673
45674				case 'map':
45675
45676					if ( 'map' in targetObject ) {
45677
45678						targetObject = targetObject.map;
45679						break;
45680
45681					}
45682
45683					if ( ! targetObject.material ) {
45684
45685						console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
45686						return;
45687
45688					}
45689
45690					if ( ! targetObject.material.map ) {
45691
45692						console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this );
45693						return;
45694
45695					}
45696
45697					targetObject = targetObject.material.map;
45698					break;
45699
45700				default:
45701
45702					if ( targetObject[ objectName ] === undefined ) {
45703
45704						console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
45705						return;
45706
45707					}
45708
45709					targetObject = targetObject[ objectName ];
45710
45711			}
45712
45713
45714			if ( objectIndex !== undefined ) {
45715
45716				if ( targetObject[ objectIndex ] === undefined ) {
45717
45718					console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
45719					return;
45720
45721				}
45722
45723				targetObject = targetObject[ objectIndex ];
45724
45725			}
45726
45727		}
45728
45729		// resolve property
45730		const nodeProperty = targetObject[ propertyName ];
45731
45732		if ( nodeProperty === undefined ) {
45733
45734			const nodeName = parsedPath.nodeName;
45735
45736			console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
45737				'.' + propertyName + ' but it wasn\'t found.', targetObject );
45738			return;
45739
45740		}
45741
45742		// determine versioning scheme
45743		let versioning = this.Versioning.None;
45744
45745		this.targetObject = targetObject;
45746
45747		if ( targetObject.needsUpdate !== undefined ) { // material
45748
45749			versioning = this.Versioning.NeedsUpdate;
45750
45751		} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
45752
45753			versioning = this.Versioning.MatrixWorldNeedsUpdate;
45754
45755		}
45756
45757		// determine how the property gets bound
45758		let bindingType = this.BindingType.Direct;
45759
45760		if ( propertyIndex !== undefined ) {
45761
45762			// access a sub element of the property array (only primitives are supported right now)
45763
45764			if ( propertyName === 'morphTargetInfluences' ) {
45765
45766				// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
45767
45768				// support resolving morphTarget names into indices.
45769				if ( ! targetObject.geometry ) {
45770
45771					console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
45772					return;
45773
45774				}
45775
45776				if ( ! targetObject.geometry.morphAttributes ) {
45777
45778					console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
45779					return;
45780
45781				}
45782
45783				if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
45784
45785					propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
45786
45787				}
45788
45789			}
45790
45791			bindingType = this.BindingType.ArrayElement;
45792
45793			this.resolvedProperty = nodeProperty;
45794			this.propertyIndex = propertyIndex;
45795
45796		} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
45797
45798			// must use copy for Object3D.Euler/Quaternion
45799
45800			bindingType = this.BindingType.HasFromToArray;
45801
45802			this.resolvedProperty = nodeProperty;
45803
45804		} else if ( Array.isArray( nodeProperty ) ) {
45805
45806			bindingType = this.BindingType.EntireArray;
45807
45808			this.resolvedProperty = nodeProperty;
45809
45810		} else {
45811
45812			this.propertyName = propertyName;
45813
45814		}
45815
45816		// select getter / setter
45817		this.getValue = this.GetterByBindingType[ bindingType ];
45818		this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
45819
45820	}
45821
45822	unbind() {
45823
45824		this.node = null;
45825
45826		// back to the prototype version of getValue / setValue
45827		// note: avoiding to mutate the shape of 'this' via 'delete'
45828		this.getValue = this._getValue_unbound;
45829		this.setValue = this._setValue_unbound;
45830
45831	}
45832
45833}
45834
45835PropertyBinding.Composite = Composite;
45836
45837PropertyBinding.prototype.BindingType = {
45838	Direct: 0,
45839	EntireArray: 1,
45840	ArrayElement: 2,
45841	HasFromToArray: 3
45842};
45843
45844PropertyBinding.prototype.Versioning = {
45845	None: 0,
45846	NeedsUpdate: 1,
45847	MatrixWorldNeedsUpdate: 2
45848};
45849
45850PropertyBinding.prototype.GetterByBindingType = [
45851
45852	PropertyBinding.prototype._getValue_direct,
45853	PropertyBinding.prototype._getValue_array,
45854	PropertyBinding.prototype._getValue_arrayElement,
45855	PropertyBinding.prototype._getValue_toArray,
45856
45857];
45858
45859PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
45860
45861	[
45862		// Direct
45863		PropertyBinding.prototype._setValue_direct,
45864		PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
45865		PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
45866
45867	], [
45868
45869		// EntireArray
45870
45871		PropertyBinding.prototype._setValue_array,
45872		PropertyBinding.prototype._setValue_array_setNeedsUpdate,
vendor: 4,282 bytes, lines 45873-46053
45873		PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
45874
45875	], [
45876
45877		// ArrayElement
45878		PropertyBinding.prototype._setValue_arrayElement,
45879		PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
45880		PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
45881
45882	], [
45883
45884		// HasToFromArray
45885		PropertyBinding.prototype._setValue_fromArray,
45886		PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
45887		PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
45888
45889	]
45890
45891];
45892
45893/**
45894 *
45895 * A group of objects that receives a shared animation state.
45896 *
45897 * Usage:
45898 *
45899 *  - Add objects you would otherwise pass as 'root' to the
45900 *    constructor or the .clipAction method of AnimationMixer.
45901 *
45902 *  - Instead pass this object as 'root'.
45903 *
45904 *  - You can also add and remove objects later when the mixer
45905 *    is running.
45906 *
45907 * Note:
45908 *
45909 *    Objects of this class appear as one object to the mixer,
45910 *    so cache control of the individual objects must be done
45911 *    on the group.
45912 *
45913 * Limitation:
45914 *
45915 *  - The animated properties must be compatible among the
45916 *    all objects in the group.
45917 *
45918 *  - A single property can either be controlled through a
45919 *    target group or directly, but not both.
45920 */
45921
45922class AnimationObjectGroup {
45923
45924	constructor() {
45925
45926		this.isAnimationObjectGroup = true;
45927
45928		this.uuid = generateUUID();
45929
45930		// cached objects followed by the active ones
45931		this._objects = Array.prototype.slice.call( arguments );
45932
45933		this.nCachedObjects_ = 0; // threshold
45934		// note: read by PropertyBinding.Composite
45935
45936		const indices = {};
45937		this._indicesByUUID = indices; // for bookkeeping
45938
45939		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
45940
45941			indices[ arguments[ i ].uuid ] = i;
45942
45943		}
45944
45945		this._paths = []; // inside: string
45946		this._parsedPaths = []; // inside: { we don't care, here }
45947		this._bindings = []; // inside: Array< PropertyBinding >
45948		this._bindingsIndicesByPath = {}; // inside: indices in these arrays
45949
45950		const scope = this;
45951
45952		this.stats = {
45953
45954			objects: {
45955				get total() {
45956
45957					return scope._objects.length;
45958
45959				},
45960				get inUse() {
45961
45962					return this.total - scope.nCachedObjects_;
45963
45964				}
45965			},
45966			get bindingsPerObject() {
45967
45968				return scope._bindings.length;
45969
45970			}
45971
45972		};
45973
45974	}
45975
45976	add() {
45977
45978		const objects = this._objects,
45979			indicesByUUID = this._indicesByUUID,
45980			paths = this._paths,
45981			parsedPaths = this._parsedPaths,
45982			bindings = this._bindings,
45983			nBindings = bindings.length;
45984
45985		let knownObject = undefined,
45986			nObjects = objects.length,
45987			nCachedObjects = this.nCachedObjects_;
45988
45989		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
45990
45991			const object = arguments[ i ],
45992				uuid = object.uuid;
45993			let index = indicesByUUID[ uuid ];
45994
45995			if ( index === undefined ) {
45996
45997				// unknown object -> add it to the ACTIVE region
45998
45999				index = nObjects ++;
46000				indicesByUUID[ uuid ] = index;
46001				objects.push( object );
46002
46003				// accounting is done, now do the same for all bindings
46004
46005				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
46006
46007					bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
46008
46009				}
46010
46011			} else if ( index < nCachedObjects ) {
46012
46013				knownObject = objects[ index ];
46014
46015				// move existing object to the ACTIVE region
46016
46017				const firstActiveIndex = -- nCachedObjects,
46018					lastCachedObject = objects[ firstActiveIndex ];
46019
46020				indicesByUUID[ lastCachedObject.uuid ] = index;
46021				objects[ index ] = lastCachedObject;
46022
46023				indicesByUUID[ uuid ] = firstActiveIndex;
46024				objects[ firstActiveIndex ] = object;
46025
46026				// accounting is done, now do the same for all bindings
46027
46028				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
46029
46030					const bindingsForPath = bindings[ j ],
46031						lastCached = bindingsForPath[ firstActiveIndex ];
46032
46033					let binding = bindingsForPath[ index ];
46034
46035					bindingsForPath[ index ] = lastCached;
46036
46037					if ( binding === undefined ) {
46038
46039						// since we do not bother to create new bindings
46040						// for objects that are cached, the binding may
46041						// or may not exist
46042
46043						binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
46044
46045					}
46046
46047					bindingsForPath[ firstActiveIndex ] = binding;
46048
46049				}
46050
46051			} else if ( objects[ index ] !== knownObject ) {
46052
46053				console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
vendor: 4,120 bytes, lines 46054-46220
46054					'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
46055
46056			} // else the object is already where we want it to be
46057
46058		} // for arguments
46059
46060		this.nCachedObjects_ = nCachedObjects;
46061
46062	}
46063
46064	remove() {
46065
46066		const objects = this._objects,
46067			indicesByUUID = this._indicesByUUID,
46068			bindings = this._bindings,
46069			nBindings = bindings.length;
46070
46071		let nCachedObjects = this.nCachedObjects_;
46072
46073		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
46074
46075			const object = arguments[ i ],
46076				uuid = object.uuid,
46077				index = indicesByUUID[ uuid ];
46078
46079			if ( index !== undefined && index >= nCachedObjects ) {
46080
46081				// move existing object into the CACHED region
46082
46083				const lastCachedIndex = nCachedObjects ++,
46084					firstActiveObject = objects[ lastCachedIndex ];
46085
46086				indicesByUUID[ firstActiveObject.uuid ] = index;
46087				objects[ index ] = firstActiveObject;
46088
46089				indicesByUUID[ uuid ] = lastCachedIndex;
46090				objects[ lastCachedIndex ] = object;
46091
46092				// accounting is done, now do the same for all bindings
46093
46094				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
46095
46096					const bindingsForPath = bindings[ j ],
46097						firstActive = bindingsForPath[ lastCachedIndex ],
46098						binding = bindingsForPath[ index ];
46099
46100					bindingsForPath[ index ] = firstActive;
46101					bindingsForPath[ lastCachedIndex ] = binding;
46102
46103				}
46104
46105			}
46106
46107		} // for arguments
46108
46109		this.nCachedObjects_ = nCachedObjects;
46110
46111	}
46112
46113	// remove & forget
46114	uncache() {
46115
46116		const objects = this._objects,
46117			indicesByUUID = this._indicesByUUID,
46118			bindings = this._bindings,
46119			nBindings = bindings.length;
46120
46121		let nCachedObjects = this.nCachedObjects_,
46122			nObjects = objects.length;
46123
46124		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
46125
46126			const object = arguments[ i ],
46127				uuid = object.uuid,
46128				index = indicesByUUID[ uuid ];
46129
46130			if ( index !== undefined ) {
46131
46132				delete indicesByUUID[ uuid ];
46133
46134				if ( index < nCachedObjects ) {
46135
46136					// object is cached, shrink the CACHED region
46137
46138					const firstActiveIndex = -- nCachedObjects,
46139						lastCachedObject = objects[ firstActiveIndex ],
46140						lastIndex = -- nObjects,
46141						lastObject = objects[ lastIndex ];
46142
46143					// last cached object takes this object's place
46144					indicesByUUID[ lastCachedObject.uuid ] = index;
46145					objects[ index ] = lastCachedObject;
46146
46147					// last object goes to the activated slot and pop
46148					indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
46149					objects[ firstActiveIndex ] = lastObject;
46150					objects.pop();
46151
46152					// accounting is done, now do the same for all bindings
46153
46154					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
46155
46156						const bindingsForPath = bindings[ j ],
46157							lastCached = bindingsForPath[ firstActiveIndex ],
46158							last = bindingsForPath[ lastIndex ];
46159
46160						bindingsForPath[ index ] = lastCached;
46161						bindingsForPath[ firstActiveIndex ] = last;
46162						bindingsForPath.pop();
46163
46164					}
46165
46166				} else {
46167
46168					// object is active, just swap with the last and pop
46169
46170					const lastIndex = -- nObjects,
46171						lastObject = objects[ lastIndex ];
46172
46173					if ( lastIndex > 0 ) {
46174
46175						indicesByUUID[ lastObject.uuid ] = index;
46176
46177					}
46178
46179					objects[ index ] = lastObject;
46180					objects.pop();
46181
46182					// accounting is done, now do the same for all bindings
46183
46184					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
46185
46186						const bindingsForPath = bindings[ j ];
46187
46188						bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
46189						bindingsForPath.pop();
46190
46191					}
46192
46193				} // cached or active
46194
46195			} // if object is known
46196
46197		} // for arguments
46198
46199		this.nCachedObjects_ = nCachedObjects;
46200
46201	}
46202
46203	// Internal interface used by befriended PropertyBinding.Composite:
46204
46205	subscribe_( path, parsedPath ) {
46206
46207		// returns an array of bindings for the given path that is changed
46208		// according to the contained objects in the group
46209
46210		const indicesByPath = this._bindingsIndicesByPath;
46211		let index = indicesByPath[ path ];
46212		const bindings = this._bindings;
46213
46214		if ( index !== undefined ) return bindings[ index ];
46215
46216		const paths = this._paths,
46217			parsedPaths = this._parsedPaths,
46218			objects = this._objects,
46219			nObjects = objects.length,
46220			nCachedObjects = this.nCachedObjects_,
vendor: 7,613 bytes, lines 46221-46614
46221			bindingsForPath = new Array( nObjects );
46222
46223		index = bindings.length;
46224
46225		indicesByPath[ path ] = index;
46226
46227		paths.push( path );
46228		parsedPaths.push( parsedPath );
46229		bindings.push( bindingsForPath );
46230
46231		for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
46232
46233			const object = objects[ i ];
46234			bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
46235
46236		}
46237
46238		return bindingsForPath;
46239
46240	}
46241
46242	unsubscribe_( path ) {
46243
46244		// tells the group to forget about a property path and no longer
46245		// update the array previously obtained with 'subscribe_'
46246
46247		const indicesByPath = this._bindingsIndicesByPath,
46248			index = indicesByPath[ path ];
46249
46250		if ( index !== undefined ) {
46251
46252			const paths = this._paths,
46253				parsedPaths = this._parsedPaths,
46254				bindings = this._bindings,
46255				lastBindingsIndex = bindings.length - 1,
46256				lastBindings = bindings[ lastBindingsIndex ],
46257				lastBindingsPath = path[ lastBindingsIndex ];
46258
46259			indicesByPath[ lastBindingsPath ] = index;
46260
46261			bindings[ index ] = lastBindings;
46262			bindings.pop();
46263
46264			parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
46265			parsedPaths.pop();
46266
46267			paths[ index ] = paths[ lastBindingsIndex ];
46268			paths.pop();
46269
46270		}
46271
46272	}
46273
46274}
46275
46276class AnimationAction {
46277
46278	constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
46279
46280		this._mixer = mixer;
46281		this._clip = clip;
46282		this._localRoot = localRoot;
46283		this.blendMode = blendMode;
46284
46285		const tracks = clip.tracks,
46286			nTracks = tracks.length,
46287			interpolants = new Array( nTracks );
46288
46289		const interpolantSettings = {
46290			endingStart: ZeroCurvatureEnding,
46291			endingEnd: ZeroCurvatureEnding
46292		};
46293
46294		for ( let i = 0; i !== nTracks; ++ i ) {
46295
46296			const interpolant = tracks[ i ].createInterpolant( null );
46297			interpolants[ i ] = interpolant;
46298			interpolant.settings = interpolantSettings;
46299
46300		}
46301
46302		this._interpolantSettings = interpolantSettings;
46303
46304		this._interpolants = interpolants; // bound by the mixer
46305
46306		// inside: PropertyMixer (managed by the mixer)
46307		this._propertyBindings = new Array( nTracks );
46308
46309		this._cacheIndex = null; // for the memory manager
46310		this._byClipCacheIndex = null; // for the memory manager
46311
46312		this._timeScaleInterpolant = null;
46313		this._weightInterpolant = null;
46314
46315		this.loop = LoopRepeat;
46316		this._loopCount = - 1;
46317
46318		// global mixer time when the action is to be started
46319		// it's set back to 'null' upon start of the action
46320		this._startTime = null;
46321
46322		// scaled local time of the action
46323		// gets clamped or wrapped to 0..clip.duration according to loop
46324		this.time = 0;
46325
46326		this.timeScale = 1;
46327		this._effectiveTimeScale = 1;
46328
46329		this.weight = 1;
46330		this._effectiveWeight = 1;
46331
46332		this.repetitions = Infinity; // no. of repetitions when looping
46333
46334		this.paused = false; // true -> zero effective time scale
46335		this.enabled = true; // false -> zero effective weight
46336
46337		this.clampWhenFinished = false;// keep feeding the last frame?
46338
46339		this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
46340		this.zeroSlopeAtEnd = true;// clips for start, loop and end
46341
46342	}
46343
46344	// State & Scheduling
46345
46346	play() {
46347
46348		this._mixer._activateAction( this );
46349
46350		return this;
46351
46352	}
46353
46354	stop() {
46355
46356		this._mixer._deactivateAction( this );
46357
46358		return this.reset();
46359
46360	}
46361
46362	reset() {
46363
46364		this.paused = false;
46365		this.enabled = true;
46366
46367		this.time = 0; // restart clip
46368		this._loopCount = - 1;// forget previous loops
46369		this._startTime = null;// forget scheduling
46370
46371		return this.stopFading().stopWarping();
46372
46373	}
46374
46375	isRunning() {
46376
46377		return this.enabled && ! this.paused && this.timeScale !== 0 &&
46378			this._startTime === null && this._mixer._isActiveAction( this );
46379
46380	}
46381
46382	// return true when play has been called
46383	isScheduled() {
46384
46385		return this._mixer._isActiveAction( this );
46386
46387	}
46388
46389	startAt( time ) {
46390
46391		this._startTime = time;
46392
46393		return this;
46394
46395	}
46396
46397	setLoop( mode, repetitions ) {
46398
46399		this.loop = mode;
46400		this.repetitions = repetitions;
46401
46402		return this;
46403
46404	}
46405
46406	// Weight
46407
46408	// set the weight stopping any scheduled fading
46409	// although .enabled = false yields an effective weight of zero, this
46410	// method does *not* change .enabled, because it would be confusing
46411	setEffectiveWeight( weight ) {
46412
46413		this.weight = weight;
46414
46415		// note: same logic as when updated at runtime
46416		this._effectiveWeight = this.enabled ? weight : 0;
46417
46418		return this.stopFading();
46419
46420	}
46421
46422	// return the weight considering fading and .enabled
46423	getEffectiveWeight() {
46424
46425		return this._effectiveWeight;
46426
46427	}
46428
46429	fadeIn( duration ) {
46430
46431		return this._scheduleFading( duration, 0, 1 );
46432
46433	}
46434
46435	fadeOut( duration ) {
46436
46437		return this._scheduleFading( duration, 1, 0 );
46438
46439	}
46440
46441	crossFadeFrom( fadeOutAction, duration, warp ) {
46442
46443		fadeOutAction.fadeOut( duration );
46444		this.fadeIn( duration );
46445
46446		if ( warp ) {
46447
46448			const fadeInDuration = this._clip.duration,
46449				fadeOutDuration = fadeOutAction._clip.duration,
46450
46451				startEndRatio = fadeOutDuration / fadeInDuration,
46452				endStartRatio = fadeInDuration / fadeOutDuration;
46453
46454			fadeOutAction.warp( 1.0, startEndRatio, duration );
46455			this.warp( endStartRatio, 1.0, duration );
46456
46457		}
46458
46459		return this;
46460
46461	}
46462
46463	crossFadeTo( fadeInAction, duration, warp ) {
46464
46465		return fadeInAction.crossFadeFrom( this, duration, warp );
46466
46467	}
46468
46469	stopFading() {
46470
46471		const weightInterpolant = this._weightInterpolant;
46472
46473		if ( weightInterpolant !== null ) {
46474
46475			this._weightInterpolant = null;
46476			this._mixer._takeBackControlInterpolant( weightInterpolant );
46477
46478		}
46479
46480		return this;
46481
46482	}
46483
46484	// Time Scale Control
46485
46486	// set the time scale stopping any scheduled warping
46487	// although .paused = true yields an effective time scale of zero, this
46488	// method does *not* change .paused, because it would be confusing
46489	setEffectiveTimeScale( timeScale ) {
46490
46491		this.timeScale = timeScale;
46492		this._effectiveTimeScale = this.paused ? 0 : timeScale;
46493
46494		return this.stopWarping();
46495
46496	}
46497
46498	// return the time scale considering warping and .paused
46499	getEffectiveTimeScale() {
46500
46501		return this._effectiveTimeScale;
46502
46503	}
46504
46505	setDuration( duration ) {
46506
46507		this.timeScale = this._clip.duration / duration;
46508
46509		return this.stopWarping();
46510
46511	}
46512
46513	syncWith( action ) {
46514
46515		this.time = action.time;
46516		this.timeScale = action.timeScale;
46517
46518		return this.stopWarping();
46519
46520	}
46521
46522	halt( duration ) {
46523
46524		return this.warp( this._effectiveTimeScale, 0, duration );
46525
46526	}
46527
46528	warp( startTimeScale, endTimeScale, duration ) {
46529
46530		const mixer = this._mixer,
46531			now = mixer.time,
46532			timeScale = this.timeScale;
46533
46534		let interpolant = this._timeScaleInterpolant;
46535
46536		if ( interpolant === null ) {
46537
46538			interpolant = mixer._lendControlInterpolant();
46539			this._timeScaleInterpolant = interpolant;
46540
46541		}
46542
46543		const times = interpolant.parameterPositions,
46544			values = interpolant.sampleValues;
46545
46546		times[ 0 ] = now;
46547		times[ 1 ] = now + duration;
46548
46549		values[ 0 ] = startTimeScale / timeScale;
46550		values[ 1 ] = endTimeScale / timeScale;
46551
46552		return this;
46553
46554	}
46555
46556	stopWarping() {
46557
46558		const timeScaleInterpolant = this._timeScaleInterpolant;
46559
46560		if ( timeScaleInterpolant !== null ) {
46561
46562			this._timeScaleInterpolant = null;
46563			this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
46564
46565		}
46566
46567		return this;
46568
46569	}
46570
46571	// Object Accessors
46572
46573	getMixer() {
46574
46575		return this._mixer;
46576
46577	}
46578
46579	getClip() {
46580
46581		return this._clip;
46582
46583	}
46584
46585	getRoot() {
46586
46587		return this._localRoot || this._mixer._root;
46588
46589	}
46590
46591	// Interna
46592
46593	_update( time, deltaTime, timeDirection, accuIndex ) {
46594
46595		// called by the mixer
46596
46597		if ( ! this.enabled ) {
46598
46599			// call ._updateWeight() to update ._effectiveWeight
46600
46601			this._updateWeight( time );
46602			return;
46603
46604		}
46605
46606		const startTime = this._startTime;
46607
46608		if ( startTime !== null ) {
46609
46610			// check for scheduled start of action
46611
46612			const timeRunning = ( time - startTime ) * timeDirection;
46613			if ( timeRunning < 0 || timeDirection === 0 ) {
46614
vendor: 6,044 bytes, lines 46615-46973
46615				deltaTime = 0;
46616
46617			} else {
46618
46619
46620				this._startTime = null; // unschedule
46621				deltaTime = timeDirection * timeRunning;
46622
46623			}
46624
46625		}
46626
46627		// apply time scale and advance time
46628
46629		deltaTime *= this._updateTimeScale( time );
46630		const clipTime = this._updateTime( deltaTime );
46631
46632		// note: _updateTime may disable the action resulting in
46633		// an effective weight of 0
46634
46635		const weight = this._updateWeight( time );
46636
46637		if ( weight > 0 ) {
46638
46639			const interpolants = this._interpolants;
46640			const propertyMixers = this._propertyBindings;
46641
46642			switch ( this.blendMode ) {
46643
46644				case AdditiveAnimationBlendMode:
46645
46646					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
46647
46648						interpolants[ j ].evaluate( clipTime );
46649						propertyMixers[ j ].accumulateAdditive( weight );
46650
46651					}
46652
46653					break;
46654
46655				case NormalAnimationBlendMode:
46656				default:
46657
46658					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
46659
46660						interpolants[ j ].evaluate( clipTime );
46661						propertyMixers[ j ].accumulate( accuIndex, weight );
46662
46663					}
46664
46665			}
46666
46667		}
46668
46669	}
46670
46671	_updateWeight( time ) {
46672
46673		let weight = 0;
46674
46675		if ( this.enabled ) {
46676
46677			weight = this.weight;
46678			const interpolant = this._weightInterpolant;
46679
46680			if ( interpolant !== null ) {
46681
46682				const interpolantValue = interpolant.evaluate( time )[ 0 ];
46683
46684				weight *= interpolantValue;
46685
46686				if ( time > interpolant.parameterPositions[ 1 ] ) {
46687
46688					this.stopFading();
46689
46690					if ( interpolantValue === 0 ) {
46691
46692						// faded out, disable
46693						this.enabled = false;
46694
46695					}
46696
46697				}
46698
46699			}
46700
46701		}
46702
46703		this._effectiveWeight = weight;
46704		return weight;
46705
46706	}
46707
46708	_updateTimeScale( time ) {
46709
46710		let timeScale = 0;
46711
46712		if ( ! this.paused ) {
46713
46714			timeScale = this.timeScale;
46715
46716			const interpolant = this._timeScaleInterpolant;
46717
46718			if ( interpolant !== null ) {
46719
46720				const interpolantValue = interpolant.evaluate( time )[ 0 ];
46721
46722				timeScale *= interpolantValue;
46723
46724				if ( time > interpolant.parameterPositions[ 1 ] ) {
46725
46726					this.stopWarping();
46727
46728					if ( timeScale === 0 ) {
46729
46730						// motion has halted, pause
46731						this.paused = true;
46732
46733					} else {
46734
46735						// warp done - apply final time scale
46736						this.timeScale = timeScale;
46737
46738					}
46739
46740				}
46741
46742			}
46743
46744		}
46745
46746		this._effectiveTimeScale = timeScale;
46747		return timeScale;
46748
46749	}
46750
46751	_updateTime( deltaTime ) {
46752
46753		const duration = this._clip.duration;
46754		const loop = this.loop;
46755
46756		let time = this.time + deltaTime;
46757		let loopCount = this._loopCount;
46758
46759		const pingPong = ( loop === LoopPingPong );
46760
46761		if ( deltaTime === 0 ) {
46762
46763			if ( loopCount === - 1 ) return time;
46764
46765			return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
46766
46767		}
46768
46769		if ( loop === LoopOnce ) {
46770
46771			if ( loopCount === - 1 ) {
46772
46773				// just started
46774
46775				this._loopCount = 0;
46776				this._setEndings( true, true, false );
46777
46778			}
46779
46780			handle_stop: {
46781
46782				if ( time >= duration ) {
46783
46784					time = duration;
46785
46786				} else if ( time < 0 ) {
46787
46788					time = 0;
46789
46790				} else {
46791
46792					this.time = time;
46793
46794					break handle_stop;
46795
46796				}
46797
46798				if ( this.clampWhenFinished ) this.paused = true;
46799				else this.enabled = false;
46800
46801				this.time = time;
46802
46803				this._mixer.dispatchEvent( {
46804					type: 'finished', action: this,
46805					direction: deltaTime < 0 ? - 1 : 1
46806				} );
46807
46808			}
46809
46810		} else { // repetitive Repeat or PingPong
46811
46812			if ( loopCount === - 1 ) {
46813
46814				// just started
46815
46816				if ( deltaTime >= 0 ) {
46817
46818					loopCount = 0;
46819
46820					this._setEndings( true, this.repetitions === 0, pingPong );
46821
46822				} else {
46823
46824					// when looping in reverse direction, the initial
46825					// transition through zero counts as a repetition,
46826					// so leave loopCount at -1
46827
46828					this._setEndings( this.repetitions === 0, true, pingPong );
46829
46830				}
46831
46832			}
46833
46834			if ( time >= duration || time < 0 ) {
46835
46836				// wrap around
46837
46838				const loopDelta = Math.floor( time / duration ); // signed
46839				time -= duration * loopDelta;
46840
46841				loopCount += Math.abs( loopDelta );
46842
46843				const pending = this.repetitions - loopCount;
46844
46845				if ( pending <= 0 ) {
46846
46847					// have to stop (switch state, clamp time, fire event)
46848
46849					if ( this.clampWhenFinished ) this.paused = true;
46850					else this.enabled = false;
46851
46852					time = deltaTime > 0 ? duration : 0;
46853
46854					this.time = time;
46855
46856					this._mixer.dispatchEvent( {
46857						type: 'finished', action: this,
46858						direction: deltaTime > 0 ? 1 : - 1
46859					} );
46860
46861				} else {
46862
46863					// keep running
46864
46865					if ( pending === 1 ) {
46866
46867						// entering the last round
46868
46869						const atStart = deltaTime < 0;
46870						this._setEndings( atStart, ! atStart, pingPong );
46871
46872					} else {
46873
46874						this._setEndings( false, false, pingPong );
46875
46876					}
46877
46878					this._loopCount = loopCount;
46879
46880					this.time = time;
46881
46882					this._mixer.dispatchEvent( {
46883						type: 'loop', action: this, loopDelta: loopDelta
46884					} );
46885
46886				}
46887
46888			} else {
46889
46890				this.time = time;
46891
46892			}
46893
46894			if ( pingPong && ( loopCount & 1 ) === 1 ) {
46895
46896				// invert time for the "pong round"
46897
46898				return duration - time;
46899
46900			}
46901
46902		}
46903
46904		return time;
46905
46906	}
46907
46908	_setEndings( atStart, atEnd, pingPong ) {
46909
46910		const settings = this._interpolantSettings;
46911
46912		if ( pingPong ) {
46913
46914			settings.endingStart = ZeroSlopeEnding;
46915			settings.endingEnd = ZeroSlopeEnding;
46916
46917		} else {
46918
46919			// assuming for LoopOnce atStart == atEnd == true
46920
46921			if ( atStart ) {
46922
46923				settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
46924
46925			} else {
46926
46927				settings.endingStart = WrapAroundEnding;
46928
46929			}
46930
46931			if ( atEnd ) {
46932
46933				settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
46934
46935			} else {
46936
46937				settings.endingEnd 	 = WrapAroundEnding;
46938
46939			}
46940
46941		}
46942
46943	}
46944
46945	_scheduleFading( duration, weightNow, weightThen ) {
46946
46947		const mixer = this._mixer, now = mixer.time;
46948		let interpolant = this._weightInterpolant;
46949
46950		if ( interpolant === null ) {
46951
46952			interpolant = mixer._lendControlInterpolant();
46953			this._weightInterpolant = interpolant;
46954
46955		}
46956
46957		const times = interpolant.parameterPositions,
46958			values = interpolant.sampleValues;
46959
46960		times[ 0 ] = now;
46961		values[ 0 ] = weightNow;
46962		times[ 1 ] = now + duration;
46963		values[ 1 ] = weightThen;
46964
46965		return this;
46966
46967	}
46968
46969}
46970
46971const _controlInterpolantsResultBuffer = new Float32Array( 1 );
46972
46973
vendor: 13,381 bytes, lines 46974-47614
46974class AnimationMixer extends EventDispatcher {
46975
46976	constructor( root ) {
46977
46978		super();
46979
46980		this._root = root;
46981		this._initMemoryManager();
46982		this._accuIndex = 0;
46983		this.time = 0;
46984		this.timeScale = 1.0;
46985
46986	}
46987
46988	_bindAction( action, prototypeAction ) {
46989
46990		const root = action._localRoot || this._root,
46991			tracks = action._clip.tracks,
46992			nTracks = tracks.length,
46993			bindings = action._propertyBindings,
46994			interpolants = action._interpolants,
46995			rootUuid = root.uuid,
46996			bindingsByRoot = this._bindingsByRootAndName;
46997
46998		let bindingsByName = bindingsByRoot[ rootUuid ];
46999
47000		if ( bindingsByName === undefined ) {
47001
47002			bindingsByName = {};
47003			bindingsByRoot[ rootUuid ] = bindingsByName;
47004
47005		}
47006
47007		for ( let i = 0; i !== nTracks; ++ i ) {
47008
47009			const track = tracks[ i ],
47010				trackName = track.name;
47011
47012			let binding = bindingsByName[ trackName ];
47013
47014			if ( binding !== undefined ) {
47015
47016				++ binding.referenceCount;
47017				bindings[ i ] = binding;
47018
47019			} else {
47020
47021				binding = bindings[ i ];
47022
47023				if ( binding !== undefined ) {
47024
47025					// existing binding, make sure the cache knows
47026
47027					if ( binding._cacheIndex === null ) {
47028
47029						++ binding.referenceCount;
47030						this._addInactiveBinding( binding, rootUuid, trackName );
47031
47032					}
47033
47034					continue;
47035
47036				}
47037
47038				const path = prototypeAction && prototypeAction.
47039					_propertyBindings[ i ].binding.parsedPath;
47040
47041				binding = new PropertyMixer(
47042					PropertyBinding.create( root, trackName, path ),
47043					track.ValueTypeName, track.getValueSize() );
47044
47045				++ binding.referenceCount;
47046				this._addInactiveBinding( binding, rootUuid, trackName );
47047
47048				bindings[ i ] = binding;
47049
47050			}
47051
47052			interpolants[ i ].resultBuffer = binding.buffer;
47053
47054		}
47055
47056	}
47057
47058	_activateAction( action ) {
47059
47060		if ( ! this._isActiveAction( action ) ) {
47061
47062			if ( action._cacheIndex === null ) {
47063
47064				// this action has been forgotten by the cache, but the user
47065				// appears to be still using it -> rebind
47066
47067				const rootUuid = ( action._localRoot || this._root ).uuid,
47068					clipUuid = action._clip.uuid,
47069					actionsForClip = this._actionsByClip[ clipUuid ];
47070
47071				this._bindAction( action,
47072					actionsForClip && actionsForClip.knownActions[ 0 ] );
47073
47074				this._addInactiveAction( action, clipUuid, rootUuid );
47075
47076			}
47077
47078			const bindings = action._propertyBindings;
47079
47080			// increment reference counts / sort out state
47081			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
47082
47083				const binding = bindings[ i ];
47084
47085				if ( binding.useCount ++ === 0 ) {
47086
47087					this._lendBinding( binding );
47088					binding.saveOriginalState();
47089
47090				}
47091
47092			}
47093
47094			this._lendAction( action );
47095
47096		}
47097
47098	}
47099
47100	_deactivateAction( action ) {
47101
47102		if ( this._isActiveAction( action ) ) {
47103
47104			const bindings = action._propertyBindings;
47105
47106			// decrement reference counts / sort out state
47107			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
47108
47109				const binding = bindings[ i ];
47110
47111				if ( -- binding.useCount === 0 ) {
47112
47113					binding.restoreOriginalState();
47114					this._takeBackBinding( binding );
47115
47116				}
47117
47118			}
47119
47120			this._takeBackAction( action );
47121
47122		}
47123
47124	}
47125
47126	// Memory manager
47127
47128	_initMemoryManager() {
47129
47130		this._actions = []; // 'nActiveActions' followed by inactive ones
47131		this._nActiveActions = 0;
47132
47133		this._actionsByClip = {};
47134		// inside:
47135		// {
47136		// 	knownActions: Array< AnimationAction > - used as prototypes
47137		// 	actionByRoot: AnimationAction - lookup
47138		// }
47139
47140
47141		this._bindings = []; // 'nActiveBindings' followed by inactive ones
47142		this._nActiveBindings = 0;
47143
47144		this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
47145
47146
47147		this._controlInterpolants = []; // same game as above
47148		this._nActiveControlInterpolants = 0;
47149
47150		const scope = this;
47151
47152		this.stats = {
47153
47154			actions: {
47155				get total() {
47156
47157					return scope._actions.length;
47158
47159				},
47160				get inUse() {
47161
47162					return scope._nActiveActions;
47163
47164				}
47165			},
47166			bindings: {
47167				get total() {
47168
47169					return scope._bindings.length;
47170
47171				},
47172				get inUse() {
47173
47174					return scope._nActiveBindings;
47175
47176				}
47177			},
47178			controlInterpolants: {
47179				get total() {
47180
47181					return scope._controlInterpolants.length;
47182
47183				},
47184				get inUse() {
47185
47186					return scope._nActiveControlInterpolants;
47187
47188				}
47189			}
47190
47191		};
47192
47193	}
47194
47195	// Memory management for AnimationAction objects
47196
47197	_isActiveAction( action ) {
47198
47199		const index = action._cacheIndex;
47200		return index !== null && index < this._nActiveActions;
47201
47202	}
47203
47204	_addInactiveAction( action, clipUuid, rootUuid ) {
47205
47206		const actions = this._actions,
47207			actionsByClip = this._actionsByClip;
47208
47209		let actionsForClip = actionsByClip[ clipUuid ];
47210
47211		if ( actionsForClip === undefined ) {
47212
47213			actionsForClip = {
47214
47215				knownActions: [ action ],
47216				actionByRoot: {}
47217
47218			};
47219
47220			action._byClipCacheIndex = 0;
47221
47222			actionsByClip[ clipUuid ] = actionsForClip;
47223
47224		} else {
47225
47226			const knownActions = actionsForClip.knownActions;
47227
47228			action._byClipCacheIndex = knownActions.length;
47229			knownActions.push( action );
47230
47231		}
47232
47233		action._cacheIndex = actions.length;
47234		actions.push( action );
47235
47236		actionsForClip.actionByRoot[ rootUuid ] = action;
47237
47238	}
47239
47240	_removeInactiveAction( action ) {
47241
47242		const actions = this._actions,
47243			lastInactiveAction = actions[ actions.length - 1 ],
47244			cacheIndex = action._cacheIndex;
47245
47246		lastInactiveAction._cacheIndex = cacheIndex;
47247		actions[ cacheIndex ] = lastInactiveAction;
47248		actions.pop();
47249
47250		action._cacheIndex = null;
47251
47252
47253		const clipUuid = action._clip.uuid,
47254			actionsByClip = this._actionsByClip,
47255			actionsForClip = actionsByClip[ clipUuid ],
47256			knownActionsForClip = actionsForClip.knownActions,
47257
47258			lastKnownAction =
47259				knownActionsForClip[ knownActionsForClip.length - 1 ],
47260
47261			byClipCacheIndex = action._byClipCacheIndex;
47262
47263		lastKnownAction._byClipCacheIndex = byClipCacheIndex;
47264		knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
47265		knownActionsForClip.pop();
47266
47267		action._byClipCacheIndex = null;
47268
47269
47270		const actionByRoot = actionsForClip.actionByRoot,
47271			rootUuid = ( action._localRoot || this._root ).uuid;
47272
47273		delete actionByRoot[ rootUuid ];
47274
47275		if ( knownActionsForClip.length === 0 ) {
47276
47277			delete actionsByClip[ clipUuid ];
47278
47279		}
47280
47281		this._removeInactiveBindingsForAction( action );
47282
47283	}
47284
47285	_removeInactiveBindingsForAction( action ) {
47286
47287		const bindings = action._propertyBindings;
47288
47289		for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
47290
47291			const binding = bindings[ i ];
47292
47293			if ( -- binding.referenceCount === 0 ) {
47294
47295				this._removeInactiveBinding( binding );
47296
47297			}
47298
47299		}
47300
47301	}
47302
47303	_lendAction( action ) {
47304
47305		// [ active actions |  inactive actions  ]
47306		// [  active actions >| inactive actions ]
47307		//                 s        a
47308		//                  <-swap->
47309		//                 a        s
47310
47311		const actions = this._actions,
47312			prevIndex = action._cacheIndex,
47313
47314			lastActiveIndex = this._nActiveActions ++,
47315
47316			firstInactiveAction = actions[ lastActiveIndex ];
47317
47318		action._cacheIndex = lastActiveIndex;
47319		actions[ lastActiveIndex ] = action;
47320
47321		firstInactiveAction._cacheIndex = prevIndex;
47322		actions[ prevIndex ] = firstInactiveAction;
47323
47324	}
47325
47326	_takeBackAction( action ) {
47327
47328		// [  active actions  | inactive actions ]
47329		// [ active actions |< inactive actions  ]
47330		//        a        s
47331		//         <-swap->
47332		//        s        a
47333
47334		const actions = this._actions,
47335			prevIndex = action._cacheIndex,
47336
47337			firstInactiveIndex = -- this._nActiveActions,
47338
47339			lastActiveAction = actions[ firstInactiveIndex ];
47340
47341		action._cacheIndex = firstInactiveIndex;
47342		actions[ firstInactiveIndex ] = action;
47343
47344		lastActiveAction._cacheIndex = prevIndex;
47345		actions[ prevIndex ] = lastActiveAction;
47346
47347	}
47348
47349	// Memory management for PropertyMixer objects
47350
47351	_addInactiveBinding( binding, rootUuid, trackName ) {
47352
47353		const bindingsByRoot = this._bindingsByRootAndName,
47354			bindings = this._bindings;
47355
47356		let bindingByName = bindingsByRoot[ rootUuid ];
47357
47358		if ( bindingByName === undefined ) {
47359
47360			bindingByName = {};
47361			bindingsByRoot[ rootUuid ] = bindingByName;
47362
47363		}
47364
47365		bindingByName[ trackName ] = binding;
47366
47367		binding._cacheIndex = bindings.length;
47368		bindings.push( binding );
47369
47370	}
47371
47372	_removeInactiveBinding( binding ) {
47373
47374		const bindings = this._bindings,
47375			propBinding = binding.binding,
47376			rootUuid = propBinding.rootNode.uuid,
47377			trackName = propBinding.path,
47378			bindingsByRoot = this._bindingsByRootAndName,
47379			bindingByName = bindingsByRoot[ rootUuid ],
47380
47381			lastInactiveBinding = bindings[ bindings.length - 1 ],
47382			cacheIndex = binding._cacheIndex;
47383
47384		lastInactiveBinding._cacheIndex = cacheIndex;
47385		bindings[ cacheIndex ] = lastInactiveBinding;
47386		bindings.pop();
47387
47388		delete bindingByName[ trackName ];
47389
47390		if ( Object.keys( bindingByName ).length === 0 ) {
47391
47392			delete bindingsByRoot[ rootUuid ];
47393
47394		}
47395
47396	}
47397
47398	_lendBinding( binding ) {
47399
47400		const bindings = this._bindings,
47401			prevIndex = binding._cacheIndex,
47402
47403			lastActiveIndex = this._nActiveBindings ++,
47404
47405			firstInactiveBinding = bindings[ lastActiveIndex ];
47406
47407		binding._cacheIndex = lastActiveIndex;
47408		bindings[ lastActiveIndex ] = binding;
47409
47410		firstInactiveBinding._cacheIndex = prevIndex;
47411		bindings[ prevIndex ] = firstInactiveBinding;
47412
47413	}
47414
47415	_takeBackBinding( binding ) {
47416
47417		const bindings = this._bindings,
47418			prevIndex = binding._cacheIndex,
47419
47420			firstInactiveIndex = -- this._nActiveBindings,
47421
47422			lastActiveBinding = bindings[ firstInactiveIndex ];
47423
47424		binding._cacheIndex = firstInactiveIndex;
47425		bindings[ firstInactiveIndex ] = binding;
47426
47427		lastActiveBinding._cacheIndex = prevIndex;
47428		bindings[ prevIndex ] = lastActiveBinding;
47429
47430	}
47431
47432
47433	// Memory management of Interpolants for weight and time scale
47434
47435	_lendControlInterpolant() {
47436
47437		const interpolants = this._controlInterpolants,
47438			lastActiveIndex = this._nActiveControlInterpolants ++;
47439
47440		let interpolant = interpolants[ lastActiveIndex ];
47441
47442		if ( interpolant === undefined ) {
47443
47444			interpolant = new LinearInterpolant(
47445				new Float32Array( 2 ), new Float32Array( 2 ),
47446				1, _controlInterpolantsResultBuffer );
47447
47448			interpolant.__cacheIndex = lastActiveIndex;
47449			interpolants[ lastActiveIndex ] = interpolant;
47450
47451		}
47452
47453		return interpolant;
47454
47455	}
47456
47457	_takeBackControlInterpolant( interpolant ) {
47458
47459		const interpolants = this._controlInterpolants,
47460			prevIndex = interpolant.__cacheIndex,
47461
47462			firstInactiveIndex = -- this._nActiveControlInterpolants,
47463
47464			lastActiveInterpolant = interpolants[ firstInactiveIndex ];
47465
47466		interpolant.__cacheIndex = firstInactiveIndex;
47467		interpolants[ firstInactiveIndex ] = interpolant;
47468
47469		lastActiveInterpolant.__cacheIndex = prevIndex;
47470		interpolants[ prevIndex ] = lastActiveInterpolant;
47471
47472	}
47473
47474	// return an action for a clip optionally using a custom root target
47475	// object (this method allocates a lot of dynamic memory in case a
47476	// previously unknown clip/root combination is specified)
47477	clipAction( clip, optionalRoot, blendMode ) {
47478
47479		const root = optionalRoot || this._root,
47480			rootUuid = root.uuid;
47481
47482		let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
47483
47484		const clipUuid = clipObject !== null ? clipObject.uuid : clip;
47485
47486		const actionsForClip = this._actionsByClip[ clipUuid ];
47487		let prototypeAction = null;
47488
47489		if ( blendMode === undefined ) {
47490
47491			if ( clipObject !== null ) {
47492
47493				blendMode = clipObject.blendMode;
47494
47495			} else {
47496
47497				blendMode = NormalAnimationBlendMode;
47498
47499			}
47500
47501		}
47502
47503		if ( actionsForClip !== undefined ) {
47504
47505			const existingAction = actionsForClip.actionByRoot[ rootUuid ];
47506
47507			if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
47508
47509				return existingAction;
47510
47511			}
47512
47513			// we know the clip, so we don't have to parse all
47514			// the bindings again but can just copy
47515			prototypeAction = actionsForClip.knownActions[ 0 ];
47516
47517			// also, take the clip from the prototype action
47518			if ( clipObject === null )
47519				clipObject = prototypeAction._clip;
47520
47521		}
47522
47523		// clip must be known when specified via string
47524		if ( clipObject === null ) return null;
47525
47526		// allocate all resources required to run it
47527		const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
47528
47529		this._bindAction( newAction, prototypeAction );
47530
47531		// and make the action known to the memory manager
47532		this._addInactiveAction( newAction, clipUuid, rootUuid );
47533
47534		return newAction;
47535
47536	}
47537
47538	// get an existing action
47539	existingAction( clip, optionalRoot ) {
47540
47541		const root = optionalRoot || this._root,
47542			rootUuid = root.uuid,
47543
47544			clipObject = typeof clip === 'string' ?
47545				AnimationClip.findByName( root, clip ) : clip,
47546
47547			clipUuid = clipObject ? clipObject.uuid : clip,
47548
47549			actionsForClip = this._actionsByClip[ clipUuid ];
47550
47551		if ( actionsForClip !== undefined ) {
47552
47553			return actionsForClip.actionByRoot[ rootUuid ] || null;
47554
47555		}
47556
47557		return null;
47558
47559	}
47560
47561	// deactivates all previously scheduled actions
47562	stopAllAction() {
47563
47564		const actions = this._actions,
47565			nActions = this._nActiveActions;
47566
47567		for ( let i = nActions - 1; i >= 0; -- i ) {
47568
47569			actions[ i ].stop();
47570
47571		}
47572
47573		return this;
47574
47575	}
47576
47577	// advance the time and update apply the animation
47578	update( deltaTime ) {
47579
47580		deltaTime *= this.timeScale;
47581
47582		const actions = this._actions,
47583			nActions = this._nActiveActions,
47584
47585			time = this.time += deltaTime,
47586			timeDirection = Math.sign( deltaTime ),
47587
47588			accuIndex = this._accuIndex ^= 1;
47589
47590		// run active actions
47591
47592		for ( let i = 0; i !== nActions; ++ i ) {
47593
47594			const action = actions[ i ];
47595
47596			action._update( time, deltaTime, timeDirection, accuIndex );
47597
47598		}
47599
47600		// update scene graph
47601
47602		const bindings = this._bindings,
47603			nBindings = this._nActiveBindings;
47604
47605		for ( let i = 0; i !== nBindings; ++ i ) {
47606
47607			bindings[ i ].apply( accuIndex );
47608
47609		}
47610
47611		return this;
47612
47613	}
47614
vendor: 2,762 bytes, lines 47615-47748
47615	// Allows you to seek to a specific time in an animation.
47616	setTime( timeInSeconds ) {
47617
47618		this.time = 0; // Zero out time attribute for AnimationMixer object;
47619		for ( let i = 0; i < this._actions.length; i ++ ) {
47620
47621			this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
47622
47623		}
47624
47625		return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
47626
47627	}
47628
47629	// return this mixer's root target object
47630	getRoot() {
47631
47632		return this._root;
47633
47634	}
47635
47636	// free all resources specific to a particular clip
47637	uncacheClip( clip ) {
47638
47639		const actions = this._actions,
47640			clipUuid = clip.uuid,
47641			actionsByClip = this._actionsByClip,
47642			actionsForClip = actionsByClip[ clipUuid ];
47643
47644		if ( actionsForClip !== undefined ) {
47645
47646			// note: just calling _removeInactiveAction would mess up the
47647			// iteration state and also require updating the state we can
47648			// just throw away
47649
47650			const actionsToRemove = actionsForClip.knownActions;
47651
47652			for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
47653
47654				const action = actionsToRemove[ i ];
47655
47656				this._deactivateAction( action );
47657
47658				const cacheIndex = action._cacheIndex,
47659					lastInactiveAction = actions[ actions.length - 1 ];
47660
47661				action._cacheIndex = null;
47662				action._byClipCacheIndex = null;
47663
47664				lastInactiveAction._cacheIndex = cacheIndex;
47665				actions[ cacheIndex ] = lastInactiveAction;
47666				actions.pop();
47667
47668				this._removeInactiveBindingsForAction( action );
47669
47670			}
47671
47672			delete actionsByClip[ clipUuid ];
47673
47674		}
47675
47676	}
47677
47678	// free all resources specific to a particular root target object
47679	uncacheRoot( root ) {
47680
47681		const rootUuid = root.uuid,
47682			actionsByClip = this._actionsByClip;
47683
47684		for ( const clipUuid in actionsByClip ) {
47685
47686			const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
47687				action = actionByRoot[ rootUuid ];
47688
47689			if ( action !== undefined ) {
47690
47691				this._deactivateAction( action );
47692				this._removeInactiveAction( action );
47693
47694			}
47695
47696		}
47697
47698		const bindingsByRoot = this._bindingsByRootAndName,
47699			bindingByName = bindingsByRoot[ rootUuid ];
47700
47701		if ( bindingByName !== undefined ) {
47702
47703			for ( const trackName in bindingByName ) {
47704
47705				const binding = bindingByName[ trackName ];
47706				binding.restoreOriginalState();
47707				this._removeInactiveBinding( binding );
47708
47709			}
47710
47711		}
47712
47713	}
47714
47715	// remove a targeted clip from the cache
47716	uncacheAction( clip, optionalRoot ) {
47717
47718		const action = this.existingAction( clip, optionalRoot );
47719
47720		if ( action !== null ) {
47721
47722			this._deactivateAction( action );
47723			this._removeInactiveAction( action );
47724
47725		}
47726
47727	}
47728
47729}
47730
47731class Uniform {
47732
47733	constructor( value ) {
47734
47735		this.value = value;
47736
47737	}
47738
47739	clone() {
47740
47741		return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
47742
47743	}
47744
47745}
47746
47747let id = 0;
47748
vendor: 4,765 bytes, lines 47749-48053
47749class UniformsGroup extends EventDispatcher {
47750
47751	constructor() {
47752
47753		super();
47754
47755		this.isUniformsGroup = true;
47756
47757		Object.defineProperty( this, 'id', { value: id ++ } );
47758
47759		this.name = '';
47760
47761		this.usage = StaticDrawUsage;
47762		this.uniforms = [];
47763
47764	}
47765
47766	add( uniform ) {
47767
47768		this.uniforms.push( uniform );
47769
47770		return this;
47771
47772	}
47773
47774	remove( uniform ) {
47775
47776		const index = this.uniforms.indexOf( uniform );
47777
47778		if ( index !== - 1 ) this.uniforms.splice( index, 1 );
47779
47780		return this;
47781
47782	}
47783
47784	setName( name ) {
47785
47786		this.name = name;
47787
47788		return this;
47789
47790	}
47791
47792	setUsage( value ) {
47793
47794		this.usage = value;
47795
47796		return this;
47797
47798	}
47799
47800	dispose() {
47801
47802		this.dispatchEvent( { type: 'dispose' } );
47803
47804		return this;
47805
47806	}
47807
47808	copy( source ) {
47809
47810		this.name = source.name;
47811		this.usage = source.usage;
47812
47813		const uniformsSource = source.uniforms;
47814
47815		this.uniforms.length = 0;
47816
47817		for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) {
47818
47819			this.uniforms.push( uniformsSource[ i ].clone() );
47820
47821		}
47822
47823		return this;
47824
47825	}
47826
47827	clone() {
47828
47829		return new this.constructor().copy( this );
47830
47831	}
47832
47833}
47834
47835class InstancedInterleavedBuffer extends InterleavedBuffer {
47836
47837	constructor( array, stride, meshPerAttribute = 1 ) {
47838
47839		super( array, stride );
47840
47841		this.isInstancedInterleavedBuffer = true;
47842
47843		this.meshPerAttribute = meshPerAttribute;
47844
47845	}
47846
47847	copy( source ) {
47848
47849		super.copy( source );
47850
47851		this.meshPerAttribute = source.meshPerAttribute;
47852
47853		return this;
47854
47855	}
47856
47857	clone( data ) {
47858
47859		const ib = super.clone( data );
47860
47861		ib.meshPerAttribute = this.meshPerAttribute;
47862
47863		return ib;
47864
47865	}
47866
47867	toJSON( data ) {
47868
47869		const json = super.toJSON( data );
47870
47871		json.isInstancedInterleavedBuffer = true;
47872		json.meshPerAttribute = this.meshPerAttribute;
47873
47874		return json;
47875
47876	}
47877
47878}
47879
47880class GLBufferAttribute {
47881
47882	constructor( buffer, type, itemSize, elementSize, count ) {
47883
47884		this.isGLBufferAttribute = true;
47885
47886		this.name = '';
47887
47888		this.buffer = buffer;
47889		this.type = type;
47890		this.itemSize = itemSize;
47891		this.elementSize = elementSize;
47892		this.count = count;
47893
47894		this.version = 0;
47895
47896	}
47897
47898	set needsUpdate( value ) {
47899
47900		if ( value === true ) this.version ++;
47901
47902	}
47903
47904	setBuffer( buffer ) {
47905
47906		this.buffer = buffer;
47907
47908		return this;
47909
47910	}
47911
47912	setType( type, elementSize ) {
47913
47914		this.type = type;
47915		this.elementSize = elementSize;
47916
47917		return this;
47918
47919	}
47920
47921	setItemSize( itemSize ) {
47922
47923		this.itemSize = itemSize;
47924
47925		return this;
47926
47927	}
47928
47929	setCount( count ) {
47930
47931		this.count = count;
47932
47933		return this;
47934
47935	}
47936
47937}
47938
47939class Raycaster {
47940
47941	constructor( origin, direction, near = 0, far = Infinity ) {
47942
47943		this.ray = new Ray( origin, direction );
47944		// direction is assumed to be normalized (for accurate distance calculations)
47945
47946		this.near = near;
47947		this.far = far;
47948		this.camera = null;
47949		this.layers = new Layers();
47950
47951		this.params = {
47952			Mesh: {},
47953			Line: { threshold: 1 },
47954			LOD: {},
47955			Points: { threshold: 1 },
47956			Sprite: {}
47957		};
47958
47959	}
47960
47961	set( origin, direction ) {
47962
47963		// direction is assumed to be normalized (for accurate distance calculations)
47964
47965		this.ray.set( origin, direction );
47966
47967	}
47968
47969	setFromCamera( coords, camera ) {
47970
47971		if ( camera.isPerspectiveCamera ) {
47972
47973			this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
47974			this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
47975			this.camera = camera;
47976
47977		} else if ( camera.isOrthographicCamera ) {
47978
47979			this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
47980			this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
47981			this.camera = camera;
47982
47983		} else {
47984
47985			console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
47986
47987		}
47988
47989	}
47990
47991	intersectObject( object, recursive = true, intersects = [] ) {
47992
47993		intersectObject( object, this, intersects, recursive );
47994
47995		intersects.sort( ascSort );
47996
47997		return intersects;
47998
47999	}
48000
48001	intersectObjects( objects, recursive = true, intersects = [] ) {
48002
48003		for ( let i = 0, l = objects.length; i < l; i ++ ) {
48004
48005			intersectObject( objects[ i ], this, intersects, recursive );
48006
48007		}
48008
48009		intersects.sort( ascSort );
48010
48011		return intersects;
48012
48013	}
48014
48015}
48016
48017function ascSort( a, b ) {
48018
48019	return a.distance - b.distance;
48020
48021}
48022
48023function intersectObject( object, raycaster, intersects, recursive ) {
48024
48025	if ( object.layers.test( raycaster.layers ) ) {
48026
48027		object.raycast( raycaster, intersects );
48028
48029	}
48030
48031	if ( recursive === true ) {
48032
48033		const children = object.children;
48034
48035		for ( let i = 0, l = children.length; i < l; i ++ ) {
48036
48037			intersectObject( children[ i ], raycaster, intersects, true );
48038
48039		}
48040
48041	}
48042
48043}
48044
48045/**
48046 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
48047 *
48048 * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
48049 * The azimuthal angle (theta) is measured from the positive z-axis.
48050 */
48051
48052class Spherical {
48053
vendor: 20,801 bytes, lines 48054-49189
48054	constructor( radius = 1, phi = 0, theta = 0 ) {
48055
48056		this.radius = radius;
48057		this.phi = phi; // polar angle
48058		this.theta = theta; // azimuthal angle
48059
48060		return this;
48061
48062	}
48063
48064	set( radius, phi, theta ) {
48065
48066		this.radius = radius;
48067		this.phi = phi;
48068		this.theta = theta;
48069
48070		return this;
48071
48072	}
48073
48074	copy( other ) {
48075
48076		this.radius = other.radius;
48077		this.phi = other.phi;
48078		this.theta = other.theta;
48079
48080		return this;
48081
48082	}
48083
48084	// restrict phi to be between EPS and PI-EPS
48085	makeSafe() {
48086
48087		const EPS = 0.000001;
48088		this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
48089
48090		return this;
48091
48092	}
48093
48094	setFromVector3( v ) {
48095
48096		return this.setFromCartesianCoords( v.x, v.y, v.z );
48097
48098	}
48099
48100	setFromCartesianCoords( x, y, z ) {
48101
48102		this.radius = Math.sqrt( x * x + y * y + z * z );
48103
48104		if ( this.radius === 0 ) {
48105
48106			this.theta = 0;
48107			this.phi = 0;
48108
48109		} else {
48110
48111			this.theta = Math.atan2( x, z );
48112			this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) );
48113
48114		}
48115
48116		return this;
48117
48118	}
48119
48120	clone() {
48121
48122		return new this.constructor().copy( this );
48123
48124	}
48125
48126}
48127
48128/**
48129 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
48130 */
48131
48132class Cylindrical {
48133
48134	constructor( radius = 1, theta = 0, y = 0 ) {
48135
48136		this.radius = radius; // distance from the origin to a point in the x-z plane
48137		this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
48138		this.y = y; // height above the x-z plane
48139
48140		return this;
48141
48142	}
48143
48144	set( radius, theta, y ) {
48145
48146		this.radius = radius;
48147		this.theta = theta;
48148		this.y = y;
48149
48150		return this;
48151
48152	}
48153
48154	copy( other ) {
48155
48156		this.radius = other.radius;
48157		this.theta = other.theta;
48158		this.y = other.y;
48159
48160		return this;
48161
48162	}
48163
48164	setFromVector3( v ) {
48165
48166		return this.setFromCartesianCoords( v.x, v.y, v.z );
48167
48168	}
48169
48170	setFromCartesianCoords( x, y, z ) {
48171
48172		this.radius = Math.sqrt( x * x + z * z );
48173		this.theta = Math.atan2( x, z );
48174		this.y = y;
48175
48176		return this;
48177
48178	}
48179
48180	clone() {
48181
48182		return new this.constructor().copy( this );
48183
48184	}
48185
48186}
48187
48188const _vector$4 = /*@__PURE__*/ new Vector2();
48189
48190class Box2 {
48191
48192	constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) {
48193
48194		this.isBox2 = true;
48195
48196		this.min = min;
48197		this.max = max;
48198
48199	}
48200
48201	set( min, max ) {
48202
48203		this.min.copy( min );
48204		this.max.copy( max );
48205
48206		return this;
48207
48208	}
48209
48210	setFromPoints( points ) {
48211
48212		this.makeEmpty();
48213
48214		for ( let i = 0, il = points.length; i < il; i ++ ) {
48215
48216			this.expandByPoint( points[ i ] );
48217
48218		}
48219
48220		return this;
48221
48222	}
48223
48224	setFromCenterAndSize( center, size ) {
48225
48226		const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 );
48227		this.min.copy( center ).sub( halfSize );
48228		this.max.copy( center ).add( halfSize );
48229
48230		return this;
48231
48232	}
48233
48234	clone() {
48235
48236		return new this.constructor().copy( this );
48237
48238	}
48239
48240	copy( box ) {
48241
48242		this.min.copy( box.min );
48243		this.max.copy( box.max );
48244
48245		return this;
48246
48247	}
48248
48249	makeEmpty() {
48250
48251		this.min.x = this.min.y = + Infinity;
48252		this.max.x = this.max.y = - Infinity;
48253
48254		return this;
48255
48256	}
48257
48258	isEmpty() {
48259
48260		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
48261
48262		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
48263
48264	}
48265
48266	getCenter( target ) {
48267
48268		return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
48269
48270	}
48271
48272	getSize( target ) {
48273
48274		return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
48275
48276	}
48277
48278	expandByPoint( point ) {
48279
48280		this.min.min( point );
48281		this.max.max( point );
48282
48283		return this;
48284
48285	}
48286
48287	expandByVector( vector ) {
48288
48289		this.min.sub( vector );
48290		this.max.add( vector );
48291
48292		return this;
48293
48294	}
48295
48296	expandByScalar( scalar ) {
48297
48298		this.min.addScalar( - scalar );
48299		this.max.addScalar( scalar );
48300
48301		return this;
48302
48303	}
48304
48305	containsPoint( point ) {
48306
48307		return point.x < this.min.x || point.x > this.max.x ||
48308			point.y < this.min.y || point.y > this.max.y ? false : true;
48309
48310	}
48311
48312	containsBox( box ) {
48313
48314		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
48315			this.min.y <= box.min.y && box.max.y <= this.max.y;
48316
48317	}
48318
48319	getParameter( point, target ) {
48320
48321		// This can potentially have a divide by zero if the box
48322		// has a size dimension of 0.
48323
48324		return target.set(
48325			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
48326			( point.y - this.min.y ) / ( this.max.y - this.min.y )
48327		);
48328
48329	}
48330
48331	intersectsBox( box ) {
48332
48333		// using 4 splitting planes to rule out intersections
48334
48335		return box.max.x < this.min.x || box.min.x > this.max.x ||
48336			box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
48337
48338	}
48339
48340	clampPoint( point, target ) {
48341
48342		return target.copy( point ).clamp( this.min, this.max );
48343
48344	}
48345
48346	distanceToPoint( point ) {
48347
48348		return this.clampPoint( point, _vector$4 ).distanceTo( point );
48349
48350	}
48351
48352	intersect( box ) {
48353
48354		this.min.max( box.min );
48355		this.max.min( box.max );
48356
48357		if ( this.isEmpty() ) this.makeEmpty();
48358
48359		return this;
48360
48361	}
48362
48363	union( box ) {
48364
48365		this.min.min( box.min );
48366		this.max.max( box.max );
48367
48368		return this;
48369
48370	}
48371
48372	translate( offset ) {
48373
48374		this.min.add( offset );
48375		this.max.add( offset );
48376
48377		return this;
48378
48379	}
48380
48381	equals( box ) {
48382
48383		return box.min.equals( this.min ) && box.max.equals( this.max );
48384
48385	}
48386
48387}
48388
48389const _startP = /*@__PURE__*/ new Vector3();
48390const _startEnd = /*@__PURE__*/ new Vector3();
48391
48392class Line3 {
48393
48394	constructor( start = new Vector3(), end = new Vector3() ) {
48395
48396		this.start = start;
48397		this.end = end;
48398
48399	}
48400
48401	set( start, end ) {
48402
48403		this.start.copy( start );
48404		this.end.copy( end );
48405
48406		return this;
48407
48408	}
48409
48410	copy( line ) {
48411
48412		this.start.copy( line.start );
48413		this.end.copy( line.end );
48414
48415		return this;
48416
48417	}
48418
48419	getCenter( target ) {
48420
48421		return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
48422
48423	}
48424
48425	delta( target ) {
48426
48427		return target.subVectors( this.end, this.start );
48428
48429	}
48430
48431	distanceSq() {
48432
48433		return this.start.distanceToSquared( this.end );
48434
48435	}
48436
48437	distance() {
48438
48439		return this.start.distanceTo( this.end );
48440
48441	}
48442
48443	at( t, target ) {
48444
48445		return this.delta( target ).multiplyScalar( t ).add( this.start );
48446
48447	}
48448
48449	closestPointToPointParameter( point, clampToLine ) {
48450
48451		_startP.subVectors( point, this.start );
48452		_startEnd.subVectors( this.end, this.start );
48453
48454		const startEnd2 = _startEnd.dot( _startEnd );
48455		const startEnd_startP = _startEnd.dot( _startP );
48456
48457		let t = startEnd_startP / startEnd2;
48458
48459		if ( clampToLine ) {
48460
48461			t = clamp( t, 0, 1 );
48462
48463		}
48464
48465		return t;
48466
48467	}
48468
48469	closestPointToPoint( point, clampToLine, target ) {
48470
48471		const t = this.closestPointToPointParameter( point, clampToLine );
48472
48473		return this.delta( target ).multiplyScalar( t ).add( this.start );
48474
48475	}
48476
48477	applyMatrix4( matrix ) {
48478
48479		this.start.applyMatrix4( matrix );
48480		this.end.applyMatrix4( matrix );
48481
48482		return this;
48483
48484	}
48485
48486	equals( line ) {
48487
48488		return line.start.equals( this.start ) && line.end.equals( this.end );
48489
48490	}
48491
48492	clone() {
48493
48494		return new this.constructor().copy( this );
48495
48496	}
48497
48498}
48499
48500const _vector$3 = /*@__PURE__*/ new Vector3();
48501
48502class SpotLightHelper extends Object3D {
48503
48504	constructor( light, color ) {
48505
48506		super();
48507
48508		this.light = light;
48509
48510		this.matrix = light.matrixWorld;
48511		this.matrixAutoUpdate = false;
48512
48513		this.color = color;
48514
48515		this.type = 'SpotLightHelper';
48516
48517		const geometry = new BufferGeometry();
48518
48519		const positions = [
48520			0, 0, 0, 	0, 0, 1,
48521			0, 0, 0, 	1, 0, 1,
48522			0, 0, 0,	- 1, 0, 1,
48523			0, 0, 0, 	0, 1, 1,
48524			0, 0, 0, 	0, - 1, 1
48525		];
48526
48527		for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
48528
48529			const p1 = ( i / l ) * Math.PI * 2;
48530			const p2 = ( j / l ) * Math.PI * 2;
48531
48532			positions.push(
48533				Math.cos( p1 ), Math.sin( p1 ), 1,
48534				Math.cos( p2 ), Math.sin( p2 ), 1
48535			);
48536
48537		}
48538
48539		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
48540
48541		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
48542
48543		this.cone = new LineSegments( geometry, material );
48544		this.add( this.cone );
48545
48546		this.update();
48547
48548	}
48549
48550	dispose() {
48551
48552		this.cone.geometry.dispose();
48553		this.cone.material.dispose();
48554
48555	}
48556
48557	update() {
48558
48559		this.light.updateWorldMatrix( true, false );
48560		this.light.target.updateWorldMatrix( true, false );
48561
48562		const coneLength = this.light.distance ? this.light.distance : 1000;
48563		const coneWidth = coneLength * Math.tan( this.light.angle );
48564
48565		this.cone.scale.set( coneWidth, coneWidth, coneLength );
48566
48567		_vector$3.setFromMatrixPosition( this.light.target.matrixWorld );
48568
48569		this.cone.lookAt( _vector$3 );
48570
48571		if ( this.color !== undefined ) {
48572
48573			this.cone.material.color.set( this.color );
48574
48575		} else {
48576
48577			this.cone.material.color.copy( this.light.color );
48578
48579		}
48580
48581	}
48582
48583}
48584
48585const _vector$2 = /*@__PURE__*/ new Vector3();
48586const _boneMatrix = /*@__PURE__*/ new Matrix4();
48587const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
48588
48589
48590class SkeletonHelper extends LineSegments {
48591
48592	constructor( object ) {
48593
48594		const bones = getBoneList( object );
48595
48596		const geometry = new BufferGeometry();
48597
48598		const vertices = [];
48599		const colors = [];
48600
48601		const color1 = new Color( 0, 0, 1 );
48602		const color2 = new Color( 0, 1, 0 );
48603
48604		for ( let i = 0; i < bones.length; i ++ ) {
48605
48606			const bone = bones[ i ];
48607
48608			if ( bone.parent && bone.parent.isBone ) {
48609
48610				vertices.push( 0, 0, 0 );
48611				vertices.push( 0, 0, 0 );
48612				colors.push( color1.r, color1.g, color1.b );
48613				colors.push( color2.r, color2.g, color2.b );
48614
48615			}
48616
48617		}
48618
48619		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
48620		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
48621
48622		const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
48623
48624		super( geometry, material );
48625
48626		this.isSkeletonHelper = true;
48627
48628		this.type = 'SkeletonHelper';
48629
48630		this.root = object;
48631		this.bones = bones;
48632
48633		this.matrix = object.matrixWorld;
48634		this.matrixAutoUpdate = false;
48635
48636	}
48637
48638	updateMatrixWorld( force ) {
48639
48640		const bones = this.bones;
48641
48642		const geometry = this.geometry;
48643		const position = geometry.getAttribute( 'position' );
48644
48645		_matrixWorldInv.copy( this.root.matrixWorld ).invert();
48646
48647		for ( let i = 0, j = 0; i < bones.length; i ++ ) {
48648
48649			const bone = bones[ i ];
48650
48651			if ( bone.parent && bone.parent.isBone ) {
48652
48653				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
48654				_vector$2.setFromMatrixPosition( _boneMatrix );
48655				position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z );
48656
48657				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
48658				_vector$2.setFromMatrixPosition( _boneMatrix );
48659				position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z );
48660
48661				j += 2;
48662
48663			}
48664
48665		}
48666
48667		geometry.getAttribute( 'position' ).needsUpdate = true;
48668
48669		super.updateMatrixWorld( force );
48670
48671	}
48672
48673	dispose() {
48674
48675		this.geometry.dispose();
48676		this.material.dispose();
48677
48678	}
48679
48680}
48681
48682
48683function getBoneList( object ) {
48684
48685	const boneList = [];
48686
48687	if ( object.isBone === true ) {
48688
48689		boneList.push( object );
48690
48691	}
48692
48693	for ( let i = 0; i < object.children.length; i ++ ) {
48694
48695		boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
48696
48697	}
48698
48699	return boneList;
48700
48701}
48702
48703class PointLightHelper extends Mesh {
48704
48705	constructor( light, sphereSize, color ) {
48706
48707		const geometry = new SphereGeometry( sphereSize, 4, 2 );
48708		const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
48709
48710		super( geometry, material );
48711
48712		this.light = light;
48713
48714		this.color = color;
48715
48716		this.type = 'PointLightHelper';
48717
48718		this.matrix = this.light.matrixWorld;
48719		this.matrixAutoUpdate = false;
48720
48721		this.update();
48722
48723
48724		/*
48725	// TODO: delete this comment?
48726	const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
48727	const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
48728
48729	this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
48730	this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
48731
48732	const d = light.distance;
48733
48734	if ( d === 0.0 ) {
48735
48736		this.lightDistance.visible = false;
48737
48738	} else {
48739
48740		this.lightDistance.scale.set( d, d, d );
48741
48742	}
48743
48744	this.add( this.lightDistance );
48745	*/
48746
48747	}
48748
48749	dispose() {
48750
48751		this.geometry.dispose();
48752		this.material.dispose();
48753
48754	}
48755
48756	update() {
48757
48758		this.light.updateWorldMatrix( true, false );
48759
48760		if ( this.color !== undefined ) {
48761
48762			this.material.color.set( this.color );
48763
48764		} else {
48765
48766			this.material.color.copy( this.light.color );
48767
48768		}
48769
48770		/*
48771		const d = this.light.distance;
48772
48773		if ( d === 0.0 ) {
48774
48775			this.lightDistance.visible = false;
48776
48777		} else {
48778
48779			this.lightDistance.visible = true;
48780			this.lightDistance.scale.set( d, d, d );
48781
48782		}
48783		*/
48784
48785	}
48786
48787}
48788
48789const _vector$1 = /*@__PURE__*/ new Vector3();
48790const _color1 = /*@__PURE__*/ new Color();
48791const _color2 = /*@__PURE__*/ new Color();
48792
48793class HemisphereLightHelper extends Object3D {
48794
48795	constructor( light, size, color ) {
48796
48797		super();
48798
48799		this.light = light;
48800
48801		this.matrix = light.matrixWorld;
48802		this.matrixAutoUpdate = false;
48803
48804		this.color = color;
48805
48806		this.type = 'HemisphereLightHelper';
48807
48808		const geometry = new OctahedronGeometry( size );
48809		geometry.rotateY( Math.PI * 0.5 );
48810
48811		this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
48812		if ( this.color === undefined ) this.material.vertexColors = true;
48813
48814		const position = geometry.getAttribute( 'position' );
48815		const colors = new Float32Array( position.count * 3 );
48816
48817		geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
48818
48819		this.add( new Mesh( geometry, this.material ) );
48820
48821		this.update();
48822
48823	}
48824
48825	dispose() {
48826
48827		this.children[ 0 ].geometry.dispose();
48828		this.children[ 0 ].material.dispose();
48829
48830	}
48831
48832	update() {
48833
48834		const mesh = this.children[ 0 ];
48835
48836		if ( this.color !== undefined ) {
48837
48838			this.material.color.set( this.color );
48839
48840		} else {
48841
48842			const colors = mesh.geometry.getAttribute( 'color' );
48843
48844			_color1.copy( this.light.color );
48845			_color2.copy( this.light.groundColor );
48846
48847			for ( let i = 0, l = colors.count; i < l; i ++ ) {
48848
48849				const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
48850
48851				colors.setXYZ( i, color.r, color.g, color.b );
48852
48853			}
48854
48855			colors.needsUpdate = true;
48856
48857		}
48858
48859		this.light.updateWorldMatrix( true, false );
48860
48861		mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() );
48862
48863	}
48864
48865}
48866
48867class GridHelper extends LineSegments {
48868
48869	constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
48870
48871		color1 = new Color( color1 );
48872		color2 = new Color( color2 );
48873
48874		const center = divisions / 2;
48875		const step = size / divisions;
48876		const halfSize = size / 2;
48877
48878		const vertices = [], colors = [];
48879
48880		for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
48881
48882			vertices.push( - halfSize, 0, k, halfSize, 0, k );
48883			vertices.push( k, 0, - halfSize, k, 0, halfSize );
48884
48885			const color = i === center ? color1 : color2;
48886
48887			color.toArray( colors, j ); j += 3;
48888			color.toArray( colors, j ); j += 3;
48889			color.toArray( colors, j ); j += 3;
48890			color.toArray( colors, j ); j += 3;
48891
48892		}
48893
48894		const geometry = new BufferGeometry();
48895		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
48896		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
48897
48898		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
48899
48900		super( geometry, material );
48901
48902		this.type = 'GridHelper';
48903
48904	}
48905
48906	dispose() {
48907
48908		this.geometry.dispose();
48909		this.material.dispose();
48910
48911	}
48912
48913}
48914
48915class PolarGridHelper extends LineSegments {
48916
48917	constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
48918
48919		color1 = new Color( color1 );
48920		color2 = new Color( color2 );
48921
48922		const vertices = [];
48923		const colors = [];
48924
48925		// create the sectors
48926
48927		if ( sectors > 1 ) {
48928
48929			for ( let i = 0; i < sectors; i ++ ) {
48930
48931				const v = ( i / sectors ) * ( Math.PI * 2 );
48932
48933				const x = Math.sin( v ) * radius;
48934				const z = Math.cos( v ) * radius;
48935
48936				vertices.push( 0, 0, 0 );
48937				vertices.push( x, 0, z );
48938
48939				const color = ( i & 1 ) ? color1 : color2;
48940
48941				colors.push( color.r, color.g, color.b );
48942				colors.push( color.r, color.g, color.b );
48943
48944			}
48945
48946		}
48947
48948		// create the rings
48949
48950		for ( let i = 0; i < rings; i ++ ) {
48951
48952			const color = ( i & 1 ) ? color1 : color2;
48953
48954			const r = radius - ( radius / rings * i );
48955
48956			for ( let j = 0; j < divisions; j ++ ) {
48957
48958				// first vertex
48959
48960				let v = ( j / divisions ) * ( Math.PI * 2 );
48961
48962				let x = Math.sin( v ) * r;
48963				let z = Math.cos( v ) * r;
48964
48965				vertices.push( x, 0, z );
48966				colors.push( color.r, color.g, color.b );
48967
48968				// second vertex
48969
48970				v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
48971
48972				x = Math.sin( v ) * r;
48973				z = Math.cos( v ) * r;
48974
48975				vertices.push( x, 0, z );
48976				colors.push( color.r, color.g, color.b );
48977
48978			}
48979
48980		}
48981
48982		const geometry = new BufferGeometry();
48983		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
48984		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
48985
48986		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
48987
48988		super( geometry, material );
48989
48990		this.type = 'PolarGridHelper';
48991
48992	}
48993
48994	dispose() {
48995
48996		this.geometry.dispose();
48997		this.material.dispose();
48998
48999	}
49000
49001}
49002
49003const _v1 = /*@__PURE__*/ new Vector3();
49004const _v2 = /*@__PURE__*/ new Vector3();
49005const _v3 = /*@__PURE__*/ new Vector3();
49006
49007class DirectionalLightHelper extends Object3D {
49008
49009	constructor( light, size, color ) {
49010
49011		super();
49012
49013		this.light = light;
49014
49015		this.matrix = light.matrixWorld;
49016		this.matrixAutoUpdate = false;
49017
49018		this.color = color;
49019
49020		this.type = 'DirectionalLightHelper';
49021
49022		if ( size === undefined ) size = 1;
49023
49024		let geometry = new BufferGeometry();
49025		geometry.setAttribute( 'position', new Float32BufferAttribute( [
49026			- size, size, 0,
49027			size, size, 0,
49028			size, - size, 0,
49029			- size, - size, 0,
49030			- size, size, 0
49031		], 3 ) );
49032
49033		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
49034
49035		this.lightPlane = new Line( geometry, material );
49036		this.add( this.lightPlane );
49037
49038		geometry = new BufferGeometry();
49039		geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
49040
49041		this.targetLine = new Line( geometry, material );
49042		this.add( this.targetLine );
49043
49044		this.update();
49045
49046	}
49047
49048	dispose() {
49049
49050		this.lightPlane.geometry.dispose();
49051		this.lightPlane.material.dispose();
49052		this.targetLine.geometry.dispose();
49053		this.targetLine.material.dispose();
49054
49055	}
49056
49057	update() {
49058
49059		this.light.updateWorldMatrix( true, false );
49060		this.light.target.updateWorldMatrix( true, false );
49061
49062		_v1.setFromMatrixPosition( this.light.matrixWorld );
49063		_v2.setFromMatrixPosition( this.light.target.matrixWorld );
49064		_v3.subVectors( _v2, _v1 );
49065
49066		this.lightPlane.lookAt( _v2 );
49067
49068		if ( this.color !== undefined ) {
49069
49070			this.lightPlane.material.color.set( this.color );
49071			this.targetLine.material.color.set( this.color );
49072
49073		} else {
49074
49075			this.lightPlane.material.color.copy( this.light.color );
49076			this.targetLine.material.color.copy( this.light.color );
49077
49078		}
49079
49080		this.targetLine.lookAt( _v2 );
49081		this.targetLine.scale.z = _v3.length();
49082
49083	}
49084
49085}
49086
49087const _vector = /*@__PURE__*/ new Vector3();
49088const _camera = /*@__PURE__*/ new Camera();
49089
49090/**
49091 *	- shows frustum, line of sight and up of the camera
49092 *	- suitable for fast updates
49093 * 	- based on frustum visualization in lightgl.js shadowmap example
49094 *		https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html
49095 */
49096
49097class CameraHelper extends LineSegments {
49098
49099	constructor( camera ) {
49100
49101		const geometry = new BufferGeometry();
49102		const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
49103
49104		const vertices = [];
49105		const colors = [];
49106
49107		const pointMap = {};
49108
49109		// near
49110
49111		addLine( 'n1', 'n2' );
49112		addLine( 'n2', 'n4' );
49113		addLine( 'n4', 'n3' );
49114		addLine( 'n3', 'n1' );
49115
49116		// far
49117
49118		addLine( 'f1', 'f2' );
49119		addLine( 'f2', 'f4' );
49120		addLine( 'f4', 'f3' );
49121		addLine( 'f3', 'f1' );
49122
49123		// sides
49124
49125		addLine( 'n1', 'f1' );
49126		addLine( 'n2', 'f2' );
49127		addLine( 'n3', 'f3' );
49128		addLine( 'n4', 'f4' );
49129
49130		// cone
49131
49132		addLine( 'p', 'n1' );
49133		addLine( 'p', 'n2' );
49134		addLine( 'p', 'n3' );
49135		addLine( 'p', 'n4' );
49136
49137		// up
49138
49139		addLine( 'u1', 'u2' );
49140		addLine( 'u2', 'u3' );
49141		addLine( 'u3', 'u1' );
49142
49143		// target
49144
49145		addLine( 'c', 't' );
49146		addLine( 'p', 'c' );
49147
49148		// cross
49149
49150		addLine( 'cn1', 'cn2' );
49151		addLine( 'cn3', 'cn4' );
49152
49153		addLine( 'cf1', 'cf2' );
49154		addLine( 'cf3', 'cf4' );
49155
49156		function addLine( a, b ) {
49157
49158			addPoint( a );
49159			addPoint( b );
49160
49161		}
49162
49163		function addPoint( id ) {
49164
49165			vertices.push( 0, 0, 0 );
49166			colors.push( 0, 0, 0 );
49167
49168			if ( pointMap[ id ] === undefined ) {
49169
49170				pointMap[ id ] = [];
49171
49172			}
49173
49174			pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
49175
49176		}
49177
49178		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
49179		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
49180
49181		super( geometry, material );
49182
49183		this.type = 'CameraHelper';
49184
49185		this.camera = camera;
49186		if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
49187
49188		this.matrix = camera.matrixWorld;
49189		this.matrixAutoUpdate = false;
49190
49191		this.pointMap = pointMap;
49192
49193		this.update();
49194
49195		// colors
49196
49197		const colorFrustum = new Color( 0xffaa00 );
49198		const colorCone = new Color( 0xff0000 );
49199		const colorUp = new Color( 0x00aaff );
49200		const colorTarget = new Color( 0xffffff );
49201		const colorCross = new Color( 0x333333 );
49202
49203		this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross );
49204
49205	}
49206
49207	setColors( frustum, cone, up, target, cross ) {
49208
49209		const geometry = this.geometry;
49210
49211		const colorAttribute = geometry.getAttribute( 'color' );
49212
49213		// near
49214
49215		colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2
49216		colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4
49217		colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3
49218		colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1
49219
49220		// far
49221
49222		colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2
49223		colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4
49224		colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3
49225		colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1
49226
49227		// sides
49228
49229		colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1
49230		colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2
49231		colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3
49232		colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4
49233
49234		// cone
49235
49236		colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1
49237		colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2
49238		colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3
49239		colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4
49240
49241		// up
49242
49243		colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2
49244		colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3
49245		colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1
49246
49247		// target
49248
49249		colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t
49250		colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c
49251
49252		// cross
49253
49254		colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2
49255		colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4
49256
49257		colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2
49258		colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4
49259
49260		colorAttribute.needsUpdate = true;
49261
49262	}
49263
49264	update() {
49265
49266		const geometry = this.geometry;
49267		const pointMap = this.pointMap;
49268
49269		const w = 1, h = 1;
49270
49271		// we need just camera projection matrix inverse
49272		// world matrix must be identity
49273
49274		_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
49275
49276		// center / target
49277
49278		setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
49279		setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
49280
49281		// near
49282
49283		setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
49284		setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
49285		setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
49286		setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
49287
49288		// far
49289
49290		setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
49291		setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
49292		setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
49293		setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
49294
49295		// up
49296
49297		setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
49298		setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
49299		setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
49300
49301		// cross
49302
49303		setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
49304		setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
49305		setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
49306		setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
49307
49308		setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
49309		setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
49310		setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
49311		setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
49312
49313		geometry.getAttribute( 'position' ).needsUpdate = true;
49314
49315	}
49316
49317	dispose() {
49318
49319		this.geometry.dispose();
49320		this.material.dispose();
49321
49322	}
49323
49324}
49325
49326
49327function setPoint( point, pointMap, geometry, camera, x, y, z ) {
49328
49329	_vector.set( x, y, z ).unproject( camera );
49330
49331	const points = pointMap[ point ];
49332
49333	if ( points !== undefined ) {
49334
49335		const position = geometry.getAttribute( 'position' );
49336
49337		for ( let i = 0, l = points.length; i < l; i ++ ) {
49338
49339			position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z );
49340
49341		}
49342
49343	}
49344
49345}
49346
49347const _box = /*@__PURE__*/ new Box3();
49348
49349class BoxHelper extends LineSegments {
49350
49351	constructor( object, color = 0xffff00 ) {
49352
49353		const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
49354		const positions = new Float32Array( 8 * 3 );
49355
49356		const geometry = new BufferGeometry();
49357		geometry.setIndex( new BufferAttribute( indices, 1 ) );
49358		geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
49359
49360		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
49361
49362		this.object = object;
49363		this.type = 'BoxHelper';
49364
49365		this.matrixAutoUpdate = false;
vendor: 4,705 bytes, lines 49366-49582
49366
49367		this.update();
49368
49369	}
49370
49371	update( object ) {
49372
49373		if ( object !== undefined ) {
49374
49375			console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
49376
49377		}
49378
49379		if ( this.object !== undefined ) {
49380
49381			_box.setFromObject( this.object );
49382
49383		}
49384
49385		if ( _box.isEmpty() ) return;
49386
49387		const min = _box.min;
49388		const max = _box.max;
49389
49390		/*
49391			5____4
49392		1/___0/|
49393		| 6__|_7
49394		2/___3/
49395
49396		0: max.x, max.y, max.z
49397		1: min.x, max.y, max.z
49398		2: min.x, min.y, max.z
49399		3: max.x, min.y, max.z
49400		4: max.x, max.y, min.z
49401		5: min.x, max.y, min.z
49402		6: min.x, min.y, min.z
49403		7: max.x, min.y, min.z
49404		*/
49405
49406		const position = this.geometry.attributes.position;
49407		const array = position.array;
49408
49409		array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
49410		array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
49411		array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
49412		array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
49413		array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
49414		array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
49415		array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
49416		array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
49417
49418		position.needsUpdate = true;
49419
49420		this.geometry.computeBoundingSphere();
49421
49422	}
49423
49424	setFromObject( object ) {
49425
49426		this.object = object;
49427		this.update();
49428
49429		return this;
49430
49431	}
49432
49433	copy( source, recursive ) {
49434
49435		super.copy( source, recursive );
49436
49437		this.object = source.object;
49438
49439		return this;
49440
49441	}
49442
49443	dispose() {
49444
49445		this.geometry.dispose();
49446		this.material.dispose();
49447
49448	}
49449
49450}
49451
49452class Box3Helper extends LineSegments {
49453
49454	constructor( box, color = 0xffff00 ) {
49455
49456		const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
49457
49458		const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ];
49459
49460		const geometry = new BufferGeometry();
49461
49462		geometry.setIndex( new BufferAttribute( indices, 1 ) );
49463
49464		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
49465
49466		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
49467
49468		this.box = box;
49469
49470		this.type = 'Box3Helper';
49471
49472		this.geometry.computeBoundingSphere();
49473
49474	}
49475
49476	updateMatrixWorld( force ) {
49477
49478		const box = this.box;
49479
49480		if ( box.isEmpty() ) return;
49481
49482		box.getCenter( this.position );
49483
49484		box.getSize( this.scale );
49485
49486		this.scale.multiplyScalar( 0.5 );
49487
49488		super.updateMatrixWorld( force );
49489
49490	}
49491
49492	dispose() {
49493
49494		this.geometry.dispose();
49495		this.material.dispose();
49496
49497	}
49498
49499}
49500
49501class PlaneHelper extends Line {
49502
49503	constructor( plane, size = 1, hex = 0xffff00 ) {
49504
49505		const color = hex;
49506
49507		const positions = [ 1, - 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ];
49508
49509		const geometry = new BufferGeometry();
49510		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
49511		geometry.computeBoundingSphere();
49512
49513		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
49514
49515		this.type = 'PlaneHelper';
49516
49517		this.plane = plane;
49518
49519		this.size = size;
49520
49521		const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];
49522
49523		const geometry2 = new BufferGeometry();
49524		geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
49525		geometry2.computeBoundingSphere();
49526
49527		this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
49528
49529	}
49530
49531	updateMatrixWorld( force ) {
49532
49533		this.position.set( 0, 0, 0 );
49534
49535		this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 );
49536
49537		this.lookAt( this.plane.normal );
49538
49539		this.translateZ( - this.plane.constant );
49540
49541		super.updateMatrixWorld( force );
49542
49543	}
49544
49545	dispose() {
49546
49547		this.geometry.dispose();
49548		this.material.dispose();
49549		this.children[ 0 ].geometry.dispose();
49550		this.children[ 0 ].material.dispose();
49551
49552	}
49553
49554}
49555
49556const _axis = /*@__PURE__*/ new Vector3();
49557let _lineGeometry, _coneGeometry;
49558
49559class ArrowHelper extends Object3D {
49560
49561	// dir is assumed to be normalized
49562
49563	constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
49564
49565		super();
49566
49567		this.type = 'ArrowHelper';
49568
49569		if ( _lineGeometry === undefined ) {
49570
49571			_lineGeometry = new BufferGeometry();
49572			_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
49573
49574			_coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 );
49575			_coneGeometry.translate( 0, - 0.5, 0 );
49576
49577		}
49578
49579		this.position.copy( origin );
49580
49581		this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
49582		this.line.matrixAutoUpdate = false;
vendor: 3,957 bytes, lines 49583-49802
49583		this.add( this.line );
49584
49585		this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
49586		this.cone.matrixAutoUpdate = false;
49587		this.add( this.cone );
49588
49589		this.setDirection( dir );
49590		this.setLength( length, headLength, headWidth );
49591
49592	}
49593
49594	setDirection( dir ) {
49595
49596		// dir is assumed to be normalized
49597
49598		if ( dir.y > 0.99999 ) {
49599
49600			this.quaternion.set( 0, 0, 0, 1 );
49601
49602		} else if ( dir.y < - 0.99999 ) {
49603
49604			this.quaternion.set( 1, 0, 0, 0 );
49605
49606		} else {
49607
49608			_axis.set( dir.z, 0, - dir.x ).normalize();
49609
49610			const radians = Math.acos( dir.y );
49611
49612			this.quaternion.setFromAxisAngle( _axis, radians );
49613
49614		}
49615
49616	}
49617
49618	setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
49619
49620		this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
49621		this.line.updateMatrix();
49622
49623		this.cone.scale.set( headWidth, headLength, headWidth );
49624		this.cone.position.y = length;
49625		this.cone.updateMatrix();
49626
49627	}
49628
49629	setColor( color ) {
49630
49631		this.line.material.color.set( color );
49632		this.cone.material.color.set( color );
49633
49634	}
49635
49636	copy( source ) {
49637
49638		super.copy( source, false );
49639
49640		this.line.copy( source.line );
49641		this.cone.copy( source.cone );
49642
49643		return this;
49644
49645	}
49646
49647	dispose() {
49648
49649		this.line.geometry.dispose();
49650		this.line.material.dispose();
49651		this.cone.geometry.dispose();
49652		this.cone.material.dispose();
49653
49654	}
49655
49656}
49657
49658class AxesHelper extends LineSegments {
49659
49660	constructor( size = 1 ) {
49661
49662		const vertices = [
49663			0, 0, 0,	size, 0, 0,
49664			0, 0, 0,	0, size, 0,
49665			0, 0, 0,	0, 0, size
49666		];
49667
49668		const colors = [
49669			1, 0, 0,	1, 0.6, 0,
49670			0, 1, 0,	0.6, 1, 0,
49671			0, 0, 1,	0, 0.6, 1
49672		];
49673
49674		const geometry = new BufferGeometry();
49675		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
49676		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
49677
49678		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
49679
49680		super( geometry, material );
49681
49682		this.type = 'AxesHelper';
49683
49684	}
49685
49686	setColors( xAxisColor, yAxisColor, zAxisColor ) {
49687
49688		const color = new Color();
49689		const array = this.geometry.attributes.color.array;
49690
49691		color.set( xAxisColor );
49692		color.toArray( array, 0 );
49693		color.toArray( array, 3 );
49694
49695		color.set( yAxisColor );
49696		color.toArray( array, 6 );
49697		color.toArray( array, 9 );
49698
49699		color.set( zAxisColor );
49700		color.toArray( array, 12 );
49701		color.toArray( array, 15 );
49702
49703		this.geometry.attributes.color.needsUpdate = true;
49704
49705		return this;
49706
49707	}
49708
49709	dispose() {
49710
49711		this.geometry.dispose();
49712		this.material.dispose();
49713
49714	}
49715
49716}
49717
49718class ShapePath {
49719
49720	constructor() {
49721
49722		this.type = 'ShapePath';
49723
49724		this.color = new Color();
49725
49726		this.subPaths = [];
49727		this.currentPath = null;
49728
49729	}
49730
49731	moveTo( x, y ) {
49732
49733		this.currentPath = new Path();
49734		this.subPaths.push( this.currentPath );
49735		this.currentPath.moveTo( x, y );
49736
49737		return this;
49738
49739	}
49740
49741	lineTo( x, y ) {
49742
49743		this.currentPath.lineTo( x, y );
49744
49745		return this;
49746
49747	}
49748
49749	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
49750
49751		this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
49752
49753		return this;
49754
49755	}
49756
49757	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
49758
49759		this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
49760
49761		return this;
49762
49763	}
49764
49765	splineThru( pts ) {
49766
49767		this.currentPath.splineThru( pts );
49768
49769		return this;
49770
49771	}
49772
49773	toShapes( isCCW ) {
49774
49775		function toShapesNoHoles( inSubpaths ) {
49776
49777			const shapes = [];
49778
49779			for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
49780
49781				const tmpPath = inSubpaths[ i ];
49782
49783				const tmpShape = new Shape();
49784				tmpShape.curves = tmpPath.curves;
49785
49786				shapes.push( tmpShape );
49787
49788			}
49789
49790			return shapes;
49791
49792		}
49793
49794		function isPointInsidePolygon( inPt, inPolygon ) {
49795
49796			const polyLen = inPolygon.length;
49797
49798			// inPt on polygon contour => immediate success    or
49799			// toggling of inside/outside at every single! intersection point of an edge
49800			//  with the horizontal line through inPt, left of inPt
49801			//  not counting lowerY endpoints of edges and whole edges on that line
49802			let inside = false;
49803			for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
49804
49805				let edgeLowPt = inPolygon[ p ];
49806				let edgeHighPt = inPolygon[ q ];
49807
49808				let edgeDx = edgeHighPt.x - edgeLowPt.x;
49809				let edgeDy = edgeHighPt.y - edgeLowPt.y;
49810
49811				if ( Math.abs( edgeDy ) > Number.EPSILON ) {
49812
49813					// not parallel
49814					if ( edgeDy < 0 ) {
49815
49816						edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
49817						edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
49818
49819					}
49820
49821					if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) 		continue;
49822
49823					if ( inPt.y === edgeLowPt.y ) {
49824
49825						if ( inPt.x === edgeLowPt.x )		return	true;		// inPt is on contour ?
49826						// continue;				// no intersection or edgeLowPt => doesn't count !!!
49827
49828					} else {
49829
49830						const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
49831						if ( perpEdge === 0 )				return	true;		// inPt is on contour ?
49832						if ( perpEdge < 0 ) 				continue;
49833						inside = ! inside;		// true intersection left of inPt
49834
49835					}
49836
49837				} else {
49838
49839					// parallel or collinear
49840					if ( inPt.y !== edgeLowPt.y ) 		continue;			// parallel
49841					// edge lies on the same horizontal line as inPt
49842					if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
49843						 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )		return	true;	// inPt: Point on contour !
49844					// continue;
49845
49846				}
49847
49848			}
49849
49850			return	inside;
49851
49852		}
49853
49854		const isClockWise = ShapeUtils.isClockWise;
49855
49856		const subPaths = this.subPaths;
49857		if ( subPaths.length === 0 ) return [];
49858
49859		let solid, tmpPath, tmpShape;
49860		const shapes = [];
49861
49862		if ( subPaths.length === 1 ) {
49863
49864			tmpPath = subPaths[ 0 ];
49865			tmpShape = new Shape();
49866			tmpShape.curves = tmpPath.curves;
49867			shapes.push( tmpShape );
49868			return shapes;
49869
49870		}
49871
49872		let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
49873		holesFirst = isCCW ? ! holesFirst : holesFirst;
49874
49875		// console.log("Holes first", holesFirst);
49876
49877		const betterShapeHoles = [];
49878		const newShapes = [];
49879		let newShapeHoles = [];
49880		let mainIdx = 0;
49881		let tmpPoints;
49882
49883		newShapes[ mainIdx ] = undefined;
49884		newShapeHoles[ mainIdx ] = [];
49885
49886		for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
49887
49888			tmpPath = subPaths[ i ];
49889			tmpPoints = tmpPath.getPoints();
49890			solid = isClockWise( tmpPoints );
49891			solid = isCCW ? ! solid : solid;
49892
49893			if ( solid ) {
49894
49895				if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )	mainIdx ++;
49896
49897				newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
49898				newShapes[ mainIdx ].s.curves = tmpPath.curves;
49899
49900				if ( holesFirst )	mainIdx ++;
49901				newShapeHoles[ mainIdx ] = [];
49902
49903				//console.log('cw', i);
49904
49905			} else {
49906
49907				newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
49908
49909				//console.log('ccw', i);
49910
49911			}
49912
49913		}
49914
49915		// only Holes? -> probably all Shapes with wrong orientation
49916		if ( ! newShapes[ 0 ] )	return	toShapesNoHoles( subPaths );
49917
49918
49919		if ( newShapes.length > 1 ) {
49920
49921			let ambiguous = false;
49922			let toChange = 0;
49923
49924			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
49925
49926				betterShapeHoles[ sIdx ] = [];
49927
49928			}
49929
49930			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
49931
49932				const sho = newShapeHoles[ sIdx ];
49933
49934				for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
49935
49936					const ho = sho[ hIdx ];
49937					let hole_unassigned = true;
49938
49939					for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
49940
49941						if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
49942
49943							if ( sIdx !== s2Idx )	toChange ++;
49944
49945							if ( hole_unassigned ) {
49946
49947								hole_unassigned = false;
49948								betterShapeHoles[ s2Idx ].push( ho );
49949
49950							} else {
49951
49952								ambiguous = true;
49953
49954							}
49955
49956						}
49957
49958					}
49959
49960					if ( hole_unassigned ) {
49961
49962						betterShapeHoles[ sIdx ].push( ho );
49963
49964					}
49965
49966				}
49967
49968			}
49969
49970			if ( toChange > 0 && ambiguous === false ) {
49971
49972				newShapeHoles = betterShapeHoles;
49973
49974			}
49975
49976		}
49977
49978		let tmpHoles;
49979
49980		for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
49981
49982			tmpShape = newShapes[ i ].s;
49983			shapes.push( tmpShape );
49984			tmpHoles = newShapeHoles[ i ];
49985
49986			for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
49987
49988				tmpShape.holes.push( tmpHoles[ j ].h );
49989
49990			}
49991
49992		}
49993
49994		//console.log("shape", shapes);
49995
49996		return shapes;
49997
49998	}
49999
50000}
50001
50002// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
50003
50004const _tables = /*@__PURE__*/ _generateTables();
50005
50006function _generateTables() {
50007
50008	// float32 to float16 helpers
50009
50010	const buffer = new ArrayBuffer( 4 );
50011	const floatView = new Float32Array( buffer );
50012	const uint32View = new Uint32Array( buffer );
50013
50014	const baseTable = new Uint32Array( 512 );
50015	const shiftTable = new Uint32Array( 512 );
50016
50017	for ( let i = 0; i < 256; ++ i ) {
50018
50019		const e = i - 127;
50020
50021		// very small number (0, -0)
50022
50023		if ( e < - 27 ) {
50024
50025			baseTable[ i ] = 0x0000;
50026			baseTable[ i | 0x100 ] = 0x8000;
50027			shiftTable[ i ] = 24;
50028			shiftTable[ i | 0x100 ] = 24;
50029
50030			// small number (denorm)
50031
50032		} else if ( e < - 14 ) {
50033
50034			baseTable[ i ] = 0x0400 >> ( - e - 14 );
50035			baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000;
50036			shiftTable[ i ] = - e - 1;
50037			shiftTable[ i | 0x100 ] = - e - 1;
50038
50039			// normal number
50040
50041		} else if ( e <= 15 ) {
50042
50043			baseTable[ i ] = ( e + 15 ) << 10;
50044			baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000;
50045			shiftTable[ i ] = 13;
50046			shiftTable[ i | 0x100 ] = 13;
50047
50048			// large number (Infinity, -Infinity)
50049
50050		} else if ( e < 128 ) {
50051
50052			baseTable[ i ] = 0x7c00;
50053			baseTable[ i | 0x100 ] = 0xfc00;
50054			shiftTable[ i ] = 24;
50055			shiftTable[ i | 0x100 ] = 24;
50056
50057			// stay (NaN, Infinity, -Infinity)
50058
50059		} else {
50060
50061			baseTable[ i ] = 0x7c00;
50062			baseTable[ i | 0x100 ] = 0xfc00;
50063			shiftTable[ i ] = 13;
50064			shiftTable[ i | 0x100 ] = 13;
50065
50066		}
50067
50068	}
50069
50070	// float16 to float32 helpers
50071
50072	const mantissaTable = new Uint32Array( 2048 );
50073	const exponentTable = new Uint32Array( 64 );
50074	const offsetTable = new Uint32Array( 64 );
50075
50076	for ( let i = 1; i < 1024; ++ i ) {
50077
50078		let m = i << 13; // zero pad mantissa bits
50079		let e = 0; // zero exponent
50080
50081		// normalized
50082		while ( ( m & 0x00800000 ) === 0 ) {
50083
50084			m <<= 1;
50085			e -= 0x00800000; // decrement exponent
50086
50087		}
50088
50089		m &= ~ 0x00800000; // clear leading 1 bit
50090		e += 0x38800000; // adjust bias
50091
50092		mantissaTable[ i ] = m | e;
50093
50094	}
50095
50096	for ( let i = 1024; i < 2048; ++ i ) {
50097
50098		mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 );
50099
50100	}
50101
50102	for ( let i = 1; i < 31; ++ i ) {
50103
50104		exponentTable[ i ] = i << 23;
50105
50106	}
50107
50108	exponentTable[ 31 ] = 0x47800000;
50109	exponentTable[ 32 ] = 0x80000000;
50110
50111	for ( let i = 33; i < 63; ++ i ) {
50112
50113		exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 );
50114
50115	}
50116
50117	exponentTable[ 63 ] = 0xc7800000;
50118
50119	for ( let i = 1; i < 64; ++ i ) {
50120
50121		if ( i !== 32 ) {
50122
50123			offsetTable[ i ] = 1024;
50124
50125		}
50126
50127	}
50128
50129	return {
50130		floatView: floatView,
50131		uint32View: uint32View,
50132		baseTable: baseTable,
50133		shiftTable: shiftTable,
50134		mantissaTable: mantissaTable,
50135		exponentTable: exponentTable,
50136		offsetTable: offsetTable
50137	};
50138
50139}
50140
50141// float32 to float16
50142
50143function toHalfFloat( val ) {
50144
50145	if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' );
50146
50147	val = clamp( val, - 65504, 65504 );
50148
50149	_tables.floatView[ 0 ] = val;
50150	const f = _tables.uint32View[ 0 ];
50151	const e = ( f >> 23 ) & 0x1ff;
50152	return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] );
50153
50154}
50155
50156// float16 to float32
50157
50158function fromHalfFloat( val ) {
50159
50160	const m = val >> 10;
50161	_tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ];
50162	return _tables.floatView[ 0 ];
50163
50164}
50165
50166const DataUtils = {
50167	toHalfFloat: toHalfFloat,
50168	fromHalfFloat: fromHalfFloat,
50169};
50170
50171// r144
50172
50173class BoxBufferGeometry extends BoxGeometry {
50174
50175	constructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {
50176
50177		console.warn( 'THREE.BoxBufferGeometry has been renamed to THREE.BoxGeometry.' );
50178		super( width, height, depth, widthSegments, heightSegments, depthSegments );
50179
50180
50181	}
50182
50183}
50184
50185// r144
50186
50187class CapsuleBufferGeometry extends CapsuleGeometry {
50188
50189	constructor( radius, length, capSegments, radialSegments ) {
50190
50191		console.warn( 'THREE.CapsuleBufferGeometry has been renamed to THREE.CapsuleGeometry.' );
50192		super( radius, length, capSegments, radialSegments );
50193
50194	}
50195
50196}
50197
50198// r144
50199
50200class CircleBufferGeometry extends CircleGeometry {
50201
50202	constructor( radius, segments, thetaStart, thetaLength ) {
50203
50204		console.warn( 'THREE.CircleBufferGeometry has been renamed to THREE.CircleGeometry.' );
50205		super( radius, segments, thetaStart, thetaLength );
50206
50207	}
50208
50209}
50210
50211// r144
50212
50213class ConeBufferGeometry extends ConeGeometry {
50214
50215	constructor( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
50216
50217		console.warn( 'THREE.ConeBufferGeometry has been renamed to THREE.ConeGeometry.' );
50218		super( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
50219
50220	}
50221
50222}
50223
50224// r144
50225
50226class CylinderBufferGeometry extends CylinderGeometry {
50227
50228	constructor( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {
50229
50230		console.warn( 'THREE.CylinderBufferGeometry has been renamed to THREE.CylinderGeometry.' );
50231		super( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
50232
50233	}
50234
50235}
50236
50237// r144
50238
50239class DodecahedronBufferGeometry extends DodecahedronGeometry {
50240
50241	constructor( radius, detail ) {
50242
50243		console.warn( 'THREE.DodecahedronBufferGeometry has been renamed to THREE.DodecahedronGeometry.' );
50244		super( radius, detail );
50245
50246	}
50247
50248}
50249
50250// r144
50251
50252class ExtrudeBufferGeometry extends ExtrudeGeometry {
50253
50254	constructor( shapes, options ) {
50255
50256		console.warn( 'THREE.ExtrudeBufferGeometry has been renamed to THREE.ExtrudeGeometry.' );
50257		super( shapes, options );
50258
50259	}
50260
50261}
50262
50263// r144
50264
50265class IcosahedronBufferGeometry extends IcosahedronGeometry {
50266
50267	constructor( radius, detail ) {
50268
50269		console.warn( 'THREE.IcosahedronBufferGeometry has been renamed to THREE.IcosahedronGeometry.' );
50270		super( radius, detail );
50271
50272	}
50273
50274}
50275
50276// r144
50277
50278class LatheBufferGeometry extends LatheGeometry {
50279
50280	constructor( points, segments, phiStart, phiLength ) {
50281
50282		console.warn( 'THREE.LatheBufferGeometry has been renamed to THREE.LatheGeometry.' );
50283		super( points, segments, phiStart, phiLength );
50284
50285	}
50286
50287}
50288
50289// r144
50290
50291class OctahedronBufferGeometry extends OctahedronGeometry {
50292
50293	constructor( radius, detail ) {
50294
50295		console.warn( 'THREE.OctahedronBufferGeometry has been renamed to THREE.OctahedronGeometry.' );
50296		super( radius, detail );
50297
50298	}
50299
50300}
50301
50302// r144
50303
50304class PlaneBufferGeometry extends PlaneGeometry {
50305
50306	constructor( width, height, widthSegments, heightSegments ) {
50307
50308		console.warn( 'THREE.PlaneBufferGeometry has been renamed to THREE.PlaneGeometry.' );
50309		super( width, height, widthSegments, heightSegments );
50310
50311	}
50312
50313}
50314
50315// r144
50316
50317class PolyhedronBufferGeometry extends PolyhedronGeometry {
50318
50319	constructor( vertices, indices, radius, detail ) {
50320
50321		console.warn( 'THREE.PolyhedronBufferGeometry has been renamed to THREE.PolyhedronGeometry.' );
50322		super( vertices, indices, radius, detail );
50323
50324	}
50325
50326}
50327
50328// r144
50329
50330class RingBufferGeometry extends RingGeometry {
50331
50332	constructor( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {
50333
50334		console.warn( 'THREE.RingBufferGeometry has been renamed to THREE.RingGeometry.' );
50335		super( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength );
50336
50337	}
50338
50339}
50340
50341// r144
50342
50343class ShapeBufferGeometry extends ShapeGeometry {
50344
50345	constructor( shapes, curveSegments ) {
50346
50347		console.warn( 'THREE.ShapeBufferGeometry has been renamed to THREE.ShapeGeometry.' );
50348		super( shapes, curveSegments );
50349
50350	}
50351
50352}
50353
50354// r144
50355
50356class SphereBufferGeometry extends SphereGeometry {
50357
50358	constructor( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
50359
50360		console.warn( 'THREE.SphereBufferGeometry has been renamed to THREE.SphereGeometry.' );
50361		super( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength );
50362
50363	}
50364
50365}
50366
50367// r144
50368
50369class TetrahedronBufferGeometry extends TetrahedronGeometry {
50370
50371	constructor( radius, detail ) {
50372
50373		console.warn( 'THREE.TetrahedronBufferGeometry has been renamed to THREE.TetrahedronGeometry.' );
50374		super( radius, detail );
50375
50376	}
50377
50378}
50379
50380// r144
50381
50382class TorusBufferGeometry extends TorusGeometry {
50383
50384	constructor( radius, tube, radialSegments, tubularSegments, arc ) {
50385
50386		console.warn( 'THREE.TorusBufferGeometry has been renamed to THREE.TorusGeometry.' );
50387		super( radius, tube, radialSegments, tubularSegments, arc );
50388
50389	}
50390
50391}
50392
50393// r144
50394
50395class TorusKnotBufferGeometry extends TorusKnotGeometry {
50396
50397	constructor( radius, tube, tubularSegments, radialSegments, p, q ) {
50398
50399		console.warn( 'THREE.TorusKnotBufferGeometry has been renamed to THREE.TorusKnotGeometry.' );
50400		super( radius, tube, tubularSegments, radialSegments, p, q );
50401
50402	}
50403
50404}
50405
50406// r144
50407
50408class TubeBufferGeometry extends TubeGeometry {
50409
50410	constructor( path, tubularSegments, radius, radialSegments, closed ) {
50411
50412		console.warn( 'THREE.TubeBufferGeometry has been renamed to THREE.TubeGeometry.' );
50413		super( path, tubularSegments, radius, radialSegments, closed );
50414
50415	}
50416
50417}
50418
50419if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
50420
50421	__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
50422		revision: REVISION,
50423	} } ) );
50424
50425}
50426
50427if ( typeof window !== 'undefined' ) {
50428
50429	if ( window.__THREE__ ) {
50430
50431		console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
50432
50433	} else {
50434
50435		window.__THREE__ = REVISION;
50436
50437	}
50438
50439}
50440
50441export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AlphaFormat, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightProbe, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxBufferGeometry, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleBufferGeometry, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleBufferGeometry, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedTexture, CompressedTextureLoader, ConeBufferGeometry, ConeGeometry, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderBufferGeometry, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronBufferGeometry, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeBufferGeometry, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, Float64BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterDepth, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightProbe, IcosahedronBufferGeometry, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheBufferGeometry, LatheGeometry, Layers, LessDepth, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearEncoding, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, MOUSE, Material, MaterialLoader, MathUtils, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronBufferGeometry, OctahedronGeometry, OneFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, Orthogra
50441phicCamera, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, Path, PerspectiveCamera, Plane, PlaneBufferGeometry, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronBufferGeometry, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, 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, 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, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, Scene, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeBufferGeometry, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereBufferGeometry, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronBufferGeometry, TetrahedronGeometry, Texture, TextureLoader, TorusBufferGeometry, TorusGeometry, TorusKnotBufferGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeBufferGeometry, TubeGeometry, TwoPassDoubleSide, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL1Renderer, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, _SRGBAFormat, 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.