PageSourceSearch

https://inchbyinch.ru/local/templates/inch/js/three/three.module.js

js inchbyinch.ru collected 2026-10-07 12:33:14 UTC 1,268,830 bytes, 52,804 lines download raw bytes

1/**
2 * @license
3 * Copyright 2010-2023 Three.js Authors
4 * SPDX-License-Identifier: MIT
5 */
6const REVISION = '163';
7
8const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
9const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
10const CullFaceNone = 0;
11const CullFaceBack = 1;
12const CullFaceFront = 2;
13const CullFaceFrontBack = 3;
14const BasicShadowMap = 0;
15const PCFShadowMap = 1;
16const PCFSoftShadowMap = 2;
17const VSMShadowMap = 3;
18const FrontSide = 0;
19const BackSide = 1;
20const DoubleSide = 2;
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 ConstantColorFactor = 211;
44const OneMinusConstantColorFactor = 212;
45const ConstantAlphaFactor = 213;
46const OneMinusConstantAlphaFactor = 214;
47const NeverDepth = 0;
48const AlwaysDepth = 1;
49const LessDepth = 2;
50const LessEqualDepth = 3;
51const EqualDepth = 4;
52const GreaterEqualDepth = 5;
53const GreaterDepth = 6;
54const NotEqualDepth = 7;
55const MultiplyOperation = 0;
56const MixOperation = 1;
57const AddOperation = 2;
58const NoToneMapping = 0;
59const LinearToneMapping = 1;
60const ReinhardToneMapping = 2;
61const CineonToneMapping = 3;
62const ACESFilmicToneMapping = 4;
63const CustomToneMapping = 5;
64const AgXToneMapping = 6;
65const NeutralToneMapping = 7;
66const AttachedBindMode = 'attached';
67const DetachedBindMode = 'detached';
68
69const UVMapping = 300;
70const CubeReflectionMapping = 301;
71const CubeRefractionMapping = 302;
72const EquirectangularReflectionMapping = 303;
73const EquirectangularRefractionMapping = 304;
74const CubeUVReflectionMapping = 306;
75const RepeatWrapping = 1000;
76const ClampToEdgeWrapping = 1001;
77const MirroredRepeatWrapping = 1002;
78const NearestFilter = 1003;
79const NearestMipmapNearestFilter = 1004;
80const NearestMipMapNearestFilter = 1004;
81const NearestMipmapLinearFilter = 1005;
82const NearestMipMapLinearFilter = 1005;
83const LinearFilter = 1006;
84const LinearMipmapNearestFilter = 1007;
85const LinearMipMapNearestFilter = 1007;
86const LinearMipmapLinearFilter = 1008;
87const LinearMipMapLinearFilter = 1008;
88const UnsignedByteType = 1009;
89const ByteType = 1010;
90const ShortType = 1011;
91const UnsignedShortType = 1012;
92const IntType = 1013;
93const UnsignedIntType = 1014;
94const FloatType = 1015;
95const HalfFloatType = 1016;
96const UnsignedShort4444Type = 1017;
97const UnsignedShort5551Type = 1018;
98const UnsignedInt248Type = 1020;
99const UnsignedInt5999Type = 35902;
100const AlphaFormat = 1021;
101const RGBFormat = 1022;
102const RGBAFormat = 1023;
103const LuminanceFormat = 1024;
104const LuminanceAlphaFormat = 1025;
105const DepthFormat = 1026;
106const DepthStencilFormat = 1027;
107const RedFormat = 1028;
108const RedIntegerFormat = 1029;
109const RGFormat = 1030;
110const RGIntegerFormat = 1031;
111const RGBAIntegerFormat = 1033;
112
113const RGB_S3TC_DXT1_Format = 33776;
114const RGBA_S3TC_DXT1_Format = 33777;
115const RGBA_S3TC_DXT3_Format = 33778;
116const RGBA_S3TC_DXT5_Format = 33779;
117const RGB_PVRTC_4BPPV1_Format = 35840;
118const RGB_PVRTC_2BPPV1_Format = 35841;
119const RGBA_PVRTC_4BPPV1_Format = 35842;
120const RGBA_PVRTC_2BPPV1_Format = 35843;
121const RGB_ETC1_Format = 36196;
122const RGB_ETC2_Format = 37492;
123const RGBA_ETC2_EAC_Format = 37496;
124const RGBA_ASTC_4x4_Format = 37808;
125const RGBA_ASTC_5x4_Format = 37809;
126const RGBA_ASTC_5x5_Format = 37810;
127const RGBA_ASTC_6x5_Format = 37811;
128const RGBA_ASTC_6x6_Format = 37812;
129const RGBA_ASTC_8x5_Format = 37813;
130const RGBA_ASTC_8x6_Format = 37814;
131const RGBA_ASTC_8x8_Format = 37815;
132const RGBA_ASTC_10x5_Format = 37816;
133const RGBA_ASTC_10x6_Format = 37817;
134const RGBA_ASTC_10x8_Format = 37818;
135const RGBA_ASTC_10x10_Format = 37819;
136const RGBA_ASTC_12x10_Format = 37820;
137const RGBA_ASTC_12x12_Format = 37821;
138const RGBA_BPTC_Format = 36492;
139const RGB_BPTC_SIGNED_Format = 36494;
140const RGB_BPTC_UNSIGNED_Format = 36495;
141const RED_RGTC1_Format = 36283;
vendor: 8,145 bytes, lines 142-430
142const SIGNED_RED_RGTC1_Format = 36284;
143const RED_GREEN_RGTC2_Format = 36285;
144const SIGNED_RED_GREEN_RGTC2_Format = 36286;
145const LoopOnce = 2200;
146const LoopRepeat = 2201;
147const LoopPingPong = 2202;
148const InterpolateDiscrete = 2300;
149const InterpolateLinear = 2301;
150const InterpolateSmooth = 2302;
151const ZeroCurvatureEnding = 2400;
152const ZeroSlopeEnding = 2401;
153const WrapAroundEnding = 2402;
154const NormalAnimationBlendMode = 2500;
155const AdditiveAnimationBlendMode = 2501;
156const TrianglesDrawMode = 0;
157const TriangleStripDrawMode = 1;
158const TriangleFanDrawMode = 2;
159const BasicDepthPacking = 3200;
160const RGBADepthPacking = 3201;
161const TangentSpaceNormalMap = 0;
162const ObjectSpaceNormalMap = 1;
163
164// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available.
165const NoColorSpace = '';
166const SRGBColorSpace = 'srgb';
167const LinearSRGBColorSpace = 'srgb-linear';
168const DisplayP3ColorSpace = 'display-p3';
169const LinearDisplayP3ColorSpace = 'display-p3-linear';
170
171const LinearTransfer = 'linear';
172const SRGBTransfer = 'srgb';
173
174const Rec709Primaries = 'rec709';
175const P3Primaries = 'p3';
176
177const ZeroStencilOp = 0;
178const KeepStencilOp = 7680;
179const ReplaceStencilOp = 7681;
180const IncrementStencilOp = 7682;
181const DecrementStencilOp = 7683;
182const IncrementWrapStencilOp = 34055;
183const DecrementWrapStencilOp = 34056;
184const InvertStencilOp = 5386;
185
186const NeverStencilFunc = 512;
187const LessStencilFunc = 513;
188const EqualStencilFunc = 514;
189const LessEqualStencilFunc = 515;
190const GreaterStencilFunc = 516;
191const NotEqualStencilFunc = 517;
192const GreaterEqualStencilFunc = 518;
193const AlwaysStencilFunc = 519;
194
195const NeverCompare = 512;
196const LessCompare = 513;
197const EqualCompare = 514;
198const LessEqualCompare = 515;
199const GreaterCompare = 516;
200const NotEqualCompare = 517;
201const GreaterEqualCompare = 518;
202const AlwaysCompare = 519;
203
204const StaticDrawUsage = 35044;
205const DynamicDrawUsage = 35048;
206const StreamDrawUsage = 35040;
207const StaticReadUsage = 35045;
208const DynamicReadUsage = 35049;
209const StreamReadUsage = 35041;
210const StaticCopyUsage = 35046;
211const DynamicCopyUsage = 35050;
212const StreamCopyUsage = 35042;
213
214const GLSL1 = '100';
215const GLSL3 = '300 es';
216
217const WebGLCoordinateSystem = 2000;
218const WebGPUCoordinateSystem = 2001;
219
220/**
221 * https://github.com/mrdoob/eventdispatcher.js/
222 */
223
224class EventDispatcher {
225
226	addEventListener( type, listener ) {
227
228		if ( this._listeners === undefined ) this._listeners = {};
229
230		const listeners = this._listeners;
231
232		if ( listeners[ type ] === undefined ) {
233
234			listeners[ type ] = [];
235
236		}
237
238		if ( listeners[ type ].indexOf( listener ) === - 1 ) {
239
240			listeners[ type ].push( listener );
241
242		}
243
244	}
245
246	hasEventListener( type, listener ) {
247
248		if ( this._listeners === undefined ) return false;
249
250		const listeners = this._listeners;
251
252		return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
253
254	}
255
256	removeEventListener( type, listener ) {
257
258		if ( this._listeners === undefined ) return;
259
260		const listeners = this._listeners;
261		const listenerArray = listeners[ type ];
262
263		if ( listenerArray !== undefined ) {
264
265			const index = listenerArray.indexOf( listener );
266
267			if ( index !== - 1 ) {
268
269				listenerArray.splice( index, 1 );
270
271			}
272
273		}
274
275	}
276
277	dispatchEvent( event ) {
278
279		if ( this._listeners === undefined ) return;
280
281		const listeners = this._listeners;
282		const listenerArray = listeners[ event.type ];
283
284		if ( listenerArray !== undefined ) {
285
286			event.target = this;
287
288			// Make a copy, in case listeners are removed while iterating.
289			const array = listenerArray.slice( 0 );
290
291			for ( let i = 0, l = array.length; i < l; i ++ ) {
292
293				array[ i ].call( this, event );
294
295			}
296
297			event.target = null;
298
299		}
300
301	}
302
303}
304
305const _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' ];
306
307let _seed = 1234567;
308
309
310const DEG2RAD = Math.PI / 180;
311const RAD2DEG = 180 / Math.PI;
312
313// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
314function generateUUID() {
315
316	const d0 = Math.random() * 0xffffffff | 0;
317	const d1 = Math.random() * 0xffffffff | 0;
318	const d2 = Math.random() * 0xffffffff | 0;
319	const d3 = Math.random() * 0xffffffff | 0;
320	const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
321			_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
322			_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
323			_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
324
325	// .toLowerCase() here flattens concatenated strings to save heap memory space.
326	return uuid.toLowerCase();
327
328}
329
330function clamp( value, min, max ) {
331
332	return Math.max( min, Math.min( max, value ) );
333
334}
335
336// compute euclidean modulo of m % n
337// https://en.wikipedia.org/wiki/Modulo_operation
338function euclideanModulo( n, m ) {
339
340	return ( ( n % m ) + m ) % m;
341
342}
343
344// Linear mapping from range <a1, a2> to range <b1, b2>
345function mapLinear( x, a1, a2, b1, b2 ) {
346
347	return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
348
349}
350
351// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
352function inverseLerp( x, y, value ) {
353
354	if ( x !== y ) {
355
356		return ( value - x ) / ( y - x );
357
358	} else {
359
360		return 0;
361
362	}
363
364}
365
366// https://en.wikipedia.org/wiki/Linear_interpolation
367function lerp( x, y, t ) {
368
369	return ( 1 - t ) * x + t * y;
370
371}
372
373// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
374function damp( x, y, lambda, dt ) {
375
376	return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
377
378}
379
380// https://www.desmos.com/calculator/vcsjnyz7x4
381function pingpong( x, length = 1 ) {
382
383	return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
384
385}
386
387// http://en.wikipedia.org/wiki/Smoothstep
388function smoothstep( x, min, max ) {
389
390	if ( x <= min ) return 0;
391	if ( x >= max ) return 1;
392
393	x = ( x - min ) / ( max - min );
394
395	return x * x * ( 3 - 2 * x );
396
397}
398
399function smootherstep( x, min, max ) {
400
401	if ( x <= min ) return 0;
402	if ( x >= max ) return 1;
403
404	x = ( x - min ) / ( max - min );
405
406	return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
407
408}
409
410// Random integer from <low, high> interval
411function randInt( low, high ) {
412
413	return low + Math.floor( Math.random() * ( high - low + 1 ) );
414
415}
416
417// Random float from <low, high> interval
418function randFloat( low, high ) {
419
420	return low + Math.random() * ( high - low );
421
422}
423
424// Random float from <-range/2, range/2> interval
425function randFloatSpread( range ) {
426
427	return range * ( 0.5 - Math.random() );
428
429}
430
vendor: 7,916 bytes, lines 431-1006
431// Deterministic pseudo-random float in the interval [ 0, 1 ]
432function seededRandom( s ) {
433
434	if ( s !== undefined ) _seed = s;
435
436	// Mulberry32 generator
437
438	let t = _seed += 0x6D2B79F5;
439
440	t = Math.imul( t ^ t >>> 15, t | 1 );
441
442	t ^= t + Math.imul( t ^ t >>> 7, t | 61 );
443
444	return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296;
445
446}
447
448function degToRad( degrees ) {
449
450	return degrees * DEG2RAD;
451
452}
453
454function radToDeg( radians ) {
455
456	return radians * RAD2DEG;
457
458}
459
460function isPowerOfTwo( value ) {
461
462	return ( value & ( value - 1 ) ) === 0 && value !== 0;
463
464}
465
466function ceilPowerOfTwo( value ) {
467
468	return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
469
470}
471
472function floorPowerOfTwo( value ) {
473
474	return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
475
476}
477
478function setQuaternionFromProperEuler( q, a, b, c, order ) {
479
480	// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
481
482	// rotations are applied to the axes in the order specified by 'order'
483	// rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
484	// angles are in radians
485
486	const cos = Math.cos;
487	const sin = Math.sin;
488
489	const c2 = cos( b / 2 );
490	const s2 = sin( b / 2 );
491
492	const c13 = cos( ( a + c ) / 2 );
493	const s13 = sin( ( a + c ) / 2 );
494
495	const c1_3 = cos( ( a - c ) / 2 );
496	const s1_3 = sin( ( a - c ) / 2 );
497
498	const c3_1 = cos( ( c - a ) / 2 );
499	const s3_1 = sin( ( c - a ) / 2 );
500
501	switch ( order ) {
502
503		case 'XYX':
504			q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
505			break;
506
507		case 'YZY':
508			q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
509			break;
510
511		case 'ZXZ':
512			q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
513			break;
514
515		case 'XZX':
516			q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
517			break;
518
519		case 'YXY':
520			q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
521			break;
522
523		case 'ZYZ':
524			q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
525			break;
526
527		default:
528			console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
529
530	}
531
532}
533
534function denormalize( value, array ) {
535
536	switch ( array.constructor ) {
537
538		case Float32Array:
539
540			return value;
541
542		case Uint32Array:
543
544			return value / 4294967295.0;
545
546		case Uint16Array:
547
548			return value / 65535.0;
549
550		case Uint8Array:
551
552			return value / 255.0;
553
554		case Int32Array:
555
556			return Math.max( value / 2147483647.0, - 1.0 );
557
558		case Int16Array:
559
560			return Math.max( value / 32767.0, - 1.0 );
561
562		case Int8Array:
563
564			return Math.max( value / 127.0, - 1.0 );
565
566		default:
567
568			throw new Error( 'Invalid component type.' );
569
570	}
571
572}
573
574function normalize( value, array ) {
575
576	switch ( array.constructor ) {
577
578		case Float32Array:
579
580			return value;
581
582		case Uint32Array:
583
584			return Math.round( value * 4294967295.0 );
585
586		case Uint16Array:
587
588			return Math.round( value * 65535.0 );
589
590		case Uint8Array:
591
592			return Math.round( value * 255.0 );
593
594		case Int32Array:
595
596			return Math.round( value * 2147483647.0 );
597
598		case Int16Array:
599
600			return Math.round( value * 32767.0 );
601
602		case Int8Array:
603
604			return Math.round( value * 127.0 );
605
606		default:
607
608			throw new Error( 'Invalid component type.' );
609
610	}
611
612}
613
614const MathUtils = {
615	DEG2RAD: DEG2RAD,
616	RAD2DEG: RAD2DEG,
617	generateUUID: generateUUID,
618	clamp: clamp,
619	euclideanModulo: euclideanModulo,
620	mapLinear: mapLinear,
621	inverseLerp: inverseLerp,
622	lerp: lerp,
623	damp: damp,
624	pingpong: pingpong,
625	smoothstep: smoothstep,
626	smootherstep: smootherstep,
627	randInt: randInt,
628	randFloat: randFloat,
629	randFloatSpread: randFloatSpread,
630	seededRandom: seededRandom,
631	degToRad: degToRad,
632	radToDeg: radToDeg,
633	isPowerOfTwo: isPowerOfTwo,
634	ceilPowerOfTwo: ceilPowerOfTwo,
635	floorPowerOfTwo: floorPowerOfTwo,
636	setQuaternionFromProperEuler: setQuaternionFromProperEuler,
637	normalize: normalize,
638	denormalize: denormalize
639};
640
641class Vector2 {
642
643	constructor( x = 0, y = 0 ) {
644
645		Vector2.prototype.isVector2 = true;
646
647		this.x = x;
648		this.y = y;
649
650	}
651
652	get width() {
653
654		return this.x;
655
656	}
657
658	set width( value ) {
659
660		this.x = value;
661
662	}
663
664	get height() {
665
666		return this.y;
667
668	}
669
670	set height( value ) {
671
672		this.y = value;
673
674	}
675
676	set( x, y ) {
677
678		this.x = x;
679		this.y = y;
680
681		return this;
682
683	}
684
685	setScalar( scalar ) {
686
687		this.x = scalar;
688		this.y = scalar;
689
690		return this;
691
692	}
693
694	setX( x ) {
695
696		this.x = x;
697
698		return this;
699
700	}
701
702	setY( y ) {
703
704		this.y = y;
705
706		return this;
707
708	}
709
710	setComponent( index, value ) {
711
712		switch ( index ) {
713
714			case 0: this.x = value; break;
715			case 1: this.y = value; break;
716			default: throw new Error( 'index is out of range: ' + index );
717
718		}
719
720		return this;
721
722	}
723
724	getComponent( index ) {
725
726		switch ( index ) {
727
728			case 0: return this.x;
729			case 1: return this.y;
730			default: throw new Error( 'index is out of range: ' + index );
731
732		}
733
734	}
735
736	clone() {
737
738		return new this.constructor( this.x, this.y );
739
740	}
741
742	copy( v ) {
743
744		this.x = v.x;
745		this.y = v.y;
746
747		return this;
748
749	}
750
751	add( v ) {
752
753		this.x += v.x;
754		this.y += v.y;
755
756		return this;
757
758	}
759
760	addScalar( s ) {
761
762		this.x += s;
763		this.y += s;
764
765		return this;
766
767	}
768
769	addVectors( a, b ) {
770
771		this.x = a.x + b.x;
772		this.y = a.y + b.y;
773
774		return this;
775
776	}
777
778	addScaledVector( v, s ) {
779
780		this.x += v.x * s;
781		this.y += v.y * s;
782
783		return this;
784
785	}
786
787	sub( v ) {
788
789		this.x -= v.x;
790		this.y -= v.y;
791
792		return this;
793
794	}
795
796	subScalar( s ) {
797
798		this.x -= s;
799		this.y -= s;
800
801		return this;
802
803	}
804
805	subVectors( a, b ) {
806
807		this.x = a.x - b.x;
808		this.y = a.y - b.y;
809
810		return this;
811
812	}
813
814	multiply( v ) {
815
816		this.x *= v.x;
817		this.y *= v.y;
818
819		return this;
820
821	}
822
823	multiplyScalar( scalar ) {
824
825		this.x *= scalar;
826		this.y *= scalar;
827
828		return this;
829
830	}
831
832	divide( v ) {
833
834		this.x /= v.x;
835		this.y /= v.y;
836
837		return this;
838
839	}
840
841	divideScalar( scalar ) {
842
843		return this.multiplyScalar( 1 / scalar );
844
845	}
846
847	applyMatrix3( m ) {
848
849		const x = this.x, y = this.y;
850		const e = m.elements;
851
852		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
853		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
854
855		return this;
856
857	}
858
859	min( v ) {
860
861		this.x = Math.min( this.x, v.x );
862		this.y = Math.min( this.y, v.y );
863
864		return this;
865
866	}
867
868	max( v ) {
869
870		this.x = Math.max( this.x, v.x );
871		this.y = Math.max( this.y, v.y );
872
873		return this;
874
875	}
876
877	clamp( min, max ) {
878
879		// assumes min < max, componentwise
880
881		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
882		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
883
884		return this;
885
886	}
887
888	clampScalar( minVal, maxVal ) {
889
890		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
891		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
892
893		return this;
894
895	}
896
897	clampLength( min, max ) {
898
899		const length = this.length();
900
901		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
902
903	}
904
905	floor() {
906
907		this.x = Math.floor( this.x );
908		this.y = Math.floor( this.y );
909
910		return this;
911
912	}
913
914	ceil() {
915
916		this.x = Math.ceil( this.x );
917		this.y = Math.ceil( this.y );
918
919		return this;
920
921	}
922
923	round() {
924
925		this.x = Math.round( this.x );
926		this.y = Math.round( this.y );
927
928		return this;
929
930	}
931
932	roundToZero() {
933
934		this.x = Math.trunc( this.x );
935		this.y = Math.trunc( this.y );
936
937		return this;
938
939	}
940
941	negate() {
942
943		this.x = - this.x;
944		this.y = - this.y;
945
946		return this;
947
948	}
949
950	dot( v ) {
951
952		return this.x * v.x + this.y * v.y;
953
954	}
955
956	cross( v ) {
957
958		return this.x * v.y - this.y * v.x;
959
960	}
961
962	lengthSq() {
963
964		return this.x * this.x + this.y * this.y;
965
966	}
967
968	length() {
969
970		return Math.sqrt( this.x * this.x + this.y * this.y );
971
972	}
973
974	manhattanLength() {
975
976		return Math.abs( this.x ) + Math.abs( this.y );
977
978	}
979
980	normalize() {
981
982		return this.divideScalar( this.length() || 1 );
983
984	}
985
986	angle() {
987
988		// computes the angle in radians with respect to the positive x-axis
989
990		const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
991
992		return angle;
993
994	}
995
996	angleTo( v ) {
997
998		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
999
1000		if ( denominator === 0 ) return Math.PI / 2;
1001
1002		const theta = this.dot( v ) / denominator;
1003
1004		// clamp, to handle numerical problems
1005
1006		return Math.acos( clamp( theta, - 
vendor: 7,768 bytes, lines 1006-1518
10061, 1 ) );
1007
1008	}
1009
1010	distanceTo( v ) {
1011
1012		return Math.sqrt( this.distanceToSquared( v ) );
1013
1014	}
1015
1016	distanceToSquared( v ) {
1017
1018		const dx = this.x - v.x, dy = this.y - v.y;
1019		return dx * dx + dy * dy;
1020
1021	}
1022
1023	manhattanDistanceTo( v ) {
1024
1025		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
1026
1027	}
1028
1029	setLength( length ) {
1030
1031		return this.normalize().multiplyScalar( length );
1032
1033	}
1034
1035	lerp( v, alpha ) {
1036
1037		this.x += ( v.x - this.x ) * alpha;
1038		this.y += ( v.y - this.y ) * alpha;
1039
1040		return this;
1041
1042	}
1043
1044	lerpVectors( v1, v2, alpha ) {
1045
1046		this.x = v1.x + ( v2.x - v1.x ) * alpha;
1047		this.y = v1.y + ( v2.y - v1.y ) * alpha;
1048
1049		return this;
1050
1051	}
1052
1053	equals( v ) {
1054
1055		return ( ( v.x === this.x ) && ( v.y === this.y ) );
1056
1057	}
1058
1059	fromArray( array, offset = 0 ) {
1060
1061		this.x = array[ offset ];
1062		this.y = array[ offset + 1 ];
1063
1064		return this;
1065
1066	}
1067
1068	toArray( array = [], offset = 0 ) {
1069
1070		array[ offset ] = this.x;
1071		array[ offset + 1 ] = this.y;
1072
1073		return array;
1074
1075	}
1076
1077	fromBufferAttribute( attribute, index ) {
1078
1079		this.x = attribute.getX( index );
1080		this.y = attribute.getY( index );
1081
1082		return this;
1083
1084	}
1085
1086	rotateAround( center, angle ) {
1087
1088		const c = Math.cos( angle ), s = Math.sin( angle );
1089
1090		const x = this.x - center.x;
1091		const y = this.y - center.y;
1092
1093		this.x = x * c - y * s + center.x;
1094		this.y = x * s + y * c + center.y;
1095
1096		return this;
1097
1098	}
1099
1100	random() {
1101
1102		this.x = Math.random();
1103		this.y = Math.random();
1104
1105		return this;
1106
1107	}
1108
1109	*[ Symbol.iterator ]() {
1110
1111		yield this.x;
1112		yield this.y;
1113
1114	}
1115
1116}
1117
1118class Matrix3 {
1119
1120	constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1121
1122		Matrix3.prototype.isMatrix3 = true;
1123
1124		this.elements = [
1125
1126			1, 0, 0,
1127			0, 1, 0,
1128			0, 0, 1
1129
1130		];
1131
1132		if ( n11 !== undefined ) {
1133
1134			this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 );
1135
1136		}
1137
1138	}
1139
1140	set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1141
1142		const te = this.elements;
1143
1144		te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
1145		te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
1146		te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
1147
1148		return this;
1149
1150	}
1151
1152	identity() {
1153
1154		this.set(
1155
1156			1, 0, 0,
1157			0, 1, 0,
1158			0, 0, 1
1159
1160		);
1161
1162		return this;
1163
1164	}
1165
1166	copy( m ) {
1167
1168		const te = this.elements;
1169		const me = m.elements;
1170
1171		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
1172		te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
1173		te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
1174
1175		return this;
1176
1177	}
1178
1179	extractBasis( xAxis, yAxis, zAxis ) {
1180
1181		xAxis.setFromMatrix3Column( this, 0 );
1182		yAxis.setFromMatrix3Column( this, 1 );
1183		zAxis.setFromMatrix3Column( this, 2 );
1184
1185		return this;
1186
1187	}
1188
1189	setFromMatrix4( m ) {
1190
1191		const me = m.elements;
1192
1193		this.set(
1194
1195			me[ 0 ], me[ 4 ], me[ 8 ],
1196			me[ 1 ], me[ 5 ], me[ 9 ],
1197			me[ 2 ], me[ 6 ], me[ 10 ]
1198
1199		);
1200
1201		return this;
1202
1203	}
1204
1205	multiply( m ) {
1206
1207		return this.multiplyMatrices( this, m );
1208
1209	}
1210
1211	premultiply( m ) {
1212
1213		return this.multiplyMatrices( m, this );
1214
1215	}
1216
1217	multiplyMatrices( a, b ) {
1218
1219		const ae = a.elements;
1220		const be = b.elements;
1221		const te = this.elements;
1222
1223		const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
1224		const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
1225		const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
1226
1227		const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
1228		const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
1229		const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
1230
1231		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
1232		te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
1233		te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
1234
1235		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
1236		te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
1237		te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
1238
1239		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
1240		te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
1241		te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
1242
1243		return this;
1244
1245	}
1246
1247	multiplyScalar( s ) {
1248
1249		const te = this.elements;
1250
1251		te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
1252		te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
1253		te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
1254
1255		return this;
1256
1257	}
1258
1259	determinant() {
1260
1261		const te = this.elements;
1262
1263		const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
1264			d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
1265			g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
1266
1267		return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
1268
1269	}
1270
1271	invert() {
1272
1273		const te = this.elements,
1274
1275			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
1276			n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
1277			n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
1278
1279			t11 = n33 * n22 - n32 * n23,
1280			t12 = n32 * n13 - n33 * n12,
1281			t13 = n23 * n12 - n22 * n13,
1282
1283			det = n11 * t11 + n21 * t12 + n31 * t13;
1284
1285		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1286
1287		const detInv = 1 / det;
1288
1289		te[ 0 ] = t11 * detInv;
1290		te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
1291		te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
1292
1293		te[ 3 ] = t12 * detInv;
1294		te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
1295		te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
1296
1297		te[ 6 ] = t13 * detInv;
1298		te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
1299		te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
1300
1301		return this;
1302
1303	}
1304
1305	transpose() {
1306
1307		let tmp;
1308		const m = this.elements;
1309
1310		tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
1311		tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
1312		tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
1313
1314		return this;
1315
1316	}
1317
1318	getNormalMatrix( matrix4 ) {
1319
1320		return this.setFromMatrix4( matrix4 ).invert().transpose();
1321
1322	}
1323
1324	transposeIntoArray( r ) {
1325
1326		const m = this.elements;
1327
1328		r[ 0 ] = m[ 0 ];
1329		r[ 1 ] = m[ 3 ];
1330		r[ 2 ] = m[ 6 ];
1331		r[ 3 ] = m[ 1 ];
1332		r[ 4 ] = m[ 4 ];
1333		r[ 5 ] = m[ 7 ];
1334		r[ 6 ] = m[ 2 ];
1335		r[ 7 ] = m[ 5 ];
1336		r[ 8 ] = m[ 8 ];
1337
1338		return this;
1339
1340	}
1341
1342	setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
1343
1344		const c = Math.cos( rotation );
1345		const s = Math.sin( rotation );
1346
1347		this.set(
1348			sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
1349			- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
1350			0, 0, 1
1351		);
1352
1353		return this;
1354
1355	}
1356
1357	//
1358
1359	scale( sx, sy ) {
1360
1361		this.premultiply( _m3.makeScale( sx, sy ) );
1362
1363		return this;
1364
1365	}
1366
1367	rotate( theta ) {
1368
1369		this.premultiply( _m3.makeRotation( - theta ) );
1370
1371		return this;
1372
1373	}
1374
1375	translate( tx, ty ) {
1376
1377		this.premultiply( _m3.makeTranslation( tx, ty ) );
1378
1379		return this;
1380
1381	}
1382
1383	// for 2D Transforms
1384
1385	makeTranslation( x, y ) {
1386
1387		if ( x.isVector2 ) {
1388
1389			this.set(
1390
1391				1, 0, x.x,
1392				0, 1, x.y,
1393				0, 0, 1
1394
1395			);
1396
1397		} else {
1398
1399			this.set(
1400
1401				1, 0, x,
1402				0, 1, y,
1403				0, 0, 1
1404
1405			);
1406
1407		}
1408
1409		return this;
1410
1411	}
1412
1413	makeRotation( theta ) {
1414
1415		// counterclockwise
1416
1417		const c = Math.cos( theta );
1418		const s = Math.sin( theta );
1419
1420		this.set(
1421
1422			c, - s, 0,
1423			s, c, 0,
1424			0, 0, 1
1425
1426		);
1427
1428		return this;
1429
1430	}
1431
1432	makeScale( x, y ) {
1433
1434		this.set(
1435
1436			x, 0, 0,
1437			0, y, 0,
1438			0, 0, 1
1439
1440		);
1441
1442		return this;
1443
1444	}
1445
1446	//
1447
1448	equals( matrix ) {
1449
1450		const te = this.elements;
1451		const me = matrix.elements;
1452
1453		for ( let i = 0; i < 9; i ++ ) {
1454
1455			if ( te[ i ] !== me[ i ] ) return false;
1456
1457		}
1458
1459		return true;
1460
1461	}
1462
1463	fromArray( array, offset = 0 ) {
1464
1465		for ( let i = 0; i < 9; i ++ ) {
1466
1467			this.elements[ i ] = array[ i + offset ];
1468
1469		}
1470
1471		return this;
1472
1473	}
1474
1475	toArray( array = [], offset = 0 ) {
1476
1477		const te = this.elements;
1478
1479		array[ offset ] = te[ 0 ];
1480		array[ offset + 1 ] = te[ 1 ];
1481		array[ offset + 2 ] = te[ 2 ];
1482
1483		array[ offset + 3 ] = te[ 3 ];
1484		array[ offset + 4 ] = te[ 4 ];
1485		array[ offset + 5 ] = te[ 5 ];
1486
1487		array[ offset + 6 ] = te[ 6 ];
1488		array[ offset + 7 ] = te[ 7 ];
1489		array[ offset + 8 ] = te[ 8 ];
1490
1491		return array;
1492
1493	}
1494
1495	clone() {
1496
1497		return new this.constructor().fromArray( this.elements );
1498
1499	}
1500
1501}
1502
1503const _m3 = /*@__PURE__*/ new Matrix3();
1504
1505function arrayNeedsUint32( array ) {
1506
1507	// assumes larger values usually on last
1508
1509	for ( let i = array.length - 1; i >= 0; -- i ) {
1510
1511		if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
1512
1513	}
1514
1515	return false;
1516
1517}
1518
vendor: 13,026 bytes, lines 1519-2158
1519const TYPED_ARRAYS = {
1520	Int8Array: Int8Array,
1521	Uint8Array: Uint8Array,
1522	Uint8ClampedArray: Uint8ClampedArray,
1523	Int16Array: Int16Array,
1524	Uint16Array: Uint16Array,
1525	Int32Array: Int32Array,
1526	Uint32Array: Uint32Array,
1527	Float32Array: Float32Array,
1528	Float64Array: Float64Array
1529};
1530
1531function getTypedArray( type, buffer ) {
1532
1533	return new TYPED_ARRAYS[ type ]( buffer );
1534
1535}
1536
1537function createElementNS( name ) {
1538
1539	return document.createElementNS( 'http://www.w3.org/1999/xhtml', name );
1540
1541}
1542
1543function createCanvasElement() {
1544
1545	const canvas = createElementNS( 'canvas' );
1546	canvas.style.display = 'block';
1547	return canvas;
1548
1549}
1550
1551const _cache = {};
1552
1553function warnOnce( message ) {
1554
1555	if ( message in _cache ) return;
1556
1557	_cache[ message ] = true;
1558
1559	console.warn( message );
1560
1561}
1562
1563/**
1564 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping
1565 * or clipping. Based on W3C specifications for sRGB and Display P3,
1566 * and ICC specifications for the D50 connection space. Values in/out
1567 * are _linear_ sRGB and _linear_ Display P3.
1568 *
1569 * Note that both sRGB and Display P3 use the sRGB transfer functions.
1570 *
1571 * Reference:
1572 * - http://www.russellcottrell.com/photo/matrixCalculator.htm
1573 */
1574
1575const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set(
1576	0.8224621, 0.177538, 0.0,
1577	0.0331941, 0.9668058, 0.0,
1578	0.0170827, 0.0723974, 0.9105199,
1579);
1580
1581const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set(
1582	1.2249401, - 0.2249404, 0.0,
1583	- 0.0420569, 1.0420571, 0.0,
1584	- 0.0196376, - 0.0786361, 1.0982735
1585);
1586
1587/**
1588 * Defines supported color spaces by transfer function and primaries,
1589 * and provides conversions to/from the Linear-sRGB reference space.
1590 */
1591const COLOR_SPACES = {
1592	[ LinearSRGBColorSpace ]: {
1593		transfer: LinearTransfer,
1594		primaries: Rec709Primaries,
1595		toReference: ( color ) => color,
1596		fromReference: ( color ) => color,
1597	},
1598	[ SRGBColorSpace ]: {
1599		transfer: SRGBTransfer,
1600		primaries: Rec709Primaries,
1601		toReference: ( color ) => color.convertSRGBToLinear(),
1602		fromReference: ( color ) => color.convertLinearToSRGB(),
1603	},
1604	[ LinearDisplayP3ColorSpace ]: {
1605		transfer: LinearTransfer,
1606		primaries: P3Primaries,
1607		toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
1608		fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ),
1609	},
1610	[ DisplayP3ColorSpace ]: {
1611		transfer: SRGBTransfer,
1612		primaries: P3Primaries,
1613		toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
1614		fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(),
1615	},
1616};
1617
1618const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] );
1619
1620const ColorManagement = {
1621
1622	enabled: true,
1623
1624	_workingColorSpace: LinearSRGBColorSpace,
1625
1626	get workingColorSpace() {
1627
1628		return this._workingColorSpace;
1629
1630	},
1631
1632	set workingColorSpace( colorSpace ) {
1633
1634		if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) {
1635
1636			throw new Error( `Unsupported working color space, "${ colorSpace }".` );
1637
1638		}
1639
1640		this._workingColorSpace = colorSpace;
1641
1642	},
1643
1644	convert: function ( color, sourceColorSpace, targetColorSpace ) {
1645
1646		if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) {
1647
1648			return color;
1649
1650		}
1651
1652		const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference;
1653		const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference;
1654
1655		return targetFromReference( sourceToReference( color ) );
1656
1657	},
1658
1659	fromWorkingColorSpace: function ( color, targetColorSpace ) {
1660
1661		return this.convert( color, this._workingColorSpace, targetColorSpace );
1662
1663	},
1664
1665	toWorkingColorSpace: function ( color, sourceColorSpace ) {
1666
1667		return this.convert( color, sourceColorSpace, this._workingColorSpace );
1668
1669	},
1670
1671	getPrimaries: function ( colorSpace ) {
1672
1673		return COLOR_SPACES[ colorSpace ].primaries;
1674
1675	},
1676
1677	getTransfer: function ( colorSpace ) {
1678
1679		if ( colorSpace === NoColorSpace ) return LinearTransfer;
1680
1681		return COLOR_SPACES[ colorSpace ].transfer;
1682
1683	},
1684
1685};
1686
1687
1688function SRGBToLinear( c ) {
1689
1690	return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
1691
1692}
1693
1694function LinearToSRGB( c ) {
1695
1696	return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
1697
1698}
1699
1700let _canvas;
1701
1702class ImageUtils {
1703
1704	static getDataURL( image ) {
1705
1706		if ( /^data:/i.test( image.src ) ) {
1707
1708			return image.src;
1709
1710		}
1711
1712		if ( typeof HTMLCanvasElement === 'undefined' ) {
1713
1714			return image.src;
1715
1716		}
1717
1718		let canvas;
1719
1720		if ( image instanceof HTMLCanvasElement ) {
1721
1722			canvas = image;
1723
1724		} else {
1725
1726			if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' );
1727
1728			_canvas.width = image.width;
1729			_canvas.height = image.height;
1730
1731			const context = _canvas.getContext( '2d' );
1732
1733			if ( image instanceof ImageData ) {
1734
1735				context.putImageData( image, 0, 0 );
1736
1737			} else {
1738
1739				context.drawImage( image, 0, 0, image.width, image.height );
1740
1741			}
1742
1743			canvas = _canvas;
1744
1745		}
1746
1747		if ( canvas.width > 2048 || canvas.height > 2048 ) {
1748
1749			console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image );
1750
1751			return canvas.toDataURL( 'image/jpeg', 0.6 );
1752
1753		} else {
1754
1755			return canvas.toDataURL( 'image/png' );
1756
1757		}
1758
1759	}
1760
1761	static sRGBToLinear( image ) {
1762
1763		if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
1764			( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
1765			( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
1766
1767			const canvas = createElementNS( 'canvas' );
1768
1769			canvas.width = image.width;
1770			canvas.height = image.height;
1771
1772			const context = canvas.getContext( '2d' );
1773			context.drawImage( image, 0, 0, image.width, image.height );
1774
1775			const imageData = context.getImageData( 0, 0, image.width, image.height );
1776			const data = imageData.data;
1777
1778			for ( let i = 0; i < data.length; i ++ ) {
1779
1780				data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;
1781
1782			}
1783
1784			context.putImageData( imageData, 0, 0 );
1785
1786			return canvas;
1787
1788		} else if ( image.data ) {
1789
1790			const data = image.data.slice( 0 );
1791
1792			for ( let i = 0; i < data.length; i ++ ) {
1793
1794				if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {
1795
1796					data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );
1797
1798				} else {
1799
1800					// assuming float
1801
1802					data[ i ] = SRGBToLinear( data[ i ] );
1803
1804				}
1805
1806			}
1807
1808			return {
1809				data: data,
1810				width: image.width,
1811				height: image.height
1812			};
1813
1814		} else {
1815
1816			console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
1817			return image;
1818
1819		}
1820
1821	}
1822
1823}
1824
1825let _sourceId = 0;
1826
1827class Source {
1828
1829	constructor( data = null ) {
1830
1831		this.isSource = true;
1832
1833		Object.defineProperty( this, 'id', { value: _sourceId ++ } );
1834
1835		this.uuid = generateUUID();
1836
1837		this.data = data;
1838		this.dataReady = true;
1839
1840		this.version = 0;
1841
1842	}
1843
1844	set needsUpdate( value ) {
1845
1846		if ( value === true ) this.version ++;
1847
1848	}
1849
1850	toJSON( meta ) {
1851
1852		const isRootObject = ( meta === undefined || typeof meta === 'string' );
1853
1854		if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) {
1855
1856			return meta.images[ this.uuid ];
1857
1858		}
1859
1860		const output = {
1861			uuid: this.uuid,
1862			url: ''
1863		};
1864
1865		const data = this.data;
1866
1867		if ( data !== null ) {
1868
1869			let url;
1870
1871			if ( Array.isArray( data ) ) {
1872
1873				// cube texture
1874
1875				url = [];
1876
1877				for ( let i = 0, l = data.length; i < l; i ++ ) {
1878
1879					if ( data[ i ].isDataTexture ) {
1880
1881						url.push( serializeImage( data[ i ].image ) );
1882
1883					} else {
1884
1885						url.push( serializeImage( data[ i ] ) );
1886
1887					}
1888
1889				}
1890
1891			} else {
1892
1893				// texture
1894
1895				url = serializeImage( data );
1896
1897			}
1898
1899			output.url = url;
1900
1901		}
1902
1903		if ( ! isRootObject ) {
1904
1905			meta.images[ this.uuid ] = output;
1906
1907		}
1908
1909		return output;
1910
1911	}
1912
1913}
1914
1915function serializeImage( image ) {
1916
1917	if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
1918		( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
1919		( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
1920
1921		// default images
1922
1923		return ImageUtils.getDataURL( image );
1924
1925	} else {
1926
1927		if ( image.data ) {
1928
1929			// images of DataTexture
1930
1931			return {
1932				data: Array.from( image.data ),
1933				width: image.width,
1934				height: image.height,
1935				type: image.data.constructor.name
1936			};
1937
1938		} else {
1939
1940			console.warn( 'THREE.Texture: Unable to serialize Texture.' );
1941			return {};
1942
1943		}
1944
1945	}
1946
1947}
1948
1949let _textureId = 0;
1950
1951class Texture extends EventDispatcher {
1952
1953	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, colorSpace = NoColorSpace ) {
1954
1955		super();
1956
1957		this.isTexture = true;
1958
1959		Object.defineProperty( this, 'id', { value: _textureId ++ } );
1960
1961		this.uuid = generateUUID();
1962
1963		this.name = '';
1964
1965		this.source = new Source( image );
1966		this.mipmaps = [];
1967
1968		this.mapping = mapping;
1969		this.channel = 0;
1970
1971		this.wrapS = wrapS;
1972		this.wrapT = wrapT;
1973
1974		this.magFilter = magFilter;
1975		this.minFilter = minFilter;
1976
1977		this.anisotropy = anisotropy;
1978
1979		this.format = format;
1980		this.internalFormat = null;
1981		this.type = type;
1982
1983		this.offset = new Vector2( 0, 0 );
1984		this.repeat = new Vector2( 1, 1 );
1985		this.center = new Vector2( 0, 0 );
1986		this.rotation = 0;
1987
1988		this.matrixAutoUpdate = true;
1989		this.matrix = new Matrix3();
1990
1991		this.generateMipmaps = true;
1992		this.premultiplyAlpha = false;
1993		this.flipY = true;
1994		this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
1995
1996		this.colorSpace = colorSpace;
1997
1998		this.userData = {};
1999
2000		this.version = 0;
2001		this.onUpdate = null;
2002
2003		this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not
2004		this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures)
2005
2006	}
2007
2008	get image() {
2009
2010		return this.source.data;
2011
2012	}
2013
2014	set image( value = null ) {
2015
2016		this.source.data = value;
2017
2018	}
2019
2020	updateMatrix() {
2021
2022		this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
2023
2024	}
2025
2026	clone() {
2027
2028		return new this.constructor().copy( this );
2029
2030	}
2031
2032	copy( source ) {
2033
2034		this.name = source.name;
2035
2036		this.source = source.source;
2037		this.mipmaps = source.mipmaps.slice( 0 );
2038
2039		this.mapping = source.mapping;
2040		this.channel = source.channel;
2041
2042		this.wrapS = source.wrapS;
2043		this.wrapT = source.wrapT;
2044
2045		this.magFilter = source.magFilter;
2046		this.minFilter = source.minFilter;
2047
2048		this.anisotropy = source.anisotropy;
2049
2050		this.format = source.format;
2051		this.internalFormat = source.internalFormat;
2052		this.type = source.type;
2053
2054		this.offset.copy( source.offset );
2055		this.repeat.copy( source.repeat );
2056		this.center.copy( source.center );
2057		this.rotation = source.rotation;
2058
2059		this.matrixAutoUpdate = source.matrixAutoUpdate;
2060		this.matrix.copy( source.matrix );
2061
2062		this.generateMipmaps = source.generateMipmaps;
2063		this.premultiplyAlpha = source.premultiplyAlpha;
2064		this.flipY = source.flipY;
2065		this.unpackAlignment = source.unpackAlignment;
2066		this.colorSpace = source.colorSpace;
2067
2068		this.userData = JSON.parse( JSON.stringify( source.userData ) );
2069
2070		this.needsUpdate = true;
2071
2072		return this;
2073
2074	}
2075
2076	toJSON( meta ) {
2077
2078		const isRootObject = ( meta === undefined || typeof meta === 'string' );
2079
2080		if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
2081
2082			return meta.textures[ this.uuid ];
2083
2084		}
2085
2086		const output = {
2087
2088			metadata: {
2089				version: 4.6,
2090				type: 'Texture',
2091				generator: 'Texture.toJSON'
2092			},
2093
2094			uuid: this.uuid,
2095			name: this.name,
2096
2097			image: this.source.toJSON( meta ).uuid,
2098
2099			mapping: this.mapping,
2100			channel: this.channel,
2101
2102			repeat: [ this.repeat.x, this.repeat.y ],
2103			offset: [ this.offset.x, this.offset.y ],
2104			center: [ this.center.x, this.center.y ],
2105			rotation: this.rotation,
2106
2107			wrap: [ this.wrapS, this.wrapT ],
2108
2109			format: this.format,
2110			internalFormat: this.internalFormat,
2111			type: this.type,
2112			colorSpace: this.colorSpace,
2113
2114			minFilter: this.minFilter,
2115			magFilter: this.magFilter,
2116			anisotropy: this.anisotropy,
2117
2118			flipY: this.flipY,
2119
2120			generateMipmaps: this.generateMipmaps,
2121			premultiplyAlpha: this.premultiplyAlpha,
2122			unpackAlignment: this.unpackAlignment
2123
2124		};
2125
2126		if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData;
2127
2128		if ( ! isRootObject ) {
2129
2130			meta.textures[ this.uuid ] = output;
2131
2132		}
2133
2134		return output;
2135
2136	}
2137
2138	dispose() {
2139
2140		this.dispatchEvent( { type: 'dispose' } );
2141
2142	}
2143
2144	transformUv( uv ) {
2145
2146		if ( this.mapping !== UVMapping ) return uv;
2147
2148		uv.applyMatrix3( this.matrix );
2149
2150		if ( uv.x < 0 || uv.x > 1 ) {
2151
2152			switch ( this.wrapS ) {
2153
2154				case RepeatWrapping:
2155
2156					uv.x = uv.x - Math.floor( uv.x );
2157					break;
2158
vendor: 995 bytes, lines 2159-2239
2159				case ClampToEdgeWrapping:
2160
2161					uv.x = uv.x < 0 ? 0 : 1;
2162					break;
2163
2164				case MirroredRepeatWrapping:
2165
2166					if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
2167
2168						uv.x = Math.ceil( uv.x ) - uv.x;
2169
2170					} else {
2171
2172						uv.x = uv.x - Math.floor( uv.x );
2173
2174					}
2175
2176					break;
2177
2178			}
2179
2180		}
2181
2182		if ( uv.y < 0 || uv.y > 1 ) {
2183
2184			switch ( this.wrapT ) {
2185
2186				case RepeatWrapping:
2187
2188					uv.y = uv.y - Math.floor( uv.y );
2189					break;
2190
2191				case ClampToEdgeWrapping:
2192
2193					uv.y = uv.y < 0 ? 0 : 1;
2194					break;
2195
2196				case MirroredRepeatWrapping:
2197
2198					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
2199
2200						uv.y = Math.ceil( uv.y ) - uv.y;
2201
2202					} else {
2203
2204						uv.y = uv.y - Math.floor( uv.y );
2205
2206					}
2207
2208					break;
2209
2210			}
2211
2212		}
2213
2214		if ( this.flipY ) {
2215
2216			uv.y = 1 - uv.y;
2217
2218		}
2219
2220		return uv;
2221
2222	}
2223
2224	set needsUpdate( value ) {
2225
2226		if ( value === true ) {
2227
2228			this.version ++;
2229			this.source.needsUpdate = true;
2230
2231		}
2232
2233	}
2234
2235	set needsPMREMUpdate( value ) {
2236
2237		if ( value === true ) {
2238
2239			this.pmremVersion ++
vendor: 13,852 bytes, lines 2239-3076
2239;
2240
2241		}
2242
2243	}
2244
2245}
2246
2247Texture.DEFAULT_IMAGE = null;
2248Texture.DEFAULT_MAPPING = UVMapping;
2249Texture.DEFAULT_ANISOTROPY = 1;
2250
2251class Vector4 {
2252
2253	constructor( x = 0, y = 0, z = 0, w = 1 ) {
2254
2255		Vector4.prototype.isVector4 = true;
2256
2257		this.x = x;
2258		this.y = y;
2259		this.z = z;
2260		this.w = w;
2261
2262	}
2263
2264	get width() {
2265
2266		return this.z;
2267
2268	}
2269
2270	set width( value ) {
2271
2272		this.z = value;
2273
2274	}
2275
2276	get height() {
2277
2278		return this.w;
2279
2280	}
2281
2282	set height( value ) {
2283
2284		this.w = value;
2285
2286	}
2287
2288	set( x, y, z, w ) {
2289
2290		this.x = x;
2291		this.y = y;
2292		this.z = z;
2293		this.w = w;
2294
2295		return this;
2296
2297	}
2298
2299	setScalar( scalar ) {
2300
2301		this.x = scalar;
2302		this.y = scalar;
2303		this.z = scalar;
2304		this.w = scalar;
2305
2306		return this;
2307
2308	}
2309
2310	setX( x ) {
2311
2312		this.x = x;
2313
2314		return this;
2315
2316	}
2317
2318	setY( y ) {
2319
2320		this.y = y;
2321
2322		return this;
2323
2324	}
2325
2326	setZ( z ) {
2327
2328		this.z = z;
2329
2330		return this;
2331
2332	}
2333
2334	setW( w ) {
2335
2336		this.w = w;
2337
2338		return this;
2339
2340	}
2341
2342	setComponent( index, value ) {
2343
2344		switch ( index ) {
2345
2346			case 0: this.x = value; break;
2347			case 1: this.y = value; break;
2348			case 2: this.z = value; break;
2349			case 3: this.w = value; break;
2350			default: throw new Error( 'index is out of range: ' + index );
2351
2352		}
2353
2354		return this;
2355
2356	}
2357
2358	getComponent( index ) {
2359
2360		switch ( index ) {
2361
2362			case 0: return this.x;
2363			case 1: return this.y;
2364			case 2: return this.z;
2365			case 3: return this.w;
2366			default: throw new Error( 'index is out of range: ' + index );
2367
2368		}
2369
2370	}
2371
2372	clone() {
2373
2374		return new this.constructor( this.x, this.y, this.z, this.w );
2375
2376	}
2377
2378	copy( v ) {
2379
2380		this.x = v.x;
2381		this.y = v.y;
2382		this.z = v.z;
2383		this.w = ( v.w !== undefined ) ? v.w : 1;
2384
2385		return this;
2386
2387	}
2388
2389	add( v ) {
2390
2391		this.x += v.x;
2392		this.y += v.y;
2393		this.z += v.z;
2394		this.w += v.w;
2395
2396		return this;
2397
2398	}
2399
2400	addScalar( s ) {
2401
2402		this.x += s;
2403		this.y += s;
2404		this.z += s;
2405		this.w += s;
2406
2407		return this;
2408
2409	}
2410
2411	addVectors( a, b ) {
2412
2413		this.x = a.x + b.x;
2414		this.y = a.y + b.y;
2415		this.z = a.z + b.z;
2416		this.w = a.w + b.w;
2417
2418		return this;
2419
2420	}
2421
2422	addScaledVector( v, s ) {
2423
2424		this.x += v.x * s;
2425		this.y += v.y * s;
2426		this.z += v.z * s;
2427		this.w += v.w * s;
2428
2429		return this;
2430
2431	}
2432
2433	sub( v ) {
2434
2435		this.x -= v.x;
2436		this.y -= v.y;
2437		this.z -= v.z;
2438		this.w -= v.w;
2439
2440		return this;
2441
2442	}
2443
2444	subScalar( s ) {
2445
2446		this.x -= s;
2447		this.y -= s;
2448		this.z -= s;
2449		this.w -= s;
2450
2451		return this;
2452
2453	}
2454
2455	subVectors( a, b ) {
2456
2457		this.x = a.x - b.x;
2458		this.y = a.y - b.y;
2459		this.z = a.z - b.z;
2460		this.w = a.w - b.w;
2461
2462		return this;
2463
2464	}
2465
2466	multiply( v ) {
2467
2468		this.x *= v.x;
2469		this.y *= v.y;
2470		this.z *= v.z;
2471		this.w *= v.w;
2472
2473		return this;
2474
2475	}
2476
2477	multiplyScalar( scalar ) {
2478
2479		this.x *= scalar;
2480		this.y *= scalar;
2481		this.z *= scalar;
2482		this.w *= scalar;
2483
2484		return this;
2485
2486	}
2487
2488	applyMatrix4( m ) {
2489
2490		const x = this.x, y = this.y, z = this.z, w = this.w;
2491		const e = m.elements;
2492
2493		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
2494		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
2495		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
2496		this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
2497
2498		return this;
2499
2500	}
2501
2502	divideScalar( scalar ) {
2503
2504		return this.multiplyScalar( 1 / scalar );
2505
2506	}
2507
2508	setAxisAngleFromQuaternion( q ) {
2509
2510		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
2511
2512		// q is assumed to be normalized
2513
2514		this.w = 2 * Math.acos( q.w );
2515
2516		const s = Math.sqrt( 1 - q.w * q.w );
2517
2518		if ( s < 0.0001 ) {
2519
2520			this.x = 1;
2521			this.y = 0;
2522			this.z = 0;
2523
2524		} else {
2525
2526			this.x = q.x / s;
2527			this.y = q.y / s;
2528			this.z = q.z / s;
2529
2530		}
2531
2532		return this;
2533
2534	}
2535
2536	setAxisAngleFromRotationMatrix( m ) {
2537
2538		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2539
2540		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2541
2542		let angle, x, y, z; // variables for result
2543		const epsilon = 0.01,		// margin to allow for rounding errors
2544			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
2545
2546			te = m.elements,
2547
2548			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2549			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2550			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
2551
2552		if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
2553		     ( Math.abs( m13 - m31 ) < epsilon ) &&
2554		     ( Math.abs( m23 - m32 ) < epsilon ) ) {
2555
2556			// singularity found
2557			// first check for identity matrix which must have +1 for all terms
2558			// in leading diagonal and zero in other terms
2559
2560			if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
2561			     ( Math.abs( m13 + m31 ) < epsilon2 ) &&
2562			     ( Math.abs( m23 + m32 ) < epsilon2 ) &&
2563			     ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
2564
2565				// this singularity is identity matrix so angle = 0
2566
2567				this.set( 1, 0, 0, 0 );
2568
2569				return this; // zero angle, arbitrary axis
2570
2571			}
2572
2573			// otherwise this singularity is angle = 180
2574
2575			angle = Math.PI;
2576
2577			const xx = ( m11 + 1 ) / 2;
2578			const yy = ( m22 + 1 ) / 2;
2579			const zz = ( m33 + 1 ) / 2;
2580			const xy = ( m12 + m21 ) / 4;
2581			const xz = ( m13 + m31 ) / 4;
2582			const yz = ( m23 + m32 ) / 4;
2583
2584			if ( ( xx > yy ) && ( xx > zz ) ) {
2585
2586				// m11 is the largest diagonal term
2587
2588				if ( xx < epsilon ) {
2589
2590					x = 0;
2591					y = 0.707106781;
2592					z = 0.707106781;
2593
2594				} else {
2595
2596					x = Math.sqrt( xx );
2597					y = xy / x;
2598					z = xz / x;
2599
2600				}
2601
2602			} else if ( yy > zz ) {
2603
2604				// m22 is the largest diagonal term
2605
2606				if ( yy < epsilon ) {
2607
2608					x = 0.707106781;
2609					y = 0;
2610					z = 0.707106781;
2611
2612				} else {
2613
2614					y = Math.sqrt( yy );
2615					x = xy / y;
2616					z = yz / y;
2617
2618				}
2619
2620			} else {
2621
2622				// m33 is the largest diagonal term so base result on this
2623
2624				if ( zz < epsilon ) {
2625
2626					x = 0.707106781;
2627					y = 0.707106781;
2628					z = 0;
2629
2630				} else {
2631
2632					z = Math.sqrt( zz );
2633					x = xz / z;
2634					y = yz / z;
2635
2636				}
2637
2638			}
2639
2640			this.set( x, y, z, angle );
2641
2642			return this; // return 180 deg rotation
2643
2644		}
2645
2646		// as we have reached here there are no singularities so we can handle normally
2647
2648		let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
2649			( m13 - m31 ) * ( m13 - m31 ) +
2650			( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
2651
2652		if ( Math.abs( s ) < 0.001 ) s = 1;
2653
2654		// prevent divide by zero, should not happen if matrix is orthogonal and should be
2655		// caught by singularity test above, but I've left it in just in case
2656
2657		this.x = ( m32 - m23 ) / s;
2658		this.y = ( m13 - m31 ) / s;
2659		this.z = ( m21 - m12 ) / s;
2660		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
2661
2662		return this;
2663
2664	}
2665
2666	min( v ) {
2667
2668		this.x = Math.min( this.x, v.x );
2669		this.y = Math.min( this.y, v.y );
2670		this.z = Math.min( this.z, v.z );
2671		this.w = Math.min( this.w, v.w );
2672
2673		return this;
2674
2675	}
2676
2677	max( v ) {
2678
2679		this.x = Math.max( this.x, v.x );
2680		this.y = Math.max( this.y, v.y );
2681		this.z = Math.max( this.z, v.z );
2682		this.w = Math.max( this.w, v.w );
2683
2684		return this;
2685
2686	}
2687
2688	clamp( min, max ) {
2689
2690		// assumes min < max, componentwise
2691
2692		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2693		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2694		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2695		this.w = Math.max( min.w, Math.min( max.w, this.w ) );
2696
2697		return this;
2698
2699	}
2700
2701	clampScalar( minVal, maxVal ) {
2702
2703		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
2704		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
2705		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
2706		this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
2707
2708		return this;
2709
2710	}
2711
2712	clampLength( min, max ) {
2713
2714		const length = this.length();
2715
2716		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2717
2718	}
2719
2720	floor() {
2721
2722		this.x = Math.floor( this.x );
2723		this.y = Math.floor( this.y );
2724		this.z = Math.floor( this.z );
2725		this.w = Math.floor( this.w );
2726
2727		return this;
2728
2729	}
2730
2731	ceil() {
2732
2733		this.x = Math.ceil( this.x );
2734		this.y = Math.ceil( this.y );
2735		this.z = Math.ceil( this.z );
2736		this.w = Math.ceil( this.w );
2737
2738		return this;
2739
2740	}
2741
2742	round() {
2743
2744		this.x = Math.round( this.x );
2745		this.y = Math.round( this.y );
2746		this.z = Math.round( this.z );
2747		this.w = Math.round( this.w );
2748
2749		return this;
2750
2751	}
2752
2753	roundToZero() {
2754
2755		this.x = Math.trunc( this.x );
2756		this.y = Math.trunc( this.y );
2757		this.z = Math.trunc( this.z );
2758		this.w = Math.trunc( this.w );
2759
2760		return this;
2761
2762	}
2763
2764	negate() {
2765
2766		this.x = - this.x;
2767		this.y = - this.y;
2768		this.z = - this.z;
2769		this.w = - this.w;
2770
2771		return this;
2772
2773	}
2774
2775	dot( v ) {
2776
2777		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
2778
2779	}
2780
2781	lengthSq() {
2782
2783		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
2784
2785	}
2786
2787	length() {
2788
2789		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
2790
2791	}
2792
2793	manhattanLength() {
2794
2795		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
2796
2797	}
2798
2799	normalize() {
2800
2801		return this.divideScalar( this.length() || 1 );
2802
2803	}
2804
2805	setLength( length ) {
2806
2807		return this.normalize().multiplyScalar( length );
2808
2809	}
2810
2811	lerp( v, alpha ) {
2812
2813		this.x += ( v.x - this.x ) * alpha;
2814		this.y += ( v.y - this.y ) * alpha;
2815		this.z += ( v.z - this.z ) * alpha;
2816		this.w += ( v.w - this.w ) * alpha;
2817
2818		return this;
2819
2820	}
2821
2822	lerpVectors( v1, v2, alpha ) {
2823
2824		this.x = v1.x + ( v2.x - v1.x ) * alpha;
2825		this.y = v1.y + ( v2.y - v1.y ) * alpha;
2826		this.z = v1.z + ( v2.z - v1.z ) * alpha;
2827		this.w = v1.w + ( v2.w - v1.w ) * alpha;
2828
2829		return this;
2830
2831	}
2832
2833	equals( v ) {
2834
2835		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
2836
2837	}
2838
2839	fromArray( array, offset = 0 ) {
2840
2841		this.x = array[ offset ];
2842		this.y = array[ offset + 1 ];
2843		this.z = array[ offset + 2 ];
2844		this.w = array[ offset + 3 ];
2845
2846		return this;
2847
2848	}
2849
2850	toArray( array = [], offset = 0 ) {
2851
2852		array[ offset ] = this.x;
2853		array[ offset + 1 ] = this.y;
2854		array[ offset + 2 ] = this.z;
2855		array[ offset + 3 ] = this.w;
2856
2857		return array;
2858
2859	}
2860
2861	fromBufferAttribute( attribute, index ) {
2862
2863		this.x = attribute.getX( index );
2864		this.y = attribute.getY( index );
2865		this.z = attribute.getZ( index );
2866		this.w = attribute.getW( index );
2867
2868		return this;
2869
2870	}
2871
2872	random() {
2873
2874		this.x = Math.random();
2875		this.y = Math.random();
2876		this.z = Math.random();
2877		this.w = Math.random();
2878
2879		return this;
2880
2881	}
2882
2883	*[ Symbol.iterator ]() {
2884
2885		yield this.x;
2886		yield this.y;
2887		yield this.z;
2888		yield this.w;
2889
2890	}
2891
2892}
2893
2894/*
2895 In options, we can specify:
2896 * Texture parameters for an auto-generated target texture
2897 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
2898*/
2899class RenderTarget extends EventDispatcher {
2900
2901	constructor( width = 1, height = 1, options = {} ) {
2902
2903		super();
2904
2905		this.isRenderTarget = true;
2906
2907		this.width = width;
2908		this.height = height;
2909		this.depth = 1;
2910
2911		this.scissor = new Vector4( 0, 0, width, height );
2912		this.scissorTest = false;
2913
2914		this.viewport = new Vector4( 0, 0, width, height );
2915
2916		const image = { width: width, height: height, depth: 1 };
2917
2918		options = Object.assign( {
2919			generateMipmaps: false,
2920			internalFormat: null,
2921			minFilter: LinearFilter,
2922			depthBuffer: true,
2923			stencilBuffer: false,
2924			depthTexture: null,
2925			samples: 0,
2926			count: 1
2927		}, options );
2928
2929		const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
2930
2931		texture.flipY = false;
2932		texture.generateMipmaps = options.generateMipmaps;
2933		texture.internalFormat = options.internalFormat;
2934
2935		this.textures = [];
2936
2937		const count = options.count;
2938		for ( let i = 0; i < count; i ++ ) {
2939
2940			this.textures[ i ] = texture.clone();
2941			this.textures[ i ].isRenderTargetTexture = true;
2942
2943		}
2944
2945		this.depthBuffer = options.depthBuffer;
2946		this.stencilBuffer = options.stencilBuffer;
2947
2948		this.depthTexture = options.depthTexture;
2949
2950		this.samples = options.samples;
2951
2952	}
2953
2954	get texture() {
2955
2956		return this.textures[ 0 ];
2957
2958	}
2959
2960	set texture( value ) {
2961
2962		this.textures[ 0 ] = value;
2963
2964	}
2965
2966	setSize( width, height, depth = 1 ) {
2967
2968		if ( this.width !== width || this.height !== height || this.depth !== depth ) {
2969
2970			this.width = width;
2971			this.height = height;
2972			this.depth = depth;
2973
2974			for ( let i = 0, il = this.textures.length; i < il; i ++ ) {
2975
2976				this.textures[ i ].image.width = width;
2977				this.textures[ i ].image.height = height;
2978				this.textures[ i ].image.depth = depth;
2979
2980			}
2981
2982			this.dispose();
2983
2984		}
2985
2986		this.viewport.set( 0, 0, width, height );
2987		this.scissor.set( 0, 0, width, height );
2988
2989	}
2990
2991	clone() {
2992
2993		return new this.constructor().copy( this );
2994
2995	}
2996
2997	copy( source ) {
2998
2999		this.width = source.width;
3000		this.height = source.height;
3001		this.depth = source.depth;
3002
3003		this.scissor.copy( source.scissor );
3004		this.scissorTest = source.scissorTest;
3005
3006		this.viewport.copy( source.viewport );
3007
3008		this.textures.length = 0;
3009
3010		for ( let i = 0, il = source.textures.length; i < il; i ++ ) {
3011
3012			this.textures[ i ] = source.textures[ i ].clone();
3013			this.textures[ i ].isRenderTargetTexture = true;
3014
3015		}
3016
3017		// ensure image object is not shared, see #20328
3018
3019		const image = Object.assign( {}, source.texture.image );
3020		this.texture.source = new Source( image );
3021
3022		this.depthBuffer = source.depthBuffer;
3023		this.stencilBuffer = source.stencilBuffer;
3024
3025		if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
3026
3027		this.samples = source.samples;
3028
3029		return this;
3030
3031	}
3032
3033	dispose() {
3034
3035		this.dispatchEvent( { type: 'dispose' } );
3036
3037	}
3038
3039}
3040
3041class WebGLRenderTarget extends RenderTarget {
3042
3043	constructor( width = 1, height = 1, options = {} ) {
3044
3045		super( width, height, options );
3046
3047		this.isWebGLRenderTarget = true;
3048
3049	}
3050
3051}
3052
3053class DataArrayTexture extends Texture {
3054
3055	constructor( data = null, width = 1, height = 1, depth = 1 ) {
3056
3057		super( null );
3058
3059		this.isDataArrayTexture = true;
3060
3061		this.image = { data, width, height, depth };
3062
3063		this.magFilter = NearestFilter;
3064		this.minFilter = NearestFilter;
3065
3066		this.wrapR = ClampToEdgeWrapping;
3067
3068		this.generateMipmaps = false;
3069		this.flipY = false;
3070		this.unpackAlignment = 1;
3071
3072	}
3073
3074}
3075
3076class 
vendor: 21,754 bytes, lines 3076-4355
3076WebGLArrayRenderTarget extends WebGLRenderTarget {
3077
3078	constructor( width = 1, height = 1, depth = 1, options = {} ) {
3079
3080		super( width, height, options );
3081
3082		this.isWebGLArrayRenderTarget = true;
3083
3084		this.depth = depth;
3085
3086		this.texture = new DataArrayTexture( null, width, height, depth );
3087
3088		this.texture.isRenderTargetTexture = true;
3089
3090	}
3091
3092}
3093
3094class Data3DTexture extends Texture {
3095
3096	constructor( data = null, width = 1, height = 1, depth = 1 ) {
3097
3098		// We're going to add .setXXX() methods for setting properties later.
3099		// Users can still set in DataTexture3D directly.
3100		//
3101		//	const texture = new THREE.DataTexture3D( data, width, height, depth );
3102		// 	texture.anisotropy = 16;
3103		//
3104		// See #14839
3105
3106		super( null );
3107
3108		this.isData3DTexture = true;
3109
3110		this.image = { data, width, height, depth };
3111
3112		this.magFilter = NearestFilter;
3113		this.minFilter = NearestFilter;
3114
3115		this.wrapR = ClampToEdgeWrapping;
3116
3117		this.generateMipmaps = false;
3118		this.flipY = false;
3119		this.unpackAlignment = 1;
3120
3121	}
3122
3123}
3124
3125class WebGL3DRenderTarget extends WebGLRenderTarget {
3126
3127	constructor( width = 1, height = 1, depth = 1, options = {} ) {
3128
3129		super( width, height, options );
3130
3131		this.isWebGL3DRenderTarget = true;
3132
3133		this.depth = depth;
3134
3135		this.texture = new Data3DTexture( null, width, height, depth );
3136
3137		this.texture.isRenderTargetTexture = true;
3138
3139	}
3140
3141}
3142
3143class Quaternion {
3144
3145	constructor( x = 0, y = 0, z = 0, w = 1 ) {
3146
3147		this.isQuaternion = true;
3148
3149		this._x = x;
3150		this._y = y;
3151		this._z = z;
3152		this._w = w;
3153
3154	}
3155
3156	static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
3157
3158		// fuzz-free, array-based Quaternion SLERP operation
3159
3160		let x0 = src0[ srcOffset0 + 0 ],
3161			y0 = src0[ srcOffset0 + 1 ],
3162			z0 = src0[ srcOffset0 + 2 ],
3163			w0 = src0[ srcOffset0 + 3 ];
3164
3165		const x1 = src1[ srcOffset1 + 0 ],
3166			y1 = src1[ srcOffset1 + 1 ],
3167			z1 = src1[ srcOffset1 + 2 ],
3168			w1 = src1[ srcOffset1 + 3 ];
3169
3170		if ( t === 0 ) {
3171
3172			dst[ dstOffset + 0 ] = x0;
3173			dst[ dstOffset + 1 ] = y0;
3174			dst[ dstOffset + 2 ] = z0;
3175			dst[ dstOffset + 3 ] = w0;
3176			return;
3177
3178		}
3179
3180		if ( t === 1 ) {
3181
3182			dst[ dstOffset + 0 ] = x1;
3183			dst[ dstOffset + 1 ] = y1;
3184			dst[ dstOffset + 2 ] = z1;
3185			dst[ dstOffset + 3 ] = w1;
3186			return;
3187
3188		}
3189
3190		if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
3191
3192			let s = 1 - t;
3193			const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
3194				dir = ( cos >= 0 ? 1 : - 1 ),
3195				sqrSin = 1 - cos * cos;
3196
3197			// Skip the Slerp for tiny steps to avoid numeric problems:
3198			if ( sqrSin > Number.EPSILON ) {
3199
3200				const sin = Math.sqrt( sqrSin ),
3201					len = Math.atan2( sin, cos * dir );
3202
3203				s = Math.sin( s * len ) / sin;
3204				t = Math.sin( t * len ) / sin;
3205
3206			}
3207
3208			const tDir = t * dir;
3209
3210			x0 = x0 * s + x1 * tDir;
3211			y0 = y0 * s + y1 * tDir;
3212			z0 = z0 * s + z1 * tDir;
3213			w0 = w0 * s + w1 * tDir;
3214
3215			// Normalize in case we just did a lerp:
3216			if ( s === 1 - t ) {
3217
3218				const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
3219
3220				x0 *= f;
3221				y0 *= f;
3222				z0 *= f;
3223				w0 *= f;
3224
3225			}
3226
3227		}
3228
3229		dst[ dstOffset ] = x0;
3230		dst[ dstOffset + 1 ] = y0;
3231		dst[ dstOffset + 2 ] = z0;
3232		dst[ dstOffset + 3 ] = w0;
3233
3234	}
3235
3236	static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
3237
3238		const x0 = src0[ srcOffset0 ];
3239		const y0 = src0[ srcOffset0 + 1 ];
3240		const z0 = src0[ srcOffset0 + 2 ];
3241		const w0 = src0[ srcOffset0 + 3 ];
3242
3243		const x1 = src1[ srcOffset1 ];
3244		const y1 = src1[ srcOffset1 + 1 ];
3245		const z1 = src1[ srcOffset1 + 2 ];
3246		const w1 = src1[ srcOffset1 + 3 ];
3247
3248		dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
3249		dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
3250		dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
3251		dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
3252
3253		return dst;
3254
3255	}
3256
3257	get x() {
3258
3259		return this._x;
3260
3261	}
3262
3263	set x( value ) {
3264
3265		this._x = value;
3266		this._onChangeCallback();
3267
3268	}
3269
3270	get y() {
3271
3272		return this._y;
3273
3274	}
3275
3276	set y( value ) {
3277
3278		this._y = value;
3279		this._onChangeCallback();
3280
3281	}
3282
3283	get z() {
3284
3285		return this._z;
3286
3287	}
3288
3289	set z( value ) {
3290
3291		this._z = value;
3292		this._onChangeCallback();
3293
3294	}
3295
3296	get w() {
3297
3298		return this._w;
3299
3300	}
3301
3302	set w( value ) {
3303
3304		this._w = value;
3305		this._onChangeCallback();
3306
3307	}
3308
3309	set( x, y, z, w ) {
3310
3311		this._x = x;
3312		this._y = y;
3313		this._z = z;
3314		this._w = w;
3315
3316		this._onChangeCallback();
3317
3318		return this;
3319
3320	}
3321
3322	clone() {
3323
3324		return new this.constructor( this._x, this._y, this._z, this._w );
3325
3326	}
3327
3328	copy( quaternion ) {
3329
3330		this._x = quaternion.x;
3331		this._y = quaternion.y;
3332		this._z = quaternion.z;
3333		this._w = quaternion.w;
3334
3335		this._onChangeCallback();
3336
3337		return this;
3338
3339	}
3340
3341	setFromEuler( euler, update = true ) {
3342
3343		const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
3344
3345		// http://www.mathworks.com/matlabcentral/fileexchange/
3346		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
3347		//	content/SpinCalc.m
3348
3349		const cos = Math.cos;
3350		const sin = Math.sin;
3351
3352		const c1 = cos( x / 2 );
3353		const c2 = cos( y / 2 );
3354		const c3 = cos( z / 2 );
3355
3356		const s1 = sin( x / 2 );
3357		const s2 = sin( y / 2 );
3358		const s3 = sin( z / 2 );
3359
3360		switch ( order ) {
3361
3362			case 'XYZ':
3363				this._x = s1 * c2 * c3 + c1 * s2 * s3;
3364				this._y = c1 * s2 * c3 - s1 * c2 * s3;
3365				this._z = c1 * c2 * s3 + s1 * s2 * c3;
3366				this._w = c1 * c2 * c3 - s1 * s2 * s3;
3367				break;
3368
3369			case 'YXZ':
3370				this._x = s1 * c2 * c3 + c1 * s2 * s3;
3371				this._y = c1 * s2 * c3 - s1 * c2 * s3;
3372				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3373				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3374				break;
3375
3376			case 'ZXY':
3377				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3378				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3379				this._z = c1 * c2 * s3 + s1 * s2 * c3;
3380				this._w = c1 * c2 * c3 - s1 * s2 * s3;
3381				break;
3382
3383			case 'ZYX':
3384				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3385				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3386				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3387				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3388				break;
3389
3390			case 'YZX':
3391				this._x = s1 * c2 * c3 + c1 * s2 * s3;
3392				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3393				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3394				this._w = c1 * c2 * c3 - s1 * s2 * s3;
3395				break;
3396
3397			case 'XZY':
3398				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3399				this._y = c1 * s2 * c3 - s1 * c2 * s3;
3400				this._z = c1 * c2 * s3 + s1 * s2 * c3;
3401				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3402				break;
3403
3404			default:
3405				console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
3406
3407		}
3408
3409		if ( update === true ) this._onChangeCallback();
3410
3411		return this;
3412
3413	}
3414
3415	setFromAxisAngle( axis, angle ) {
3416
3417		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
3418
3419		// assumes axis is normalized
3420
3421		const halfAngle = angle / 2, s = Math.sin( halfAngle );
3422
3423		this._x = axis.x * s;
3424		this._y = axis.y * s;
3425		this._z = axis.z * s;
3426		this._w = Math.cos( halfAngle );
3427
3428		this._onChangeCallback();
3429
3430		return this;
3431
3432	}
3433
3434	setFromRotationMatrix( m ) {
3435
3436		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
3437
3438		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
3439
3440		const te = m.elements,
3441
3442			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
3443			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
3444			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
3445
3446			trace = m11 + m22 + m33;
3447
3448		if ( trace > 0 ) {
3449
3450			const s = 0.5 / Math.sqrt( trace + 1.0 );
3451
3452			this._w = 0.25 / s;
3453			this._x = ( m32 - m23 ) * s;
3454			this._y = ( m13 - m31 ) * s;
3455			this._z = ( m21 - m12 ) * s;
3456
3457		} else if ( m11 > m22 && m11 > m33 ) {
3458
3459			const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
3460
3461			this._w = ( m32 - m23 ) / s;
3462			this._x = 0.25 * s;
3463			this._y = ( m12 + m21 ) / s;
3464			this._z = ( m13 + m31 ) / s;
3465
3466		} else if ( m22 > m33 ) {
3467
3468			const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
3469
3470			this._w = ( m13 - m31 ) / s;
3471			this._x = ( m12 + m21 ) / s;
3472			this._y = 0.25 * s;
3473			this._z = ( m23 + m32 ) / s;
3474
3475		} else {
3476
3477			const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
3478
3479			this._w = ( m21 - m12 ) / s;
3480			this._x = ( m13 + m31 ) / s;
3481			this._y = ( m23 + m32 ) / s;
3482			this._z = 0.25 * s;
3483
3484		}
3485
3486		this._onChangeCallback();
3487
3488		return this;
3489
3490	}
3491
3492	setFromUnitVectors( vFrom, vTo ) {
3493
3494		// assumes direction vectors vFrom and vTo are normalized
3495
3496		let r = vFrom.dot( vTo ) + 1;
3497
3498		if ( r < Number.EPSILON ) {
3499
3500			// vFrom and vTo point in opposite directions
3501
3502			r = 0;
3503
3504			if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
3505
3506				this._x = - vFrom.y;
3507				this._y = vFrom.x;
3508				this._z = 0;
3509				this._w = r;
3510
3511			} else {
3512
3513				this._x = 0;
3514				this._y = - vFrom.z;
3515				this._z = vFrom.y;
3516				this._w = r;
3517
3518			}
3519
3520		} else {
3521
3522			// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
3523
3524			this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
3525			this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
3526			this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
3527			this._w = r;
3528
3529		}
3530
3531		return this.normalize();
3532
3533	}
3534
3535	angleTo( q ) {
3536
3537		return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) );
3538
3539	}
3540
3541	rotateTowards( q, step ) {
3542
3543		const angle = this.angleTo( q );
3544
3545		if ( angle === 0 ) return this;
3546
3547		const t = Math.min( 1, step / angle );
3548
3549		this.slerp( q, t );
3550
3551		return this;
3552
3553	}
3554
3555	identity() {
3556
3557		return this.set( 0, 0, 0, 1 );
3558
3559	}
3560
3561	invert() {
3562
3563		// quaternion is assumed to have unit length
3564
3565		return this.conjugate();
3566
3567	}
3568
3569	conjugate() {
3570
3571		this._x *= - 1;
3572		this._y *= - 1;
3573		this._z *= - 1;
3574
3575		this._onChangeCallback();
3576
3577		return this;
3578
3579	}
3580
3581	dot( v ) {
3582
3583		return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
3584
3585	}
3586
3587	lengthSq() {
3588
3589		return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
3590
3591	}
3592
3593	length() {
3594
3595		return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
3596
3597	}
3598
3599	normalize() {
3600
3601		let l = this.length();
3602
3603		if ( l === 0 ) {
3604
3605			this._x = 0;
3606			this._y = 0;
3607			this._z = 0;
3608			this._w = 1;
3609
3610		} else {
3611
3612			l = 1 / l;
3613
3614			this._x = this._x * l;
3615			this._y = this._y * l;
3616			this._z = this._z * l;
3617			this._w = this._w * l;
3618
3619		}
3620
3621		this._onChangeCallback();
3622
3623		return this;
3624
3625	}
3626
3627	multiply( q ) {
3628
3629		return this.multiplyQuaternions( this, q );
3630
3631	}
3632
3633	premultiply( q ) {
3634
3635		return this.multiplyQuaternions( q, this );
3636
3637	}
3638
3639	multiplyQuaternions( a, b ) {
3640
3641		// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
3642
3643		const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
3644		const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
3645
3646		this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
3647		this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
3648		this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
3649		this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
3650
3651		this._onChangeCallback();
3652
3653		return this;
3654
3655	}
3656
3657	slerp( qb, t ) {
3658
3659		if ( t === 0 ) return this;
3660		if ( t === 1 ) return this.copy( qb );
3661
3662		const x = this._x, y = this._y, z = this._z, w = this._w;
3663
3664		// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
3665
3666		let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
3667
3668		if ( cosHalfTheta < 0 ) {
3669
3670			this._w = - qb._w;
3671			this._x = - qb._x;
3672			this._y = - qb._y;
3673			this._z = - qb._z;
3674
3675			cosHalfTheta = - cosHalfTheta;
3676
3677		} else {
3678
3679			this.copy( qb );
3680
3681		}
3682
3683		if ( cosHalfTheta >= 1.0 ) {
3684
3685			this._w = w;
3686			this._x = x;
3687			this._y = y;
3688			this._z = z;
3689
3690			return this;
3691
3692		}
3693
3694		const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
3695
3696		if ( sqrSinHalfTheta <= Number.EPSILON ) {
3697
3698			const s = 1 - t;
3699			this._w = s * w + t * this._w;
3700			this._x = s * x + t * this._x;
3701			this._y = s * y + t * this._y;
3702			this._z = s * z + t * this._z;
3703
3704			this.normalize(); // normalize calls _onChangeCallback()
3705
3706			return this;
3707
3708		}
3709
3710		const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
3711		const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
3712		const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
3713			ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
3714
3715		this._w = ( w * ratioA + this._w * ratioB );
3716		this._x = ( x * ratioA + this._x * ratioB );
3717		this._y = ( y * ratioA + this._y * ratioB );
3718		this._z = ( z * ratioA + this._z * ratioB );
3719
3720		this._onChangeCallback();
3721
3722		return this;
3723
3724	}
3725
3726	slerpQuaternions( qa, qb, t ) {
3727
3728		return this.copy( qa ).slerp( qb, t );
3729
3730	}
3731
3732	random() {
3733
3734		// sets this quaternion to a uniform random unit quaternnion
3735
3736		// Ken Shoemake
3737		// Uniform random rotations
3738		// D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992.
3739
3740		const theta1 = 2 * Math.PI * Math.random();
3741		const theta2 = 2 * Math.PI * Math.random();
3742
3743		const x0 = Math.random();
3744		const r1 = Math.sqrt( 1 - x0 );
3745		const r2 = Math.sqrt( x0 );
3746
3747		return this.set(
3748			r1 * Math.sin( theta1 ),
3749			r1 * Math.cos( theta1 ),
3750			r2 * Math.sin( theta2 ),
3751			r2 * Math.cos( theta2 ),
3752		);
3753
3754	}
3755
3756	equals( quaternion ) {
3757
3758		return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
3759
3760	}
3761
3762	fromArray( array, offset = 0 ) {
3763
3764		this._x = array[ offset ];
3765		this._y = array[ offset + 1 ];
3766		this._z = array[ offset + 2 ];
3767		this._w = array[ offset + 3 ];
3768
3769		this._onChangeCallback();
3770
3771		return this;
3772
3773	}
3774
3775	toArray( array = [], offset = 0 ) {
3776
3777		array[ offset ] = this._x;
3778		array[ offset + 1 ] = this._y;
3779		array[ offset + 2 ] = this._z;
3780		array[ offset + 3 ] = this._w;
3781
3782		return array;
3783
3784	}
3785
3786	fromBufferAttribute( attribute, index ) {
3787
3788		this._x = attribute.getX( index );
3789		this._y = attribute.getY( index );
3790		this._z = attribute.getZ( index );
3791		this._w = attribute.getW( index );
3792
3793		this._onChangeCallback();
3794
3795		return this;
3796
3797	}
3798
3799	toJSON() {
3800
3801		return this.toArray();
3802
3803	}
3804
3805	_onChange( callback ) {
3806
3807		this._onChangeCallback = callback;
3808
3809		return this;
3810
3811	}
3812
3813	_onChangeCallback() {}
3814
3815	*[ Symbol.iterator ]() {
3816
3817		yield this._x;
3818		yield this._y;
3819		yield this._z;
3820		yield this._w;
3821
3822	}
3823
3824}
3825
3826class Vector3 {
3827
3828	constructor( x = 0, y = 0, z = 0 ) {
3829
3830		Vector3.prototype.isVector3 = true;
3831
3832		this.x = x;
3833		this.y = y;
3834		this.z = z;
3835
3836	}
3837
3838	set( x, y, z ) {
3839
3840		if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
3841
3842		this.x = x;
3843		this.y = y;
3844		this.z = z;
3845
3846		return this;
3847
3848	}
3849
3850	setScalar( scalar ) {
3851
3852		this.x = scalar;
3853		this.y = scalar;
3854		this.z = scalar;
3855
3856		return this;
3857
3858	}
3859
3860	setX( x ) {
3861
3862		this.x = x;
3863
3864		return this;
3865
3866	}
3867
3868	setY( y ) {
3869
3870		this.y = y;
3871
3872		return this;
3873
3874	}
3875
3876	setZ( z ) {
3877
3878		this.z = z;
3879
3880		return this;
3881
3882	}
3883
3884	setComponent( index, value ) {
3885
3886		switch ( index ) {
3887
3888			case 0: this.x = value; break;
3889			case 1: this.y = value; break;
3890			case 2: this.z = value; break;
3891			default: throw new Error( 'index is out of range: ' + index );
3892
3893		}
3894
3895		return this;
3896
3897	}
3898
3899	getComponent( index ) {
3900
3901		switch ( index ) {
3902
3903			case 0: return this.x;
3904			case 1: return this.y;
3905			case 2: return this.z;
3906			default: throw new Error( 'index is out of range: ' + index );
3907
3908		}
3909
3910	}
3911
3912	clone() {
3913
3914		return new this.constructor( this.x, this.y, this.z );
3915
3916	}
3917
3918	copy( v ) {
3919
3920		this.x = v.x;
3921		this.y = v.y;
3922		this.z = v.z;
3923
3924		return this;
3925
3926	}
3927
3928	add( v ) {
3929
3930		this.x += v.x;
3931		this.y += v.y;
3932		this.z += v.z;
3933
3934		return this;
3935
3936	}
3937
3938	addScalar( s ) {
3939
3940		this.x += s;
3941		this.y += s;
3942		this.z += s;
3943
3944		return this;
3945
3946	}
3947
3948	addVectors( a, b ) {
3949
3950		this.x = a.x + b.x;
3951		this.y = a.y + b.y;
3952		this.z = a.z + b.z;
3953
3954		return this;
3955
3956	}
3957
3958	addScaledVector( v, s ) {
3959
3960		this.x += v.x * s;
3961		this.y += v.y * s;
3962		this.z += v.z * s;
3963
3964		return this;
3965
3966	}
3967
3968	sub( v ) {
3969
3970		this.x -= v.x;
3971		this.y -= v.y;
3972		this.z -= v.z;
3973
3974		return this;
3975
3976	}
3977
3978	subScalar( s ) {
3979
3980		this.x -= s;
3981		this.y -= s;
3982		this.z -= s;
3983
3984		return this;
3985
3986	}
3987
3988	subVectors( a, b ) {
3989
3990		this.x = a.x - b.x;
3991		this.y = a.y - b.y;
3992		this.z = a.z - b.z;
3993
3994		return this;
3995
3996	}
3997
3998	multiply( v ) {
3999
4000		this.x *= v.x;
4001		this.y *= v.y;
4002		this.z *= v.z;
4003
4004		return this;
4005
4006	}
4007
4008	multiplyScalar( scalar ) {
4009
4010		this.x *= scalar;
4011		this.y *= scalar;
4012		this.z *= scalar;
4013
4014		return this;
4015
4016	}
4017
4018	multiplyVectors( a, b ) {
4019
4020		this.x = a.x * b.x;
4021		this.y = a.y * b.y;
4022		this.z = a.z * b.z;
4023
4024		return this;
4025
4026	}
4027
4028	applyEuler( euler ) {
4029
4030		return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) );
4031
4032	}
4033
4034	applyAxisAngle( axis, angle ) {
4035
4036		return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) );
4037
4038	}
4039
4040	applyMatrix3( m ) {
4041
4042		const x = this.x, y = this.y, z = this.z;
4043		const e = m.elements;
4044
4045		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
4046		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
4047		this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
4048
4049		return this;
4050
4051	}
4052
4053	applyNormalMatrix( m ) {
4054
4055		return this.applyMatrix3( m ).normalize();
4056
4057	}
4058
4059	applyMatrix4( m ) {
4060
4061		const x = this.x, y = this.y, z = this.z;
4062		const e = m.elements;
4063
4064		const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
4065
4066		this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
4067		this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
4068		this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
4069
4070		return this;
4071
4072	}
4073
4074	applyQuaternion( q ) {
4075
4076		// quaternion q is assumed to have unit length
4077
4078		const vx = this.x, vy = this.y, vz = this.z;
4079		const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
4080
4081		// t = 2 * cross( q.xyz, v );
4082		const tx = 2 * ( qy * vz - qz * vy );
4083		const ty = 2 * ( qz * vx - qx * vz );
4084		const tz = 2 * ( qx * vy - qy * vx );
4085
4086		// v + q.w * t + cross( q.xyz, t );
4087		this.x = vx + qw * tx + qy * tz - qz * ty;
4088		this.y = vy + qw * ty + qz * tx - qx * tz;
4089		this.z = vz + qw * tz + qx * ty - qy * tx;
4090
4091		return this;
4092
4093	}
4094
4095	project( camera ) {
4096
4097		return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
4098
4099	}
4100
4101	unproject( camera ) {
4102
4103		return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
4104
4105	}
4106
4107	transformDirection( m ) {
4108
4109		// input: THREE.Matrix4 affine matrix
4110		// vector interpreted as a direction
4111
4112		const x = this.x, y = this.y, z = this.z;
4113		const e = m.elements;
4114
4115		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
4116		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
4117		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
4118
4119		return this.normalize();
4120
4121	}
4122
4123	divide( v ) {
4124
4125		this.x /= v.x;
4126		this.y /= v.y;
4127		this.z /= v.z;
4128
4129		return this;
4130
4131	}
4132
4133	divideScalar( scalar ) {
4134
4135		return this.multiplyScalar( 1 / scalar );
4136
4137	}
4138
4139	min( v ) {
4140
4141		this.x = Math.min( this.x, v.x );
4142		this.y = Math.min( this.y, v.y );
4143		this.z = Math.min( this.z, v.z );
4144
4145		return this;
4146
4147	}
4148
4149	max( v ) {
4150
4151		this.x = Math.max( this.x, v.x );
4152		this.y = Math.max( this.y, v.y );
4153		this.z = Math.max( this.z, v.z );
4154
4155		return this;
4156
4157	}
4158
4159	clamp( min, max ) {
4160
4161		// assumes min < max, componentwise
4162
4163		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
4164		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
4165		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
4166
4167		return this;
4168
4169	}
4170
4171	clampScalar( minVal, maxVal ) {
4172
4173		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
4174		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
4175		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
4176
4177		return this;
4178
4179	}
4180
4181	clampLength( min, max ) {
4182
4183		const length = this.length();
4184
4185		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
4186
4187	}
4188
4189	floor() {
4190
4191		this.x = Math.floor( this.x );
4192		this.y = Math.floor( this.y );
4193		this.z = Math.floor( this.z );
4194
4195		return this;
4196
4197	}
4198
4199	ceil() {
4200
4201		this.x = Math.ceil( this.x );
4202		this.y = Math.ceil( this.y );
4203		this.z = Math.ceil( this.z );
4204
4205		return this;
4206
4207	}
4208
4209	round() {
4210
4211		this.x = Math.round( this.x );
4212		this.y = Math.round( this.y );
4213		this.z = Math.round( this.z );
4214
4215		return this;
4216
4217	}
4218
4219	roundToZero() {
4220
4221		this.x = Math.trunc( this.x );
4222		this.y = Math.trunc( this.y );
4223		this.z = Math.trunc( this.z );
4224
4225		return this;
4226
4227	}
4228
4229	negate() {
4230
4231		this.x = - this.x;
4232		this.y = - this.y;
4233		this.z = - this.z;
4234
4235		return this;
4236
4237	}
4238
4239	dot( v ) {
4240
4241		return this.x * v.x + this.y * v.y + this.z * v.z;
4242
4243	}
4244
4245	// TODO lengthSquared?
4246
4247	lengthSq() {
4248
4249		return this.x * this.x + this.y * this.y + this.z * this.z;
4250
4251	}
4252
4253	length() {
4254
4255		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
4256
4257	}
4258
4259	manhattanLength() {
4260
4261		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
4262
4263	}
4264
4265	normalize() {
4266
4267		return this.divideScalar( this.length() || 1 );
4268
4269	}
4270
4271	setLength( length ) {
4272
4273		return this.normalize().multiplyScalar( length );
4274
4275	}
4276
4277	lerp( v, alpha ) {
4278
4279		this.x += ( v.x - this.x ) * alpha;
4280		this.y += ( v.y - this.y ) * alpha;
4281		this.z += ( v.z - this.z ) * alpha;
4282
4283		return this;
4284
4285	}
4286
4287	lerpVectors( v1, v2, alpha ) {
4288
4289		this.x = v1.x + ( v2.x - v1.x ) * alpha;
4290		this.y = v1.y + ( v2.y - v1.y ) * alpha;
4291		this.z = v1.z + ( v2.z - v1.z ) * alpha;
4292
4293		return this;
4294
4295	}
4296
4297	cross( v ) {
4298
4299		return this.crossVectors( this, v );
4300
4301	}
4302
4303	crossVectors( a, b ) {
4304
4305		const ax = a.x, ay = a.y, az = a.z;
4306		const bx = b.x, by = b.y, bz = b.z;
4307
4308		this.x = ay * bz - az * by;
4309		this.y = az * bx - ax * bz;
4310		this.z = ax * by - ay * bx;
4311
4312		return this;
4313
4314	}
4315
4316	projectOnVector( v ) {
4317
4318		const denominator = v.lengthSq();
4319
4320		if ( denominator === 0 ) return this.set( 0, 0, 0 );
4321
4322		const scalar = v.dot( this ) / denominator;
4323
4324		return this.copy( v ).multiplyScalar( scalar );
4325
4326	}
4327
4328	projectOnPlane( planeNormal ) {
4329
4330		_vector$c.copy( this ).projectOnVector( planeNormal );
4331
4332		return this.sub( _vector$c );
4333
4334	}
4335
4336	reflect( normal ) {
4337
4338		// reflect incident vector off plane orthogonal to normal
4339		// normal is assumed to have unit length
4340
4341		return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
4342
4343	}
4344
4345	angleTo( v ) {
4346
4347		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
4348
4349		if ( denominator === 0 ) return Math.PI / 2;
4350
4351		const theta = this.dot( v ) / denominator;
4352
4353		// clamp, to handle numerical problems
4354
4355		return Math.acos( clamp( theta, - 
vendor: 14,574 bytes, lines 4355-5083
43551, 1 ) );
4356
4357	}
4358
4359	distanceTo( v ) {
4360
4361		return Math.sqrt( this.distanceToSquared( v ) );
4362
4363	}
4364
4365	distanceToSquared( v ) {
4366
4367		const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
4368
4369		return dx * dx + dy * dy + dz * dz;
4370
4371	}
4372
4373	manhattanDistanceTo( v ) {
4374
4375		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
4376
4377	}
4378
4379	setFromSpherical( s ) {
4380
4381		return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
4382
4383	}
4384
4385	setFromSphericalCoords( radius, phi, theta ) {
4386
4387		const sinPhiRadius = Math.sin( phi ) * radius;
4388
4389		this.x = sinPhiRadius * Math.sin( theta );
4390		this.y = Math.cos( phi ) * radius;
4391		this.z = sinPhiRadius * Math.cos( theta );
4392
4393		return this;
4394
4395	}
4396
4397	setFromCylindrical( c ) {
4398
4399		return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
4400
4401	}
4402
4403	setFromCylindricalCoords( radius, theta, y ) {
4404
4405		this.x = radius * Math.sin( theta );
4406		this.y = y;
4407		this.z = radius * Math.cos( theta );
4408
4409		return this;
4410
4411	}
4412
4413	setFromMatrixPosition( m ) {
4414
4415		const e = m.elements;
4416
4417		this.x = e[ 12 ];
4418		this.y = e[ 13 ];
4419		this.z = e[ 14 ];
4420
4421		return this;
4422
4423	}
4424
4425	setFromMatrixScale( m ) {
4426
4427		const sx = this.setFromMatrixColumn( m, 0 ).length();
4428		const sy = this.setFromMatrixColumn( m, 1 ).length();
4429		const sz = this.setFromMatrixColumn( m, 2 ).length();
4430
4431		this.x = sx;
4432		this.y = sy;
4433		this.z = sz;
4434
4435		return this;
4436
4437	}
4438
4439	setFromMatrixColumn( m, index ) {
4440
4441		return this.fromArray( m.elements, index * 4 );
4442
4443	}
4444
4445	setFromMatrix3Column( m, index ) {
4446
4447		return this.fromArray( m.elements, index * 3 );
4448
4449	}
4450
4451	setFromEuler( e ) {
4452
4453		this.x = e._x;
4454		this.y = e._y;
4455		this.z = e._z;
4456
4457		return this;
4458
4459	}
4460
4461	setFromColor( c ) {
4462
4463		this.x = c.r;
4464		this.y = c.g;
4465		this.z = c.b;
4466
4467		return this;
4468
4469	}
4470
4471	equals( v ) {
4472
4473		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
4474
4475	}
4476
4477	fromArray( array, offset = 0 ) {
4478
4479		this.x = array[ offset ];
4480		this.y = array[ offset + 1 ];
4481		this.z = array[ offset + 2 ];
4482
4483		return this;
4484
4485	}
4486
4487	toArray( array = [], offset = 0 ) {
4488
4489		array[ offset ] = this.x;
4490		array[ offset + 1 ] = this.y;
4491		array[ offset + 2 ] = this.z;
4492
4493		return array;
4494
4495	}
4496
4497	fromBufferAttribute( attribute, index ) {
4498
4499		this.x = attribute.getX( index );
4500		this.y = attribute.getY( index );
4501		this.z = attribute.getZ( index );
4502
4503		return this;
4504
4505	}
4506
4507	random() {
4508
4509		this.x = Math.random();
4510		this.y = Math.random();
4511		this.z = Math.random();
4512
4513		return this;
4514
4515	}
4516
4517	randomDirection() {
4518
4519		// https://mathworld.wolfram.com/SpherePointPicking.html
4520
4521		const theta = Math.random() * Math.PI * 2;
4522		const u = Math.random() * 2 - 1;
4523		const c = Math.sqrt( 1 - u * u );
4524
4525		this.x = c * Math.cos( theta );
4526		this.y = u;
4527		this.z = c * Math.sin( theta );
4528
4529		return this;
4530
4531	}
4532
4533	*[ Symbol.iterator ]() {
4534
4535		yield this.x;
4536		yield this.y;
4537		yield this.z;
4538
4539	}
4540
4541}
4542
4543const _vector$c = /*@__PURE__*/ new Vector3();
4544const _quaternion$4 = /*@__PURE__*/ new Quaternion();
4545
4546class Box3 {
4547
4548	constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) {
4549
4550		this.isBox3 = true;
4551
4552		this.min = min;
4553		this.max = max;
4554
4555	}
4556
4557	set( min, max ) {
4558
4559		this.min.copy( min );
4560		this.max.copy( max );
4561
4562		return this;
4563
4564	}
4565
4566	setFromArray( array ) {
4567
4568		this.makeEmpty();
4569
4570		for ( let i = 0, il = array.length; i < il; i += 3 ) {
4571
4572			this.expandByPoint( _vector$b.fromArray( array, i ) );
4573
4574		}
4575
4576		return this;
4577
4578	}
4579
4580	setFromBufferAttribute( attribute ) {
4581
4582		this.makeEmpty();
4583
4584		for ( let i = 0, il = attribute.count; i < il; i ++ ) {
4585
4586			this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) );
4587
4588		}
4589
4590		return this;
4591
4592	}
4593
4594	setFromPoints( points ) {
4595
4596		this.makeEmpty();
4597
4598		for ( let i = 0, il = points.length; i < il; i ++ ) {
4599
4600			this.expandByPoint( points[ i ] );
4601
4602		}
4603
4604		return this;
4605
4606	}
4607
4608	setFromCenterAndSize( center, size ) {
4609
4610		const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 );
4611
4612		this.min.copy( center ).sub( halfSize );
4613		this.max.copy( center ).add( halfSize );
4614
4615		return this;
4616
4617	}
4618
4619	setFromObject( object, precise = false ) {
4620
4621		this.makeEmpty();
4622
4623		return this.expandByObject( object, precise );
4624
4625	}
4626
4627	clone() {
4628
4629		return new this.constructor().copy( this );
4630
4631	}
4632
4633	copy( box ) {
4634
4635		this.min.copy( box.min );
4636		this.max.copy( box.max );
4637
4638		return this;
4639
4640	}
4641
4642	makeEmpty() {
4643
4644		this.min.x = this.min.y = this.min.z = + Infinity;
4645		this.max.x = this.max.y = this.max.z = - Infinity;
4646
4647		return this;
4648
4649	}
4650
4651	isEmpty() {
4652
4653		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4654
4655		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4656
4657	}
4658
4659	getCenter( target ) {
4660
4661		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4662
4663	}
4664
4665	getSize( target ) {
4666
4667		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
4668
4669	}
4670
4671	expandByPoint( point ) {
4672
4673		this.min.min( point );
4674		this.max.max( point );
4675
4676		return this;
4677
4678	}
4679
4680	expandByVector( vector ) {
4681
4682		this.min.sub( vector );
4683		this.max.add( vector );
4684
4685		return this;
4686
4687	}
4688
4689	expandByScalar( scalar ) {
4690
4691		this.min.addScalar( - scalar );
4692		this.max.addScalar( scalar );
4693
4694		return this;
4695
4696	}
4697
4698	expandByObject( object, precise = false ) {
4699
4700		// Computes the world-axis-aligned bounding box of an object (including its children),
4701		// accounting for both the object's, and children's, world transforms
4702
4703		object.updateWorldMatrix( false, false );
4704
4705		const geometry = object.geometry;
4706
4707		if ( geometry !== undefined ) {
4708
4709			const positionAttribute = geometry.getAttribute( 'position' );
4710
4711			// precise AABB computation based on vertex data requires at least a position attribute.
4712			// instancing isn't supported so far and uses the normal (conservative) code path.
4713
4714			if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) {
4715
4716				for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
4717
4718					if ( object.isMesh === true ) {
4719
4720						object.getVertexPosition( i, _vector$b );
4721
4722					} else {
4723
4724						_vector$b.fromBufferAttribute( positionAttribute, i );
4725
4726					}
4727
4728					_vector$b.applyMatrix4( object.matrixWorld );
4729					this.expandByPoint( _vector$b );
4730
4731				}
4732
4733			} else {
4734
4735				if ( object.boundingBox !== undefined ) {
4736
4737					// object-level bounding box
4738
4739					if ( object.boundingBox === null ) {
4740
4741						object.computeBoundingBox();
4742
4743					}
4744
4745					_box$4.copy( object.boundingBox );
4746
4747
4748				} else {
4749
4750					// geometry-level bounding box
4751
4752					if ( geometry.boundingBox === null ) {
4753
4754						geometry.computeBoundingBox();
4755
4756					}
4757
4758					_box$4.copy( geometry.boundingBox );
4759
4760				}
4761
4762				_box$4.applyMatrix4( object.matrixWorld );
4763
4764				this.union( _box$4 );
4765
4766			}
4767
4768		}
4769
4770		const children = object.children;
4771
4772		for ( let i = 0, l = children.length; i < l; i ++ ) {
4773
4774			this.expandByObject( children[ i ], precise );
4775
4776		}
4777
4778		return this;
4779
4780	}
4781
4782	containsPoint( point ) {
4783
4784		return point.x < this.min.x || point.x > this.max.x ||
4785			point.y < this.min.y || point.y > this.max.y ||
4786			point.z < this.min.z || point.z > this.max.z ? false : true;
4787
4788	}
4789
4790	containsBox( box ) {
4791
4792		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4793			this.min.y <= box.min.y && box.max.y <= this.max.y &&
4794			this.min.z <= box.min.z && box.max.z <= this.max.z;
4795
4796	}
4797
4798	getParameter( point, target ) {
4799
4800		// This can potentially have a divide by zero if the box
4801		// has a size dimension of 0.
4802
4803		return target.set(
4804			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4805			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4806			( point.z - this.min.z ) / ( this.max.z - this.min.z )
4807		);
4808
4809	}
4810
4811	intersectsBox( box ) {
4812
4813		// using 6 splitting planes to rule out intersections.
4814		return box.max.x < this.min.x || box.min.x > this.max.x ||
4815			box.max.y < this.min.y || box.min.y > this.max.y ||
4816			box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
4817
4818	}
4819
4820	intersectsSphere( sphere ) {
4821
4822		// Find the point on the AABB closest to the sphere center.
4823		this.clampPoint( sphere.center, _vector$b );
4824
4825		// If that point is inside the sphere, the AABB and sphere intersect.
4826		return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
4827
4828	}
4829
4830	intersectsPlane( plane ) {
4831
4832		// We compute the minimum and maximum dot product values. If those values
4833		// are on the same side (back or front) of the plane, then there is no intersection.
4834
4835		let min, max;
4836
4837		if ( plane.normal.x > 0 ) {
4838
4839			min = plane.normal.x * this.min.x;
4840			max = plane.normal.x * this.max.x;
4841
4842		} else {
4843
4844			min = plane.normal.x * this.max.x;
4845			max = plane.normal.x * this.min.x;
4846
4847		}
4848
4849		if ( plane.normal.y > 0 ) {
4850
4851			min += plane.normal.y * this.min.y;
4852			max += plane.normal.y * this.max.y;
4853
4854		} else {
4855
4856			min += plane.normal.y * this.max.y;
4857			max += plane.normal.y * this.min.y;
4858
4859		}
4860
4861		if ( plane.normal.z > 0 ) {
4862
4863			min += plane.normal.z * this.min.z;
4864			max += plane.normal.z * this.max.z;
4865
4866		} else {
4867
4868			min += plane.normal.z * this.max.z;
4869			max += plane.normal.z * this.min.z;
4870
4871		}
4872
4873		return ( min <= - plane.constant && max >= - plane.constant );
4874
4875	}
4876
4877	intersectsTriangle( triangle ) {
4878
4879		if ( this.isEmpty() ) {
4880
4881			return false;
4882
4883		}
4884
4885		// compute box center and extents
4886		this.getCenter( _center );
4887		_extents.subVectors( this.max, _center );
4888
4889		// translate triangle to aabb origin
4890		_v0$2.subVectors( triangle.a, _center );
4891		_v1$7.subVectors( triangle.b, _center );
4892		_v2$4.subVectors( triangle.c, _center );
4893
4894		// compute edge vectors for triangle
4895		_f0.subVectors( _v1$7, _v0$2 );
4896		_f1.subVectors( _v2$4, _v1$7 );
4897		_f2.subVectors( _v0$2, _v2$4 );
4898
4899		// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
4900		// 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
4901		// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
4902		let axes = [
4903			0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
4904			_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
4905			- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
4906		];
4907		if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
4908
4909			return false;
4910
4911		}
4912
4913		// test 3 face normals from the aabb
4914		axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
4915		if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
4916
4917			return false;
4918
4919		}
4920
4921		// finally testing the face normal of the triangle
4922		// use already existing triangle edge vectors here
4923		_triangleNormal.crossVectors( _f0, _f1 );
4924		axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
4925
4926		return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents );
4927
4928	}
4929
4930	clampPoint( point, target ) {
4931
4932		return target.copy( point ).clamp( this.min, this.max );
4933
4934	}
4935
4936	distanceToPoint( point ) {
4937
4938		return this.clampPoint( point, _vector$b ).distanceTo( point );
4939
4940	}
4941
4942	getBoundingSphere( target ) {
4943
4944		if ( this.isEmpty() ) {
4945
4946			target.makeEmpty();
4947
4948		} else {
4949
4950			this.getCenter( target.center );
4951
4952			target.radius = this.getSize( _vector$b ).length() * 0.5;
4953
4954		}
4955
4956		return target;
4957
4958	}
4959
4960	intersect( box ) {
4961
4962		this.min.max( box.min );
4963		this.max.min( box.max );
4964
4965		// 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.
4966		if ( this.isEmpty() ) this.makeEmpty();
4967
4968		return this;
4969
4970	}
4971
4972	union( box ) {
4973
4974		this.min.min( box.min );
4975		this.max.max( box.max );
4976
4977		return this;
4978
4979	}
4980
4981	applyMatrix4( matrix ) {
4982
4983		// transform of empty box is an empty box.
4984		if ( this.isEmpty() ) return this;
4985
4986		// NOTE: I am using a binary pattern to specify all 2^3 combinations below
4987		_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
4988		_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
4989		_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
4990		_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
4991		_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
4992		_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
4993		_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
4994		_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
4995
4996		this.setFromPoints( _points );
4997
4998		return this;
4999
5000	}
5001
5002	translate( offset ) {
5003
5004		this.min.add( offset );
5005		this.max.add( offset );
5006
5007		return this;
5008
5009	}
5010
5011	equals( box ) {
5012
5013		return box.min.equals( this.min ) && box.max.equals( this.max );
5014
5015	}
5016
5017}
5018
5019const _points = [
5020	/*@__PURE__*/ new Vector3(),
5021	/*@__PURE__*/ new Vector3(),
5022	/*@__PURE__*/ new Vector3(),
5023	/*@__PURE__*/ new Vector3(),
5024	/*@__PURE__*/ new Vector3(),
5025	/*@__PURE__*/ new Vector3(),
5026	/*@__PURE__*/ new Vector3(),
5027	/*@__PURE__*/ new Vector3()
5028];
5029
5030const _vector$b = /*@__PURE__*/ new Vector3();
5031
5032const _box$4 = /*@__PURE__*/ new Box3();
5033
5034// triangle centered vertices
5035
5036const _v0$2 = /*@__PURE__*/ new Vector3();
5037const _v1$7 = /*@__PURE__*/ new Vector3();
5038const _v2$4 = /*@__PURE__*/ new Vector3();
5039
5040// triangle edge vectors
5041
5042const _f0 = /*@__PURE__*/ new Vector3();
5043const _f1 = /*@__PURE__*/ new Vector3();
5044const _f2 = /*@__PURE__*/ new Vector3();
5045
5046const _center = /*@__PURE__*/ new Vector3();
5047const _extents = /*@__PURE__*/ new Vector3();
5048const _triangleNormal = /*@__PURE__*/ new Vector3();
5049const _testAxis = /*@__PURE__*/ new Vector3();
5050
5051function satForAxes( axes, v0, v1, v2, extents ) {
5052
5053	for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
5054
5055		_testAxis.fromArray( axes, i );
5056		// project the aabb onto the separating axis
5057		const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
5058		// project all 3 vertices of the triangle onto the separating axis
5059		const p0 = v0.dot( _testAxis );
5060		const p1 = v1.dot( _testAxis );
5061		const p2 = v2.dot( _testAxis );
5062		// actual test, basically see if either of the most extreme of the triangle points intersects r
5063		if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
5064
5065			// points of the projected triangle are outside the projected half-length of the aabb
5066			// the axis is separating and we can exit
5067			return false;
5068
5069		}
5070
5071	}
5072
5073	return true;
5074
5075}
5076
5077const _box$3 = /*@__PURE__*/ new Box3();
5078const _v1$6 = /*@__PURE__*/ new Vector3();
5079const _v2$3 = /*@__PURE__*/ new Vector3();
5080
5081class Sphere {
5082
5083	constructor( center = new Vector3(), radius = -
vendor: 3,824 bytes, lines 5083-5329
5083 1 ) {
5084
5085		this.isSphere = true;
5086
5087		this.center = center;
5088		this.radius = radius;
5089
5090	}
5091
5092	set( center, radius ) {
5093
5094		this.center.copy( center );
5095		this.radius = radius;
5096
5097		return this;
5098
5099	}
5100
5101	setFromPoints( points, optionalCenter ) {
5102
5103		const center = this.center;
5104
5105		if ( optionalCenter !== undefined ) {
5106
5107			center.copy( optionalCenter );
5108
5109		} else {
5110
5111			_box$3.setFromPoints( points ).getCenter( center );
5112
5113		}
5114
5115		let maxRadiusSq = 0;
5116
5117		for ( let i = 0, il = points.length; i < il; i ++ ) {
5118
5119			maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
5120
5121		}
5122
5123		this.radius = Math.sqrt( maxRadiusSq );
5124
5125		return this;
5126
5127	}
5128
5129	copy( sphere ) {
5130
5131		this.center.copy( sphere.center );
5132		this.radius = sphere.radius;
5133
5134		return this;
5135
5136	}
5137
5138	isEmpty() {
5139
5140		return ( this.radius < 0 );
5141
5142	}
5143
5144	makeEmpty() {
5145
5146		this.center.set( 0, 0, 0 );
5147		this.radius = - 1;
5148
5149		return this;
5150
5151	}
5152
5153	containsPoint( point ) {
5154
5155		return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
5156
5157	}
5158
5159	distanceToPoint( point ) {
5160
5161		return ( point.distanceTo( this.center ) - this.radius );
5162
5163	}
5164
5165	intersectsSphere( sphere ) {
5166
5167		const radiusSum = this.radius + sphere.radius;
5168
5169		return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
5170
5171	}
5172
5173	intersectsBox( box ) {
5174
5175		return box.intersectsSphere( this );
5176
5177	}
5178
5179	intersectsPlane( plane ) {
5180
5181		return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
5182
5183	}
5184
5185	clampPoint( point, target ) {
5186
5187		const deltaLengthSq = this.center.distanceToSquared( point );
5188
5189		target.copy( point );
5190
5191		if ( deltaLengthSq > ( this.radius * this.radius ) ) {
5192
5193			target.sub( this.center ).normalize();
5194			target.multiplyScalar( this.radius ).add( this.center );
5195
5196		}
5197
5198		return target;
5199
5200	}
5201
5202	getBoundingBox( target ) {
5203
5204		if ( this.isEmpty() ) {
5205
5206			// Empty sphere produces empty bounding box
5207			target.makeEmpty();
5208			return target;
5209
5210		}
5211
5212		target.set( this.center, this.center );
5213		target.expandByScalar( this.radius );
5214
5215		return target;
5216
5217	}
5218
5219	applyMatrix4( matrix ) {
5220
5221		this.center.applyMatrix4( matrix );
5222		this.radius = this.radius * matrix.getMaxScaleOnAxis();
5223
5224		return this;
5225
5226	}
5227
5228	translate( offset ) {
5229
5230		this.center.add( offset );
5231
5232		return this;
5233
5234	}
5235
5236	expandByPoint( point ) {
5237
5238		if ( this.isEmpty() ) {
5239
5240			this.center.copy( point );
5241
5242			this.radius = 0;
5243
5244			return this;
5245
5246		}
5247
5248		_v1$6.subVectors( point, this.center );
5249
5250		const lengthSq = _v1$6.lengthSq();
5251
5252		if ( lengthSq > ( this.radius * this.radius ) ) {
5253
5254			// calculate the minimal sphere
5255
5256			const length = Math.sqrt( lengthSq );
5257
5258			const delta = ( length - this.radius ) * 0.5;
5259
5260			this.center.addScaledVector( _v1$6, delta / length );
5261
5262			this.radius += delta;
5263
5264		}
5265
5266		return this;
5267
5268	}
5269
5270	union( sphere ) {
5271
5272		if ( sphere.isEmpty() ) {
5273
5274			return this;
5275
5276		}
5277
5278		if ( this.isEmpty() ) {
5279
5280			this.copy( sphere );
5281
5282			return this;
5283
5284		}
5285
5286		if ( this.center.equals( sphere.center ) === true ) {
5287
5288			 this.radius = Math.max( this.radius, sphere.radius );
5289
5290		} else {
5291
5292			_v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius );
5293
5294			this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) );
5295
5296			this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) );
5297
5298		}
5299
5300		return this;
5301
5302	}
5303
5304	equals( sphere ) {
5305
5306		return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
5307
5308	}
5309
5310	clone() {
5311
5312		return new this.constructor().copy( this );
5313
5314	}
5315
5316}
5317
5318const _vector$a = /*@__PURE__*/ new Vector3();
5319const _segCenter = /*@__PURE__*/ new Vector3();
5320const _segDir = /*@__PURE__*/ new Vector3();
5321const _diff = /*@__PURE__*/ new Vector3();
5322
5323const _edge1 = /*@__PURE__*/ new Vector3();
5324const _edge2 = /*@__PURE__*/ new Vector3();
5325const _normal$1 = /*@__PURE__*/ new Vector3();
5326
5327class Ray {
5328
5329	constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 
vendor: 8,510 bytes, lines 5329-5735
53291 ) ) {
5330
5331		this.origin = origin;
5332		this.direction = direction;
5333
5334	}
5335
5336	set( origin, direction ) {
5337
5338		this.origin.copy( origin );
5339		this.direction.copy( direction );
5340
5341		return this;
5342
5343	}
5344
5345	copy( ray ) {
5346
5347		this.origin.copy( ray.origin );
5348		this.direction.copy( ray.direction );
5349
5350		return this;
5351
5352	}
5353
5354	at( t, target ) {
5355
5356		return target.copy( this.origin ).addScaledVector( this.direction, t );
5357
5358	}
5359
5360	lookAt( v ) {
5361
5362		this.direction.copy( v ).sub( this.origin ).normalize();
5363
5364		return this;
5365
5366	}
5367
5368	recast( t ) {
5369
5370		this.origin.copy( this.at( t, _vector$a ) );
5371
5372		return this;
5373
5374	}
5375
5376	closestPointToPoint( point, target ) {
5377
5378		target.subVectors( point, this.origin );
5379
5380		const directionDistance = target.dot( this.direction );
5381
5382		if ( directionDistance < 0 ) {
5383
5384			return target.copy( this.origin );
5385
5386		}
5387
5388		return target.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5389
5390	}
5391
5392	distanceToPoint( point ) {
5393
5394		return Math.sqrt( this.distanceSqToPoint( point ) );
5395
5396	}
5397
5398	distanceSqToPoint( point ) {
5399
5400		const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction );
5401
5402		// point behind the ray
5403
5404		if ( directionDistance < 0 ) {
5405
5406			return this.origin.distanceToSquared( point );
5407
5408		}
5409
5410		_vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5411
5412		return _vector$a.distanceToSquared( point );
5413
5414	}
5415
5416	distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
5417
5418		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
5419		// It returns the min distance between the ray and the segment
5420		// defined by v0 and v1
5421		// It can also set two optional targets :
5422		// - The closest point on the ray
5423		// - The closest point on the segment
5424
5425		_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
5426		_segDir.copy( v1 ).sub( v0 ).normalize();
5427		_diff.copy( this.origin ).sub( _segCenter );
5428
5429		const segExtent = v0.distanceTo( v1 ) * 0.5;
5430		const a01 = - this.direction.dot( _segDir );
5431		const b0 = _diff.dot( this.direction );
5432		const b1 = - _diff.dot( _segDir );
5433		const c = _diff.lengthSq();
5434		const det = Math.abs( 1 - a01 * a01 );
5435		let s0, s1, sqrDist, extDet;
5436
5437		if ( det > 0 ) {
5438
5439			// The ray and segment are not parallel.
5440
5441			s0 = a01 * b1 - b0;
5442			s1 = a01 * b0 - b1;
5443			extDet = segExtent * det;
5444
5445			if ( s0 >= 0 ) {
5446
5447				if ( s1 >= - extDet ) {
5448
5449					if ( s1 <= extDet ) {
5450
5451						// region 0
5452						// Minimum at interior points of ray and segment.
5453
5454						const invDet = 1 / det;
5455						s0 *= invDet;
5456						s1 *= invDet;
5457						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
5458
5459					} else {
5460
5461						// region 1
5462
5463						s1 = segExtent;
5464						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5465						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5466
5467					}
5468
5469				} else {
5470
5471					// region 5
5472
5473					s1 = - segExtent;
5474					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5475					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5476
5477				}
5478
5479			} else {
5480
5481				if ( s1 <= - extDet ) {
5482
5483					// region 4
5484
5485					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
5486					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5487					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5488
5489				} else if ( s1 <= extDet ) {
5490
5491					// region 3
5492
5493					s0 = 0;
5494					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
5495					sqrDist = s1 * ( s1 + 2 * b1 ) + c;
5496
5497				} else {
5498
5499					// region 2
5500
5501					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
5502					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5503					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5504
5505				}
5506
5507			}
5508
5509		} else {
5510
5511			// Ray and segment are parallel.
5512
5513			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
5514			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5515			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5516
5517		}
5518
5519		if ( optionalPointOnRay ) {
5520
5521			optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 );
5522
5523		}
5524
5525		if ( optionalPointOnSegment ) {
5526
5527			optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 );
5528
5529		}
5530
5531		return sqrDist;
5532
5533	}
5534
5535	intersectSphere( sphere, target ) {
5536
5537		_vector$a.subVectors( sphere.center, this.origin );
5538		const tca = _vector$a.dot( this.direction );
5539		const d2 = _vector$a.dot( _vector$a ) - tca * tca;
5540		const radius2 = sphere.radius * sphere.radius;
5541
5542		if ( d2 > radius2 ) return null;
5543
5544		const thc = Math.sqrt( radius2 - d2 );
5545
5546		// t0 = first intersect point - entrance on front of sphere
5547		const t0 = tca - thc;
5548
5549		// t1 = second intersect point - exit point on back of sphere
5550		const t1 = tca + thc;
5551
5552		// test to see if t1 is behind the ray - if so, return null
5553		if ( t1 < 0 ) return null;
5554
5555		// test to see if t0 is behind the ray:
5556		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
5557		// in order to always return an intersect point that is in front of the ray.
5558		if ( t0 < 0 ) return this.at( t1, target );
5559
5560		// else t0 is in front of the ray, so return the first collision point scaled by t0
5561		return this.at( t0, target );
5562
5563	}
5564
5565	intersectsSphere( sphere ) {
5566
5567		return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
5568
5569	}
5570
5571	distanceToPlane( plane ) {
5572
5573		const denominator = plane.normal.dot( this.direction );
5574
5575		if ( denominator === 0 ) {
5576
5577			// line is coplanar, return origin
5578			if ( plane.distanceToPoint( this.origin ) === 0 ) {
5579
5580				return 0;
5581
5582			}
5583
5584			// Null is preferable to undefined since undefined means.... it is undefined
5585
5586			return null;
5587
5588		}
5589
5590		const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
5591
5592		// Return if the ray never intersects the plane
5593
5594		return t >= 0 ? t : null;
5595
5596	}
5597
5598	intersectPlane( plane, target ) {
5599
5600		const t = this.distanceToPlane( plane );
5601
5602		if ( t === null ) {
5603
5604			return null;
5605
5606		}
5607
5608		return this.at( t, target );
5609
5610	}
5611
5612	intersectsPlane( plane ) {
5613
5614		// check if the ray lies on the plane first
5615
5616		const distToPoint = plane.distanceToPoint( this.origin );
5617
5618		if ( distToPoint === 0 ) {
5619
5620			return true;
5621
5622		}
5623
5624		const denominator = plane.normal.dot( this.direction );
5625
5626		if ( denominator * distToPoint < 0 ) {
5627
5628			return true;
5629
5630		}
5631
5632		// ray origin is behind the plane (and is pointing behind it)
5633
5634		return false;
5635
5636	}
5637
5638	intersectBox( box, target ) {
5639
5640		let tmin, tmax, tymin, tymax, tzmin, tzmax;
5641
5642		const invdirx = 1 / this.direction.x,
5643			invdiry = 1 / this.direction.y,
5644			invdirz = 1 / this.direction.z;
5645
5646		const origin = this.origin;
5647
5648		if ( invdirx >= 0 ) {
5649
5650			tmin = ( box.min.x - origin.x ) * invdirx;
5651			tmax = ( box.max.x - origin.x ) * invdirx;
5652
5653		} else {
5654
5655			tmin = ( box.max.x - origin.x ) * invdirx;
5656			tmax = ( box.min.x - origin.x ) * invdirx;
5657
5658		}
5659
5660		if ( invdiry >= 0 ) {
5661
5662			tymin = ( box.min.y - origin.y ) * invdiry;
5663			tymax = ( box.max.y - origin.y ) * invdiry;
5664
5665		} else {
5666
5667			tymin = ( box.max.y - origin.y ) * invdiry;
5668			tymax = ( box.min.y - origin.y ) * invdiry;
5669
5670		}
5671
5672		if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
5673
5674		if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin;
5675
5676		if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax;
5677
5678		if ( invdirz >= 0 ) {
5679
5680			tzmin = ( box.min.z - origin.z ) * invdirz;
5681			tzmax = ( box.max.z - origin.z ) * invdirz;
5682
5683		} else {
5684
5685			tzmin = ( box.max.z - origin.z ) * invdirz;
5686			tzmax = ( box.min.z - origin.z ) * invdirz;
5687
5688		}
5689
5690		if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
5691
5692		if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
5693
5694		if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
5695
5696		//return point closest to the ray (positive side)
5697
5698		if ( tmax < 0 ) return null;
5699
5700		return this.at( tmin >= 0 ? tmin : tmax, target );
5701
5702	}
5703
5704	intersectsBox( box ) {
5705
5706		return this.intersectBox( box, _vector$a ) !== null;
5707
5708	}
5709
5710	intersectTriangle( a, b, c, backfaceCulling, target ) {
5711
5712		// Compute the offset origin, edges, and normal.
5713
5714		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
5715
5716		_edge1.subVectors( b, a );
5717		_edge2.subVectors( c, a );
5718		_normal$1.crossVectors( _edge1, _edge2 );
5719
5720		// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
5721		// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
5722		//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
5723		//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
5724		//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
5725		let DdN = this.direction.dot( _normal$1 );
5726		let sign;
5727
5728		if ( DdN > 0 ) {
5729
5730			if ( backfaceCulling ) return null;
5731			sign = 1;
5732
5733		} else if ( DdN < 0 ) {
5734
5735			sign = -
5735 
vendor: 17,907 bytes, lines 5735-6595
57351;
5736			DdN = - DdN;
5737
5738		} else {
5739
5740			return null;
5741
5742		}
5743
5744		_diff.subVectors( this.origin, a );
5745		const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
5746
5747		// b1 < 0, no intersection
5748		if ( DdQxE2 < 0 ) {
5749
5750			return null;
5751
5752		}
5753
5754		const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
5755
5756		// b2 < 0, no intersection
5757		if ( DdE1xQ < 0 ) {
5758
5759			return null;
5760
5761		}
5762
5763		// b1+b2 > 1, no intersection
5764		if ( DdQxE2 + DdE1xQ > DdN ) {
5765
5766			return null;
5767
5768		}
5769
5770		// Line intersects triangle, check if ray does.
5771		const QdN = - sign * _diff.dot( _normal$1 );
5772
5773		// t < 0, no intersection
5774		if ( QdN < 0 ) {
5775
5776			return null;
5777
5778		}
5779
5780		// Ray intersects triangle.
5781		return this.at( QdN / DdN, target );
5782
5783	}
5784
5785	applyMatrix4( matrix4 ) {
5786
5787		this.origin.applyMatrix4( matrix4 );
5788		this.direction.transformDirection( matrix4 );
5789
5790		return this;
5791
5792	}
5793
5794	equals( ray ) {
5795
5796		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
5797
5798	}
5799
5800	clone() {
5801
5802		return new this.constructor().copy( this );
5803
5804	}
5805
5806}
5807
5808class Matrix4 {
5809
5810	constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5811
5812		Matrix4.prototype.isMatrix4 = true;
5813
5814		this.elements = [
5815
5816			1, 0, 0, 0,
5817			0, 1, 0, 0,
5818			0, 0, 1, 0,
5819			0, 0, 0, 1
5820
5821		];
5822
5823		if ( n11 !== undefined ) {
5824
5825			this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 );
5826
5827		}
5828
5829	}
5830
5831	set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5832
5833		const te = this.elements;
5834
5835		te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
5836		te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
5837		te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
5838		te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
5839
5840		return this;
5841
5842	}
5843
5844	identity() {
5845
5846		this.set(
5847
5848			1, 0, 0, 0,
5849			0, 1, 0, 0,
5850			0, 0, 1, 0,
5851			0, 0, 0, 1
5852
5853		);
5854
5855		return this;
5856
5857	}
5858
5859	clone() {
5860
5861		return new Matrix4().fromArray( this.elements );
5862
5863	}
5864
5865	copy( m ) {
5866
5867		const te = this.elements;
5868		const me = m.elements;
5869
5870		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
5871		te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
5872		te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
5873		te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
5874
5875		return this;
5876
5877	}
5878
5879	copyPosition( m ) {
5880
5881		const te = this.elements, me = m.elements;
5882
5883		te[ 12 ] = me[ 12 ];
5884		te[ 13 ] = me[ 13 ];
5885		te[ 14 ] = me[ 14 ];
5886
5887		return this;
5888
5889	}
5890
5891	setFromMatrix3( m ) {
5892
5893		const me = m.elements;
5894
5895		this.set(
5896
5897			me[ 0 ], me[ 3 ], me[ 6 ], 0,
5898			me[ 1 ], me[ 4 ], me[ 7 ], 0,
5899			me[ 2 ], me[ 5 ], me[ 8 ], 0,
5900			0, 0, 0, 1
5901
5902		);
5903
5904		return this;
5905
5906	}
5907
5908	extractBasis( xAxis, yAxis, zAxis ) {
5909
5910		xAxis.setFromMatrixColumn( this, 0 );
5911		yAxis.setFromMatrixColumn( this, 1 );
5912		zAxis.setFromMatrixColumn( this, 2 );
5913
5914		return this;
5915
5916	}
5917
5918	makeBasis( xAxis, yAxis, zAxis ) {
5919
5920		this.set(
5921			xAxis.x, yAxis.x, zAxis.x, 0,
5922			xAxis.y, yAxis.y, zAxis.y, 0,
5923			xAxis.z, yAxis.z, zAxis.z, 0,
5924			0, 0, 0, 1
5925		);
5926
5927		return this;
5928
5929	}
5930
5931	extractRotation( m ) {
5932
5933		// this method does not support reflection matrices
5934
5935		const te = this.elements;
5936		const me = m.elements;
5937
5938		const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length();
5939		const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length();
5940		const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length();
5941
5942		te[ 0 ] = me[ 0 ] * scaleX;
5943		te[ 1 ] = me[ 1 ] * scaleX;
5944		te[ 2 ] = me[ 2 ] * scaleX;
5945		te[ 3 ] = 0;
5946
5947		te[ 4 ] = me[ 4 ] * scaleY;
5948		te[ 5 ] = me[ 5 ] * scaleY;
5949		te[ 6 ] = me[ 6 ] * scaleY;
5950		te[ 7 ] = 0;
5951
5952		te[ 8 ] = me[ 8 ] * scaleZ;
5953		te[ 9 ] = me[ 9 ] * scaleZ;
5954		te[ 10 ] = me[ 10 ] * scaleZ;
5955		te[ 11 ] = 0;
5956
5957		te[ 12 ] = 0;
5958		te[ 13 ] = 0;
5959		te[ 14 ] = 0;
5960		te[ 15 ] = 1;
5961
5962		return this;
5963
5964	}
5965
5966	makeRotationFromEuler( euler ) {
5967
5968		const te = this.elements;
5969
5970		const x = euler.x, y = euler.y, z = euler.z;
5971		const a = Math.cos( x ), b = Math.sin( x );
5972		const c = Math.cos( y ), d = Math.sin( y );
5973		const e = Math.cos( z ), f = Math.sin( z );
5974
5975		if ( euler.order === 'XYZ' ) {
5976
5977			const ae = a * e, af = a * f, be = b * e, bf = b * f;
5978
5979			te[ 0 ] = c * e;
5980			te[ 4 ] = - c * f;
5981			te[ 8 ] = d;
5982
5983			te[ 1 ] = af + be * d;
5984			te[ 5 ] = ae - bf * d;
5985			te[ 9 ] = - b * c;
5986
5987			te[ 2 ] = bf - ae * d;
5988			te[ 6 ] = be + af * d;
5989			te[ 10 ] = a * c;
5990
5991		} else if ( euler.order === 'YXZ' ) {
5992
5993			const ce = c * e, cf = c * f, de = d * e, df = d * f;
5994
5995			te[ 0 ] = ce + df * b;
5996			te[ 4 ] = de * b - cf;
5997			te[ 8 ] = a * d;
5998
5999			te[ 1 ] = a * f;
6000			te[ 5 ] = a * e;
6001			te[ 9 ] = - b;
6002
6003			te[ 2 ] = cf * b - de;
6004			te[ 6 ] = df + ce * b;
6005			te[ 10 ] = a * c;
6006
6007		} else if ( euler.order === 'ZXY' ) {
6008
6009			const ce = c * e, cf = c * f, de = d * e, df = d * f;
6010
6011			te[ 0 ] = ce - df * b;
6012			te[ 4 ] = - a * f;
6013			te[ 8 ] = de + cf * b;
6014
6015			te[ 1 ] = cf + de * b;
6016			te[ 5 ] = a * e;
6017			te[ 9 ] = df - ce * b;
6018
6019			te[ 2 ] = - a * d;
6020			te[ 6 ] = b;
6021			te[ 10 ] = a * c;
6022
6023		} else if ( euler.order === 'ZYX' ) {
6024
6025			const ae = a * e, af = a * f, be = b * e, bf = b * f;
6026
6027			te[ 0 ] = c * e;
6028			te[ 4 ] = be * d - af;
6029			te[ 8 ] = ae * d + bf;
6030
6031			te[ 1 ] = c * f;
6032			te[ 5 ] = bf * d + ae;
6033			te[ 9 ] = af * d - be;
6034
6035			te[ 2 ] = - d;
6036			te[ 6 ] = b * c;
6037			te[ 10 ] = a * c;
6038
6039		} else if ( euler.order === 'YZX' ) {
6040
6041			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
6042
6043			te[ 0 ] = c * e;
6044			te[ 4 ] = bd - ac * f;
6045			te[ 8 ] = bc * f + ad;
6046
6047			te[ 1 ] = f;
6048			te[ 5 ] = a * e;
6049			te[ 9 ] = - b * e;
6050
6051			te[ 2 ] = - d * e;
6052			te[ 6 ] = ad * f + bc;
6053			te[ 10 ] = ac - bd * f;
6054
6055		} else if ( euler.order === 'XZY' ) {
6056
6057			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
6058
6059			te[ 0 ] = c * e;
6060			te[ 4 ] = - f;
6061			te[ 8 ] = d * e;
6062
6063			te[ 1 ] = ac * f + bd;
6064			te[ 5 ] = a * e;
6065			te[ 9 ] = ad * f - bc;
6066
6067			te[ 2 ] = bc * f - ad;
6068			te[ 6 ] = b * e;
6069			te[ 10 ] = bd * f + ac;
6070
6071		}
6072
6073		// bottom row
6074		te[ 3 ] = 0;
6075		te[ 7 ] = 0;
6076		te[ 11 ] = 0;
6077
6078		// last column
6079		te[ 12 ] = 0;
6080		te[ 13 ] = 0;
6081		te[ 14 ] = 0;
6082		te[ 15 ] = 1;
6083
6084		return this;
6085
6086	}
6087
6088	makeRotationFromQuaternion( q ) {
6089
6090		return this.compose( _zero, q, _one );
6091
6092	}
6093
6094	lookAt( eye, target, up ) {
6095
6096		const te = this.elements;
6097
6098		_z.subVectors( eye, target );
6099
6100		if ( _z.lengthSq() === 0 ) {
6101
6102			// eye and target are in the same position
6103
6104			_z.z = 1;
6105
6106		}
6107
6108		_z.normalize();
6109		_x.crossVectors( up, _z );
6110
6111		if ( _x.lengthSq() === 0 ) {
6112
6113			// up and z are parallel
6114
6115			if ( Math.abs( up.z ) === 1 ) {
6116
6117				_z.x += 0.0001;
6118
6119			} else {
6120
6121				_z.z += 0.0001;
6122
6123			}
6124
6125			_z.normalize();
6126			_x.crossVectors( up, _z );
6127
6128		}
6129
6130		_x.normalize();
6131		_y.crossVectors( _z, _x );
6132
6133		te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
6134		te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
6135		te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
6136
6137		return this;
6138
6139	}
6140
6141	multiply( m ) {
6142
6143		return this.multiplyMatrices( this, m );
6144
6145	}
6146
6147	premultiply( m ) {
6148
6149		return this.multiplyMatrices( m, this );
6150
6151	}
6152
6153	multiplyMatrices( a, b ) {
6154
6155		const ae = a.elements;
6156		const be = b.elements;
6157		const te = this.elements;
6158
6159		const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
6160		const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
6161		const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
6162		const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
6163
6164		const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
6165		const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
6166		const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
6167		const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
6168
6169		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
6170		te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
6171		te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
6172		te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
6173
6174		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
6175		te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
6176		te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
6177		te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
6178
6179		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
6180		te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
6181		te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
6182		te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
6183
6184		te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
6185		te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
6186		te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
6187		te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
6188
6189		return this;
6190
6191	}
6192
6193	multiplyScalar( s ) {
6194
6195		const te = this.elements;
6196
6197		te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
6198		te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
6199		te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
6200		te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
6201
6202		return this;
6203
6204	}
6205
6206	determinant() {
6207
6208		const te = this.elements;
6209
6210		const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
6211		const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
6212		const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
6213		const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
6214
6215		//TODO: make this more efficient
6216		//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
6217
6218		return (
6219			n41 * (
6220				+ n14 * n23 * n32
6221				 - n13 * n24 * n32
6222				 - n14 * n22 * n33
6223				 + n12 * n24 * n33
6224				 + n13 * n22 * n34
6225				 - n12 * n23 * n34
6226			) +
6227			n42 * (
6228				+ n11 * n23 * n34
6229				 - n11 * n24 * n33
6230				 + n14 * n21 * n33
6231				 - n13 * n21 * n34
6232				 + n13 * n24 * n31
6233				 - n14 * n23 * n31
6234			) +
6235			n43 * (
6236				+ n11 * n24 * n32
6237				 - n11 * n22 * n34
6238				 - n14 * n21 * n32
6239				 + n12 * n21 * n34
6240				 + n14 * n22 * n31
6241				 - n12 * n24 * n31
6242			) +
6243			n44 * (
6244				- n13 * n22 * n31
6245				 - n11 * n23 * n32
6246				 + n11 * n22 * n33
6247				 + n13 * n21 * n32
6248				 - n12 * n21 * n33
6249				 + n12 * n23 * n31
6250			)
6251
6252		);
6253
6254	}
6255
6256	transpose() {
6257
6258		const te = this.elements;
6259		let tmp;
6260
6261		tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
6262		tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
6263		tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
6264
6265		tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
6266		tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
6267		tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
6268
6269		return this;
6270
6271	}
6272
6273	setPosition( x, y, z ) {
6274
6275		const te = this.elements;
6276
6277		if ( x.isVector3 ) {
6278
6279			te[ 12 ] = x.x;
6280			te[ 13 ] = x.y;
6281			te[ 14 ] = x.z;
6282
6283		} else {
6284
6285			te[ 12 ] = x;
6286			te[ 13 ] = y;
6287			te[ 14 ] = z;
6288
6289		}
6290
6291		return this;
6292
6293	}
6294
6295	invert() {
6296
6297		// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
6298		const te = this.elements,
6299
6300			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
6301			n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
6302			n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
6303			n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
6304
6305			t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
6306			t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
6307			t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
6308			t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
6309
6310		const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
6311
6312		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
6313
6314		const detInv = 1 / det;
6315
6316		te[ 0 ] = t11 * detInv;
6317		te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
6318		te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
6319		te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
6320
6321		te[ 4 ] = t12 * detInv;
6322		te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
6323		te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
6324		te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
6325
6326		te[ 8 ] = t13 * detInv;
6327		te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
6328		te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
6329		te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
6330
6331		te[ 12 ] = t14 * detInv;
6332		te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
6333		te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
6334		te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
6335
6336		return this;
6337
6338	}
6339
6340	scale( v ) {
6341
6342		const te = this.elements;
6343		const x = v.x, y = v.y, z = v.z;
6344
6345		te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
6346		te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
6347		te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
6348		te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
6349
6350		return this;
6351
6352	}
6353
6354	getMaxScaleOnAxis() {
6355
6356		const te = this.elements;
6357
6358		const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
6359		const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
6360		const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
6361
6362		return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
6363
6364	}
6365
6366	makeTranslation( x, y, z ) {
6367
6368		if ( x.isVector3 ) {
6369
6370			this.set(
6371
6372				1, 0, 0, x.x,
6373				0, 1, 0, x.y,
6374				0, 0, 1, x.z,
6375				0, 0, 0, 1
6376
6377			);
6378
6379		} else {
6380
6381			this.set(
6382
6383				1, 0, 0, x,
6384				0, 1, 0, y,
6385				0, 0, 1, z,
6386				0, 0, 0, 1
6387
6388			);
6389
6390		}
6391
6392		return this;
6393
6394	}
6395
6396	makeRotationX( theta ) {
6397
6398		const c = Math.cos( theta ), s = Math.sin( theta );
6399
6400		this.set(
6401
6402			1, 0, 0, 0,
6403			0, c, - s, 0,
6404			0, s, c, 0,
6405			0, 0, 0, 1
6406
6407		);
6408
6409		return this;
6410
6411	}
6412
6413	makeRotationY( theta ) {
6414
6415		const c = Math.cos( theta ), s = Math.sin( theta );
6416
6417		this.set(
6418
6419			 c, 0, s, 0,
6420			 0, 1, 0, 0,
6421			- s, 0, c, 0,
6422			 0, 0, 0, 1
6423
6424		);
6425
6426		return this;
6427
6428	}
6429
6430	makeRotationZ( theta ) {
6431
6432		const c = Math.cos( theta ), s = Math.sin( theta );
6433
6434		this.set(
6435
6436			c, - s, 0, 0,
6437			s, c, 0, 0,
6438			0, 0, 1, 0,
6439			0, 0, 0, 1
6440
6441		);
6442
6443		return this;
6444
6445	}
6446
6447	makeRotationAxis( axis, angle ) {
6448
6449		// Based on http://www.gamedev.net/reference/articles/article1199.asp
6450
6451		const c = Math.cos( angle );
6452		const s = Math.sin( angle );
6453		const t = 1 - c;
6454		const x = axis.x, y = axis.y, z = axis.z;
6455		const tx = t * x, ty = t * y;
6456
6457		this.set(
6458
6459			tx * x + c, tx * y - s * z, tx * z + s * y, 0,
6460			tx * y + s * z, ty * y + c, ty * z - s * x, 0,
6461			tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
6462			0, 0, 0, 1
6463
6464		);
6465
6466		return this;
6467
6468	}
6469
6470	makeScale( x, y, z ) {
6471
6472		this.set(
6473
6474			x, 0, 0, 0,
6475			0, y, 0, 0,
6476			0, 0, z, 0,
6477			0, 0, 0, 1
6478
6479		);
6480
6481		return this;
6482
6483	}
6484
6485	makeShear( xy, xz, yx, yz, zx, zy ) {
6486
6487		this.set(
6488
6489			1, yx, zx, 0,
6490			xy, 1, zy, 0,
6491			xz, yz, 1, 0,
6492			0, 0, 0, 1
6493
6494		);
6495
6496		return this;
6497
6498	}
6499
6500	compose( position, quaternion, scale ) {
6501
6502		const te = this.elements;
6503
6504		const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
6505		const x2 = x + x,	y2 = y + y, z2 = z + z;
6506		const xx = x * x2, xy = x * y2, xz = x * z2;
6507		const yy = y * y2, yz = y * z2, zz = z * z2;
6508		const wx = w * x2, wy = w * y2, wz = w * z2;
6509
6510		const sx = scale.x, sy = scale.y, sz = scale.z;
6511
6512		te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
6513		te[ 1 ] = ( xy + wz ) * sx;
6514		te[ 2 ] = ( xz - wy ) * sx;
6515		te[ 3 ] = 0;
6516
6517		te[ 4 ] = ( xy - wz ) * sy;
6518		te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
6519		te[ 6 ] = ( yz + wx ) * sy;
6520		te[ 7 ] = 0;
6521
6522		te[ 8 ] = ( xz + wy ) * sz;
6523		te[ 9 ] = ( yz - wx ) * sz;
6524		te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
6525		te[ 11 ] = 0;
6526
6527		te[ 12 ] = position.x;
6528		te[ 13 ] = position.y;
6529		te[ 14 ] = position.z;
6530		te[ 15 ] = 1;
6531
6532		return this;
6533
6534	}
6535
6536	decompose( position, quaternion, scale ) {
6537
6538		const te = this.elements;
6539
6540		let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
6541		const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
6542		const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
6543
6544		// if determine is negative, we need to invert one scale
6545		const det = this.determinant();
6546		if ( det < 0 ) sx = - sx;
6547
6548		position.x = te[ 12 ];
6549		position.y = te[ 13 ];
6550		position.z = te[ 14 ];
6551
6552		// scale the rotation part
6553		_m1$4.copy( this );
6554
6555		const invSX = 1 / sx;
6556		const invSY = 1 / sy;
6557		const invSZ = 1 / sz;
6558
6559		_m1$4.elements[ 0 ] *= invSX;
6560		_m1$4.elements[ 1 ] *= invSX;
6561		_m1$4.elements[ 2 ] *= invSX;
6562
6563		_m1$4.elements[ 4 ] *= invSY;
6564		_m1$4.elements[ 5 ] *= invSY;
6565		_m1$4.elements[ 6 ] *= invSY;
6566
6567		_m1$4.elements[ 8 ] *= invSZ;
6568		_m1$4.elements[ 9 ] *= invSZ;
6569		_m1$4.elements[ 10 ] *= invSZ;
6570
6571		quaternion.setFromRotationMatrix( _m1$4 );
6572
6573		scale.x = sx;
6574		scale.y = sy;
6575		scale.z = sz;
6576
6577		return this;
6578
6579	}
6580
6581	makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
6582
6583		const te = this.elements;
6584		const x = 2 * near / ( right - left );
6585		const y = 2 * near / ( top - bottom );
6586
6587		const a = ( right + left ) / ( right - left );
6588		const b = ( top + bottom ) / ( top - bottom );
6589
6590		let c, d;
6591
6592		if ( coordinateSystem === WebGLCoordinateSystem ) {
6593
6594			c = - ( far + near ) / ( far - near );
6595			d = ( -
vendor: 8,642 bytes, lines 6595-7107
6595 2 * far * near ) / ( far - near );
6596
6597		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
6598
6599			c = - far / ( far - near );
6600			d = ( - far * near ) / ( far - near );
6601
6602		} else {
6603
6604			throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
6605
6606		}
6607
6608		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a; 	te[ 12 ] = 0;
6609		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b; 	te[ 13 ] = 0;
6610		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c; 	te[ 14 ] = d;
6611		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
6612
6613		return this;
6614
6615	}
6616
6617	makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
6618
6619		const te = this.elements;
6620		const w = 1.0 / ( right - left );
6621		const h = 1.0 / ( top - bottom );
6622		const p = 1.0 / ( far - near );
6623
6624		const x = ( right + left ) * w;
6625		const y = ( top + bottom ) * h;
6626
6627		let z, zInv;
6628
6629		if ( coordinateSystem === WebGLCoordinateSystem ) {
6630
6631			z = ( far + near ) * p;
6632			zInv = - 2 * p;
6633
6634		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
6635
6636			z = near * p;
6637			zInv = - 1 * p;
6638
6639		} else {
6640
6641			throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );
6642
6643		}
6644
6645		te[ 0 ] = 2 * w;	te[ 4 ] = 0;		te[ 8 ] = 0; 		te[ 12 ] = - x;
6646		te[ 1 ] = 0; 		te[ 5 ] = 2 * h;	te[ 9 ] = 0; 		te[ 13 ] = - y;
6647		te[ 2 ] = 0; 		te[ 6 ] = 0;		te[ 10 ] = zInv;	te[ 14 ] = - z;
6648		te[ 3 ] = 0; 		te[ 7 ] = 0;		te[ 11 ] = 0;		te[ 15 ] = 1;
6649
6650		return this;
6651
6652	}
6653
6654	equals( matrix ) {
6655
6656		const te = this.elements;
6657		const me = matrix.elements;
6658
6659		for ( let i = 0; i < 16; i ++ ) {
6660
6661			if ( te[ i ] !== me[ i ] ) return false;
6662
6663		}
6664
6665		return true;
6666
6667	}
6668
6669	fromArray( array, offset = 0 ) {
6670
6671		for ( let i = 0; i < 16; i ++ ) {
6672
6673			this.elements[ i ] = array[ i + offset ];
6674
6675		}
6676
6677		return this;
6678
6679	}
6680
6681	toArray( array = [], offset = 0 ) {
6682
6683		const te = this.elements;
6684
6685		array[ offset ] = te[ 0 ];
6686		array[ offset + 1 ] = te[ 1 ];
6687		array[ offset + 2 ] = te[ 2 ];
6688		array[ offset + 3 ] = te[ 3 ];
6689
6690		array[ offset + 4 ] = te[ 4 ];
6691		array[ offset + 5 ] = te[ 5 ];
6692		array[ offset + 6 ] = te[ 6 ];
6693		array[ offset + 7 ] = te[ 7 ];
6694
6695		array[ offset + 8 ] = te[ 8 ];
6696		array[ offset + 9 ] = te[ 9 ];
6697		array[ offset + 10 ] = te[ 10 ];
6698		array[ offset + 11 ] = te[ 11 ];
6699
6700		array[ offset + 12 ] = te[ 12 ];
6701		array[ offset + 13 ] = te[ 13 ];
6702		array[ offset + 14 ] = te[ 14 ];
6703		array[ offset + 15 ] = te[ 15 ];
6704
6705		return array;
6706
6707	}
6708
6709}
6710
6711const _v1$5 = /*@__PURE__*/ new Vector3();
6712const _m1$4 = /*@__PURE__*/ new Matrix4();
6713const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
6714const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
6715const _x = /*@__PURE__*/ new Vector3();
6716const _y = /*@__PURE__*/ new Vector3();
6717const _z = /*@__PURE__*/ new Vector3();
6718
6719const _matrix$2 = /*@__PURE__*/ new Matrix4();
6720const _quaternion$3 = /*@__PURE__*/ new Quaternion();
6721
6722class Euler {
6723
6724	constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) {
6725
6726		this.isEuler = true;
6727
6728		this._x = x;
6729		this._y = y;
6730		this._z = z;
6731		this._order = order;
6732
6733	}
6734
6735	get x() {
6736
6737		return this._x;
6738
6739	}
6740
6741	set x( value ) {
6742
6743		this._x = value;
6744		this._onChangeCallback();
6745
6746	}
6747
6748	get y() {
6749
6750		return this._y;
6751
6752	}
6753
6754	set y( value ) {
6755
6756		this._y = value;
6757		this._onChangeCallback();
6758
6759	}
6760
6761	get z() {
6762
6763		return this._z;
6764
6765	}
6766
6767	set z( value ) {
6768
6769		this._z = value;
6770		this._onChangeCallback();
6771
6772	}
6773
6774	get order() {
6775
6776		return this._order;
6777
6778	}
6779
6780	set order( value ) {
6781
6782		this._order = value;
6783		this._onChangeCallback();
6784
6785	}
6786
6787	set( x, y, z, order = this._order ) {
6788
6789		this._x = x;
6790		this._y = y;
6791		this._z = z;
6792		this._order = order;
6793
6794		this._onChangeCallback();
6795
6796		return this;
6797
6798	}
6799
6800	clone() {
6801
6802		return new this.constructor( this._x, this._y, this._z, this._order );
6803
6804	}
6805
6806	copy( euler ) {
6807
6808		this._x = euler._x;
6809		this._y = euler._y;
6810		this._z = euler._z;
6811		this._order = euler._order;
6812
6813		this._onChangeCallback();
6814
6815		return this;
6816
6817	}
6818
6819	setFromRotationMatrix( m, order = this._order, update = true ) {
6820
6821		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6822
6823		const te = m.elements;
6824		const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
6825		const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
6826		const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
6827
6828		switch ( order ) {
6829
6830			case 'XYZ':
6831
6832				this._y = Math.asin( clamp( m13, - 1, 1 ) );
6833
6834				if ( Math.abs( m13 ) < 0.9999999 ) {
6835
6836					this._x = Math.atan2( - m23, m33 );
6837					this._z = Math.atan2( - m12, m11 );
6838
6839				} else {
6840
6841					this._x = Math.atan2( m32, m22 );
6842					this._z = 0;
6843
6844				}
6845
6846				break;
6847
6848			case 'YXZ':
6849
6850				this._x = Math.asin( - clamp( m23, - 1, 1 ) );
6851
6852				if ( Math.abs( m23 ) < 0.9999999 ) {
6853
6854					this._y = Math.atan2( m13, m33 );
6855					this._z = Math.atan2( m21, m22 );
6856
6857				} else {
6858
6859					this._y = Math.atan2( - m31, m11 );
6860					this._z = 0;
6861
6862				}
6863
6864				break;
6865
6866			case 'ZXY':
6867
6868				this._x = Math.asin( clamp( m32, - 1, 1 ) );
6869
6870				if ( Math.abs( m32 ) < 0.9999999 ) {
6871
6872					this._y = Math.atan2( - m31, m33 );
6873					this._z = Math.atan2( - m12, m22 );
6874
6875				} else {
6876
6877					this._y = 0;
6878					this._z = Math.atan2( m21, m11 );
6879
6880				}
6881
6882				break;
6883
6884			case 'ZYX':
6885
6886				this._y = Math.asin( - clamp( m31, - 1, 1 ) );
6887
6888				if ( Math.abs( m31 ) < 0.9999999 ) {
6889
6890					this._x = Math.atan2( m32, m33 );
6891					this._z = Math.atan2( m21, m11 );
6892
6893				} else {
6894
6895					this._x = 0;
6896					this._z = Math.atan2( - m12, m22 );
6897
6898				}
6899
6900				break;
6901
6902			case 'YZX':
6903
6904				this._z = Math.asin( clamp( m21, - 1, 1 ) );
6905
6906				if ( Math.abs( m21 ) < 0.9999999 ) {
6907
6908					this._x = Math.atan2( - m23, m22 );
6909					this._y = Math.atan2( - m31, m11 );
6910
6911				} else {
6912
6913					this._x = 0;
6914					this._y = Math.atan2( m13, m33 );
6915
6916				}
6917
6918				break;
6919
6920			case 'XZY':
6921
6922				this._z = Math.asin( - clamp( m12, - 1, 1 ) );
6923
6924				if ( Math.abs( m12 ) < 0.9999999 ) {
6925
6926					this._x = Math.atan2( m32, m22 );
6927					this._y = Math.atan2( m13, m11 );
6928
6929				} else {
6930
6931					this._x = Math.atan2( - m23, m33 );
6932					this._y = 0;
6933
6934				}
6935
6936				break;
6937
6938			default:
6939
6940				console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
6941
6942		}
6943
6944		this._order = order;
6945
6946		if ( update === true ) this._onChangeCallback();
6947
6948		return this;
6949
6950	}
6951
6952	setFromQuaternion( q, order, update ) {
6953
6954		_matrix$2.makeRotationFromQuaternion( q );
6955
6956		return this.setFromRotationMatrix( _matrix$2, order, update );
6957
6958	}
6959
6960	setFromVector3( v, order = this._order ) {
6961
6962		return this.set( v.x, v.y, v.z, order );
6963
6964	}
6965
6966	reorder( newOrder ) {
6967
6968		// WARNING: this discards revolution information -bhouston
6969
6970		_quaternion$3.setFromEuler( this );
6971
6972		return this.setFromQuaternion( _quaternion$3, newOrder );
6973
6974	}
6975
6976	equals( euler ) {
6977
6978		return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
6979
6980	}
6981
6982	fromArray( array ) {
6983
6984		this._x = array[ 0 ];
6985		this._y = array[ 1 ];
6986		this._z = array[ 2 ];
6987		if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
6988
6989		this._onChangeCallback();
6990
6991		return this;
6992
6993	}
6994
6995	toArray( array = [], offset = 0 ) {
6996
6997		array[ offset ] = this._x;
6998		array[ offset + 1 ] = this._y;
6999		array[ offset + 2 ] = this._z;
7000		array[ offset + 3 ] = this._order;
7001
7002		return array;
7003
7004	}
7005
7006	_onChange( callback ) {
7007
7008		this._onChangeCallback = callback;
7009
7010		return this;
7011
7012	}
7013
7014	_onChangeCallback() {}
7015
7016	*[ Symbol.iterator ]() {
7017
7018		yield this._x;
7019		yield this._y;
7020		yield this._z;
7021		yield this._order;
7022
7023	}
7024
7025}
7026
7027Euler.DEFAULT_ORDER = 'XYZ';
7028
7029class Layers {
7030
7031	constructor() {
7032
7033		this.mask = 1 | 0;
7034
7035	}
7036
7037	set( channel ) {
7038
7039		this.mask = ( 1 << channel | 0 ) >>> 0;
7040
7041	}
7042
7043	enable( channel ) {
7044
7045		this.mask |= 1 << channel | 0;
7046
7047	}
7048
7049	enableAll() {
7050
7051		this.mask = 0xffffffff | 0;
7052
7053	}
7054
7055	toggle( channel ) {
7056
7057		this.mask ^= 1 << channel | 0;
7058
7059	}
7060
7061	disable( channel ) {
7062
7063		this.mask &= ~ ( 1 << channel | 0 );
7064
7065	}
7066
7067	disableAll() {
7068
7069		this.mask = 0;
7070
7071	}
7072
7073	test( layers ) {
7074
7075		return ( this.mask & layers.mask ) !== 0;
7076
7077	}
7078
7079	isEnabled( channel ) {
7080
7081		return ( this.mask & ( 1 << channel | 0 ) ) !== 0;
7082
7083	}
7084
7085}
7086
7087let _object3DId = 0;
7088
7089const _v1$4 = /*@__PURE__*/ new Vector3();
7090const _q1 = /*@__PURE__*/ new Quaternion();
7091const _m1$3 = /*@__PURE__*/ new Matrix4();
7092const _target = /*@__PURE__*/ new Vector3();
7093
7094const _position$3 = /*@__PURE__*/ new Vector3();
7095const _scale$2 = /*@__PURE__*/ new Vector3();
7096const _quaternion$2 = /*@__PURE__*/ new Quaternion();
7097
7098const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
7099const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
7100const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
7101
7102const _addedEvent = { type: 'added' };
7103const _removedEvent = { type: 'removed' };
7104
7105const _childaddedEvent = { type: 'childadded', child: null };
7106const _childremovedEvent = { type: 'childremoved', child: null };
7107
vendor: 7,170 bytes, lines 7108-7516
7108class Object3D extends EventDispatcher {
7109
7110	constructor() {
7111
7112		super();
7113
7114		this.isObject3D = true;
7115
7116		Object.defineProperty( this, 'id', { value: _object3DId ++ } );
7117
7118		this.uuid = generateUUID();
7119
7120		this.name = '';
7121		this.type = 'Object3D';
7122
7123		this.parent = null;
7124		this.children = [];
7125
7126		this.up = Object3D.DEFAULT_UP.clone();
7127
7128		const position = new Vector3();
7129		const rotation = new Euler();
7130		const quaternion = new Quaternion();
7131		const scale = new Vector3( 1, 1, 1 );
7132
7133		function onRotationChange() {
7134
7135			quaternion.setFromEuler( rotation, false );
7136
7137		}
7138
7139		function onQuaternionChange() {
7140
7141			rotation.setFromQuaternion( quaternion, undefined, false );
7142
7143		}
7144
7145		rotation._onChange( onRotationChange );
7146		quaternion._onChange( onQuaternionChange );
7147
7148		Object.defineProperties( this, {
7149			position: {
7150				configurable: true,
7151				enumerable: true,
7152				value: position
7153			},
7154			rotation: {
7155				configurable: true,
7156				enumerable: true,
7157				value: rotation
7158			},
7159			quaternion: {
7160				configurable: true,
7161				enumerable: true,
7162				value: quaternion
7163			},
7164			scale: {
7165				configurable: true,
7166				enumerable: true,
7167				value: scale
7168			},
7169			modelViewMatrix: {
7170				value: new Matrix4()
7171			},
7172			normalMatrix: {
7173				value: new Matrix3()
7174			}
7175		} );
7176
7177		this.matrix = new Matrix4();
7178		this.matrixWorld = new Matrix4();
7179
7180		this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
7181
7182		this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
7183		this.matrixWorldNeedsUpdate = false;
7184
7185		this.layers = new Layers();
7186		this.visible = true;
7187
7188		this.castShadow = false;
7189		this.receiveShadow = false;
7190
7191		this.frustumCulled = true;
7192		this.renderOrder = 0;
7193
7194		this.animations = [];
7195
7196		this.userData = {};
7197
7198	}
7199
7200	onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
7201
7202	onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
7203
7204	onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
7205
7206	onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
7207
7208	applyMatrix4( matrix ) {
7209
7210		if ( this.matrixAutoUpdate ) this.updateMatrix();
7211
7212		this.matrix.premultiply( matrix );
7213
7214		this.matrix.decompose( this.position, this.quaternion, this.scale );
7215
7216	}
7217
7218	applyQuaternion( q ) {
7219
7220		this.quaternion.premultiply( q );
7221
7222		return this;
7223
7224	}
7225
7226	setRotationFromAxisAngle( axis, angle ) {
7227
7228		// assumes axis is normalized
7229
7230		this.quaternion.setFromAxisAngle( axis, angle );
7231
7232	}
7233
7234	setRotationFromEuler( euler ) {
7235
7236		this.quaternion.setFromEuler( euler, true );
7237
7238	}
7239
7240	setRotationFromMatrix( m ) {
7241
7242		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7243
7244		this.quaternion.setFromRotationMatrix( m );
7245
7246	}
7247
7248	setRotationFromQuaternion( q ) {
7249
7250		// assumes q is normalized
7251
7252		this.quaternion.copy( q );
7253
7254	}
7255
7256	rotateOnAxis( axis, angle ) {
7257
7258		// rotate object on axis in object space
7259		// axis is assumed to be normalized
7260
7261		_q1.setFromAxisAngle( axis, angle );
7262
7263		this.quaternion.multiply( _q1 );
7264
7265		return this;
7266
7267	}
7268
7269	rotateOnWorldAxis( axis, angle ) {
7270
7271		// rotate object on axis in world space
7272		// axis is assumed to be normalized
7273		// method assumes no rotated parent
7274
7275		_q1.setFromAxisAngle( axis, angle );
7276
7277		this.quaternion.premultiply( _q1 );
7278
7279		return this;
7280
7281	}
7282
7283	rotateX( angle ) {
7284
7285		return this.rotateOnAxis( _xAxis, angle );
7286
7287	}
7288
7289	rotateY( angle ) {
7290
7291		return this.rotateOnAxis( _yAxis, angle );
7292
7293	}
7294
7295	rotateZ( angle ) {
7296
7297		return this.rotateOnAxis( _zAxis, angle );
7298
7299	}
7300
7301	translateOnAxis( axis, distance ) {
7302
7303		// translate object by distance along axis in object space
7304		// axis is assumed to be normalized
7305
7306		_v1$4.copy( axis ).applyQuaternion( this.quaternion );
7307
7308		this.position.add( _v1$4.multiplyScalar( distance ) );
7309
7310		return this;
7311
7312	}
7313
7314	translateX( distance ) {
7315
7316		return this.translateOnAxis( _xAxis, distance );
7317
7318	}
7319
7320	translateY( distance ) {
7321
7322		return this.translateOnAxis( _yAxis, distance );
7323
7324	}
7325
7326	translateZ( distance ) {
7327
7328		return this.translateOnAxis( _zAxis, distance );
7329
7330	}
7331
7332	localToWorld( vector ) {
7333
7334		this.updateWorldMatrix( true, false );
7335
7336		return vector.applyMatrix4( this.matrixWorld );
7337
7338	}
7339
7340	worldToLocal( vector ) {
7341
7342		this.updateWorldMatrix( true, false );
7343
7344		return vector.applyMatrix4( _m1$3.copy( this.matrixWorld ).invert() );
7345
7346	}
7347
7348	lookAt( x, y, z ) {
7349
7350		// This method does not support objects having non-uniformly-scaled parent(s)
7351
7352		if ( x.isVector3 ) {
7353
7354			_target.copy( x );
7355
7356		} else {
7357
7358			_target.set( x, y, z );
7359
7360		}
7361
7362		const parent = this.parent;
7363
7364		this.updateWorldMatrix( true, false );
7365
7366		_position$3.setFromMatrixPosition( this.matrixWorld );
7367
7368		if ( this.isCamera || this.isLight ) {
7369
7370			_m1$3.lookAt( _position$3, _target, this.up );
7371
7372		} else {
7373
7374			_m1$3.lookAt( _target, _position$3, this.up );
7375
7376		}
7377
7378		this.quaternion.setFromRotationMatrix( _m1$3 );
7379
7380		if ( parent ) {
7381
7382			_m1$3.extractRotation( parent.matrixWorld );
7383			_q1.setFromRotationMatrix( _m1$3 );
7384			this.quaternion.premultiply( _q1.invert() );
7385
7386		}
7387
7388	}
7389
7390	add( object ) {
7391
7392		if ( arguments.length > 1 ) {
7393
7394			for ( let i = 0; i < arguments.length; i ++ ) {
7395
7396				this.add( arguments[ i ] );
7397
7398			}
7399
7400			return this;
7401
7402		}
7403
7404		if ( object === this ) {
7405
7406			console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
7407			return this;
7408
7409		}
7410
7411		if ( object && object.isObject3D ) {
7412
7413			object.removeFromParent();
7414			object.parent = this;
7415			this.children.push( object );
7416
7417			object.dispatchEvent( _addedEvent );
7418
7419			_childaddedEvent.child = object;
7420			this.dispatchEvent( _childaddedEvent );
7421			_childaddedEvent.child = null;
7422
7423		} else {
7424
7425			console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
7426
7427		}
7428
7429		return this;
7430
7431	}
7432
7433	remove( object ) {
7434
7435		if ( arguments.length > 1 ) {
7436
7437			for ( let i = 0; i < arguments.length; i ++ ) {
7438
7439				this.remove( arguments[ i ] );
7440
7441			}
7442
7443			return this;
7444
7445		}
7446
7447		const index = this.children.indexOf( object );
7448
7449		if ( index !== - 1 ) {
7450
7451			object.parent = null;
7452			this.children.splice( index, 1 );
7453
7454			object.dispatchEvent( _removedEvent );
7455
7456			_childremovedEvent.child = object;
7457			this.dispatchEvent( _childremovedEvent );
7458			_childremovedEvent.child = null;
7459
7460		}
7461
7462		return this;
7463
7464	}
7465
7466	removeFromParent() {
7467
7468		const parent = this.parent;
7469
7470		if ( parent !== null ) {
7471
7472			parent.remove( this );
7473
7474		}
7475
7476		return this;
7477
7478	}
7479
7480	clear() {
7481
7482		return this.remove( ... this.children );
7483
7484	}
7485
7486	attach( object ) {
7487
7488		// adds object as a child of this, while maintaining the object's world transform
7489
7490		// Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
7491
7492		this.updateWorldMatrix( true, false );
7493
7494		_m1$3.copy( this.matrixWorld ).invert();
7495
7496		if ( object.parent !== null ) {
7497
7498			object.parent.updateWorldMatrix( true, false );
7499
7500			_m1$3.multiply( object.parent.matrixWorld );
7501
7502		}
7503
7504		object.applyMatrix4( _m1$3 );
7505
7506		object.removeFromParent();
7507		object.parent = this;
7508		this.children.push( object );
7509
7510		object.updateWorldMatrix( false, true );
7511
7512		object.dispatchEvent( _addedEvent );
7513
7514		_childaddedEvent.child = object;
7515		this.dispatchEvent( _childaddedEvent );
7516		_childaddedEvent.child = null
vendor: 23,035 bytes, lines 7516-8532
7516;
7517
7518		return this;
7519
7520	}
7521
7522	getObjectById( id ) {
7523
7524		return this.getObjectByProperty( 'id', id );
7525
7526	}
7527
7528	getObjectByName( name ) {
7529
7530		return this.getObjectByProperty( 'name', name );
7531
7532	}
7533
7534	getObjectByProperty( name, value ) {
7535
7536		if ( this[ name ] === value ) return this;
7537
7538		for ( let i = 0, l = this.children.length; i < l; i ++ ) {
7539
7540			const child = this.children[ i ];
7541			const object = child.getObjectByProperty( name, value );
7542
7543			if ( object !== undefined ) {
7544
7545				return object;
7546
7547			}
7548
7549		}
7550
7551		return undefined;
7552
7553	}
7554
7555	getObjectsByProperty( name, value, result = [] ) {
7556
7557		if ( this[ name ] === value ) result.push( this );
7558
7559		const children = this.children;
7560
7561		for ( let i = 0, l = children.length; i < l; i ++ ) {
7562
7563			children[ i ].getObjectsByProperty( name, value, result );
7564
7565		}
7566
7567		return result;
7568
7569	}
7570
7571	getWorldPosition( target ) {
7572
7573		this.updateWorldMatrix( true, false );
7574
7575		return target.setFromMatrixPosition( this.matrixWorld );
7576
7577	}
7578
7579	getWorldQuaternion( target ) {
7580
7581		this.updateWorldMatrix( true, false );
7582
7583		this.matrixWorld.decompose( _position$3, target, _scale$2 );
7584
7585		return target;
7586
7587	}
7588
7589	getWorldScale( target ) {
7590
7591		this.updateWorldMatrix( true, false );
7592
7593		this.matrixWorld.decompose( _position$3, _quaternion$2, target );
7594
7595		return target;
7596
7597	}
7598
7599	getWorldDirection( target ) {
7600
7601		this.updateWorldMatrix( true, false );
7602
7603		const e = this.matrixWorld.elements;
7604
7605		return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
7606
7607	}
7608
7609	raycast( /* raycaster, intersects */ ) {}
7610
7611	traverse( callback ) {
7612
7613		callback( this );
7614
7615		const children = this.children;
7616
7617		for ( let i = 0, l = children.length; i < l; i ++ ) {
7618
7619			children[ i ].traverse( callback );
7620
7621		}
7622
7623	}
7624
7625	traverseVisible( callback ) {
7626
7627		if ( this.visible === false ) return;
7628
7629		callback( this );
7630
7631		const children = this.children;
7632
7633		for ( let i = 0, l = children.length; i < l; i ++ ) {
7634
7635			children[ i ].traverseVisible( callback );
7636
7637		}
7638
7639	}
7640
7641	traverseAncestors( callback ) {
7642
7643		const parent = this.parent;
7644
7645		if ( parent !== null ) {
7646
7647			callback( parent );
7648
7649			parent.traverseAncestors( callback );
7650
7651		}
7652
7653	}
7654
7655	updateMatrix() {
7656
7657		this.matrix.compose( this.position, this.quaternion, this.scale );
7658
7659		this.matrixWorldNeedsUpdate = true;
7660
7661	}
7662
7663	updateMatrixWorld( force ) {
7664
7665		if ( this.matrixAutoUpdate ) this.updateMatrix();
7666
7667		if ( this.matrixWorldNeedsUpdate || force ) {
7668
7669			if ( this.parent === null ) {
7670
7671				this.matrixWorld.copy( this.matrix );
7672
7673			} else {
7674
7675				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
7676
7677			}
7678
7679			this.matrixWorldNeedsUpdate = false;
7680
7681			force = true;
7682
7683		}
7684
7685		// update children
7686
7687		const children = this.children;
7688
7689		for ( let i = 0, l = children.length; i < l; i ++ ) {
7690
7691			const child = children[ i ];
7692
7693			if ( child.matrixWorldAutoUpdate === true || force === true ) {
7694
7695				child.updateMatrixWorld( force );
7696
7697			}
7698
7699		}
7700
7701	}
7702
7703	updateWorldMatrix( updateParents, updateChildren ) {
7704
7705		const parent = this.parent;
7706
7707		if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) {
7708
7709			parent.updateWorldMatrix( true, false );
7710
7711		}
7712
7713		if ( this.matrixAutoUpdate ) this.updateMatrix();
7714
7715		if ( this.parent === null ) {
7716
7717			this.matrixWorld.copy( this.matrix );
7718
7719		} else {
7720
7721			this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
7722
7723		}
7724
7725		// update children
7726
7727		if ( updateChildren === true ) {
7728
7729			const children = this.children;
7730
7731			for ( let i = 0, l = children.length; i < l; i ++ ) {
7732
7733				const child = children[ i ];
7734
7735				if ( child.matrixWorldAutoUpdate === true ) {
7736
7737					child.updateWorldMatrix( false, true );
7738
7739				}
7740
7741			}
7742
7743		}
7744
7745	}
7746
7747	toJSON( meta ) {
7748
7749		// meta is a string when called from JSON.stringify
7750		const isRootObject = ( meta === undefined || typeof meta === 'string' );
7751
7752		const output = {};
7753
7754		// meta is a hash used to collect geometries, materials.
7755		// not providing it implies that this is the root object
7756		// being serialized.
7757		if ( isRootObject ) {
7758
7759			// initialize meta obj
7760			meta = {
7761				geometries: {},
7762				materials: {},
7763				textures: {},
7764				images: {},
7765				shapes: {},
7766				skeletons: {},
7767				animations: {},
7768				nodes: {}
7769			};
7770
7771			output.metadata = {
7772				version: 4.6,
7773				type: 'Object',
7774				generator: 'Object3D.toJSON'
7775			};
7776
7777		}
7778
7779		// standard Object3D serialization
7780
7781		const object = {};
7782
7783		object.uuid = this.uuid;
7784		object.type = this.type;
7785
7786		if ( this.name !== '' ) object.name = this.name;
7787		if ( this.castShadow === true ) object.castShadow = true;
7788		if ( this.receiveShadow === true ) object.receiveShadow = true;
7789		if ( this.visible === false ) object.visible = false;
7790		if ( this.frustumCulled === false ) object.frustumCulled = false;
7791		if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
7792		if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
7793
7794		object.layers = this.layers.mask;
7795		object.matrix = this.matrix.toArray();
7796		object.up = this.up.toArray();
7797
7798		if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
7799
7800		// object specific properties
7801
7802		if ( this.isInstancedMesh ) {
7803
7804			object.type = 'InstancedMesh';
7805			object.count = this.count;
7806			object.instanceMatrix = this.instanceMatrix.toJSON();
7807			if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
7808
7809		}
7810
7811		if ( this.isBatchedMesh ) {
7812
7813			object.type = 'BatchedMesh';
7814			object.perObjectFrustumCulled = this.perObjectFrustumCulled;
7815			object.sortObjects = this.sortObjects;
7816
7817			object.drawRanges = this._drawRanges;
7818			object.reservedRanges = this._reservedRanges;
7819
7820			object.visibility = this._visibility;
7821			object.active = this._active;
7822			object.bounds = this._bounds.map( bound => ( {
7823				boxInitialized: bound.boxInitialized,
7824				boxMin: bound.box.min.toArray(),
7825				boxMax: bound.box.max.toArray(),
7826
7827				sphereInitialized: bound.sphereInitialized,
7828				sphereRadius: bound.sphere.radius,
7829				sphereCenter: bound.sphere.center.toArray()
7830			} ) );
7831
7832			object.maxGeometryCount = this._maxGeometryCount;
7833			object.maxVertexCount = this._maxVertexCount;
7834			object.maxIndexCount = this._maxIndexCount;
7835
7836			object.geometryInitialized = this._geometryInitialized;
7837			object.geometryCount = this._geometryCount;
7838
7839			object.matricesTexture = this._matricesTexture.toJSON( meta );
7840
7841			if ( this.boundingSphere !== null ) {
7842
7843				object.boundingSphere = {
7844					center: object.boundingSphere.center.toArray(),
7845					radius: object.boundingSphere.radius
7846				};
7847
7848			}
7849
7850			if ( this.boundingBox !== null ) {
7851
7852				object.boundingBox = {
7853					min: object.boundingBox.min.toArray(),
7854					max: object.boundingBox.max.toArray()
7855				};
7856
7857			}
7858
7859		}
7860
7861		//
7862
7863		function serialize( library, element ) {
7864
7865			if ( library[ element.uuid ] === undefined ) {
7866
7867				library[ element.uuid ] = element.toJSON( meta );
7868
7869			}
7870
7871			return element.uuid;
7872
7873		}
7874
7875		if ( this.isScene ) {
7876
7877			if ( this.background ) {
7878
7879				if ( this.background.isColor ) {
7880
7881					object.background = this.background.toJSON();
7882
7883				} else if ( this.background.isTexture ) {
7884
7885					object.background = this.background.toJSON( meta ).uuid;
7886
7887				}
7888
7889			}
7890
7891			if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
7892
7893				object.environment = this.environment.toJSON( meta ).uuid;
7894
7895			}
7896
7897		} else if ( this.isMesh || this.isLine || this.isPoints ) {
7898
7899			object.geometry = serialize( meta.geometries, this.geometry );
7900
7901			const parameters = this.geometry.parameters;
7902
7903			if ( parameters !== undefined && parameters.shapes !== undefined ) {
7904
7905				const shapes = parameters.shapes;
7906
7907				if ( Array.isArray( shapes ) ) {
7908
7909					for ( let i = 0, l = shapes.length; i < l; i ++ ) {
7910
7911						const shape = shapes[ i ];
7912
7913						serialize( meta.shapes, shape );
7914
7915					}
7916
7917				} else {
7918
7919					serialize( meta.shapes, shapes );
7920
7921				}
7922
7923			}
7924
7925		}
7926
7927		if ( this.isSkinnedMesh ) {
7928
7929			object.bindMode = this.bindMode;
7930			object.bindMatrix = this.bindMatrix.toArray();
7931
7932			if ( this.skeleton !== undefined ) {
7933
7934				serialize( meta.skeletons, this.skeleton );
7935
7936				object.skeleton = this.skeleton.uuid;
7937
7938			}
7939
7940		}
7941
7942		if ( this.material !== undefined ) {
7943
7944			if ( Array.isArray( this.material ) ) {
7945
7946				const uuids = [];
7947
7948				for ( let i = 0, l = this.material.length; i < l; i ++ ) {
7949
7950					uuids.push( serialize( meta.materials, this.material[ i ] ) );
7951
7952				}
7953
7954				object.material = uuids;
7955
7956			} else {
7957
7958				object.material = serialize( meta.materials, this.material );
7959
7960			}
7961
7962		}
7963
7964		//
7965
7966		if ( this.children.length > 0 ) {
7967
7968			object.children = [];
7969
7970			for ( let i = 0; i < this.children.length; i ++ ) {
7971
7972				object.children.push( this.children[ i ].toJSON( meta ).object );
7973
7974			}
7975
7976		}
7977
7978		//
7979
7980		if ( this.animations.length > 0 ) {
7981
7982			object.animations = [];
7983
7984			for ( let i = 0; i < this.animations.length; i ++ ) {
7985
7986				const animation = this.animations[ i ];
7987
7988				object.animations.push( serialize( meta.animations, animation ) );
7989
7990			}
7991
7992		}
7993
7994		if ( isRootObject ) {
7995
7996			const geometries = extractFromCache( meta.geometries );
7997			const materials = extractFromCache( meta.materials );
7998			const textures = extractFromCache( meta.textures );
7999			const images = extractFromCache( meta.images );
8000			const shapes = extractFromCache( meta.shapes );
8001			const skeletons = extractFromCache( meta.skeletons );
8002			const animations = extractFromCache( meta.animations );
8003			const nodes = extractFromCache( meta.nodes );
8004
8005			if ( geometries.length > 0 ) output.geometries = geometries;
8006			if ( materials.length > 0 ) output.materials = materials;
8007			if ( textures.length > 0 ) output.textures = textures;
8008			if ( images.length > 0 ) output.images = images;
8009			if ( shapes.length > 0 ) output.shapes = shapes;
8010			if ( skeletons.length > 0 ) output.skeletons = skeletons;
8011			if ( animations.length > 0 ) output.animations = animations;
8012			if ( nodes.length > 0 ) output.nodes = nodes;
8013
8014		}
8015
8016		output.object = object;
8017
8018		return output;
8019
8020		// extract data from the cache hash
8021		// remove metadata on each item
8022		// and return as array
8023		function extractFromCache( cache ) {
8024
8025			const values = [];
8026			for ( const key in cache ) {
8027
8028				const data = cache[ key ];
8029				delete data.metadata;
8030				values.push( data );
8031
8032			}
8033
8034			return values;
8035
8036		}
8037
8038	}
8039
8040	clone( recursive ) {
8041
8042		return new this.constructor().copy( this, recursive );
8043
8044	}
8045
8046	copy( source, recursive = true ) {
8047
8048		this.name = source.name;
8049
8050		this.up.copy( source.up );
8051
8052		this.position.copy( source.position );
8053		this.rotation.order = source.rotation.order;
8054		this.quaternion.copy( source.quaternion );
8055		this.scale.copy( source.scale );
8056
8057		this.matrix.copy( source.matrix );
8058		this.matrixWorld.copy( source.matrixWorld );
8059
8060		this.matrixAutoUpdate = source.matrixAutoUpdate;
8061
8062		this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
8063		this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
8064
8065		this.layers.mask = source.layers.mask;
8066		this.visible = source.visible;
8067
8068		this.castShadow = source.castShadow;
8069		this.receiveShadow = source.receiveShadow;
8070
8071		this.frustumCulled = source.frustumCulled;
8072		this.renderOrder = source.renderOrder;
8073
8074		this.animations = source.animations.slice();
8075
8076		this.userData = JSON.parse( JSON.stringify( source.userData ) );
8077
8078		if ( recursive === true ) {
8079
8080			for ( let i = 0; i < source.children.length; i ++ ) {
8081
8082				const child = source.children[ i ];
8083				this.add( child.clone() );
8084
8085			}
8086
8087		}
8088
8089		return this;
8090
8091	}
8092
8093}
8094
8095Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
8096Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
8097Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
8098
8099const _v0$1 = /*@__PURE__*/ new Vector3();
8100const _v1$3 = /*@__PURE__*/ new Vector3();
8101const _v2$2 = /*@__PURE__*/ new Vector3();
8102const _v3$2 = /*@__PURE__*/ new Vector3();
8103
8104const _vab = /*@__PURE__*/ new Vector3();
8105const _vac = /*@__PURE__*/ new Vector3();
8106const _vbc = /*@__PURE__*/ new Vector3();
8107const _vap = /*@__PURE__*/ new Vector3();
8108const _vbp = /*@__PURE__*/ new Vector3();
8109const _vcp = /*@__PURE__*/ new Vector3();
8110
8111class Triangle {
8112
8113	constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) {
8114
8115		this.a = a;
8116		this.b = b;
8117		this.c = c;
8118
8119	}
8120
8121	static getNormal( a, b, c, target ) {
8122
8123		target.subVectors( c, b );
8124		_v0$1.subVectors( a, b );
8125		target.cross( _v0$1 );
8126
8127		const targetLengthSq = target.lengthSq();
8128		if ( targetLengthSq > 0 ) {
8129
8130			return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
8131
8132		}
8133
8134		return target.set( 0, 0, 0 );
8135
8136	}
8137
8138	// static/instance method to calculate barycentric coordinates
8139	// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
8140	static getBarycoord( point, a, b, c, target ) {
8141
8142		_v0$1.subVectors( c, a );
8143		_v1$3.subVectors( b, a );
8144		_v2$2.subVectors( point, a );
8145
8146		const dot00 = _v0$1.dot( _v0$1 );
8147		const dot01 = _v0$1.dot( _v1$3 );
8148		const dot02 = _v0$1.dot( _v2$2 );
8149		const dot11 = _v1$3.dot( _v1$3 );
8150		const dot12 = _v1$3.dot( _v2$2 );
8151
8152		const denom = ( dot00 * dot11 - dot01 * dot01 );
8153
8154		// collinear or singular triangle
8155		if ( denom === 0 ) {
8156
8157			target.set( 0, 0, 0 );
8158			return null;
8159
8160		}
8161
8162		const invDenom = 1 / denom;
8163		const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
8164		const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
8165
8166		// barycentric coordinates must always sum to 1
8167		return target.set( 1 - u - v, v, u );
8168
8169	}
8170
8171	static containsPoint( point, a, b, c ) {
8172
8173		// if the triangle is degenerate then we can't contain a point
8174		if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) {
8175
8176			return false;
8177
8178		}
8179
8180		return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 );
8181
8182	}
8183
8184	static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) {
8185
8186		if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) {
8187
8188			target.x = 0;
8189			target.y = 0;
8190			if ( 'z' in target ) target.z = 0;
8191			if ( 'w' in target ) target.w = 0;
8192			return null;
8193
8194		}
8195
8196		target.setScalar( 0 );
8197		target.addScaledVector( v1, _v3$2.x );
8198		target.addScaledVector( v2, _v3$2.y );
8199		target.addScaledVector( v3, _v3$2.z );
8200
8201		return target;
8202
8203	}
8204
8205	static isFrontFacing( a, b, c, direction ) {
8206
8207		_v0$1.subVectors( c, b );
8208		_v1$3.subVectors( a, b );
8209
8210		// strictly front facing
8211		return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
8212
8213	}
8214
8215	set( a, b, c ) {
8216
8217		this.a.copy( a );
8218		this.b.copy( b );
8219		this.c.copy( c );
8220
8221		return this;
8222
8223	}
8224
8225	setFromPointsAndIndices( points, i0, i1, i2 ) {
8226
8227		this.a.copy( points[ i0 ] );
8228		this.b.copy( points[ i1 ] );
8229		this.c.copy( points[ i2 ] );
8230
8231		return this;
8232
8233	}
8234
8235	setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
8236
8237		this.a.fromBufferAttribute( attribute, i0 );
8238		this.b.fromBufferAttribute( attribute, i1 );
8239		this.c.fromBufferAttribute( attribute, i2 );
8240
8241		return this;
8242
8243	}
8244
8245	clone() {
8246
8247		return new this.constructor().copy( this );
8248
8249	}
8250
8251	copy( triangle ) {
8252
8253		this.a.copy( triangle.a );
8254		this.b.copy( triangle.b );
8255		this.c.copy( triangle.c );
8256
8257		return this;
8258
8259	}
8260
8261	getArea() {
8262
8263		_v0$1.subVectors( this.c, this.b );
8264		_v1$3.subVectors( this.a, this.b );
8265
8266		return _v0$1.cross( _v1$3 ).length() * 0.5;
8267
8268	}
8269
8270	getMidpoint( target ) {
8271
8272		return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
8273
8274	}
8275
8276	getNormal( target ) {
8277
8278		return Triangle.getNormal( this.a, this.b, this.c, target );
8279
8280	}
8281
8282	getPlane( target ) {
8283
8284		return target.setFromCoplanarPoints( this.a, this.b, this.c );
8285
8286	}
8287
8288	getBarycoord( point, target ) {
8289
8290		return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
8291
8292	}
8293
8294	getInterpolation( point, v1, v2, v3, target ) {
8295
8296		return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target );
8297
8298	}
8299
8300	containsPoint( point ) {
8301
8302		return Triangle.containsPoint( point, this.a, this.b, this.c );
8303
8304	}
8305
8306	isFrontFacing( direction ) {
8307
8308		return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
8309
8310	}
8311
8312	intersectsBox( box ) {
8313
8314		return box.intersectsTriangle( this );
8315
8316	}
8317
8318	closestPointToPoint( p, target ) {
8319
8320		const a = this.a, b = this.b, c = this.c;
8321		let v, w;
8322
8323		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
8324		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
8325		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
8326		// basically, we're distinguishing which of the voronoi regions of the triangle
8327		// the point lies in with the minimum amount of redundant computation.
8328
8329		_vab.subVectors( b, a );
8330		_vac.subVectors( c, a );
8331		_vap.subVectors( p, a );
8332		const d1 = _vab.dot( _vap );
8333		const d2 = _vac.dot( _vap );
8334		if ( d1 <= 0 && d2 <= 0 ) {
8335
8336			// vertex region of A; barycentric coords (1, 0, 0)
8337			return target.copy( a );
8338
8339		}
8340
8341		_vbp.subVectors( p, b );
8342		const d3 = _vab.dot( _vbp );
8343		const d4 = _vac.dot( _vbp );
8344		if ( d3 >= 0 && d4 <= d3 ) {
8345
8346			// vertex region of B; barycentric coords (0, 1, 0)
8347			return target.copy( b );
8348
8349		}
8350
8351		const vc = d1 * d4 - d3 * d2;
8352		if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
8353
8354			v = d1 / ( d1 - d3 );
8355			// edge region of AB; barycentric coords (1-v, v, 0)
8356			return target.copy( a ).addScaledVector( _vab, v );
8357
8358		}
8359
8360		_vcp.subVectors( p, c );
8361		const d5 = _vab.dot( _vcp );
8362		const d6 = _vac.dot( _vcp );
8363		if ( d6 >= 0 && d5 <= d6 ) {
8364
8365			// vertex region of C; barycentric coords (0, 0, 1)
8366			return target.copy( c );
8367
8368		}
8369
8370		const vb = d5 * d2 - d1 * d6;
8371		if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
8372
8373			w = d2 / ( d2 - d6 );
8374			// edge region of AC; barycentric coords (1-w, 0, w)
8375			return target.copy( a ).addScaledVector( _vac, w );
8376
8377		}
8378
8379		const va = d3 * d6 - d5 * d4;
8380		if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
8381
8382			_vbc.subVectors( c, b );
8383			w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
8384			// edge region of BC; barycentric coords (0, 1-w, w)
8385			return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
8386
8387		}
8388
8389		// face region
8390		const denom = 1 / ( va + vb + vc );
8391		// u = va * denom
8392		v = vb * denom;
8393		w = vc * denom;
8394
8395		return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
8396
8397	}
8398
8399	equals( triangle ) {
8400
8401		return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
8402
8403	}
8404
8405}
8406
8407const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
8408	'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
8409	'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
8410	'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
8411	'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
8412	'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
8413	'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
8414	'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
8415	'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
8416	'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
8417	'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
8418	'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
8419	'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
8420	'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
8421	'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
8422	'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
8423	'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
8424	'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
8425	'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
8426	'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
8427	'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
8428	'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
8429	'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
8430	'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
8431
8432const _hslA = { h: 0, s: 0, l: 0 };
8433const _hslB = { h: 0, s: 0, l: 0 };
8434
8435function hue2rgb( p, q, t ) {
8436
8437	if ( t < 0 ) t += 1;
8438	if ( t > 1 ) t -= 1;
8439	if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
8440	if ( t < 1 / 2 ) return q;
8441	if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
8442	return p;
8443
8444}
8445
8446class Color {
8447
8448	constructor( r, g, b ) {
8449
8450		this.isColor = true;
8451
8452		this.r = 1;
8453		this.g = 1;
8454		this.b = 1;
8455
8456		return this.set( r, g, b );
8457
8458	}
8459
8460	set( r, g, b ) {
8461
8462		if ( g === undefined && b === undefined ) {
8463
8464			// r is THREE.Color, hex or string
8465
8466			const value = r;
8467
8468			if ( value && value.isColor ) {
8469
8470				this.copy( value );
8471
8472			} else if ( typeof value === 'number' ) {
8473
8474				this.setHex( value );
8475
8476			} else if ( typeof value === 'string' ) {
8477
8478				this.setStyle( value );
8479
8480			}
8481
8482		} else {
8483
8484			this.setRGB( r, g, b );
8485
8486		}
8487
8488		return this;
8489
8490	}
8491
8492	setScalar( scalar ) {
8493
8494		this.r = scalar;
8495		this.g = scalar;
8496		this.b = scalar;
8497
8498		return this;
8499
8500	}
8501
8502	setHex( hex, colorSpace = SRGBColorSpace ) {
8503
8504		hex = Math.floor( hex );
8505
8506		this.r = ( hex >> 16 & 255 ) / 255;
8507		this.g = ( hex >> 8 & 255 ) / 255;
8508		this.b = ( hex & 255 ) / 255;
8509
8510		ColorManagement.toWorkingColorSpace( this, colorSpace );
8511
8512		return this;
8513
8514	}
8515
8516	setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) {
8517
8518		this.r = r;
8519		this.g = g;
8520		this.b = b;
8521
8522		ColorManagement.toWorkingColorSpace( this, colorSpace );
8523
8524		return this;
8525
8526	}
8527
8528	setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) {
8529
8530		// h,s,l ranges are in 0.0 - 1.0
8531		h = euclideanModulo( h, 1 );
8532		s = clamp
vendor: 4,270 bytes, lines 8532-8765
8532( s, 0, 1 );
8533		l = clamp( l, 0, 1 );
8534
8535		if ( s === 0 ) {
8536
8537			this.r = this.g = this.b = l;
8538
8539		} else {
8540
8541			const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
8542			const q = ( 2 * l ) - p;
8543
8544			this.r = hue2rgb( q, p, h + 1 / 3 );
8545			this.g = hue2rgb( q, p, h );
8546			this.b = hue2rgb( q, p, h - 1 / 3 );
8547
8548		}
8549
8550		ColorManagement.toWorkingColorSpace( this, colorSpace );
8551
8552		return this;
8553
8554	}
8555
8556	setStyle( style, colorSpace = SRGBColorSpace ) {
8557
8558		function handleAlpha( string ) {
8559
8560			if ( string === undefined ) return;
8561
8562			if ( parseFloat( string ) < 1 ) {
8563
8564				console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
8565
8566			}
8567
8568		}
8569
8570
8571		let m;
8572
8573		if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) {
8574
8575			// rgb / hsl
8576
8577			let color;
8578			const name = m[ 1 ];
8579			const components = m[ 2 ];
8580
8581			switch ( name ) {
8582
8583				case 'rgb':
8584				case 'rgba':
8585
8586					if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8587
8588						// rgb(255,0,0) rgba(255,0,0,0.5)
8589
8590						handleAlpha( color[ 4 ] );
8591
8592						return this.setRGB(
8593							Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255,
8594							Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255,
8595							Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255,
8596							colorSpace
8597						);
8598
8599					}
8600
8601					if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8602
8603						// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
8604
8605						handleAlpha( color[ 4 ] );
8606
8607						return this.setRGB(
8608							Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100,
8609							Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100,
8610							Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100,
8611							colorSpace
8612						);
8613
8614					}
8615
8616					break;
8617
8618				case 'hsl':
8619				case 'hsla':
8620
8621					if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8622
8623						// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
8624
8625						handleAlpha( color[ 4 ] );
8626
8627						return this.setHSL(
8628							parseFloat( color[ 1 ] ) / 360,
8629							parseFloat( color[ 2 ] ) / 100,
8630							parseFloat( color[ 3 ] ) / 100,
8631							colorSpace
8632						);
8633
8634					}
8635
8636					break;
8637
8638				default:
8639
8640					console.warn( 'THREE.Color: Unknown color model ' + style );
8641
8642			}
8643
8644		} else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
8645
8646			// hex color
8647
8648			const hex = m[ 1 ];
8649			const size = hex.length;
8650
8651			if ( size === 3 ) {
8652
8653				// #ff0
8654				return this.setRGB(
8655					parseInt( hex.charAt( 0 ), 16 ) / 15,
8656					parseInt( hex.charAt( 1 ), 16 ) / 15,
8657					parseInt( hex.charAt( 2 ), 16 ) / 15,
8658					colorSpace
8659				);
8660
8661			} else if ( size === 6 ) {
8662
8663				// #ff0000
8664				return this.setHex( parseInt( hex, 16 ), colorSpace );
8665
8666			} else {
8667
8668				console.warn( 'THREE.Color: Invalid hex color ' + style );
8669
8670			}
8671
8672		} else if ( style && style.length > 0 ) {
8673
8674			return this.setColorName( style, colorSpace );
8675
8676		}
8677
8678		return this;
8679
8680	}
8681
8682	setColorName( style, colorSpace = SRGBColorSpace ) {
8683
8684		// color keywords
8685		const hex = _colorKeywords[ style.toLowerCase() ];
8686
8687		if ( hex !== undefined ) {
8688
8689			// red
8690			this.setHex( hex, colorSpace );
8691
8692		} else {
8693
8694			// unknown color
8695			console.warn( 'THREE.Color: Unknown color ' + style );
8696
8697		}
8698
8699		return this;
8700
8701	}
8702
8703	clone() {
8704
8705		return new this.constructor( this.r, this.g, this.b );
8706
8707	}
8708
8709	copy( color ) {
8710
8711		this.r = color.r;
8712		this.g = color.g;
8713		this.b = color.b;
8714
8715		return this;
8716
8717	}
8718
8719	copySRGBToLinear( color ) {
8720
8721		this.r = SRGBToLinear( color.r );
8722		this.g = SRGBToLinear( color.g );
8723		this.b = SRGBToLinear( color.b );
8724
8725		return this;
8726
8727	}
8728
8729	copyLinearToSRGB( color ) {
8730
8731		this.r = LinearToSRGB( color.r );
8732		this.g = LinearToSRGB( color.g );
8733		this.b = LinearToSRGB( color.b );
8734
8735		return this;
8736
8737	}
8738
8739	convertSRGBToLinear() {
8740
8741		this.copySRGBToLinear( this );
8742
8743		return this;
8744
8745	}
8746
8747	convertLinearToSRGB() {
8748
8749		this.copyLinearToSRGB( this );
8750
8751		return this;
8752
8753	}
8754
8755	getHex( colorSpace = SRGBColorSpace ) {
8756
8757		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8758
8759		return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp( _color.b * 255, 0, 255 ) );
8760
8761	}
8762
8763	getHexString( colorSpace = SRGBColorSpace ) {
8764
8765		return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 
vendor: 21,438 bytes, lines 8765-9619
87656 );
8766
8767	}
8768
8769	getHSL( target, colorSpace = ColorManagement.workingColorSpace ) {
8770
8771		// h,s,l ranges are in 0.0 - 1.0
8772
8773		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8774
8775		const r = _color.r, g = _color.g, b = _color.b;
8776
8777		const max = Math.max( r, g, b );
8778		const min = Math.min( r, g, b );
8779
8780		let hue, saturation;
8781		const lightness = ( min + max ) / 2.0;
8782
8783		if ( min === max ) {
8784
8785			hue = 0;
8786			saturation = 0;
8787
8788		} else {
8789
8790			const delta = max - min;
8791
8792			saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
8793
8794			switch ( max ) {
8795
8796				case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
8797				case g: hue = ( b - r ) / delta + 2; break;
8798				case b: hue = ( r - g ) / delta + 4; break;
8799
8800			}
8801
8802			hue /= 6;
8803
8804		}
8805
8806		target.h = hue;
8807		target.s = saturation;
8808		target.l = lightness;
8809
8810		return target;
8811
8812	}
8813
8814	getRGB( target, colorSpace = ColorManagement.workingColorSpace ) {
8815
8816		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8817
8818		target.r = _color.r;
8819		target.g = _color.g;
8820		target.b = _color.b;
8821
8822		return target;
8823
8824	}
8825
8826	getStyle( colorSpace = SRGBColorSpace ) {
8827
8828		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8829
8830		const r = _color.r, g = _color.g, b = _color.b;
8831
8832		if ( colorSpace !== SRGBColorSpace ) {
8833
8834			// Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
8835			return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`;
8836
8837		}
8838
8839		return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`;
8840
8841	}
8842
8843	offsetHSL( h, s, l ) {
8844
8845		this.getHSL( _hslA );
8846
8847		return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l );
8848
8849	}
8850
8851	add( color ) {
8852
8853		this.r += color.r;
8854		this.g += color.g;
8855		this.b += color.b;
8856
8857		return this;
8858
8859	}
8860
8861	addColors( color1, color2 ) {
8862
8863		this.r = color1.r + color2.r;
8864		this.g = color1.g + color2.g;
8865		this.b = color1.b + color2.b;
8866
8867		return this;
8868
8869	}
8870
8871	addScalar( s ) {
8872
8873		this.r += s;
8874		this.g += s;
8875		this.b += s;
8876
8877		return this;
8878
8879	}
8880
8881	sub( color ) {
8882
8883		this.r = Math.max( 0, this.r - color.r );
8884		this.g = Math.max( 0, this.g - color.g );
8885		this.b = Math.max( 0, this.b - color.b );
8886
8887		return this;
8888
8889	}
8890
8891	multiply( color ) {
8892
8893		this.r *= color.r;
8894		this.g *= color.g;
8895		this.b *= color.b;
8896
8897		return this;
8898
8899	}
8900
8901	multiplyScalar( s ) {
8902
8903		this.r *= s;
8904		this.g *= s;
8905		this.b *= s;
8906
8907		return this;
8908
8909	}
8910
8911	lerp( color, alpha ) {
8912
8913		this.r += ( color.r - this.r ) * alpha;
8914		this.g += ( color.g - this.g ) * alpha;
8915		this.b += ( color.b - this.b ) * alpha;
8916
8917		return this;
8918
8919	}
8920
8921	lerpColors( color1, color2, alpha ) {
8922
8923		this.r = color1.r + ( color2.r - color1.r ) * alpha;
8924		this.g = color1.g + ( color2.g - color1.g ) * alpha;
8925		this.b = color1.b + ( color2.b - color1.b ) * alpha;
8926
8927		return this;
8928
8929	}
8930
8931	lerpHSL( color, alpha ) {
8932
8933		this.getHSL( _hslA );
8934		color.getHSL( _hslB );
8935
8936		const h = lerp( _hslA.h, _hslB.h, alpha );
8937		const s = lerp( _hslA.s, _hslB.s, alpha );
8938		const l = lerp( _hslA.l, _hslB.l, alpha );
8939
8940		this.setHSL( h, s, l );
8941
8942		return this;
8943
8944	}
8945
8946	setFromVector3( v ) {
8947
8948		this.r = v.x;
8949		this.g = v.y;
8950		this.b = v.z;
8951
8952		return this;
8953
8954	}
8955
8956	applyMatrix3( m ) {
8957
8958		const r = this.r, g = this.g, b = this.b;
8959		const e = m.elements;
8960
8961		this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b;
8962		this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b;
8963		this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b;
8964
8965		return this;
8966
8967	}
8968
8969	equals( c ) {
8970
8971		return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
8972
8973	}
8974
8975	fromArray( array, offset = 0 ) {
8976
8977		this.r = array[ offset ];
8978		this.g = array[ offset + 1 ];
8979		this.b = array[ offset + 2 ];
8980
8981		return this;
8982
8983	}
8984
8985	toArray( array = [], offset = 0 ) {
8986
8987		array[ offset ] = this.r;
8988		array[ offset + 1 ] = this.g;
8989		array[ offset + 2 ] = this.b;
8990
8991		return array;
8992
8993	}
8994
8995	fromBufferAttribute( attribute, index ) {
8996
8997		this.r = attribute.getX( index );
8998		this.g = attribute.getY( index );
8999		this.b = attribute.getZ( index );
9000
9001		return this;
9002
9003	}
9004
9005	toJSON() {
9006
9007		return this.getHex();
9008
9009	}
9010
9011	*[ Symbol.iterator ]() {
9012
9013		yield this.r;
9014		yield this.g;
9015		yield this.b;
9016
9017	}
9018
9019}
9020
9021const _color = /*@__PURE__*/ new Color();
9022
9023Color.NAMES = _colorKeywords;
9024
9025let _materialId = 0;
9026
9027class Material extends EventDispatcher {
9028
9029	constructor() {
9030
9031		super();
9032
9033		this.isMaterial = true;
9034
9035		Object.defineProperty( this, 'id', { value: _materialId ++ } );
9036
9037		this.uuid = generateUUID();
9038
9039		this.name = '';
9040		this.type = 'Material';
9041
9042		this.blending = NormalBlending;
9043		this.side = FrontSide;
9044		this.vertexColors = false;
9045
9046		this.opacity = 1;
9047		this.transparent = false;
9048		this.alphaHash = false;
9049
9050		this.blendSrc = SrcAlphaFactor;
9051		this.blendDst = OneMinusSrcAlphaFactor;
9052		this.blendEquation = AddEquation;
9053		this.blendSrcAlpha = null;
9054		this.blendDstAlpha = null;
9055		this.blendEquationAlpha = null;
9056		this.blendColor = new Color( 0, 0, 0 );
9057		this.blendAlpha = 0;
9058
9059		this.depthFunc = LessEqualDepth;
9060		this.depthTest = true;
9061		this.depthWrite = true;
9062
9063		this.stencilWriteMask = 0xff;
9064		this.stencilFunc = AlwaysStencilFunc;
9065		this.stencilRef = 0;
9066		this.stencilFuncMask = 0xff;
9067		this.stencilFail = KeepStencilOp;
9068		this.stencilZFail = KeepStencilOp;
9069		this.stencilZPass = KeepStencilOp;
9070		this.stencilWrite = false;
9071
9072		this.clippingPlanes = null;
9073		this.clipIntersection = false;
9074		this.clipShadows = false;
9075
9076		this.shadowSide = null;
9077
9078		this.colorWrite = true;
9079
9080		this.precision = null; // override the renderer's default precision for this material
9081
9082		this.polygonOffset = false;
9083		this.polygonOffsetFactor = 0;
9084		this.polygonOffsetUnits = 0;
9085
9086		this.dithering = false;
9087
9088		this.alphaToCoverage = false;
9089		this.premultipliedAlpha = false;
9090		this.forceSinglePass = false;
9091
9092		this.visible = true;
9093
9094		this.toneMapped = true;
9095
9096		this.userData = {};
9097
9098		this.version = 0;
9099
9100		this._alphaTest = 0;
9101
9102	}
9103
9104	get alphaTest() {
9105
9106		return this._alphaTest;
9107
9108	}
9109
9110	set alphaTest( value ) {
9111
9112		if ( this._alphaTest > 0 !== value > 0 ) {
9113
9114			this.version ++;
9115
9116		}
9117
9118		this._alphaTest = value;
9119
9120	}
9121
9122	onBuild( /* shaderobject, renderer */ ) {}
9123
9124	onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {}
9125
9126	onBeforeCompile( /* shaderobject, renderer */ ) {}
9127
9128	customProgramCacheKey() {
9129
9130		return this.onBeforeCompile.toString();
9131
9132	}
9133
9134	setValues( values ) {
9135
9136		if ( values === undefined ) return;
9137
9138		for ( const key in values ) {
9139
9140			const newValue = values[ key ];
9141
9142			if ( newValue === undefined ) {
9143
9144				console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` );
9145				continue;
9146
9147			}
9148
9149			const currentValue = this[ key ];
9150
9151			if ( currentValue === undefined ) {
9152
9153				console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` );
9154				continue;
9155
9156			}
9157
9158			if ( currentValue && currentValue.isColor ) {
9159
9160				currentValue.set( newValue );
9161
9162			} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
9163
9164				currentValue.copy( newValue );
9165
9166			} else {
9167
9168				this[ key ] = newValue;
9169
9170			}
9171
9172		}
9173
9174	}
9175
9176	toJSON( meta ) {
9177
9178		const isRootObject = ( meta === undefined || typeof meta === 'string' );
9179
9180		if ( isRootObject ) {
9181
9182			meta = {
9183				textures: {},
9184				images: {}
9185			};
9186
9187		}
9188
9189		const data = {
9190			metadata: {
9191				version: 4.6,
9192				type: 'Material',
9193				generator: 'Material.toJSON'
9194			}
9195		};
9196
9197		// standard Material serialization
9198		data.uuid = this.uuid;
9199		data.type = this.type;
9200
9201		if ( this.name !== '' ) data.name = this.name;
9202
9203		if ( this.color && this.color.isColor ) data.color = this.color.getHex();
9204
9205		if ( this.roughness !== undefined ) data.roughness = this.roughness;
9206		if ( this.metalness !== undefined ) data.metalness = this.metalness;
9207
9208		if ( this.sheen !== undefined ) data.sheen = this.sheen;
9209		if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
9210		if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness;
9211		if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
9212		if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
9213
9214		if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
9215		if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity;
9216		if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
9217		if ( this.shininess !== undefined ) data.shininess = this.shininess;
9218		if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
9219		if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
9220
9221		if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
9222
9223			data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
9224
9225		}
9226
9227		if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
9228
9229			data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
9230
9231		}
9232
9233		if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
9234
9235			data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
9236			data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
9237
9238		}
9239
9240		if ( this.iridescence !== undefined ) data.iridescence = this.iridescence;
9241		if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR;
9242		if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
9243
9244		if ( this.iridescenceMap && this.iridescenceMap.isTexture ) {
9245
9246			data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid;
9247
9248		}
9249
9250		if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) {
9251
9252			data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid;
9253
9254		}
9255
9256		if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy;
9257		if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation;
9258
9259		if ( this.anisotropyMap && this.anisotropyMap.isTexture ) {
9260
9261			data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid;
9262
9263		}
9264
9265		if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
9266		if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
9267		if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
9268
9269		if ( this.lightMap && this.lightMap.isTexture ) {
9270
9271			data.lightMap = this.lightMap.toJSON( meta ).uuid;
9272			data.lightMapIntensity = this.lightMapIntensity;
9273
9274		}
9275
9276		if ( this.aoMap && this.aoMap.isTexture ) {
9277
9278			data.aoMap = this.aoMap.toJSON( meta ).uuid;
9279			data.aoMapIntensity = this.aoMapIntensity;
9280
9281		}
9282
9283		if ( this.bumpMap && this.bumpMap.isTexture ) {
9284
9285			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
9286			data.bumpScale = this.bumpScale;
9287
9288		}
9289
9290		if ( this.normalMap && this.normalMap.isTexture ) {
9291
9292			data.normalMap = this.normalMap.toJSON( meta ).uuid;
9293			data.normalMapType = this.normalMapType;
9294			data.normalScale = this.normalScale.toArray();
9295
9296		}
9297
9298		if ( this.displacementMap && this.displacementMap.isTexture ) {
9299
9300			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
9301			data.displacementScale = this.displacementScale;
9302			data.displacementBias = this.displacementBias;
9303
9304		}
9305
9306		if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
9307		if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
9308
9309		if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
9310		if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
9311		if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
9312		if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
9313
9314		if ( this.envMap && this.envMap.isTexture ) {
9315
9316			data.envMap = this.envMap.toJSON( meta ).uuid;
9317
9318			if ( this.combine !== undefined ) data.combine = this.combine;
9319
9320		}
9321
9322		if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray();
9323		if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
9324		if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity;
9325		if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio;
9326
9327		if ( this.gradientMap && this.gradientMap.isTexture ) {
9328
9329			data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
9330
9331		}
9332
9333		if ( this.transmission !== undefined ) data.transmission = this.transmission;
9334		if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
9335		if ( this.thickness !== undefined ) data.thickness = this.thickness;
9336		if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
9337		if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance;
9338		if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
9339
9340		if ( this.size !== undefined ) data.size = this.size;
9341		if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide;
9342		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
9343
9344		if ( this.blending !== NormalBlending ) data.blending = this.blending;
9345		if ( this.side !== FrontSide ) data.side = this.side;
9346		if ( this.vertexColors === true ) data.vertexColors = true;
9347
9348		if ( this.opacity < 1 ) data.opacity = this.opacity;
9349		if ( this.transparent === true ) data.transparent = true;
9350
9351		if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc;
9352		if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst;
9353		if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation;
9354		if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha;
9355		if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha;
9356		if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha;
9357		if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex();
9358		if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha;
9359
9360		if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc;
9361		if ( this.depthTest === false ) data.depthTest = this.depthTest;
9362		if ( this.depthWrite === false ) data.depthWrite = this.depthWrite;
9363		if ( this.colorWrite === false ) data.colorWrite = this.colorWrite;
9364
9365		if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask;
9366		if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc;
9367		if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef;
9368		if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask;
9369		if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail;
9370		if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail;
9371		if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass;
9372		if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite;
9373
9374		// rotation (SpriteMaterial)
9375		if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation;
9376
9377		if ( this.polygonOffset === true ) data.polygonOffset = true;
9378		if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
9379		if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
9380
9381		if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth;
9382		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
9383		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
9384		if ( this.scale !== undefined ) data.scale = this.scale;
9385
9386		if ( this.dithering === true ) data.dithering = true;
9387
9388		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
9389		if ( this.alphaHash === true ) data.alphaHash = true;
9390		if ( this.alphaToCoverage === true ) data.alphaToCoverage = true;
9391		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true;
9392		if ( this.forceSinglePass === true ) data.forceSinglePass = true;
9393
9394		if ( this.wireframe === true ) data.wireframe = true;
9395		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
9396		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
9397		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
9398
9399		if ( this.flatShading === true ) data.flatShading = true;
9400
9401		if ( this.visible === false ) data.visible = false;
9402
9403		if ( this.toneMapped === false ) data.toneMapped = false;
9404
9405		if ( this.fog === false ) data.fog = false;
9406
9407		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
9408
9409		// TODO: Copied from Object3D.toJSON
9410
9411		function extractFromCache( cache ) {
9412
9413			const values = [];
9414
9415			for ( const key in cache ) {
9416
9417				const data = cache[ key ];
9418				delete data.metadata;
9419				values.push( data );
9420
9421			}
9422
9423			return values;
9424
9425		}
9426
9427		if ( isRootObject ) {
9428
9429			const textures = extractFromCache( meta.textures );
9430			const images = extractFromCache( meta.images );
9431
9432			if ( textures.length > 0 ) data.textures = textures;
9433			if ( images.length > 0 ) data.images = images;
9434
9435		}
9436
9437		return data;
9438
9439	}
9440
9441	clone() {
9442
9443		return new this.constructor().copy( this );
9444
9445	}
9446
9447	copy( source ) {
9448
9449		this.name = source.name;
9450
9451		this.blending = source.blending;
9452		this.side = source.side;
9453		this.vertexColors = source.vertexColors;
9454
9455		this.opacity = source.opacity;
9456		this.transparent = source.transparent;
9457
9458		this.blendSrc = source.blendSrc;
9459		this.blendDst = source.blendDst;
9460		this.blendEquation = source.blendEquation;
9461		this.blendSrcAlpha = source.blendSrcAlpha;
9462		this.blendDstAlpha = source.blendDstAlpha;
9463		this.blendEquationAlpha = source.blendEquationAlpha;
9464		this.blendColor.copy( source.blendColor );
9465		this.blendAlpha = source.blendAlpha;
9466
9467		this.depthFunc = source.depthFunc;
9468		this.depthTest = source.depthTest;
9469		this.depthWrite = source.depthWrite;
9470
9471		this.stencilWriteMask = source.stencilWriteMask;
9472		this.stencilFunc = source.stencilFunc;
9473		this.stencilRef = source.stencilRef;
9474		this.stencilFuncMask = source.stencilFuncMask;
9475		this.stencilFail = source.stencilFail;
9476		this.stencilZFail = source.stencilZFail;
9477		this.stencilZPass = source.stencilZPass;
9478		this.stencilWrite = source.stencilWrite;
9479
9480		const srcPlanes = source.clippingPlanes;
9481		let dstPlanes = null;
9482
9483		if ( srcPlanes !== null ) {
9484
9485			const n = srcPlanes.length;
9486			dstPlanes = new Array( n );
9487
9488			for ( let i = 0; i !== n; ++ i ) {
9489
9490				dstPlanes[ i ] = srcPlanes[ i ].clone();
9491
9492			}
9493
9494		}
9495
9496		this.clippingPlanes = dstPlanes;
9497		this.clipIntersection = source.clipIntersection;
9498		this.clipShadows = source.clipShadows;
9499
9500		this.shadowSide = source.shadowSide;
9501
9502		this.colorWrite = source.colorWrite;
9503
9504		this.precision = source.precision;
9505
9506		this.polygonOffset = source.polygonOffset;
9507		this.polygonOffsetFactor = source.polygonOffsetFactor;
9508		this.polygonOffsetUnits = source.polygonOffsetUnits;
9509
9510		this.dithering = source.dithering;
9511
9512		this.alphaTest = source.alphaTest;
9513		this.alphaHash = source.alphaHash;
9514		this.alphaToCoverage = source.alphaToCoverage;
9515		this.premultipliedAlpha = source.premultipliedAlpha;
9516		this.forceSinglePass = source.forceSinglePass;
9517
9518		this.visible = source.visible;
9519
9520		this.toneMapped = source.toneMapped;
9521
9522		this.userData = JSON.parse( JSON.stringify( source.userData ) );
9523
9524		return this;
9525
9526	}
9527
9528	dispose() {
9529
9530		this.dispatchEvent( { type: 'dispose' } );
9531
9532	}
9533
9534	set needsUpdate( value ) {
9535
9536		if ( value === true ) this.version ++;
9537
9538	}
9539
9540}
9541
9542class MeshBasicMaterial extends Material {
9543
9544	constructor( parameters ) {
9545
9546		super();
9547
9548		this.isMeshBasicMaterial = true;
9549
9550		this.type = 'MeshBasicMaterial';
9551
9552		this.color = new Color( 0xffffff ); // emissive
9553
9554		this.map = null;
9555
9556		this.lightMap = null;
9557		this.lightMapIntensity = 1.0;
9558
9559		this.aoMap = null;
9560		this.aoMapIntensity = 1.0;
9561
9562		this.specularMap = null;
9563
9564		this.alphaMap = null;
9565
9566		this.envMap = null;
9567		this.envMapRotation = new Euler();
9568		this.combine = MultiplyOperation;
9569		this.reflectivity = 1;
9570		this.refractionRatio = 0.98;
9571
9572		this.wireframe = false;
9573		this.wireframeLinewidth = 1;
9574		this.wireframeLinecap = 'round';
9575		this.wireframeLinejoin = 'round';
9576
9577		this.fog = true;
9578
9579		this.setValues( parameters );
9580
9581	}
9582
9583	copy( source ) {
9584
9585		super.copy( source );
9586
9587		this.color.copy( source.color );
9588
9589		this.map = source.map;
9590
9591		this.lightMap = source.lightMap;
9592		this.lightMapIntensity = source.lightMapIntensity;
9593
9594		this.aoMap = source.aoMap;
9595		this.aoMapIntensity = source.aoMapIntensity;
9596
9597		this.specularMap = source.specularMap;
9598
9599		this.alphaMap = source.alphaMap;
9600
9601		this.envMap = source.envMap;
9602		this.envMapRotation.copy( source.envMapRotation );
9603		this.combine = source.combine;
9604		this.reflectivity = source.reflectivity;
9605		this.refractionRatio = source.refractionRatio;
9606
9607		this.wireframe = source.wireframe;
9608		this.wireframeLinewidth = source.wireframeLinewidth;
9609		this.wireframeLinecap = source.wireframeLinecap;
9610		this.wireframeLinejoin = source.wireframeLinejoin;
9611
9612		this.fog = source.fog;
9613
9614		return this;
9615
9616	}
9617
9618}
9619
vendor: 4,666 bytes, lines 9620-9858
9620// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
9621
9622const _tables = /*@__PURE__*/ _generateTables();
9623
9624function _generateTables() {
9625
9626	// float32 to float16 helpers
9627
9628	const buffer = new ArrayBuffer( 4 );
9629	const floatView = new Float32Array( buffer );
9630	const uint32View = new Uint32Array( buffer );
9631
9632	const baseTable = new Uint32Array( 512 );
9633	const shiftTable = new Uint32Array( 512 );
9634
9635	for ( let i = 0; i < 256; ++ i ) {
9636
9637		const e = i - 127;
9638
9639		// very small number (0, -0)
9640
9641		if ( e < - 27 ) {
9642
9643			baseTable[ i ] = 0x0000;
9644			baseTable[ i | 0x100 ] = 0x8000;
9645			shiftTable[ i ] = 24;
9646			shiftTable[ i | 0x100 ] = 24;
9647
9648			// small number (denorm)
9649
9650		} else if ( e < - 14 ) {
9651
9652			baseTable[ i ] = 0x0400 >> ( - e - 14 );
9653			baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000;
9654			shiftTable[ i ] = - e - 1;
9655			shiftTable[ i | 0x100 ] = - e - 1;
9656
9657			// normal number
9658
9659		} else if ( e <= 15 ) {
9660
9661			baseTable[ i ] = ( e + 15 ) << 10;
9662			baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000;
9663			shiftTable[ i ] = 13;
9664			shiftTable[ i | 0x100 ] = 13;
9665
9666			// large number (Infinity, -Infinity)
9667
9668		} else if ( e < 128 ) {
9669
9670			baseTable[ i ] = 0x7c00;
9671			baseTable[ i | 0x100 ] = 0xfc00;
9672			shiftTable[ i ] = 24;
9673			shiftTable[ i | 0x100 ] = 24;
9674
9675			// stay (NaN, Infinity, -Infinity)
9676
9677		} else {
9678
9679			baseTable[ i ] = 0x7c00;
9680			baseTable[ i | 0x100 ] = 0xfc00;
9681			shiftTable[ i ] = 13;
9682			shiftTable[ i | 0x100 ] = 13;
9683
9684		}
9685
9686	}
9687
9688	// float16 to float32 helpers
9689
9690	const mantissaTable = new Uint32Array( 2048 );
9691	const exponentTable = new Uint32Array( 64 );
9692	const offsetTable = new Uint32Array( 64 );
9693
9694	for ( let i = 1; i < 1024; ++ i ) {
9695
9696		let m = i << 13; // zero pad mantissa bits
9697		let e = 0; // zero exponent
9698
9699		// normalized
9700		while ( ( m & 0x00800000 ) === 0 ) {
9701
9702			m <<= 1;
9703			e -= 0x00800000; // decrement exponent
9704
9705		}
9706
9707		m &= ~ 0x00800000; // clear leading 1 bit
9708		e += 0x38800000; // adjust bias
9709
9710		mantissaTable[ i ] = m | e;
9711
9712	}
9713
9714	for ( let i = 1024; i < 2048; ++ i ) {
9715
9716		mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 );
9717
9718	}
9719
9720	for ( let i = 1; i < 31; ++ i ) {
9721
9722		exponentTable[ i ] = i << 23;
9723
9724	}
9725
9726	exponentTable[ 31 ] = 0x47800000;
9727	exponentTable[ 32 ] = 0x80000000;
9728
9729	for ( let i = 33; i < 63; ++ i ) {
9730
9731		exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 );
9732
9733	}
9734
9735	exponentTable[ 63 ] = 0xc7800000;
9736
9737	for ( let i = 1; i < 64; ++ i ) {
9738
9739		if ( i !== 32 ) {
9740
9741			offsetTable[ i ] = 1024;
9742
9743		}
9744
9745	}
9746
9747	return {
9748		floatView: floatView,
9749		uint32View: uint32View,
9750		baseTable: baseTable,
9751		shiftTable: shiftTable,
9752		mantissaTable: mantissaTable,
9753		exponentTable: exponentTable,
9754		offsetTable: offsetTable
9755	};
9756
9757}
9758
9759// float32 to float16
9760
9761function toHalfFloat( val ) {
9762
9763	if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' );
9764
9765	val = clamp( val, - 65504, 65504 );
9766
9767	_tables.floatView[ 0 ] = val;
9768	const f = _tables.uint32View[ 0 ];
9769	const e = ( f >> 23 ) & 0x1ff;
9770	return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] );
9771
9772}
9773
9774// float16 to float32
9775
9776function fromHalfFloat( val ) {
9777
9778	const m = val >> 10;
9779	_tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ];
9780	return _tables.floatView[ 0 ];
9781
9782}
9783
9784const DataUtils = {
9785	toHalfFloat: toHalfFloat,
9786	fromHalfFloat: fromHalfFloat,
9787};
9788
9789const _vector$9 = /*@__PURE__*/ new Vector3();
9790const _vector2$1 = /*@__PURE__*/ new Vector2();
9791
9792class BufferAttribute {
9793
9794	constructor( array, itemSize, normalized = false ) {
9795
9796		if ( Array.isArray( array ) ) {
9797
9798			throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
9799
9800		}
9801
9802		this.isBufferAttribute = true;
9803
9804		this.name = '';
9805
9806		this.array = array;
9807		this.itemSize = itemSize;
9808		this.count = array !== undefined ? array.length / itemSize : 0;
9809		this.normalized = normalized;
9810
9811		this.usage = StaticDrawUsage;
9812		this._updateRange = { offset: 0, count: - 1 };
9813		this.updateRanges = [];
9814		this.gpuType = FloatType;
9815
9816		this.version = 0;
9817
9818	}
9819
9820	onUploadCallback() {}
9821
9822	set needsUpdate( value ) {
9823
9824		if ( value === true ) this.version ++;
9825
9826	}
9827
9828	get updateRange() {
9829
9830		warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159
9831		return this._updateRange;
9832
9833	}
9834
9835	setUsage( value ) {
9836
9837		this.usage = value;
9838
9839		return this;
9840
9841	}
9842
9843	addUpdateRange( start, count ) {
9844
9845		this.updateRanges.push( { start, count } );
9846
9847	}
9848
9849	clearUpdateRanges() {
9850
9851		this.updateRanges.length = 0;
9852
9853	}
9854
9855	copy( source ) {
9856
9857		this.name = source.name;
9858		this.array = new source.array.constructor( source.array );
vendor: 8,607 bytes, lines 9859-10390
9859		this.itemSize = source.itemSize;
9860		this.count = source.count;
9861		this.normalized = source.normalized;
9862
9863		this.usage = source.usage;
9864		this.gpuType = source.gpuType;
9865
9866		return this;
9867
9868	}
9869
9870	copyAt( index1, attribute, index2 ) {
9871
9872		index1 *= this.itemSize;
9873		index2 *= attribute.itemSize;
9874
9875		for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
9876
9877			this.array[ index1 + i ] = attribute.array[ index2 + i ];
9878
9879		}
9880
9881		return this;
9882
9883	}
9884
9885	copyArray( array ) {
9886
9887		this.array.set( array );
9888
9889		return this;
9890
9891	}
9892
9893	applyMatrix3( m ) {
9894
9895		if ( this.itemSize === 2 ) {
9896
9897			for ( let i = 0, l = this.count; i < l; i ++ ) {
9898
9899				_vector2$1.fromBufferAttribute( this, i );
9900				_vector2$1.applyMatrix3( m );
9901
9902				this.setXY( i, _vector2$1.x, _vector2$1.y );
9903
9904			}
9905
9906		} else if ( this.itemSize === 3 ) {
9907
9908			for ( let i = 0, l = this.count; i < l; i ++ ) {
9909
9910				_vector$9.fromBufferAttribute( this, i );
9911				_vector$9.applyMatrix3( m );
9912
9913				this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9914
9915			}
9916
9917		}
9918
9919		return this;
9920
9921	}
9922
9923	applyMatrix4( m ) {
9924
9925		for ( let i = 0, l = this.count; i < l; i ++ ) {
9926
9927			_vector$9.fromBufferAttribute( this, i );
9928
9929			_vector$9.applyMatrix4( m );
9930
9931			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9932
9933		}
9934
9935		return this;
9936
9937	}
9938
9939	applyNormalMatrix( m ) {
9940
9941		for ( let i = 0, l = this.count; i < l; i ++ ) {
9942
9943			_vector$9.fromBufferAttribute( this, i );
9944
9945			_vector$9.applyNormalMatrix( m );
9946
9947			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9948
9949		}
9950
9951		return this;
9952
9953	}
9954
9955	transformDirection( m ) {
9956
9957		for ( let i = 0, l = this.count; i < l; i ++ ) {
9958
9959			_vector$9.fromBufferAttribute( this, i );
9960
9961			_vector$9.transformDirection( m );
9962
9963			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9964
9965		}
9966
9967		return this;
9968
9969	}
9970
9971	set( value, offset = 0 ) {
9972
9973		// Matching BufferAttribute constructor, do not normalize the array.
9974		this.array.set( value, offset );
9975
9976		return this;
9977
9978	}
9979
9980	getComponent( index, component ) {
9981
9982		let value = this.array[ index * this.itemSize + component ];
9983
9984		if ( this.normalized ) value = denormalize( value, this.array );
9985
9986		return value;
9987
9988	}
9989
9990	setComponent( index, component, value ) {
9991
9992		if ( this.normalized ) value = normalize( value, this.array );
9993
9994		this.array[ index * this.itemSize + component ] = value;
9995
9996		return this;
9997
9998	}
9999
10000	getX( index ) {
10001
10002		let x = this.array[ index * this.itemSize ];
10003
10004		if ( this.normalized ) x = denormalize( x, this.array );
10005
10006		return x;
10007
10008	}
10009
10010	setX( index, x ) {
10011
10012		if ( this.normalized ) x = normalize( x, this.array );
10013
10014		this.array[ index * this.itemSize ] = x;
10015
10016		return this;
10017
10018	}
10019
10020	getY( index ) {
10021
10022		let y = this.array[ index * this.itemSize + 1 ];
10023
10024		if ( this.normalized ) y = denormalize( y, this.array );
10025
10026		return y;
10027
10028	}
10029
10030	setY( index, y ) {
10031
10032		if ( this.normalized ) y = normalize( y, this.array );
10033
10034		this.array[ index * this.itemSize + 1 ] = y;
10035
10036		return this;
10037
10038	}
10039
10040	getZ( index ) {
10041
10042		let z = this.array[ index * this.itemSize + 2 ];
10043
10044		if ( this.normalized ) z = denormalize( z, this.array );
10045
10046		return z;
10047
10048	}
10049
10050	setZ( index, z ) {
10051
10052		if ( this.normalized ) z = normalize( z, this.array );
10053
10054		this.array[ index * this.itemSize + 2 ] = z;
10055
10056		return this;
10057
10058	}
10059
10060	getW( index ) {
10061
10062		let w = this.array[ index * this.itemSize + 3 ];
10063
10064		if ( this.normalized ) w = denormalize( w, this.array );
10065
10066		return w;
10067
10068	}
10069
10070	setW( index, w ) {
10071
10072		if ( this.normalized ) w = normalize( w, this.array );
10073
10074		this.array[ index * this.itemSize + 3 ] = w;
10075
10076		return this;
10077
10078	}
10079
10080	setXY( index, x, y ) {
10081
10082		index *= this.itemSize;
10083
10084		if ( this.normalized ) {
10085
10086			x = normalize( x, this.array );
10087			y = normalize( y, this.array );
10088
10089		}
10090
10091		this.array[ index + 0 ] = x;
10092		this.array[ index + 1 ] = y;
10093
10094		return this;
10095
10096	}
10097
10098	setXYZ( index, x, y, z ) {
10099
10100		index *= this.itemSize;
10101
10102		if ( this.normalized ) {
10103
10104			x = normalize( x, this.array );
10105			y = normalize( y, this.array );
10106			z = normalize( z, this.array );
10107
10108		}
10109
10110		this.array[ index + 0 ] = x;
10111		this.array[ index + 1 ] = y;
10112		this.array[ index + 2 ] = z;
10113
10114		return this;
10115
10116	}
10117
10118	setXYZW( index, x, y, z, w ) {
10119
10120		index *= this.itemSize;
10121
10122		if ( this.normalized ) {
10123
10124			x = normalize( x, this.array );
10125			y = normalize( y, this.array );
10126			z = normalize( z, this.array );
10127			w = normalize( w, this.array );
10128
10129		}
10130
10131		this.array[ index + 0 ] = x;
10132		this.array[ index + 1 ] = y;
10133		this.array[ index + 2 ] = z;
10134		this.array[ index + 3 ] = w;
10135
10136		return this;
10137
10138	}
10139
10140	onUpload( callback ) {
10141
10142		this.onUploadCallback = callback;
10143
10144		return this;
10145
10146	}
10147
10148	clone() {
10149
10150		return new this.constructor( this.array, this.itemSize ).copy( this );
10151
10152	}
10153
10154	toJSON() {
10155
10156		const data = {
10157			itemSize: this.itemSize,
10158			type: this.array.constructor.name,
10159			array: Array.from( this.array ),
10160			normalized: this.normalized
10161		};
10162
10163		if ( this.name !== '' ) data.name = this.name;
10164		if ( this.usage !== StaticDrawUsage ) data.usage = this.usage;
10165
10166		return data;
10167
10168	}
10169
10170}
10171
10172//
10173
10174class Int8BufferAttribute extends BufferAttribute {
10175
10176	constructor( array, itemSize, normalized ) {
10177
10178		super( new Int8Array( array ), itemSize, normalized );
10179
10180	}
10181
10182}
10183
10184class Uint8BufferAttribute extends BufferAttribute {
10185
10186	constructor( array, itemSize, normalized ) {
10187
10188		super( new Uint8Array( array ), itemSize, normalized );
10189
10190	}
10191
10192}
10193
10194class Uint8ClampedBufferAttribute extends BufferAttribute {
10195
10196	constructor( array, itemSize, normalized ) {
10197
10198		super( new Uint8ClampedArray( array ), itemSize, normalized );
10199
10200	}
10201
10202}
10203
10204class Int16BufferAttribute extends BufferAttribute {
10205
10206	constructor( array, itemSize, normalized ) {
10207
10208		super( new Int16Array( array ), itemSize, normalized );
10209
10210	}
10211
10212}
10213
10214class Uint16BufferAttribute extends BufferAttribute {
10215
10216	constructor( array, itemSize, normalized ) {
10217
10218		super( new Uint16Array( array ), itemSize, normalized );
10219
10220	}
10221
10222}
10223
10224class Int32BufferAttribute extends BufferAttribute {
10225
10226	constructor( array, itemSize, normalized ) {
10227
10228		super( new Int32Array( array ), itemSize, normalized );
10229
10230	}
10231
10232}
10233
10234class Uint32BufferAttribute extends BufferAttribute {
10235
10236	constructor( array, itemSize, normalized ) {
10237
10238		super( new Uint32Array( array ), itemSize, normalized );
10239
10240	}
10241
10242}
10243
10244class Float16BufferAttribute extends BufferAttribute {
10245
10246	constructor( array, itemSize, normalized ) {
10247
10248		super( new Uint16Array( array ), itemSize, normalized );
10249
10250		this.isFloat16BufferAttribute = true;
10251
10252	}
10253
10254	getX( index ) {
10255
10256		let x = fromHalfFloat( this.array[ index * this.itemSize ] );
10257
10258		if ( this.normalized ) x = denormalize( x, this.array );
10259
10260		return x;
10261
10262	}
10263
10264	setX( index, x ) {
10265
10266		if ( this.normalized ) x = normalize( x, this.array );
10267
10268		this.array[ index * this.itemSize ] = toHalfFloat( x );
10269
10270		return this;
10271
10272	}
10273
10274	getY( index ) {
10275
10276		let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] );
10277
10278		if ( this.normalized ) y = denormalize( y, this.array );
10279
10280		return y;
10281
10282	}
10283
10284	setY( index, y ) {
10285
10286		if ( this.normalized ) y = normalize( y, this.array );
10287
10288		this.array[ index * this.itemSize + 1 ] = toHalfFloat( y );
10289
10290		return this;
10291
10292	}
10293
10294	getZ( index ) {
10295
10296		let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] );
10297
10298		if ( this.normalized ) z = denormalize( z, this.array );
10299
10300		return z;
10301
10302	}
10303
10304	setZ( index, z ) {
10305
10306		if ( this.normalized ) z = normalize( z, this.array );
10307
10308		this.array[ index * this.itemSize + 2 ] = toHalfFloat( z );
10309
10310		return this;
10311
10312	}
10313
10314	getW( index ) {
10315
10316		let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] );
10317
10318		if ( this.normalized ) w = denormalize( w, this.array );
10319
10320		return w;
10321
10322	}
10323
10324	setW( index, w ) {
10325
10326		if ( this.normalized ) w = normalize( w, this.array );
10327
10328		this.array[ index * this.itemSize + 3 ] = toHalfFloat( w );
10329
10330		return this;
10331
10332	}
10333
10334	setXY( index, x, y ) {
10335
10336		index *= this.itemSize;
10337
10338		if ( this.normalized ) {
10339
10340			x = normalize( x, this.array );
10341			y = normalize( y, this.array );
10342
10343		}
10344
10345		this.array[ index + 0 ] = toHalfFloat( x );
10346		this.array[ index + 1 ] = toHalfFloat( y );
10347
10348		return this;
10349
10350	}
10351
10352	setXYZ( index, x, y, z ) {
10353
10354		index *= this.itemSize;
10355
10356		if ( this.normalized ) {
10357
10358			x = normalize( x, this.array );
10359			y = normalize( y, this.array );
10360			z = normalize( z, this.array );
10361
10362		}
10363
10364		this.array[ index + 0 ] = toHalfFloat( x );
10365		this.array[ index + 1 ] = toHalfFloat( y );
10366		this.array[ index + 2 ] = toHalfFloat( z );
10367
10368		return this;
10369
10370	}
10371
10372	setXYZW( index, x, y, z, w ) {
10373
10374		index *= this.itemSize;
10375
10376		if ( this.normalized ) {
10377
10378			x = normalize( x, this.array );
10379			y = normalize( y, this.array );
10380			z = normalize( z, this.array );
10381			w = normalize( w, this.array );
10382
10383		}
10384
10385		this.array[ index + 0 ] = toHalfFloat( x );
10386		this.array[ index + 1 ] = toHalfFloat( y );
10387		this.array[ index + 2 ] = toHalfFloat( z );
10388		this.array[ index + 3 ] = toHalfFloat( w );
10389
10390		return this
vendor: 11,366 bytes, lines 10390-11000
10390;
10391
10392	}
10393
10394}
10395
10396
10397class Float32BufferAttribute extends BufferAttribute {
10398
10399	constructor( array, itemSize, normalized ) {
10400
10401		super( new Float32Array( array ), itemSize, normalized );
10402
10403	}
10404
10405}
10406
10407let _id$2 = 0;
10408
10409const _m1$2 = /*@__PURE__*/ new Matrix4();
10410const _obj = /*@__PURE__*/ new Object3D();
10411const _offset = /*@__PURE__*/ new Vector3();
10412const _box$2 = /*@__PURE__*/ new Box3();
10413const _boxMorphTargets = /*@__PURE__*/ new Box3();
10414const _vector$8 = /*@__PURE__*/ new Vector3();
10415
10416class BufferGeometry extends EventDispatcher {
10417
10418	constructor() {
10419
10420		super();
10421
10422		this.isBufferGeometry = true;
10423
10424		Object.defineProperty( this, 'id', { value: _id$2 ++ } );
10425
10426		this.uuid = generateUUID();
10427
10428		this.name = '';
10429		this.type = 'BufferGeometry';
10430
10431		this.index = null;
10432		this.attributes = {};
10433
10434		this.morphAttributes = {};
10435		this.morphTargetsRelative = false;
10436
10437		this.groups = [];
10438
10439		this.boundingBox = null;
10440		this.boundingSphere = null;
10441
10442		this.drawRange = { start: 0, count: Infinity };
10443
10444		this.userData = {};
10445
10446	}
10447
10448	getIndex() {
10449
10450		return this.index;
10451
10452	}
10453
10454	setIndex( index ) {
10455
10456		if ( Array.isArray( index ) ) {
10457
10458			this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
10459
10460		} else {
10461
10462			this.index = index;
10463
10464		}
10465
10466		return this;
10467
10468	}
10469
10470	getAttribute( name ) {
10471
10472		return this.attributes[ name ];
10473
10474	}
10475
10476	setAttribute( name, attribute ) {
10477
10478		this.attributes[ name ] = attribute;
10479
10480		return this;
10481
10482	}
10483
10484	deleteAttribute( name ) {
10485
10486		delete this.attributes[ name ];
10487
10488		return this;
10489
10490	}
10491
10492	hasAttribute( name ) {
10493
10494		return this.attributes[ name ] !== undefined;
10495
10496	}
10497
10498	addGroup( start, count, materialIndex = 0 ) {
10499
10500		this.groups.push( {
10501
10502			start: start,
10503			count: count,
10504			materialIndex: materialIndex
10505
10506		} );
10507
10508	}
10509
10510	clearGroups() {
10511
10512		this.groups = [];
10513
10514	}
10515
10516	setDrawRange( start, count ) {
10517
10518		this.drawRange.start = start;
10519		this.drawRange.count = count;
10520
10521	}
10522
10523	applyMatrix4( matrix ) {
10524
10525		const position = this.attributes.position;
10526
10527		if ( position !== undefined ) {
10528
10529			position.applyMatrix4( matrix );
10530
10531			position.needsUpdate = true;
10532
10533		}
10534
10535		const normal = this.attributes.normal;
10536
10537		if ( normal !== undefined ) {
10538
10539			const normalMatrix = new Matrix3().getNormalMatrix( matrix );
10540
10541			normal.applyNormalMatrix( normalMatrix );
10542
10543			normal.needsUpdate = true;
10544
10545		}
10546
10547		const tangent = this.attributes.tangent;
10548
10549		if ( tangent !== undefined ) {
10550
10551			tangent.transformDirection( matrix );
10552
10553			tangent.needsUpdate = true;
10554
10555		}
10556
10557		if ( this.boundingBox !== null ) {
10558
10559			this.computeBoundingBox();
10560
10561		}
10562
10563		if ( this.boundingSphere !== null ) {
10564
10565			this.computeBoundingSphere();
10566
10567		}
10568
10569		return this;
10570
10571	}
10572
10573	applyQuaternion( q ) {
10574
10575		_m1$2.makeRotationFromQuaternion( q );
10576
10577		this.applyMatrix4( _m1$2 );
10578
10579		return this;
10580
10581	}
10582
10583	rotateX( angle ) {
10584
10585		// rotate geometry around world x-axis
10586
10587		_m1$2.makeRotationX( angle );
10588
10589		this.applyMatrix4( _m1$2 );
10590
10591		return this;
10592
10593	}
10594
10595	rotateY( angle ) {
10596
10597		// rotate geometry around world y-axis
10598
10599		_m1$2.makeRotationY( angle );
10600
10601		this.applyMatrix4( _m1$2 );
10602
10603		return this;
10604
10605	}
10606
10607	rotateZ( angle ) {
10608
10609		// rotate geometry around world z-axis
10610
10611		_m1$2.makeRotationZ( angle );
10612
10613		this.applyMatrix4( _m1$2 );
10614
10615		return this;
10616
10617	}
10618
10619	translate( x, y, z ) {
10620
10621		// translate geometry
10622
10623		_m1$2.makeTranslation( x, y, z );
10624
10625		this.applyMatrix4( _m1$2 );
10626
10627		return this;
10628
10629	}
10630
10631	scale( x, y, z ) {
10632
10633		// scale geometry
10634
10635		_m1$2.makeScale( x, y, z );
10636
10637		this.applyMatrix4( _m1$2 );
10638
10639		return this;
10640
10641	}
10642
10643	lookAt( vector ) {
10644
10645		_obj.lookAt( vector );
10646
10647		_obj.updateMatrix();
10648
10649		this.applyMatrix4( _obj.matrix );
10650
10651		return this;
10652
10653	}
10654
10655	center() {
10656
10657		this.computeBoundingBox();
10658
10659		this.boundingBox.getCenter( _offset ).negate();
10660
10661		this.translate( _offset.x, _offset.y, _offset.z );
10662
10663		return this;
10664
10665	}
10666
10667	setFromPoints( points ) {
10668
10669		const position = [];
10670
10671		for ( let i = 0, l = points.length; i < l; i ++ ) {
10672
10673			const point = points[ i ];
10674			position.push( point.x, point.y, point.z || 0 );
10675
10676		}
10677
10678		this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
10679
10680		return this;
10681
10682	}
10683
10684	computeBoundingBox() {
10685
10686		if ( this.boundingBox === null ) {
10687
10688			this.boundingBox = new Box3();
10689
10690		}
10691
10692		const position = this.attributes.position;
10693		const morphAttributesPosition = this.morphAttributes.position;
10694
10695		if ( position && position.isGLBufferAttribute ) {
10696
10697			console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this );
10698
10699			this.boundingBox.set(
10700				new Vector3( - Infinity, - Infinity, - Infinity ),
10701				new Vector3( + Infinity, + Infinity, + Infinity )
10702			);
10703
10704			return;
10705
10706		}
10707
10708		if ( position !== undefined ) {
10709
10710			this.boundingBox.setFromBufferAttribute( position );
10711
10712			// process morph attributes if present
10713
10714			if ( morphAttributesPosition ) {
10715
10716				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10717
10718					const morphAttribute = morphAttributesPosition[ i ];
10719					_box$2.setFromBufferAttribute( morphAttribute );
10720
10721					if ( this.morphTargetsRelative ) {
10722
10723						_vector$8.addVectors( this.boundingBox.min, _box$2.min );
10724						this.boundingBox.expandByPoint( _vector$8 );
10725
10726						_vector$8.addVectors( this.boundingBox.max, _box$2.max );
10727						this.boundingBox.expandByPoint( _vector$8 );
10728
10729					} else {
10730
10731						this.boundingBox.expandByPoint( _box$2.min );
10732						this.boundingBox.expandByPoint( _box$2.max );
10733
10734					}
10735
10736				}
10737
10738			}
10739
10740		} else {
10741
10742			this.boundingBox.makeEmpty();
10743
10744		}
10745
10746		if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
10747
10748			console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
10749
10750		}
10751
10752	}
10753
10754	computeBoundingSphere() {
10755
10756		if ( this.boundingSphere === null ) {
10757
10758			this.boundingSphere = new Sphere();
10759
10760		}
10761
10762		const position = this.attributes.position;
10763		const morphAttributesPosition = this.morphAttributes.position;
10764
10765		if ( position && position.isGLBufferAttribute ) {
10766
10767			console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this );
10768
10769			this.boundingSphere.set( new Vector3(), Infinity );
10770
10771			return;
10772
10773		}
10774
10775		if ( position ) {
10776
10777			// first, find the center of the bounding sphere
10778
10779			const center = this.boundingSphere.center;
10780
10781			_box$2.setFromBufferAttribute( position );
10782
10783			// process morph attributes if present
10784
10785			if ( morphAttributesPosition ) {
10786
10787				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10788
10789					const morphAttribute = morphAttributesPosition[ i ];
10790					_boxMorphTargets.setFromBufferAttribute( morphAttribute );
10791
10792					if ( this.morphTargetsRelative ) {
10793
10794						_vector$8.addVectors( _box$2.min, _boxMorphTargets.min );
10795						_box$2.expandByPoint( _vector$8 );
10796
10797						_vector$8.addVectors( _box$2.max, _boxMorphTargets.max );
10798						_box$2.expandByPoint( _vector$8 );
10799
10800					} else {
10801
10802						_box$2.expandByPoint( _boxMorphTargets.min );
10803						_box$2.expandByPoint( _boxMorphTargets.max );
10804
10805					}
10806
10807				}
10808
10809			}
10810
10811			_box$2.getCenter( center );
10812
10813			// second, try to find a boundingSphere with a radius smaller than the
10814			// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
10815
10816			let maxRadiusSq = 0;
10817
10818			for ( let i = 0, il = position.count; i < il; i ++ ) {
10819
10820				_vector$8.fromBufferAttribute( position, i );
10821
10822				maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10823
10824			}
10825
10826			// process morph attributes if present
10827
10828			if ( morphAttributesPosition ) {
10829
10830				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10831
10832					const morphAttribute = morphAttributesPosition[ i ];
10833					const morphTargetsRelative = this.morphTargetsRelative;
10834
10835					for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
10836
10837						_vector$8.fromBufferAttribute( morphAttribute, j );
10838
10839						if ( morphTargetsRelative ) {
10840
10841							_offset.fromBufferAttribute( position, j );
10842							_vector$8.add( _offset );
10843
10844						}
10845
10846						maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10847
10848					}
10849
10850				}
10851
10852			}
10853
10854			this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
10855
10856			if ( isNaN( this.boundingSphere.radius ) ) {
10857
10858				console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
10859
10860			}
10861
10862		}
10863
10864	}
10865
10866	computeTangents() {
10867
10868		const index = this.index;
10869		const attributes = this.attributes;
10870
10871		// based on http://www.terathon.com/code/tangent.html
10872		// (per vertex tangents)
10873
10874		if ( index === null ||
10875			 attributes.position === undefined ||
10876			 attributes.normal === undefined ||
10877			 attributes.uv === undefined ) {
10878
10879			console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
10880			return;
10881
10882		}
10883
10884		const positionAttribute = attributes.position;
10885		const normalAttribute = attributes.normal;
10886		const uvAttribute = attributes.uv;
10887
10888		if ( this.hasAttribute( 'tangent' ) === false ) {
10889
10890			this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) );
10891
10892		}
10893
10894		const tangentAttribute = this.getAttribute( 'tangent' );
10895
10896		const tan1 = [], tan2 = [];
10897
10898		for ( let i = 0; i < positionAttribute.count; i ++ ) {
10899
10900			tan1[ i ] = new Vector3();
10901			tan2[ i ] = new Vector3();
10902
10903		}
10904
10905		const vA = new Vector3(),
10906			vB = new Vector3(),
10907			vC = new Vector3(),
10908
10909			uvA = new Vector2(),
10910			uvB = new Vector2(),
10911			uvC = new Vector2(),
10912
10913			sdir = new Vector3(),
10914			tdir = new Vector3();
10915
10916		function handleTriangle( a, b, c ) {
10917
10918			vA.fromBufferAttribute( positionAttribute, a );
10919			vB.fromBufferAttribute( positionAttribute, b );
10920			vC.fromBufferAttribute( positionAttribute, c );
10921
10922			uvA.fromBufferAttribute( uvAttribute, a );
10923			uvB.fromBufferAttribute( uvAttribute, b );
10924			uvC.fromBufferAttribute( uvAttribute, c );
10925
10926			vB.sub( vA );
10927			vC.sub( vA );
10928
10929			uvB.sub( uvA );
10930			uvC.sub( uvA );
10931
10932			const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
10933
10934			// silently ignore degenerate uv triangles having coincident or colinear vertices
10935
10936			if ( ! isFinite( r ) ) return;
10937
10938			sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
10939			tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
10940
10941			tan1[ a ].add( sdir );
10942			tan1[ b ].add( sdir );
10943			tan1[ c ].add( sdir );
10944
10945			tan2[ a ].add( tdir );
10946			tan2[ b ].add( tdir );
10947			tan2[ c ].add( tdir );
10948
10949		}
10950
10951		let groups = this.groups;
10952
10953		if ( groups.length === 0 ) {
10954
10955			groups = [ {
10956				start: 0,
10957				count: index.count
10958			} ];
10959
10960		}
10961
10962		for ( let i = 0, il = groups.length; i < il; ++ i ) {
10963
10964			const group = groups[ i ];
10965
10966			const start = group.start;
10967			const count = group.count;
10968
10969			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
10970
10971				handleTriangle(
10972					index.getX( j + 0 ),
10973					index.getX( j + 1 ),
10974					index.getX( j + 2 )
10975				);
10976
10977			}
10978
10979		}
10980
10981		const tmp = new Vector3(), tmp2 = new Vector3();
10982		const n = new Vector3(), n2 = new Vector3();
10983
10984		function handleVertex( v ) {
10985
10986			n.fromBufferAttribute( normalAttribute, v );
10987			n2.copy( n );
10988
10989			const t = tan1[ v ];
10990
10991			// Gram-Schmidt orthogonalize
10992
10993			tmp.copy( t );
10994			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
10995
10996			// Calculate handedness
10997
10998			tmp2.crossVectors( n2, t );
10999			const test = tmp2.dot( tan2[ v ] );
11000			const w = ( test < 0.0 ) ? -
11000 1.0
vendor: 18,822 bytes, lines 11000-11859
11000 : 1.0;
11001
11002			tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w );
11003
11004		}
11005
11006		for ( let i = 0, il = groups.length; i < il; ++ i ) {
11007
11008			const group = groups[ i ];
11009
11010			const start = group.start;
11011			const count = group.count;
11012
11013			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
11014
11015				handleVertex( index.getX( j + 0 ) );
11016				handleVertex( index.getX( j + 1 ) );
11017				handleVertex( index.getX( j + 2 ) );
11018
11019			}
11020
11021		}
11022
11023	}
11024
11025	computeVertexNormals() {
11026
11027		const index = this.index;
11028		const positionAttribute = this.getAttribute( 'position' );
11029
11030		if ( positionAttribute !== undefined ) {
11031
11032			let normalAttribute = this.getAttribute( 'normal' );
11033
11034			if ( normalAttribute === undefined ) {
11035
11036				normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
11037				this.setAttribute( 'normal', normalAttribute );
11038
11039			} else {
11040
11041				// reset existing normals to zero
11042
11043				for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
11044
11045					normalAttribute.setXYZ( i, 0, 0, 0 );
11046
11047				}
11048
11049			}
11050
11051			const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
11052			const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
11053			const cb = new Vector3(), ab = new Vector3();
11054
11055			// indexed elements
11056
11057			if ( index ) {
11058
11059				for ( let i = 0, il = index.count; i < il; i += 3 ) {
11060
11061					const vA = index.getX( i + 0 );
11062					const vB = index.getX( i + 1 );
11063					const vC = index.getX( i + 2 );
11064
11065					pA.fromBufferAttribute( positionAttribute, vA );
11066					pB.fromBufferAttribute( positionAttribute, vB );
11067					pC.fromBufferAttribute( positionAttribute, vC );
11068
11069					cb.subVectors( pC, pB );
11070					ab.subVectors( pA, pB );
11071					cb.cross( ab );
11072
11073					nA.fromBufferAttribute( normalAttribute, vA );
11074					nB.fromBufferAttribute( normalAttribute, vB );
11075					nC.fromBufferAttribute( normalAttribute, vC );
11076
11077					nA.add( cb );
11078					nB.add( cb );
11079					nC.add( cb );
11080
11081					normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
11082					normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
11083					normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
11084
11085				}
11086
11087			} else {
11088
11089				// non-indexed elements (unconnected triangle soup)
11090
11091				for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
11092
11093					pA.fromBufferAttribute( positionAttribute, i + 0 );
11094					pB.fromBufferAttribute( positionAttribute, i + 1 );
11095					pC.fromBufferAttribute( positionAttribute, i + 2 );
11096
11097					cb.subVectors( pC, pB );
11098					ab.subVectors( pA, pB );
11099					cb.cross( ab );
11100
11101					normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
11102					normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
11103					normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
11104
11105				}
11106
11107			}
11108
11109			this.normalizeNormals();
11110
11111			normalAttribute.needsUpdate = true;
11112
11113		}
11114
11115	}
11116
11117	normalizeNormals() {
11118
11119		const normals = this.attributes.normal;
11120
11121		for ( let i = 0, il = normals.count; i < il; i ++ ) {
11122
11123			_vector$8.fromBufferAttribute( normals, i );
11124
11125			_vector$8.normalize();
11126
11127			normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
11128
11129		}
11130
11131	}
11132
11133	toNonIndexed() {
11134
11135		function convertBufferAttribute( attribute, indices ) {
11136
11137			const array = attribute.array;
11138			const itemSize = attribute.itemSize;
11139			const normalized = attribute.normalized;
11140
11141			const array2 = new array.constructor( indices.length * itemSize );
11142
11143			let index = 0, index2 = 0;
11144
11145			for ( let i = 0, l = indices.length; i < l; i ++ ) {
11146
11147				if ( attribute.isInterleavedBufferAttribute ) {
11148
11149					index = indices[ i ] * attribute.data.stride + attribute.offset;
11150
11151				} else {
11152
11153					index = indices[ i ] * itemSize;
11154
11155				}
11156
11157				for ( let j = 0; j < itemSize; j ++ ) {
11158
11159					array2[ index2 ++ ] = array[ index ++ ];
11160
11161				}
11162
11163			}
11164
11165			return new BufferAttribute( array2, itemSize, normalized );
11166
11167		}
11168
11169		//
11170
11171		if ( this.index === null ) {
11172
11173			console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
11174			return this;
11175
11176		}
11177
11178		const geometry2 = new BufferGeometry();
11179
11180		const indices = this.index.array;
11181		const attributes = this.attributes;
11182
11183		// attributes
11184
11185		for ( const name in attributes ) {
11186
11187			const attribute = attributes[ name ];
11188
11189			const newAttribute = convertBufferAttribute( attribute, indices );
11190
11191			geometry2.setAttribute( name, newAttribute );
11192
11193		}
11194
11195		// morph attributes
11196
11197		const morphAttributes = this.morphAttributes;
11198
11199		for ( const name in morphAttributes ) {
11200
11201			const morphArray = [];
11202			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
11203
11204			for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
11205
11206				const attribute = morphAttribute[ i ];
11207
11208				const newAttribute = convertBufferAttribute( attribute, indices );
11209
11210				morphArray.push( newAttribute );
11211
11212			}
11213
11214			geometry2.morphAttributes[ name ] = morphArray;
11215
11216		}
11217
11218		geometry2.morphTargetsRelative = this.morphTargetsRelative;
11219
11220		// groups
11221
11222		const groups = this.groups;
11223
11224		for ( let i = 0, l = groups.length; i < l; i ++ ) {
11225
11226			const group = groups[ i ];
11227			geometry2.addGroup( group.start, group.count, group.materialIndex );
11228
11229		}
11230
11231		return geometry2;
11232
11233	}
11234
11235	toJSON() {
11236
11237		const data = {
11238			metadata: {
11239				version: 4.6,
11240				type: 'BufferGeometry',
11241				generator: 'BufferGeometry.toJSON'
11242			}
11243		};
11244
11245		// standard BufferGeometry serialization
11246
11247		data.uuid = this.uuid;
11248		data.type = this.type;
11249		if ( this.name !== '' ) data.name = this.name;
11250		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
11251
11252		if ( this.parameters !== undefined ) {
11253
11254			const parameters = this.parameters;
11255
11256			for ( const key in parameters ) {
11257
11258				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
11259
11260			}
11261
11262			return data;
11263
11264		}
11265
11266		// for simplicity the code assumes attributes are not shared across geometries, see #15811
11267
11268		data.data = { attributes: {} };
11269
11270		const index = this.index;
11271
11272		if ( index !== null ) {
11273
11274			data.data.index = {
11275				type: index.array.constructor.name,
11276				array: Array.prototype.slice.call( index.array )
11277			};
11278
11279		}
11280
11281		const attributes = this.attributes;
11282
11283		for ( const key in attributes ) {
11284
11285			const attribute = attributes[ key ];
11286
11287			data.data.attributes[ key ] = attribute.toJSON( data.data );
11288
11289		}
11290
11291		const morphAttributes = {};
11292		let hasMorphAttributes = false;
11293
11294		for ( const key in this.morphAttributes ) {
11295
11296			const attributeArray = this.morphAttributes[ key ];
11297
11298			const array = [];
11299
11300			for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
11301
11302				const attribute = attributeArray[ i ];
11303
11304				array.push( attribute.toJSON( data.data ) );
11305
11306			}
11307
11308			if ( array.length > 0 ) {
11309
11310				morphAttributes[ key ] = array;
11311
11312				hasMorphAttributes = true;
11313
11314			}
11315
11316		}
11317
11318		if ( hasMorphAttributes ) {
11319
11320			data.data.morphAttributes = morphAttributes;
11321			data.data.morphTargetsRelative = this.morphTargetsRelative;
11322
11323		}
11324
11325		const groups = this.groups;
11326
11327		if ( groups.length > 0 ) {
11328
11329			data.data.groups = JSON.parse( JSON.stringify( groups ) );
11330
11331		}
11332
11333		const boundingSphere = this.boundingSphere;
11334
11335		if ( boundingSphere !== null ) {
11336
11337			data.data.boundingSphere = {
11338				center: boundingSphere.center.toArray(),
11339				radius: boundingSphere.radius
11340			};
11341
11342		}
11343
11344		return data;
11345
11346	}
11347
11348	clone() {
11349
11350		return new this.constructor().copy( this );
11351
11352	}
11353
11354	copy( source ) {
11355
11356		// reset
11357
11358		this.index = null;
11359		this.attributes = {};
11360		this.morphAttributes = {};
11361		this.groups = [];
11362		this.boundingBox = null;
11363		this.boundingSphere = null;
11364
11365		// used for storing cloned, shared data
11366
11367		const data = {};
11368
11369		// name
11370
11371		this.name = source.name;
11372
11373		// index
11374
11375		const index = source.index;
11376
11377		if ( index !== null ) {
11378
11379			this.setIndex( index.clone( data ) );
11380
11381		}
11382
11383		// attributes
11384
11385		const attributes = source.attributes;
11386
11387		for ( const name in attributes ) {
11388
11389			const attribute = attributes[ name ];
11390			this.setAttribute( name, attribute.clone( data ) );
11391
11392		}
11393
11394		// morph attributes
11395
11396		const morphAttributes = source.morphAttributes;
11397
11398		for ( const name in morphAttributes ) {
11399
11400			const array = [];
11401			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
11402
11403			for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
11404
11405				array.push( morphAttribute[ i ].clone( data ) );
11406
11407			}
11408
11409			this.morphAttributes[ name ] = array;
11410
11411		}
11412
11413		this.morphTargetsRelative = source.morphTargetsRelative;
11414
11415		// groups
11416
11417		const groups = source.groups;
11418
11419		for ( let i = 0, l = groups.length; i < l; i ++ ) {
11420
11421			const group = groups[ i ];
11422			this.addGroup( group.start, group.count, group.materialIndex );
11423
11424		}
11425
11426		// bounding box
11427
11428		const boundingBox = source.boundingBox;
11429
11430		if ( boundingBox !== null ) {
11431
11432			this.boundingBox = boundingBox.clone();
11433
11434		}
11435
11436		// bounding sphere
11437
11438		const boundingSphere = source.boundingSphere;
11439
11440		if ( boundingSphere !== null ) {
11441
11442			this.boundingSphere = boundingSphere.clone();
11443
11444		}
11445
11446		// draw range
11447
11448		this.drawRange.start = source.drawRange.start;
11449		this.drawRange.count = source.drawRange.count;
11450
11451		// user data
11452
11453		this.userData = source.userData;
11454
11455		return this;
11456
11457	}
11458
11459	dispose() {
11460
11461		this.dispatchEvent( { type: 'dispose' } );
11462
11463	}
11464
11465}
11466
11467const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4();
11468const _ray$3 = /*@__PURE__*/ new Ray();
11469const _sphere$6 = /*@__PURE__*/ new Sphere();
11470const _sphereHitAt = /*@__PURE__*/ new Vector3();
11471
11472const _vA$1 = /*@__PURE__*/ new Vector3();
11473const _vB$1 = /*@__PURE__*/ new Vector3();
11474const _vC$1 = /*@__PURE__*/ new Vector3();
11475
11476const _tempA = /*@__PURE__*/ new Vector3();
11477const _morphA = /*@__PURE__*/ new Vector3();
11478
11479const _uvA$1 = /*@__PURE__*/ new Vector2();
11480const _uvB$1 = /*@__PURE__*/ new Vector2();
11481const _uvC$1 = /*@__PURE__*/ new Vector2();
11482
11483const _normalA = /*@__PURE__*/ new Vector3();
11484const _normalB = /*@__PURE__*/ new Vector3();
11485const _normalC = /*@__PURE__*/ new Vector3();
11486
11487const _intersectionPoint = /*@__PURE__*/ new Vector3();
11488const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
11489
11490class Mesh extends Object3D {
11491
11492	constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
11493
11494		super();
11495
11496		this.isMesh = true;
11497
11498		this.type = 'Mesh';
11499
11500		this.geometry = geometry;
11501		this.material = material;
11502
11503		this.updateMorphTargets();
11504
11505	}
11506
11507	copy( source, recursive ) {
11508
11509		super.copy( source, recursive );
11510
11511		if ( source.morphTargetInfluences !== undefined ) {
11512
11513			this.morphTargetInfluences = source.morphTargetInfluences.slice();
11514
11515		}
11516
11517		if ( source.morphTargetDictionary !== undefined ) {
11518
11519			this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
11520
11521		}
11522
11523		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
11524		this.geometry = source.geometry;
11525
11526		return this;
11527
11528	}
11529
11530	updateMorphTargets() {
11531
11532		const geometry = this.geometry;
11533
11534		const morphAttributes = geometry.morphAttributes;
11535		const keys = Object.keys( morphAttributes );
11536
11537		if ( keys.length > 0 ) {
11538
11539			const morphAttribute = morphAttributes[ keys[ 0 ] ];
11540
11541			if ( morphAttribute !== undefined ) {
11542
11543				this.morphTargetInfluences = [];
11544				this.morphTargetDictionary = {};
11545
11546				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
11547
11548					const name = morphAttribute[ m ].name || String( m );
11549
11550					this.morphTargetInfluences.push( 0 );
11551					this.morphTargetDictionary[ name ] = m;
11552
11553				}
11554
11555			}
11556
11557		}
11558
11559	}
11560
11561	getVertexPosition( index, target ) {
11562
11563		const geometry = this.geometry;
11564		const position = geometry.attributes.position;
11565		const morphPosition = geometry.morphAttributes.position;
11566		const morphTargetsRelative = geometry.morphTargetsRelative;
11567
11568		target.fromBufferAttribute( position, index );
11569
11570		const morphInfluences = this.morphTargetInfluences;
11571
11572		if ( morphPosition && morphInfluences ) {
11573
11574			_morphA.set( 0, 0, 0 );
11575
11576			for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
11577
11578				const influence = morphInfluences[ i ];
11579				const morphAttribute = morphPosition[ i ];
11580
11581				if ( influence === 0 ) continue;
11582
11583				_tempA.fromBufferAttribute( morphAttribute, index );
11584
11585				if ( morphTargetsRelative ) {
11586
11587					_morphA.addScaledVector( _tempA, influence );
11588
11589				} else {
11590
11591					_morphA.addScaledVector( _tempA.sub( target ), influence );
11592
11593				}
11594
11595			}
11596
11597			target.add( _morphA );
11598
11599		}
11600
11601		return target;
11602
11603	}
11604
11605	raycast( raycaster, intersects ) {
11606
11607		const geometry = this.geometry;
11608		const material = this.material;
11609		const matrixWorld = this.matrixWorld;
11610
11611		if ( material === undefined ) return;
11612
11613		// test with bounding sphere in world space
11614
11615		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
11616
11617		_sphere$6.copy( geometry.boundingSphere );
11618		_sphere$6.applyMatrix4( matrixWorld );
11619
11620		// check distance from ray origin to bounding sphere
11621
11622		_ray$3.copy( raycaster.ray ).recast( raycaster.near );
11623
11624		if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) {
11625
11626			if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return;
11627
11628			if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return;
11629
11630		}
11631
11632		// convert ray to local space of mesh
11633
11634		_inverseMatrix$3.copy( matrixWorld ).invert();
11635		_ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 );
11636
11637		// test with bounding box in local space
11638
11639		if ( geometry.boundingBox !== null ) {
11640
11641			if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return;
11642
11643		}
11644
11645		// test for intersections with geometry
11646
11647		this._computeIntersections( raycaster, intersects, _ray$3 );
11648
11649	}
11650
11651	_computeIntersections( raycaster, intersects, rayLocalSpace ) {
11652
11653		let intersection;
11654
11655		const geometry = this.geometry;
11656		const material = this.material;
11657
11658		const index = geometry.index;
11659		const position = geometry.attributes.position;
11660		const uv = geometry.attributes.uv;
11661		const uv1 = geometry.attributes.uv1;
11662		const normal = geometry.attributes.normal;
11663		const groups = geometry.groups;
11664		const drawRange = geometry.drawRange;
11665
11666		if ( index !== null ) {
11667
11668			// indexed buffer geometry
11669
11670			if ( Array.isArray( material ) ) {
11671
11672				for ( let i = 0, il = groups.length; i < il; i ++ ) {
11673
11674					const group = groups[ i ];
11675					const groupMaterial = material[ group.materialIndex ];
11676
11677					const start = Math.max( group.start, drawRange.start );
11678					const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11679
11680					for ( let j = start, jl = end; j < jl; j += 3 ) {
11681
11682						const a = index.getX( j );
11683						const b = index.getX( j + 1 );
11684						const c = index.getX( j + 2 );
11685
11686						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11687
11688						if ( intersection ) {
11689
11690							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
11691							intersection.face.materialIndex = group.materialIndex;
11692							intersects.push( intersection );
11693
11694						}
11695
11696					}
11697
11698				}
11699
11700			} else {
11701
11702				const start = Math.max( 0, drawRange.start );
11703				const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
11704
11705				for ( let i = start, il = end; i < il; i += 3 ) {
11706
11707					const a = index.getX( i );
11708					const b = index.getX( i + 1 );
11709					const c = index.getX( i + 2 );
11710
11711					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11712
11713					if ( intersection ) {
11714
11715						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
11716						intersects.push( intersection );
11717
11718					}
11719
11720				}
11721
11722			}
11723
11724		} else if ( position !== undefined ) {
11725
11726			// non-indexed buffer geometry
11727
11728			if ( Array.isArray( material ) ) {
11729
11730				for ( let i = 0, il = groups.length; i < il; i ++ ) {
11731
11732					const group = groups[ i ];
11733					const groupMaterial = material[ group.materialIndex ];
11734
11735					const start = Math.max( group.start, drawRange.start );
11736					const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11737
11738					for ( let j = start, jl = end; j < jl; j += 3 ) {
11739
11740						const a = j;
11741						const b = j + 1;
11742						const c = j + 2;
11743
11744						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11745
11746						if ( intersection ) {
11747
11748							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
11749							intersection.face.materialIndex = group.materialIndex;
11750							intersects.push( intersection );
11751
11752						}
11753
11754					}
11755
11756				}
11757
11758			} else {
11759
11760				const start = Math.max( 0, drawRange.start );
11761				const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
11762
11763				for ( let i = start, il = end; i < il; i += 3 ) {
11764
11765					const a = i;
11766					const b = i + 1;
11767					const c = i + 2;
11768
11769					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11770
11771					if ( intersection ) {
11772
11773						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
11774						intersects.push( intersection );
11775
11776					}
11777
11778				}
11779
11780			}
11781
11782		}
11783
11784	}
11785
11786}
11787
11788function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {
11789
11790	let intersect;
11791
11792	if ( material.side === BackSide ) {
11793
11794		intersect = ray.intersectTriangle( pC, pB, pA, true, point );
11795
11796	} else {
11797
11798		intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point );
11799
11800	}
11801
11802	if ( intersect === null ) return null;
11803
11804	_intersectionPointWorld.copy( point );
11805	_intersectionPointWorld.applyMatrix4( object.matrixWorld );
11806
11807	const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
11808
11809	if ( distance < raycaster.near || distance > raycaster.far ) return null;
11810
11811	return {
11812		distance: distance,
11813		point: _intersectionPointWorld.clone(),
11814		object: object
11815	};
11816
11817}
11818
11819function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) {
11820
11821	object.getVertexPosition( a, _vA$1 );
11822	object.getVertexPosition( b, _vB$1 );
11823	object.getVertexPosition( c, _vC$1 );
11824
11825	const intersection = checkIntersection( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint );
11826
11827	if ( intersection ) {
11828
11829		if ( uv ) {
11830
11831			_uvA$1.fromBufferAttribute( uv, a );
11832			_uvB$1.fromBufferAttribute( uv, b );
11833			_uvC$1.fromBufferAttribute( uv, c );
11834
11835			intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
11836
11837		}
11838
11839		if ( uv1 ) {
11840
11841			_uvA$1.fromBufferAttribute( uv1, a );
11842			_uvB$1.fromBufferAttribute( uv1, b );
11843			_uvC$1.fromBufferAttribute( uv1, c );
11844
11845			intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
11846
11847		}
11848
11849		if ( normal ) {
11850
11851			_normalA.fromBufferAttribute( normal, a );
11852			_normalB.fromBufferAttribute( normal, b );
11853			_normalC.fromBufferAttribute( normal, c );
11854
11855			intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() );
11856
11857			if ( intersection.normal.dot( ray.direction ) > 0 ) {
11858
11859				intersection.normal.multiplyScalar( -
vendor: 6,710 bytes, lines 11859-12191
11859 1 );
11860
11861			}
11862
11863		}
11864
11865		const face = {
11866			a: a,
11867			b: b,
11868			c: c,
11869			normal: new Vector3(),
11870			materialIndex: 0
11871		};
11872
11873		Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal );
11874
11875		intersection.face = face;
11876
11877	}
11878
11879	return intersection;
11880
11881}
11882
11883class BoxGeometry extends BufferGeometry {
11884
11885	constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
11886
11887		super();
11888
11889		this.type = 'BoxGeometry';
11890
11891		this.parameters = {
11892			width: width,
11893			height: height,
11894			depth: depth,
11895			widthSegments: widthSegments,
11896			heightSegments: heightSegments,
11897			depthSegments: depthSegments
11898		};
11899
11900		const scope = this;
11901
11902		// segments
11903
11904		widthSegments = Math.floor( widthSegments );
11905		heightSegments = Math.floor( heightSegments );
11906		depthSegments = Math.floor( depthSegments );
11907
11908		// buffers
11909
11910		const indices = [];
11911		const vertices = [];
11912		const normals = [];
11913		const uvs = [];
11914
11915		// helper variables
11916
11917		let numberOfVertices = 0;
11918		let groupStart = 0;
11919
11920		// build each side of the box geometry
11921
11922		buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
11923		buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
11924		buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
11925		buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
11926		buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
11927		buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
11928
11929		// build geometry
11930
11931		this.setIndex( indices );
11932		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
11933		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
11934		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
11935
11936		function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
11937
11938			const segmentWidth = width / gridX;
11939			const segmentHeight = height / gridY;
11940
11941			const widthHalf = width / 2;
11942			const heightHalf = height / 2;
11943			const depthHalf = depth / 2;
11944
11945			const gridX1 = gridX + 1;
11946			const gridY1 = gridY + 1;
11947
11948			let vertexCounter = 0;
11949			let groupCount = 0;
11950
11951			const vector = new Vector3();
11952
11953			// generate vertices, normals and uvs
11954
11955			for ( let iy = 0; iy < gridY1; iy ++ ) {
11956
11957				const y = iy * segmentHeight - heightHalf;
11958
11959				for ( let ix = 0; ix < gridX1; ix ++ ) {
11960
11961					const x = ix * segmentWidth - widthHalf;
11962
11963					// set values to correct vector component
11964
11965					vector[ u ] = x * udir;
11966					vector[ v ] = y * vdir;
11967					vector[ w ] = depthHalf;
11968
11969					// now apply vector to vertex buffer
11970
11971					vertices.push( vector.x, vector.y, vector.z );
11972
11973					// set values to correct vector component
11974
11975					vector[ u ] = 0;
11976					vector[ v ] = 0;
11977					vector[ w ] = depth > 0 ? 1 : - 1;
11978
11979					// now apply vector to normal buffer
11980
11981					normals.push( vector.x, vector.y, vector.z );
11982
11983					// uvs
11984
11985					uvs.push( ix / gridX );
11986					uvs.push( 1 - ( iy / gridY ) );
11987
11988					// counters
11989
11990					vertexCounter += 1;
11991
11992				}
11993
11994			}
11995
11996			// indices
11997
11998			// 1. you need three indices to draw a single face
11999			// 2. a single segment consists of two faces
12000			// 3. so we need to generate six (2*3) indices per segment
12001
12002			for ( let iy = 0; iy < gridY; iy ++ ) {
12003
12004				for ( let ix = 0; ix < gridX; ix ++ ) {
12005
12006					const a = numberOfVertices + ix + gridX1 * iy;
12007					const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
12008					const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
12009					const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
12010
12011					// faces
12012
12013					indices.push( a, b, d );
12014					indices.push( b, c, d );
12015
12016					// increase counter
12017
12018					groupCount += 6;
12019
12020				}
12021
12022			}
12023
12024			// add a group to the geometry. this will ensure multi material support
12025
12026			scope.addGroup( groupStart, groupCount, materialIndex );
12027
12028			// calculate new start value for groups
12029
12030			groupStart += groupCount;
12031
12032			// update total number of vertices
12033
12034			numberOfVertices += vertexCounter;
12035
12036		}
12037
12038	}
12039
12040	copy( source ) {
12041
12042		super.copy( source );
12043
12044		this.parameters = Object.assign( {}, source.parameters );
12045
12046		return this;
12047
12048	}
12049
12050	static fromJSON( data ) {
12051
12052		return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
12053
12054	}
12055
12056}
12057
12058/**
12059 * Uniform Utilities
12060 */
12061
12062function cloneUniforms( src ) {
12063
12064	const dst = {};
12065
12066	for ( const u in src ) {
12067
12068		dst[ u ] = {};
12069
12070		for ( const p in src[ u ] ) {
12071
12072			const property = src[ u ][ p ];
12073
12074			if ( property && ( property.isColor ||
12075				property.isMatrix3 || property.isMatrix4 ||
12076				property.isVector2 || property.isVector3 || property.isVector4 ||
12077				property.isTexture || property.isQuaternion ) ) {
12078
12079				if ( property.isRenderTargetTexture ) {
12080
12081					console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' );
12082					dst[ u ][ p ] = null;
12083
12084				} else {
12085
12086					dst[ u ][ p ] = property.clone();
12087
12088				}
12089
12090			} else if ( Array.isArray( property ) ) {
12091
12092				dst[ u ][ p ] = property.slice();
12093
12094			} else {
12095
12096				dst[ u ][ p ] = property;
12097
12098			}
12099
12100		}
12101
12102	}
12103
12104	return dst;
12105
12106}
12107
12108function mergeUniforms( uniforms ) {
12109
12110	const merged = {};
12111
12112	for ( let u = 0; u < uniforms.length; u ++ ) {
12113
12114		const tmp = cloneUniforms( uniforms[ u ] );
12115
12116		for ( const p in tmp ) {
12117
12118			merged[ p ] = tmp[ p ];
12119
12120		}
12121
12122	}
12123
12124	return merged;
12125
12126}
12127
12128function cloneUniformsGroups( src ) {
12129
12130	const dst = [];
12131
12132	for ( let u = 0; u < src.length; u ++ ) {
12133
12134		dst.push( src[ u ].clone() );
12135
12136	}
12137
12138	return dst;
12139
12140}
12141
12142function getUnlitUniformColorSpace( renderer ) {
12143
12144	const currentRenderTarget = renderer.getRenderTarget();
12145
12146	if ( currentRenderTarget === null ) {
12147
12148		// https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398
12149		return renderer.outputColorSpace;
12150
12151	}
12152
12153	// https://github.com/mrdoob/three.js/issues/27868
12154	if ( currentRenderTarget.isXRRenderTarget === true ) {
12155
12156		return currentRenderTarget.texture.colorSpace;
12157
12158	}
12159
12160	return ColorManagement.workingColorSpace;
12161
12162}
12163
12164// Legacy
12165
12166const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
12167
12168var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
12169
12170var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
12171
12172class ShaderMaterial extends Material {
12173
12174	constructor( parameters ) {
12175
12176		super();
12177
12178		this.isShaderMaterial = true;
12179
12180		this.type = 'ShaderMaterial';
12181
12182		this.defines = {};
12183		this.uniforms = {};
12184		this.uniformsGroups = [];
12185
12186		this.vertexShader = default_vertex;
12187		this.fragmentShader = default_fragment;
12188
12189		this.linewidth = 1;
12190
12191		this.wireframe = false;
vendor: 5,162 bytes, lines 12192-12454
12192		this.wireframeLinewidth = 1;
12193
12194		this.fog = false; // set to use scene fog
12195		this.lights = false; // set to use scene lights
12196		this.clipping = false; // set to use user-defined clipping planes
12197
12198		this.forceSinglePass = true;
12199
12200		this.extensions = {
12201			clipCullDistance: false, // set to use vertex shader clipping
12202			multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID
12203		};
12204
12205		// When rendered geometry doesn't include these attributes but the material does,
12206		// use these default values in WebGL. This avoids errors when buffer data is missing.
12207		this.defaultAttributeValues = {
12208			'color': [ 1, 1, 1 ],
12209			'uv': [ 0, 0 ],
12210			'uv1': [ 0, 0 ]
12211		};
12212
12213		this.index0AttributeName = undefined;
12214		this.uniformsNeedUpdate = false;
12215
12216		this.glslVersion = null;
12217
12218		if ( parameters !== undefined ) {
12219
12220			this.setValues( parameters );
12221
12222		}
12223
12224	}
12225
12226	copy( source ) {
12227
12228		super.copy( source );
12229
12230		this.fragmentShader = source.fragmentShader;
12231		this.vertexShader = source.vertexShader;
12232
12233		this.uniforms = cloneUniforms( source.uniforms );
12234		this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups );
12235
12236		this.defines = Object.assign( {}, source.defines );
12237
12238		this.wireframe = source.wireframe;
12239		this.wireframeLinewidth = source.wireframeLinewidth;
12240
12241		this.fog = source.fog;
12242		this.lights = source.lights;
12243		this.clipping = source.clipping;
12244
12245		this.extensions = Object.assign( {}, source.extensions );
12246
12247		this.glslVersion = source.glslVersion;
12248
12249		return this;
12250
12251	}
12252
12253	toJSON( meta ) {
12254
12255		const data = super.toJSON( meta );
12256
12257		data.glslVersion = this.glslVersion;
12258		data.uniforms = {};
12259
12260		for ( const name in this.uniforms ) {
12261
12262			const uniform = this.uniforms[ name ];
12263			const value = uniform.value;
12264
12265			if ( value && value.isTexture ) {
12266
12267				data.uniforms[ name ] = {
12268					type: 't',
12269					value: value.toJSON( meta ).uuid
12270				};
12271
12272			} else if ( value && value.isColor ) {
12273
12274				data.uniforms[ name ] = {
12275					type: 'c',
12276					value: value.getHex()
12277				};
12278
12279			} else if ( value && value.isVector2 ) {
12280
12281				data.uniforms[ name ] = {
12282					type: 'v2',
12283					value: value.toArray()
12284				};
12285
12286			} else if ( value && value.isVector3 ) {
12287
12288				data.uniforms[ name ] = {
12289					type: 'v3',
12290					value: value.toArray()
12291				};
12292
12293			} else if ( value && value.isVector4 ) {
12294
12295				data.uniforms[ name ] = {
12296					type: 'v4',
12297					value: value.toArray()
12298				};
12299
12300			} else if ( value && value.isMatrix3 ) {
12301
12302				data.uniforms[ name ] = {
12303					type: 'm3',
12304					value: value.toArray()
12305				};
12306
12307			} else if ( value && value.isMatrix4 ) {
12308
12309				data.uniforms[ name ] = {
12310					type: 'm4',
12311					value: value.toArray()
12312				};
12313
12314			} else {
12315
12316				data.uniforms[ name ] = {
12317					value: value
12318				};
12319
12320				// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
12321
12322			}
12323
12324		}
12325
12326		if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
12327
12328		data.vertexShader = this.vertexShader;
12329		data.fragmentShader = this.fragmentShader;
12330
12331		data.lights = this.lights;
12332		data.clipping = this.clipping;
12333
12334		const extensions = {};
12335
12336		for ( const key in this.extensions ) {
12337
12338			if ( this.extensions[ key ] === true ) extensions[ key ] = true;
12339
12340		}
12341
12342		if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
12343
12344		return data;
12345
12346	}
12347
12348}
12349
12350class Camera extends Object3D {
12351
12352	constructor() {
12353
12354		super();
12355
12356		this.isCamera = true;
12357
12358		this.type = 'Camera';
12359
12360		this.matrixWorldInverse = new Matrix4();
12361
12362		this.projectionMatrix = new Matrix4();
12363		this.projectionMatrixInverse = new Matrix4();
12364
12365		this.coordinateSystem = WebGLCoordinateSystem;
12366
12367	}
12368
12369	copy( source, recursive ) {
12370
12371		super.copy( source, recursive );
12372
12373		this.matrixWorldInverse.copy( source.matrixWorldInverse );
12374
12375		this.projectionMatrix.copy( source.projectionMatrix );
12376		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
12377
12378		this.coordinateSystem = source.coordinateSystem;
12379
12380		return this;
12381
12382	}
12383
12384	getWorldDirection( target ) {
12385
12386		return super.getWorldDirection( target ).negate();
12387
12388	}
12389
12390	updateMatrixWorld( force ) {
12391
12392		super.updateMatrixWorld( force );
12393
12394		this.matrixWorldInverse.copy( this.matrixWorld ).invert();
12395
12396	}
12397
12398	updateWorldMatrix( updateParents, updateChildren ) {
12399
12400		super.updateWorldMatrix( updateParents, updateChildren );
12401
12402		this.matrixWorldInverse.copy( this.matrixWorld ).invert();
12403
12404	}
12405
12406	clone() {
12407
12408		return new this.constructor().copy( this );
12409
12410	}
12411
12412}
12413
12414const _v3$1 = /*@__PURE__*/ new Vector3();
12415const _minTarget = /*@__PURE__*/ new Vector2();
12416const _maxTarget = /*@__PURE__*/ new Vector2();
12417
12418
12419class PerspectiveCamera extends Camera {
12420
12421	constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
12422
12423		super();
12424
12425		this.isPerspectiveCamera = true;
12426
12427		this.type = 'PerspectiveCamera';
12428
12429		this.fov = fov;
12430		this.zoom = 1;
12431
12432		this.near = near;
12433		this.far = far;
12434		this.focus = 10;
12435
12436		this.aspect = aspect;
12437		this.view = null;
12438
12439		this.filmGauge = 35;	// width of the film (default in millimeters)
12440		this.filmOffset = 0;	// horizontal film offset (same unit as gauge)
12441
12442		this.updateProjectionMatrix();
12443
12444	}
12445
12446	copy( source, recursive ) {
12447
12448		super.copy( source, recursive );
12449
12450		this.fov = source.fov;
12451		this.zoom = source.zoom;
12452
12453		this.near = source.near;
12454		this.far = source.far;
vendor: 4,346 bytes, lines 12455-12628
12455		this.focus = source.focus;
12456
12457		this.aspect = source.aspect;
12458		this.view = source.view === null ? null : Object.assign( {}, source.view );
12459
12460		this.filmGauge = source.filmGauge;
12461		this.filmOffset = source.filmOffset;
12462
12463		return this;
12464
12465	}
12466
12467	/**
12468	 * Sets the FOV by focal length in respect to the current .filmGauge.
12469	 *
12470	 * The default film gauge is 35, so that the focal length can be specified for
12471	 * a 35mm (full frame) camera.
12472	 *
12473	 * Values for focal length and film gauge must have the same unit.
12474	 */
12475	setFocalLength( focalLength ) {
12476
12477		/** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
12478		const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
12479
12480		this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
12481		this.updateProjectionMatrix();
12482
12483	}
12484
12485	/**
12486	 * Calculates the focal length from the current .fov and .filmGauge.
12487	 */
12488	getFocalLength() {
12489
12490		const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
12491
12492		return 0.5 * this.getFilmHeight() / vExtentSlope;
12493
12494	}
12495
12496	getEffectiveFOV() {
12497
12498		return RAD2DEG * 2 * Math.atan(
12499			Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
12500
12501	}
12502
12503	getFilmWidth() {
12504
12505		// film not completely covered in portrait format (aspect < 1)
12506		return this.filmGauge * Math.min( this.aspect, 1 );
12507
12508	}
12509
12510	getFilmHeight() {
12511
12512		// film not completely covered in landscape format (aspect > 1)
12513		return this.filmGauge / Math.max( this.aspect, 1 );
12514
12515	}
12516
12517	/**
12518	 * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction.
12519	 * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle.
12520	 */
12521	getViewBounds( distance, minTarget, maxTarget ) {
12522
12523		_v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
12524
12525		minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
12526
12527		_v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
12528
12529		maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
12530
12531	}
12532
12533	/**
12534	 * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction.
12535	 * Copies the result into the target Vector2, where x is width and y is height.
12536	 */
12537	getViewSize( distance, target ) {
12538
12539		this.getViewBounds( distance, _minTarget, _maxTarget );
12540
12541		return target.subVectors( _maxTarget, _minTarget );
12542
12543	}
12544
12545	/**
12546	 * Sets an offset in a larger frustum. This is useful for multi-window or
12547	 * multi-monitor/multi-machine setups.
12548	 *
12549	 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
12550	 * the monitors are in grid like this
12551	 *
12552	 *   +---+---+---+
12553	 *   | A | B | C |
12554	 *   +---+---+---+
12555	 *   | D | E | F |
12556	 *   +---+---+---+
12557	 *
12558	 * then for each monitor you would call it like this
12559	 *
12560	 *   const w = 1920;
12561	 *   const h = 1080;
12562	 *   const fullWidth = w * 3;
12563	 *   const fullHeight = h * 2;
12564	 *
12565	 *   --A--
12566	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
12567	 *   --B--
12568	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
12569	 *   --C--
12570	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
12571	 *   --D--
12572	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
12573	 *   --E--
12574	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
12575	 *   --F--
12576	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
12577	 *
12578	 *   Note there is no reason monitors have to be the same size or in a grid.
12579	 */
12580	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
12581
12582		this.aspect = fullWidth / fullHeight;
12583
12584		if ( this.view === null ) {
12585
12586			this.view = {
12587				enabled: true,
12588				fullWidth: 1,
12589				fullHeight: 1,
12590				offsetX: 0,
12591				offsetY: 0,
12592				width: 1,
12593				height: 1
12594			};
12595
12596		}
12597
12598		this.view.enabled = true;
12599		this.view.fullWidth = fullWidth;
12600		this.view.fullHeight = fullHeight;
12601		this.view.offsetX = x;
12602		this.view.offsetY = y;
12603		this.view.width = width;
12604		this.view.height = height;
12605
12606		this.updateProjectionMatrix();
12607
12608	}
12609
12610	clearViewOffset() {
12611
12612		if ( this.view !== null ) {
12613
12614			this.view.enabled = false;
12615
12616		}
12617
12618		this.updateProjectionMatrix();
12619
12620	}
12621
12622	updateProjectionMatrix() {
12623
12624		const near = this.near;
12625		let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
12626		let height = 2 * top;
12627		let width = this.aspect * height;
12628		let left = - 0.5 * width;
vendor: 3,266 bytes, lines 12629-12765
12629		const view = this.view;
12630
12631		if ( this.view !== null && this.view.enabled ) {
12632
12633			const fullWidth = view.fullWidth,
12634				fullHeight = view.fullHeight;
12635
12636			left += view.offsetX * width / fullWidth;
12637			top -= view.offsetY * height / fullHeight;
12638			width *= view.width / fullWidth;
12639			height *= view.height / fullHeight;
12640
12641		}
12642
12643		const skew = this.filmOffset;
12644		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
12645
12646		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem );
12647
12648		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
12649
12650	}
12651
12652	toJSON( meta ) {
12653
12654		const data = super.toJSON( meta );
12655
12656		data.object.fov = this.fov;
12657		data.object.zoom = this.zoom;
12658
12659		data.object.near = this.near;
12660		data.object.far = this.far;
12661		data.object.focus = this.focus;
12662
12663		data.object.aspect = this.aspect;
12664
12665		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
12666
12667		data.object.filmGauge = this.filmGauge;
12668		data.object.filmOffset = this.filmOffset;
12669
12670		return data;
12671
12672	}
12673
12674}
12675
12676const fov = - 90; // negative fov is not an error
12677const aspect = 1;
12678
12679class CubeCamera extends Object3D {
12680
12681	constructor( near, far, renderTarget ) {
12682
12683		super();
12684
12685		this.type = 'CubeCamera';
12686
12687		this.renderTarget = renderTarget;
12688		this.coordinateSystem = null;
12689		this.activeMipmapLevel = 0;
12690
12691		const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
12692		cameraPX.layers = this.layers;
12693		this.add( cameraPX );
12694
12695		const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
12696		cameraNX.layers = this.layers;
12697		this.add( cameraNX );
12698
12699		const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
12700		cameraPY.layers = this.layers;
12701		this.add( cameraPY );
12702
12703		const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
12704		cameraNY.layers = this.layers;
12705		this.add( cameraNY );
12706
12707		const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
12708		cameraPZ.layers = this.layers;
12709		this.add( cameraPZ );
12710
12711		const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
12712		cameraNZ.layers = this.layers;
12713		this.add( cameraNZ );
12714
12715	}
12716
12717	updateCoordinateSystem() {
12718
12719		const coordinateSystem = this.coordinateSystem;
12720
12721		const cameras = this.children.concat();
12722
12723		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
12724
12725		for ( const camera of cameras ) this.remove( camera );
12726
12727		if ( coordinateSystem === WebGLCoordinateSystem ) {
12728
12729			cameraPX.up.set( 0, 1, 0 );
12730			cameraPX.lookAt( 1, 0, 0 );
12731
12732			cameraNX.up.set( 0, 1, 0 );
12733			cameraNX.lookAt( - 1, 0, 0 );
12734
12735			cameraPY.up.set( 0, 0, - 1 );
12736			cameraPY.lookAt( 0, 1, 0 );
12737
12738			cameraNY.up.set( 0, 0, 1 );
12739			cameraNY.lookAt( 0, - 1, 0 );
12740
12741			cameraPZ.up.set( 0, 1, 0 );
12742			cameraPZ.lookAt( 0, 0, 1 );
12743
12744			cameraNZ.up.set( 0, 1, 0 );
12745			cameraNZ.lookAt( 0, 0, - 1 );
12746
12747		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
12748
12749			cameraPX.up.set( 0, - 1, 0 );
12750			cameraPX.lookAt( - 1, 0, 0 );
12751
12752			cameraNX.up.set( 0, - 1, 0 );
12753			cameraNX.lookAt( 1, 0, 0 );
12754
12755			cameraPY.up.set( 0, 0, 1 );
12756			cameraPY.lookAt( 0, 1, 0 );
12757
12758			cameraNY.up.set( 0, 0, - 1 );
12759			cameraNY.lookAt( 0, - 1, 0 );
12760
12761			cameraPZ.up.set( 0, - 1, 0 );
12762			cameraPZ.lookAt( 0, 0, 1 );
12763
12764			cameraNZ.up.set( 0, - 1, 0 );
12765			cameraNZ.lookAt( 0, 0, - 
vendor: 7,494 bytes, lines 12765-13088
127651 );
12766
12767		} else {
12768
12769			throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
12770
12771		}
12772
12773		for ( const camera of cameras ) {
12774
12775			this.add( camera );
12776
12777			camera.updateMatrixWorld();
12778
12779		}
12780
12781	}
12782
12783	update( renderer, scene ) {
12784
12785		if ( this.parent === null ) this.updateMatrixWorld();
12786
12787		const { renderTarget, activeMipmapLevel } = this;
12788
12789		if ( this.coordinateSystem !== renderer.coordinateSystem ) {
12790
12791			this.coordinateSystem = renderer.coordinateSystem;
12792
12793			this.updateCoordinateSystem();
12794
12795		}
12796
12797		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
12798
12799		const currentRenderTarget = renderer.getRenderTarget();
12800		const currentActiveCubeFace = renderer.getActiveCubeFace();
12801		const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
12802
12803		const currentXrEnabled = renderer.xr.enabled;
12804
12805		renderer.xr.enabled = false;
12806
12807		const generateMipmaps = renderTarget.texture.generateMipmaps;
12808
12809		renderTarget.texture.generateMipmaps = false;
12810
12811		renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
12812		renderer.render( scene, cameraPX );
12813
12814		renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
12815		renderer.render( scene, cameraNX );
12816
12817		renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
12818		renderer.render( scene, cameraPY );
12819
12820		renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
12821		renderer.render( scene, cameraNY );
12822
12823		renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
12824		renderer.render( scene, cameraPZ );
12825
12826		// mipmaps are generated during the last call of render()
12827		// at this point, all sides of the cube render target are defined
12828
12829		renderTarget.texture.generateMipmaps = generateMipmaps;
12830
12831		renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
12832		renderer.render( scene, cameraNZ );
12833
12834		renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
12835
12836		renderer.xr.enabled = currentXrEnabled;
12837
12838		renderTarget.texture.needsPMREMUpdate = true;
12839
12840	}
12841
12842}
12843
12844class CubeTexture extends Texture {
12845
12846	constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
12847
12848		images = images !== undefined ? images : [];
12849		mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
12850
12851		super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
12852
12853		this.isCubeTexture = true;
12854
12855		this.flipY = false;
12856
12857	}
12858
12859	get images() {
12860
12861		return this.image;
12862
12863	}
12864
12865	set images( value ) {
12866
12867		this.image = value;
12868
12869	}
12870
12871}
12872
12873class WebGLCubeRenderTarget extends WebGLRenderTarget {
12874
12875	constructor( size = 1, options = {} ) {
12876
12877		super( size, size, options );
12878
12879		this.isWebGLCubeRenderTarget = true;
12880
12881		const image = { width: size, height: size, depth: 1 };
12882		const images = [ image, image, image, image, image, image ];
12883
12884		this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
12885
12886		// By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
12887		// in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
12888		// in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
12889
12890		// three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
12891		// and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
12892		// as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
12893
12894		this.texture.isRenderTargetTexture = true;
12895
12896		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
12897		this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
12898
12899	}
12900
12901	fromEquirectangularTexture( renderer, texture ) {
12902
12903		this.texture.type = texture.type;
12904		this.texture.colorSpace = texture.colorSpace;
12905
12906		this.texture.generateMipmaps = texture.generateMipmaps;
12907		this.texture.minFilter = texture.minFilter;
12908		this.texture.magFilter = texture.magFilter;
12909
12910		const shader = {
12911
12912			uniforms: {
12913				tEquirect: { value: null },
12914			},
12915
12916			vertexShader: /* glsl */`
12917
12918				varying vec3 vWorldDirection;
12919
12920				vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
12921
12922					return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
12923
12924				}
12925
12926				void main() {
12927
12928					vWorldDirection = transformDirection( position, modelMatrix );
12929
12930					#include <begin_vertex>
12931					#include <project_vertex>
12932
12933				}
12934			`,
12935
12936			fragmentShader: /* glsl */`
12937
12938				uniform sampler2D tEquirect;
12939
12940				varying vec3 vWorldDirection;
12941
12942				#include <common>
12943
12944				void main() {
12945
12946					vec3 direction = normalize( vWorldDirection );
12947
12948					vec2 sampleUV = equirectUv( direction );
12949
12950					gl_FragColor = texture2D( tEquirect, sampleUV );
12951
12952				}
12953			`
12954		};
12955
12956		const geometry = new BoxGeometry( 5, 5, 5 );
12957
12958		const material = new ShaderMaterial( {
12959
12960			name: 'CubemapFromEquirect',
12961
12962			uniforms: cloneUniforms( shader.uniforms ),
12963			vertexShader: shader.vertexShader,
12964			fragmentShader: shader.fragmentShader,
12965			side: BackSide,
12966			blending: NoBlending
12967
12968		} );
12969
12970		material.uniforms.tEquirect.value = texture;
12971
12972		const mesh = new Mesh( geometry, material );
12973
12974		const currentMinFilter = texture.minFilter;
12975
12976		// Avoid blurred poles
12977		if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
12978
12979		const camera = new CubeCamera( 1, 10, this );
12980		camera.update( renderer, mesh );
12981
12982		texture.minFilter = currentMinFilter;
12983
12984		mesh.geometry.dispose();
12985		mesh.material.dispose();
12986
12987		return this;
12988
12989	}
12990
12991	clear( renderer, color, depth, stencil ) {
12992
12993		const currentRenderTarget = renderer.getRenderTarget();
12994
12995		for ( let i = 0; i < 6; i ++ ) {
12996
12997			renderer.setRenderTarget( this, i );
12998
12999			renderer.clear( color, depth, stencil );
13000
13001		}
13002
13003		renderer.setRenderTarget( currentRenderTarget );
13004
13005	}
13006
13007}
13008
13009const _vector1 = /*@__PURE__*/ new Vector3();
13010const _vector2 = /*@__PURE__*/ new Vector3();
13011const _normalMatrix = /*@__PURE__*/ new Matrix3();
13012
13013class Plane {
13014
13015	constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) {
13016
13017		this.isPlane = true;
13018
13019		// normal is assumed to be normalized
13020
13021		this.normal = normal;
13022		this.constant = constant;
13023
13024	}
13025
13026	set( normal, constant ) {
13027
13028		this.normal.copy( normal );
13029		this.constant = constant;
13030
13031		return this;
13032
13033	}
13034
13035	setComponents( x, y, z, w ) {
13036
13037		this.normal.set( x, y, z );
13038		this.constant = w;
13039
13040		return this;
13041
13042	}
13043
13044	setFromNormalAndCoplanarPoint( normal, point ) {
13045
13046		this.normal.copy( normal );
13047		this.constant = - point.dot( this.normal );
13048
13049		return this;
13050
13051	}
13052
13053	setFromCoplanarPoints( a, b, c ) {
13054
13055		const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
13056
13057		// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
13058
13059		this.setFromNormalAndCoplanarPoint( normal, a );
13060
13061		return this;
13062
13063	}
13064
13065	copy( plane ) {
13066
13067		this.normal.copy( plane.normal );
13068		this.constant = plane.constant;
13069
13070		return this;
13071
13072	}
13073
13074	normalize() {
13075
13076		// Note: will lead to a divide by zero if the plane is invalid.
13077
13078		const inverseNormalLength = 1.0 / this.normal.length();
13079		this.normal.multiplyScalar( inverseNormalLength );
13080		this.constant *= inverseNormalLength;
13081
13082		return this;
13083
13084	}
13085
13086	negate() {
13087
13088		this.constant *= -
vendor: 8,824 bytes, lines 13088-13552
13088 1;
13089		this.normal.negate();
13090
13091		return this;
13092
13093	}
13094
13095	distanceToPoint( point ) {
13096
13097		return this.normal.dot( point ) + this.constant;
13098
13099	}
13100
13101	distanceToSphere( sphere ) {
13102
13103		return this.distanceToPoint( sphere.center ) - sphere.radius;
13104
13105	}
13106
13107	projectPoint( point, target ) {
13108
13109		return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) );
13110
13111	}
13112
13113	intersectLine( line, target ) {
13114
13115		const direction = line.delta( _vector1 );
13116
13117		const denominator = this.normal.dot( direction );
13118
13119		if ( denominator === 0 ) {
13120
13121			// line is coplanar, return origin
13122			if ( this.distanceToPoint( line.start ) === 0 ) {
13123
13124				return target.copy( line.start );
13125
13126			}
13127
13128			// Unsure if this is the correct method to handle this case.
13129			return null;
13130
13131		}
13132
13133		const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
13134
13135		if ( t < 0 || t > 1 ) {
13136
13137			return null;
13138
13139		}
13140
13141		return target.copy( line.start ).addScaledVector( direction, t );
13142
13143	}
13144
13145	intersectsLine( line ) {
13146
13147		// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
13148
13149		const startSign = this.distanceToPoint( line.start );
13150		const endSign = this.distanceToPoint( line.end );
13151
13152		return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
13153
13154	}
13155
13156	intersectsBox( box ) {
13157
13158		return box.intersectsPlane( this );
13159
13160	}
13161
13162	intersectsSphere( sphere ) {
13163
13164		return sphere.intersectsPlane( this );
13165
13166	}
13167
13168	coplanarPoint( target ) {
13169
13170		return target.copy( this.normal ).multiplyScalar( - this.constant );
13171
13172	}
13173
13174	applyMatrix4( matrix, optionalNormalMatrix ) {
13175
13176		const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
13177
13178		const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
13179
13180		const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
13181
13182		this.constant = - referencePoint.dot( normal );
13183
13184		return this;
13185
13186	}
13187
13188	translate( offset ) {
13189
13190		this.constant -= offset.dot( this.normal );
13191
13192		return this;
13193
13194	}
13195
13196	equals( plane ) {
13197
13198		return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
13199
13200	}
13201
13202	clone() {
13203
13204		return new this.constructor().copy( this );
13205
13206	}
13207
13208}
13209
13210const _sphere$5 = /*@__PURE__*/ new Sphere();
13211const _vector$7 = /*@__PURE__*/ new Vector3();
13212
13213class Frustum {
13214
13215	constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
13216
13217		this.planes = [ p0, p1, p2, p3, p4, p5 ];
13218
13219	}
13220
13221	set( p0, p1, p2, p3, p4, p5 ) {
13222
13223		const planes = this.planes;
13224
13225		planes[ 0 ].copy( p0 );
13226		planes[ 1 ].copy( p1 );
13227		planes[ 2 ].copy( p2 );
13228		planes[ 3 ].copy( p3 );
13229		planes[ 4 ].copy( p4 );
13230		planes[ 5 ].copy( p5 );
13231
13232		return this;
13233
13234	}
13235
13236	copy( frustum ) {
13237
13238		const planes = this.planes;
13239
13240		for ( let i = 0; i < 6; i ++ ) {
13241
13242			planes[ i ].copy( frustum.planes[ i ] );
13243
13244		}
13245
13246		return this;
13247
13248	}
13249
13250	setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) {
13251
13252		const planes = this.planes;
13253		const me = m.elements;
13254		const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
13255		const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
13256		const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
13257		const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
13258
13259		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
13260		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
13261		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
13262		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
13263		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
13264
13265		if ( coordinateSystem === WebGLCoordinateSystem ) {
13266
13267			planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
13268
13269		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
13270
13271			planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
13272
13273		} else {
13274
13275			throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
13276
13277		}
13278
13279		return this;
13280
13281	}
13282
13283	intersectsObject( object ) {
13284
13285		if ( object.boundingSphere !== undefined ) {
13286
13287			if ( object.boundingSphere === null ) object.computeBoundingSphere();
13288
13289			_sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld );
13290
13291		} else {
13292
13293			const geometry = object.geometry;
13294
13295			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
13296
13297			_sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
13298
13299		}
13300
13301		return this.intersectsSphere( _sphere$5 );
13302
13303	}
13304
13305	intersectsSprite( sprite ) {
13306
13307		_sphere$5.center.set( 0, 0, 0 );
13308		_sphere$5.radius = 0.7071067811865476;
13309		_sphere$5.applyMatrix4( sprite.matrixWorld );
13310
13311		return this.intersectsSphere( _sphere$5 );
13312
13313	}
13314
13315	intersectsSphere( sphere ) {
13316
13317		const planes = this.planes;
13318		const center = sphere.center;
13319		const negRadius = - sphere.radius;
13320
13321		for ( let i = 0; i < 6; i ++ ) {
13322
13323			const distance = planes[ i ].distanceToPoint( center );
13324
13325			if ( distance < negRadius ) {
13326
13327				return false;
13328
13329			}
13330
13331		}
13332
13333		return true;
13334
13335	}
13336
13337	intersectsBox( box ) {
13338
13339		const planes = this.planes;
13340
13341		for ( let i = 0; i < 6; i ++ ) {
13342
13343			const plane = planes[ i ];
13344
13345			// corner at max distance
13346
13347			_vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x;
13348			_vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y;
13349			_vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z;
13350
13351			if ( plane.distanceToPoint( _vector$7 ) < 0 ) {
13352
13353				return false;
13354
13355			}
13356
13357		}
13358
13359		return true;
13360
13361	}
13362
13363	containsPoint( point ) {
13364
13365		const planes = this.planes;
13366
13367		for ( let i = 0; i < 6; i ++ ) {
13368
13369			if ( planes[ i ].distanceToPoint( point ) < 0 ) {
13370
13371				return false;
13372
13373			}
13374
13375		}
13376
13377		return true;
13378
13379	}
13380
13381	clone() {
13382
13383		return new this.constructor().copy( this );
13384
13385	}
13386
13387}
13388
13389function WebGLAnimation() {
13390
13391	let context = null;
13392	let isAnimating = false;
13393	let animationLoop = null;
13394	let requestId = null;
13395
13396	function onAnimationFrame( time, frame ) {
13397
13398		animationLoop( time, frame );
13399
13400		requestId = context.requestAnimationFrame( onAnimationFrame );
13401
13402	}
13403
13404	return {
13405
13406		start: function () {
13407
13408			if ( isAnimating === true ) return;
13409			if ( animationLoop === null ) return;
13410
13411			requestId = context.requestAnimationFrame( onAnimationFrame );
13412
13413			isAnimating = true;
13414
13415		},
13416
13417		stop: function () {
13418
13419			context.cancelAnimationFrame( requestId );
13420
13421			isAnimating = false;
13422
13423		},
13424
13425		setAnimationLoop: function ( callback ) {
13426
13427			animationLoop = callback;
13428
13429		},
13430
13431		setContext: function ( value ) {
13432
13433			context = value;
13434
13435		}
13436
13437	};
13438
13439}
13440
13441function WebGLAttributes( gl ) {
13442
13443	const buffers = new WeakMap();
13444
13445	function createBuffer( attribute, bufferType ) {
13446
13447		const array = attribute.array;
13448		const usage = attribute.usage;
13449		const size = array.byteLength;
13450
13451		const buffer = gl.createBuffer();
13452
13453		gl.bindBuffer( bufferType, buffer );
13454		gl.bufferData( bufferType, array, usage );
13455
13456		attribute.onUploadCallback();
13457
13458		let type;
13459
13460		if ( array instanceof Float32Array ) {
13461
13462			type = gl.FLOAT;
13463
13464		} else if ( array instanceof Uint16Array ) {
13465
13466			if ( attribute.isFloat16BufferAttribute ) {
13467
13468				type = gl.HALF_FLOAT;
13469
13470			} else {
13471
13472				type = gl.UNSIGNED_SHORT;
13473
13474			}
13475
13476		} else if ( array instanceof Int16Array ) {
13477
13478			type = gl.SHORT;
13479
13480		} else if ( array instanceof Uint32Array ) {
13481
13482			type = gl.UNSIGNED_INT;
13483
13484		} else if ( array instanceof Int32Array ) {
13485
13486			type = gl.INT;
13487
13488		} else if ( array instanceof Int8Array ) {
13489
13490			type = gl.BYTE;
13491
13492		} else if ( array instanceof Uint8Array ) {
13493
13494			type = gl.UNSIGNED_BYTE;
13495
13496		} else if ( array instanceof Uint8ClampedArray ) {
13497
13498			type = gl.UNSIGNED_BYTE;
13499
13500		} else {
13501
13502			throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array );
13503
13504		}
13505
13506		return {
13507			buffer: buffer,
13508			type: type,
13509			bytesPerElement: array.BYTES_PER_ELEMENT,
13510			version: attribute.version,
13511			size: size
13512		};
13513
13514	}
13515
13516	function updateBuffer( buffer, attribute, bufferType ) {
13517
13518		const array = attribute.array;
13519		const updateRange = attribute._updateRange; // @deprecated, r159
13520		const updateRanges = attribute.updateRanges;
13521
13522		gl.bindBuffer( bufferType, buffer );
13523
13524		if ( updateRange.count === - 1 && updateRanges.length === 0 ) {
13525
13526			// Not using update ranges
13527			gl.bufferSubData( bufferType, 0, array );
13528
13529		}
13530
13531		if ( updateRanges.length !== 0 ) {
13532
13533			for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
13534
13535				const range = updateRanges[ i ];
13536
13537				gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
13538					array, range.start, range.count );
13539
13540			}
13541
13542			attribute.clearUpdateRanges();
13543
13544		}
13545
13546		// @deprecated, r159
13547		if ( updateRange.count !== - 1 ) {
13548
13549			gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
13550				array, updateRange.offset, updateRange.count );
13551
13552			updateRange.count = - 
vendor: 65,372 bytes, lines 13552-13849
135521; // reset range
13553
13554		}
13555
13556		attribute.onUploadCallback();
13557
13558	}
13559
13560	//
13561
13562	function get( attribute ) {
13563
13564		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13565
13566		return buffers.get( attribute );
13567
13568	}
13569
13570	function remove( attribute ) {
13571
13572		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13573
13574		const data = buffers.get( attribute );
13575
13576		if ( data ) {
13577
13578			gl.deleteBuffer( data.buffer );
13579
13580			buffers.delete( attribute );
13581
13582		}
13583
13584	}
13585
13586	function update( attribute, bufferType ) {
13587
13588		if ( attribute.isGLBufferAttribute ) {
13589
13590			const cached = buffers.get( attribute );
13591
13592			if ( ! cached || cached.version < attribute.version ) {
13593
13594				buffers.set( attribute, {
13595					buffer: attribute.buffer,
13596					type: attribute.type,
13597					bytesPerElement: attribute.elementSize,
13598					version: attribute.version
13599				} );
13600
13601			}
13602
13603			return;
13604
13605		}
13606
13607		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13608
13609		const data = buffers.get( attribute );
13610
13611		if ( data === undefined ) {
13612
13613			buffers.set( attribute, createBuffer( attribute, bufferType ) );
13614
13615		} else if ( data.version < attribute.version ) {
13616
13617			if ( data.size !== attribute.array.byteLength ) {
13618
13619				throw new Error( 'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' );
13620
13621			}
13622
13623			updateBuffer( data.buffer, attribute, bufferType );
13624
13625			data.version = attribute.version;
13626
13627		}
13628
13629	}
13630
13631	return {
13632
13633		get: get,
13634		remove: remove,
13635		update: update
13636
13637	};
13638
13639}
13640
13641class PlaneGeometry extends BufferGeometry {
13642
13643	constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
13644
13645		super();
13646
13647		this.type = 'PlaneGeometry';
13648
13649		this.parameters = {
13650			width: width,
13651			height: height,
13652			widthSegments: widthSegments,
13653			heightSegments: heightSegments
13654		};
13655
13656		const width_half = width / 2;
13657		const height_half = height / 2;
13658
13659		const gridX = Math.floor( widthSegments );
13660		const gridY = Math.floor( heightSegments );
13661
13662		const gridX1 = gridX + 1;
13663		const gridY1 = gridY + 1;
13664
13665		const segment_width = width / gridX;
13666		const segment_height = height / gridY;
13667
13668		//
13669
13670		const indices = [];
13671		const vertices = [];
13672		const normals = [];
13673		const uvs = [];
13674
13675		for ( let iy = 0; iy < gridY1; iy ++ ) {
13676
13677			const y = iy * segment_height - height_half;
13678
13679			for ( let ix = 0; ix < gridX1; ix ++ ) {
13680
13681				const x = ix * segment_width - width_half;
13682
13683				vertices.push( x, - y, 0 );
13684
13685				normals.push( 0, 0, 1 );
13686
13687				uvs.push( ix / gridX );
13688				uvs.push( 1 - ( iy / gridY ) );
13689
13690			}
13691
13692		}
13693
13694		for ( let iy = 0; iy < gridY; iy ++ ) {
13695
13696			for ( let ix = 0; ix < gridX; ix ++ ) {
13697
13698				const a = ix + gridX1 * iy;
13699				const b = ix + gridX1 * ( iy + 1 );
13700				const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
13701				const d = ( ix + 1 ) + gridX1 * iy;
13702
13703				indices.push( a, b, d );
13704				indices.push( b, c, d );
13705
13706			}
13707
13708		}
13709
13710		this.setIndex( indices );
13711		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
13712		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
13713		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
13714
13715	}
13716
13717	copy( source ) {
13718
13719		super.copy( source );
13720
13721		this.parameters = Object.assign( {}, source.parameters );
13722
13723		return this;
13724
13725	}
13726
13727	static fromJSON( data ) {
13728
13729		return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
13730
13731	}
13732
13733}
13734
13735var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif";
13736
13737var alphahash_pars_fragment = "#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x < ( 1.0 - a ) )\n\t\t\t? ( ( x < a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif";
13738
13739var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif";
13740
13741var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
13742
13743var alphatest_fragment = "#ifdef USE_ALPHATEST\n\t#ifdef ALPHA_TO_COVERAGE\n\tdiffuseColor.a = smoothstep( alphaTest, alphaTest + fwidth( diffuseColor.a ), diffuseColor.a );\n\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\tif ( diffuseColor.a < alphaTest ) discard;\n\t#endif\n#endif";
13744
13745var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif";
13746
13747var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_CLEARCOAT ) \n\t\tclearcoatSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_SHEEN ) \n\t\tsheenSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif";
13748
13749var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
13750
13751var batching_pars_vertex = "#ifdef USE_BATCHING\n\tattribute float batchId;\n\tuniform highp sampler2D batchingTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif";
13752
13753var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif";
13754
13755var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif";
13756
13757var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
13758
13759var bsdfs = "float 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} // validated";
13760
13761var 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\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\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";
13762
13763var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + 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 = normalize( dFdx( surf_pos.xyz ) );\n\t\tvec3 vSigmaY = normalize( 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";
13764
13765var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\n\t#endif\n#endif";
13766
13767var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
13768
13769var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
13770
13771var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
13772
13773var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif";
13774
13775var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif";
13776
13777var 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";
13778
13779var 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";
13780
13781var 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};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\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}\nvec3 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} // validated";
13782
13783var 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_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\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";
13784
13785var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif";
13786
13787var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
13788
13789var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif";
13790
13791var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
13792
13793var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
13794
13795var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
13796
13797var colorspace_pars_fragment = "\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn sRGBTransferOETF( value );\n}";
13798
13799var 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, envMapRotation * 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";
13800
13801var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform mat3 envMapRotation;\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";
13802
13803var 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";
13804
13805var 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";
13806
13807var envmap_vertex = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif";
13808
13809var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif";
13810
13811var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif";
13812
13813var 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";
13814
13815var 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";
13816
13817var 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}";
13818
13819var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif";
13820
13821var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
13822
13823var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;";
13824
13825var 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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";
13826
13827var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\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, 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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\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}\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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\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";
13828
13829var envmap_physical_pars_fragment = "#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * 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#ifdef 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, envMapRotation * 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\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif";
13830
13831var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
13832
13833var lights_toon_pars_fragment = "varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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";
13834
13835var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
13836
13837var 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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";
13838
13839var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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 USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\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;\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, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).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, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).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_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif";
13840
13841var 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\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\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}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\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 = F_Schlick( f0, f90, dotVH );\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\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\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 dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\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\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 = DFGApprox( 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, 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}";
13842
13843var lights_fragment_begin = "\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\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, geometryPosition, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, 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_LIGHT_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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\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 ], geometryNormal );\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";
13844
13845var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\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( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
13846
13847var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif";
13848
13849var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF )
13849\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
13850
13851var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
13852
13853var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
13854
13855var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );
vendor: 20,217 bytes, lines 13855-13915
13855\n#endif";
13856
13857var map_fragment = "#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\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\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif";
13858
13859var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
13860
13861var map_particle_fragment = "#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\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";
13862
13863var map_particle_pars_fragment = "#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
13864
13865var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
13866
13867var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
13868
13869var morphinstance_vertex = "#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[MORPHTARGETS_COUNT];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] =  texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif";
13870
13871var 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";
13872
13873var 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";
13874
13875var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t#endif\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\t#ifndef USE_INSTANCING_MORPH\n\t\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\t#endif\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";
13876
13877var 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";
13878
13879var 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 *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;";
13880
13881var normal_fragment_maps = "#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).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( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
13882
13883var 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";
13884
13885var 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";
13886
13887var 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";
13888
13889var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.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 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif";
13890
13891var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif";
13892
13893var clearcoat_normal_fragment_maps = "#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif";
13894
13895var clearcoat_pars_fragment = "#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif";
13896
13897var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif";
13898
13899var opaque_fragment = "#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );";
13900
13901var 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 depth, const in float near, const in float far ) {\n\treturn depth * ( 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 depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}";
13902
13903var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
13904
13905var project_vertex = "vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;";
13906
13907var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
13908
13909var 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";
13910
13911var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
13912
13913var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
13914
13915var 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\t
13915float shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn shadow;
vendor: 10,186 bytes, lines 13915-13937
13915\n\t}\n#endif";
13916
13917var 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";
13918
13919var 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";
13920
13921var 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}";
13922
13923var 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";
13924
13925var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif";
13926
13927var 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";
13928
13929var 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";
13930
13931var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
13932
13933var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
13934
13935var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
13936
13937var 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 saturate( 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}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tfloat startCompression = 0.8 - 0.04;\n\tfloat desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min(color.r, min(color.g, color.b));\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max(color.r, max(color.g, color.b));\n\tif (peak < startCompression) return color;\n\tfloat d = 1. - startCompression;\n\tfloat newPeak = 1. - d * d / (peak + d - startCompression);\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);\n\treturn mix(color, 
13937newPeak * vec3(1, 1, 1), g);\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
13938
13939var 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, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = 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, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif";
13940
13941var 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\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a *  a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\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 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\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 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );
vendor: 6,253 bytes, lines 13941-13947
13941\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif";
13942
13943var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
13944
13945var uv_pars_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
13946
13947var uv_vertex = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;
vendor: 43,618 bytes, lines 13947-14197
13947\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif";
13948
13949var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif";
13950
13951const 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}";
13952
13953const 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 <colorspace_fragment>\n}";
13954
13955const 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}";
13956
13957const 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;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * 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 <colorspace_fragment>\n}";
13958
13959const 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}";
13960
13961const 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 <colorspace_fragment>\n}";
13962
13963const vertex$e = "#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <skinbase_vertex>\n\t#include <morphinstance_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}";
13964
13965const 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 <alphahash_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <clipping_planes_fragment>\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 <alphahash_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}";
13966
13967const vertex$d = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <skinbase_vertex>\n\t#include <morphinstance_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}";
13968
13969const 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 <alphahash_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <clipping_planes_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}";
13970
13971const 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}";
13972
13973const 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 <colorspace_fragment>\n}";
13974
13975const vertex$b = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <uv_pars_vertex>\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 <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphinstance_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}";
13976
13977const 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 <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
13978
13979const vertex$a = "#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}";
13980
13981const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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, vLightMapUv );\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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13982
13983const vertex$9 = "#define LAMBERT\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}";
13984
13985const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13986
13987const vertex$8 = "#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\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 <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}";
13988
13989const 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 <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13990
13991const vertex$7 = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphinstance_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( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}";
13992
13993const fragment$7 = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\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\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\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 ), diffuseColor.a );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}";
13994
13995const vertex$6 = "#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphinstance_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}";
13996
13997const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
13998
13999const vertex$5 = "#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}";
14000
14001const fragment$5 = "#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_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 USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\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_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14002
14003const vertex$4 = "#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_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 <color_vertex>\n\t#include <morphinstance_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_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}";
14004
14005const 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 <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\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 <alphahash_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 <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14006
14007const 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>\n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include <color_vertex>\n\t#include <morphinstance_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}";
14008
14009const 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 <alphahash_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
14010
14011const vertex$2 = "#include <common>\n#include <batching_pars_vertex>\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 <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphinstance_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}";
14012
14013const 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 <colorspace_fragment>\n\t#include <fog_fragment>\n}";
14014
14015const 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}";
14016
14017const 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 <alphahash_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n}";
14018
14019const ShaderChunk = {
14020	alphahash_fragment: alphahash_fragment,
14021	alphahash_pars_fragment: alphahash_pars_fragment,
14022	alphamap_fragment: alphamap_fragment,
14023	alphamap_pars_fragment: alphamap_pars_fragment,
14024	alphatest_fragment: alphatest_fragment,
14025	alphatest_pars_fragment: alphatest_pars_fragment,
14026	aomap_fragment: aomap_fragment,
14027	aomap_pars_fragment: aomap_pars_fragment,
14028	batching_pars_vertex: batching_pars_vertex,
14029	batching_vertex: batching_vertex,
14030	begin_vertex: begin_vertex,
14031	beginnormal_vertex: beginnormal_vertex,
14032	bsdfs: bsdfs,
14033	iridescence_fragment: iridescence_fragment,
14034	bumpmap_pars_fragment: bumpmap_pars_fragment,
14035	clipping_planes_fragment: clipping_planes_fragment,
14036	clipping_planes_pars_fragment: clipping_planes_pars_fragment,
14037	clipping_planes_pars_vertex: clipping_planes_pars_vertex,
14038	clipping_planes_vertex: clipping_planes_vertex,
14039	color_fragment: color_fragment,
14040	color_pars_fragment: color_pars_fragment,
14041	color_pars_vertex: color_pars_vertex,
14042	color_vertex: color_vertex,
14043	common: common,
14044	cube_uv_reflection_fragment: cube_uv_reflection_fragment,
14045	defaultnormal_vertex: defaultnormal_vertex,
14046	displacementmap_pars_vertex: displacementmap_pars_vertex,
14047	displacementmap_vertex: displacementmap_vertex,
14048	emissivemap_fragment: emissivemap_fragment,
14049	emissivemap_pars_fragment: emissivemap_pars_fragment,
14050	colorspace_fragment: colorspace_fragment,
14051	colorspace_pars_fragment: colorspace_pars_fragment,
14052	envmap_fragment: envmap_fragment,
14053	envmap_common_pars_fragment: envmap_common_pars_fragment,
14054	envmap_pars_fragment: envmap_pars_fragment,
14055	envmap_pars_vertex: envmap_pars_vertex,
14056	envmap_physical_pars_fragment: envmap_physical_pars_fragment,
14057	envmap_vertex: envmap_vertex,
14058	fog_vertex: fog_vertex,
14059	fog_pars_vertex: fog_pars_vertex,
14060	fog_fragment: fog_fragment,
14061	fog_pars_fragment: fog_pars_fragment,
14062	gradientmap_pars_fragment: gradientmap_pars_fragment,
14063	lightmap_fragment: lightmap_fragment,
14064	lightmap_pars_fragment: lightmap_pars_fragment,
14065	lights_lambert_fragment: lights_lambert_fragment,
14066	lights_lambert_pars_fragment: lights_lambert_pars_fragment,
14067	lights_pars_begin: lights_pars_begin,
14068	lights_toon_fragment: lights_toon_fragment,
14069	lights_toon_pars_fragment: lights_toon_pars_fragment,
14070	lights_phong_fragment: lights_phong_fragment,
14071	lights_phong_pars_fragment: lights_phong_pars_fragment,
14072	lights_physical_fragment: lights_physical_fragment,
14073	lights_physical_pars_fragment: lights_physical_pars_fragment,
14074	lights_fragment_begin: lights_fragment_begin,
14075	lights_fragment_maps: lights_fragment_maps,
14076	lights_fragment_end: lights_fragment_end,
14077	logdepthbuf_fragment: logdepthbuf_fragment,
14078	logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
14079	logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
14080	logdepthbuf_vertex: logdepthbuf_vertex,
14081	map_fragment: map_fragment,
14082	map_pars_fragment: map_pars_fragment,
14083	map_particle_fragment: map_particle_fragment,
14084	map_particle_pars_fragment: map_particle_pars_fragment,
14085	metalnessmap_fragment: metalnessmap_fragment,
14086	metalnessmap_pars_fragment: metalnessmap_pars_fragment,
14087	morphinstance_vertex: morphinstance_vertex,
14088	morphcolor_vertex: morphcolor_vertex,
14089	morphnormal_vertex: morphnormal_vertex,
14090	morphtarget_pars_vertex: morphtarget_pars_vertex,
14091	morphtarget_vertex: morphtarget_vertex,
14092	normal_fragment_begin: normal_fragment_begin,
14093	normal_fragment_maps: normal_fragment_maps,
14094	normal_pars_fragment: normal_pars_fragment,
14095	normal_pars_vertex: normal_pars_vertex,
14096	normal_vertex: normal_vertex,
14097	normalmap_pars_fragment: normalmap_pars_fragment,
14098	clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
14099	clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
14100	clearcoat_pars_fragment: clearcoat_pars_fragment,
14101	iridescence_pars_fragment: iridescence_pars_fragment,
14102	opaque_fragment: opaque_fragment,
14103	packing: packing,
14104	premultiplied_alpha_fragment: premultiplied_alpha_fragment,
14105	project_vertex: project_vertex,
14106	dithering_fragment: dithering_fragment,
14107	dithering_pars_fragment: dithering_pars_fragment,
14108	roughnessmap_fragment: roughnessmap_fragment,
14109	roughnessmap_pars_fragment: roughnessmap_pars_fragment,
14110	shadowmap_pars_fragment: shadowmap_pars_fragment,
14111	shadowmap_pars_vertex: shadowmap_pars_vertex,
14112	shadowmap_vertex: shadowmap_vertex,
14113	shadowmask_pars_fragment: shadowmask_pars_fragment,
14114	skinbase_vertex: skinbase_vertex,
14115	skinning_pars_vertex: skinning_pars_vertex,
14116	skinning_vertex: skinning_vertex,
14117	skinnormal_vertex: skinnormal_vertex,
14118	specularmap_fragment: specularmap_fragment,
14119	specularmap_pars_fragment: specularmap_pars_fragment,
14120	tonemapping_fragment: tonemapping_fragment,
14121	tonemapping_pars_fragment: tonemapping_pars_fragment,
14122	transmission_fragment: transmission_fragment,
14123	transmission_pars_fragment: transmission_pars_fragment,
14124	uv_pars_fragment: uv_pars_fragment,
14125	uv_pars_vertex: uv_pars_vertex,
14126	uv_vertex: uv_vertex,
14127	worldpos_vertex: worldpos_vertex,
14128
14129	background_vert: vertex$h,
14130	background_frag: fragment$h,
14131	backgroundCube_vert: vertex$g,
14132	backgroundCube_frag: fragment$g,
14133	cube_vert: vertex$f,
14134	cube_frag: fragment$f,
14135	depth_vert: vertex$e,
14136	depth_frag: fragment$e,
14137	distanceRGBA_vert: vertex$d,
14138	distanceRGBA_frag: fragment$d,
14139	equirect_vert: vertex$c,
14140	equirect_frag: fragment$c,
14141	linedashed_vert: vertex$b,
14142	linedashed_frag: fragment$b,
14143	meshbasic_vert: vertex$a,
14144	meshbasic_frag: fragment$a,
14145	meshlambert_vert: vertex$9,
14146	meshlambert_frag: fragment$9,
14147	meshmatcap_vert: vertex$8,
14148	meshmatcap_frag: fragment$8,
14149	meshnormal_vert: vertex$7,
14150	meshnormal_frag: fragment$7,
14151	meshphong_vert: vertex$6,
14152	meshphong_frag: fragment$6,
14153	meshphysical_vert: vertex$5,
14154	meshphysical_frag: fragment$5,
14155	meshtoon_vert: vertex$4,
14156	meshtoon_frag: fragment$4,
14157	points_vert: vertex$3,
14158	points_frag: fragment$3,
14159	shadow_vert: vertex$2,
14160	shadow_frag: fragment$2,
14161	sprite_vert: vertex$1,
14162	sprite_frag: fragment$1
14163};
14164
14165/**
14166 * Uniforms library for shared webgl shaders
14167 */
14168
14169const UniformsLib = {
14170
14171	common: {
14172
14173		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
14174		opacity: { value: 1.0 },
14175
14176		map: { value: null },
14177		mapTransform: { value: /*@__PURE__*/ new Matrix3() },
14178
14179		alphaMap: { value: null },
14180		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14181
14182		alphaTest: { value: 0 }
14183
14184	},
14185
14186	specularmap: {
14187
14188		specularMap: { value: null },
14189		specularMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14190
14191	},
14192
14193	envmap: {
14194
14195		envMap: { value: null },
14196		envMapRotation: { value: /*@__PURE__*/ new Matrix3() },
14197		flipEnvMap: { value: -
14197 1 },
14198		reflectivity: { value: 1.0 }, // basic, lambert, phong
14199		ior: { value: 1.5 }, // physical
14200		refractionRatio: { value: 0.98 }, // basic, lambert, phong
14201
14202	},
vendor: 6,354 bytes, lines 14203-14518
14203
14204	aomap: {
14205
14206		aoMap: { value: null },
14207		aoMapIntensity: { value: 1 },
14208		aoMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14209
14210	},
14211
14212	lightmap: {
14213
14214		lightMap: { value: null },
14215		lightMapIntensity: { value: 1 },
14216		lightMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14217
14218	},
14219
14220	bumpmap: {
14221
14222		bumpMap: { value: null },
14223		bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14224		bumpScale: { value: 1 }
14225
14226	},
14227
14228	normalmap: {
14229
14230		normalMap: { value: null },
14231		normalMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14232		normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }
14233
14234	},
14235
14236	displacementmap: {
14237
14238		displacementMap: { value: null },
14239		displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14240		displacementScale: { value: 1 },
14241		displacementBias: { value: 0 }
14242
14243	},
14244
14245	emissivemap: {
14246
14247		emissiveMap: { value: null },
14248		emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14249
14250	},
14251
14252	metalnessmap: {
14253
14254		metalnessMap: { value: null },
14255		metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14256
14257	},
14258
14259	roughnessmap: {
14260
14261		roughnessMap: { value: null },
14262		roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14263
14264	},
14265
14266	gradientmap: {
14267
14268		gradientMap: { value: null }
14269
14270	},
14271
14272	fog: {
14273
14274		fogDensity: { value: 0.00025 },
14275		fogNear: { value: 1 },
14276		fogFar: { value: 2000 },
14277		fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) }
14278
14279	},
14280
14281	lights: {
14282
14283		ambientLightColor: { value: [] },
14284
14285		lightProbe: { value: [] },
14286
14287		directionalLights: { value: [], properties: {
14288			direction: {},
14289			color: {}
14290		} },
14291
14292		directionalLightShadows: { value: [], properties: {
14293			shadowBias: {},
14294			shadowNormalBias: {},
14295			shadowRadius: {},
14296			shadowMapSize: {}
14297		} },
14298
14299		directionalShadowMap: { value: [] },
14300		directionalShadowMatrix: { value: [] },
14301
14302		spotLights: { value: [], properties: {
14303			color: {},
14304			position: {},
14305			direction: {},
14306			distance: {},
14307			coneCos: {},
14308			penumbraCos: {},
14309			decay: {}
14310		} },
14311
14312		spotLightShadows: { value: [], properties: {
14313			shadowBias: {},
14314			shadowNormalBias: {},
14315			shadowRadius: {},
14316			shadowMapSize: {}
14317		} },
14318
14319		spotLightMap: { value: [] },
14320		spotShadowMap: { value: [] },
14321		spotLightMatrix: { value: [] },
14322
14323		pointLights: { value: [], properties: {
14324			color: {},
14325			position: {},
14326			decay: {},
14327			distance: {}
14328		} },
14329
14330		pointLightShadows: { value: [], properties: {
14331			shadowBias: {},
14332			shadowNormalBias: {},
14333			shadowRadius: {},
14334			shadowMapSize: {},
14335			shadowCameraNear: {},
14336			shadowCameraFar: {}
14337		} },
14338
14339		pointShadowMap: { value: [] },
14340		pointShadowMatrix: { value: [] },
14341
14342		hemisphereLights: { value: [], properties: {
14343			direction: {},
14344			skyColor: {},
14345			groundColor: {}
14346		} },
14347
14348		// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
14349		rectAreaLights: { value: [], properties: {
14350			color: {},
14351			position: {},
14352			width: {},
14353			height: {}
14354		} },
14355
14356		ltc_1: { value: null },
14357		ltc_2: { value: null }
14358
14359	},
14360
14361	points: {
14362
14363		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
14364		opacity: { value: 1.0 },
14365		size: { value: 1.0 },
14366		scale: { value: 1.0 },
14367		map: { value: null },
14368		alphaMap: { value: null },
14369		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14370		alphaTest: { value: 0 },
14371		uvTransform: { value: /*@__PURE__*/ new Matrix3() }
14372
14373	},
14374
14375	sprite: {
14376
14377		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
14378		opacity: { value: 1.0 },
14379		center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) },
14380		rotation: { value: 0.0 },
14381		map: { value: null },
14382		mapTransform: { value: /*@__PURE__*/ new Matrix3() },
14383		alphaMap: { value: null },
14384		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14385		alphaTest: { value: 0 }
14386
14387	}
14388
14389};
14390
14391const ShaderLib = {
14392
14393	basic: {
14394
14395		uniforms: /*@__PURE__*/ mergeUniforms( [
14396			UniformsLib.common,
14397			UniformsLib.specularmap,
14398			UniformsLib.envmap,
14399			UniformsLib.aomap,
14400			UniformsLib.lightmap,
14401			UniformsLib.fog
14402		] ),
14403
14404		vertexShader: ShaderChunk.meshbasic_vert,
14405		fragmentShader: ShaderChunk.meshbasic_frag
14406
14407	},
14408
14409	lambert: {
14410
14411		uniforms: /*@__PURE__*/ mergeUniforms( [
14412			UniformsLib.common,
14413			UniformsLib.specularmap,
14414			UniformsLib.envmap,
14415			UniformsLib.aomap,
14416			UniformsLib.lightmap,
14417			UniformsLib.emissivemap,
14418			UniformsLib.bumpmap,
14419			UniformsLib.normalmap,
14420			UniformsLib.displacementmap,
14421			UniformsLib.fog,
14422			UniformsLib.lights,
14423			{
14424				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }
14425			}
14426		] ),
14427
14428		vertexShader: ShaderChunk.meshlambert_vert,
14429		fragmentShader: ShaderChunk.meshlambert_frag
14430
14431	},
14432
14433	phong: {
14434
14435		uniforms: /*@__PURE__*/ mergeUniforms( [
14436			UniformsLib.common,
14437			UniformsLib.specularmap,
14438			UniformsLib.envmap,
14439			UniformsLib.aomap,
14440			UniformsLib.lightmap,
14441			UniformsLib.emissivemap,
14442			UniformsLib.bumpmap,
14443			UniformsLib.normalmap,
14444			UniformsLib.displacementmap,
14445			UniformsLib.fog,
14446			UniformsLib.lights,
14447			{
14448				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14449				specular: { value: /*@__PURE__*/ new Color( 0x111111 ) },
14450				shininess: { value: 30 }
14451			}
14452		] ),
14453
14454		vertexShader: ShaderChunk.meshphong_vert,
14455		fragmentShader: ShaderChunk.meshphong_frag
14456
14457	},
14458
14459	standard: {
14460
14461		uniforms: /*@__PURE__*/ mergeUniforms( [
14462			UniformsLib.common,
14463			UniformsLib.envmap,
14464			UniformsLib.aomap,
14465			UniformsLib.lightmap,
14466			UniformsLib.emissivemap,
14467			UniformsLib.bumpmap,
14468			UniformsLib.normalmap,
14469			UniformsLib.displacementmap,
14470			UniformsLib.roughnessmap,
14471			UniformsLib.metalnessmap,
14472			UniformsLib.fog,
14473			UniformsLib.lights,
14474			{
14475				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14476				roughness: { value: 1.0 },
14477				metalness: { value: 0.0 },
14478				envMapIntensity: { value: 1 }
14479			}
14480		] ),
14481
14482		vertexShader: ShaderChunk.meshphysical_vert,
14483		fragmentShader: ShaderChunk.meshphysical_frag
14484
14485	},
14486
14487	toon: {
14488
14489		uniforms: /*@__PURE__*/ mergeUniforms( [
14490			UniformsLib.common,
14491			UniformsLib.aomap,
14492			UniformsLib.lightmap,
14493			UniformsLib.emissivemap,
14494			UniformsLib.bumpmap,
14495			UniformsLib.normalmap,
14496			UniformsLib.displacementmap,
14497			UniformsLib.gradientmap,
14498			UniformsLib.fog,
14499			UniformsLib.lights,
14500			{
14501				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }
14502			}
14503		] ),
14504
14505		vertexShader: ShaderChunk.meshtoon_vert,
14506		fragmentShader: ShaderChunk.meshtoon_frag
14507
14508	},
14509
14510	matcap: {
14511
14512		uniforms: /*@__PURE__*/ mergeUniforms( [
14513			UniformsLib.common,
14514			UniformsLib.bumpmap,
14515			UniformsLib.normalmap,
14516			UniformsLib.displacementmap,
14517			UniformsLib.fog,
14518			{
vendor: 5,418 bytes, lines 14519-14744
14519				matcap: { value: null }
14520			}
14521		] ),
14522
14523		vertexShader: ShaderChunk.meshmatcap_vert,
14524		fragmentShader: ShaderChunk.meshmatcap_frag
14525
14526	},
14527
14528	points: {
14529
14530		uniforms: /*@__PURE__*/ mergeUniforms( [
14531			UniformsLib.points,
14532			UniformsLib.fog
14533		] ),
14534
14535		vertexShader: ShaderChunk.points_vert,
14536		fragmentShader: ShaderChunk.points_frag
14537
14538	},
14539
14540	dashed: {
14541
14542		uniforms: /*@__PURE__*/ mergeUniforms( [
14543			UniformsLib.common,
14544			UniformsLib.fog,
14545			{
14546				scale: { value: 1 },
14547				dashSize: { value: 1 },
14548				totalSize: { value: 2 }
14549			}
14550		] ),
14551
14552		vertexShader: ShaderChunk.linedashed_vert,
14553		fragmentShader: ShaderChunk.linedashed_frag
14554
14555	},
14556
14557	depth: {
14558
14559		uniforms: /*@__PURE__*/ mergeUniforms( [
14560			UniformsLib.common,
14561			UniformsLib.displacementmap
14562		] ),
14563
14564		vertexShader: ShaderChunk.depth_vert,
14565		fragmentShader: ShaderChunk.depth_frag
14566
14567	},
14568
14569	normal: {
14570
14571		uniforms: /*@__PURE__*/ mergeUniforms( [
14572			UniformsLib.common,
14573			UniformsLib.bumpmap,
14574			UniformsLib.normalmap,
14575			UniformsLib.displacementmap,
14576			{
14577				opacity: { value: 1.0 }
14578			}
14579		] ),
14580
14581		vertexShader: ShaderChunk.meshnormal_vert,
14582		fragmentShader: ShaderChunk.meshnormal_frag
14583
14584	},
14585
14586	sprite: {
14587
14588		uniforms: /*@__PURE__*/ mergeUniforms( [
14589			UniformsLib.sprite,
14590			UniformsLib.fog
14591		] ),
14592
14593		vertexShader: ShaderChunk.sprite_vert,
14594		fragmentShader: ShaderChunk.sprite_frag
14595
14596	},
14597
14598	background: {
14599
14600		uniforms: {
14601			uvTransform: { value: /*@__PURE__*/ new Matrix3() },
14602			t2D: { value: null },
14603			backgroundIntensity: { value: 1 }
14604		},
14605
14606		vertexShader: ShaderChunk.background_vert,
14607		fragmentShader: ShaderChunk.background_frag
14608
14609	},
14610
14611	backgroundCube: {
14612
14613		uniforms: {
14614			envMap: { value: null },
14615			flipEnvMap: { value: - 1 },
14616			backgroundBlurriness: { value: 0 },
14617			backgroundIntensity: { value: 1 },
14618			backgroundRotation: { value: /*@__PURE__*/ new Matrix3() }
14619		},
14620
14621		vertexShader: ShaderChunk.backgroundCube_vert,
14622		fragmentShader: ShaderChunk.backgroundCube_frag
14623
14624	},
14625
14626	cube: {
14627
14628		uniforms: {
14629			tCube: { value: null },
14630			tFlip: { value: - 1 },
14631			opacity: { value: 1.0 }
14632		},
14633
14634		vertexShader: ShaderChunk.cube_vert,
14635		fragmentShader: ShaderChunk.cube_frag
14636
14637	},
14638
14639	equirect: {
14640
14641		uniforms: {
14642			tEquirect: { value: null },
14643		},
14644
14645		vertexShader: ShaderChunk.equirect_vert,
14646		fragmentShader: ShaderChunk.equirect_frag
14647
14648	},
14649
14650	distanceRGBA: {
14651
14652		uniforms: /*@__PURE__*/ mergeUniforms( [
14653			UniformsLib.common,
14654			UniformsLib.displacementmap,
14655			{
14656				referencePosition: { value: /*@__PURE__*/ new Vector3() },
14657				nearDistance: { value: 1 },
14658				farDistance: { value: 1000 }
14659			}
14660		] ),
14661
14662		vertexShader: ShaderChunk.distanceRGBA_vert,
14663		fragmentShader: ShaderChunk.distanceRGBA_frag
14664
14665	},
14666
14667	shadow: {
14668
14669		uniforms: /*@__PURE__*/ mergeUniforms( [
14670			UniformsLib.lights,
14671			UniformsLib.fog,
14672			{
14673				color: { value: /*@__PURE__*/ new Color( 0x00000 ) },
14674				opacity: { value: 1.0 }
14675			},
14676		] ),
14677
14678		vertexShader: ShaderChunk.shadow_vert,
14679		fragmentShader: ShaderChunk.shadow_frag
14680
14681	}
14682
14683};
14684
14685ShaderLib.physical = {
14686
14687	uniforms: /*@__PURE__*/ mergeUniforms( [
14688		ShaderLib.standard.uniforms,
14689		{
14690			clearcoat: { value: 0 },
14691			clearcoatMap: { value: null },
14692			clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14693			clearcoatNormalMap: { value: null },
14694			clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14695			clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) },
14696			clearcoatRoughness: { value: 0 },
14697			clearcoatRoughnessMap: { value: null },
14698			clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14699			iridescence: { value: 0 },
14700			iridescenceMap: { value: null },
14701			iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14702			iridescenceIOR: { value: 1.3 },
14703			iridescenceThicknessMinimum: { value: 100 },
14704			iridescenceThicknessMaximum: { value: 400 },
14705			iridescenceThicknessMap: { value: null },
14706			iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14707			sheen: { value: 0 },
14708			sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14709			sheenColorMap: { value: null },
14710			sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14711			sheenRoughness: { value: 1 },
14712			sheenRoughnessMap: { value: null },
14713			sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14714			transmission: { value: 0 },
14715			transmissionMap: { value: null },
14716			transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14717			transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() },
14718			transmissionSamplerMap: { value: null },
14719			thickness: { value: 0 },
14720			thicknessMap: { value: null },
14721			thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14722			attenuationDistance: { value: 0 },
14723			attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14724			specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) },
14725			specularColorMap: { value: null },
14726			specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14727			specularIntensity: { value: 1 },
14728			specularIntensityMap: { value: null },
14729			specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14730			anisotropyVector: { value: /*@__PURE__*/ new Vector2() },
14731			anisotropyMap: { value: null },
14732			anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14733		}
14734	] ),
14735
14736	vertexShader: ShaderChunk.meshphysical_vert,
14737	fragmentShader: ShaderChunk.meshphysical_frag
14738
14739};
14740
14741const _rgb = { r: 0, b: 0, g: 0 };
14742const _e1$1 = /*@__PURE__*/ new Euler();
14743const _m1$1 = /*@__PURE__*/ new Matrix4();
14744
vendor: 4,335 bytes, lines 14745-14894
14745function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) {
14746
14747	const clearColor = new Color( 0x000000 );
14748	let clearAlpha = alpha === true ? 0 : 1;
14749
14750	let planeMesh;
14751	let boxMesh;
14752
14753	let currentBackground = null;
14754	let currentBackgroundVersion = 0;
14755	let currentTonemapping = null;
14756
14757	function render( renderList, scene ) {
14758
14759		let forceClear = false;
14760		let background = scene.isScene === true ? scene.background : null;
14761
14762		if ( background && background.isTexture ) {
14763
14764			const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background
14765			background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background );
14766
14767		}
14768
14769		if ( background === null ) {
14770
14771			setClear( clearColor, clearAlpha );
14772
14773		} else if ( background && background.isColor ) {
14774
14775			setClear( background, 1 );
14776			forceClear = true;
14777
14778		}
14779
14780		const environmentBlendMode = renderer.xr.getEnvironmentBlendMode();
14781
14782		if ( environmentBlendMode === 'additive' ) {
14783
14784			state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha );
14785
14786		} else if ( environmentBlendMode === 'alpha-blend' ) {
14787
14788			state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha );
14789
14790		}
14791
14792		if ( renderer.autoClear || forceClear ) {
14793
14794			renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
14795
14796		}
14797
14798		if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
14799
14800			if ( boxMesh === undefined ) {
14801
14802				boxMesh = new Mesh(
14803					new BoxGeometry( 1, 1, 1 ),
14804					new ShaderMaterial( {
14805						name: 'BackgroundCubeMaterial',
14806						uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ),
14807						vertexShader: ShaderLib.backgroundCube.vertexShader,
14808						fragmentShader: ShaderLib.backgroundCube.fragmentShader,
14809						side: BackSide,
14810						depthTest: false,
14811						depthWrite: false,
14812						fog: false
14813					} )
14814				);
14815
14816				boxMesh.geometry.deleteAttribute( 'normal' );
14817				boxMesh.geometry.deleteAttribute( 'uv' );
14818
14819				boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
14820
14821					this.matrixWorld.copyPosition( camera.matrixWorld );
14822
14823				};
14824
14825				// add "envMap" material property so the renderer can evaluate it like for built-in materials
14826				Object.defineProperty( boxMesh.material, 'envMap', {
14827
14828					get: function () {
14829
14830						return this.uniforms.envMap.value;
14831
14832					}
14833
14834				} );
14835
14836				objects.update( boxMesh );
14837
14838			}
14839
14840			_e1$1.copy( scene.backgroundRotation );
14841
14842			// accommodate left-handed frame
14843			_e1$1.x *= - 1; _e1$1.y *= - 1; _e1$1.z *= - 1;
14844
14845			if ( background.isCubeTexture && background.isRenderTargetTexture === false ) {
14846
14847				// environment maps which are not cube render targets or PMREMs follow a different convention
14848				_e1$1.y *= - 1;
14849				_e1$1.z *= - 1;
14850
14851			}
14852
14853			boxMesh.material.uniforms.envMap.value = background;
14854			boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
14855			boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
14856			boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14857			boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) );
14858			boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
14859
14860			if ( currentBackground !== background ||
14861				currentBackgroundVersion !== background.version ||
14862				currentTonemapping !== renderer.toneMapping ) {
14863
14864				boxMesh.material.needsUpdate = true;
14865
14866				currentBackground = background;
14867				currentBackgroundVersion = background.version;
14868				currentTonemapping = renderer.toneMapping;
14869
14870			}
14871
14872			boxMesh.layers.enableAll();
14873
14874			// push to the pre-sorted opaque render list
14875			renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
14876
14877		} else if ( background && background.isTexture ) {
14878
14879			if ( planeMesh === undefined ) {
14880
14881				planeMesh = new Mesh(
14882					new PlaneGeometry( 2, 2 ),
14883					new ShaderMaterial( {
14884						name: 'BackgroundMaterial',
14885						uniforms: cloneUniforms( ShaderLib.background.uniforms ),
14886						vertexShader: ShaderLib.background.vertexShader,
14887						fragmentShader: ShaderLib.background.fragmentShader,
14888						side: FrontSide,
14889						depthTest: false,
14890						depthWrite: false,
14891						fog: false
14892					} )
14893				);
14894
vendor: 13,870 bytes, lines 14895-15553
14895				planeMesh.geometry.deleteAttribute( 'normal' );
14896
14897				// add "map" material property so the renderer can evaluate it like for built-in materials
14898				Object.defineProperty( planeMesh.material, 'map', {
14899
14900					get: function () {
14901
14902						return this.uniforms.t2D.value;
14903
14904					}
14905
14906				} );
14907
14908				objects.update( planeMesh );
14909
14910			}
14911
14912			planeMesh.material.uniforms.t2D.value = background;
14913			planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14914			planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
14915
14916			if ( background.matrixAutoUpdate === true ) {
14917
14918				background.updateMatrix();
14919
14920			}
14921
14922			planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
14923
14924			if ( currentBackground !== background ||
14925				currentBackgroundVersion !== background.version ||
14926				currentTonemapping !== renderer.toneMapping ) {
14927
14928				planeMesh.material.needsUpdate = true;
14929
14930				currentBackground = background;
14931				currentBackgroundVersion = background.version;
14932				currentTonemapping = renderer.toneMapping;
14933
14934			}
14935
14936			planeMesh.layers.enableAll();
14937
14938			// push to the pre-sorted opaque render list
14939			renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
14940
14941		}
14942
14943	}
14944
14945	function setClear( color, alpha ) {
14946
14947		color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) );
14948
14949		state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha );
14950
14951	}
14952
14953	return {
14954
14955		getClearColor: function () {
14956
14957			return clearColor;
14958
14959		},
14960		setClearColor: function ( color, alpha = 1 ) {
14961
14962			clearColor.set( color );
14963			clearAlpha = alpha;
14964			setClear( clearColor, clearAlpha );
14965
14966		},
14967		getClearAlpha: function () {
14968
14969			return clearAlpha;
14970
14971		},
14972		setClearAlpha: function ( alpha ) {
14973
14974			clearAlpha = alpha;
14975			setClear( clearColor, clearAlpha );
14976
14977		},
14978		render: render
14979
14980	};
14981
14982}
14983
14984function WebGLBindingStates( gl, attributes ) {
14985
14986	const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
14987
14988	const bindingStates = {};
14989
14990	const defaultState = createBindingState( null );
14991	let currentState = defaultState;
14992	let forceUpdate = false;
14993
14994	function setup( object, material, program, geometry, index ) {
14995
14996		let updateBuffers = false;
14997
14998		const state = getBindingState( geometry, program, material );
14999
15000		if ( currentState !== state ) {
15001
15002			currentState = state;
15003			bindVertexArrayObject( currentState.object );
15004
15005		}
15006
15007		updateBuffers = needsUpdate( object, geometry, program, index );
15008
15009		if ( updateBuffers ) saveCache( object, geometry, program, index );
15010
15011		if ( index !== null ) {
15012
15013			attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
15014
15015		}
15016
15017		if ( updateBuffers || forceUpdate ) {
15018
15019			forceUpdate = false;
15020
15021			setupVertexAttributes( object, material, program, geometry );
15022
15023			if ( index !== null ) {
15024
15025				gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer );
15026
15027			}
15028
15029		}
15030
15031	}
15032
15033	function createVertexArrayObject() {
15034
15035		return gl.createVertexArray();
15036
15037	}
15038
15039	function bindVertexArrayObject( vao ) {
15040
15041		return gl.bindVertexArray( vao );
15042
15043	}
15044
15045	function deleteVertexArrayObject( vao ) {
15046
15047		return gl.deleteVertexArray( vao );
15048
15049	}
15050
15051	function getBindingState( geometry, program, material ) {
15052
15053		const wireframe = ( material.wireframe === true );
15054
15055		let programMap = bindingStates[ geometry.id ];
15056
15057		if ( programMap === undefined ) {
15058
15059			programMap = {};
15060			bindingStates[ geometry.id ] = programMap;
15061
15062		}
15063
15064		let stateMap = programMap[ program.id ];
15065
15066		if ( stateMap === undefined ) {
15067
15068			stateMap = {};
15069			programMap[ program.id ] = stateMap;
15070
15071		}
15072
15073		let state = stateMap[ wireframe ];
15074
15075		if ( state === undefined ) {
15076
15077			state = createBindingState( createVertexArrayObject() );
15078			stateMap[ wireframe ] = state;
15079
15080		}
15081
15082		return state;
15083
15084	}
15085
15086	function createBindingState( vao ) {
15087
15088		const newAttributes = [];
15089		const enabledAttributes = [];
15090		const attributeDivisors = [];
15091
15092		for ( let i = 0; i < maxVertexAttributes; i ++ ) {
15093
15094			newAttributes[ i ] = 0;
15095			enabledAttributes[ i ] = 0;
15096			attributeDivisors[ i ] = 0;
15097
15098		}
15099
15100		return {
15101
15102			// for backward compatibility on non-VAO support browser
15103			geometry: null,
15104			program: null,
15105			wireframe: false,
15106
15107			newAttributes: newAttributes,
15108			enabledAttributes: enabledAttributes,
15109			attributeDivisors: attributeDivisors,
15110			object: vao,
15111			attributes: {},
15112			index: null
15113
15114		};
15115
15116	}
15117
15118	function needsUpdate( object, geometry, program, index ) {
15119
15120		const cachedAttributes = currentState.attributes;
15121		const geometryAttributes = geometry.attributes;
15122
15123		let attributesNum = 0;
15124
15125		const programAttributes = program.getAttributes();
15126
15127		for ( const name in programAttributes ) {
15128
15129			const programAttribute = programAttributes[ name ];
15130
15131			if ( programAttribute.location >= 0 ) {
15132
15133				const cachedAttribute = cachedAttributes[ name ];
15134				let geometryAttribute = geometryAttributes[ name ];
15135
15136				if ( geometryAttribute === undefined ) {
15137
15138					if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
15139					if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
15140
15141				}
15142
15143				if ( cachedAttribute === undefined ) return true;
15144
15145				if ( cachedAttribute.attribute !== geometryAttribute ) return true;
15146
15147				if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true;
15148
15149				attributesNum ++;
15150
15151			}
15152
15153		}
15154
15155		if ( currentState.attributesNum !== attributesNum ) return true;
15156
15157		if ( currentState.index !== index ) return true;
15158
15159		return false;
15160
15161	}
15162
15163	function saveCache( object, geometry, program, index ) {
15164
15165		const cache = {};
15166		const attributes = geometry.attributes;
15167		let attributesNum = 0;
15168
15169		const programAttributes = program.getAttributes();
15170
15171		for ( const name in programAttributes ) {
15172
15173			const programAttribute = programAttributes[ name ];
15174
15175			if ( programAttribute.location >= 0 ) {
15176
15177				let attribute = attributes[ name ];
15178
15179				if ( attribute === undefined ) {
15180
15181					if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix;
15182					if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor;
15183
15184				}
15185
15186				const data = {};
15187				data.attribute = attribute;
15188
15189				if ( attribute && attribute.data ) {
15190
15191					data.data = attribute.data;
15192
15193				}
15194
15195				cache[ name ] = data;
15196
15197				attributesNum ++;
15198
15199			}
15200
15201		}
15202
15203		currentState.attributes = cache;
15204		currentState.attributesNum = attributesNum;
15205
15206		currentState.index = index;
15207
15208	}
15209
15210	function initAttributes() {
15211
15212		const newAttributes = currentState.newAttributes;
15213
15214		for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
15215
15216			newAttributes[ i ] = 0;
15217
15218		}
15219
15220	}
15221
15222	function enableAttribute( attribute ) {
15223
15224		enableAttributeAndDivisor( attribute, 0 );
15225
15226	}
15227
15228	function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
15229
15230		const newAttributes = currentState.newAttributes;
15231		const enabledAttributes = currentState.enabledAttributes;
15232		const attributeDivisors = currentState.attributeDivisors;
15233
15234		newAttributes[ attribute ] = 1;
15235
15236		if ( enabledAttributes[ attribute ] === 0 ) {
15237
15238			gl.enableVertexAttribArray( attribute );
15239			enabledAttributes[ attribute ] = 1;
15240
15241		}
15242
15243		if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
15244
15245			gl.vertexAttribDivisor( attribute, meshPerAttribute );
15246			attributeDivisors[ attribute ] = meshPerAttribute;
15247
15248		}
15249
15250	}
15251
15252	function disableUnusedAttributes() {
15253
15254		const newAttributes = currentState.newAttributes;
15255		const enabledAttributes = currentState.enabledAttributes;
15256
15257		for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
15258
15259			if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
15260
15261				gl.disableVertexAttribArray( i );
15262				enabledAttributes[ i ] = 0;
15263
15264			}
15265
15266		}
15267
15268	}
15269
15270	function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) {
15271
15272		if ( integer === true ) {
15273
15274			gl.vertexAttribIPointer( index, size, type, stride, offset );
15275
15276		} else {
15277
15278			gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
15279
15280		}
15281
15282	}
15283
15284	function setupVertexAttributes( object, material, program, geometry ) {
15285
15286		initAttributes();
15287
15288		const geometryAttributes = geometry.attributes;
15289
15290		const programAttributes = program.getAttributes();
15291
15292		const materialDefaultAttributeValues = material.defaultAttributeValues;
15293
15294		for ( const name in programAttributes ) {
15295
15296			const programAttribute = programAttributes[ name ];
15297
15298			if ( programAttribute.location >= 0 ) {
15299
15300				let geometryAttribute = geometryAttributes[ name ];
15301
15302				if ( geometryAttribute === undefined ) {
15303
15304					if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
15305					if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
15306
15307				}
15308
15309				if ( geometryAttribute !== undefined ) {
15310
15311					const normalized = geometryAttribute.normalized;
15312					const size = geometryAttribute.itemSize;
15313
15314					const attribute = attributes.get( geometryAttribute );
15315
15316					// TODO Attribute may not be available on context restore
15317
15318					if ( attribute === undefined ) continue;
15319
15320					const buffer = attribute.buffer;
15321					const type = attribute.type;
15322					const bytesPerElement = attribute.bytesPerElement;
15323
15324					// check for integer attributes
15325
15326					const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType );
15327
15328					if ( geometryAttribute.isInterleavedBufferAttribute ) {
15329
15330						const data = geometryAttribute.data;
15331						const stride = data.stride;
15332						const offset = geometryAttribute.offset;
15333
15334						if ( data.isInstancedInterleavedBuffer ) {
15335
15336							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15337
15338								enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute );
15339
15340							}
15341
15342							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
15343
15344								geometry._maxInstanceCount = data.meshPerAttribute * data.count;
15345
15346							}
15347
15348						} else {
15349
15350							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15351
15352								enableAttribute( programAttribute.location + i );
15353
15354							}
15355
15356						}
15357
15358						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
15359
15360						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15361
15362							vertexAttribPointer(
15363								programAttribute.location + i,
15364								size / programAttribute.locationSize,
15365								type,
15366								normalized,
15367								stride * bytesPerElement,
15368								( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement,
15369								integer
15370							);
15371
15372						}
15373
15374					} else {
15375
15376						if ( geometryAttribute.isInstancedBufferAttribute ) {
15377
15378							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15379
15380								enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute );
15381
15382							}
15383
15384							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
15385
15386								geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
15387
15388							}
15389
15390						} else {
15391
15392							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15393
15394								enableAttribute( programAttribute.location + i );
15395
15396							}
15397
15398						}
15399
15400						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
15401
15402						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15403
15404							vertexAttribPointer(
15405								programAttribute.location + i,
15406								size / programAttribute.locationSize,
15407								type,
15408								normalized,
15409								size * bytesPerElement,
15410								( size / programAttribute.locationSize ) * i * bytesPerElement,
15411								integer
15412							);
15413
15414						}
15415
15416					}
15417
15418				} else if ( materialDefaultAttributeValues !== undefined ) {
15419
15420					const value = materialDefaultAttributeValues[ name ];
15421
15422					if ( value !== undefined ) {
15423
15424						switch ( value.length ) {
15425
15426							case 2:
15427								gl.vertexAttrib2fv( programAttribute.location, value );
15428								break;
15429
15430							case 3:
15431								gl.vertexAttrib3fv( programAttribute.location, value );
15432								break;
15433
15434							case 4:
15435								gl.vertexAttrib4fv( programAttribute.location, value );
15436								break;
15437
15438							default:
15439								gl.vertexAttrib1fv( programAttribute.location, value );
15440
15441						}
15442
15443					}
15444
15445				}
15446
15447			}
15448
15449		}
15450
15451		disableUnusedAttributes();
15452
15453	}
15454
15455	function dispose() {
15456
15457		reset();
15458
15459		for ( const geometryId in bindingStates ) {
15460
15461			const programMap = bindingStates[ geometryId ];
15462
15463			for ( const programId in programMap ) {
15464
15465				const stateMap = programMap[ programId ];
15466
15467				for ( const wireframe in stateMap ) {
15468
15469					deleteVertexArrayObject( stateMap[ wireframe ].object );
15470
15471					delete stateMap[ wireframe ];
15472
15473				}
15474
15475				delete programMap[ programId ];
15476
15477			}
15478
15479			delete bindingStates[ geometryId ];
15480
15481		}
15482
15483	}
15484
15485	function releaseStatesOfGeometry( geometry ) {
15486
15487		if ( bindingStates[ geometry.id ] === undefined ) return;
15488
15489		const programMap = bindingStates[ geometry.id ];
15490
15491		for ( const programId in programMap ) {
15492
15493			const stateMap = programMap[ programId ];
15494
15495			for ( const wireframe in stateMap ) {
15496
15497				deleteVertexArrayObject( stateMap[ wireframe ].object );
15498
15499				delete stateMap[ wireframe ];
15500
15501			}
15502
15503			delete programMap[ programId ];
15504
15505		}
15506
15507		delete bindingStates[ geometry.id ];
15508
15509	}
15510
15511	function releaseStatesOfProgram( program ) {
15512
15513		for ( const geometryId in bindingStates ) {
15514
15515			const programMap = bindingStates[ geometryId ];
15516
15517			if ( programMap[ program.id ] === undefined ) continue;
15518
15519			const stateMap = programMap[ program.id ];
15520
15521			for ( const wireframe in stateMap ) {
15522
15523				deleteVertexArrayObject( stateMap[ wireframe ].object );
15524
15525				delete stateMap[ wireframe ];
15526
15527			}
15528
15529			delete programMap[ program.id ];
15530
15531		}
15532
15533	}
15534
15535	function reset() {
15536
15537		resetDefaultState();
15538		forceUpdate = true;
15539
15540		if ( currentState === defaultState ) return;
15541
15542		currentState = defaultState;
15543		bindVertexArrayObject( currentState.object );
15544
15545	}
15546
15547	// for backward-compatibility
15548
15549	function resetDefaultState() {
15550
15551		defaultState.geometry = null;
15552		defaultState.program = null;
15553		defaultState.wireframe = false;
vendor: 3,707 bytes, lines 15554-15727
15554
15555	}
15556
15557	return {
15558
15559		setup: setup,
15560		reset: reset,
15561		resetDefaultState: resetDefaultState,
15562		dispose: dispose,
15563		releaseStatesOfGeometry: releaseStatesOfGeometry,
15564		releaseStatesOfProgram: releaseStatesOfProgram,
15565
15566		initAttributes: initAttributes,
15567		enableAttribute: enableAttribute,
15568		disableUnusedAttributes: disableUnusedAttributes
15569
15570	};
15571
15572}
15573
15574function WebGLBufferRenderer( gl, extensions, info ) {
15575
15576	let mode;
15577
15578	function setMode( value ) {
15579
15580		mode = value;
15581
15582	}
15583
15584	function render( start, count ) {
15585
15586		gl.drawArrays( mode, start, count );
15587
15588		info.update( count, mode, 1 );
15589
15590	}
15591
15592	function renderInstances( start, count, primcount ) {
15593
15594		if ( primcount === 0 ) return;
15595
15596		gl.drawArraysInstanced( mode, start, count, primcount );
15597
15598		info.update( count, mode, primcount );
15599
15600	}
15601
15602	function renderMultiDraw( starts, counts, drawCount ) {
15603
15604		if ( drawCount === 0 ) return;
15605
15606		const extension = extensions.get( 'WEBGL_multi_draw' );
15607
15608		if ( extension === null ) {
15609
15610			for ( let i = 0; i < drawCount; i ++ ) {
15611
15612				this.render( starts[ i ], counts[ i ] );
15613
15614			}
15615
15616		} else {
15617
15618			extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount );
15619
15620			let elementCount = 0;
15621			for ( let i = 0; i < drawCount; i ++ ) {
15622
15623				elementCount += counts[ i ];
15624
15625			}
15626
15627			info.update( elementCount, mode, 1 );
15628
15629		}
15630
15631	}
15632
15633	//
15634
15635	this.setMode = setMode;
15636	this.render = render;
15637	this.renderInstances = renderInstances;
15638	this.renderMultiDraw = renderMultiDraw;
15639
15640}
15641
15642function WebGLCapabilities( gl, extensions, parameters ) {
15643
15644	let maxAnisotropy;
15645
15646	function getMaxAnisotropy() {
15647
15648		if ( maxAnisotropy !== undefined ) return maxAnisotropy;
15649
15650		if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
15651
15652			const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
15653
15654			maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
15655
15656		} else {
15657
15658			maxAnisotropy = 0;
15659
15660		}
15661
15662		return maxAnisotropy;
15663
15664	}
15665
15666	function getMaxPrecision( precision ) {
15667
15668		if ( precision === 'highp' ) {
15669
15670			if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
15671				gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
15672
15673				return 'highp';
15674
15675			}
15676
15677			precision = 'mediump';
15678
15679		}
15680
15681		if ( precision === 'mediump' ) {
15682
15683			if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
15684				gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
15685
15686				return 'mediump';
15687
15688			}
15689
15690		}
15691
15692		return 'lowp';
15693
15694	}
15695
15696	let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
15697	const maxPrecision = getMaxPrecision( precision );
15698
15699	if ( maxPrecision !== precision ) {
15700
15701		console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
15702		precision = maxPrecision;
15703
15704	}
15705
15706	const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
15707
15708	const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
15709	const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
15710	const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
15711	const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
15712
15713	const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
15714	const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
15715	const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
15716	const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
15717
15718	const vertexTextures = maxVertexTextures > 0;
15719
15720	const maxSamples = gl.getParameter( gl.MAX_SAMPLES );
15721
15722	return {
15723
15724		isWebGL2: true, // keeping this for backwards compatibility
15725
15726		getMaxAnisotropy: getMaxAnisotropy,
15727		getMaxPrecision: getMaxPrecision,
vendor: 1,617 bytes, lines 15728-15808
15728
15729		precision: precision,
15730		logarithmicDepthBuffer: logarithmicDepthBuffer,
15731
15732		maxTextures: maxTextures,
15733		maxVertexTextures: maxVertexTextures,
15734		maxTextureSize: maxTextureSize,
15735		maxCubemapSize: maxCubemapSize,
15736
15737		maxAttributes: maxAttributes,
15738		maxVertexUniforms: maxVertexUniforms,
15739		maxVaryings: maxVaryings,
15740		maxFragmentUniforms: maxFragmentUniforms,
15741
15742		vertexTextures: vertexTextures,
15743
15744		maxSamples: maxSamples
15745
15746	};
15747
15748}
15749
15750function WebGLClipping( properties ) {
15751
15752	const scope = this;
15753
15754	let globalState = null,
15755		numGlobalPlanes = 0,
15756		localClippingEnabled = false,
15757		renderingShadows = false;
15758
15759	const plane = new Plane(),
15760		viewNormalMatrix = new Matrix3(),
15761
15762		uniform = { value: null, needsUpdate: false };
15763
15764	this.uniform = uniform;
15765	this.numPlanes = 0;
15766	this.numIntersection = 0;
15767
15768	this.init = function ( planes, enableLocalClipping ) {
15769
15770		const enabled =
15771			planes.length !== 0 ||
15772			enableLocalClipping ||
15773			// enable state of previous frame - the clipping code has to
15774			// run another frame in order to reset the state:
15775			numGlobalPlanes !== 0 ||
15776			localClippingEnabled;
15777
15778		localClippingEnabled = enableLocalClipping;
15779
15780		numGlobalPlanes = planes.length;
15781
15782		return enabled;
15783
15784	};
15785
15786	this.beginShadows = function () {
15787
15788		renderingShadows = true;
15789		projectPlanes( null );
15790
15791	};
15792
15793	this.endShadows = function () {
15794
15795		renderingShadows = false;
15796
15797	};
15798
15799	this.setGlobalState = function ( planes, camera ) {
15800
15801		globalState = projectPlanes( planes, camera, 0 );
15802
15803	};
15804
15805	this.setState = function ( material, camera, useCache ) {
15806
15807		const planes = material.clippingPlanes,
15808			clipIntersection = material.clipIntersection,
vendor: 9,736 bytes, lines 15809-16231
15809			clipShadows = material.clipShadows;
15810
15811		const materialProperties = properties.get( material );
15812
15813		if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
15814
15815			// there's no local clipping
15816
15817			if ( renderingShadows ) {
15818
15819				// there's no global clipping
15820
15821				projectPlanes( null );
15822
15823			} else {
15824
15825				resetGlobalState();
15826
15827			}
15828
15829		} else {
15830
15831			const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
15832				lGlobal = nGlobal * 4;
15833
15834			let dstArray = materialProperties.clippingState || null;
15835
15836			uniform.value = dstArray; // ensure unique state
15837
15838			dstArray = projectPlanes( planes, camera, lGlobal, useCache );
15839
15840			for ( let i = 0; i !== lGlobal; ++ i ) {
15841
15842				dstArray[ i ] = globalState[ i ];
15843
15844			}
15845
15846			materialProperties.clippingState = dstArray;
15847			this.numIntersection = clipIntersection ? this.numPlanes : 0;
15848			this.numPlanes += nGlobal;
15849
15850		}
15851
15852
15853	};
15854
15855	function resetGlobalState() {
15856
15857		if ( uniform.value !== globalState ) {
15858
15859			uniform.value = globalState;
15860			uniform.needsUpdate = numGlobalPlanes > 0;
15861
15862		}
15863
15864		scope.numPlanes = numGlobalPlanes;
15865		scope.numIntersection = 0;
15866
15867	}
15868
15869	function projectPlanes( planes, camera, dstOffset, skipTransform ) {
15870
15871		const nPlanes = planes !== null ? planes.length : 0;
15872		let dstArray = null;
15873
15874		if ( nPlanes !== 0 ) {
15875
15876			dstArray = uniform.value;
15877
15878			if ( skipTransform !== true || dstArray === null ) {
15879
15880				const flatSize = dstOffset + nPlanes * 4,
15881					viewMatrix = camera.matrixWorldInverse;
15882
15883				viewNormalMatrix.getNormalMatrix( viewMatrix );
15884
15885				if ( dstArray === null || dstArray.length < flatSize ) {
15886
15887					dstArray = new Float32Array( flatSize );
15888
15889				}
15890
15891				for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
15892
15893					plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
15894
15895					plane.normal.toArray( dstArray, i4 );
15896					dstArray[ i4 + 3 ] = plane.constant;
15897
15898				}
15899
15900			}
15901
15902			uniform.value = dstArray;
15903			uniform.needsUpdate = true;
15904
15905		}
15906
15907		scope.numPlanes = nPlanes;
15908		scope.numIntersection = 0;
15909
15910		return dstArray;
15911
15912	}
15913
15914}
15915
15916function WebGLCubeMaps( renderer ) {
15917
15918	let cubemaps = new WeakMap();
15919
15920	function mapTextureMapping( texture, mapping ) {
15921
15922		if ( mapping === EquirectangularReflectionMapping ) {
15923
15924			texture.mapping = CubeReflectionMapping;
15925
15926		} else if ( mapping === EquirectangularRefractionMapping ) {
15927
15928			texture.mapping = CubeRefractionMapping;
15929
15930		}
15931
15932		return texture;
15933
15934	}
15935
15936	function get( texture ) {
15937
15938		if ( texture && texture.isTexture ) {
15939
15940			const mapping = texture.mapping;
15941
15942			if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
15943
15944				if ( cubemaps.has( texture ) ) {
15945
15946					const cubemap = cubemaps.get( texture ).texture;
15947					return mapTextureMapping( cubemap, texture.mapping );
15948
15949				} else {
15950
15951					const image = texture.image;
15952
15953					if ( image && image.height > 0 ) {
15954
15955						const renderTarget = new WebGLCubeRenderTarget( image.height );
15956						renderTarget.fromEquirectangularTexture( renderer, texture );
15957						cubemaps.set( texture, renderTarget );
15958
15959						texture.addEventListener( 'dispose', onTextureDispose );
15960
15961						return mapTextureMapping( renderTarget.texture, texture.mapping );
15962
15963					} else {
15964
15965						// image not yet ready. try the conversion next frame
15966
15967						return null;
15968
15969					}
15970
15971				}
15972
15973			}
15974
15975		}
15976
15977		return texture;
15978
15979	}
15980
15981	function onTextureDispose( event ) {
15982
15983		const texture = event.target;
15984
15985		texture.removeEventListener( 'dispose', onTextureDispose );
15986
15987		const cubemap = cubemaps.get( texture );
15988
15989		if ( cubemap !== undefined ) {
15990
15991			cubemaps.delete( texture );
15992			cubemap.dispose();
15993
15994		}
15995
15996	}
15997
15998	function dispose() {
15999
16000		cubemaps = new WeakMap();
16001
16002	}
16003
16004	return {
16005		get: get,
16006		dispose: dispose
16007	};
16008
16009}
16010
16011class OrthographicCamera extends Camera {
16012
16013	constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
16014
16015		super();
16016
16017		this.isOrthographicCamera = true;
16018
16019		this.type = 'OrthographicCamera';
16020
16021		this.zoom = 1;
16022		this.view = null;
16023
16024		this.left = left;
16025		this.right = right;
16026		this.top = top;
16027		this.bottom = bottom;
16028
16029		this.near = near;
16030		this.far = far;
16031
16032		this.updateProjectionMatrix();
16033
16034	}
16035
16036	copy( source, recursive ) {
16037
16038		super.copy( source, recursive );
16039
16040		this.left = source.left;
16041		this.right = source.right;
16042		this.top = source.top;
16043		this.bottom = source.bottom;
16044		this.near = source.near;
16045		this.far = source.far;
16046
16047		this.zoom = source.zoom;
16048		this.view = source.view === null ? null : Object.assign( {}, source.view );
16049
16050		return this;
16051
16052	}
16053
16054	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
16055
16056		if ( this.view === null ) {
16057
16058			this.view = {
16059				enabled: true,
16060				fullWidth: 1,
16061				fullHeight: 1,
16062				offsetX: 0,
16063				offsetY: 0,
16064				width: 1,
16065				height: 1
16066			};
16067
16068		}
16069
16070		this.view.enabled = true;
16071		this.view.fullWidth = fullWidth;
16072		this.view.fullHeight = fullHeight;
16073		this.view.offsetX = x;
16074		this.view.offsetY = y;
16075		this.view.width = width;
16076		this.view.height = height;
16077
16078		this.updateProjectionMatrix();
16079
16080	}
16081
16082	clearViewOffset() {
16083
16084		if ( this.view !== null ) {
16085
16086			this.view.enabled = false;
16087
16088		}
16089
16090		this.updateProjectionMatrix();
16091
16092	}
16093
16094	updateProjectionMatrix() {
16095
16096		const dx = ( this.right - this.left ) / ( 2 * this.zoom );
16097		const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
16098		const cx = ( this.right + this.left ) / 2;
16099		const cy = ( this.top + this.bottom ) / 2;
16100
16101		let left = cx - dx;
16102		let right = cx + dx;
16103		let top = cy + dy;
16104		let bottom = cy - dy;
16105
16106		if ( this.view !== null && this.view.enabled ) {
16107
16108			const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
16109			const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
16110
16111			left += scaleW * this.view.offsetX;
16112			right = left + scaleW * this.view.width;
16113			top -= scaleH * this.view.offsetY;
16114			bottom = top - scaleH * this.view.height;
16115
16116		}
16117
16118		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem );
16119
16120		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
16121
16122	}
16123
16124	toJSON( meta ) {
16125
16126		const data = super.toJSON( meta );
16127
16128		data.object.zoom = this.zoom;
16129		data.object.left = this.left;
16130		data.object.right = this.right;
16131		data.object.top = this.top;
16132		data.object.bottom = this.bottom;
16133		data.object.near = this.near;
16134		data.object.far = this.far;
16135
16136		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
16137
16138		return data;
16139
16140	}
16141
16142}
16143
16144const LOD_MIN = 4;
16145
16146// The standard deviations (radians) associated with the extra mips. These are
16147// chosen to approximate a Trowbridge-Reitz distribution function times the
16148// geometric shadowing function. These sigma values squared must match the
16149// variance #defines in cube_uv_reflection_fragment.glsl.js.
16150const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
16151
16152// The maximum length of the blur for loop. Smaller sigmas will use fewer
16153// samples and exit early, but not recompile the shader.
16154const MAX_SAMPLES = 20;
16155
16156const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
16157const _clearColor = /*@__PURE__*/ new Color();
16158let _oldTarget = null;
16159let _oldActiveCubeFace = 0;
16160let _oldActiveMipmapLevel = 0;
16161let _oldXrEnabled = false;
16162
16163// Golden Ratio
16164const PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
16165const INV_PHI = 1 / PHI;
16166
16167// Vertices of a dodecahedron (except the opposites, which represent the
16168// same axis), used as axis directions evenly spread on a sphere.
16169const _axisDirections = [
16170	/*@__PURE__*/ new Vector3( 1, 1, 1 ),
16171	/*@__PURE__*/ new Vector3( - 1, 1, 1 ),
16172	/*@__PURE__*/ new Vector3( 1, 1, - 1 ),
16173	/*@__PURE__*/ new Vector3( - 1, 1, - 1 ),
16174	/*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ),
16175	/*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ),
16176	/*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ),
16177	/*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ),
16178	/*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ),
16179	/*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ];
16180
16181/**
16182 * This class generates a Prefiltered, Mipmapped Radiance Environment Map
16183 * (PMREM) from a cubeMap environment texture. This allows different levels of
16184 * blur to be quickly accessed based on material roughness. It is packed into a
16185 * special CubeUV format that allows us to perform custom interpolation so that
16186 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
16187 * chain, it only goes down to the LOD_MIN level (above), and then creates extra
16188 * even more filtered 'mips' at the same LOD_MIN resolution, associated with
16189 * higher roughness levels. In this way we maintain resolution to smoothly
16190 * interpolate diffuse lighting while limiting sampling computation.
16191 *
16192 * Paper: Fast, Accurate Image-Based Lighting
16193 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view
16194*/
16195
16196class PMREMGenerator {
16197
16198	constructor( renderer ) {
16199
16200		this._renderer = renderer;
16201		this._pingPongRenderTarget = null;
16202
16203		this._lodMax = 0;
16204		this._cubeSize = 0;
16205		this._lodPlanes = [];
16206		this._sizeLods = [];
16207		this._sigmas = [];
16208
16209		this._blurMaterial = null;
16210		this._cubemapMaterial = null;
16211		this._equirectMaterial = null;
16212
16213		this._compileMaterial( this._blurMaterial );
16214
16215	}
16216
16217	/**
16218	 * Generates a PMREM from a supplied Scene, which can be faster than using an
16219	 * image if networking bandwidth is low. Optional sigma specifies a blur radius
16220	 * in radians to be applied to the scene before PMREM generation. Optional near
16221	 * and far planes ensure the scene is rendered in its entirety (the cubeCamera
16222	 * is placed at the origin).
16223	 */
16224	fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
16225
16226		_oldTarget = this._renderer.getRenderTarget();
16227		_oldActiveCubeFace = this._renderer.getActiveCubeFace();
16228		_oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
16229		_oldXrEnabled = this._renderer.xr.enabled;
16230
16231		this._renderer.xr.enabled = false;
vendor: 5,454 bytes, lines 16232-16441
16232
16233		this._setSize( 256 );
16234
16235		const cubeUVRenderTarget = this._allocateTargets();
16236		cubeUVRenderTarget.depthBuffer = true;
16237
16238		this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
16239
16240		if ( sigma > 0 ) {
16241
16242			this._blur( cubeUVRenderTarget, 0, 0, sigma );
16243
16244		}
16245
16246		this._applyPMREM( cubeUVRenderTarget );
16247		this._cleanup( cubeUVRenderTarget );
16248
16249		return cubeUVRenderTarget;
16250
16251	}
16252
16253	/**
16254	 * Generates a PMREM from an equirectangular texture, which can be either LDR
16255	 * or HDR. The ideal input image size is 1k (1024 x 512),
16256	 * as this matches best with the 256 x 256 cubemap output.
16257	 * The smallest supported equirectangular image size is 64 x 32.
16258	 */
16259	fromEquirectangular( equirectangular, renderTarget = null ) {
16260
16261		return this._fromTexture( equirectangular, renderTarget );
16262
16263	}
16264
16265	/**
16266	 * Generates a PMREM from an cubemap texture, which can be either LDR
16267	 * or HDR. The ideal input cube size is 256 x 256,
16268	 * as this matches best with the 256 x 256 cubemap output.
16269	 * The smallest supported cube size is 16 x 16.
16270	 */
16271	fromCubemap( cubemap, renderTarget = null ) {
16272
16273		return this._fromTexture( cubemap, renderTarget );
16274
16275	}
16276
16277	/**
16278	 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
16279	 * your texture's network fetch for increased concurrency.
16280	 */
16281	compileCubemapShader() {
16282
16283		if ( this._cubemapMaterial === null ) {
16284
16285			this._cubemapMaterial = _getCubemapMaterial();
16286			this._compileMaterial( this._cubemapMaterial );
16287
16288		}
16289
16290	}
16291
16292	/**
16293	 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
16294	 * your texture's network fetch for increased concurrency.
16295	 */
16296	compileEquirectangularShader() {
16297
16298		if ( this._equirectMaterial === null ) {
16299
16300			this._equirectMaterial = _getEquirectMaterial();
16301			this._compileMaterial( this._equirectMaterial );
16302
16303		}
16304
16305	}
16306
16307	/**
16308	 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
16309	 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
16310	 * one of them will cause any others to also become unusable.
16311	 */
16312	dispose() {
16313
16314		this._dispose();
16315
16316		if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose();
16317		if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose();
16318
16319	}
16320
16321	// private interface
16322
16323	_setSize( cubeSize ) {
16324
16325		this._lodMax = Math.floor( Math.log2( cubeSize ) );
16326		this._cubeSize = Math.pow( 2, this._lodMax );
16327
16328	}
16329
16330	_dispose() {
16331
16332		if ( this._blurMaterial !== null ) this._blurMaterial.dispose();
16333
16334		if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose();
16335
16336		for ( let i = 0; i < this._lodPlanes.length; i ++ ) {
16337
16338			this._lodPlanes[ i ].dispose();
16339
16340		}
16341
16342	}
16343
16344	_cleanup( outputTarget ) {
16345
16346		this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel );
16347		this._renderer.xr.enabled = _oldXrEnabled;
16348
16349		outputTarget.scissorTest = false;
16350		_setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
16351
16352	}
16353
16354	_fromTexture( texture, renderTarget ) {
16355
16356		if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
16357
16358			this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
16359
16360		} else { // Equirectangular
16361
16362			this._setSize( texture.image.width / 4 );
16363
16364		}
16365
16366		_oldTarget = this._renderer.getRenderTarget();
16367		_oldActiveCubeFace = this._renderer.getActiveCubeFace();
16368		_oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
16369		_oldXrEnabled = this._renderer.xr.enabled;
16370
16371		this._renderer.xr.enabled = false;
16372
16373		const cubeUVRenderTarget = renderTarget || this._allocateTargets();
16374		this._textureToCubeUV( texture, cubeUVRenderTarget );
16375		this._applyPMREM( cubeUVRenderTarget );
16376		this._cleanup( cubeUVRenderTarget );
16377
16378		return cubeUVRenderTarget;
16379
16380	}
16381
16382	_allocateTargets() {
16383
16384		const width = 3 * Math.max( this._cubeSize, 16 * 7 );
16385		const height = 4 * this._cubeSize;
16386
16387		const params = {
16388			magFilter: LinearFilter,
16389			minFilter: LinearFilter,
16390			generateMipmaps: false,
16391			type: HalfFloatType,
16392			format: RGBAFormat,
16393			colorSpace: LinearSRGBColorSpace,
16394			depthBuffer: false
16395		};
16396
16397		const cubeUVRenderTarget = _createRenderTarget( width, height, params );
16398
16399		if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) {
16400
16401			if ( this._pingPongRenderTarget !== null ) {
16402
16403				this._dispose();
16404
16405			}
16406
16407			this._pingPongRenderTarget = _createRenderTarget( width, height, params );
16408
16409			const { _lodMax } = this;
16410			( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) );
16411
16412			this._blurMaterial = _getBlurShader( _lodMax, width, height );
16413
16414		}
16415
16416		return cubeUVRenderTarget;
16417
16418	}
16419
16420	_compileMaterial( material ) {
16421
16422		const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material );
16423		this._renderer.compile( tmpMesh, _flatCamera );
16424
16425	}
16426
16427	_sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
16428
16429		const fov = 90;
16430		const aspect = 1;
16431		const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
16432		const upSign = [ 1, - 1, 1, 1, 1, 1 ];
16433		const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
16434		const renderer = this._renderer;
16435
16436		const originalAutoClear = renderer.autoClear;
16437		const toneMapping = renderer.toneMapping;
16438		renderer.getClearColor( _clearColor );
16439
16440		renderer.toneMapping = NoToneMapping;
16441		renderer.autoClear = false;
vendor: 8,445 bytes, lines 16442-16797
16442
16443		const backgroundMaterial = new MeshBasicMaterial( {
16444			name: 'PMREM.Background',
16445			side: BackSide,
16446			depthWrite: false,
16447			depthTest: false,
16448		} );
16449
16450		const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial );
16451
16452		let useSolidColor = false;
16453		const background = scene.background;
16454
16455		if ( background ) {
16456
16457			if ( background.isColor ) {
16458
16459				backgroundMaterial.color.copy( background );
16460				scene.background = null;
16461				useSolidColor = true;
16462
16463			}
16464
16465		} else {
16466
16467			backgroundMaterial.color.copy( _clearColor );
16468			useSolidColor = true;
16469
16470		}
16471
16472		for ( let i = 0; i < 6; i ++ ) {
16473
16474			const col = i % 3;
16475
16476			if ( col === 0 ) {
16477
16478				cubeCamera.up.set( 0, upSign[ i ], 0 );
16479				cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
16480
16481			} else if ( col === 1 ) {
16482
16483				cubeCamera.up.set( 0, 0, upSign[ i ] );
16484				cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
16485
16486			} else {
16487
16488				cubeCamera.up.set( 0, upSign[ i ], 0 );
16489				cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
16490
16491			}
16492
16493			const size = this._cubeSize;
16494
16495			_setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size );
16496
16497			renderer.setRenderTarget( cubeUVRenderTarget );
16498
16499			if ( useSolidColor ) {
16500
16501				renderer.render( backgroundBox, cubeCamera );
16502
16503			}
16504
16505			renderer.render( scene, cubeCamera );
16506
16507		}
16508
16509		backgroundBox.geometry.dispose();
16510		backgroundBox.material.dispose();
16511
16512		renderer.toneMapping = toneMapping;
16513		renderer.autoClear = originalAutoClear;
16514		scene.background = background;
16515
16516	}
16517
16518	_textureToCubeUV( texture, cubeUVRenderTarget ) {
16519
16520		const renderer = this._renderer;
16521
16522		const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping );
16523
16524		if ( isCubeTexture ) {
16525
16526			if ( this._cubemapMaterial === null ) {
16527
16528				this._cubemapMaterial = _getCubemapMaterial();
16529
16530			}
16531
16532			this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1;
16533
16534		} else {
16535
16536			if ( this._equirectMaterial === null ) {
16537
16538				this._equirectMaterial = _getEquirectMaterial();
16539
16540			}
16541
16542		}
16543
16544		const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
16545		const mesh = new Mesh( this._lodPlanes[ 0 ], material );
16546
16547		const uniforms = material.uniforms;
16548
16549		uniforms[ 'envMap' ].value = texture;
16550
16551		const size = this._cubeSize;
16552
16553		_setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size );
16554
16555		renderer.setRenderTarget( cubeUVRenderTarget );
16556		renderer.render( mesh, _flatCamera );
16557
16558	}
16559
16560	_applyPMREM( cubeUVRenderTarget ) {
16561
16562		const renderer = this._renderer;
16563		const autoClear = renderer.autoClear;
16564		renderer.autoClear = false;
16565
16566		for ( let i = 1; i < this._lodPlanes.length; i ++ ) {
16567
16568			const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] );
16569
16570			const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ];
16571
16572			this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
16573
16574		}
16575
16576		renderer.autoClear = autoClear;
16577
16578	}
16579
16580	/**
16581	 * This is a two-pass Gaussian blur for a cubemap. Normally this is done
16582	 * vertically and horizontally, but this breaks down on a cube. Here we apply
16583	 * the blur latitudinally (around the poles), and then longitudinally (towards
16584	 * the poles) to approximate the orthogonally-separable blur. It is least
16585	 * accurate at the poles, but still does a decent job.
16586	 */
16587	_blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
16588
16589		const pingPongRenderTarget = this._pingPongRenderTarget;
16590
16591		this._halfBlur(
16592			cubeUVRenderTarget,
16593			pingPongRenderTarget,
16594			lodIn,
16595			lodOut,
16596			sigma,
16597			'latitudinal',
16598			poleAxis );
16599
16600		this._halfBlur(
16601			pingPongRenderTarget,
16602			cubeUVRenderTarget,
16603			lodOut,
16604			lodOut,
16605			sigma,
16606			'longitudinal',
16607			poleAxis );
16608
16609	}
16610
16611	_halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
16612
16613		const renderer = this._renderer;
16614		const blurMaterial = this._blurMaterial;
16615
16616		if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
16617
16618			console.error(
16619				'blur direction must be either latitudinal or longitudinal!' );
16620
16621		}
16622
16623		// Number of standard deviations at which to cut off the discrete approximation.
16624		const STANDARD_DEVIATIONS = 3;
16625
16626		const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial );
16627		const blurUniforms = blurMaterial.uniforms;
16628
16629		const pixels = this._sizeLods[ lodIn ] - 1;
16630		const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
16631		const sigmaPixels = sigmaRadians / radiansPerPixel;
16632		const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
16633
16634		if ( samples > MAX_SAMPLES ) {
16635
16636			console.warn( `sigmaRadians, ${
16637				sigmaRadians}, is too large and will clip, as it requested ${
16638				samples} samples when the maximum is set to ${MAX_SAMPLES}` );
16639
16640		}
16641
16642		const weights = [];
16643		let sum = 0;
16644
16645		for ( let i = 0; i < MAX_SAMPLES; ++ i ) {
16646
16647			const x = i / sigmaPixels;
16648			const weight = Math.exp( - x * x / 2 );
16649			weights.push( weight );
16650
16651			if ( i === 0 ) {
16652
16653				sum += weight;
16654
16655			} else if ( i < samples ) {
16656
16657				sum += 2 * weight;
16658
16659			}
16660
16661		}
16662
16663		for ( let i = 0; i < weights.length; i ++ ) {
16664
16665			weights[ i ] = weights[ i ] / sum;
16666
16667		}
16668
16669		blurUniforms[ 'envMap' ].value = targetIn.texture;
16670		blurUniforms[ 'samples' ].value = samples;
16671		blurUniforms[ 'weights' ].value = weights;
16672		blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
16673
16674		if ( poleAxis ) {
16675
16676			blurUniforms[ 'poleAxis' ].value = poleAxis;
16677
16678		}
16679
16680		const { _lodMax } = this;
16681		blurUniforms[ 'dTheta' ].value = radiansPerPixel;
16682		blurUniforms[ 'mipInt' ].value = _lodMax - lodIn;
16683
16684		const outputSize = this._sizeLods[ lodOut ];
16685		const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 );
16686		const y = 4 * ( this._cubeSize - outputSize );
16687
16688		_setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
16689		renderer.setRenderTarget( targetOut );
16690		renderer.render( blurMesh, _flatCamera );
16691
16692	}
16693
16694}
16695
16696
16697
16698function _createPlanes( lodMax ) {
16699
16700	const lodPlanes = [];
16701	const sizeLods = [];
16702	const sigmas = [];
16703
16704	let lod = lodMax;
16705
16706	const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
16707
16708	for ( let i = 0; i < totalLods; i ++ ) {
16709
16710		const sizeLod = Math.pow( 2, lod );
16711		sizeLods.push( sizeLod );
16712		let sigma = 1.0 / sizeLod;
16713
16714		if ( i > lodMax - LOD_MIN ) {
16715
16716			sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ];
16717
16718		} else if ( i === 0 ) {
16719
16720			sigma = 0;
16721
16722		}
16723
16724		sigmas.push( sigma );
16725
16726		const texelSize = 1.0 / ( sizeLod - 2 );
16727		const min = - texelSize;
16728		const max = 1 + texelSize;
16729		const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
16730
16731		const cubeFaces = 6;
16732		const vertices = 6;
16733		const positionSize = 3;
16734		const uvSize = 2;
16735		const faceIndexSize = 1;
16736
16737		const position = new Float32Array( positionSize * vertices * cubeFaces );
16738		const uv = new Float32Array( uvSize * vertices * cubeFaces );
16739		const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
16740
16741		for ( let face = 0; face < cubeFaces; face ++ ) {
16742
16743			const x = ( face % 3 ) * 2 / 3 - 1;
16744			const y = face > 2 ? 0 : - 1;
16745			const coordinates = [
16746				x, y, 0,
16747				x + 2 / 3, y, 0,
16748				x + 2 / 3, y + 1, 0,
16749				x, y, 0,
16750				x + 2 / 3, y + 1, 0,
16751				x, y + 1, 0
16752			];
16753			position.set( coordinates, positionSize * vertices * face );
16754			uv.set( uv1, uvSize * vertices * face );
16755			const fill = [ face, face, face, face, face, face ];
16756			faceIndex.set( fill, faceIndexSize * vertices * face );
16757
16758		}
16759
16760		const planes = new BufferGeometry();
16761		planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
16762		planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
16763		planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
16764		lodPlanes.push( planes );
16765
16766		if ( lod > LOD_MIN ) {
16767
16768			lod --;
16769
16770		}
16771
16772	}
16773
16774	return { lodPlanes, sizeLods, sigmas };
16775
16776}
16777
16778function _createRenderTarget( width, height, params ) {
16779
16780	const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params );
16781	cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
16782	cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
16783	cubeUVRenderTarget.scissorTest = true;
16784	return cubeUVRenderTarget;
16785
16786}
16787
16788function _setViewport( target, x, y, width, height ) {
16789
16790	target.viewport.set( x, y, width, height );
16791	target.scissor.set( x, y, width, height );
16792
16793}
16794
16795function _getBlurShader( lodMax, width, height ) {
16796
16797	const weights = new Float32Array( MAX_SAMPLES );
vendor: 4,417 bytes, lines 16798-17036
16798	const poleAxis = new Vector3( 0, 1, 0 );
16799	const shaderMaterial = new ShaderMaterial( {
16800
16801		name: 'SphericalGaussianBlur',
16802
16803		defines: {
16804			'n': MAX_SAMPLES,
16805			'CUBEUV_TEXEL_WIDTH': 1.0 / width,
16806			'CUBEUV_TEXEL_HEIGHT': 1.0 / height,
16807			'CUBEUV_MAX_MIP': `${lodMax}.0`,
16808		},
16809
16810		uniforms: {
16811			'envMap': { value: null },
16812			'samples': { value: 1 },
16813			'weights': { value: weights },
16814			'latitudinal': { value: false },
16815			'dTheta': { value: 0 },
16816			'mipInt': { value: 0 },
16817			'poleAxis': { value: poleAxis }
16818		},
16819
16820		vertexShader: _getCommonVertexShader(),
16821
16822		fragmentShader: /* glsl */`
16823
16824			precision mediump float;
16825			precision mediump int;
16826
16827			varying vec3 vOutputDirection;
16828
16829			uniform sampler2D envMap;
16830			uniform int samples;
16831			uniform float weights[ n ];
16832			uniform bool latitudinal;
16833			uniform float dTheta;
16834			uniform float mipInt;
16835			uniform vec3 poleAxis;
16836
16837			#define ENVMAP_TYPE_CUBE_UV
16838			#include <cube_uv_reflection_fragment>
16839
16840			vec3 getSample( float theta, vec3 axis ) {
16841
16842				float cosTheta = cos( theta );
16843				// Rodrigues' axis-angle rotation
16844				vec3 sampleDirection = vOutputDirection * cosTheta
16845					+ cross( axis, vOutputDirection ) * sin( theta )
16846					+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
16847
16848				return bilinearCubeUV( envMap, sampleDirection, mipInt );
16849
16850			}
16851
16852			void main() {
16853
16854				vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
16855
16856				if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
16857
16858					axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
16859
16860				}
16861
16862				axis = normalize( axis );
16863
16864				gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
16865				gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
16866
16867				for ( int i = 1; i < n; i++ ) {
16868
16869					if ( i >= samples ) {
16870
16871						break;
16872
16873					}
16874
16875					float theta = dTheta * float( i );
16876					gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
16877					gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
16878
16879				}
16880
16881			}
16882		`,
16883
16884		blending: NoBlending,
16885		depthTest: false,
16886		depthWrite: false
16887
16888	} );
16889
16890	return shaderMaterial;
16891
16892}
16893
16894function _getEquirectMaterial() {
16895
16896	return new ShaderMaterial( {
16897
16898		name: 'EquirectangularToCubeUV',
16899
16900		uniforms: {
16901			'envMap': { value: null }
16902		},
16903
16904		vertexShader: _getCommonVertexShader(),
16905
16906		fragmentShader: /* glsl */`
16907
16908			precision mediump float;
16909			precision mediump int;
16910
16911			varying vec3 vOutputDirection;
16912
16913			uniform sampler2D envMap;
16914
16915			#include <common>
16916
16917			void main() {
16918
16919				vec3 outputDirection = normalize( vOutputDirection );
16920				vec2 uv = equirectUv( outputDirection );
16921
16922				gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );
16923
16924			}
16925		`,
16926
16927		blending: NoBlending,
16928		depthTest: false,
16929		depthWrite: false
16930
16931	} );
16932
16933}
16934
16935function _getCubemapMaterial() {
16936
16937	return new ShaderMaterial( {
16938
16939		name: 'CubemapToCubeUV',
16940
16941		uniforms: {
16942			'envMap': { value: null },
16943			'flipEnvMap': { value: - 1 }
16944		},
16945
16946		vertexShader: _getCommonVertexShader(),
16947
16948		fragmentShader: /* glsl */`
16949
16950			precision mediump float;
16951			precision mediump int;
16952
16953			uniform float flipEnvMap;
16954
16955			varying vec3 vOutputDirection;
16956
16957			uniform samplerCube envMap;
16958
16959			void main() {
16960
16961				gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
16962
16963			}
16964		`,
16965
16966		blending: NoBlending,
16967		depthTest: false,
16968		depthWrite: false
16969
16970	} );
16971
16972}
16973
16974function _getCommonVertexShader() {
16975
16976	return /* glsl */`
16977
16978		precision mediump float;
16979		precision mediump int;
16980
16981		attribute float faceIndex;
16982
16983		varying vec3 vOutputDirection;
16984
16985		// RH coordinate system; PMREM face-indexing convention
16986		vec3 getDirection( vec2 uv, float face ) {
16987
16988			uv = 2.0 * uv - 1.0;
16989
16990			vec3 direction = vec3( uv, 1.0 );
16991
16992			if ( face == 0.0 ) {
16993
16994				direction = direction.zyx; // ( 1, v, u ) pos x
16995
16996			} else if ( face == 1.0 ) {
16997
16998				direction = direction.xzy;
16999				direction.xz *= -1.0; // ( -u, 1, -v ) pos y
17000
17001			} else if ( face == 2.0 ) {
17002
17003				direction.x *= -1.0; // ( -u, v, 1 ) pos z
17004
17005			} else if ( face == 3.0 ) {
17006
17007				direction = direction.zyx;
17008				direction.xz *= -1.0; // ( -1, v, -u ) neg x
17009
17010			} else if ( face == 4.0 ) {
17011
17012				direction = direction.xzy;
17013				direction.xy *= -1.0; // ( -u, -1, v ) neg y
17014
17015			} else if ( face == 5.0 ) {
17016
17017				direction.z *= -1.0; // ( u, v, -1 ) neg z
17018
17019			}
17020
17021			return direction;
17022
17023		}
17024
17025		void main() {
17026
17027			vOutputDirection = getDirection( uv, faceIndex );
17028			gl_Position = vec4( position, 1.0 );
17029
17030		}
17031	`;
17032
17033}
17034
17035function WebGLCubeUVMaps( renderer ) {
17036
vendor: 12,094 bytes, lines 17037-17637
17037	let cubeUVmaps = new WeakMap();
17038
17039	let pmremGenerator = null;
17040
17041	function get( texture ) {
17042
17043		if ( texture && texture.isTexture ) {
17044
17045			const mapping = texture.mapping;
17046
17047			const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
17048			const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
17049
17050			// equirect/cube map to cubeUV conversion
17051
17052			if ( isEquirectMap || isCubeMap ) {
17053
17054				let renderTarget = cubeUVmaps.get( texture );
17055
17056				const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0;
17057
17058				if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) {
17059
17060					if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
17061
17062					renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget );
17063					renderTarget.texture.pmremVersion = texture.pmremVersion;
17064
17065					cubeUVmaps.set( texture, renderTarget );
17066
17067					return renderTarget.texture;
17068
17069				} else {
17070
17071					if ( renderTarget !== undefined ) {
17072
17073						return renderTarget.texture;
17074
17075					} else {
17076
17077						const image = texture.image;
17078
17079						if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) {
17080
17081							if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
17082
17083							renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture );
17084							renderTarget.texture.pmremVersion = texture.pmremVersion;
17085
17086							cubeUVmaps.set( texture, renderTarget );
17087
17088							texture.addEventListener( 'dispose', onTextureDispose );
17089
17090							return renderTarget.texture;
17091
17092						} else {
17093
17094							// image not yet ready. try the conversion next frame
17095
17096							return null;
17097
17098						}
17099
17100					}
17101
17102				}
17103
17104			}
17105
17106		}
17107
17108		return texture;
17109
17110	}
17111
17112	function isCubeTextureComplete( image ) {
17113
17114		let count = 0;
17115		const length = 6;
17116
17117		for ( let i = 0; i < length; i ++ ) {
17118
17119			if ( image[ i ] !== undefined ) count ++;
17120
17121		}
17122
17123		return count === length;
17124
17125
17126	}
17127
17128	function onTextureDispose( event ) {
17129
17130		const texture = event.target;
17131
17132		texture.removeEventListener( 'dispose', onTextureDispose );
17133
17134		const cubemapUV = cubeUVmaps.get( texture );
17135
17136		if ( cubemapUV !== undefined ) {
17137
17138			cubeUVmaps.delete( texture );
17139			cubemapUV.dispose();
17140
17141		}
17142
17143	}
17144
17145	function dispose() {
17146
17147		cubeUVmaps = new WeakMap();
17148
17149		if ( pmremGenerator !== null ) {
17150
17151			pmremGenerator.dispose();
17152			pmremGenerator = null;
17153
17154		}
17155
17156	}
17157
17158	return {
17159		get: get,
17160		dispose: dispose
17161	};
17162
17163}
17164
17165function WebGLExtensions( gl ) {
17166
17167	const extensions = {};
17168
17169	function getExtension( name ) {
17170
17171		if ( extensions[ name ] !== undefined ) {
17172
17173			return extensions[ name ];
17174
17175		}
17176
17177		let extension;
17178
17179		switch ( name ) {
17180
17181			case 'WEBGL_depth_texture':
17182				extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
17183				break;
17184
17185			case 'EXT_texture_filter_anisotropic':
17186				extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
17187				break;
17188
17189			case 'WEBGL_compressed_texture_s3tc':
17190				extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
17191				break;
17192
17193			case 'WEBGL_compressed_texture_pvrtc':
17194				extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
17195				break;
17196
17197			default:
17198				extension = gl.getExtension( name );
17199
17200		}
17201
17202		extensions[ name ] = extension;
17203
17204		return extension;
17205
17206	}
17207
17208	return {
17209
17210		has: function ( name ) {
17211
17212			return getExtension( name ) !== null;
17213
17214		},
17215
17216		init: function () {
17217
17218			getExtension( 'EXT_color_buffer_float' );
17219			getExtension( 'WEBGL_clip_cull_distance' );
17220			getExtension( 'OES_texture_float_linear' );
17221			getExtension( 'EXT_color_buffer_half_float' );
17222			getExtension( 'WEBGL_multisampled_render_to_texture' );
17223			getExtension( 'WEBGL_render_shared_exponent' );
17224
17225		},
17226
17227		get: function ( name ) {
17228
17229			const extension = getExtension( name );
17230
17231			if ( extension === null ) {
17232
17233				console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
17234
17235			}
17236
17237			return extension;
17238
17239		}
17240
17241	};
17242
17243}
17244
17245function WebGLGeometries( gl, attributes, info, bindingStates ) {
17246
17247	const geometries = {};
17248	const wireframeAttributes = new WeakMap();
17249
17250	function onGeometryDispose( event ) {
17251
17252		const geometry = event.target;
17253
17254		if ( geometry.index !== null ) {
17255
17256			attributes.remove( geometry.index );
17257
17258		}
17259
17260		for ( const name in geometry.attributes ) {
17261
17262			attributes.remove( geometry.attributes[ name ] );
17263
17264		}
17265
17266		for ( const name in geometry.morphAttributes ) {
17267
17268			const array = geometry.morphAttributes[ name ];
17269
17270			for ( let i = 0, l = array.length; i < l; i ++ ) {
17271
17272				attributes.remove( array[ i ] );
17273
17274			}
17275
17276		}
17277
17278		geometry.removeEventListener( 'dispose', onGeometryDispose );
17279
17280		delete geometries[ geometry.id ];
17281
17282		const attribute = wireframeAttributes.get( geometry );
17283
17284		if ( attribute ) {
17285
17286			attributes.remove( attribute );
17287			wireframeAttributes.delete( geometry );
17288
17289		}
17290
17291		bindingStates.releaseStatesOfGeometry( geometry );
17292
17293		if ( geometry.isInstancedBufferGeometry === true ) {
17294
17295			delete geometry._maxInstanceCount;
17296
17297		}
17298
17299		//
17300
17301		info.memory.geometries --;
17302
17303	}
17304
17305	function get( object, geometry ) {
17306
17307		if ( geometries[ geometry.id ] === true ) return geometry;
17308
17309		geometry.addEventListener( 'dispose', onGeometryDispose );
17310
17311		geometries[ geometry.id ] = true;
17312
17313		info.memory.geometries ++;
17314
17315		return geometry;
17316
17317	}
17318
17319	function update( geometry ) {
17320
17321		const geometryAttributes = geometry.attributes;
17322
17323		// Updating index buffer in VAO now. See WebGLBindingStates.
17324
17325		for ( const name in geometryAttributes ) {
17326
17327			attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
17328
17329		}
17330
17331		// morph targets
17332
17333		const morphAttributes = geometry.morphAttributes;
17334
17335		for ( const name in morphAttributes ) {
17336
17337			const array = morphAttributes[ name ];
17338
17339			for ( let i = 0, l = array.length; i < l; i ++ ) {
17340
17341				attributes.update( array[ i ], gl.ARRAY_BUFFER );
17342
17343			}
17344
17345		}
17346
17347	}
17348
17349	function updateWireframeAttribute( geometry ) {
17350
17351		const indices = [];
17352
17353		const geometryIndex = geometry.index;
17354		const geometryPosition = geometry.attributes.position;
17355		let version = 0;
17356
17357		if ( geometryIndex !== null ) {
17358
17359			const array = geometryIndex.array;
17360			version = geometryIndex.version;
17361
17362			for ( let i = 0, l = array.length; i < l; i += 3 ) {
17363
17364				const a = array[ i + 0 ];
17365				const b = array[ i + 1 ];
17366				const c = array[ i + 2 ];
17367
17368				indices.push( a, b, b, c, c, a );
17369
17370			}
17371
17372		} else if ( geometryPosition !== undefined ) {
17373
17374			const array = geometryPosition.array;
17375			version = geometryPosition.version;
17376
17377			for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
17378
17379				const a = i + 0;
17380				const b = i + 1;
17381				const c = i + 2;
17382
17383				indices.push( a, b, b, c, c, a );
17384
17385			}
17386
17387		} else {
17388
17389			return;
17390
17391		}
17392
17393		const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
17394		attribute.version = version;
17395
17396		// Updating index buffer in VAO now. See WebGLBindingStates
17397
17398		//
17399
17400		const previousAttribute = wireframeAttributes.get( geometry );
17401
17402		if ( previousAttribute ) attributes.remove( previousAttribute );
17403
17404		//
17405
17406		wireframeAttributes.set( geometry, attribute );
17407
17408	}
17409
17410	function getWireframeAttribute( geometry ) {
17411
17412		const currentAttribute = wireframeAttributes.get( geometry );
17413
17414		if ( currentAttribute ) {
17415
17416			const geometryIndex = geometry.index;
17417
17418			if ( geometryIndex !== null ) {
17419
17420				// if the attribute is obsolete, create a new one
17421
17422				if ( currentAttribute.version < geometryIndex.version ) {
17423
17424					updateWireframeAttribute( geometry );
17425
17426				}
17427
17428			}
17429
17430		} else {
17431
17432			updateWireframeAttribute( geometry );
17433
17434		}
17435
17436		return wireframeAttributes.get( geometry );
17437
17438	}
17439
17440	return {
17441
17442		get: get,
17443		update: update,
17444
17445		getWireframeAttribute: getWireframeAttribute
17446
17447	};
17448
17449}
17450
17451function WebGLIndexedBufferRenderer( gl, extensions, info ) {
17452
17453	let mode;
17454
17455	function setMode( value ) {
17456
17457		mode = value;
17458
17459	}
17460
17461	let type, bytesPerElement;
17462
17463	function setIndex( value ) {
17464
17465		type = value.type;
17466		bytesPerElement = value.bytesPerElement;
17467
17468	}
17469
17470	function render( start, count ) {
17471
17472		gl.drawElements( mode, count, type, start * bytesPerElement );
17473
17474		info.update( count, mode, 1 );
17475
17476	}
17477
17478	function renderInstances( start, count, primcount ) {
17479
17480		if ( primcount === 0 ) return;
17481
17482		gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount );
17483
17484		info.update( count, mode, primcount );
17485
17486	}
17487
17488	function renderMultiDraw( starts, counts, drawCount ) {
17489
17490		if ( drawCount === 0 ) return;
17491
17492		const extension = extensions.get( 'WEBGL_multi_draw' );
17493
17494		if ( extension === null ) {
17495
17496			for ( let i = 0; i < drawCount; i ++ ) {
17497
17498				this.render( starts[ i ] / bytesPerElement, counts[ i ] );
17499
17500			}
17501
17502		} else {
17503
17504			extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount );
17505
17506			let elementCount = 0;
17507			for ( let i = 0; i < drawCount; i ++ ) {
17508
17509				elementCount += counts[ i ];
17510
17511			}
17512
17513			info.update( elementCount, mode, 1 );
17514
17515		}
17516
17517	}
17518
17519	//
17520
17521	this.setMode = setMode;
17522	this.setIndex = setIndex;
17523	this.render = render;
17524	this.renderInstances = renderInstances;
17525	this.renderMultiDraw = renderMultiDraw;
17526
17527}
17528
17529function WebGLInfo( gl ) {
17530
17531	const memory = {
17532		geometries: 0,
17533		textures: 0
17534	};
17535
17536	const render = {
17537		frame: 0,
17538		calls: 0,
17539		triangles: 0,
17540		points: 0,
17541		lines: 0
17542	};
17543
17544	function update( count, mode, instanceCount ) {
17545
17546		render.calls ++;
17547
17548		switch ( mode ) {
17549
17550			case gl.TRIANGLES:
17551				render.triangles += instanceCount * ( count / 3 );
17552				break;
17553
17554			case gl.LINES:
17555				render.lines += instanceCount * ( count / 2 );
17556				break;
17557
17558			case gl.LINE_STRIP:
17559				render.lines += instanceCount * ( count - 1 );
17560				break;
17561
17562			case gl.LINE_LOOP:
17563				render.lines += instanceCount * count;
17564				break;
17565
17566			case gl.POINTS:
17567				render.points += instanceCount * count;
17568				break;
17569
17570			default:
17571				console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
17572				break;
17573
17574		}
17575
17576	}
17577
17578	function reset() {
17579
17580		render.calls = 0;
17581		render.triangles = 0;
17582		render.points = 0;
17583		render.lines = 0;
17584
17585	}
17586
17587	return {
17588		memory: memory,
17589		render: render,
17590		programs: null,
17591		autoReset: true,
17592		reset: reset,
17593		update: update
17594	};
17595
17596}
17597
17598function WebGLMorphtargets( gl, capabilities, textures ) {
17599
17600	const morphTextures = new WeakMap();
17601	const morph = new Vector4();
17602
17603	function update( object, geometry, program ) {
17604
17605		const objectInfluences = object.morphTargetInfluences;
17606
17607		// instead of using attributes, the WebGL 2 code path encodes morph targets
17608		// into an array of data textures. Each layer represents a single morph target.
17609
17610		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
17611		const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
17612
17613		let entry = morphTextures.get( geometry );
17614
17615		if ( entry === undefined || entry.count !== morphTargetsCount ) {
17616
17617			if ( entry !== undefined ) entry.texture.dispose();
17618
17619			const hasMorphPosition = geometry.morphAttributes.position !== undefined;
17620			const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
17621			const hasMorphColors = geometry.morphAttributes.color !== undefined;
17622
17623			const morphTargets = geometry.morphAttributes.position || [];
17624			const morphNormals = geometry.morphAttributes.normal || [];
17625			const morphColors = geometry.morphAttributes.color || [];
17626
17627			let vertexDataCount = 0;
17628
17629			if ( hasMorphPosition === true ) vertexDataCount = 1;
17630			if ( hasMorphNormals === true ) vertexDataCount = 2;
17631			if ( hasMorphColors === true ) vertexDataCount = 3;
17632
17633			let width = geometry.attributes.position.count * vertexDataCount;
17634			let height = 1;
17635
17636			if ( width > capabilities.maxTextureSize ) {
17637
vendor: 2,781 bytes, lines 17638-17748
17638				height = Math.ceil( width / capabilities.maxTextureSize );
17639				width = capabilities.maxTextureSize;
17640
17641			}
17642
17643			const buffer = new Float32Array( width * height * 4 * morphTargetsCount );
17644
17645			const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount );
17646			texture.type = FloatType;
17647			texture.needsUpdate = true;
17648
17649			// fill buffer
17650
17651			const vertexDataStride = vertexDataCount * 4;
17652
17653			for ( let i = 0; i < morphTargetsCount; i ++ ) {
17654
17655				const morphTarget = morphTargets[ i ];
17656				const morphNormal = morphNormals[ i ];
17657				const morphColor = morphColors[ i ];
17658
17659				const offset = width * height * 4 * i;
17660
17661				for ( let j = 0; j < morphTarget.count; j ++ ) {
17662
17663					const stride = j * vertexDataStride;
17664
17665					if ( hasMorphPosition === true ) {
17666
17667						morph.fromBufferAttribute( morphTarget, j );
17668
17669						buffer[ offset + stride + 0 ] = morph.x;
17670						buffer[ offset + stride + 1 ] = morph.y;
17671						buffer[ offset + stride + 2 ] = morph.z;
17672						buffer[ offset + stride + 3 ] = 0;
17673
17674					}
17675
17676					if ( hasMorphNormals === true ) {
17677
17678						morph.fromBufferAttribute( morphNormal, j );
17679
17680						buffer[ offset + stride + 4 ] = morph.x;
17681						buffer[ offset + stride + 5 ] = morph.y;
17682						buffer[ offset + stride + 6 ] = morph.z;
17683						buffer[ offset + stride + 7 ] = 0;
17684
17685					}
17686
17687					if ( hasMorphColors === true ) {
17688
17689						morph.fromBufferAttribute( morphColor, j );
17690
17691						buffer[ offset + stride + 8 ] = morph.x;
17692						buffer[ offset + stride + 9 ] = morph.y;
17693						buffer[ offset + stride + 10 ] = morph.z;
17694						buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1;
17695
17696					}
17697
17698				}
17699
17700			}
17701
17702			entry = {
17703				count: morphTargetsCount,
17704				texture: texture,
17705				size: new Vector2( width, height )
17706			};
17707
17708			morphTextures.set( geometry, entry );
17709
17710			function disposeTexture() {
17711
17712				texture.dispose();
17713
17714				morphTextures.delete( geometry );
17715
17716				geometry.removeEventListener( 'dispose', disposeTexture );
17717
17718			}
17719
17720			geometry.addEventListener( 'dispose', disposeTexture );
17721
17722		}
17723
17724		//
17725		if ( object.isInstancedMesh === true && object.morphTexture !== null ) {
17726
17727			program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures );
17728
17729		} else {
17730
17731			let morphInfluencesSum = 0;
17732
17733			for ( let i = 0; i < objectInfluences.length; i ++ ) {
17734
17735				morphInfluencesSum += objectInfluences[ i ];
17736
17737			}
17738
17739			const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
17740
17741
17742			program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
17743			program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences );
17744
17745		}
17746
17747		program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures );
17748		program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
vendor: 26,597 bytes, lines 17748-19202
17748
17749
17750	}
17751
17752	return {
17753
17754		update: update
17755
17756	};
17757
17758}
17759
17760function WebGLObjects( gl, geometries, attributes, info ) {
17761
17762	let updateMap = new WeakMap();
17763
17764	function update( object ) {
17765
17766		const frame = info.render.frame;
17767
17768		const geometry = object.geometry;
17769		const buffergeometry = geometries.get( object, geometry );
17770
17771		// Update once per frame
17772
17773		if ( updateMap.get( buffergeometry ) !== frame ) {
17774
17775			geometries.update( buffergeometry );
17776
17777			updateMap.set( buffergeometry, frame );
17778
17779		}
17780
17781		if ( object.isInstancedMesh ) {
17782
17783			if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
17784
17785				object.addEventListener( 'dispose', onInstancedMeshDispose );
17786
17787			}
17788
17789			if ( updateMap.get( object ) !== frame ) {
17790
17791				attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER );
17792
17793				if ( object.instanceColor !== null ) {
17794
17795					attributes.update( object.instanceColor, gl.ARRAY_BUFFER );
17796
17797				}
17798
17799				updateMap.set( object, frame );
17800
17801			}
17802
17803		}
17804
17805		if ( object.isSkinnedMesh ) {
17806
17807			const skeleton = object.skeleton;
17808
17809			if ( updateMap.get( skeleton ) !== frame ) {
17810
17811				skeleton.update();
17812
17813				updateMap.set( skeleton, frame );
17814
17815			}
17816
17817		}
17818
17819		return buffergeometry;
17820
17821	}
17822
17823	function dispose() {
17824
17825		updateMap = new WeakMap();
17826
17827	}
17828
17829	function onInstancedMeshDispose( event ) {
17830
17831		const instancedMesh = event.target;
17832
17833		instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
17834
17835		attributes.remove( instancedMesh.instanceMatrix );
17836
17837		if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
17838
17839	}
17840
17841	return {
17842
17843		update: update,
17844		dispose: dispose
17845
17846	};
17847
17848}
17849
17850class DepthTexture extends Texture {
17851
17852	constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
17853
17854		format = format !== undefined ? format : DepthFormat;
17855
17856		if ( format !== DepthFormat && format !== DepthStencilFormat ) {
17857
17858			throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
17859
17860		}
17861
17862		if ( type === undefined && format === DepthFormat ) type = UnsignedIntType;
17863		if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
17864
17865		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
17866
17867		this.isDepthTexture = true;
17868
17869		this.image = { width: width, height: height };
17870
17871		this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
17872		this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
17873
17874		this.flipY = false;
17875		this.generateMipmaps = false;
17876
17877		this.compareFunction = null;
17878
17879	}
17880
17881
17882	copy( source ) {
17883
17884		super.copy( source );
17885
17886		this.compareFunction = source.compareFunction;
17887
17888		return this;
17889
17890	}
17891
17892	toJSON( meta ) {
17893
17894		const data = super.toJSON( meta );
17895
17896		if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction;
17897
17898		return data;
17899
17900	}
17901
17902}
17903
17904/**
17905 * Uniforms of a program.
17906 * Those form a tree structure with a special top-level container for the root,
17907 * which you get by calling 'new WebGLUniforms( gl, program )'.
17908 *
17909 *
17910 * Properties of inner nodes including the top-level container:
17911 *
17912 * .seq - array of nested uniforms
17913 * .map - nested uniforms by name
17914 *
17915 *
17916 * Methods of all nodes except the top-level container:
17917 *
17918 * .setValue( gl, value, [textures] )
17919 *
17920 * 		uploads a uniform value(s)
17921 *  	the 'textures' parameter is needed for sampler uniforms
17922 *
17923 *
17924 * Static methods of the top-level container (textures factorizations):
17925 *
17926 * .upload( gl, seq, values, textures )
17927 *
17928 * 		sets uniforms in 'seq' to 'values[id].value'
17929 *
17930 * .seqWithValue( seq, values ) : filteredSeq
17931 *
17932 * 		filters 'seq' entries with corresponding entry in values
17933 *
17934 *
17935 * Methods of the top-level container (textures factorizations):
17936 *
17937 * .setValue( gl, name, value, textures )
17938 *
17939 * 		sets uniform with  name 'name' to 'value'
17940 *
17941 * .setOptional( gl, obj, prop )
17942 *
17943 * 		like .set for an optional property of the object
17944 *
17945 */
17946
17947
17948const emptyTexture = /*@__PURE__*/ new Texture();
17949
17950const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 );
17951emptyShadowTexture.compareFunction = LessEqualCompare;
17952
17953const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture();
17954const empty3dTexture = /*@__PURE__*/ new Data3DTexture();
17955const emptyCubeTexture = /*@__PURE__*/ new CubeTexture();
17956
17957// --- Utilities ---
17958
17959// Array Caches (provide typed arrays for temporary by size)
17960
17961const arrayCacheF32 = [];
17962const arrayCacheI32 = [];
17963
17964// Float32Array caches used for uploading Matrix uniforms
17965
17966const mat4array = new Float32Array( 16 );
17967const mat3array = new Float32Array( 9 );
17968const mat2array = new Float32Array( 4 );
17969
17970// Flattening for arrays of vectors and matrices
17971
17972function flatten( array, nBlocks, blockSize ) {
17973
17974	const firstElem = array[ 0 ];
17975
17976	if ( firstElem <= 0 || firstElem > 0 ) return array;
17977	// unoptimized: ! isNaN( firstElem )
17978	// see http://jacksondunstan.com/articles/983
17979
17980	const n = nBlocks * blockSize;
17981	let r = arrayCacheF32[ n ];
17982
17983	if ( r === undefined ) {
17984
17985		r = new Float32Array( n );
17986		arrayCacheF32[ n ] = r;
17987
17988	}
17989
17990	if ( nBlocks !== 0 ) {
17991
17992		firstElem.toArray( r, 0 );
17993
17994		for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
17995
17996			offset += blockSize;
17997			array[ i ].toArray( r, offset );
17998
17999		}
18000
18001	}
18002
18003	return r;
18004
18005}
18006
18007function arraysEqual( a, b ) {
18008
18009	if ( a.length !== b.length ) return false;
18010
18011	for ( let i = 0, l = a.length; i < l; i ++ ) {
18012
18013		if ( a[ i ] !== b[ i ] ) return false;
18014
18015	}
18016
18017	return true;
18018
18019}
18020
18021function copyArray( a, b ) {
18022
18023	for ( let i = 0, l = b.length; i < l; i ++ ) {
18024
18025		a[ i ] = b[ i ];
18026
18027	}
18028
18029}
18030
18031// Texture unit allocation
18032
18033function allocTexUnits( textures, n ) {
18034
18035	let r = arrayCacheI32[ n ];
18036
18037	if ( r === undefined ) {
18038
18039		r = new Int32Array( n );
18040		arrayCacheI32[ n ] = r;
18041
18042	}
18043
18044	for ( let i = 0; i !== n; ++ i ) {
18045
18046		r[ i ] = textures.allocateTextureUnit();
18047
18048	}
18049
18050	return r;
18051
18052}
18053
18054// --- Setters ---
18055
18056// Note: Defining these methods externally, because they come in a bunch
18057// and this way their names minify.
18058
18059// Single scalar
18060
18061function setValueV1f( gl, v ) {
18062
18063	const cache = this.cache;
18064
18065	if ( cache[ 0 ] === v ) return;
18066
18067	gl.uniform1f( this.addr, v );
18068
18069	cache[ 0 ] = v;
18070
18071}
18072
18073// Single float vector (from flat array or THREE.VectorN)
18074
18075function setValueV2f( gl, v ) {
18076
18077	const cache = this.cache;
18078
18079	if ( v.x !== undefined ) {
18080
18081		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
18082
18083			gl.uniform2f( this.addr, v.x, v.y );
18084
18085			cache[ 0 ] = v.x;
18086			cache[ 1 ] = v.y;
18087
18088		}
18089
18090	} else {
18091
18092		if ( arraysEqual( cache, v ) ) return;
18093
18094		gl.uniform2fv( this.addr, v );
18095
18096		copyArray( cache, v );
18097
18098	}
18099
18100}
18101
18102function setValueV3f( gl, v ) {
18103
18104	const cache = this.cache;
18105
18106	if ( v.x !== undefined ) {
18107
18108		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
18109
18110			gl.uniform3f( this.addr, v.x, v.y, v.z );
18111
18112			cache[ 0 ] = v.x;
18113			cache[ 1 ] = v.y;
18114			cache[ 2 ] = v.z;
18115
18116		}
18117
18118	} else if ( v.r !== undefined ) {
18119
18120		if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
18121
18122			gl.uniform3f( this.addr, v.r, v.g, v.b );
18123
18124			cache[ 0 ] = v.r;
18125			cache[ 1 ] = v.g;
18126			cache[ 2 ] = v.b;
18127
18128		}
18129
18130	} else {
18131
18132		if ( arraysEqual( cache, v ) ) return;
18133
18134		gl.uniform3fv( this.addr, v );
18135
18136		copyArray( cache, v );
18137
18138	}
18139
18140}
18141
18142function setValueV4f( gl, v ) {
18143
18144	const cache = this.cache;
18145
18146	if ( v.x !== undefined ) {
18147
18148		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
18149
18150			gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
18151
18152			cache[ 0 ] = v.x;
18153			cache[ 1 ] = v.y;
18154			cache[ 2 ] = v.z;
18155			cache[ 3 ] = v.w;
18156
18157		}
18158
18159	} else {
18160
18161		if ( arraysEqual( cache, v ) ) return;
18162
18163		gl.uniform4fv( this.addr, v );
18164
18165		copyArray( cache, v );
18166
18167	}
18168
18169}
18170
18171// Single matrix (from flat array or THREE.MatrixN)
18172
18173function setValueM2( gl, v ) {
18174
18175	const cache = this.cache;
18176	const elements = v.elements;
18177
18178	if ( elements === undefined ) {
18179
18180		if ( arraysEqual( cache, v ) ) return;
18181
18182		gl.uniformMatrix2fv( this.addr, false, v );
18183
18184		copyArray( cache, v );
18185
18186	} else {
18187
18188		if ( arraysEqual( cache, elements ) ) return;
18189
18190		mat2array.set( elements );
18191
18192		gl.uniformMatrix2fv( this.addr, false, mat2array );
18193
18194		copyArray( cache, elements );
18195
18196	}
18197
18198}
18199
18200function setValueM3( gl, v ) {
18201
18202	const cache = this.cache;
18203	const elements = v.elements;
18204
18205	if ( elements === undefined ) {
18206
18207		if ( arraysEqual( cache, v ) ) return;
18208
18209		gl.uniformMatrix3fv( this.addr, false, v );
18210
18211		copyArray( cache, v );
18212
18213	} else {
18214
18215		if ( arraysEqual( cache, elements ) ) return;
18216
18217		mat3array.set( elements );
18218
18219		gl.uniformMatrix3fv( this.addr, false, mat3array );
18220
18221		copyArray( cache, elements );
18222
18223	}
18224
18225}
18226
18227function setValueM4( gl, v ) {
18228
18229	const cache = this.cache;
18230	const elements = v.elements;
18231
18232	if ( elements === undefined ) {
18233
18234		if ( arraysEqual( cache, v ) ) return;
18235
18236		gl.uniformMatrix4fv( this.addr, false, v );
18237
18238		copyArray( cache, v );
18239
18240	} else {
18241
18242		if ( arraysEqual( cache, elements ) ) return;
18243
18244		mat4array.set( elements );
18245
18246		gl.uniformMatrix4fv( this.addr, false, mat4array );
18247
18248		copyArray( cache, elements );
18249
18250	}
18251
18252}
18253
18254// Single integer / boolean
18255
18256function setValueV1i( gl, v ) {
18257
18258	const cache = this.cache;
18259
18260	if ( cache[ 0 ] === v ) return;
18261
18262	gl.uniform1i( this.addr, v );
18263
18264	cache[ 0 ] = v;
18265
18266}
18267
18268// Single integer / boolean vector (from flat array or THREE.VectorN)
18269
18270function setValueV2i( gl, v ) {
18271
18272	const cache = this.cache;
18273
18274	if ( v.x !== undefined ) {
18275
18276		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
18277
18278			gl.uniform2i( this.addr, v.x, v.y );
18279
18280			cache[ 0 ] = v.x;
18281			cache[ 1 ] = v.y;
18282
18283		}
18284
18285	} else {
18286
18287		if ( arraysEqual( cache, v ) ) return;
18288
18289		gl.uniform2iv( this.addr, v );
18290
18291		copyArray( cache, v );
18292
18293	}
18294
18295}
18296
18297function setValueV3i( gl, v ) {
18298
18299	const cache = this.cache;
18300
18301	if ( v.x !== undefined ) {
18302
18303		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
18304
18305			gl.uniform3i( this.addr, v.x, v.y, v.z );
18306
18307			cache[ 0 ] = v.x;
18308			cache[ 1 ] = v.y;
18309			cache[ 2 ] = v.z;
18310
18311		}
18312
18313	} else {
18314
18315		if ( arraysEqual( cache, v ) ) return;
18316
18317		gl.uniform3iv( this.addr, v );
18318
18319		copyArray( cache, v );
18320
18321	}
18322
18323}
18324
18325function setValueV4i( gl, v ) {
18326
18327	const cache = this.cache;
18328
18329	if ( v.x !== undefined ) {
18330
18331		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
18332
18333			gl.uniform4i( this.addr, v.x, v.y, v.z, v.w );
18334
18335			cache[ 0 ] = v.x;
18336			cache[ 1 ] = v.y;
18337			cache[ 2 ] = v.z;
18338			cache[ 3 ] = v.w;
18339
18340		}
18341
18342	} else {
18343
18344		if ( arraysEqual( cache, v ) ) return;
18345
18346		gl.uniform4iv( this.addr, v );
18347
18348		copyArray( cache, v );
18349
18350	}
18351
18352}
18353
18354// Single unsigned integer
18355
18356function setValueV1ui( gl, v ) {
18357
18358	const cache = this.cache;
18359
18360	if ( cache[ 0 ] === v ) return;
18361
18362	gl.uniform1ui( this.addr, v );
18363
18364	cache[ 0 ] = v;
18365
18366}
18367
18368// Single unsigned integer vector (from flat array or THREE.VectorN)
18369
18370function setValueV2ui( gl, v ) {
18371
18372	const cache = this.cache;
18373
18374	if ( v.x !== undefined ) {
18375
18376		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
18377
18378			gl.uniform2ui( this.addr, v.x, v.y );
18379
18380			cache[ 0 ] = v.x;
18381			cache[ 1 ] = v.y;
18382
18383		}
18384
18385	} else {
18386
18387		if ( arraysEqual( cache, v ) ) return;
18388
18389		gl.uniform2uiv( this.addr, v );
18390
18391		copyArray( cache, v );
18392
18393	}
18394
18395}
18396
18397function setValueV3ui( gl, v ) {
18398
18399	const cache = this.cache;
18400
18401	if ( v.x !== undefined ) {
18402
18403		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
18404
18405			gl.uniform3ui( this.addr, v.x, v.y, v.z );
18406
18407			cache[ 0 ] = v.x;
18408			cache[ 1 ] = v.y;
18409			cache[ 2 ] = v.z;
18410
18411		}
18412
18413	} else {
18414
18415		if ( arraysEqual( cache, v ) ) return;
18416
18417		gl.uniform3uiv( this.addr, v );
18418
18419		copyArray( cache, v );
18420
18421	}
18422
18423}
18424
18425function setValueV4ui( gl, v ) {
18426
18427	const cache = this.cache;
18428
18429	if ( v.x !== undefined ) {
18430
18431		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
18432
18433			gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w );
18434
18435			cache[ 0 ] = v.x;
18436			cache[ 1 ] = v.y;
18437			cache[ 2 ] = v.z;
18438			cache[ 3 ] = v.w;
18439
18440		}
18441
18442	} else {
18443
18444		if ( arraysEqual( cache, v ) ) return;
18445
18446		gl.uniform4uiv( this.addr, v );
18447
18448		copyArray( cache, v );
18449
18450	}
18451
18452}
18453
18454
18455// Single texture (2D / Cube)
18456
18457function setValueT1( gl, v, textures ) {
18458
18459	const cache = this.cache;
18460	const unit = textures.allocateTextureUnit();
18461
18462	if ( cache[ 0 ] !== unit ) {
18463
18464		gl.uniform1i( this.addr, unit );
18465		cache[ 0 ] = unit;
18466
18467	}
18468
18469	const emptyTexture2D = ( this.type === gl.SAMPLER_2D_SHADOW ) ? emptyShadowTexture : emptyTexture;
18470
18471	textures.setTexture2D( v || emptyTexture2D, unit );
18472
18473}
18474
18475function setValueT3D1( gl, v, textures ) {
18476
18477	const cache = this.cache;
18478	const unit = textures.allocateTextureUnit();
18479
18480	if ( cache[ 0 ] !== unit ) {
18481
18482		gl.uniform1i( this.addr, unit );
18483		cache[ 0 ] = unit;
18484
18485	}
18486
18487	textures.setTexture3D( v || empty3dTexture, unit );
18488
18489}
18490
18491function setValueT6( gl, v, textures ) {
18492
18493	const cache = this.cache;
18494	const unit = textures.allocateTextureUnit();
18495
18496	if ( cache[ 0 ] !== unit ) {
18497
18498		gl.uniform1i( this.addr, unit );
18499		cache[ 0 ] = unit;
18500
18501	}
18502
18503	textures.setTextureCube( v || emptyCubeTexture, unit );
18504
18505}
18506
18507function setValueT2DArray1( gl, v, textures ) {
18508
18509	const cache = this.cache;
18510	const unit = textures.allocateTextureUnit();
18511
18512	if ( cache[ 0 ] !== unit ) {
18513
18514		gl.uniform1i( this.addr, unit );
18515		cache[ 0 ] = unit;
18516
18517	}
18518
18519	textures.setTexture2DArray( v || emptyArrayTexture, unit );
18520
18521}
18522
18523// Helper to pick the right setter for the singular case
18524
18525function getSingularSetter( type ) {
18526
18527	switch ( type ) {
18528
18529		case 0x1406: return setValueV1f; // FLOAT
18530		case 0x8b50: return setValueV2f; // _VEC2
18531		case 0x8b51: return setValueV3f; // _VEC3
18532		case 0x8b52: return setValueV4f; // _VEC4
18533
18534		case 0x8b5a: return setValueM2; // _MAT2
18535		case 0x8b5b: return setValueM3; // _MAT3
18536		case 0x8b5c: return setValueM4; // _MAT4
18537
18538		case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
18539		case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
18540		case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
18541		case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
18542
18543		case 0x1405: return setValueV1ui; // UINT
18544		case 0x8dc6: return setValueV2ui; // _VEC2
18545		case 0x8dc7: return setValueV3ui; // _VEC3
18546		case 0x8dc8: return setValueV4ui; // _VEC4
18547
18548		case 0x8b5e: // SAMPLER_2D
18549		case 0x8d66: // SAMPLER_EXTERNAL_OES
18550		case 0x8dca: // INT_SAMPLER_2D
18551		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
18552		case 0x8b62: // SAMPLER_2D_SHADOW
18553			return setValueT1;
18554
18555		case 0x8b5f: // SAMPLER_3D
18556		case 0x8dcb: // INT_SAMPLER_3D
18557		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
18558			return setValueT3D1;
18559
18560		case 0x8b60: // SAMPLER_CUBE
18561		case 0x8dcc: // INT_SAMPLER_CUBE
18562		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
18563		case 0x8dc5: // SAMPLER_CUBE_SHADOW
18564			return setValueT6;
18565
18566		case 0x8dc1: // SAMPLER_2D_ARRAY
18567		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
18568		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
18569		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
18570			return setValueT2DArray1;
18571
18572	}
18573
18574}
18575
18576
18577// Array of scalars
18578
18579function setValueV1fArray( gl, v ) {
18580
18581	gl.uniform1fv( this.addr, v );
18582
18583}
18584
18585// Array of vectors (from flat array or array of THREE.VectorN)
18586
18587function setValueV2fArray( gl, v ) {
18588
18589	const data = flatten( v, this.size, 2 );
18590
18591	gl.uniform2fv( this.addr, data );
18592
18593}
18594
18595function setValueV3fArray( gl, v ) {
18596
18597	const data = flatten( v, this.size, 3 );
18598
18599	gl.uniform3fv( this.addr, data );
18600
18601}
18602
18603function setValueV4fArray( gl, v ) {
18604
18605	const data = flatten( v, this.size, 4 );
18606
18607	gl.uniform4fv( this.addr, data );
18608
18609}
18610
18611// Array of matrices (from flat array or array of THREE.MatrixN)
18612
18613function setValueM2Array( gl, v ) {
18614
18615	const data = flatten( v, this.size, 4 );
18616
18617	gl.uniformMatrix2fv( this.addr, false, data );
18618
18619}
18620
18621function setValueM3Array( gl, v ) {
18622
18623	const data = flatten( v, this.size, 9 );
18624
18625	gl.uniformMatrix3fv( this.addr, false, data );
18626
18627}
18628
18629function setValueM4Array( gl, v ) {
18630
18631	const data = flatten( v, this.size, 16 );
18632
18633	gl.uniformMatrix4fv( this.addr, false, data );
18634
18635}
18636
18637// Array of integer / boolean
18638
18639function setValueV1iArray( gl, v ) {
18640
18641	gl.uniform1iv( this.addr, v );
18642
18643}
18644
18645// Array of integer / boolean vectors (from flat array)
18646
18647function setValueV2iArray( gl, v ) {
18648
18649	gl.uniform2iv( this.addr, v );
18650
18651}
18652
18653function setValueV3iArray( gl, v ) {
18654
18655	gl.uniform3iv( this.addr, v );
18656
18657}
18658
18659function setValueV4iArray( gl, v ) {
18660
18661	gl.uniform4iv( this.addr, v );
18662
18663}
18664
18665// Array of unsigned integer
18666
18667function setValueV1uiArray( gl, v ) {
18668
18669	gl.uniform1uiv( this.addr, v );
18670
18671}
18672
18673// Array of unsigned integer vectors (from flat array)
18674
18675function setValueV2uiArray( gl, v ) {
18676
18677	gl.uniform2uiv( this.addr, v );
18678
18679}
18680
18681function setValueV3uiArray( gl, v ) {
18682
18683	gl.uniform3uiv( this.addr, v );
18684
18685}
18686
18687function setValueV4uiArray( gl, v ) {
18688
18689	gl.uniform4uiv( this.addr, v );
18690
18691}
18692
18693
18694// Array of textures (2D / 3D / Cube / 2DArray)
18695
18696function setValueT1Array( gl, v, textures ) {
18697
18698	const cache = this.cache;
18699
18700	const n = v.length;
18701
18702	const units = allocTexUnits( textures, n );
18703
18704	if ( ! arraysEqual( cache, units ) ) {
18705
18706		gl.uniform1iv( this.addr, units );
18707
18708		copyArray( cache, units );
18709
18710	}
18711
18712	for ( let i = 0; i !== n; ++ i ) {
18713
18714		textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
18715
18716	}
18717
18718}
18719
18720function setValueT3DArray( gl, v, textures ) {
18721
18722	const cache = this.cache;
18723
18724	const n = v.length;
18725
18726	const units = allocTexUnits( textures, n );
18727
18728	if ( ! arraysEqual( cache, units ) ) {
18729
18730		gl.uniform1iv( this.addr, units );
18731
18732		copyArray( cache, units );
18733
18734	}
18735
18736	for ( let i = 0; i !== n; ++ i ) {
18737
18738		textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] );
18739
18740	}
18741
18742}
18743
18744function setValueT6Array( gl, v, textures ) {
18745
18746	const cache = this.cache;
18747
18748	const n = v.length;
18749
18750	const units = allocTexUnits( textures, n );
18751
18752	if ( ! arraysEqual( cache, units ) ) {
18753
18754		gl.uniform1iv( this.addr, units );
18755
18756		copyArray( cache, units );
18757
18758	}
18759
18760	for ( let i = 0; i !== n; ++ i ) {
18761
18762		textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
18763
18764	}
18765
18766}
18767
18768function setValueT2DArrayArray( gl, v, textures ) {
18769
18770	const cache = this.cache;
18771
18772	const n = v.length;
18773
18774	const units = allocTexUnits( textures, n );
18775
18776	if ( ! arraysEqual( cache, units ) ) {
18777
18778		gl.uniform1iv( this.addr, units );
18779
18780		copyArray( cache, units );
18781
18782	}
18783
18784	for ( let i = 0; i !== n; ++ i ) {
18785
18786		textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] );
18787
18788	}
18789
18790}
18791
18792
18793// Helper to pick the right setter for a pure (bottom-level) array
18794
18795function getPureArraySetter( type ) {
18796
18797	switch ( type ) {
18798
18799		case 0x1406: return setValueV1fArray; // FLOAT
18800		case 0x8b50: return setValueV2fArray; // _VEC2
18801		case 0x8b51: return setValueV3fArray; // _VEC3
18802		case 0x8b52: return setValueV4fArray; // _VEC4
18803
18804		case 0x8b5a: return setValueM2Array; // _MAT2
18805		case 0x8b5b: return setValueM3Array; // _MAT3
18806		case 0x8b5c: return setValueM4Array; // _MAT4
18807
18808		case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
18809		case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
18810		case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
18811		case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
18812
18813		case 0x1405: return setValueV1uiArray; // UINT
18814		case 0x8dc6: return setValueV2uiArray; // _VEC2
18815		case 0x8dc7: return setValueV3uiArray; // _VEC3
18816		case 0x8dc8: return setValueV4uiArray; // _VEC4
18817
18818		case 0x8b5e: // SAMPLER_2D
18819		case 0x8d66: // SAMPLER_EXTERNAL_OES
18820		case 0x8dca: // INT_SAMPLER_2D
18821		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
18822		case 0x8b62: // SAMPLER_2D_SHADOW
18823			return setValueT1Array;
18824
18825		case 0x8b5f: // SAMPLER_3D
18826		case 0x8dcb: // INT_SAMPLER_3D
18827		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
18828			return setValueT3DArray;
18829
18830		case 0x8b60: // SAMPLER_CUBE
18831		case 0x8dcc: // INT_SAMPLER_CUBE
18832		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
18833		case 0x8dc5: // SAMPLER_CUBE_SHADOW
18834			return setValueT6Array;
18835
18836		case 0x8dc1: // SAMPLER_2D_ARRAY
18837		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
18838		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
18839		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
18840			return setValueT2DArrayArray;
18841
18842	}
18843
18844}
18845
18846// --- Uniform Classes ---
18847
18848class SingleUniform {
18849
18850	constructor( id, activeInfo, addr ) {
18851
18852		this.id = id;
18853		this.addr = addr;
18854		this.cache = [];
18855		this.type = activeInfo.type;
18856		this.setValue = getSingularSetter( activeInfo.type );
18857
18858		// this.path = activeInfo.name; // DEBUG
18859
18860	}
18861
18862}
18863
18864class PureArrayUniform {
18865
18866	constructor( id, activeInfo, addr ) {
18867
18868		this.id = id;
18869		this.addr = addr;
18870		this.cache = [];
18871		this.type = activeInfo.type;
18872		this.size = activeInfo.size;
18873		this.setValue = getPureArraySetter( activeInfo.type );
18874
18875		// this.path = activeInfo.name; // DEBUG
18876
18877	}
18878
18879}
18880
18881class StructuredUniform {
18882
18883	constructor( id ) {
18884
18885		this.id = id;
18886
18887		this.seq = [];
18888		this.map = {};
18889
18890	}
18891
18892	setValue( gl, value, textures ) {
18893
18894		const seq = this.seq;
18895
18896		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
18897
18898			const u = seq[ i ];
18899			u.setValue( gl, value[ u.id ], textures );
18900
18901		}
18902
18903	}
18904
18905}
18906
18907// --- Top-level ---
18908
18909// Parser - builds up the property tree from the path strings
18910
18911const RePathPart = /(\w+)(\])?(\[|\.)?/g;
18912
18913// extracts
18914// 	- the identifier (member name or array index)
18915//  - followed by an optional right bracket (found when array index)
18916//  - followed by an optional left bracket or dot (type of subscript)
18917//
18918// Note: These portions can be read in a non-overlapping fashion and
18919// allow straightforward parsing of the hierarchy that WebGL encodes
18920// in the uniform names.
18921
18922function addUniform( container, uniformObject ) {
18923
18924	container.seq.push( uniformObject );
18925	container.map[ uniformObject.id ] = uniformObject;
18926
18927}
18928
18929function parseUniform( activeInfo, addr, container ) {
18930
18931	const path = activeInfo.name,
18932		pathLength = path.length;
18933
18934	// reset RegExp object, because of the early exit of a previous run
18935	RePathPart.lastIndex = 0;
18936
18937	while ( true ) {
18938
18939		const match = RePathPart.exec( path ),
18940			matchEnd = RePathPart.lastIndex;
18941
18942		let id = match[ 1 ];
18943		const idIsIndex = match[ 2 ] === ']',
18944			subscript = match[ 3 ];
18945
18946		if ( idIsIndex ) id = id | 0; // convert to integer
18947
18948		if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
18949
18950			// bare name or "pure" bottom-level array "[0]" suffix
18951
18952			addUniform( container, subscript === undefined ?
18953				new SingleUniform( id, activeInfo, addr ) :
18954				new PureArrayUniform( id, activeInfo, addr ) );
18955
18956			break;
18957
18958		} else {
18959
18960			// step into inner node / create it in case it doesn't exist
18961
18962			const map = container.map;
18963			let next = map[ id ];
18964
18965			if ( next === undefined ) {
18966
18967				next = new StructuredUniform( id );
18968				addUniform( container, next );
18969
18970			}
18971
18972			container = next;
18973
18974		}
18975
18976	}
18977
18978}
18979
18980// Root Container
18981
18982class WebGLUniforms {
18983
18984	constructor( gl, program ) {
18985
18986		this.seq = [];
18987		this.map = {};
18988
18989		const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
18990
18991		for ( let i = 0; i < n; ++ i ) {
18992
18993			const info = gl.getActiveUniform( program, i ),
18994				addr = gl.getUniformLocation( program, info.name );
18995
18996			parseUniform( info, addr, this );
18997
18998		}
18999
19000	}
19001
19002	setValue( gl, name, value, textures ) {
19003
19004		const u = this.map[ name ];
19005
19006		if ( u !== undefined ) u.setValue( gl, value, textures );
19007
19008	}
19009
19010	setOptional( gl, object, name ) {
19011
19012		const v = object[ name ];
19013
19014		if ( v !== undefined ) this.setValue( gl, name, v );
19015
19016	}
19017
19018	static upload( gl, seq, values, textures ) {
19019
19020		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
19021
19022			const u = seq[ i ],
19023				v = values[ u.id ];
19024
19025			if ( v.needsUpdate !== false ) {
19026
19027				// note: always updating when .needsUpdate is undefined
19028				u.setValue( gl, v.value, textures );
19029
19030			}
19031
19032		}
19033
19034	}
19035
19036	static seqWithValue( seq, values ) {
19037
19038		const r = [];
19039
19040		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
19041
19042			const u = seq[ i ];
19043			if ( u.id in values ) r.push( u );
19044
19045		}
19046
19047		return r;
19048
19049	}
19050
19051}
19052
19053function WebGLShader( gl, type, string ) {
19054
19055	const shader = gl.createShader( type );
19056
19057	gl.shaderSource( shader, string );
19058	gl.compileShader( shader );
19059
19060	return shader;
19061
19062}
19063
19064// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/
19065const COMPLETION_STATUS_KHR = 0x91B1;
19066
19067let programIdCount = 0;
19068
19069function handleSource( string, errorLine ) {
19070
19071	const lines = string.split( '\n' );
19072	const lines2 = [];
19073
19074	const from = Math.max( errorLine - 6, 0 );
19075	const to = Math.min( errorLine + 6, lines.length );
19076
19077	for ( let i = from; i < to; i ++ ) {
19078
19079		const line = i + 1;
19080		lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` );
19081
19082	}
19083
19084	return lines2.join( '\n' );
19085
19086}
19087
19088function getEncodingComponents( colorSpace ) {
19089
19090	const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
19091	const encodingPrimaries = ColorManagement.getPrimaries( colorSpace );
19092
19093	let gamutMapping;
19094
19095	if ( workingPrimaries === encodingPrimaries ) {
19096
19097		gamutMapping = '';
19098
19099	} else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) {
19100
19101		gamutMapping = 'LinearDisplayP3ToLinearSRGB';
19102
19103	} else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) {
19104
19105		gamutMapping = 'LinearSRGBToLinearDisplayP3';
19106
19107	}
19108
19109	switch ( colorSpace ) {
19110
19111		case LinearSRGBColorSpace:
19112		case LinearDisplayP3ColorSpace:
19113			return [ gamutMapping, 'LinearTransferOETF' ];
19114
19115		case SRGBColorSpace:
19116		case DisplayP3ColorSpace:
19117			return [ gamutMapping, 'sRGBTransferOETF' ];
19118
19119		default:
19120			console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace );
19121			return [ gamutMapping, 'LinearTransferOETF' ];
19122
19123	}
19124
19125}
19126
19127function getShaderErrors( gl, shader, type ) {
19128
19129	const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS );
19130	const errors = gl.getShaderInfoLog( shader ).trim();
19131
19132	if ( status && errors === '' ) return '';
19133
19134	const errorMatches = /ERROR: 0:(\d+)/.exec( errors );
19135	if ( errorMatches ) {
19136
19137		// --enable-privileged-webgl-extension
19138		// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
19139
19140		const errorLine = parseInt( errorMatches[ 1 ] );
19141		return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine );
19142
19143	} else {
19144
19145		return errors;
19146
19147	}
19148
19149}
19150
19151function getTexelEncodingFunction( functionName, colorSpace ) {
19152
19153	const components = getEncodingComponents( colorSpace );
19154	return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`;
19155
19156}
19157
19158function getToneMappingFunction( functionName, toneMapping ) {
19159
19160	let toneMappingName;
19161
19162	switch ( toneMapping ) {
19163
19164		case LinearToneMapping:
19165			toneMappingName = 'Linear';
19166			break;
19167
19168		case ReinhardToneMapping:
19169			toneMappingName = 'Reinhard';
19170			break;
19171
19172		case CineonToneMapping:
19173			toneMappingName = 'OptimizedCineon';
19174			break;
19175
19176		case ACESFilmicToneMapping:
19177			toneMappingName = 'ACESFilmic';
19178			break;
19179
19180		case AgXToneMapping:
19181			toneMappingName = 'AgX';
19182			break;
19183
19184		case NeutralToneMapping:
19185			toneMappingName = 'Neutral';
19186			break;
19187
19188		case CustomToneMapping:
19189			toneMappingName = 'Custom';
19190			break;
19191
19192		default:
19193			console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
19194			toneMappingName = 'Linear';
19195
19196	}
19197
19198	return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
19199
19200}
19201
19202function generate
19202VertexExtensions( parameters ) {
19203
19204	const chunks = [
vendor: 7,293 bytes, lines 19205-19516
19205		parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '',
19206		parameters.extensionMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '',
19207	];
19208
19209	return chunks.filter( filterEmptyLine ).join( '\n' );
19210
19211}
19212
19213function generateDefines( defines ) {
19214
19215	const chunks = [];
19216
19217	for ( const name in defines ) {
19218
19219		const value = defines[ name ];
19220
19221		if ( value === false ) continue;
19222
19223		chunks.push( '#define ' + name + ' ' + value );
19224
19225	}
19226
19227	return chunks.join( '\n' );
19228
19229}
19230
19231function fetchAttributeLocations( gl, program ) {
19232
19233	const attributes = {};
19234
19235	const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
19236
19237	for ( let i = 0; i < n; i ++ ) {
19238
19239		const info = gl.getActiveAttrib( program, i );
19240		const name = info.name;
19241
19242		let locationSize = 1;
19243		if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2;
19244		if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3;
19245		if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4;
19246
19247		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
19248
19249		attributes[ name ] = {
19250			type: info.type,
19251			location: gl.getAttribLocation( program, name ),
19252			locationSize: locationSize
19253		};
19254
19255	}
19256
19257	return attributes;
19258
19259}
19260
19261function filterEmptyLine( string ) {
19262
19263	return string !== '';
19264
19265}
19266
19267function replaceLightNums( string, parameters ) {
19268
19269	const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps;
19270
19271	return string
19272		.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
19273		.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
19274		.replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps )
19275		.replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords )
19276		.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
19277		.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
19278		.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
19279		.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
19280		.replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps )
19281		.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
19282		.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
19283
19284}
19285
19286function replaceClippingPlaneNums( string, parameters ) {
19287
19288	return string
19289		.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
19290		.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
19291
19292}
19293
19294// Resolve Includes
19295
19296const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
19297
19298function resolveIncludes( string ) {
19299
19300	return string.replace( includePattern, includeReplacer );
19301
19302}
19303
19304const shaderChunkMap = new Map( [
19305	[ 'encodings_fragment', 'colorspace_fragment' ], // @deprecated, r154
19306	[ 'encodings_pars_fragment', 'colorspace_pars_fragment' ], // @deprecated, r154
19307	[ 'output_fragment', 'opaque_fragment' ], // @deprecated, r154
19308] );
19309
19310function includeReplacer( match, include ) {
19311
19312	let string = ShaderChunk[ include ];
19313
19314	if ( string === undefined ) {
19315
19316		const newInclude = shaderChunkMap.get( include );
19317
19318		if ( newInclude !== undefined ) {
19319
19320			string = ShaderChunk[ newInclude ];
19321			console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude );
19322
19323		} else {
19324
19325			throw new Error( 'Can not resolve #include <' + include + '>' );
19326
19327		}
19328
19329	}
19330
19331	return resolveIncludes( string );
19332
19333}
19334
19335// Unroll Loops
19336
19337const 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;
19338
19339function unrollLoops( string ) {
19340
19341	return string.replace( unrollLoopPattern, loopReplacer );
19342
19343}
19344
19345function loopReplacer( match, start, end, snippet ) {
19346
19347	let string = '';
19348
19349	for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
19350
19351		string += snippet
19352			.replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
19353			.replace( /UNROLLED_LOOP_INDEX/g, i );
19354
19355	}
19356
19357	return string;
19358
19359}
19360
19361//
19362
19363function generatePrecision( parameters ) {
19364
19365	let precisionstring = `precision ${parameters.precision} float;
19366	precision ${parameters.precision} int;
19367	precision ${parameters.precision} sampler2D;
19368	precision ${parameters.precision} samplerCube;
19369	precision ${parameters.precision} sampler3D;
19370	precision ${parameters.precision} sampler2DArray;
19371	precision ${parameters.precision} sampler2DShadow;
19372	precision ${parameters.precision} samplerCubeShadow;
19373	precision ${parameters.precision} sampler2DArrayShadow;
19374	precision ${parameters.precision} isampler2D;
19375	precision ${parameters.precision} isampler3D;
19376	precision ${parameters.precision} isamplerCube;
19377	precision ${parameters.precision} isampler2DArray;
19378	precision ${parameters.precision} usampler2D;
19379	precision ${parameters.precision} usampler3D;
19380	precision ${parameters.precision} usamplerCube;
19381	precision ${parameters.precision} usampler2DArray;
19382	`;
19383
19384	if ( parameters.precision === 'highp' ) {
19385
19386		precisionstring += '\n#define HIGH_PRECISION';
19387
19388	} else if ( parameters.precision === 'mediump' ) {
19389
19390		precisionstring += '\n#define MEDIUM_PRECISION';
19391
19392	} else if ( parameters.precision === 'lowp' ) {
19393
19394		precisionstring += '\n#define LOW_PRECISION';
19395
19396	}
19397
19398	return precisionstring;
19399
19400}
19401
19402function generateShadowMapTypeDefine( parameters ) {
19403
19404	let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
19405
19406	if ( parameters.shadowMapType === PCFShadowMap ) {
19407
19408		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
19409
19410	} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
19411
19412		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
19413
19414	} else if ( parameters.shadowMapType === VSMShadowMap ) {
19415
19416		shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
19417
19418	}
19419
19420	return shadowMapTypeDefine;
19421
19422}
19423
19424function generateEnvMapTypeDefine( parameters ) {
19425
19426	let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
19427
19428	if ( parameters.envMap ) {
19429
19430		switch ( parameters.envMapMode ) {
19431
19432			case CubeReflectionMapping:
19433			case CubeRefractionMapping:
19434				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
19435				break;
19436
19437			case CubeUVReflectionMapping:
19438				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
19439				break;
19440
19441		}
19442
19443	}
19444
19445	return envMapTypeDefine;
19446
19447}
19448
19449function generateEnvMapModeDefine( parameters ) {
19450
19451	let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
19452
19453	if ( parameters.envMap ) {
19454
19455		switch ( parameters.envMapMode ) {
19456
19457			case CubeRefractionMapping:
19458
19459				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
19460				break;
19461
19462		}
19463
19464	}
19465
19466	return envMapModeDefine;
19467
19468}
19469
19470function generateEnvMapBlendingDefine( parameters ) {
19471
19472	let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
19473
19474	if ( parameters.envMap ) {
19475
19476		switch ( parameters.combine ) {
19477
19478			case MultiplyOperation:
19479				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
19480				break;
19481
19482			case MixOperation:
19483				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
19484				break;
19485
19486			case AddOperation:
19487				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
19488				break;
19489
19490		}
19491
19492	}
19493
19494	return envMapBlendingDefine;
19495
19496}
19497
19498function generateCubeUVSize( parameters ) {
19499
19500	const imageHeight = parameters.envMapCubeUVHeight;
19501
19502	if ( imageHeight === null ) return null;
19503
19504	const maxMip = Math.log2( imageHeight ) - 2;
19505
19506	const texelHeight = 1.0 / imageHeight;
19507
19508	const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) );
19509
19510	return { texelWidth, texelHeight, maxMip };
19511
19512}
19513
19514function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
19515
19516	// TODO Send this event to Three.js DevTools
vendor: 15,382 bytes, lines 19517-19935
19517	// console.log( 'WebGLProgram', cacheKey );
19518
19519	const gl = renderer.getContext();
19520
19521	const defines = parameters.defines;
19522
19523	let vertexShader = parameters.vertexShader;
19524	let fragmentShader = parameters.fragmentShader;
19525
19526	const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
19527	const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
19528	const envMapModeDefine = generateEnvMapModeDefine( parameters );
19529	const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
19530	const envMapCubeUVSize = generateCubeUVSize( parameters );
19531
19532	const customVertexExtensions = generateVertexExtensions( parameters );
19533
19534	const customDefines = generateDefines( defines );
19535
19536	const program = gl.createProgram();
19537
19538	let prefixVertex, prefixFragment;
19539	let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
19540
19541	if ( parameters.isRawShaderMaterial ) {
19542
19543		prefixVertex = [
19544
19545			'#define SHADER_TYPE ' + parameters.shaderType,
19546			'#define SHADER_NAME ' + parameters.shaderName,
19547
19548			customDefines
19549
19550		].filter( filterEmptyLine ).join( '\n' );
19551
19552		if ( prefixVertex.length > 0 ) {
19553
19554			prefixVertex += '\n';
19555
19556		}
19557
19558		prefixFragment = [
19559
19560			'#define SHADER_TYPE ' + parameters.shaderType,
19561			'#define SHADER_NAME ' + parameters.shaderName,
19562
19563			customDefines
19564
19565		].filter( filterEmptyLine ).join( '\n' );
19566
19567		if ( prefixFragment.length > 0 ) {
19568
19569			prefixFragment += '\n';
19570
19571		}
19572
19573	} else {
19574
19575		prefixVertex = [
19576
19577			generatePrecision( parameters ),
19578
19579			'#define SHADER_TYPE ' + parameters.shaderType,
19580			'#define SHADER_NAME ' + parameters.shaderName,
19581
19582			customDefines,
19583
19584			parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '',
19585			parameters.batching ? '#define USE_BATCHING' : '',
19586			parameters.instancing ? '#define USE_INSTANCING' : '',
19587			parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
19588			parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '',
19589
19590			parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
19591			parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
19592
19593			parameters.map ? '#define USE_MAP' : '',
19594			parameters.envMap ? '#define USE_ENVMAP' : '',
19595			parameters.envMap ? '#define ' + envMapModeDefine : '',
19596			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
19597			parameters.aoMap ? '#define USE_AOMAP' : '',
19598			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
19599			parameters.normalMap ? '#define USE_NORMALMAP' : '',
19600			parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '',
19601			parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '',
19602			parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '',
19603			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
19604
19605			parameters.anisotropy ? '#define USE_ANISOTROPY' : '',
19606			parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '',
19607
19608			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
19609			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
19610			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
19611
19612			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
19613			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
19614
19615			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
19616			parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '',
19617			parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '',
19618
19619			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
19620			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
19621			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
19622			parameters.alphaHash ? '#define USE_ALPHAHASH' : '',
19623
19624			parameters.transmission ? '#define USE_TRANSMISSION' : '',
19625			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
19626			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
19627
19628			parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '',
19629			parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '',
19630
19631			//
19632
19633			parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '',
19634			parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '',
19635			parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '',
19636			parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '',
19637			parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '',
19638			parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '',
19639			parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '',
19640			parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '',
19641
19642			parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '',
19643			parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '',
19644
19645			parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '',
19646
19647			parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '',
19648			parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '',
19649			parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '',
19650
19651			parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '',
19652			parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '',
19653
19654			parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '',
19655			parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '',
19656
19657			parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '',
19658			parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '',
19659			parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '',
19660
19661			parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '',
19662			parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '',
19663
19664			//
19665
19666			parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
19667			parameters.vertexColors ? '#define USE_COLOR' : '',
19668			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
19669			parameters.vertexUv1s ? '#define USE_UV1' : '',
19670			parameters.vertexUv2s ? '#define USE_UV2' : '',
19671			parameters.vertexUv3s ? '#define USE_UV3' : '',
19672
19673			parameters.pointsUvs ? '#define USE_POINTS_UV' : '',
19674
19675			parameters.flatShading ? '#define FLAT_SHADED' : '',
19676
19677			parameters.skinning ? '#define USE_SKINNING' : '',
19678
19679			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
19680			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
19681			( parameters.morphColors ) ? '#define USE_MORPHCOLORS' : '',
19682			( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE' : '',
19683			( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '',
19684			( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '',
19685			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
19686			parameters.flipSided ? '#define FLIP_SIDED' : '',
19687
19688			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
19689			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
19690
19691			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
19692
19693			parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
19694
19695			parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '',
19696
19697			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
19698
19699			'uniform mat4 modelMatrix;',
19700			'uniform mat4 modelViewMatrix;',
19701			'uniform mat4 projectionMatrix;',
19702			'uniform mat4 viewMatrix;',
19703			'uniform mat3 normalMatrix;',
19704			'uniform vec3 cameraPosition;',
19705			'uniform bool isOrthographic;',
19706
19707			'#ifdef USE_INSTANCING',
19708
19709			'	attribute mat4 instanceMatrix;',
19710
19711			'#endif',
19712
19713			'#ifdef USE_INSTANCING_COLOR',
19714
19715			'	attribute vec3 instanceColor;',
19716
19717			'#endif',
19718
19719			'#ifdef USE_INSTANCING_MORPH',
19720
19721			'	uniform sampler2D morphTexture;',
19722
19723			'#endif',
19724
19725			'attribute vec3 position;',
19726			'attribute vec3 normal;',
19727			'attribute vec2 uv;',
19728
19729			'#ifdef USE_UV1',
19730
19731			'	attribute vec2 uv1;',
19732
19733			'#endif',
19734
19735			'#ifdef USE_UV2',
19736
19737			'	attribute vec2 uv2;',
19738
19739			'#endif',
19740
19741			'#ifdef USE_UV3',
19742
19743			'	attribute vec2 uv3;',
19744
19745			'#endif',
19746
19747			'#ifdef USE_TANGENT',
19748
19749			'	attribute vec4 tangent;',
19750
19751			'#endif',
19752
19753			'#if defined( USE_COLOR_ALPHA )',
19754
19755			'	attribute vec4 color;',
19756
19757			'#elif defined( USE_COLOR )',
19758
19759			'	attribute vec3 color;',
19760
19761			'#endif',
19762
19763			'#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )',
19764
19765			'	attribute vec3 morphTarget0;',
19766			'	attribute vec3 morphTarget1;',
19767			'	attribute vec3 morphTarget2;',
19768			'	attribute vec3 morphTarget3;',
19769
19770			'	#ifdef USE_MORPHNORMALS',
19771
19772			'		attribute vec3 morphNormal0;',
19773			'		attribute vec3 morphNormal1;',
19774			'		attribute vec3 morphNormal2;',
19775			'		attribute vec3 morphNormal3;',
19776
19777			'	#else',
19778
19779			'		attribute vec3 morphTarget4;',
19780			'		attribute vec3 morphTarget5;',
19781			'		attribute vec3 morphTarget6;',
19782			'		attribute vec3 morphTarget7;',
19783
19784			'	#endif',
19785
19786			'#endif',
19787
19788			'#ifdef USE_SKINNING',
19789
19790			'	attribute vec4 skinIndex;',
19791			'	attribute vec4 skinWeight;',
19792
19793			'#endif',
19794
19795			'\n'
19796
19797		].filter( filterEmptyLine ).join( '\n' );
19798
19799		prefixFragment = [
19800
19801			generatePrecision( parameters ),
19802
19803			'#define SHADER_TYPE ' + parameters.shaderType,
19804			'#define SHADER_NAME ' + parameters.shaderName,
19805
19806			customDefines,
19807
19808			parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
19809			parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
19810
19811			parameters.alphaToCoverage ? '#define ALPHA_TO_COVERAGE' : '',
19812			parameters.map ? '#define USE_MAP' : '',
19813			parameters.matcap ? '#define USE_MATCAP' : '',
19814			parameters.envMap ? '#define USE_ENVMAP' : '',
19815			parameters.envMap ? '#define ' + envMapTypeDefine : '',
19816			parameters.envMap ? '#define ' + envMapModeDefine : '',
19817			parameters.envMap ? '#define ' + envMapBlendingDefine : '',
19818			envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '',
19819			envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '',
19820			envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '',
19821			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
19822			parameters.aoMap ? '#define USE_AOMAP' : '',
19823			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
19824			parameters.normalMap ? '#define USE_NORMALMAP' : '',
19825			parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '',
19826			parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '',
19827			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
19828
19829			parameters.anisotropy ? '#define USE_ANISOTROPY' : '',
19830			parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '',
19831
19832			parameters.clearcoat ? '#define USE_CLEARCOAT' : '',
19833			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
19834			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
19835			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
19836
19837			parameters.iridescence ? '#define USE_IRIDESCENCE' : '',
19838			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
19839			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
19840
19841			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
19842			parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '',
19843			parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '',
19844
19845			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
19846			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
19847
19848			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
19849			parameters.alphaTest ? '#define USE_ALPHATEST' : '',
19850			parameters.alphaHash ? '#define USE_ALPHAHASH' : '',
19851
19852			parameters.sheen ? '#define USE_SHEEN' : '',
19853			parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '',
19854			parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '',
19855
19856			parameters.transmission ? '#define USE_TRANSMISSION' : '',
19857			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
19858			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
19859
19860			parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
19861			parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
19862			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
19863			parameters.vertexUv1s ? '#define USE_UV1' : '',
19864			parameters.vertexUv2s ? '#define USE_UV2' : '',
19865			parameters.vertexUv3s ? '#define USE_UV3' : '',
19866
19867			parameters.pointsUvs ? '#define USE_POINTS_UV' : '',
19868
19869			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
19870
19871			parameters.flatShading ? '#define FLAT_SHADED' : '',
19872
19873			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
19874			parameters.flipSided ? '#define FLIP_SIDED' : '',
19875
19876			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
19877			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
19878
19879			parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
19880
19881			parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
19882
19883			parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '',
19884
19885			parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '',
19886
19887			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
19888
19889			'uniform mat4 viewMatrix;',
19890			'uniform vec3 cameraPosition;',
19891			'uniform bool isOrthographic;',
19892
19893			( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
19894			( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
19895			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
19896
19897			parameters.dithering ? '#define DITHERING' : '',
19898			parameters.opaque ? '#define OPAQUE' : '',
19899
19900			ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
19901			getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ),
19902
19903			parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
19904
19905			'\n'
19906
19907		].filter( filterEmptyLine ).join( '\n' );
19908
19909	}
19910
19911	vertexShader = resolveIncludes( vertexShader );
19912	vertexShader = replaceLightNums( vertexShader, parameters );
19913	vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
19914
19915	fragmentShader = resolveIncludes( fragmentShader );
19916	fragmentShader = replaceLightNums( fragmentShader, parameters );
19917	fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
19918
19919	vertexShader = unrollLoops( vertexShader );
19920	fragmentShader = unrollLoops( fragmentShader );
19921
19922	if ( parameters.isRawShaderMaterial !== true ) {
19923
19924		// GLSL 3.0 conversion for built-in materials and ShaderMaterial
19925
19926		versionString = '#version 300 es\n';
19927
19928		prefixVertex = [
19929			customVertexExtensions,
19930			'#define attribute in',
19931			'#define varying out',
19932			'#define texture2D texture'
19933		].join( '\n' ) + '\n' + prefixVertex;
19934
19935		prefixFragment = [
vendor: 7,213 bytes, lines 19935-20278
19935
19936			'#define varying in',
19937			( parameters.glslVersion === GLSL3 ) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;',
19938			( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
19939			'#define gl_FragDepthEXT gl_FragDepth',
19940			'#define texture2D texture',
19941			'#define textureCube texture',
19942			'#define texture2DProj textureProj',
19943			'#define texture2DLodEXT textureLod',
19944			'#define texture2DProjLodEXT textureProjLod',
19945			'#define textureCubeLodEXT textureLod',
19946			'#define texture2DGradEXT textureGrad',
19947			'#define texture2DProjGradEXT textureProjGrad',
19948			'#define textureCubeGradEXT textureGrad'
19949		].join( '\n' ) + '\n' + prefixFragment;
19950
19951	}
19952
19953	const vertexGlsl = versionString + prefixVertex + vertexShader;
19954	const fragmentGlsl = versionString + prefixFragment + fragmentShader;
19955
19956	// console.log( '*VERTEX*', vertexGlsl );
19957	// console.log( '*FRAGMENT*', fragmentGlsl );
19958
19959	const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
19960	const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
19961
19962	gl.attachShader( program, glVertexShader );
19963	gl.attachShader( program, glFragmentShader );
19964
19965	// Force a particular attribute to index 0.
19966
19967	if ( parameters.index0AttributeName !== undefined ) {
19968
19969		gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
19970
19971	} else if ( parameters.morphTargets === true ) {
19972
19973		// programs with morphTargets displace position out of attribute 0
19974		gl.bindAttribLocation( program, 0, 'position' );
19975
19976	}
19977
19978	gl.linkProgram( program );
19979
19980	function onFirstUse( self ) {
19981
19982		// check for link errors
19983		if ( renderer.debug.checkShaderErrors ) {
19984
19985			const programLog = gl.getProgramInfoLog( program ).trim();
19986			const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
19987			const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
19988
19989			let runnable = true;
19990			let haveDiagnostics = true;
19991
19992			if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
19993
19994				runnable = false;
19995
19996				if ( typeof renderer.debug.onShaderError === 'function' ) {
19997
19998					renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
19999
20000				} else {
20001
20002					// default error reporting
20003
20004					const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
20005					const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
20006
20007					console.error(
20008						'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
20009						'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
20010						'Material Name: ' + self.name + '\n' +
20011						'Material Type: ' + self.type + '\n\n' +
20012						'Program Info Log: ' + programLog + '\n' +
20013						vertexErrors + '\n' +
20014						fragmentErrors
20015					);
20016
20017				}
20018
20019			} else if ( programLog !== '' ) {
20020
20021				console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
20022
20023			} else if ( vertexLog === '' || fragmentLog === '' ) {
20024
20025				haveDiagnostics = false;
20026
20027			}
20028
20029			if ( haveDiagnostics ) {
20030
20031				self.diagnostics = {
20032
20033					runnable: runnable,
20034
20035					programLog: programLog,
20036
20037					vertexShader: {
20038
20039						log: vertexLog,
20040						prefix: prefixVertex
20041
20042					},
20043
20044					fragmentShader: {
20045
20046						log: fragmentLog,
20047						prefix: prefixFragment
20048
20049					}
20050
20051				};
20052
20053			}
20054
20055		}
20056
20057		// Clean up
20058
20059		// Crashes in iOS9 and iOS10. #18402
20060		// gl.detachShader( program, glVertexShader );
20061		// gl.detachShader( program, glFragmentShader );
20062
20063		gl.deleteShader( glVertexShader );
20064		gl.deleteShader( glFragmentShader );
20065
20066		cachedUniforms = new WebGLUniforms( gl, program );
20067		cachedAttributes = fetchAttributeLocations( gl, program );
20068
20069	}
20070
20071	// set up caching for uniform locations
20072
20073	let cachedUniforms;
20074
20075	this.getUniforms = function () {
20076
20077		if ( cachedUniforms === undefined ) {
20078
20079			// Populates cachedUniforms and cachedAttributes
20080			onFirstUse( this );
20081
20082		}
20083
20084		return cachedUniforms;
20085
20086	};
20087
20088	// set up caching for attribute locations
20089
20090	let cachedAttributes;
20091
20092	this.getAttributes = function () {
20093
20094		if ( cachedAttributes === undefined ) {
20095
20096			// Populates cachedAttributes and cachedUniforms
20097			onFirstUse( this );
20098
20099		}
20100
20101		return cachedAttributes;
20102
20103	};
20104
20105	// indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported,
20106	// flag the program as ready immediately. It may cause a stall when it's first used.
20107
20108	let programReady = ( parameters.rendererExtensionParallelShaderCompile === false );
20109
20110	this.isReady = function () {
20111
20112		if ( programReady === false ) {
20113
20114			programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR );
20115
20116		}
20117
20118		return programReady;
20119
20120	};
20121
20122	// free resource
20123
20124	this.destroy = function () {
20125
20126		bindingStates.releaseStatesOfProgram( this );
20127
20128		gl.deleteProgram( program );
20129		this.program = undefined;
20130
20131	};
20132
20133	//
20134
20135	this.type = parameters.shaderType;
20136	this.name = parameters.shaderName;
20137	this.id = programIdCount ++;
20138	this.cacheKey = cacheKey;
20139	this.usedTimes = 1;
20140	this.program = program;
20141	this.vertexShader = glVertexShader;
20142	this.fragmentShader = glFragmentShader;
20143
20144	return this;
20145
20146}
20147
20148let _id$1 = 0;
20149
20150class WebGLShaderCache {
20151
20152	constructor() {
20153
20154		this.shaderCache = new Map();
20155		this.materialCache = new Map();
20156
20157	}
20158
20159	update( material ) {
20160
20161		const vertexShader = material.vertexShader;
20162		const fragmentShader = material.fragmentShader;
20163
20164		const vertexShaderStage = this._getShaderStage( vertexShader );
20165		const fragmentShaderStage = this._getShaderStage( fragmentShader );
20166
20167		const materialShaders = this._getShaderCacheForMaterial( material );
20168
20169		if ( materialShaders.has( vertexShaderStage ) === false ) {
20170
20171			materialShaders.add( vertexShaderStage );
20172			vertexShaderStage.usedTimes ++;
20173
20174		}
20175
20176		if ( materialShaders.has( fragmentShaderStage ) === false ) {
20177
20178			materialShaders.add( fragmentShaderStage );
20179			fragmentShaderStage.usedTimes ++;
20180
20181		}
20182
20183		return this;
20184
20185	}
20186
20187	remove( material ) {
20188
20189		const materialShaders = this.materialCache.get( material );
20190
20191		for ( const shaderStage of materialShaders ) {
20192
20193			shaderStage.usedTimes --;
20194
20195			if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code );
20196
20197		}
20198
20199		this.materialCache.delete( material );
20200
20201		return this;
20202
20203	}
20204
20205	getVertexShaderID( material ) {
20206
20207		return this._getShaderStage( material.vertexShader ).id;
20208
20209	}
20210
20211	getFragmentShaderID( material ) {
20212
20213		return this._getShaderStage( material.fragmentShader ).id;
20214
20215	}
20216
20217	dispose() {
20218
20219		this.shaderCache.clear();
20220		this.materialCache.clear();
20221
20222	}
20223
20224	_getShaderCacheForMaterial( material ) {
20225
20226		const cache = this.materialCache;
20227		let set = cache.get( material );
20228
20229		if ( set === undefined ) {
20230
20231			set = new Set();
20232			cache.set( material, set );
20233
20234		}
20235
20236		return set;
20237
20238	}
20239
20240	_getShaderStage( code ) {
20241
20242		const cache = this.shaderCache;
20243		let stage = cache.get( code );
20244
20245		if ( stage === undefined ) {
20246
20247			stage = new WebGLShaderStage( code );
20248			cache.set( code, stage );
20249
20250		}
20251
20252		return stage;
20253
20254	}
20255
20256}
20257
20258class WebGLShaderStage {
20259
20260	constructor( code ) {
20261
20262		this.id = _id$1 ++;
20263
20264		this.code = code;
20265		this.usedTimes = 0;
20266
20267	}
20268
20269}
20270
20271function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) {
20272
20273	const _programLayers = new Layers();
20274	const _customShaders = new WebGLShaderCache();
20275	const _activeChannels = new Set();
20276	const programs = [];
20277
20278	const 
vendor: 19,894 bytes, lines 20278-20908
20278logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
20279	const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures;
20280
20281	let precision = capabilities.precision;
20282
20283	const shaderIDs = {
20284		MeshDepthMaterial: 'depth',
20285		MeshDistanceMaterial: 'distanceRGBA',
20286		MeshNormalMaterial: 'normal',
20287		MeshBasicMaterial: 'basic',
20288		MeshLambertMaterial: 'lambert',
20289		MeshPhongMaterial: 'phong',
20290		MeshToonMaterial: 'toon',
20291		MeshStandardMaterial: 'physical',
20292		MeshPhysicalMaterial: 'physical',
20293		MeshMatcapMaterial: 'matcap',
20294		LineBasicMaterial: 'basic',
20295		LineDashedMaterial: 'dashed',
20296		PointsMaterial: 'points',
20297		ShadowMaterial: 'shadow',
20298		SpriteMaterial: 'sprite'
20299	};
20300
20301	function getChannel( value ) {
20302
20303		_activeChannels.add( value );
20304
20305		if ( value === 0 ) return 'uv';
20306
20307		return `uv${ value }`;
20308
20309	}
20310
20311	function getParameters( material, lights, shadows, scene, object ) {
20312
20313		const fog = scene.fog;
20314		const geometry = object.geometry;
20315		const environment = material.isMeshStandardMaterial ? scene.environment : null;
20316
20317		const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
20318		const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null;
20319
20320		const shaderID = shaderIDs[ material.type ];
20321
20322		// heuristics to create shader parameters according to lights in the scene
20323		// (not to blow over maxLights budget)
20324
20325		if ( material.precision !== null ) {
20326
20327			precision = capabilities.getMaxPrecision( material.precision );
20328
20329			if ( precision !== material.precision ) {
20330
20331				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
20332
20333			}
20334
20335		}
20336
20337		//
20338
20339		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
20340		const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
20341
20342		let morphTextureStride = 0;
20343
20344		if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1;
20345		if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2;
20346		if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3;
20347
20348		//
20349
20350		let vertexShader, fragmentShader;
20351		let customVertexShaderID, customFragmentShaderID;
20352
20353		if ( shaderID ) {
20354
20355			const shader = ShaderLib[ shaderID ];
20356
20357			vertexShader = shader.vertexShader;
20358			fragmentShader = shader.fragmentShader;
20359
20360		} else {
20361
20362			vertexShader = material.vertexShader;
20363			fragmentShader = material.fragmentShader;
20364
20365			_customShaders.update( material );
20366
20367			customVertexShaderID = _customShaders.getVertexShaderID( material );
20368			customFragmentShaderID = _customShaders.getFragmentShaderID( material );
20369
20370		}
20371
20372		const currentRenderTarget = renderer.getRenderTarget();
20373
20374		const IS_INSTANCEDMESH = object.isInstancedMesh === true;
20375		const IS_BATCHEDMESH = object.isBatchedMesh === true;
20376
20377		const HAS_MAP = !! material.map;
20378		const HAS_MATCAP = !! material.matcap;
20379		const HAS_ENVMAP = !! envMap;
20380		const HAS_AOMAP = !! material.aoMap;
20381		const HAS_LIGHTMAP = !! material.lightMap;
20382		const HAS_BUMPMAP = !! material.bumpMap;
20383		const HAS_NORMALMAP = !! material.normalMap;
20384		const HAS_DISPLACEMENTMAP = !! material.displacementMap;
20385		const HAS_EMISSIVEMAP = !! material.emissiveMap;
20386
20387		const HAS_METALNESSMAP = !! material.metalnessMap;
20388		const HAS_ROUGHNESSMAP = !! material.roughnessMap;
20389
20390		const HAS_ANISOTROPY = material.anisotropy > 0;
20391		const HAS_CLEARCOAT = material.clearcoat > 0;
20392		const HAS_IRIDESCENCE = material.iridescence > 0;
20393		const HAS_SHEEN = material.sheen > 0;
20394		const HAS_TRANSMISSION = material.transmission > 0;
20395
20396		const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap;
20397
20398		const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap;
20399		const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap;
20400		const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap;
20401
20402		const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap;
20403		const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap;
20404
20405		const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap;
20406		const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap;
20407
20408		const HAS_SPECULARMAP = !! material.specularMap;
20409		const HAS_SPECULAR_COLORMAP = !! material.specularColorMap;
20410		const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap;
20411
20412		const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap;
20413		const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap;
20414
20415		const HAS_GRADIENTMAP = !! material.gradientMap;
20416
20417		const HAS_ALPHAMAP = !! material.alphaMap;
20418
20419		const HAS_ALPHATEST = material.alphaTest > 0;
20420
20421		const HAS_ALPHAHASH = !! material.alphaHash;
20422
20423		const HAS_EXTENSIONS = !! material.extensions;
20424
20425		let toneMapping = NoToneMapping;
20426
20427		if ( material.toneMapped ) {
20428
20429			if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) {
20430
20431				toneMapping = renderer.toneMapping;
20432
20433			}
20434
20435		}
20436
20437		const parameters = {
20438
20439			shaderID: shaderID,
20440			shaderType: material.type,
20441			shaderName: material.name,
20442
20443			vertexShader: vertexShader,
20444			fragmentShader: fragmentShader,
20445			defines: material.defines,
20446
20447			customVertexShaderID: customVertexShaderID,
20448			customFragmentShaderID: customFragmentShaderID,
20449
20450			isRawShaderMaterial: material.isRawShaderMaterial === true,
20451			glslVersion: material.glslVersion,
20452
20453			precision: precision,
20454
20455			batching: IS_BATCHEDMESH,
20456			instancing: IS_INSTANCEDMESH,
20457			instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null,
20458			instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null,
20459
20460			supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES,
20461			outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ),
20462			alphaToCoverage: !! material.alphaToCoverage,
20463
20464			map: HAS_MAP,
20465			matcap: HAS_MATCAP,
20466			envMap: HAS_ENVMAP,
20467			envMapMode: HAS_ENVMAP && envMap.mapping,
20468			envMapCubeUVHeight: envMapCubeUVHeight,
20469			aoMap: HAS_AOMAP,
20470			lightMap: HAS_LIGHTMAP,
20471			bumpMap: HAS_BUMPMAP,
20472			normalMap: HAS_NORMALMAP,
20473			displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP,
20474			emissiveMap: HAS_EMISSIVEMAP,
20475
20476			normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap,
20477			normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap,
20478
20479			metalnessMap: HAS_METALNESSMAP,
20480			roughnessMap: HAS_ROUGHNESSMAP,
20481
20482			anisotropy: HAS_ANISOTROPY,
20483			anisotropyMap: HAS_ANISOTROPYMAP,
20484
20485			clearcoat: HAS_CLEARCOAT,
20486			clearcoatMap: HAS_CLEARCOATMAP,
20487			clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP,
20488			clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP,
20489
20490			iridescence: HAS_IRIDESCENCE,
20491			iridescenceMap: HAS_IRIDESCENCEMAP,
20492			iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP,
20493
20494			sheen: HAS_SHEEN,
20495			sheenColorMap: HAS_SHEEN_COLORMAP,
20496			sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP,
20497
20498			specularMap: HAS_SPECULARMAP,
20499			specularColorMap: HAS_SPECULAR_COLORMAP,
20500			specularIntensityMap: HAS_SPECULAR_INTENSITYMAP,
20501
20502			transmission: HAS_TRANSMISSION,
20503			transmissionMap: HAS_TRANSMISSIONMAP,
20504			thicknessMap: HAS_THICKNESSMAP,
20505
20506			gradientMap: HAS_GRADIENTMAP,
20507
20508			opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false,
20509
20510			alphaMap: HAS_ALPHAMAP,
20511			alphaTest: HAS_ALPHATEST,
20512			alphaHash: HAS_ALPHAHASH,
20513
20514			combine: material.combine,
20515
20516			//
20517
20518			mapUv: HAS_MAP && getChannel( material.map.channel ),
20519			aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ),
20520			lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ),
20521			bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ),
20522			normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ),
20523			displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ),
20524			emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ),
20525
20526			metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ),
20527			roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ),
20528
20529			anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ),
20530
20531			clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ),
20532			clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ),
20533			clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ),
20534
20535			iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ),
20536			iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ),
20537
20538			sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ),
20539			sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ),
20540
20541			specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ),
20542			specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ),
20543			specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ),
20544
20545			transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ),
20546			thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ),
20547
20548			alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ),
20549
20550			//
20551
20552			vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ),
20553			vertexColors: material.vertexColors,
20554			vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4,
20555
20556			pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ),
20557
20558			fog: !! fog,
20559			useFog: material.fog === true,
20560			fogExp2: ( !! fog && fog.isFogExp2 ),
20561
20562			flatShading: material.flatShading === true,
20563
20564			sizeAttenuation: material.sizeAttenuation === true,
20565			logarithmicDepthBuffer: logarithmicDepthBuffer,
20566
20567			skinning: object.isSkinnedMesh === true,
20568
20569			morphTargets: geometry.morphAttributes.position !== undefined,
20570			morphNormals: geometry.morphAttributes.normal !== undefined,
20571			morphColors: geometry.morphAttributes.color !== undefined,
20572			morphTargetsCount: morphTargetsCount,
20573			morphTextureStride: morphTextureStride,
20574
20575			numDirLights: lights.directional.length,
20576			numPointLights: lights.point.length,
20577			numSpotLights: lights.spot.length,
20578			numSpotLightMaps: lights.spotLightMap.length,
20579			numRectAreaLights: lights.rectArea.length,
20580			numHemiLights: lights.hemi.length,
20581
20582			numDirLightShadows: lights.directionalShadowMap.length,
20583			numPointLightShadows: lights.pointShadowMap.length,
20584			numSpotLightShadows: lights.spotShadowMap.length,
20585			numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps,
20586
20587			numLightProbes: lights.numLightProbes,
20588
20589			numClippingPlanes: clipping.numPlanes,
20590			numClipIntersection: clipping.numIntersection,
20591
20592			dithering: material.dithering,
20593
20594			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
20595			shadowMapType: renderer.shadowMap.type,
20596
20597			toneMapping: toneMapping,
20598			useLegacyLights: renderer._useLegacyLights,
20599
20600			decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ),
20601
20602			premultipliedAlpha: material.premultipliedAlpha,
20603
20604			doubleSided: material.side === DoubleSide,
20605			flipSided: material.side === BackSide,
20606
20607			useDepthPacking: material.depthPacking >= 0,
20608			depthPacking: material.depthPacking || 0,
20609
20610			index0AttributeName: material.index0AttributeName,
20611
20612			extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ),
20613			extensionMultiDraw: HAS_EXTENSIONS && material.extensions.multiDraw === true && extensions.has( 'WEBGL_multi_draw' ),
20614
20615			rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ),
20616
20617			customProgramCacheKey: material.customProgramCacheKey()
20618
20619		};
20620
20621		// the usage of getChannel() determines the active texture channels for this shader
20622
20623		parameters.vertexUv1s = _activeChannels.has( 1 );
20624		parameters.vertexUv2s = _activeChannels.has( 2 );
20625		parameters.vertexUv3s = _activeChannels.has( 3 );
20626
20627		_activeChannels.clear();
20628
20629		return parameters;
20630
20631	}
20632
20633	function getProgramCacheKey( parameters ) {
20634
20635		const array = [];
20636
20637		if ( parameters.shaderID ) {
20638
20639			array.push( parameters.shaderID );
20640
20641		} else {
20642
20643			array.push( parameters.customVertexShaderID );
20644			array.push( parameters.customFragmentShaderID );
20645
20646		}
20647
20648		if ( parameters.defines !== undefined ) {
20649
20650			for ( const name in parameters.defines ) {
20651
20652				array.push( name );
20653				array.push( parameters.defines[ name ] );
20654
20655			}
20656
20657		}
20658
20659		if ( parameters.isRawShaderMaterial === false ) {
20660
20661			getProgramCacheKeyParameters( array, parameters );
20662			getProgramCacheKeyBooleans( array, parameters );
20663			array.push( renderer.outputColorSpace );
20664
20665		}
20666
20667		array.push( parameters.customProgramCacheKey );
20668
20669		return array.join();
20670
20671	}
20672
20673	function getProgramCacheKeyParameters( array, parameters ) {
20674
20675		array.push( parameters.precision );
20676		array.push( parameters.outputColorSpace );
20677		array.push( parameters.envMapMode );
20678		array.push( parameters.envMapCubeUVHeight );
20679		array.push( parameters.mapUv );
20680		array.push( parameters.alphaMapUv );
20681		array.push( parameters.lightMapUv );
20682		array.push( parameters.aoMapUv );
20683		array.push( parameters.bumpMapUv );
20684		array.push( parameters.normalMapUv );
20685		array.push( parameters.displacementMapUv );
20686		array.push( parameters.emissiveMapUv );
20687		array.push( parameters.metalnessMapUv );
20688		array.push( parameters.roughnessMapUv );
20689		array.push( parameters.anisotropyMapUv );
20690		array.push( parameters.clearcoatMapUv );
20691		array.push( parameters.clearcoatNormalMapUv );
20692		array.push( parameters.clearcoatRoughnessMapUv );
20693		array.push( parameters.iridescenceMapUv );
20694		array.push( parameters.iridescenceThicknessMapUv );
20695		array.push( parameters.sheenColorMapUv );
20696		array.push( parameters.sheenRoughnessMapUv );
20697		array.push( parameters.specularMapUv );
20698		array.push( parameters.specularColorMapUv );
20699		array.push( parameters.specularIntensityMapUv );
20700		array.push( parameters.transmissionMapUv );
20701		array.push( parameters.thicknessMapUv );
20702		array.push( parameters.combine );
20703		array.push( parameters.fogExp2 );
20704		array.push( parameters.sizeAttenuation );
20705		array.push( parameters.morphTargetsCount );
20706		array.push( parameters.morphAttributeCount );
20707		array.push( parameters.numDirLights );
20708		array.push( parameters.numPointLights );
20709		array.push( parameters.numSpotLights );
20710		array.push( parameters.numSpotLightMaps );
20711		array.push( parameters.numHemiLights );
20712		array.push( parameters.numRectAreaLights );
20713		array.push( parameters.numDirLightShadows );
20714		array.push( parameters.numPointLightShadows );
20715		array.push( parameters.numSpotLightShadows );
20716		array.push( parameters.numSpotLightShadowsWithMaps );
20717		array.push( parameters.numLightProbes );
20718		array.push( parameters.shadowMapType );
20719		array.push( parameters.toneMapping );
20720		array.push( parameters.numClippingPlanes );
20721		array.push( parameters.numClipIntersection );
20722		array.push( parameters.depthPacking );
20723
20724	}
20725
20726	function getProgramCacheKeyBooleans( array, parameters ) {
20727
20728		_programLayers.disableAll();
20729
20730		if ( parameters.supportsVertexTextures )
20731			_programLayers.enable( 0 );
20732		if ( parameters.instancing )
20733			_programLayers.enable( 1 );
20734		if ( parameters.instancingColor )
20735			_programLayers.enable( 2 );
20736		if ( parameters.instancingMorph )
20737			_programLayers.enable( 3 );
20738		if ( parameters.matcap )
20739			_programLayers.enable( 4 );
20740		if ( parameters.envMap )
20741			_programLayers.enable( 5 );
20742		if ( parameters.normalMapObjectSpace )
20743			_programLayers.enable( 6 );
20744		if ( parameters.normalMapTangentSpace )
20745			_programLayers.enable( 7 );
20746		if ( parameters.clearcoat )
20747			_programLayers.enable( 8 );
20748		if ( parameters.iridescence )
20749			_programLayers.enable( 9 );
20750		if ( parameters.alphaTest )
20751			_programLayers.enable( 10 );
20752		if ( parameters.vertexColors )
20753			_programLayers.enable( 11 );
20754		if ( parameters.vertexAlphas )
20755			_programLayers.enable( 12 );
20756		if ( parameters.vertexUv1s )
20757			_programLayers.enable( 13 );
20758		if ( parameters.vertexUv2s )
20759			_programLayers.enable( 14 );
20760		if ( parameters.vertexUv3s )
20761			_programLayers.enable( 15 );
20762		if ( parameters.vertexTangents )
20763			_programLayers.enable( 16 );
20764		if ( parameters.anisotropy )
20765			_programLayers.enable( 17 );
20766		if ( parameters.alphaHash )
20767			_programLayers.enable( 18 );
20768		if ( parameters.batching )
20769			_programLayers.enable( 19 );
20770
20771		array.push( _programLayers.mask );
20772		_programLayers.disableAll();
20773
20774		if ( parameters.fog )
20775			_programLayers.enable( 0 );
20776		if ( parameters.useFog )
20777			_programLayers.enable( 1 );
20778		if ( parameters.flatShading )
20779			_programLayers.enable( 2 );
20780		if ( parameters.logarithmicDepthBuffer )
20781			_programLayers.enable( 3 );
20782		if ( parameters.skinning )
20783			_programLayers.enable( 4 );
20784		if ( parameters.morphTargets )
20785			_programLayers.enable( 5 );
20786		if ( parameters.morphNormals )
20787			_programLayers.enable( 6 );
20788		if ( parameters.morphColors )
20789			_programLayers.enable( 7 );
20790		if ( parameters.premultipliedAlpha )
20791			_programLayers.enable( 8 );
20792		if ( parameters.shadowMapEnabled )
20793			_programLayers.enable( 9 );
20794		if ( parameters.useLegacyLights )
20795			_programLayers.enable( 10 );
20796		if ( parameters.doubleSided )
20797			_programLayers.enable( 11 );
20798		if ( parameters.flipSided )
20799			_programLayers.enable( 12 );
20800		if ( parameters.useDepthPacking )
20801			_programLayers.enable( 13 );
20802		if ( parameters.dithering )
20803			_programLayers.enable( 14 );
20804		if ( parameters.transmission )
20805			_programLayers.enable( 15 );
20806		if ( parameters.sheen )
20807			_programLayers.enable( 16 );
20808		if ( parameters.opaque )
20809			_programLayers.enable( 17 );
20810		if ( parameters.pointsUvs )
20811			_programLayers.enable( 18 );
20812		if ( parameters.decodeVideoTexture )
20813			_programLayers.enable( 19 );
20814		if ( parameters.alphaToCoverage )
20815			_programLayers.enable( 20 );
20816
20817		array.push( _programLayers.mask );
20818
20819	}
20820
20821	function getUniforms( material ) {
20822
20823		const shaderID = shaderIDs[ material.type ];
20824		let uniforms;
20825
20826		if ( shaderID ) {
20827
20828			const shader = ShaderLib[ shaderID ];
20829			uniforms = UniformsUtils.clone( shader.uniforms );
20830
20831		} else {
20832
20833			uniforms = material.uniforms;
20834
20835		}
20836
20837		return uniforms;
20838
20839	}
20840
20841	function acquireProgram( parameters, cacheKey ) {
20842
20843		let program;
20844
20845		// Check if code has been already compiled
20846		for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
20847
20848			const preexistingProgram = programs[ p ];
20849
20850			if ( preexistingProgram.cacheKey === cacheKey ) {
20851
20852				program = preexistingProgram;
20853				++ program.usedTimes;
20854
20855				break;
20856
20857			}
20858
20859		}
20860
20861		if ( program === undefined ) {
20862
20863			program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
20864			programs.push( program );
20865
20866		}
20867
20868		return program;
20869
20870	}
20871
20872	function releaseProgram( program ) {
20873
20874		if ( -- program.usedTimes === 0 ) {
20875
20876			// Remove from unordered set
20877			const i = programs.indexOf( program );
20878			programs[ i ] = programs[ programs.length - 1 ];
20879			programs.pop();
20880
20881			// Free WebGL resources
20882			program.destroy();
20883
20884		}
20885
20886	}
20887
20888	function releaseShaderCache( material ) {
20889
20890		_customShaders.remove( material );
20891
20892	}
20893
20894	function dispose() {
20895
20896		_customShaders.dispose();
20897
20898	}
20899
20900	return {
20901		getParameters: getParameters,
20902		getProgramCacheKey: getProgramCacheKey,
20903		getUniforms: getUniforms,
20904		acquireProgram: acquireProgram,
20905		releaseProgram: releaseProgram,
20906		releaseShaderCache: releaseShaderCache,
20907		// Exposed for resource monitoring & error feedback via renderer.info:
20908		programs: programs,
vendor: 4,538 bytes, lines 20909-21190
20909		dispose: dispose
20910	};
20911
20912}
20913
20914function WebGLProperties() {
20915
20916	let properties = new WeakMap();
20917
20918	function get( object ) {
20919
20920		let map = properties.get( object );
20921
20922		if ( map === undefined ) {
20923
20924			map = {};
20925			properties.set( object, map );
20926
20927		}
20928
20929		return map;
20930
20931	}
20932
20933	function remove( object ) {
20934
20935		properties.delete( object );
20936
20937	}
20938
20939	function update( object, key, value ) {
20940
20941		properties.get( object )[ key ] = value;
20942
20943	}
20944
20945	function dispose() {
20946
20947		properties = new WeakMap();
20948
20949	}
20950
20951	return {
20952		get: get,
20953		remove: remove,
20954		update: update,
20955		dispose: dispose
20956	};
20957
20958}
20959
20960function painterSortStable( a, b ) {
20961
20962	if ( a.groupOrder !== b.groupOrder ) {
20963
20964		return a.groupOrder - b.groupOrder;
20965
20966	} else if ( a.renderOrder !== b.renderOrder ) {
20967
20968		return a.renderOrder - b.renderOrder;
20969
20970	} else if ( a.material.id !== b.material.id ) {
20971
20972		return a.material.id - b.material.id;
20973
20974	} else if ( a.z !== b.z ) {
20975
20976		return a.z - b.z;
20977
20978	} else {
20979
20980		return a.id - b.id;
20981
20982	}
20983
20984}
20985
20986function reversePainterSortStable( a, b ) {
20987
20988	if ( a.groupOrder !== b.groupOrder ) {
20989
20990		return a.groupOrder - b.groupOrder;
20991
20992	} else if ( a.renderOrder !== b.renderOrder ) {
20993
20994		return a.renderOrder - b.renderOrder;
20995
20996	} else if ( a.z !== b.z ) {
20997
20998		return b.z - a.z;
20999
21000	} else {
21001
21002		return a.id - b.id;
21003
21004	}
21005
21006}
21007
21008
21009function WebGLRenderList() {
21010
21011	const renderItems = [];
21012	let renderItemsIndex = 0;
21013
21014	const opaque = [];
21015	const transmissive = [];
21016	const transparent = [];
21017
21018	function init() {
21019
21020		renderItemsIndex = 0;
21021
21022		opaque.length = 0;
21023		transmissive.length = 0;
21024		transparent.length = 0;
21025
21026	}
21027
21028	function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
21029
21030		let renderItem = renderItems[ renderItemsIndex ];
21031
21032		if ( renderItem === undefined ) {
21033
21034			renderItem = {
21035				id: object.id,
21036				object: object,
21037				geometry: geometry,
21038				material: material,
21039				groupOrder: groupOrder,
21040				renderOrder: object.renderOrder,
21041				z: z,
21042				group: group
21043			};
21044
21045			renderItems[ renderItemsIndex ] = renderItem;
21046
21047		} else {
21048
21049			renderItem.id = object.id;
21050			renderItem.object = object;
21051			renderItem.geometry = geometry;
21052			renderItem.material = material;
21053			renderItem.groupOrder = groupOrder;
21054			renderItem.renderOrder = object.renderOrder;
21055			renderItem.z = z;
21056			renderItem.group = group;
21057
21058		}
21059
21060		renderItemsIndex ++;
21061
21062		return renderItem;
21063
21064	}
21065
21066	function push( object, geometry, material, groupOrder, z, group ) {
21067
21068		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
21069
21070		if ( material.transmission > 0.0 ) {
21071
21072			transmissive.push( renderItem );
21073
21074		} else if ( material.transparent === true ) {
21075
21076			transparent.push( renderItem );
21077
21078		} else {
21079
21080			opaque.push( renderItem );
21081
21082		}
21083
21084	}
21085
21086	function unshift( object, geometry, material, groupOrder, z, group ) {
21087
21088		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
21089
21090		if ( material.transmission > 0.0 ) {
21091
21092			transmissive.unshift( renderItem );
21093
21094		} else if ( material.transparent === true ) {
21095
21096			transparent.unshift( renderItem );
21097
21098		} else {
21099
21100			opaque.unshift( renderItem );
21101
21102		}
21103
21104	}
21105
21106	function sort( customOpaqueSort, customTransparentSort ) {
21107
21108		if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
21109		if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
21110		if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
21111
21112	}
21113
21114	function finish() {
21115
21116		// Clear references from inactive renderItems in the list
21117
21118		for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
21119
21120			const renderItem = renderItems[ i ];
21121
21122			if ( renderItem.id === null ) break;
21123
21124			renderItem.id = null;
21125			renderItem.object = null;
21126			renderItem.geometry = null;
21127			renderItem.material = null;
21128			renderItem.group = null;
21129
21130		}
21131
21132	}
21133
21134	return {
21135
21136		opaque: opaque,
21137		transmissive: transmissive,
21138		transparent: transparent,
21139
21140		init: init,
21141		push: push,
21142		unshift: unshift,
21143		finish: finish,
21144
21145		sort: sort
21146	};
21147
21148}
21149
21150function WebGLRenderLists() {
21151
21152	let lists = new WeakMap();
21153
21154	function get( scene, renderCallDepth ) {
21155
21156		const listArray = lists.get( scene );
21157		let list;
21158
21159		if ( listArray === undefined ) {
21160
21161			list = new WebGLRenderList();
21162			lists.set( scene, [ list ] );
21163
21164		} else {
21165
21166			if ( renderCallDepth >= listArray.length ) {
21167
21168				list = new WebGLRenderList();
21169				listArray.push( list );
21170
21171			} else {
21172
21173				list = listArray[ renderCallDepth ];
21174
21175			}
21176
21177		}
21178
21179		return list;
21180
21181	}
21182
21183	function dispose() {
21184
21185		lists = new WeakMap();
21186
21187	}
21188
21189	return {
21190		get: get,
vendor: 10,595 bytes, lines 21191-21653
21191		dispose: dispose
21192	};
21193
21194}
21195
21196function UniformsCache() {
21197
21198	const lights = {};
21199
21200	return {
21201
21202		get: function ( light ) {
21203
21204			if ( lights[ light.id ] !== undefined ) {
21205
21206				return lights[ light.id ];
21207
21208			}
21209
21210			let uniforms;
21211
21212			switch ( light.type ) {
21213
21214				case 'DirectionalLight':
21215					uniforms = {
21216						direction: new Vector3(),
21217						color: new Color()
21218					};
21219					break;
21220
21221				case 'SpotLight':
21222					uniforms = {
21223						position: new Vector3(),
21224						direction: new Vector3(),
21225						color: new Color(),
21226						distance: 0,
21227						coneCos: 0,
21228						penumbraCos: 0,
21229						decay: 0
21230					};
21231					break;
21232
21233				case 'PointLight':
21234					uniforms = {
21235						position: new Vector3(),
21236						color: new Color(),
21237						distance: 0,
21238						decay: 0
21239					};
21240					break;
21241
21242				case 'HemisphereLight':
21243					uniforms = {
21244						direction: new Vector3(),
21245						skyColor: new Color(),
21246						groundColor: new Color()
21247					};
21248					break;
21249
21250				case 'RectAreaLight':
21251					uniforms = {
21252						color: new Color(),
21253						position: new Vector3(),
21254						halfWidth: new Vector3(),
21255						halfHeight: new Vector3()
21256					};
21257					break;
21258
21259			}
21260
21261			lights[ light.id ] = uniforms;
21262
21263			return uniforms;
21264
21265		}
21266
21267	};
21268
21269}
21270
21271function ShadowUniformsCache() {
21272
21273	const lights = {};
21274
21275	return {
21276
21277		get: function ( light ) {
21278
21279			if ( lights[ light.id ] !== undefined ) {
21280
21281				return lights[ light.id ];
21282
21283			}
21284
21285			let uniforms;
21286
21287			switch ( light.type ) {
21288
21289				case 'DirectionalLight':
21290					uniforms = {
21291						shadowBias: 0,
21292						shadowNormalBias: 0,
21293						shadowRadius: 1,
21294						shadowMapSize: new Vector2()
21295					};
21296					break;
21297
21298				case 'SpotLight':
21299					uniforms = {
21300						shadowBias: 0,
21301						shadowNormalBias: 0,
21302						shadowRadius: 1,
21303						shadowMapSize: new Vector2()
21304					};
21305					break;
21306
21307				case 'PointLight':
21308					uniforms = {
21309						shadowBias: 0,
21310						shadowNormalBias: 0,
21311						shadowRadius: 1,
21312						shadowMapSize: new Vector2(),
21313						shadowCameraNear: 1,
21314						shadowCameraFar: 1000
21315					};
21316					break;
21317
21318				// TODO (abelnation): set RectAreaLight shadow uniforms
21319
21320			}
21321
21322			lights[ light.id ] = uniforms;
21323
21324			return uniforms;
21325
21326		}
21327
21328	};
21329
21330}
21331
21332
21333
21334let nextVersion = 0;
21335
21336function shadowCastingAndTexturingLightsFirst( lightA, lightB ) {
21337
21338	return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 );
21339
21340}
21341
21342function WebGLLights( extensions ) {
21343
21344	const cache = new UniformsCache();
21345
21346	const shadowCache = ShadowUniformsCache();
21347
21348	const state = {
21349
21350		version: 0,
21351
21352		hash: {
21353			directionalLength: - 1,
21354			pointLength: - 1,
21355			spotLength: - 1,
21356			rectAreaLength: - 1,
21357			hemiLength: - 1,
21358
21359			numDirectionalShadows: - 1,
21360			numPointShadows: - 1,
21361			numSpotShadows: - 1,
21362			numSpotMaps: - 1,
21363
21364			numLightProbes: - 1
21365		},
21366
21367		ambient: [ 0, 0, 0 ],
21368		probe: [],
21369		directional: [],
21370		directionalShadow: [],
21371		directionalShadowMap: [],
21372		directionalShadowMatrix: [],
21373		spot: [],
21374		spotLightMap: [],
21375		spotShadow: [],
21376		spotShadowMap: [],
21377		spotLightMatrix: [],
21378		rectArea: [],
21379		rectAreaLTC1: null,
21380		rectAreaLTC2: null,
21381		point: [],
21382		pointShadow: [],
21383		pointShadowMap: [],
21384		pointShadowMatrix: [],
21385		hemi: [],
21386		numSpotLightShadowsWithMaps: 0,
21387		numLightProbes: 0
21388
21389	};
21390
21391	for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
21392
21393	const vector3 = new Vector3();
21394	const matrix4 = new Matrix4();
21395	const matrix42 = new Matrix4();
21396
21397	function setup( lights, useLegacyLights ) {
21398
21399		let r = 0, g = 0, b = 0;
21400
21401		for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
21402
21403		let directionalLength = 0;
21404		let pointLength = 0;
21405		let spotLength = 0;
21406		let rectAreaLength = 0;
21407		let hemiLength = 0;
21408
21409		let numDirectionalShadows = 0;
21410		let numPointShadows = 0;
21411		let numSpotShadows = 0;
21412		let numSpotMaps = 0;
21413		let numSpotShadowsWithMaps = 0;
21414
21415		let numLightProbes = 0;
21416
21417		// ordering : [shadow casting + map texturing, map texturing, shadow casting, none ]
21418		lights.sort( shadowCastingAndTexturingLightsFirst );
21419
21420		// artist-friendly light intensity scaling factor
21421		const scaleFactor = ( useLegacyLights === true ) ? Math.PI : 1;
21422
21423		for ( let i = 0, l = lights.length; i < l; i ++ ) {
21424
21425			const light = lights[ i ];
21426
21427			const color = light.color;
21428			const intensity = light.intensity;
21429			const distance = light.distance;
21430
21431			const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
21432
21433			if ( light.isAmbientLight ) {
21434
21435				r += color.r * intensity * scaleFactor;
21436				g += color.g * intensity * scaleFactor;
21437				b += color.b * intensity * scaleFactor;
21438
21439			} else if ( light.isLightProbe ) {
21440
21441				for ( let j = 0; j < 9; j ++ ) {
21442
21443					state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
21444
21445				}
21446
21447				numLightProbes ++;
21448
21449			} else if ( light.isDirectionalLight ) {
21450
21451				const uniforms = cache.get( light );
21452
21453				uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
21454
21455				if ( light.castShadow ) {
21456
21457					const shadow = light.shadow;
21458
21459					const shadowUniforms = shadowCache.get( light );
21460
21461					shadowUniforms.shadowBias = shadow.bias;
21462					shadowUniforms.shadowNormalBias = shadow.normalBias;
21463					shadowUniforms.shadowRadius = shadow.radius;
21464					shadowUniforms.shadowMapSize = shadow.mapSize;
21465
21466					state.directionalShadow[ directionalLength ] = shadowUniforms;
21467					state.directionalShadowMap[ directionalLength ] = shadowMap;
21468					state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
21469
21470					numDirectionalShadows ++;
21471
21472				}
21473
21474				state.directional[ directionalLength ] = uniforms;
21475
21476				directionalLength ++;
21477
21478			} else if ( light.isSpotLight ) {
21479
21480				const uniforms = cache.get( light );
21481
21482				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21483
21484				uniforms.color.copy( color ).multiplyScalar( intensity * scaleFactor );
21485				uniforms.distance = distance;
21486
21487				uniforms.coneCos = Math.cos( light.angle );
21488				uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
21489				uniforms.decay = light.decay;
21490
21491				state.spot[ spotLength ] = uniforms;
21492
21493				const shadow = light.shadow;
21494
21495				if ( light.map ) {
21496
21497					state.spotLightMap[ numSpotMaps ] = light.map;
21498					numSpotMaps ++;
21499
21500					// make sure the lightMatrix is up to date
21501					// TODO : do it if required only
21502					shadow.updateMatrices( light );
21503
21504					if ( light.castShadow ) numSpotShadowsWithMaps ++;
21505
21506				}
21507
21508				state.spotLightMatrix[ spotLength ] = shadow.matrix;
21509
21510				if ( light.castShadow ) {
21511
21512					const shadowUniforms = shadowCache.get( light );
21513
21514					shadowUniforms.shadowBias = shadow.bias;
21515					shadowUniforms.shadowNormalBias = shadow.normalBias;
21516					shadowUniforms.shadowRadius = shadow.radius;
21517					shadowUniforms.shadowMapSize = shadow.mapSize;
21518
21519					state.spotShadow[ spotLength ] = shadowUniforms;
21520					state.spotShadowMap[ spotLength ] = shadowMap;
21521
21522					numSpotShadows ++;
21523
21524				}
21525
21526				spotLength ++;
21527
21528			} else if ( light.isRectAreaLight ) {
21529
21530				const uniforms = cache.get( light );
21531
21532				uniforms.color.copy( color ).multiplyScalar( intensity );
21533
21534				uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
21535				uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
21536
21537				state.rectArea[ rectAreaLength ] = uniforms;
21538
21539				rectAreaLength ++;
21540
21541			} else if ( light.isPointLight ) {
21542
21543				const uniforms = cache.get( light );
21544
21545				uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
21546				uniforms.distance = light.distance;
21547				uniforms.decay = light.decay;
21548
21549				if ( light.castShadow ) {
21550
21551					const shadow = light.shadow;
21552
21553					const shadowUniforms = shadowCache.get( light );
21554
21555					shadowUniforms.shadowBias = shadow.bias;
21556					shadowUniforms.shadowNormalBias = shadow.normalBias;
21557					shadowUniforms.shadowRadius = shadow.radius;
21558					shadowUniforms.shadowMapSize = shadow.mapSize;
21559					shadowUniforms.shadowCameraNear = shadow.camera.near;
21560					shadowUniforms.shadowCameraFar = shadow.camera.far;
21561
21562					state.pointShadow[ pointLength ] = shadowUniforms;
21563					state.pointShadowMap[ pointLength ] = shadowMap;
21564					state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
21565
21566					numPointShadows ++;
21567
21568				}
21569
21570				state.point[ pointLength ] = uniforms;
21571
21572				pointLength ++;
21573
21574			} else if ( light.isHemisphereLight ) {
21575
21576				const uniforms = cache.get( light );
21577
21578				uniforms.skyColor.copy( light.color ).multiplyScalar( intensity * scaleFactor );
21579				uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity * scaleFactor );
21580
21581				state.hemi[ hemiLength ] = uniforms;
21582
21583				hemiLength ++;
21584
21585			}
21586
21587		}
21588
21589		if ( rectAreaLength > 0 ) {
21590
21591			if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
21592
21593				state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
21594				state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
21595
21596			} else {
21597
21598				state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
21599				state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
21600
21601			}
21602
21603		}
21604
21605		state.ambient[ 0 ] = r;
21606		state.ambient[ 1 ] = g;
21607		state.ambient[ 2 ] = b;
21608
21609		const hash = state.hash;
21610
21611		if ( hash.directionalLength !== directionalLength ||
21612			hash.pointLength !== pointLength ||
21613			hash.spotLength !== spotLength ||
21614			hash.rectAreaLength !== rectAreaLength ||
21615			hash.hemiLength !== hemiLength ||
21616			hash.numDirectionalShadows !== numDirectionalShadows ||
21617			hash.numPointShadows !== numPointShadows ||
21618			hash.numSpotShadows !== numSpotShadows ||
21619			hash.numSpotMaps !== numSpotMaps ||
21620			hash.numLightProbes !== numLightProbes ) {
21621
21622			state.directional.length = directionalLength;
21623			state.spot.length = spotLength;
21624			state.rectArea.length = rectAreaLength;
21625			state.point.length = pointLength;
21626			state.hemi.length = hemiLength;
21627
21628			state.directionalShadow.length = numDirectionalShadows;
21629			state.directionalShadowMap.length = numDirectionalShadows;
21630			state.pointShadow.length = numPointShadows;
21631			state.pointShadowMap.length = numPointShadows;
21632			state.spotShadow.length = numSpotShadows;
21633			state.spotShadowMap.length = numSpotShadows;
21634			state.directionalShadowMatrix.length = numDirectionalShadows;
21635			state.pointShadowMatrix.length = numPointShadows;
21636			state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps;
21637			state.spotLightMap.length = numSpotMaps;
21638			state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps;
21639			state.numLightProbes = numLightProbes;
21640
21641			hash.directionalLength = directionalLength;
21642			hash.pointLength = pointLength;
21643			hash.spotLength = spotLength;
21644			hash.rectAreaLength = rectAreaLength;
21645			hash.hemiLength = hemiLength;
21646
21647			hash.numDirectionalShadows = numDirectionalShadows;
21648			hash.numPointShadows = numPointShadows;
21649			hash.numSpotShadows = numSpotShadows;
21650			hash.numSpotMaps = numSpotMaps;
21651
21652			hash.numLightProbes = numLightProbes;
21653
vendor: 4,314 bytes, lines 21654-21877
21654			state.version = nextVersion ++;
21655
21656		}
21657
21658	}
21659
21660	function setupView( lights, camera ) {
21661
21662		let directionalLength = 0;
21663		let pointLength = 0;
21664		let spotLength = 0;
21665		let rectAreaLength = 0;
21666		let hemiLength = 0;
21667
21668		const viewMatrix = camera.matrixWorldInverse;
21669
21670		for ( let i = 0, l = lights.length; i < l; i ++ ) {
21671
21672			const light = lights[ i ];
21673
21674			if ( light.isDirectionalLight ) {
21675
21676				const uniforms = state.directional[ directionalLength ];
21677
21678				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
21679				vector3.setFromMatrixPosition( light.target.matrixWorld );
21680				uniforms.direction.sub( vector3 );
21681				uniforms.direction.transformDirection( viewMatrix );
21682
21683				directionalLength ++;
21684
21685			} else if ( light.isSpotLight ) {
21686
21687				const uniforms = state.spot[ spotLength ];
21688
21689				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21690				uniforms.position.applyMatrix4( viewMatrix );
21691
21692				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
21693				vector3.setFromMatrixPosition( light.target.matrixWorld );
21694				uniforms.direction.sub( vector3 );
21695				uniforms.direction.transformDirection( viewMatrix );
21696
21697				spotLength ++;
21698
21699			} else if ( light.isRectAreaLight ) {
21700
21701				const uniforms = state.rectArea[ rectAreaLength ];
21702
21703				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21704				uniforms.position.applyMatrix4( viewMatrix );
21705
21706				// extract local rotation of light to derive width/height half vectors
21707				matrix42.identity();
21708				matrix4.copy( light.matrixWorld );
21709				matrix4.premultiply( viewMatrix );
21710				matrix42.extractRotation( matrix4 );
21711
21712				uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
21713				uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
21714
21715				uniforms.halfWidth.applyMatrix4( matrix42 );
21716				uniforms.halfHeight.applyMatrix4( matrix42 );
21717
21718				rectAreaLength ++;
21719
21720			} else if ( light.isPointLight ) {
21721
21722				const uniforms = state.point[ pointLength ];
21723
21724				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21725				uniforms.position.applyMatrix4( viewMatrix );
21726
21727				pointLength ++;
21728
21729			} else if ( light.isHemisphereLight ) {
21730
21731				const uniforms = state.hemi[ hemiLength ];
21732
21733				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
21734				uniforms.direction.transformDirection( viewMatrix );
21735
21736				hemiLength ++;
21737
21738			}
21739
21740		}
21741
21742	}
21743
21744	return {
21745		setup: setup,
21746		setupView: setupView,
21747		state: state
21748	};
21749
21750}
21751
21752function WebGLRenderState( extensions ) {
21753
21754	const lights = new WebGLLights( extensions );
21755
21756	const lightsArray = [];
21757	const shadowsArray = [];
21758
21759	function init() {
21760
21761		lightsArray.length = 0;
21762		shadowsArray.length = 0;
21763
21764	}
21765
21766	function pushLight( light ) {
21767
21768		lightsArray.push( light );
21769
21770	}
21771
21772	function pushShadow( shadowLight ) {
21773
21774		shadowsArray.push( shadowLight );
21775
21776	}
21777
21778	function setupLights( useLegacyLights ) {
21779
21780		lights.setup( lightsArray, useLegacyLights );
21781
21782	}
21783
21784	function setupLightsView( camera ) {
21785
21786		lights.setupView( lightsArray, camera );
21787
21788	}
21789
21790	const state = {
21791		lightsArray: lightsArray,
21792		shadowsArray: shadowsArray,
21793
21794		lights: lights,
21795
21796		transmissionRenderTarget: null
21797	};
21798
21799	return {
21800		init: init,
21801		state: state,
21802		setupLights: setupLights,
21803		setupLightsView: setupLightsView,
21804
21805		pushLight: pushLight,
21806		pushShadow: pushShadow
21807	};
21808
21809}
21810
21811function WebGLRenderStates( extensions ) {
21812
21813	let renderStates = new WeakMap();
21814
21815	function get( scene, renderCallDepth = 0 ) {
21816
21817		const renderStateArray = renderStates.get( scene );
21818		let renderState;
21819
21820		if ( renderStateArray === undefined ) {
21821
21822			renderState = new WebGLRenderState( extensions );
21823			renderStates.set( scene, [ renderState ] );
21824
21825		} else {
21826
21827			if ( renderCallDepth >= renderStateArray.length ) {
21828
21829				renderState = new WebGLRenderState( extensions );
21830				renderStateArray.push( renderState );
21831
21832			} else {
21833
21834				renderState = renderStateArray[ renderCallDepth ];
21835
21836			}
21837
21838		}
21839
21840		return renderState;
21841
21842	}
21843
21844	function dispose() {
21845
21846		renderStates = new WeakMap();
21847
21848	}
21849
21850	return {
21851		get: get,
21852		dispose: dispose
21853	};
21854
21855}
21856
21857class MeshDepthMaterial extends Material {
21858
21859	constructor( parameters ) {
21860
21861		super();
21862
21863		this.isMeshDepthMaterial = true;
21864
21865		this.type = 'MeshDepthMaterial';
21866
21867		this.depthPacking = BasicDepthPacking;
21868
21869		this.map = null;
21870
21871		this.alphaMap = null;
21872
21873		this.displacementMap = null;
21874		this.displacementScale = 1;
21875		this.displacementBias = 0;
21876
21877		this.wireframe = false;
vendor: 3,393 bytes, lines 21878-21991
21878		this.wireframeLinewidth = 1;
21879
21880		this.setValues( parameters );
21881
21882	}
21883
21884	copy( source ) {
21885
21886		super.copy( source );
21887
21888		this.depthPacking = source.depthPacking;
21889
21890		this.map = source.map;
21891
21892		this.alphaMap = source.alphaMap;
21893
21894		this.displacementMap = source.displacementMap;
21895		this.displacementScale = source.displacementScale;
21896		this.displacementBias = source.displacementBias;
21897
21898		this.wireframe = source.wireframe;
21899		this.wireframeLinewidth = source.wireframeLinewidth;
21900
21901		return this;
21902
21903	}
21904
21905}
21906
21907class MeshDistanceMaterial extends Material {
21908
21909	constructor( parameters ) {
21910
21911		super();
21912
21913		this.isMeshDistanceMaterial = true;
21914
21915		this.type = 'MeshDistanceMaterial';
21916
21917		this.map = null;
21918
21919		this.alphaMap = null;
21920
21921		this.displacementMap = null;
21922		this.displacementScale = 1;
21923		this.displacementBias = 0;
21924
21925		this.setValues( parameters );
21926
21927	}
21928
21929	copy( source ) {
21930
21931		super.copy( source );
21932
21933		this.map = source.map;
21934
21935		this.alphaMap = source.alphaMap;
21936
21937		this.displacementMap = source.displacementMap;
21938		this.displacementScale = source.displacementScale;
21939		this.displacementBias = source.displacementBias;
21940
21941		return this;
21942
21943	}
21944
21945}
21946
21947const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
21948
21949const 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}";
21950
21951function WebGLShadowMap( _renderer, _objects, _capabilities ) {
21952
21953	let _frustum = new Frustum();
21954
21955	const _shadowMapSize = new Vector2(),
21956		_viewportSize = new Vector2(),
21957
21958		_viewport = new Vector4(),
21959
21960		_depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ),
21961		_distanceMaterial = new MeshDistanceMaterial(),
21962
21963		_materialCache = {},
21964
21965		_maxTextureSize = _capabilities.maxTextureSize;
21966
21967	const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide };
21968
21969	const shadowMaterialVertical = new ShaderMaterial( {
21970		defines: {
21971			VSM_SAMPLES: 8
21972		},
21973		uniforms: {
21974			shadow_pass: { value: null },
21975			resolution: { value: new Vector2() },
21976			radius: { value: 4.0 }
21977		},
21978
21979		vertexShader: vertex,
21980		fragmentShader: fragment
21981
21982	} );
21983
21984	const shadowMaterialHorizontal = shadowMaterialVertical.clone();
21985	shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
21986
21987	const fullScreenTri = new BufferGeometry();
21988	fullScreenTri.setAttribute(
21989		'position',
21990		new BufferAttribute(
21991			new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 
vendor: 9,734 bytes, lines 21991-22359
219911, 3, 0.5 ] ),
21992			3
21993		)
21994	);
21995
21996	const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
21997
21998	const scope = this;
21999
22000	this.enabled = false;
22001
22002	this.autoUpdate = true;
22003	this.needsUpdate = false;
22004
22005	this.type = PCFShadowMap;
22006	let _previousType = this.type;
22007
22008	this.render = function ( lights, scene, camera ) {
22009
22010		if ( scope.enabled === false ) return;
22011		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
22012
22013		if ( lights.length === 0 ) return;
22014
22015		const currentRenderTarget = _renderer.getRenderTarget();
22016		const activeCubeFace = _renderer.getActiveCubeFace();
22017		const activeMipmapLevel = _renderer.getActiveMipmapLevel();
22018
22019		const _state = _renderer.state;
22020
22021		// Set GL state for depth map.
22022		_state.setBlending( NoBlending );
22023		_state.buffers.color.setClear( 1, 1, 1, 1 );
22024		_state.buffers.depth.setTest( true );
22025		_state.setScissorTest( false );
22026
22027		// check for shadow map type changes
22028
22029		const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap );
22030		const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap );
22031
22032		// render depth map
22033
22034		for ( let i = 0, il = lights.length; i < il; i ++ ) {
22035
22036			const light = lights[ i ];
22037			const shadow = light.shadow;
22038
22039			if ( shadow === undefined ) {
22040
22041				console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
22042				continue;
22043
22044			}
22045
22046			if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
22047
22048			_shadowMapSize.copy( shadow.mapSize );
22049
22050			const shadowFrameExtents = shadow.getFrameExtents();
22051
22052			_shadowMapSize.multiply( shadowFrameExtents );
22053
22054			_viewportSize.copy( shadow.mapSize );
22055
22056			if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) {
22057
22058				if ( _shadowMapSize.x > _maxTextureSize ) {
22059
22060					_viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x );
22061					_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
22062					shadow.mapSize.x = _viewportSize.x;
22063
22064				}
22065
22066				if ( _shadowMapSize.y > _maxTextureSize ) {
22067
22068					_viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y );
22069					_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
22070					shadow.mapSize.y = _viewportSize.y;
22071
22072				}
22073
22074			}
22075
22076			if ( shadow.map === null || toVSM === true || fromVSM === true ) {
22077
22078				const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {};
22079
22080				if ( shadow.map !== null ) {
22081
22082					shadow.map.dispose();
22083
22084				}
22085
22086				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
22087				shadow.map.texture.name = light.name + '.shadowMap';
22088
22089				shadow.camera.updateProjectionMatrix();
22090
22091			}
22092
22093			_renderer.setRenderTarget( shadow.map );
22094			_renderer.clear();
22095
22096			const viewportCount = shadow.getViewportCount();
22097
22098			for ( let vp = 0; vp < viewportCount; vp ++ ) {
22099
22100				const viewport = shadow.getViewport( vp );
22101
22102				_viewport.set(
22103					_viewportSize.x * viewport.x,
22104					_viewportSize.y * viewport.y,
22105					_viewportSize.x * viewport.z,
22106					_viewportSize.y * viewport.w
22107				);
22108
22109				_state.viewport( _viewport );
22110
22111				shadow.updateMatrices( light, vp );
22112
22113				_frustum = shadow.getFrustum();
22114
22115				renderObject( scene, camera, shadow.camera, light, this.type );
22116
22117			}
22118
22119			// do blur pass for VSM
22120
22121			if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) {
22122
22123				VSMPass( shadow, camera );
22124
22125			}
22126
22127			shadow.needsUpdate = false;
22128
22129		}
22130
22131		_previousType = this.type;
22132
22133		scope.needsUpdate = false;
22134
22135		_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
22136
22137	};
22138
22139	function VSMPass( shadow, camera ) {
22140
22141		const geometry = _objects.update( fullScreenMesh );
22142
22143		if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) {
22144
22145			shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
22146			shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
22147
22148			shadowMaterialVertical.needsUpdate = true;
22149			shadowMaterialHorizontal.needsUpdate = true;
22150
22151		}
22152
22153		if ( shadow.mapPass === null ) {
22154
22155			shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y );
22156
22157		}
22158
22159		// vertical pass
22160
22161		shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
22162		shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
22163		shadowMaterialVertical.uniforms.radius.value = shadow.radius;
22164		_renderer.setRenderTarget( shadow.mapPass );
22165		_renderer.clear();
22166		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
22167
22168		// horizontal pass
22169
22170		shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
22171		shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
22172		shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
22173		_renderer.setRenderTarget( shadow.map );
22174		_renderer.clear();
22175		_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
22176
22177	}
22178
22179	function getDepthMaterial( object, material, light, type ) {
22180
22181		let result = null;
22182
22183		const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial;
22184
22185		if ( customMaterial !== undefined ) {
22186
22187			result = customMaterial;
22188
22189		} else {
22190
22191			result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial;
22192
22193			if ( ( _renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) ||
22194				( material.displacementMap && material.displacementScale !== 0 ) ||
22195				( material.alphaMap && material.alphaTest > 0 ) ||
22196				( material.map && material.alphaTest > 0 ) ) {
22197
22198				// in this case we need a unique material instance reflecting the
22199				// appropriate state
22200
22201				const keyA = result.uuid, keyB = material.uuid;
22202
22203				let materialsForVariant = _materialCache[ keyA ];
22204
22205				if ( materialsForVariant === undefined ) {
22206
22207					materialsForVariant = {};
22208					_materialCache[ keyA ] = materialsForVariant;
22209
22210				}
22211
22212				let cachedMaterial = materialsForVariant[ keyB ];
22213
22214				if ( cachedMaterial === undefined ) {
22215
22216					cachedMaterial = result.clone();
22217					materialsForVariant[ keyB ] = cachedMaterial;
22218					material.addEventListener( 'dispose', onMaterialDispose );
22219
22220				}
22221
22222				result = cachedMaterial;
22223
22224			}
22225
22226		}
22227
22228		result.visible = material.visible;
22229		result.wireframe = material.wireframe;
22230
22231		if ( type === VSMShadowMap ) {
22232
22233			result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
22234
22235		} else {
22236
22237			result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
22238
22239		}
22240
22241		result.alphaMap = material.alphaMap;
22242		result.alphaTest = material.alphaTest;
22243		result.map = material.map;
22244
22245		result.clipShadows = material.clipShadows;
22246		result.clippingPlanes = material.clippingPlanes;
22247		result.clipIntersection = material.clipIntersection;
22248
22249		result.displacementMap = material.displacementMap;
22250		result.displacementScale = material.displacementScale;
22251		result.displacementBias = material.displacementBias;
22252
22253		result.wireframeLinewidth = material.wireframeLinewidth;
22254		result.linewidth = material.linewidth;
22255
22256		if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
22257
22258			const materialProperties = _renderer.properties.get( result );
22259			materialProperties.light = light;
22260
22261		}
22262
22263		return result;
22264
22265	}
22266
22267	function renderObject( object, camera, shadowCamera, light, type ) {
22268
22269		if ( object.visible === false ) return;
22270
22271		const visible = object.layers.test( camera.layers );
22272
22273		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
22274
22275			if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
22276
22277				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
22278
22279				const geometry = _objects.update( object );
22280				const material = object.material;
22281
22282				if ( Array.isArray( material ) ) {
22283
22284					const groups = geometry.groups;
22285
22286					for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
22287
22288						const group = groups[ k ];
22289						const groupMaterial = material[ group.materialIndex ];
22290
22291						if ( groupMaterial && groupMaterial.visible ) {
22292
22293							const depthMaterial = getDepthMaterial( object, groupMaterial, light, type );
22294
22295							object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group );
22296
22297							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
22298
22299							object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group );
22300
22301						}
22302
22303					}
22304
22305				} else if ( material.visible ) {
22306
22307					const depthMaterial = getDepthMaterial( object, material, light, type );
22308
22309					object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null );
22310
22311					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
22312
22313					object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null );
22314
22315				}
22316
22317			}
22318
22319		}
22320
22321		const children = object.children;
22322
22323		for ( let i = 0, l = children.length; i < l; i ++ ) {
22324
22325			renderObject( children[ i ], camera, shadowCamera, light, type );
22326
22327		}
22328
22329	}
22330
22331	function onMaterialDispose( event ) {
22332
22333		const material = event.target;
22334
22335		material.removeEventListener( 'dispose', onMaterialDispose );
22336
22337		// make sure to remove the unique distance/depth materials used for shadow map rendering
22338
22339		for ( const id in _materialCache ) {
22340
22341			const cache = _materialCache[ id ];
22342
22343			const uuid = event.target.uuid;
22344
22345			if ( uuid in cache ) {
22346
22347				const shadowMaterial = cache[ uuid ];
22348				shadowMaterial.dispose();
22349				delete cache[ uuid ];
22350
22351			}
22352
22353		}
22354
22355	}
22356
22357}
22358
22359function WebGLState( gl
vendor: 9,931 bytes, lines 22359-22898
22359 ) {
22360
22361	function ColorBuffer() {
22362
22363		let locked = false;
22364
22365		const color = new Vector4();
22366		let currentColorMask = null;
22367		const currentColorClear = new Vector4( 0, 0, 0, 0 );
22368
22369		return {
22370
22371			setMask: function ( colorMask ) {
22372
22373				if ( currentColorMask !== colorMask && ! locked ) {
22374
22375					gl.colorMask( colorMask, colorMask, colorMask, colorMask );
22376					currentColorMask = colorMask;
22377
22378				}
22379
22380			},
22381
22382			setLocked: function ( lock ) {
22383
22384				locked = lock;
22385
22386			},
22387
22388			setClear: function ( r, g, b, a, premultipliedAlpha ) {
22389
22390				if ( premultipliedAlpha === true ) {
22391
22392					r *= a; g *= a; b *= a;
22393
22394				}
22395
22396				color.set( r, g, b, a );
22397
22398				if ( currentColorClear.equals( color ) === false ) {
22399
22400					gl.clearColor( r, g, b, a );
22401					currentColorClear.copy( color );
22402
22403				}
22404
22405			},
22406
22407			reset: function () {
22408
22409				locked = false;
22410
22411				currentColorMask = null;
22412				currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
22413
22414			}
22415
22416		};
22417
22418	}
22419
22420	function DepthBuffer() {
22421
22422		let locked = false;
22423
22424		let currentDepthMask = null;
22425		let currentDepthFunc = null;
22426		let currentDepthClear = null;
22427
22428		return {
22429
22430			setTest: function ( depthTest ) {
22431
22432				if ( depthTest ) {
22433
22434					enable( gl.DEPTH_TEST );
22435
22436				} else {
22437
22438					disable( gl.DEPTH_TEST );
22439
22440				}
22441
22442			},
22443
22444			setMask: function ( depthMask ) {
22445
22446				if ( currentDepthMask !== depthMask && ! locked ) {
22447
22448					gl.depthMask( depthMask );
22449					currentDepthMask = depthMask;
22450
22451				}
22452
22453			},
22454
22455			setFunc: function ( depthFunc ) {
22456
22457				if ( currentDepthFunc !== depthFunc ) {
22458
22459					switch ( depthFunc ) {
22460
22461						case NeverDepth:
22462
22463							gl.depthFunc( gl.NEVER );
22464							break;
22465
22466						case AlwaysDepth:
22467
22468							gl.depthFunc( gl.ALWAYS );
22469							break;
22470
22471						case LessDepth:
22472
22473							gl.depthFunc( gl.LESS );
22474							break;
22475
22476						case LessEqualDepth:
22477
22478							gl.depthFunc( gl.LEQUAL );
22479							break;
22480
22481						case EqualDepth:
22482
22483							gl.depthFunc( gl.EQUAL );
22484							break;
22485
22486						case GreaterEqualDepth:
22487
22488							gl.depthFunc( gl.GEQUAL );
22489							break;
22490
22491						case GreaterDepth:
22492
22493							gl.depthFunc( gl.GREATER );
22494							break;
22495
22496						case NotEqualDepth:
22497
22498							gl.depthFunc( gl.NOTEQUAL );
22499							break;
22500
22501						default:
22502
22503							gl.depthFunc( gl.LEQUAL );
22504
22505					}
22506
22507					currentDepthFunc = depthFunc;
22508
22509				}
22510
22511			},
22512
22513			setLocked: function ( lock ) {
22514
22515				locked = lock;
22516
22517			},
22518
22519			setClear: function ( depth ) {
22520
22521				if ( currentDepthClear !== depth ) {
22522
22523					gl.clearDepth( depth );
22524					currentDepthClear = depth;
22525
22526				}
22527
22528			},
22529
22530			reset: function () {
22531
22532				locked = false;
22533
22534				currentDepthMask = null;
22535				currentDepthFunc = null;
22536				currentDepthClear = null;
22537
22538			}
22539
22540		};
22541
22542	}
22543
22544	function StencilBuffer() {
22545
22546		let locked = false;
22547
22548		let currentStencilMask = null;
22549		let currentStencilFunc = null;
22550		let currentStencilRef = null;
22551		let currentStencilFuncMask = null;
22552		let currentStencilFail = null;
22553		let currentStencilZFail = null;
22554		let currentStencilZPass = null;
22555		let currentStencilClear = null;
22556
22557		return {
22558
22559			setTest: function ( stencilTest ) {
22560
22561				if ( ! locked ) {
22562
22563					if ( stencilTest ) {
22564
22565						enable( gl.STENCIL_TEST );
22566
22567					} else {
22568
22569						disable( gl.STENCIL_TEST );
22570
22571					}
22572
22573				}
22574
22575			},
22576
22577			setMask: function ( stencilMask ) {
22578
22579				if ( currentStencilMask !== stencilMask && ! locked ) {
22580
22581					gl.stencilMask( stencilMask );
22582					currentStencilMask = stencilMask;
22583
22584				}
22585
22586			},
22587
22588			setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
22589
22590				if ( currentStencilFunc !== stencilFunc ||
22591				     currentStencilRef !== stencilRef ||
22592				     currentStencilFuncMask !== stencilMask ) {
22593
22594					gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
22595
22596					currentStencilFunc = stencilFunc;
22597					currentStencilRef = stencilRef;
22598					currentStencilFuncMask = stencilMask;
22599
22600				}
22601
22602			},
22603
22604			setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
22605
22606				if ( currentStencilFail !== stencilFail ||
22607				     currentStencilZFail !== stencilZFail ||
22608				     currentStencilZPass !== stencilZPass ) {
22609
22610					gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
22611
22612					currentStencilFail = stencilFail;
22613					currentStencilZFail = stencilZFail;
22614					currentStencilZPass = stencilZPass;
22615
22616				}
22617
22618			},
22619
22620			setLocked: function ( lock ) {
22621
22622				locked = lock;
22623
22624			},
22625
22626			setClear: function ( stencil ) {
22627
22628				if ( currentStencilClear !== stencil ) {
22629
22630					gl.clearStencil( stencil );
22631					currentStencilClear = stencil;
22632
22633				}
22634
22635			},
22636
22637			reset: function () {
22638
22639				locked = false;
22640
22641				currentStencilMask = null;
22642				currentStencilFunc = null;
22643				currentStencilRef = null;
22644				currentStencilFuncMask = null;
22645				currentStencilFail = null;
22646				currentStencilZFail = null;
22647				currentStencilZPass = null;
22648				currentStencilClear = null;
22649
22650			}
22651
22652		};
22653
22654	}
22655
22656	//
22657
22658	const colorBuffer = new ColorBuffer();
22659	const depthBuffer = new DepthBuffer();
22660	const stencilBuffer = new StencilBuffer();
22661
22662	const uboBindings = new WeakMap();
22663	const uboProgramMap = new WeakMap();
22664
22665	let enabledCapabilities = {};
22666
22667	let currentBoundFramebuffers = {};
22668	let currentDrawbuffers = new WeakMap();
22669	let defaultDrawbuffers = [];
22670
22671	let currentProgram = null;
22672
22673	let currentBlendingEnabled = false;
22674	let currentBlending = null;
22675	let currentBlendEquation = null;
22676	let currentBlendSrc = null;
22677	let currentBlendDst = null;
22678	let currentBlendEquationAlpha = null;
22679	let currentBlendSrcAlpha = null;
22680	let currentBlendDstAlpha = null;
22681	let currentBlendColor = new Color( 0, 0, 0 );
22682	let currentBlendAlpha = 0;
22683	let currentPremultipledAlpha = false;
22684
22685	let currentFlipSided = null;
22686	let currentCullFace = null;
22687
22688	let currentLineWidth = null;
22689
22690	let currentPolygonOffsetFactor = null;
22691	let currentPolygonOffsetUnits = null;
22692
22693	const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );
22694
22695	let lineWidthAvailable = false;
22696	let version = 0;
22697	const glVersion = gl.getParameter( gl.VERSION );
22698
22699	if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
22700
22701		version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
22702		lineWidthAvailable = ( version >= 1.0 );
22703
22704	} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
22705
22706		version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
22707		lineWidthAvailable = ( version >= 2.0 );
22708
22709	}
22710
22711	let currentTextureSlot = null;
22712	let currentBoundTextures = {};
22713
22714	const scissorParam = gl.getParameter( gl.SCISSOR_BOX );
22715	const viewportParam = gl.getParameter( gl.VIEWPORT );
22716
22717	const currentScissor = new Vector4().fromArray( scissorParam );
22718	const currentViewport = new Vector4().fromArray( viewportParam );
22719
22720	function createTexture( type, target, count, dimensions ) {
22721
22722		const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
22723		const texture = gl.createTexture();
22724
22725		gl.bindTexture( type, texture );
22726		gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
22727		gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
22728
22729		for ( let i = 0; i < count; i ++ ) {
22730
22731			if ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) {
22732
22733				gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
22734
22735			} else {
22736
22737				gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
22738
22739			}
22740
22741		}
22742
22743		return texture;
22744
22745	}
22746
22747	const emptyTextures = {};
22748	emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );
22749	emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );
22750	emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 );
22751	emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 );
22752
22753	// init
22754
22755	colorBuffer.setClear( 0, 0, 0, 1 );
22756	depthBuffer.setClear( 1 );
22757	stencilBuffer.setClear( 0 );
22758
22759	enable( gl.DEPTH_TEST );
22760	depthBuffer.setFunc( LessEqualDepth );
22761
22762	setFlipSided( false );
22763	setCullFace( CullFaceBack );
22764	enable( gl.CULL_FACE );
22765
22766	setBlending( NoBlending );
22767
22768	//
22769
22770	function enable( id ) {
22771
22772		if ( enabledCapabilities[ id ] !== true ) {
22773
22774			gl.enable( id );
22775			enabledCapabilities[ id ] = true;
22776
22777		}
22778
22779	}
22780
22781	function disable( id ) {
22782
22783		if ( enabledCapabilities[ id ] !== false ) {
22784
22785			gl.disable( id );
22786			enabledCapabilities[ id ] = false;
22787
22788		}
22789
22790	}
22791
22792	function bindFramebuffer( target, framebuffer ) {
22793
22794		if ( currentBoundFramebuffers[ target ] !== framebuffer ) {
22795
22796			gl.bindFramebuffer( target, framebuffer );
22797
22798			currentBoundFramebuffers[ target ] = framebuffer;
22799
22800			// gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER
22801
22802			if ( target === gl.DRAW_FRAMEBUFFER ) {
22803
22804				currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer;
22805
22806			}
22807
22808			if ( target === gl.FRAMEBUFFER ) {
22809
22810				currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer;
22811
22812			}
22813
22814			return true;
22815
22816		}
22817
22818		return false;
22819
22820	}
22821
22822	function drawBuffers( renderTarget, framebuffer ) {
22823
22824		let drawBuffers = defaultDrawbuffers;
22825
22826		let needsUpdate = false;
22827
22828		if ( renderTarget ) {
22829
22830			drawBuffers = currentDrawbuffers.get( framebuffer );
22831
22832			if ( drawBuffers === undefined ) {
22833
22834				drawBuffers = [];
22835				currentDrawbuffers.set( framebuffer, drawBuffers );
22836
22837			}
22838
22839			const textures = renderTarget.textures;
22840
22841			if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) {
22842
22843				for ( let i = 0, il = textures.length; i < il; i ++ ) {
22844
22845					drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i;
22846
22847				}
22848
22849				drawBuffers.length = textures.length;
22850
22851				needsUpdate = true;
22852
22853			}
22854
22855		} else {
22856
22857			if ( drawBuffers[ 0 ] !== gl.BACK ) {
22858
22859				drawBuffers[ 0 ] = gl.BACK;
22860
22861				needsUpdate = true;
22862
22863			}
22864
22865		}
22866
22867		if ( needsUpdate ) {
22868
22869			gl.drawBuffers( drawBuffers );
22870
22871		}
22872
22873	}
22874
22875	function useProgram( program ) {
22876
22877		if ( currentProgram !== program ) {
22878
22879			gl.useProgram( program );
22880
22881			currentProgram = program;
22882
22883			return true;
22884
22885		}
22886
22887		return false;
22888
22889	}
22890
22891	const equationToGL = {
22892		[ AddEquation ]: gl.FUNC_ADD,
22893		[ SubtractEquation ]: gl.FUNC_SUBTRACT,
22894		[ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT
22895	};
22896
22897	equationToGL[ MinEquation ] = gl.MIN;
22898	equationToGL[ MaxEquation ] = gl.MAX;
vendor: 12,328 bytes, lines 22898-23521
22898
22899
22900	const factorToGL = {
22901		[ ZeroFactor ]: gl.ZERO,
22902		[ OneFactor ]: gl.ONE,
22903		[ SrcColorFactor ]: gl.SRC_COLOR,
22904		[ SrcAlphaFactor ]: gl.SRC_ALPHA,
22905		[ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE,
22906		[ DstColorFactor ]: gl.DST_COLOR,
22907		[ DstAlphaFactor ]: gl.DST_ALPHA,
22908		[ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR,
22909		[ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA,
22910		[ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR,
22911		[ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA,
22912		[ ConstantColorFactor ]: gl.CONSTANT_COLOR,
22913		[ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR,
22914		[ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA,
22915		[ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA
22916	};
22917
22918	function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) {
22919
22920		if ( blending === NoBlending ) {
22921
22922			if ( currentBlendingEnabled === true ) {
22923
22924				disable( gl.BLEND );
22925				currentBlendingEnabled = false;
22926
22927			}
22928
22929			return;
22930
22931		}
22932
22933		if ( currentBlendingEnabled === false ) {
22934
22935			enable( gl.BLEND );
22936			currentBlendingEnabled = true;
22937
22938		}
22939
22940		if ( blending !== CustomBlending ) {
22941
22942			if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
22943
22944				if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
22945
22946					gl.blendEquation( gl.FUNC_ADD );
22947
22948					currentBlendEquation = AddEquation;
22949					currentBlendEquationAlpha = AddEquation;
22950
22951				}
22952
22953				if ( premultipliedAlpha ) {
22954
22955					switch ( blending ) {
22956
22957						case NormalBlending:
22958							gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
22959							break;
22960
22961						case AdditiveBlending:
22962							gl.blendFunc( gl.ONE, gl.ONE );
22963							break;
22964
22965						case SubtractiveBlending:
22966							gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
22967							break;
22968
22969						case MultiplyBlending:
22970							gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
22971							break;
22972
22973						default:
22974							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
22975							break;
22976
22977					}
22978
22979				} else {
22980
22981					switch ( blending ) {
22982
22983						case NormalBlending:
22984							gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
22985							break;
22986
22987						case AdditiveBlending:
22988							gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
22989							break;
22990
22991						case SubtractiveBlending:
22992							gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
22993							break;
22994
22995						case MultiplyBlending:
22996							gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
22997							break;
22998
22999						default:
23000							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
23001							break;
23002
23003					}
23004
23005				}
23006
23007				currentBlendSrc = null;
23008				currentBlendDst = null;
23009				currentBlendSrcAlpha = null;
23010				currentBlendDstAlpha = null;
23011				currentBlendColor.set( 0, 0, 0 );
23012				currentBlendAlpha = 0;
23013
23014				currentBlending = blending;
23015				currentPremultipledAlpha = premultipliedAlpha;
23016
23017			}
23018
23019			return;
23020
23021		}
23022
23023		// custom blending
23024
23025		blendEquationAlpha = blendEquationAlpha || blendEquation;
23026		blendSrcAlpha = blendSrcAlpha || blendSrc;
23027		blendDstAlpha = blendDstAlpha || blendDst;
23028
23029		if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
23030
23031			gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
23032
23033			currentBlendEquation = blendEquation;
23034			currentBlendEquationAlpha = blendEquationAlpha;
23035
23036		}
23037
23038		if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
23039
23040			gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
23041
23042			currentBlendSrc = blendSrc;
23043			currentBlendDst = blendDst;
23044			currentBlendSrcAlpha = blendSrcAlpha;
23045			currentBlendDstAlpha = blendDstAlpha;
23046
23047		}
23048
23049		if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) {
23050
23051			gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha );
23052
23053			currentBlendColor.copy( blendColor );
23054			currentBlendAlpha = blendAlpha;
23055
23056		}
23057
23058		currentBlending = blending;
23059		currentPremultipledAlpha = false;
23060
23061	}
23062
23063	function setMaterial( material, frontFaceCW ) {
23064
23065		material.side === DoubleSide
23066			? disable( gl.CULL_FACE )
23067			: enable( gl.CULL_FACE );
23068
23069		let flipSided = ( material.side === BackSide );
23070		if ( frontFaceCW ) flipSided = ! flipSided;
23071
23072		setFlipSided( flipSided );
23073
23074		( material.blending === NormalBlending && material.transparent === false )
23075			? setBlending( NoBlending )
23076			: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha );
23077
23078		depthBuffer.setFunc( material.depthFunc );
23079		depthBuffer.setTest( material.depthTest );
23080		depthBuffer.setMask( material.depthWrite );
23081		colorBuffer.setMask( material.colorWrite );
23082
23083		const stencilWrite = material.stencilWrite;
23084		stencilBuffer.setTest( stencilWrite );
23085		if ( stencilWrite ) {
23086
23087			stencilBuffer.setMask( material.stencilWriteMask );
23088			stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
23089			stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
23090
23091		}
23092
23093		setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
23094
23095		material.alphaToCoverage === true
23096			? enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
23097			: disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
23098
23099	}
23100
23101	//
23102
23103	function setFlipSided( flipSided ) {
23104
23105		if ( currentFlipSided !== flipSided ) {
23106
23107			if ( flipSided ) {
23108
23109				gl.frontFace( gl.CW );
23110
23111			} else {
23112
23113				gl.frontFace( gl.CCW );
23114
23115			}
23116
23117			currentFlipSided = flipSided;
23118
23119		}
23120
23121	}
23122
23123	function setCullFace( cullFace ) {
23124
23125		if ( cullFace !== CullFaceNone ) {
23126
23127			enable( gl.CULL_FACE );
23128
23129			if ( cullFace !== currentCullFace ) {
23130
23131				if ( cullFace === CullFaceBack ) {
23132
23133					gl.cullFace( gl.BACK );
23134
23135				} else if ( cullFace === CullFaceFront ) {
23136
23137					gl.cullFace( gl.FRONT );
23138
23139				} else {
23140
23141					gl.cullFace( gl.FRONT_AND_BACK );
23142
23143				}
23144
23145			}
23146
23147		} else {
23148
23149			disable( gl.CULL_FACE );
23150
23151		}
23152
23153		currentCullFace = cullFace;
23154
23155	}
23156
23157	function setLineWidth( width ) {
23158
23159		if ( width !== currentLineWidth ) {
23160
23161			if ( lineWidthAvailable ) gl.lineWidth( width );
23162
23163			currentLineWidth = width;
23164
23165		}
23166
23167	}
23168
23169	function setPolygonOffset( polygonOffset, factor, units ) {
23170
23171		if ( polygonOffset ) {
23172
23173			enable( gl.POLYGON_OFFSET_FILL );
23174
23175			if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
23176
23177				gl.polygonOffset( factor, units );
23178
23179				currentPolygonOffsetFactor = factor;
23180				currentPolygonOffsetUnits = units;
23181
23182			}
23183
23184		} else {
23185
23186			disable( gl.POLYGON_OFFSET_FILL );
23187
23188		}
23189
23190	}
23191
23192	function setScissorTest( scissorTest ) {
23193
23194		if ( scissorTest ) {
23195
23196			enable( gl.SCISSOR_TEST );
23197
23198		} else {
23199
23200			disable( gl.SCISSOR_TEST );
23201
23202		}
23203
23204	}
23205
23206	// texture
23207
23208	function activeTexture( webglSlot ) {
23209
23210		if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
23211
23212		if ( currentTextureSlot !== webglSlot ) {
23213
23214			gl.activeTexture( webglSlot );
23215			currentTextureSlot = webglSlot;
23216
23217		}
23218
23219	}
23220
23221	function bindTexture( webglType, webglTexture, webglSlot ) {
23222
23223		if ( webglSlot === undefined ) {
23224
23225			if ( currentTextureSlot === null ) {
23226
23227				webglSlot = gl.TEXTURE0 + maxTextures - 1;
23228
23229			} else {
23230
23231				webglSlot = currentTextureSlot;
23232
23233			}
23234
23235		}
23236
23237		let boundTexture = currentBoundTextures[ webglSlot ];
23238
23239		if ( boundTexture === undefined ) {
23240
23241			boundTexture = { type: undefined, texture: undefined };
23242			currentBoundTextures[ webglSlot ] = boundTexture;
23243
23244		}
23245
23246		if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
23247
23248			if ( currentTextureSlot !== webglSlot ) {
23249
23250				gl.activeTexture( webglSlot );
23251				currentTextureSlot = webglSlot;
23252
23253			}
23254
23255			gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
23256
23257			boundTexture.type = webglType;
23258			boundTexture.texture = webglTexture;
23259
23260		}
23261
23262	}
23263
23264	function unbindTexture() {
23265
23266		const boundTexture = currentBoundTextures[ currentTextureSlot ];
23267
23268		if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
23269
23270			gl.bindTexture( boundTexture.type, null );
23271
23272			boundTexture.type = undefined;
23273			boundTexture.texture = undefined;
23274
23275		}
23276
23277	}
23278
23279	function compressedTexImage2D() {
23280
23281		try {
23282
23283			gl.compressedTexImage2D.apply( gl, arguments );
23284
23285		} catch ( error ) {
23286
23287			console.error( 'THREE.WebGLState:', error );
23288
23289		}
23290
23291	}
23292
23293	function compressedTexImage3D() {
23294
23295		try {
23296
23297			gl.compressedTexImage3D.apply( gl, arguments );
23298
23299		} catch ( error ) {
23300
23301			console.error( 'THREE.WebGLState:', error );
23302
23303		}
23304
23305	}
23306
23307	function texSubImage2D() {
23308
23309		try {
23310
23311			gl.texSubImage2D.apply( gl, arguments );
23312
23313		} catch ( error ) {
23314
23315			console.error( 'THREE.WebGLState:', error );
23316
23317		}
23318
23319	}
23320
23321	function texSubImage3D() {
23322
23323		try {
23324
23325			gl.texSubImage3D.apply( gl, arguments );
23326
23327		} catch ( error ) {
23328
23329			console.error( 'THREE.WebGLState:', error );
23330
23331		}
23332
23333	}
23334
23335	function compressedTexSubImage2D() {
23336
23337		try {
23338
23339			gl.compressedTexSubImage2D.apply( gl, arguments );
23340
23341		} catch ( error ) {
23342
23343			console.error( 'THREE.WebGLState:', error );
23344
23345		}
23346
23347	}
23348
23349	function compressedTexSubImage3D() {
23350
23351		try {
23352
23353			gl.compressedTexSubImage3D.apply( gl, arguments );
23354
23355		} catch ( error ) {
23356
23357			console.error( 'THREE.WebGLState:', error );
23358
23359		}
23360
23361	}
23362
23363	function texStorage2D() {
23364
23365		try {
23366
23367			gl.texStorage2D.apply( gl, arguments );
23368
23369		} catch ( error ) {
23370
23371			console.error( 'THREE.WebGLState:', error );
23372
23373		}
23374
23375	}
23376
23377	function texStorage3D() {
23378
23379		try {
23380
23381			gl.texStorage3D.apply( gl, arguments );
23382
23383		} catch ( error ) {
23384
23385			console.error( 'THREE.WebGLState:', error );
23386
23387		}
23388
23389	}
23390
23391	function texImage2D() {
23392
23393		try {
23394
23395			gl.texImage2D.apply( gl, arguments );
23396
23397		} catch ( error ) {
23398
23399			console.error( 'THREE.WebGLState:', error );
23400
23401		}
23402
23403	}
23404
23405	function texImage3D() {
23406
23407		try {
23408
23409			gl.texImage3D.apply( gl, arguments );
23410
23411		} catch ( error ) {
23412
23413			console.error( 'THREE.WebGLState:', error );
23414
23415		}
23416
23417	}
23418
23419	//
23420
23421	function scissor( scissor ) {
23422
23423		if ( currentScissor.equals( scissor ) === false ) {
23424
23425			gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
23426			currentScissor.copy( scissor );
23427
23428		}
23429
23430	}
23431
23432	function viewport( viewport ) {
23433
23434		if ( currentViewport.equals( viewport ) === false ) {
23435
23436			gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
23437			currentViewport.copy( viewport );
23438
23439		}
23440
23441	}
23442
23443	function updateUBOMapping( uniformsGroup, program ) {
23444
23445		let mapping = uboProgramMap.get( program );
23446
23447		if ( mapping === undefined ) {
23448
23449			mapping = new WeakMap();
23450
23451			uboProgramMap.set( program, mapping );
23452
23453		}
23454
23455		let blockIndex = mapping.get( uniformsGroup );
23456
23457		if ( blockIndex === undefined ) {
23458
23459			blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name );
23460
23461			mapping.set( uniformsGroup, blockIndex );
23462
23463		}
23464
23465	}
23466
23467	function uniformBlockBinding( uniformsGroup, program ) {
23468
23469		const mapping = uboProgramMap.get( program );
23470		const blockIndex = mapping.get( uniformsGroup );
23471
23472		if ( uboBindings.get( program ) !== blockIndex ) {
23473
23474			// bind shader specific block index to global block point
23475			gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex );
23476
23477			uboBindings.set( program, blockIndex );
23478
23479		}
23480
23481	}
23482
23483	//
23484
23485	function reset() {
23486
23487		// reset state
23488
23489		gl.disable( gl.BLEND );
23490		gl.disable( gl.CULL_FACE );
23491		gl.disable( gl.DEPTH_TEST );
23492		gl.disable( gl.POLYGON_OFFSET_FILL );
23493		gl.disable( gl.SCISSOR_TEST );
23494		gl.disable( gl.STENCIL_TEST );
23495		gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
23496
23497		gl.blendEquation( gl.FUNC_ADD );
23498		gl.blendFunc( gl.ONE, gl.ZERO );
23499		gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO );
23500		gl.blendColor( 0, 0, 0, 0 );
23501
23502		gl.colorMask( true, true, true, true );
23503		gl.clearColor( 0, 0, 0, 0 );
23504
23505		gl.depthMask( true );
23506		gl.depthFunc( gl.LESS );
23507		gl.clearDepth( 1 );
23508
23509		gl.stencilMask( 0xffffffff );
23510		gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff );
23511		gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP );
23512		gl.clearStencil( 0 );
23513
23514		gl.cullFace( gl.BACK );
23515		gl.frontFace( gl.CCW );
23516
23517		gl.polygonOffset( 0, 0 );
23518
23519		gl.activeTexture( gl.TEXTURE0 );
23520
23521		gl.bindFramebuffer( gl.FRAMEBUFFER, null );
vendor: 4,512 bytes, lines 23522-23694
23522		gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null );
23523		gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
23524
23525		gl.useProgram( null );
23526
23527		gl.lineWidth( 1 );
23528
23529		gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height );
23530		gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height );
23531
23532		// reset internals
23533
23534		enabledCapabilities = {};
23535
23536		currentTextureSlot = null;
23537		currentBoundTextures = {};
23538
23539		currentBoundFramebuffers = {};
23540		currentDrawbuffers = new WeakMap();
23541		defaultDrawbuffers = [];
23542
23543		currentProgram = null;
23544
23545		currentBlendingEnabled = false;
23546		currentBlending = null;
23547		currentBlendEquation = null;
23548		currentBlendSrc = null;
23549		currentBlendDst = null;
23550		currentBlendEquationAlpha = null;
23551		currentBlendSrcAlpha = null;
23552		currentBlendDstAlpha = null;
23553		currentBlendColor = new Color( 0, 0, 0 );
23554		currentBlendAlpha = 0;
23555		currentPremultipledAlpha = false;
23556
23557		currentFlipSided = null;
23558		currentCullFace = null;
23559
23560		currentLineWidth = null;
23561
23562		currentPolygonOffsetFactor = null;
23563		currentPolygonOffsetUnits = null;
23564
23565		currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height );
23566		currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height );
23567
23568		colorBuffer.reset();
23569		depthBuffer.reset();
23570		stencilBuffer.reset();
23571
23572	}
23573
23574	return {
23575
23576		buffers: {
23577			color: colorBuffer,
23578			depth: depthBuffer,
23579			stencil: stencilBuffer
23580		},
23581
23582		enable: enable,
23583		disable: disable,
23584
23585		bindFramebuffer: bindFramebuffer,
23586		drawBuffers: drawBuffers,
23587
23588		useProgram: useProgram,
23589
23590		setBlending: setBlending,
23591		setMaterial: setMaterial,
23592
23593		setFlipSided: setFlipSided,
23594		setCullFace: setCullFace,
23595
23596		setLineWidth: setLineWidth,
23597		setPolygonOffset: setPolygonOffset,
23598
23599		setScissorTest: setScissorTest,
23600
23601		activeTexture: activeTexture,
23602		bindTexture: bindTexture,
23603		unbindTexture: unbindTexture,
23604		compressedTexImage2D: compressedTexImage2D,
23605		compressedTexImage3D: compressedTexImage3D,
23606		texImage2D: texImage2D,
23607		texImage3D: texImage3D,
23608
23609		updateUBOMapping: updateUBOMapping,
23610		uniformBlockBinding: uniformBlockBinding,
23611
23612		texStorage2D: texStorage2D,
23613		texStorage3D: texStorage3D,
23614		texSubImage2D: texSubImage2D,
23615		texSubImage3D: texSubImage3D,
23616		compressedTexSubImage2D: compressedTexSubImage2D,
23617		compressedTexSubImage3D: compressedTexSubImage3D,
23618
23619		scissor: scissor,
23620		viewport: viewport,
23621
23622		reset: reset
23623
23624	};
23625
23626}
23627
23628function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
23629
23630	const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null;
23631	const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent );
23632
23633	const _imageDimensions = new Vector2();
23634	const _videoTextures = new WeakMap();
23635	let _canvas;
23636
23637	const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source
23638
23639	// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
23640	// also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
23641	// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
23642
23643	let useOffscreenCanvas = false;
23644
23645	try {
23646
23647		useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
23648			// eslint-disable-next-line compat/compat
23649			&& ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
23650
23651	} catch ( err ) {
23652
23653		// Ignore any errors
23654
23655	}
23656
23657	function createCanvas( width, height ) {
23658
23659		// Use OffscreenCanvas when available. Specially needed in web workers
23660
23661		return useOffscreenCanvas ?
23662			// eslint-disable-next-line compat/compat
23663			new OffscreenCanvas( width, height ) : createElementNS( 'canvas' );
23664
23665	}
23666
23667	function resizeImage( image, needsNewCanvas, maxSize ) {
23668
23669		let scale = 1;
23670
23671		const dimensions = getDimensions( image );
23672
23673		// handle case if texture exceeds max size
23674
23675		if ( dimensions.width > maxSize || dimensions.height > maxSize ) {
23676
23677			scale = maxSize / Math.max( dimensions.width, dimensions.height );
23678
23679		}
23680
23681		// only perform resize if necessary
23682
23683		if ( scale < 1 ) {
23684
23685			// only perform resize for certain image types
23686
23687			if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
23688				( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
23689				( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ||
23690				( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) ) {
23691
23692				const width = Math.floor( scale * dimensions.width );
23693				const height = Math.floor( scale * dimensions.height );
23694
vendor: 14,080 bytes, lines 23695-24210
23695				if ( _canvas === undefined ) _canvas = createCanvas( width, height );
23696
23697				// cube textures can't reuse the same canvas
23698
23699				const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
23700
23701				canvas.width = width;
23702				canvas.height = height;
23703
23704				const context = canvas.getContext( '2d' );
23705				context.drawImage( image, 0, 0, width, height );
23706
23707				console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' );
23708
23709				return canvas;
23710
23711			} else {
23712
23713				if ( 'data' in image ) {
23714
23715					console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' );
23716
23717				}
23718
23719				return image;
23720
23721			}
23722
23723		}
23724
23725		return image;
23726
23727	}
23728
23729	function textureNeedsGenerateMipmaps( texture ) {
23730
23731		return texture.generateMipmaps && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
23732
23733	}
23734
23735	function generateMipmap( target ) {
23736
23737		_gl.generateMipmap( target );
23738
23739	}
23740
23741	function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) {
23742
23743		if ( internalFormatName !== null ) {
23744
23745			if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
23746
23747			console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
23748
23749		}
23750
23751		let internalFormat = glFormat;
23752
23753		if ( glFormat === _gl.RED ) {
23754
23755			if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F;
23756			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F;
23757			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8;
23758
23759		}
23760
23761		if ( glFormat === _gl.RED_INTEGER ) {
23762
23763			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI;
23764			if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI;
23765			if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI;
23766			if ( glType === _gl.BYTE ) internalFormat = _gl.R8I;
23767			if ( glType === _gl.SHORT ) internalFormat = _gl.R16I;
23768			if ( glType === _gl.INT ) internalFormat = _gl.R32I;
23769
23770		}
23771
23772		if ( glFormat === _gl.RG ) {
23773
23774			if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F;
23775			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F;
23776			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8;
23777
23778		}
23779
23780		if ( glFormat === _gl.RG_INTEGER ) {
23781
23782			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8UI;
23783			if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RG16UI;
23784			if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RG32UI;
23785			if ( glType === _gl.BYTE ) internalFormat = _gl.RG8I;
23786			if ( glType === _gl.SHORT ) internalFormat = _gl.RG16I;
23787			if ( glType === _gl.INT ) internalFormat = _gl.RG32I;
23788
23789		}
23790
23791		if ( glFormat === _gl.RGB ) {
23792
23793			if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5;
23794
23795		}
23796
23797		if ( glFormat === _gl.RGBA ) {
23798
23799			const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace );
23800
23801			if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F;
23802			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F;
23803			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8;
23804			if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4;
23805			if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1;
23806
23807		}
23808
23809		if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F ||
23810			internalFormat === _gl.RG16F || internalFormat === _gl.RG32F ||
23811			internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) {
23812
23813			extensions.get( 'EXT_color_buffer_float' );
23814
23815		}
23816
23817		return internalFormat;
23818
23819	}
23820
23821	function getMipLevels( texture, image ) {
23822
23823		if ( textureNeedsGenerateMipmaps( texture ) === true || ( texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) {
23824
23825			return Math.log2( Math.max( image.width, image.height ) ) + 1;
23826
23827		} else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) {
23828
23829			// user-defined mipmaps
23830
23831			return texture.mipmaps.length;
23832
23833		} else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) {
23834
23835			return image.mipmaps.length;
23836
23837		} else {
23838
23839			// texture without mipmaps (only base level)
23840
23841			return 1;
23842
23843		}
23844
23845	}
23846
23847	//
23848
23849	function onTextureDispose( event ) {
23850
23851		const texture = event.target;
23852
23853		texture.removeEventListener( 'dispose', onTextureDispose );
23854
23855		deallocateTexture( texture );
23856
23857		if ( texture.isVideoTexture ) {
23858
23859			_videoTextures.delete( texture );
23860
23861		}
23862
23863	}
23864
23865	function onRenderTargetDispose( event ) {
23866
23867		const renderTarget = event.target;
23868
23869		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
23870
23871		deallocateRenderTarget( renderTarget );
23872
23873	}
23874
23875	//
23876
23877	function deallocateTexture( texture ) {
23878
23879		const textureProperties = properties.get( texture );
23880
23881		if ( textureProperties.__webglInit === undefined ) return;
23882
23883		// check if it's necessary to remove the WebGLTexture object
23884
23885		const source = texture.source;
23886		const webglTextures = _sources.get( source );
23887
23888		if ( webglTextures ) {
23889
23890			const webglTexture = webglTextures[ textureProperties.__cacheKey ];
23891			webglTexture.usedTimes --;
23892
23893			// the WebGLTexture object is not used anymore, remove it
23894
23895			if ( webglTexture.usedTimes === 0 ) {
23896
23897				deleteTexture( texture );
23898
23899			}
23900
23901			// remove the weak map entry if no WebGLTexture uses the source anymore
23902
23903			if ( Object.keys( webglTextures ).length === 0 ) {
23904
23905				_sources.delete( source );
23906
23907			}
23908
23909		}
23910
23911		properties.remove( texture );
23912
23913	}
23914
23915	function deleteTexture( texture ) {
23916
23917		const textureProperties = properties.get( texture );
23918		_gl.deleteTexture( textureProperties.__webglTexture );
23919
23920		const source = texture.source;
23921		const webglTextures = _sources.get( source );
23922		delete webglTextures[ textureProperties.__cacheKey ];
23923
23924		info.memory.textures --;
23925
23926	}
23927
23928	function deallocateRenderTarget( renderTarget ) {
23929
23930		const renderTargetProperties = properties.get( renderTarget );
23931
23932		if ( renderTarget.depthTexture ) {
23933
23934			renderTarget.depthTexture.dispose();
23935
23936		}
23937
23938		if ( renderTarget.isWebGLCubeRenderTarget ) {
23939
23940			for ( let i = 0; i < 6; i ++ ) {
23941
23942				if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) {
23943
23944					for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] );
23945
23946				} else {
23947
23948					_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
23949
23950				}
23951
23952				if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
23953
23954			}
23955
23956		} else {
23957
23958			if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) {
23959
23960				for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] );
23961
23962			} else {
23963
23964				_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
23965
23966			}
23967
23968			if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
23969			if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
23970
23971			if ( renderTargetProperties.__webglColorRenderbuffer ) {
23972
23973				for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) {
23974
23975					if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] );
23976
23977				}
23978
23979			}
23980
23981			if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
23982
23983		}
23984
23985		const textures = renderTarget.textures;
23986
23987		for ( let i = 0, il = textures.length; i < il; i ++ ) {
23988
23989			const attachmentProperties = properties.get( textures[ i ] );
23990
23991			if ( attachmentProperties.__webglTexture ) {
23992
23993				_gl.deleteTexture( attachmentProperties.__webglTexture );
23994
23995				info.memory.textures --;
23996
23997			}
23998
23999			properties.remove( textures[ i ] );
24000
24001		}
24002
24003		properties.remove( renderTarget );
24004
24005	}
24006
24007	//
24008
24009	let textureUnits = 0;
24010
24011	function resetTextureUnits() {
24012
24013		textureUnits = 0;
24014
24015	}
24016
24017	function allocateTextureUnit() {
24018
24019		const textureUnit = textureUnits;
24020
24021		if ( textureUnit >= capabilities.maxTextures ) {
24022
24023			console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
24024
24025		}
24026
24027		textureUnits += 1;
24028
24029		return textureUnit;
24030
24031	}
24032
24033	function getTextureCacheKey( texture ) {
24034
24035		const array = [];
24036
24037		array.push( texture.wrapS );
24038		array.push( texture.wrapT );
24039		array.push( texture.wrapR || 0 );
24040		array.push( texture.magFilter );
24041		array.push( texture.minFilter );
24042		array.push( texture.anisotropy );
24043		array.push( texture.internalFormat );
24044		array.push( texture.format );
24045		array.push( texture.type );
24046		array.push( texture.generateMipmaps );
24047		array.push( texture.premultiplyAlpha );
24048		array.push( texture.flipY );
24049		array.push( texture.unpackAlignment );
24050		array.push( texture.colorSpace );
24051
24052		return array.join();
24053
24054	}
24055
24056	//
24057
24058	function setTexture2D( texture, slot ) {
24059
24060		const textureProperties = properties.get( texture );
24061
24062		if ( texture.isVideoTexture ) updateVideoTexture( texture );
24063
24064		if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) {
24065
24066			const image = texture.image;
24067
24068			if ( image === null ) {
24069
24070				console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' );
24071
24072			} else if ( image.complete === false ) {
24073
24074				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
24075
24076			} else {
24077
24078				uploadTexture( textureProperties, texture, slot );
24079				return;
24080
24081			}
24082
24083		}
24084
24085		state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24086
24087	}
24088
24089	function setTexture2DArray( texture, slot ) {
24090
24091		const textureProperties = properties.get( texture );
24092
24093		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24094
24095			uploadTexture( textureProperties, texture, slot );
24096			return;
24097
24098		}
24099
24100		state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24101
24102	}
24103
24104	function setTexture3D( texture, slot ) {
24105
24106		const textureProperties = properties.get( texture );
24107
24108		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24109
24110			uploadTexture( textureProperties, texture, slot );
24111			return;
24112
24113		}
24114
24115		state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24116
24117	}
24118
24119	function setTextureCube( texture, slot ) {
24120
24121		const textureProperties = properties.get( texture );
24122
24123		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24124
24125			uploadCubeTexture( textureProperties, texture, slot );
24126			return;
24127
24128		}
24129
24130		state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24131
24132	}
24133
24134	const wrappingToGL = {
24135		[ RepeatWrapping ]: _gl.REPEAT,
24136		[ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE,
24137		[ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT
24138	};
24139
24140	const filterToGL = {
24141		[ NearestFilter ]: _gl.NEAREST,
24142		[ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST,
24143		[ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR,
24144
24145		[ LinearFilter ]: _gl.LINEAR,
24146		[ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST,
24147		[ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR
24148	};
24149
24150	const compareToGL = {
24151		[ NeverCompare ]: _gl.NEVER,
24152		[ AlwaysCompare ]: _gl.ALWAYS,
24153		[ LessCompare ]: _gl.LESS,
24154		[ LessEqualCompare ]: _gl.LEQUAL,
24155		[ EqualCompare ]: _gl.EQUAL,
24156		[ GreaterEqualCompare ]: _gl.GEQUAL,
24157		[ GreaterCompare ]: _gl.GREATER,
24158		[ NotEqualCompare ]: _gl.NOTEQUAL
24159	};
24160
24161	function setTextureParameters( textureType, texture ) {
24162
24163		if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false &&
24164			( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter ||
24165			texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) {
24166
24167			console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' );
24168
24169		}
24170
24171		_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] );
24172		_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] );
24173
24174		if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {
24175
24176			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] );
24177
24178		}
24179
24180		_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] );
24181		_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] );
24182
24183		if ( texture.compareFunction ) {
24184
24185			_gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE );
24186			_gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] );
24187
24188		}
24189
24190		if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
24191
24192			if ( texture.magFilter === NearestFilter ) return;
24193			if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return;
24194			if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension
24195
24196			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
24197
24198				const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
24199				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
24200				properties.get( texture ).__currentAnisotropy = texture.anisotropy;
24201
24202			}
24203
24204		}
24205
24206	}
24207
24208	function initTexture( textureProperties, texture ) {
24209
24210		let forceUpload = false;
vendor: 4,815 bytes, lines 24211-24375
24211
24212		if ( textureProperties.__webglInit === undefined ) {
24213
24214			textureProperties.__webglInit = true;
24215
24216			texture.addEventListener( 'dispose', onTextureDispose );
24217
24218		}
24219
24220		// create Source <-> WebGLTextures mapping if necessary
24221
24222		const source = texture.source;
24223		let webglTextures = _sources.get( source );
24224
24225		if ( webglTextures === undefined ) {
24226
24227			webglTextures = {};
24228			_sources.set( source, webglTextures );
24229
24230		}
24231
24232		// check if there is already a WebGLTexture object for the given texture parameters
24233
24234		const textureCacheKey = getTextureCacheKey( texture );
24235
24236		if ( textureCacheKey !== textureProperties.__cacheKey ) {
24237
24238			// if not, create a new instance of WebGLTexture
24239
24240			if ( webglTextures[ textureCacheKey ] === undefined ) {
24241
24242				// create new entry
24243
24244				webglTextures[ textureCacheKey ] = {
24245					texture: _gl.createTexture(),
24246					usedTimes: 0
24247				};
24248
24249				info.memory.textures ++;
24250
24251				// when a new instance of WebGLTexture was created, a texture upload is required
24252				// even if the image contents are identical
24253
24254				forceUpload = true;
24255
24256			}
24257
24258			webglTextures[ textureCacheKey ].usedTimes ++;
24259
24260			// every time the texture cache key changes, it's necessary to check if an instance of
24261			// WebGLTexture can be deleted in order to avoid a memory leak.
24262
24263			const webglTexture = webglTextures[ textureProperties.__cacheKey ];
24264
24265			if ( webglTexture !== undefined ) {
24266
24267				webglTextures[ textureProperties.__cacheKey ].usedTimes --;
24268
24269				if ( webglTexture.usedTimes === 0 ) {
24270
24271					deleteTexture( texture );
24272
24273				}
24274
24275			}
24276
24277			// store references to cache key and WebGLTexture object
24278
24279			textureProperties.__cacheKey = textureCacheKey;
24280			textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture;
24281
24282		}
24283
24284		return forceUpload;
24285
24286	}
24287
24288	function uploadTexture( textureProperties, texture, slot ) {
24289
24290		let textureType = _gl.TEXTURE_2D;
24291
24292		if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY;
24293		if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D;
24294
24295		const forceUpload = initTexture( textureProperties, texture );
24296		const source = texture.source;
24297
24298		state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24299
24300		const sourceProperties = properties.get( source );
24301
24302		if ( source.version !== sourceProperties.__version || forceUpload === true ) {
24303
24304			state.activeTexture( _gl.TEXTURE0 + slot );
24305
24306			const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
24307			const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
24308			const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
24309
24310			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
24311			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
24312			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
24313			_gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
24314
24315			let image = resizeImage( texture.image, false, capabilities.maxTextureSize );
24316			image = verifyColorSpace( texture, image );
24317
24318			const glFormat = utils.convert( texture.format, texture.colorSpace );
24319
24320			const glType = utils.convert( texture.type );
24321			let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture );
24322
24323			setTextureParameters( textureType, texture );
24324
24325			let mipmap;
24326			const mipmaps = texture.mipmaps;
24327
24328			const useTexStorage = ( texture.isVideoTexture !== true && glInternalFormat !== RGB_ETC1_Format );
24329			const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
24330			const dataReady = source.dataReady;
24331			const levels = getMipLevels( texture, image );
24332
24333			if ( texture.isDepthTexture ) {
24334
24335				// populate depth texture with dummy data
24336
24337				glInternalFormat = _gl.DEPTH_COMPONENT16;
24338
24339				if ( texture.type === FloatType ) {
24340
24341					glInternalFormat = _gl.DEPTH_COMPONENT32F;
24342
24343				} else if ( texture.type === UnsignedIntType ) {
24344
24345					glInternalFormat = _gl.DEPTH_COMPONENT24;
24346
24347				} else if ( texture.type === UnsignedInt248Type ) {
24348
24349					glInternalFormat = _gl.DEPTH24_STENCIL8;
24350
24351				}
24352
24353				//
24354
24355				if ( allocateMemory ) {
24356
24357					if ( useTexStorage ) {
24358
24359						state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height );
24360
24361					} else {
24362
24363						state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
24364
24365					}
24366
24367				}
24368
24369			} else if ( texture.isDataTexture ) {
24370
24371				// use manually created mipmaps if available
24372				// if there are no manual mipmaps
24373				// set 0 level mipmap and then use GL to generate other mipmap levels
24374
24375				if ( mipmaps.length > 0
vendor: 5,625 bytes, lines 24375-24622
24375 ) {
24376
24377					if ( useTexStorage && allocateMemory ) {
24378
24379						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
24380
24381					}
24382
24383					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24384
24385						mipmap = mipmaps[ i ];
24386
24387						if ( useTexStorage ) {
24388
24389							if ( dataReady ) {
24390
24391								state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
24392
24393							}
24394
24395						} else {
24396
24397							state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24398
24399						}
24400
24401					}
24402
24403					texture.generateMipmaps = false;
24404
24405				} else {
24406
24407					if ( useTexStorage ) {
24408
24409						if ( allocateMemory ) {
24410
24411							state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
24412
24413						}
24414
24415						if ( dataReady ) {
24416
24417							state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
24418
24419						}
24420
24421					} else {
24422
24423						state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
24424
24425					}
24426
24427				}
24428
24429			} else if ( texture.isCompressedTexture ) {
24430
24431				if ( texture.isCompressedArrayTexture ) {
24432
24433					if ( useTexStorage && allocateMemory ) {
24434
24435						state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth );
24436
24437					}
24438
24439					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24440
24441						mipmap = mipmaps[ i ];
24442
24443						if ( texture.format !== RGBAFormat ) {
24444
24445							if ( glFormat !== null ) {
24446
24447								if ( useTexStorage ) {
24448
24449									if ( dataReady ) {
24450
24451										state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 );
24452
24453									}
24454
24455								} else {
24456
24457									state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 );
24458
24459								}
24460
24461							} else {
24462
24463								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
24464
24465							}
24466
24467						} else {
24468
24469							if ( useTexStorage ) {
24470
24471								if ( dataReady ) {
24472
24473									state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data );
24474
24475								}
24476
24477							} else {
24478
24479								state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data );
24480
24481							}
24482
24483						}
24484
24485					}
24486
24487				} else {
24488
24489					if ( useTexStorage && allocateMemory ) {
24490
24491						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
24492
24493					}
24494
24495					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24496
24497						mipmap = mipmaps[ i ];
24498
24499						if ( texture.format !== RGBAFormat ) {
24500
24501							if ( glFormat !== null ) {
24502
24503								if ( useTexStorage ) {
24504
24505									if ( dataReady ) {
24506
24507										state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
24508
24509									}
24510
24511								} else {
24512
24513									state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24514
24515								}
24516
24517							} else {
24518
24519								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
24520
24521							}
24522
24523						} else {
24524
24525							if ( useTexStorage ) {
24526
24527								if ( dataReady ) {
24528
24529									state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
24530
24531								}
24532
24533							} else {
24534
24535								state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24536
24537							}
24538
24539						}
24540
24541					}
24542
24543				}
24544
24545			} else if ( texture.isDataArrayTexture ) {
24546
24547				if ( useTexStorage ) {
24548
24549					if ( allocateMemory ) {
24550
24551						state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth );
24552
24553					}
24554
24555					if ( dataReady ) {
24556
24557						state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
24558
24559					}
24560
24561				} else {
24562
24563					state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
24564
24565				}
24566
24567			} else if ( texture.isData3DTexture ) {
24568
24569				if ( useTexStorage ) {
24570
24571					if ( allocateMemory ) {
24572
24573						state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth );
24574
24575					}
24576
24577					if ( dataReady ) {
24578
24579						state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
24580
24581					}
24582
24583				} else {
24584
24585					state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
24586
24587				}
24588
24589			} else if ( texture.isFramebufferTexture ) {
24590
24591				if ( allocateMemory ) {
24592
24593					if ( useTexStorage ) {
24594
24595						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
24596
24597					} else {
24598
24599						let width = image.width, height = image.height;
24600
24601						for ( let i = 0; i < levels; i ++ ) {
24602
24603							state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null );
24604
24605							width >>= 1;
24606							height >>= 1;
24607
24608						}
24609
24610					}
24611
24612				}
24613
24614			} else {
24615
24616				// regular Texture (image, video, canvas)
24617
24618				// use manually created mipmaps if available
24619				// if there are no manual mipmaps
24620				// set 0 level mipmap and then use GL to generate other mipmap levels
24621
24622				if ( mipmaps.length > 0 
vendor: 7,841 bytes, lines 24622-24936
24622) {
24623
24624					if ( useTexStorage && allocateMemory ) {
24625
24626						const dimensions = getDimensions( mipmaps[ 0 ] );
24627
24628						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height );
24629
24630					}
24631
24632					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24633
24634						mipmap = mipmaps[ i ];
24635
24636						if ( useTexStorage ) {
24637
24638							if ( dataReady ) {
24639
24640								state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap );
24641
24642							}
24643
24644						} else {
24645
24646							state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
24647
24648						}
24649
24650					}
24651
24652					texture.generateMipmaps = false;
24653
24654				} else {
24655
24656					if ( useTexStorage ) {
24657
24658						if ( allocateMemory ) {
24659
24660							const dimensions = getDimensions( image );
24661
24662							state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height );
24663
24664						}
24665
24666						if ( dataReady ) {
24667
24668							state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image );
24669
24670						}
24671
24672					} else {
24673
24674						state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
24675
24676					}
24677
24678				}
24679
24680			}
24681
24682			if ( textureNeedsGenerateMipmaps( texture ) ) {
24683
24684				generateMipmap( textureType );
24685
24686			}
24687
24688			sourceProperties.__version = source.version;
24689
24690			if ( texture.onUpdate ) texture.onUpdate( texture );
24691
24692		}
24693
24694		textureProperties.__version = texture.version;
24695
24696	}
24697
24698	function uploadCubeTexture( textureProperties, texture, slot ) {
24699
24700		if ( texture.image.length !== 6 ) return;
24701
24702		const forceUpload = initTexture( textureProperties, texture );
24703		const source = texture.source;
24704
24705		state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24706
24707		const sourceProperties = properties.get( source );
24708
24709		if ( source.version !== sourceProperties.__version || forceUpload === true ) {
24710
24711			state.activeTexture( _gl.TEXTURE0 + slot );
24712
24713			const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
24714			const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
24715			const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
24716
24717			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
24718			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
24719			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
24720			_gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
24721
24722			const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture );
24723			const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
24724
24725			const cubeImage = [];
24726
24727			for ( let i = 0; i < 6; i ++ ) {
24728
24729				if ( ! isCompressed && ! isDataTexture ) {
24730
24731					cubeImage[ i ] = resizeImage( texture.image[ i ], true, capabilities.maxCubemapSize );
24732
24733				} else {
24734
24735					cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
24736
24737				}
24738
24739				cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] );
24740
24741			}
24742
24743			const image = cubeImage[ 0 ],
24744				glFormat = utils.convert( texture.format, texture.colorSpace ),
24745				glType = utils.convert( texture.type ),
24746				glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
24747
24748			const useTexStorage = ( texture.isVideoTexture !== true );
24749			const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
24750			const dataReady = source.dataReady;
24751			let levels = getMipLevels( texture, image );
24752
24753			setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture );
24754
24755			let mipmaps;
24756
24757			if ( isCompressed ) {
24758
24759				if ( useTexStorage && allocateMemory ) {
24760
24761					state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height );
24762
24763				}
24764
24765				for ( let i = 0; i < 6; i ++ ) {
24766
24767					mipmaps = cubeImage[ i ].mipmaps;
24768
24769					for ( let j = 0; j < mipmaps.length; j ++ ) {
24770
24771						const mipmap = mipmaps[ j ];
24772
24773						if ( texture.format !== RGBAFormat ) {
24774
24775							if ( glFormat !== null ) {
24776
24777								if ( useTexStorage ) {
24778
24779									if ( dataReady ) {
24780
24781										state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
24782
24783									}
24784
24785								} else {
24786
24787									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24788
24789								}
24790
24791							} else {
24792
24793								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
24794
24795							}
24796
24797						} else {
24798
24799							if ( useTexStorage ) {
24800
24801								if ( dataReady ) {
24802
24803									state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
24804
24805								}
24806
24807							} else {
24808
24809								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24810
24811							}
24812
24813						}
24814
24815					}
24816
24817				}
24818
24819			} else {
24820
24821				mipmaps = texture.mipmaps;
24822
24823				if ( useTexStorage && allocateMemory ) {
24824
24825					// TODO: Uniformly handle mipmap definitions
24826					// Normal textures and compressed cube textures define base level + mips with their mipmap array
24827					// Uncompressed cube textures use their mipmap array only for mips (no base level)
24828
24829					if ( mipmaps.length > 0 ) levels ++;
24830
24831					const dimensions = getDimensions( cubeImage[ 0 ] );
24832
24833					state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, dimensions.width, dimensions.height );
24834
24835				}
24836
24837				for ( let i = 0; i < 6; i ++ ) {
24838
24839					if ( isDataTexture ) {
24840
24841						if ( useTexStorage ) {
24842
24843							if ( dataReady ) {
24844
24845								state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data );
24846
24847							}
24848
24849						} else {
24850
24851							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
24852
24853						}
24854
24855						for ( let j = 0; j < mipmaps.length; j ++ ) {
24856
24857							const mipmap = mipmaps[ j ];
24858							const mipmapImage = mipmap.image[ i ].image;
24859
24860							if ( useTexStorage ) {
24861
24862								if ( dataReady ) {
24863
24864									state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data );
24865
24866								}
24867
24868							} else {
24869
24870								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
24871
24872							}
24873
24874						}
24875
24876					} else {
24877
24878						if ( useTexStorage ) {
24879
24880							if ( dataReady ) {
24881
24882								state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] );
24883
24884							}
24885
24886						} else {
24887
24888							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
24889
24890						}
24891
24892						for ( let j = 0; j < mipmaps.length; j ++ ) {
24893
24894							const mipmap = mipmaps[ j ];
24895
24896							if ( useTexStorage ) {
24897
24898								if ( dataReady ) {
24899
24900									state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] );
24901
24902								}
24903
24904							} else {
24905
24906								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
24907
24908							}
24909
24910						}
24911
24912					}
24913
24914				}
24915
24916			}
24917
24918			if ( textureNeedsGenerateMipmaps( texture ) ) {
24919
24920				// We assume images for cube map have the same size.
24921				generateMipmap( _gl.TEXTURE_CUBE_MAP );
24922
24923			}
24924
24925			sourceProperties.__version = source.version;
24926
24927			if ( texture.onUpdate ) texture.onUpdate( texture );
24928
24929		}
24930
24931		textureProperties.__version = texture.version;
24932
24933	}
24934
24935	// Render targets
24936
vendor: 10,864 bytes, lines 24937-25295
24937	// Setup storage for target texture and bind it to correct framebuffer
24938	function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) {
24939
24940		const glFormat = utils.convert( texture.format, texture.colorSpace );
24941		const glType = utils.convert( texture.type );
24942		const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
24943		const renderTargetProperties = properties.get( renderTarget );
24944
24945		if ( ! renderTargetProperties.__hasExternalTextures ) {
24946
24947			const width = Math.max( 1, renderTarget.width >> level );
24948			const height = Math.max( 1, renderTarget.height >> level );
24949
24950			if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) {
24951
24952				state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null );
24953
24954			} else {
24955
24956				state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null );
24957
24958			}
24959
24960		}
24961
24962		state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
24963
24964		if ( useMultisampledRTT( renderTarget ) ) {
24965
24966			multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) );
24967
24968		} else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753
24969
24970			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level );
24971
24972		}
24973
24974		state.bindFramebuffer( _gl.FRAMEBUFFER, null );
24975
24976	}
24977
24978
24979	// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
24980	function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
24981
24982		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
24983
24984		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
24985
24986			let glInternalFormat = _gl.DEPTH_COMPONENT24;
24987
24988			if ( isMultisample || useMultisampledRTT( renderTarget ) ) {
24989
24990				const depthTexture = renderTarget.depthTexture;
24991
24992				if ( depthTexture && depthTexture.isDepthTexture ) {
24993
24994					if ( depthTexture.type === FloatType ) {
24995
24996						glInternalFormat = _gl.DEPTH_COMPONENT32F;
24997
24998					} else if ( depthTexture.type === UnsignedIntType ) {
24999
25000						glInternalFormat = _gl.DEPTH_COMPONENT24;
25001
25002					}
25003
25004				}
25005
25006				const samples = getRenderTargetSamples( renderTarget );
25007
25008				if ( useMultisampledRTT( renderTarget ) ) {
25009
25010					multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25011
25012				} else {
25013
25014					_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25015
25016				}
25017
25018			} else {
25019
25020				_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
25021
25022			}
25023
25024			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
25025
25026		} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
25027
25028			const samples = getRenderTargetSamples( renderTarget );
25029
25030			if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) {
25031
25032				_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );
25033
25034			} else if ( useMultisampledRTT( renderTarget ) ) {
25035
25036				multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );
25037
25038			} else {
25039
25040				_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
25041
25042			}
25043
25044
25045			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
25046
25047		} else {
25048
25049			const textures = renderTarget.textures;
25050
25051			for ( let i = 0; i < textures.length; i ++ ) {
25052
25053				const texture = textures[ i ];
25054
25055				const glFormat = utils.convert( texture.format, texture.colorSpace );
25056				const glType = utils.convert( texture.type );
25057				const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
25058				const samples = getRenderTargetSamples( renderTarget );
25059
25060				if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) {
25061
25062					_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25063
25064				} else if ( useMultisampledRTT( renderTarget ) ) {
25065
25066					multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25067
25068				} else {
25069
25070					_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
25071
25072				}
25073
25074			}
25075
25076		}
25077
25078		_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
25079
25080	}
25081
25082	// Setup resources for a Depth Texture for a FBO (needs an extension)
25083	function setupDepthTexture( framebuffer, renderTarget ) {
25084
25085		const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
25086		if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
25087
25088		state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
25089
25090		if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
25091
25092			throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
25093
25094		}
25095
25096		// upload an empty depth texture with framebuffer size
25097		if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
25098				renderTarget.depthTexture.image.width !== renderTarget.width ||
25099				renderTarget.depthTexture.image.height !== renderTarget.height ) {
25100
25101			renderTarget.depthTexture.image.width = renderTarget.width;
25102			renderTarget.depthTexture.image.height = renderTarget.height;
25103			renderTarget.depthTexture.needsUpdate = true;
25104
25105		}
25106
25107		setTexture2D( renderTarget.depthTexture, 0 );
25108
25109		const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
25110		const samples = getRenderTargetSamples( renderTarget );
25111
25112		if ( renderTarget.depthTexture.format === DepthFormat ) {
25113
25114			if ( useMultisampledRTT( renderTarget ) ) {
25115
25116				multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
25117
25118			} else {
25119
25120				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
25121
25122			}
25123
25124		} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
25125
25126			if ( useMultisampledRTT( renderTarget ) ) {
25127
25128				multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
25129
25130			} else {
25131
25132				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
25133
25134			}
25135
25136		} else {
25137
25138			throw new Error( 'Unknown depthTexture format' );
25139
25140		}
25141
25142	}
25143
25144	// Setup GL resources for a non-texture depth buffer
25145	function setupDepthRenderbuffer( renderTarget ) {
25146
25147		const renderTargetProperties = properties.get( renderTarget );
25148		const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25149
25150		if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) {
25151
25152			if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
25153
25154			setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
25155
25156		} else {
25157
25158			if ( isCube ) {
25159
25160				renderTargetProperties.__webglDepthbuffer = [];
25161
25162				for ( let i = 0; i < 6; i ++ ) {
25163
25164					state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
25165					renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
25166					setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
25167
25168				}
25169
25170			} else {
25171
25172				state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25173				renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
25174				setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
25175
25176			}
25177
25178		}
25179
25180		state.bindFramebuffer( _gl.FRAMEBUFFER, null );
25181
25182	}
25183
25184	// rebind framebuffer with external textures
25185	function rebindTextures( renderTarget, colorTexture, depthTexture ) {
25186
25187		const renderTargetProperties = properties.get( renderTarget );
25188
25189		if ( colorTexture !== undefined ) {
25190
25191			setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 );
25192
25193		}
25194
25195		if ( depthTexture !== undefined ) {
25196
25197			setupDepthRenderbuffer( renderTarget );
25198
25199		}
25200
25201	}
25202
25203	// Set up GL resources for the render target
25204	function setupRenderTarget( renderTarget ) {
25205
25206		const texture = renderTarget.texture;
25207
25208		const renderTargetProperties = properties.get( renderTarget );
25209		const textureProperties = properties.get( texture );
25210
25211		renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
25212
25213		const textures = renderTarget.textures;
25214
25215		const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25216		const isMultipleRenderTargets = ( textures.length > 1 );
25217
25218		if ( ! isMultipleRenderTargets ) {
25219
25220			if ( textureProperties.__webglTexture === undefined ) {
25221
25222				textureProperties.__webglTexture = _gl.createTexture();
25223
25224			}
25225
25226			textureProperties.__version = texture.version;
25227			info.memory.textures ++;
25228
25229		}
25230
25231		// Setup framebuffer
25232
25233		if ( isCube ) {
25234
25235			renderTargetProperties.__webglFramebuffer = [];
25236
25237			for ( let i = 0; i < 6; i ++ ) {
25238
25239				if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25240
25241					renderTargetProperties.__webglFramebuffer[ i ] = [];
25242
25243					for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25244
25245						renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer();
25246
25247					}
25248
25249				} else {
25250
25251					renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
25252
25253				}
25254
25255			}
25256
25257		} else {
25258
25259			if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25260
25261				renderTargetProperties.__webglFramebuffer = [];
25262
25263				for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25264
25265					renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer();
25266
25267				}
25268
25269			} else {
25270
25271				renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
25272
25273			}
25274
25275			if ( isMultipleRenderTargets ) {
25276
25277				for ( let i = 0, il = textures.length; i < il; i ++ ) {
25278
25279					const attachmentProperties = properties.get( textures[ i ] );
25280
25281					if ( attachmentProperties.__webglTexture === undefined ) {
25282
25283						attachmentProperties.__webglTexture = _gl.createTexture();
25284
25285						info.memory.textures ++;
25286
25287					}
25288
25289				}
25290
25291			}
25292
25293			if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) {
25294
25295				renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
vendor: 4,218 bytes, lines 25296-25442
25296				renderTargetProperties.__webglColorRenderbuffer = [];
25297
25298				state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25299
25300				for ( let i = 0; i < textures.length; i ++ ) {
25301
25302					const texture = textures[ i ];
25303					renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer();
25304
25305					_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25306
25307					const glFormat = utils.convert( texture.format, texture.colorSpace );
25308					const glType = utils.convert( texture.type );
25309					const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true );
25310					const samples = getRenderTargetSamples( renderTarget );
25311					_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25312
25313					_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25314
25315				}
25316
25317				_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
25318
25319				if ( renderTarget.depthBuffer ) {
25320
25321					renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
25322					setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
25323
25324				}
25325
25326				state.bindFramebuffer( _gl.FRAMEBUFFER, null );
25327
25328			}
25329
25330		}
25331
25332		// Setup color buffer
25333
25334		if ( isCube ) {
25335
25336			state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
25337			setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture );
25338
25339			for ( let i = 0; i < 6; i ++ ) {
25340
25341				if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25342
25343					for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25344
25345						setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level );
25346
25347					}
25348
25349				} else {
25350
25351					setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 );
25352
25353				}
25354
25355			}
25356
25357			if ( textureNeedsGenerateMipmaps( texture ) ) {
25358
25359				generateMipmap( _gl.TEXTURE_CUBE_MAP );
25360
25361			}
25362
25363			state.unbindTexture();
25364
25365		} else if ( isMultipleRenderTargets ) {
25366
25367			for ( let i = 0, il = textures.length; i < il; i ++ ) {
25368
25369				const attachment = textures[ i ];
25370				const attachmentProperties = properties.get( attachment );
25371
25372				state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture );
25373				setTextureParameters( _gl.TEXTURE_2D, attachment );
25374				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 );
25375
25376				if ( textureNeedsGenerateMipmaps( attachment ) ) {
25377
25378					generateMipmap( _gl.TEXTURE_2D );
25379
25380				}
25381
25382			}
25383
25384			state.unbindTexture();
25385
25386		} else {
25387
25388			let glTextureType = _gl.TEXTURE_2D;
25389
25390			if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) {
25391
25392				glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY;
25393
25394			}
25395
25396			state.bindTexture( glTextureType, textureProperties.__webglTexture );
25397			setTextureParameters( glTextureType, texture );
25398
25399			if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25400
25401				for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25402
25403					setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level );
25404
25405				}
25406
25407			} else {
25408
25409				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 );
25410
25411			}
25412
25413			if ( textureNeedsGenerateMipmaps( texture ) ) {
25414
25415				generateMipmap( glTextureType );
25416
25417			}
25418
25419			state.unbindTexture();
25420
25421		}
25422
25423		// Setup depth and stencil buffers
25424
25425		if ( renderTarget.depthBuffer ) {
25426
25427			setupDepthRenderbuffer( renderTarget );
25428
25429		}
25430
25431	}
25432
25433	function updateRenderTargetMipmap( renderTarget ) {
25434
25435		const textures = renderTarget.textures;
25436
25437		for ( let i = 0, il = textures.length; i < il; i ++ ) {
25438
25439			const texture = textures[ i ];
25440
25441			if ( textureNeedsGenerateMipmaps( texture ) ) {
25442
vendor: 4,748 bytes, lines 25443-25588
25443				const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
25444				const webglTexture = properties.get( texture ).__webglTexture;
25445
25446				state.bindTexture( target, webglTexture );
25447				generateMipmap( target );
25448				state.unbindTexture();
25449
25450			}
25451
25452		}
25453
25454	}
25455
25456	function updateMultisampleRenderTarget( renderTarget ) {
25457
25458		if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) {
25459
25460			const textures = renderTarget.textures;
25461			const width = renderTarget.width;
25462			const height = renderTarget.height;
25463			let mask = _gl.COLOR_BUFFER_BIT;
25464			const invalidationArray = [];
25465			const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT;
25466			const renderTargetProperties = properties.get( renderTarget );
25467			const isMultipleRenderTargets = ( textures.length > 1 );
25468
25469			// If MRT we need to remove FBO attachments
25470			if ( isMultipleRenderTargets ) {
25471
25472				for ( let i = 0; i < textures.length; i ++ ) {
25473
25474					state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25475					_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null );
25476
25477					state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25478					_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 );
25479
25480				}
25481
25482			}
25483
25484			state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25485			state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25486
25487			for ( let i = 0; i < textures.length; i ++ ) {
25488
25489				invalidationArray.push( _gl.COLOR_ATTACHMENT0 + i );
25490
25491				if ( renderTarget.depthBuffer ) {
25492
25493					invalidationArray.push( depthStyle );
25494
25495				}
25496
25497				const ignoreDepthValues = ( renderTargetProperties.__ignoreDepthValues !== undefined ) ? renderTargetProperties.__ignoreDepthValues : false;
25498
25499				if ( ignoreDepthValues === false ) {
25500
25501					if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT;
25502
25503					// resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799)
25504
25505					if ( renderTarget.stencilBuffer && renderTargetProperties.__isTransmissionRenderTarget !== true ) mask |= _gl.STENCIL_BUFFER_BIT;
25506
25507				}
25508
25509				if ( isMultipleRenderTargets ) {
25510
25511					_gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25512
25513				}
25514
25515				if ( ignoreDepthValues === true ) {
25516
25517					_gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, [ depthStyle ] );
25518					_gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] );
25519
25520				}
25521
25522				if ( isMultipleRenderTargets ) {
25523
25524					const webglTexture = properties.get( textures[ i ] ).__webglTexture;
25525					_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 );
25526
25527				}
25528
25529				_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST );
25530
25531				if ( supportsInvalidateFramebuffer ) {
25532
25533					_gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArray );
25534
25535				}
25536
25537
25538			}
25539
25540			state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null );
25541			state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null );
25542
25543			// If MRT since pre-blit we removed the FBO we need to reconstruct the attachments
25544			if ( isMultipleRenderTargets ) {
25545
25546				for ( let i = 0; i < textures.length; i ++ ) {
25547
25548					state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25549					_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25550
25551					const webglTexture = properties.get( textures[ i ] ).__webglTexture;
25552
25553					state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25554					_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 );
25555
25556				}
25557
25558			}
25559
25560			state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25561
25562		}
25563
25564	}
25565
25566	function getRenderTargetSamples( renderTarget ) {
25567
25568		return Math.min( capabilities.maxSamples, renderTarget.samples );
25569
25570	}
25571
25572	function useMultisampledRTT( renderTarget ) {
25573
25574		const renderTargetProperties = properties.get( renderTarget );
25575
25576		return renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false;
25577
25578	}
25579
25580	function updateVideoTexture( texture ) {
25581
25582		const frame = info.render.frame;
25583
25584		// Check the last frame we updated the VideoTexture
25585
25586		if ( _videoTextures.get( texture ) !== frame ) {
25587
25588			_videoTextures.set( texture, frame );
vendor: 9,717 bytes, lines 25589-25864
25589			texture.update();
25590
25591		}
25592
25593	}
25594
25595	function verifyColorSpace( texture, image ) {
25596
25597		const colorSpace = texture.colorSpace;
25598		const format = texture.format;
25599		const type = texture.type;
25600
25601		if ( texture.isCompressedTexture === true || texture.isVideoTexture === true ) return image;
25602
25603		if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) {
25604
25605			// sRGB
25606
25607			if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) {
25608
25609				// in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format
25610
25611				if ( format !== RGBAFormat || type !== UnsignedByteType ) {
25612
25613					console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' );
25614
25615				}
25616
25617			} else {
25618
25619				console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace );
25620
25621			}
25622
25623		}
25624
25625		return image;
25626
25627	}
25628
25629	function getDimensions( image ) {
25630
25631		if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) {
25632
25633			// if intrinsic data are not available, fallback to width/height
25634
25635			_imageDimensions.width = image.naturalWidth || image.width;
25636			_imageDimensions.height = image.naturalHeight || image.height;
25637
25638		} else if ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) {
25639
25640			_imageDimensions.width = image.displayWidth;
25641			_imageDimensions.height = image.displayHeight;
25642
25643		} else {
25644
25645			_imageDimensions.width = image.width;
25646			_imageDimensions.height = image.height;
25647
25648		}
25649
25650		return _imageDimensions;
25651
25652	}
25653
25654	//
25655
25656	this.allocateTextureUnit = allocateTextureUnit;
25657	this.resetTextureUnits = resetTextureUnits;
25658
25659	this.setTexture2D = setTexture2D;
25660	this.setTexture2DArray = setTexture2DArray;
25661	this.setTexture3D = setTexture3D;
25662	this.setTextureCube = setTextureCube;
25663	this.rebindTextures = rebindTextures;
25664	this.setupRenderTarget = setupRenderTarget;
25665	this.updateRenderTargetMipmap = updateRenderTargetMipmap;
25666	this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
25667	this.setupDepthRenderbuffer = setupDepthRenderbuffer;
25668	this.setupFrameBufferTexture = setupFrameBufferTexture;
25669	this.useMultisampledRTT = useMultisampledRTT;
25670
25671}
25672
25673function WebGLUtils( gl, extensions ) {
25674
25675	function convert( p, colorSpace = NoColorSpace ) {
25676
25677		let extension;
25678
25679		const transfer = ColorManagement.getTransfer( colorSpace );
25680
25681		if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;
25682		if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;
25683		if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;
25684		if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV;
25685
25686		if ( p === ByteType ) return gl.BYTE;
25687		if ( p === ShortType ) return gl.SHORT;
25688		if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;
25689		if ( p === IntType ) return gl.INT;
25690		if ( p === UnsignedIntType ) return gl.UNSIGNED_INT;
25691		if ( p === FloatType ) return gl.FLOAT;
25692		if ( p === HalfFloatType ) return gl.HALF_FLOAT;
25693
25694		if ( p === AlphaFormat ) return gl.ALPHA;
25695		if ( p === RGBFormat ) return gl.RGB;
25696		if ( p === RGBAFormat ) return gl.RGBA;
25697		if ( p === LuminanceFormat ) return gl.LUMINANCE;
25698		if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;
25699		if ( p === DepthFormat ) return gl.DEPTH_COMPONENT;
25700		if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;
25701
25702		// WebGL2 formats.
25703
25704		if ( p === RedFormat ) return gl.RED;
25705		if ( p === RedIntegerFormat ) return gl.RED_INTEGER;
25706		if ( p === RGFormat ) return gl.RG;
25707		if ( p === RGIntegerFormat ) return gl.RG_INTEGER;
25708		if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER;
25709
25710		// S3TC
25711
25712		if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
25713
25714			if ( transfer === SRGBTransfer ) {
25715
25716				extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' );
25717
25718				if ( extension !== null ) {
25719
25720					if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT;
25721					if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
25722					if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
25723					if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
25724
25725				} else {
25726
25727					return null;
25728
25729				}
25730
25731			} else {
25732
25733				extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
25734
25735				if ( extension !== null ) {
25736
25737					if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
25738					if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
25739					if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
25740					if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
25741
25742				} else {
25743
25744					return null;
25745
25746				}
25747
25748			}
25749
25750		}
25751
25752		// PVRTC
25753
25754		if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
25755
25756			extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
25757
25758			if ( extension !== null ) {
25759
25760				if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
25761				if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
25762				if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
25763				if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
25764
25765			} else {
25766
25767				return null;
25768
25769			}
25770
25771		}
25772
25773		// ETC1
25774
25775		if ( p === RGB_ETC1_Format ) {
25776
25777			extension = extensions.get( 'WEBGL_compressed_texture_etc1' );
25778
25779			if ( extension !== null ) {
25780
25781				return extension.COMPRESSED_RGB_ETC1_WEBGL;
25782
25783			} else {
25784
25785				return null;
25786
25787			}
25788
25789		}
25790
25791		// ETC2
25792
25793		if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
25794
25795			extension = extensions.get( 'WEBGL_compressed_texture_etc' );
25796
25797			if ( extension !== null ) {
25798
25799				if ( p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
25800				if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
25801
25802			} else {
25803
25804				return null;
25805
25806			}
25807
25808		}
25809
25810		// ASTC
25811
25812		if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
25813			p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
25814			p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
25815			p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
25816			p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
25817
25818			extension = extensions.get( 'WEBGL_compressed_texture_astc' );
25819
25820			if ( extension !== null ) {
25821
25822				if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
25823				if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
25824				if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR;
25825				if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR;
25826				if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR;
25827				if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR;
25828				if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR;
25829				if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR;
25830				if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR;
25831				if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR;
25832				if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR;
25833				if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR;
25834				if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR;
25835				if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR;
25836
25837			} else {
25838
25839				return null;
25840
25841			}
25842
25843		}
25844
25845		// BPTC
25846
25847		if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) {
25848
25849			extension = extensions.get( 'EXT_texture_compression_bptc' );
25850
25851			if ( extension !== null ) {
25852
25853				if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
25854				if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;
25855				if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
25856
25857			} else {
25858
25859				return null;
25860
25861			}
25862
25863		}
25864
vendor: 4,803 bytes, lines 25865-26117
25865		// RGTC
25866
25867		if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) {
25868
25869			extension = extensions.get( 'EXT_texture_compression_rgtc' );
25870
25871			if ( extension !== null ) {
25872
25873				if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT;
25874				if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT;
25875				if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT;
25876				if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
25877
25878			} else {
25879
25880				return null;
25881
25882			}
25883
25884		}
25885
25886		//
25887
25888		if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8;
25889
25890		// if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats)
25891
25892		return ( gl[ p ] !== undefined ) ? gl[ p ] : null;
25893
25894	}
25895
25896	return { convert: convert };
25897
25898}
25899
25900class ArrayCamera extends PerspectiveCamera {
25901
25902	constructor( array = [] ) {
25903
25904		super();
25905
25906		this.isArrayCamera = true;
25907
25908		this.cameras = array;
25909
25910	}
25911
25912}
25913
25914class Group extends Object3D {
25915
25916	constructor() {
25917
25918		super();
25919
25920		this.isGroup = true;
25921
25922		this.type = 'Group';
25923
25924	}
25925
25926}
25927
25928const _moveEvent = { type: 'move' };
25929
25930class WebXRController {
25931
25932	constructor() {
25933
25934		this._targetRay = null;
25935		this._grip = null;
25936		this._hand = null;
25937
25938	}
25939
25940	getHandSpace() {
25941
25942		if ( this._hand === null ) {
25943
25944			this._hand = new Group();
25945			this._hand.matrixAutoUpdate = false;
25946			this._hand.visible = false;
25947
25948			this._hand.joints = {};
25949			this._hand.inputState = { pinching: false };
25950
25951		}
25952
25953		return this._hand;
25954
25955	}
25956
25957	getTargetRaySpace() {
25958
25959		if ( this._targetRay === null ) {
25960
25961			this._targetRay = new Group();
25962			this._targetRay.matrixAutoUpdate = false;
25963			this._targetRay.visible = false;
25964			this._targetRay.hasLinearVelocity = false;
25965			this._targetRay.linearVelocity = new Vector3();
25966			this._targetRay.hasAngularVelocity = false;
25967			this._targetRay.angularVelocity = new Vector3();
25968
25969		}
25970
25971		return this._targetRay;
25972
25973	}
25974
25975	getGripSpace() {
25976
25977		if ( this._grip === null ) {
25978
25979			this._grip = new Group();
25980			this._grip.matrixAutoUpdate = false;
25981			this._grip.visible = false;
25982			this._grip.hasLinearVelocity = false;
25983			this._grip.linearVelocity = new Vector3();
25984			this._grip.hasAngularVelocity = false;
25985			this._grip.angularVelocity = new Vector3();
25986
25987		}
25988
25989		return this._grip;
25990
25991	}
25992
25993	dispatchEvent( event ) {
25994
25995		if ( this._targetRay !== null ) {
25996
25997			this._targetRay.dispatchEvent( event );
25998
25999		}
26000
26001		if ( this._grip !== null ) {
26002
26003			this._grip.dispatchEvent( event );
26004
26005		}
26006
26007		if ( this._hand !== null ) {
26008
26009			this._hand.dispatchEvent( event );
26010
26011		}
26012
26013		return this;
26014
26015	}
26016
26017	connect( inputSource ) {
26018
26019		if ( inputSource && inputSource.hand ) {
26020
26021			const hand = this._hand;
26022
26023			if ( hand ) {
26024
26025				for ( const inputjoint of inputSource.hand.values() ) {
26026
26027					// Initialize hand with joints when connected
26028					this._getHandJoint( hand, inputjoint );
26029
26030				}
26031
26032			}
26033
26034		}
26035
26036		this.dispatchEvent( { type: 'connected', data: inputSource } );
26037
26038		return this;
26039
26040	}
26041
26042	disconnect( inputSource ) {
26043
26044		this.dispatchEvent( { type: 'disconnected', data: inputSource } );
26045
26046		if ( this._targetRay !== null ) {
26047
26048			this._targetRay.visible = false;
26049
26050		}
26051
26052		if ( this._grip !== null ) {
26053
26054			this._grip.visible = false;
26055
26056		}
26057
26058		if ( this._hand !== null ) {
26059
26060			this._hand.visible = false;
26061
26062		}
26063
26064		return this;
26065
26066	}
26067
26068	update( inputSource, frame, referenceSpace ) {
26069
26070		let inputPose = null;
26071		let gripPose = null;
26072		let handPose = null;
26073
26074		const targetRay = this._targetRay;
26075		const grip = this._grip;
26076		const hand = this._hand;
26077
26078		if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
26079
26080			if ( hand && inputSource.hand ) {
26081
26082				handPose = true;
26083
26084				for ( const inputjoint of inputSource.hand.values() ) {
26085
26086					// Update the joints groups with the XRJoint poses
26087					const jointPose = frame.getJointPose( inputjoint, referenceSpace );
26088
26089					// The transform of this joint will be updated with the joint pose on each frame
26090					const joint = this._getHandJoint( hand, inputjoint );
26091
26092					if ( jointPose !== null ) {
26093
26094						joint.matrix.fromArray( jointPose.transform.matrix );
26095						joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
26096						joint.matrixWorldNeedsUpdate = true;
26097						joint.jointRadius = jointPose.radius;
26098
26099					}
26100
26101					joint.visible = jointPose !== null;
26102
26103				}
26104
26105				// Custom events
26106
26107				// Check pinchz
26108				const indexTip = hand.joints[ 'index-finger-tip' ];
26109				const thumbTip = hand.joints[ 'thumb-tip' ];
26110				const distance = indexTip.position.distanceTo( thumbTip.position );
26111
26112				const distanceToPinch = 0.02;
26113				const threshold = 0.005;
26114
26115				if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
26116
26117					hand.inputState.pinching = false;
vendor: 14,152 bytes, lines 26118-26783
26118					this.dispatchEvent( {
26119						type: 'pinchend',
26120						handedness: inputSource.handedness,
26121						target: this
26122					} );
26123
26124				} else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
26125
26126					hand.inputState.pinching = true;
26127					this.dispatchEvent( {
26128						type: 'pinchstart',
26129						handedness: inputSource.handedness,
26130						target: this
26131					} );
26132
26133				}
26134
26135			} else {
26136
26137				if ( grip !== null && inputSource.gripSpace ) {
26138
26139					gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
26140
26141					if ( gripPose !== null ) {
26142
26143						grip.matrix.fromArray( gripPose.transform.matrix );
26144						grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
26145						grip.matrixWorldNeedsUpdate = true;
26146
26147						if ( gripPose.linearVelocity ) {
26148
26149							grip.hasLinearVelocity = true;
26150							grip.linearVelocity.copy( gripPose.linearVelocity );
26151
26152						} else {
26153
26154							grip.hasLinearVelocity = false;
26155
26156						}
26157
26158						if ( gripPose.angularVelocity ) {
26159
26160							grip.hasAngularVelocity = true;
26161							grip.angularVelocity.copy( gripPose.angularVelocity );
26162
26163						} else {
26164
26165							grip.hasAngularVelocity = false;
26166
26167						}
26168
26169					}
26170
26171				}
26172
26173			}
26174
26175			if ( targetRay !== null ) {
26176
26177				inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
26178
26179				// Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it
26180				if ( inputPose === null && gripPose !== null ) {
26181
26182					inputPose = gripPose;
26183
26184				}
26185
26186				if ( inputPose !== null ) {
26187
26188					targetRay.matrix.fromArray( inputPose.transform.matrix );
26189					targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
26190					targetRay.matrixWorldNeedsUpdate = true;
26191
26192					if ( inputPose.linearVelocity ) {
26193
26194						targetRay.hasLinearVelocity = true;
26195						targetRay.linearVelocity.copy( inputPose.linearVelocity );
26196
26197					} else {
26198
26199						targetRay.hasLinearVelocity = false;
26200
26201					}
26202
26203					if ( inputPose.angularVelocity ) {
26204
26205						targetRay.hasAngularVelocity = true;
26206						targetRay.angularVelocity.copy( inputPose.angularVelocity );
26207
26208					} else {
26209
26210						targetRay.hasAngularVelocity = false;
26211
26212					}
26213
26214					this.dispatchEvent( _moveEvent );
26215
26216				}
26217
26218			}
26219
26220
26221		}
26222
26223		if ( targetRay !== null ) {
26224
26225			targetRay.visible = ( inputPose !== null );
26226
26227		}
26228
26229		if ( grip !== null ) {
26230
26231			grip.visible = ( gripPose !== null );
26232
26233		}
26234
26235		if ( hand !== null ) {
26236
26237			hand.visible = ( handPose !== null );
26238
26239		}
26240
26241		return this;
26242
26243	}
26244
26245	// private method
26246
26247	_getHandJoint( hand, inputjoint ) {
26248
26249		if ( hand.joints[ inputjoint.jointName ] === undefined ) {
26250
26251			const joint = new Group();
26252			joint.matrixAutoUpdate = false;
26253			joint.visible = false;
26254			hand.joints[ inputjoint.jointName ] = joint;
26255
26256			hand.add( joint );
26257
26258		}
26259
26260		return hand.joints[ inputjoint.jointName ];
26261
26262	}
26263
26264}
26265
26266const _occlusion_vertex = `
26267void main() {
26268
26269	gl_Position = vec4( position, 1.0 );
26270
26271}`;
26272
26273const _occlusion_fragment = `
26274uniform sampler2DArray depthColor;
26275uniform float depthWidth;
26276uniform float depthHeight;
26277
26278void main() {
26279
26280	vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );
26281
26282	if ( coord.x >= 1.0 ) {
26283
26284		gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;
26285
26286	} else {
26287
26288		gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;
26289
26290	}
26291
26292}`;
26293
26294class WebXRDepthSensing {
26295
26296	constructor() {
26297
26298		this.texture = null;
26299		this.mesh = null;
26300
26301		this.depthNear = 0;
26302		this.depthFar = 0;
26303
26304	}
26305
26306	init( renderer, depthData, renderState ) {
26307
26308		if ( this.texture === null ) {
26309
26310			const texture = new Texture();
26311
26312			const texProps = renderer.properties.get( texture );
26313			texProps.__webglTexture = depthData.texture;
26314
26315			if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) {
26316
26317				this.depthNear = depthData.depthNear;
26318				this.depthFar = depthData.depthFar;
26319
26320			}
26321
26322			this.texture = texture;
26323
26324		}
26325
26326	}
26327
26328	render( renderer, cameraXR ) {
26329
26330		if ( this.texture !== null ) {
26331
26332			if ( this.mesh === null ) {
26333
26334				const viewport = cameraXR.cameras[ 0 ].viewport;
26335				const material = new ShaderMaterial( {
26336					vertexShader: _occlusion_vertex,
26337					fragmentShader: _occlusion_fragment,
26338					uniforms: {
26339						depthColor: { value: this.texture },
26340						depthWidth: { value: viewport.z },
26341						depthHeight: { value: viewport.w }
26342					}
26343				} );
26344
26345				this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material );
26346
26347			}
26348
26349			renderer.render( this.mesh, cameraXR );
26350
26351		}
26352
26353	}
26354
26355	reset() {
26356
26357		this.texture = null;
26358		this.mesh = null;
26359
26360	}
26361
26362}
26363
26364class WebXRManager extends EventDispatcher {
26365
26366	constructor( renderer, gl ) {
26367
26368		super();
26369
26370		const scope = this;
26371
26372		let session = null;
26373
26374		let framebufferScaleFactor = 1.0;
26375
26376		let referenceSpace = null;
26377		let referenceSpaceType = 'local-floor';
26378		// Set default foveation to maximum.
26379		let foveation = 1.0;
26380		let customReferenceSpace = null;
26381
26382		let pose = null;
26383		let glBinding = null;
26384		let glProjLayer = null;
26385		let glBaseLayer = null;
26386		let xrFrame = null;
26387
26388		const depthSensing = new WebXRDepthSensing();
26389		const attributes = gl.getContextAttributes();
26390
26391		let initialRenderTarget = null;
26392		let newRenderTarget = null;
26393
26394		const controllers = [];
26395		const controllerInputSources = [];
26396
26397		const currentSize = new Vector2();
26398		let currentPixelRatio = null;
26399
26400		//
26401
26402		const cameraL = new PerspectiveCamera();
26403		cameraL.layers.enable( 1 );
26404		cameraL.viewport = new Vector4();
26405
26406		const cameraR = new PerspectiveCamera();
26407		cameraR.layers.enable( 2 );
26408		cameraR.viewport = new Vector4();
26409
26410		const cameras = [ cameraL, cameraR ];
26411
26412		const cameraXR = new ArrayCamera();
26413		cameraXR.layers.enable( 1 );
26414		cameraXR.layers.enable( 2 );
26415
26416		let _currentDepthNear = null;
26417		let _currentDepthFar = null;
26418
26419		//
26420
26421		this.cameraAutoUpdate = true;
26422		this.enabled = false;
26423
26424		this.isPresenting = false;
26425
26426		this.getController = function ( index ) {
26427
26428			let controller = controllers[ index ];
26429
26430			if ( controller === undefined ) {
26431
26432				controller = new WebXRController();
26433				controllers[ index ] = controller;
26434
26435			}
26436
26437			return controller.getTargetRaySpace();
26438
26439		};
26440
26441		this.getControllerGrip = function ( index ) {
26442
26443			let controller = controllers[ index ];
26444
26445			if ( controller === undefined ) {
26446
26447				controller = new WebXRController();
26448				controllers[ index ] = controller;
26449
26450			}
26451
26452			return controller.getGripSpace();
26453
26454		};
26455
26456		this.getHand = function ( index ) {
26457
26458			let controller = controllers[ index ];
26459
26460			if ( controller === undefined ) {
26461
26462				controller = new WebXRController();
26463				controllers[ index ] = controller;
26464
26465			}
26466
26467			return controller.getHandSpace();
26468
26469		};
26470
26471		//
26472
26473		function onSessionEvent( event ) {
26474
26475			const controllerIndex = controllerInputSources.indexOf( event.inputSource );
26476
26477			if ( controllerIndex === - 1 ) {
26478
26479				return;
26480
26481			}
26482
26483			const controller = controllers[ controllerIndex ];
26484
26485			if ( controller !== undefined ) {
26486
26487				controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace );
26488				controller.dispatchEvent( { type: event.type, data: event.inputSource } );
26489
26490			}
26491
26492		}
26493
26494		function onSessionEnd() {
26495
26496			session.removeEventListener( 'select', onSessionEvent );
26497			session.removeEventListener( 'selectstart', onSessionEvent );
26498			session.removeEventListener( 'selectend', onSessionEvent );
26499			session.removeEventListener( 'squeeze', onSessionEvent );
26500			session.removeEventListener( 'squeezestart', onSessionEvent );
26501			session.removeEventListener( 'squeezeend', onSessionEvent );
26502			session.removeEventListener( 'end', onSessionEnd );
26503			session.removeEventListener( 'inputsourceschange', onInputSourcesChange );
26504
26505			for ( let i = 0; i < controllers.length; i ++ ) {
26506
26507				const inputSource = controllerInputSources[ i ];
26508
26509				if ( inputSource === null ) continue;
26510
26511				controllerInputSources[ i ] = null;
26512
26513				controllers[ i ].disconnect( inputSource );
26514
26515			}
26516
26517			_currentDepthNear = null;
26518			_currentDepthFar = null;
26519
26520			depthSensing.reset();
26521
26522			// restore framebuffer/rendering state
26523
26524			renderer.setRenderTarget( initialRenderTarget );
26525
26526			glBaseLayer = null;
26527			glProjLayer = null;
26528			glBinding = null;
26529			session = null;
26530			newRenderTarget = null;
26531
26532			//
26533
26534			animation.stop();
26535
26536			scope.isPresenting = false;
26537
26538			renderer.setPixelRatio( currentPixelRatio );
26539			renderer.setSize( currentSize.width, currentSize.height, false );
26540
26541			scope.dispatchEvent( { type: 'sessionend' } );
26542
26543		}
26544
26545		this.setFramebufferScaleFactor = function ( value ) {
26546
26547			framebufferScaleFactor = value;
26548
26549			if ( scope.isPresenting === true ) {
26550
26551				console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
26552
26553			}
26554
26555		};
26556
26557		this.setReferenceSpaceType = function ( value ) {
26558
26559			referenceSpaceType = value;
26560
26561			if ( scope.isPresenting === true ) {
26562
26563				console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
26564
26565			}
26566
26567		};
26568
26569		this.getReferenceSpace = function () {
26570
26571			return customReferenceSpace || referenceSpace;
26572
26573		};
26574
26575		this.setReferenceSpace = function ( space ) {
26576
26577			customReferenceSpace = space;
26578
26579		};
26580
26581		this.getBaseLayer = function () {
26582
26583			return glProjLayer !== null ? glProjLayer : glBaseLayer;
26584
26585		};
26586
26587		this.getBinding = function () {
26588
26589			return glBinding;
26590
26591		};
26592
26593		this.getFrame = function () {
26594
26595			return xrFrame;
26596
26597		};
26598
26599		this.getSession = function () {
26600
26601			return session;
26602
26603		};
26604
26605		this.setSession = async function ( value ) {
26606
26607			session = value;
26608
26609			if ( session !== null ) {
26610
26611				initialRenderTarget = renderer.getRenderTarget();
26612
26613				session.addEventListener( 'select', onSessionEvent );
26614				session.addEventListener( 'selectstart', onSessionEvent );
26615				session.addEventListener( 'selectend', onSessionEvent );
26616				session.addEventListener( 'squeeze', onSessionEvent );
26617				session.addEventListener( 'squeezestart', onSessionEvent );
26618				session.addEventListener( 'squeezeend', onSessionEvent );
26619				session.addEventListener( 'end', onSessionEnd );
26620				session.addEventListener( 'inputsourceschange', onInputSourcesChange );
26621
26622				if ( attributes.xrCompatible !== true ) {
26623
26624					await gl.makeXRCompatible();
26625
26626				}
26627
26628				currentPixelRatio = renderer.getPixelRatio();
26629				renderer.getSize( currentSize );
26630
26631				if ( session.renderState.layers === undefined ) {
26632
26633					const layerInit = {
26634						antialias: attributes.antialias,
26635						alpha: true,
26636						depth: attributes.depth,
26637						stencil: attributes.stencil,
26638						framebufferScaleFactor: framebufferScaleFactor
26639					};
26640
26641					glBaseLayer = new XRWebGLLayer( session, gl, layerInit );
26642
26643					session.updateRenderState( { baseLayer: glBaseLayer } );
26644
26645					renderer.setPixelRatio( 1 );
26646					renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false );
26647
26648					newRenderTarget = new WebGLRenderTarget(
26649						glBaseLayer.framebufferWidth,
26650						glBaseLayer.framebufferHeight,
26651						{
26652							format: RGBAFormat,
26653							type: UnsignedByteType,
26654							colorSpace: renderer.outputColorSpace,
26655							stencilBuffer: attributes.stencil
26656						}
26657					);
26658
26659				} else {
26660
26661					let depthFormat = null;
26662					let depthType = null;
26663					let glDepthFormat = null;
26664
26665					if ( attributes.depth ) {
26666
26667						glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
26668						depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat;
26669						depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType;
26670
26671					}
26672
26673					const projectionlayerInit = {
26674						colorFormat: gl.RGBA8,
26675						depthFormat: glDepthFormat,
26676						scaleFactor: framebufferScaleFactor
26677					};
26678
26679					glBinding = new XRWebGLBinding( session, gl );
26680
26681					glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
26682
26683					session.updateRenderState( { layers: [ glProjLayer ] } );
26684
26685					renderer.setPixelRatio( 1 );
26686					renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false );
26687
26688					newRenderTarget = new WebGLRenderTarget(
26689						glProjLayer.textureWidth,
26690						glProjLayer.textureHeight,
26691						{
26692							format: RGBAFormat,
26693							type: UnsignedByteType,
26694							depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ),
26695							stencilBuffer: attributes.stencil,
26696							colorSpace: renderer.outputColorSpace,
26697							samples: attributes.antialias ? 4 : 0
26698						} );
26699
26700					const renderTargetProperties = renderer.properties.get( newRenderTarget );
26701					renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues;
26702
26703				}
26704
26705				newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278
26706
26707				this.setFoveation( foveation );
26708
26709				customReferenceSpace = null;
26710				referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
26711
26712				animation.setContext( session );
26713				animation.start();
26714
26715				scope.isPresenting = true;
26716
26717				scope.dispatchEvent( { type: 'sessionstart' } );
26718
26719			}
26720
26721		};
26722
26723		this.getEnvironmentBlendMode = function () {
26724
26725			if ( session !== null ) {
26726
26727				return session.environmentBlendMode;
26728
26729			}
26730
26731		};
26732
26733		function onInputSourcesChange( event ) {
26734
26735			// Notify disconnected
26736
26737			for ( let i = 0; i < event.removed.length; i ++ ) {
26738
26739				const inputSource = event.removed[ i ];
26740				const index = controllerInputSources.indexOf( inputSource );
26741
26742				if ( index >= 0 ) {
26743
26744					controllerInputSources[ index ] = null;
26745					controllers[ index ].disconnect( inputSource );
26746
26747				}
26748
26749			}
26750
26751			// Notify connected
26752
26753			for ( let i = 0; i < event.added.length; i ++ ) {
26754
26755				const inputSource = event.added[ i ];
26756
26757				let controllerIndex = controllerInputSources.indexOf( inputSource );
26758
26759				if ( controllerIndex === - 1 ) {
26760
26761					// Assign input source a controller that currently has no input source
26762
26763					for ( let i = 0; i < controllers.length; i ++ ) {
26764
26765						if ( i >= controllerInputSources.length ) {
26766
26767							controllerInputSources.push( inputSource );
26768							controllerIndex = i;
26769							break;
26770
26771						} else if ( controllerInputSources[ i ] === null ) {
26772
26773							controllerInputSources[ i ] = inputSource;
26774							controllerIndex = i;
26775							break;
26776
26777						}
26778
26779					}
26780
26781					// If all controllers do currently receive input we ignore new ones
26782
26783					if ( controllerIndex === - 
vendor: 12,726 bytes, lines 26783-27329
267831 ) break;
26784
26785				}
26786
26787				const controller = controllers[ controllerIndex ];
26788
26789				if ( controller ) {
26790
26791					controller.connect( inputSource );
26792
26793				}
26794
26795			}
26796
26797		}
26798
26799		//
26800
26801		const cameraLPos = new Vector3();
26802		const cameraRPos = new Vector3();
26803
26804		/**
26805		 * Assumes 2 cameras that are parallel and share an X-axis, and that
26806		 * the cameras' projection and world matrices have already been set.
26807		 * And that near and far planes are identical for both cameras.
26808		 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
26809		 */
26810		function setProjectionFromUnion( camera, cameraL, cameraR ) {
26811
26812			cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
26813			cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
26814
26815			const ipd = cameraLPos.distanceTo( cameraRPos );
26816
26817			const projL = cameraL.projectionMatrix.elements;
26818			const projR = cameraR.projectionMatrix.elements;
26819
26820			// VR systems will have identical far and near planes, and
26821			// most likely identical top and bottom frustum extents.
26822			// Use the left camera for these values.
26823			const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
26824			const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
26825			const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
26826			const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
26827
26828			const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
26829			const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
26830			const left = near * leftFov;
26831			const right = near * rightFov;
26832
26833			// Calculate the new camera's position offset from the
26834			// left camera. xOffset should be roughly half `ipd`.
26835			const zOffset = ipd / ( - leftFov + rightFov );
26836			const xOffset = zOffset * - leftFov;
26837
26838			// TODO: Better way to apply this offset?
26839			cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
26840			camera.translateX( xOffset );
26841			camera.translateZ( zOffset );
26842			camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
26843			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
26844
26845			// Find the union of the frustum values of the cameras and scale
26846			// the values so that the near plane's position does not change in world space,
26847			// although must now be relative to the new union camera.
26848			const near2 = near + zOffset;
26849			const far2 = far + zOffset;
26850			const left2 = left - xOffset;
26851			const right2 = right + ( ipd - xOffset );
26852			const top2 = topFov * far / far2 * near2;
26853			const bottom2 = bottomFov * far / far2 * near2;
26854
26855			camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
26856			camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
26857
26858		}
26859
26860		function updateCamera( camera, parent ) {
26861
26862			if ( parent === null ) {
26863
26864				camera.matrixWorld.copy( camera.matrix );
26865
26866			} else {
26867
26868				camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
26869
26870			}
26871
26872			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
26873
26874		}
26875
26876		this.updateCamera = function ( camera ) {
26877
26878			if ( session === null ) return;
26879
26880			if ( depthSensing.texture !== null ) {
26881
26882				camera.near = depthSensing.depthNear;
26883				camera.far = depthSensing.depthFar;
26884
26885			}
26886
26887			cameraXR.near = cameraR.near = cameraL.near = camera.near;
26888			cameraXR.far = cameraR.far = cameraL.far = camera.far;
26889
26890			if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) {
26891
26892				// Note that the new renderState won't apply until the next frame. See #18320
26893
26894				session.updateRenderState( {
26895					depthNear: cameraXR.near,
26896					depthFar: cameraXR.far
26897				} );
26898
26899				_currentDepthNear = cameraXR.near;
26900				_currentDepthFar = cameraXR.far;
26901
26902				cameraL.near = _currentDepthNear;
26903				cameraL.far = _currentDepthFar;
26904				cameraR.near = _currentDepthNear;
26905				cameraR.far = _currentDepthFar;
26906
26907				cameraL.updateProjectionMatrix();
26908				cameraR.updateProjectionMatrix();
26909				camera.updateProjectionMatrix();
26910
26911			}
26912
26913			const parent = camera.parent;
26914			const cameras = cameraXR.cameras;
26915
26916			updateCamera( cameraXR, parent );
26917
26918			for ( let i = 0; i < cameras.length; i ++ ) {
26919
26920				updateCamera( cameras[ i ], parent );
26921
26922			}
26923
26924			// update projection matrix for proper view frustum culling
26925
26926			if ( cameras.length === 2 ) {
26927
26928				setProjectionFromUnion( cameraXR, cameraL, cameraR );
26929
26930			} else {
26931
26932				// assume single camera setup (AR)
26933
26934				cameraXR.projectionMatrix.copy( cameraL.projectionMatrix );
26935
26936			}
26937
26938			// update user camera and its children
26939
26940			updateUserCamera( camera, cameraXR, parent );
26941
26942		};
26943
26944		function updateUserCamera( camera, cameraXR, parent ) {
26945
26946			if ( parent === null ) {
26947
26948				camera.matrix.copy( cameraXR.matrixWorld );
26949
26950			} else {
26951
26952				camera.matrix.copy( parent.matrixWorld );
26953				camera.matrix.invert();
26954				camera.matrix.multiply( cameraXR.matrixWorld );
26955
26956			}
26957
26958			camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
26959			camera.updateMatrixWorld( true );
26960
26961			camera.projectionMatrix.copy( cameraXR.projectionMatrix );
26962			camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse );
26963
26964			if ( camera.isPerspectiveCamera ) {
26965
26966				camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] );
26967				camera.zoom = 1;
26968
26969			}
26970
26971		}
26972
26973		this.getCamera = function () {
26974
26975			return cameraXR;
26976
26977		};
26978
26979		this.getFoveation = function () {
26980
26981			if ( glProjLayer === null && glBaseLayer === null ) {
26982
26983				return undefined;
26984
26985			}
26986
26987			return foveation;
26988
26989		};
26990
26991		this.setFoveation = function ( value ) {
26992
26993			// 0 = no foveation = full resolution
26994			// 1 = maximum foveation = the edges render at lower resolution
26995
26996			foveation = value;
26997
26998			if ( glProjLayer !== null ) {
26999
27000				glProjLayer.fixedFoveation = value;
27001
27002			}
27003
27004			if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) {
27005
27006				glBaseLayer.fixedFoveation = value;
27007
27008			}
27009
27010		};
27011
27012		this.hasDepthSensing = function () {
27013
27014			return depthSensing.texture !== null;
27015
27016		};
27017
27018		// Animation Loop
27019
27020		let onAnimationFrameCallback = null;
27021
27022		function onAnimationFrame( time, frame ) {
27023
27024			pose = frame.getViewerPose( customReferenceSpace || referenceSpace );
27025			xrFrame = frame;
27026
27027			if ( pose !== null ) {
27028
27029				const views = pose.views;
27030
27031				if ( glBaseLayer !== null ) {
27032
27033					renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer );
27034					renderer.setRenderTarget( newRenderTarget );
27035
27036				}
27037
27038				let cameraXRNeedsUpdate = false;
27039
27040				// check if it's necessary to rebuild cameraXR's camera list
27041
27042				if ( views.length !== cameraXR.cameras.length ) {
27043
27044					cameraXR.cameras.length = 0;
27045					cameraXRNeedsUpdate = true;
27046
27047				}
27048
27049				for ( let i = 0; i < views.length; i ++ ) {
27050
27051					const view = views[ i ];
27052
27053					let viewport = null;
27054
27055					if ( glBaseLayer !== null ) {
27056
27057						viewport = glBaseLayer.getViewport( view );
27058
27059					} else {
27060
27061						const glSubImage = glBinding.getViewSubImage( glProjLayer, view );
27062						viewport = glSubImage.viewport;
27063
27064						// For side-by-side projection, we only produce a single texture for both eyes.
27065						if ( i === 0 ) {
27066
27067							renderer.setRenderTargetTextures(
27068								newRenderTarget,
27069								glSubImage.colorTexture,
27070								glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture );
27071
27072							renderer.setRenderTarget( newRenderTarget );
27073
27074						}
27075
27076					}
27077
27078					let camera = cameras[ i ];
27079
27080					if ( camera === undefined ) {
27081
27082						camera = new PerspectiveCamera();
27083						camera.layers.enable( i );
27084						camera.viewport = new Vector4();
27085						cameras[ i ] = camera;
27086
27087					}
27088
27089					camera.matrix.fromArray( view.transform.matrix );
27090					camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
27091					camera.projectionMatrix.fromArray( view.projectionMatrix );
27092					camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
27093					camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
27094
27095					if ( i === 0 ) {
27096
27097						cameraXR.matrix.copy( camera.matrix );
27098						cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale );
27099
27100					}
27101
27102					if ( cameraXRNeedsUpdate === true ) {
27103
27104						cameraXR.cameras.push( camera );
27105
27106					}
27107
27108				}
27109
27110				//
27111
27112				const enabledFeatures = session.enabledFeatures;
27113
27114				if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) {
27115
27116					const depthData = glBinding.getDepthInformation( views[ 0 ] );
27117
27118					if ( depthData && depthData.isValid && depthData.texture ) {
27119
27120						depthSensing.init( renderer, depthData, session.renderState );
27121
27122					}
27123
27124				}
27125
27126			}
27127
27128			//
27129
27130			for ( let i = 0; i < controllers.length; i ++ ) {
27131
27132				const inputSource = controllerInputSources[ i ];
27133				const controller = controllers[ i ];
27134
27135				if ( inputSource !== null && controller !== undefined ) {
27136
27137					controller.update( inputSource, frame, customReferenceSpace || referenceSpace );
27138
27139				}
27140
27141			}
27142
27143			depthSensing.render( renderer, cameraXR );
27144
27145			if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
27146
27147			if ( frame.detectedPlanes ) {
27148
27149				scope.dispatchEvent( { type: 'planesdetected', data: frame } );
27150
27151			}
27152
27153			xrFrame = null;
27154
27155		}
27156
27157		const animation = new WebGLAnimation();
27158
27159		animation.setAnimationLoop( onAnimationFrame );
27160
27161		this.setAnimationLoop = function ( callback ) {
27162
27163			onAnimationFrameCallback = callback;
27164
27165		};
27166
27167		this.dispose = function () {};
27168
27169	}
27170
27171}
27172
27173const _e1 = /*@__PURE__*/ new Euler();
27174const _m1 = /*@__PURE__*/ new Matrix4();
27175
27176function WebGLMaterials( renderer, properties ) {
27177
27178	function refreshTransformUniform( map, uniform ) {
27179
27180		if ( map.matrixAutoUpdate === true ) {
27181
27182			map.updateMatrix();
27183
27184		}
27185
27186		uniform.value.copy( map.matrix );
27187
27188	}
27189
27190	function refreshFogUniforms( uniforms, fog ) {
27191
27192		fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) );
27193
27194		if ( fog.isFog ) {
27195
27196			uniforms.fogNear.value = fog.near;
27197			uniforms.fogFar.value = fog.far;
27198
27199		} else if ( fog.isFogExp2 ) {
27200
27201			uniforms.fogDensity.value = fog.density;
27202
27203		}
27204
27205	}
27206
27207	function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
27208
27209		if ( material.isMeshBasicMaterial ) {
27210
27211			refreshUniformsCommon( uniforms, material );
27212
27213		} else if ( material.isMeshLambertMaterial ) {
27214
27215			refreshUniformsCommon( uniforms, material );
27216
27217		} else if ( material.isMeshToonMaterial ) {
27218
27219			refreshUniformsCommon( uniforms, material );
27220			refreshUniformsToon( uniforms, material );
27221
27222		} else if ( material.isMeshPhongMaterial ) {
27223
27224			refreshUniformsCommon( uniforms, material );
27225			refreshUniformsPhong( uniforms, material );
27226
27227		} else if ( material.isMeshStandardMaterial ) {
27228
27229			refreshUniformsCommon( uniforms, material );
27230			refreshUniformsStandard( uniforms, material );
27231
27232			if ( material.isMeshPhysicalMaterial ) {
27233
27234				refreshUniformsPhysical( uniforms, material, transmissionRenderTarget );
27235
27236			}
27237
27238		} else if ( material.isMeshMatcapMaterial ) {
27239
27240			refreshUniformsCommon( uniforms, material );
27241			refreshUniformsMatcap( uniforms, material );
27242
27243		} else if ( material.isMeshDepthMaterial ) {
27244
27245			refreshUniformsCommon( uniforms, material );
27246
27247		} else if ( material.isMeshDistanceMaterial ) {
27248
27249			refreshUniformsCommon( uniforms, material );
27250			refreshUniformsDistance( uniforms, material );
27251
27252		} else if ( material.isMeshNormalMaterial ) {
27253
27254			refreshUniformsCommon( uniforms, material );
27255
27256		} else if ( material.isLineBasicMaterial ) {
27257
27258			refreshUniformsLine( uniforms, material );
27259
27260			if ( material.isLineDashedMaterial ) {
27261
27262				refreshUniformsDash( uniforms, material );
27263
27264			}
27265
27266		} else if ( material.isPointsMaterial ) {
27267
27268			refreshUniformsPoints( uniforms, material, pixelRatio, height );
27269
27270		} else if ( material.isSpriteMaterial ) {
27271
27272			refreshUniformsSprites( uniforms, material );
27273
27274		} else if ( material.isShadowMaterial ) {
27275
27276			uniforms.color.value.copy( material.color );
27277			uniforms.opacity.value = material.opacity;
27278
27279		} else if ( material.isShaderMaterial ) {
27280
27281			material.uniformsNeedUpdate = false; // #15581
27282
27283		}
27284
27285	}
27286
27287	function refreshUniformsCommon( uniforms, material ) {
27288
27289		uniforms.opacity.value = material.opacity;
27290
27291		if ( material.color ) {
27292
27293			uniforms.diffuse.value.copy( material.color );
27294
27295		}
27296
27297		if ( material.emissive ) {
27298
27299			uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
27300
27301		}
27302
27303		if ( material.map ) {
27304
27305			uniforms.map.value = material.map;
27306
27307			refreshTransformUniform( material.map, uniforms.mapTransform );
27308
27309		}
27310
27311		if ( material.alphaMap ) {
27312
27313			uniforms.alphaMap.value = material.alphaMap;
27314
27315			refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27316
27317		}
27318
27319		if ( material.bumpMap ) {
27320
27321			uniforms.bumpMap.value = material.bumpMap;
27322
27323			refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform );
27324
27325			uniforms.bumpScale.value = material.bumpScale;
27326
27327			if ( material.side === BackSide ) {
27328
27329				uniforms.bumpScale.value *= -
27329 1;
27330
27331			}
27332
27333		}
27334
27335		if ( material.normalMap ) {
27336
27337			uniforms.normalMap.value = material.normalMap;
27338
27339			refreshTransformUniform( material.normalMap, uniforms.normalMapTransform );
27340
27341			uniforms.normalScale.value.copy( material.normalScale );
27342
27343			if ( material.side === BackSide ) {
27344
27345				uniforms.normalScale.value.negate();
27346
27347			}
27348
27349		}
27350
27351		if ( material.displacementMap ) {
27352
27353			uniforms.displacementMap.value = material.displacementMap;
27354
27355			refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform );
27356
27357			uniforms.displacementScale.value = material.displacementScale;
27358			uniforms.displacementBias.value = material.displacementBias;
27359
27360		}
27361
27362		if ( material.emissiveMap ) {
27363
27364			uniforms.emissiveMap.value = material.emissiveMap;
27365
27366			refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform );
27367
27368		}
27369
27370		if ( material.specularMap ) {
27371
27372			uniforms.specularMap.value = material.specularMap;
27373
27374			refreshTransformUniform( material.specularMap, uniforms.specularMapTransform );
27375
27376		}
27377
27378		if ( material.alphaTest > 0 ) {
27379
27380			uniforms.alphaTest.value = material.alphaTest;
27381
27382		}
27383
27384		const materialProperties = properties.get( material );
27385
27386		const envMap = materialProperties.envMap;
27387		const envMapRotation = materialProperties.envMapRotation;
27388
27389		if ( envMap ) {
27390
27391			uniforms.envMap.value = envMap;
27392
27393			_e1.copy( envMapRotation );
27394
27395			// accommodate left-handed frame
27396			_e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1;
27397
27398			if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) {
27399
27400				// environment maps which are not cube render targets or PMREMs follow a different c
vendor: 10,580 bytes, lines 27400-27829
27400onvention
27401				_e1.y *= - 1;
27402				_e1.z *= - 1;
27403
27404			}
27405
27406			uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) );
27407
27408			uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
27409
27410			uniforms.reflectivity.value = material.reflectivity;
27411			uniforms.ior.value = material.ior;
27412			uniforms.refractionRatio.value = material.refractionRatio;
27413
27414		}
27415
27416		if ( material.lightMap ) {
27417
27418			uniforms.lightMap.value = material.lightMap;
27419
27420			// artist-friendly light intensity scaling factor
27421			const scaleFactor = ( renderer._useLegacyLights === true ) ? Math.PI : 1;
27422
27423			uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor;
27424
27425			refreshTransformUniform( material.lightMap, uniforms.lightMapTransform );
27426
27427		}
27428
27429		if ( material.aoMap ) {
27430
27431			uniforms.aoMap.value = material.aoMap;
27432			uniforms.aoMapIntensity.value = material.aoMapIntensity;
27433
27434			refreshTransformUniform( material.aoMap, uniforms.aoMapTransform );
27435
27436		}
27437
27438	}
27439
27440	function refreshUniformsLine( uniforms, material ) {
27441
27442		uniforms.diffuse.value.copy( material.color );
27443		uniforms.opacity.value = material.opacity;
27444
27445		if ( material.map ) {
27446
27447			uniforms.map.value = material.map;
27448
27449			refreshTransformUniform( material.map, uniforms.mapTransform );
27450
27451		}
27452
27453	}
27454
27455	function refreshUniformsDash( uniforms, material ) {
27456
27457		uniforms.dashSize.value = material.dashSize;
27458		uniforms.totalSize.value = material.dashSize + material.gapSize;
27459		uniforms.scale.value = material.scale;
27460
27461	}
27462
27463	function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
27464
27465		uniforms.diffuse.value.copy( material.color );
27466		uniforms.opacity.value = material.opacity;
27467		uniforms.size.value = material.size * pixelRatio;
27468		uniforms.scale.value = height * 0.5;
27469
27470		if ( material.map ) {
27471
27472			uniforms.map.value = material.map;
27473
27474			refreshTransformUniform( material.map, uniforms.uvTransform );
27475
27476		}
27477
27478		if ( material.alphaMap ) {
27479
27480			uniforms.alphaMap.value = material.alphaMap;
27481
27482			refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27483
27484		}
27485
27486		if ( material.alphaTest > 0 ) {
27487
27488			uniforms.alphaTest.value = material.alphaTest;
27489
27490		}
27491
27492	}
27493
27494	function refreshUniformsSprites( uniforms, material ) {
27495
27496		uniforms.diffuse.value.copy( material.color );
27497		uniforms.opacity.value = material.opacity;
27498		uniforms.rotation.value = material.rotation;
27499
27500		if ( material.map ) {
27501
27502			uniforms.map.value = material.map;
27503
27504			refreshTransformUniform( material.map, uniforms.mapTransform );
27505
27506		}
27507
27508		if ( material.alphaMap ) {
27509
27510			uniforms.alphaMap.value = material.alphaMap;
27511
27512			refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27513
27514		}
27515
27516		if ( material.alphaTest > 0 ) {
27517
27518			uniforms.alphaTest.value = material.alphaTest;
27519
27520		}
27521
27522	}
27523
27524	function refreshUniformsPhong( uniforms, material ) {
27525
27526		uniforms.specular.value.copy( material.specular );
27527		uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
27528
27529	}
27530
27531	function refreshUniformsToon( uniforms, material ) {
27532
27533		if ( material.gradientMap ) {
27534
27535			uniforms.gradientMap.value = material.gradientMap;
27536
27537		}
27538
27539	}
27540
27541	function refreshUniformsStandard( uniforms, material ) {
27542
27543		uniforms.metalness.value = material.metalness;
27544
27545		if ( material.metalnessMap ) {
27546
27547			uniforms.metalnessMap.value = material.metalnessMap;
27548
27549			refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform );
27550
27551		}
27552
27553		uniforms.roughness.value = material.roughness;
27554
27555		if ( material.roughnessMap ) {
27556
27557			uniforms.roughnessMap.value = material.roughnessMap;
27558
27559			refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform );
27560
27561		}
27562
27563		if ( material.envMap ) {
27564
27565			//uniforms.envMap.value = material.envMap; // part of uniforms common
27566
27567			uniforms.envMapIntensity.value = material.envMapIntensity;
27568
27569		}
27570
27571	}
27572
27573	function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) {
27574
27575		uniforms.ior.value = material.ior; // also part of uniforms common
27576
27577		if ( material.sheen > 0 ) {
27578
27579			uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen );
27580
27581			uniforms.sheenRoughness.value = material.sheenRoughness;
27582
27583			if ( material.sheenColorMap ) {
27584
27585				uniforms.sheenColorMap.value = material.sheenColorMap;
27586
27587				refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform );
27588
27589			}
27590
27591			if ( material.sheenRoughnessMap ) {
27592
27593				uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap;
27594
27595				refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform );
27596
27597			}
27598
27599		}
27600
27601		if ( material.clearcoat > 0 ) {
27602
27603			uniforms.clearcoat.value = material.clearcoat;
27604			uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
27605
27606			if ( material.clearcoatMap ) {
27607
27608				uniforms.clearcoatMap.value = material.clearcoatMap;
27609
27610				refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform );
27611
27612			}
27613
27614			if ( material.clearcoatRoughnessMap ) {
27615
27616				uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
27617
27618				refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform );
27619
27620			}
27621
27622			if ( material.clearcoatNormalMap ) {
27623
27624				uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
27625
27626				refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform );
27627
27628				uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
27629
27630				if ( material.side === BackSide ) {
27631
27632					uniforms.clearcoatNormalScale.value.negate();
27633
27634				}
27635
27636			}
27637
27638		}
27639
27640		if ( material.iridescence > 0 ) {
27641
27642			uniforms.iridescence.value = material.iridescence;
27643			uniforms.iridescenceIOR.value = material.iridescenceIOR;
27644			uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ];
27645			uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ];
27646
27647			if ( material.iridescenceMap ) {
27648
27649				uniforms.iridescenceMap.value = material.iridescenceMap;
27650
27651				refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform );
27652
27653			}
27654
27655			if ( material.iridescenceThicknessMap ) {
27656
27657				uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap;
27658
27659				refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform );
27660
27661			}
27662
27663		}
27664
27665		if ( material.transmission > 0 ) {
27666
27667			uniforms.transmission.value = material.transmission;
27668			uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
27669			uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
27670
27671			if ( material.transmissionMap ) {
27672
27673				uniforms.transmissionMap.value = material.transmissionMap;
27674
27675				refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform );
27676
27677			}
27678
27679			uniforms.thickness.value = material.thickness;
27680
27681			if ( material.thicknessMap ) {
27682
27683				uniforms.thicknessMap.value = material.thicknessMap;
27684
27685				refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform );
27686
27687			}
27688
27689			uniforms.attenuationDistance.value = material.attenuationDistance;
27690			uniforms.attenuationColor.value.copy( material.attenuationColor );
27691
27692		}
27693
27694		if ( material.anisotropy > 0 ) {
27695
27696			uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) );
27697
27698			if ( material.anisotropyMap ) {
27699
27700				uniforms.anisotropyMap.value = material.anisotropyMap;
27701
27702				refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform );
27703
27704			}
27705
27706		}
27707
27708		uniforms.specularIntensity.value = material.specularIntensity;
27709		uniforms.specularColor.value.copy( material.specularColor );
27710
27711		if ( material.specularColorMap ) {
27712
27713			uniforms.specularColorMap.value = material.specularColorMap;
27714
27715			refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform );
27716
27717		}
27718
27719		if ( material.specularIntensityMap ) {
27720
27721			uniforms.specularIntensityMap.value = material.specularIntensityMap;
27722
27723			refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform );
27724
27725		}
27726
27727	}
27728
27729	function refreshUniformsMatcap( uniforms, material ) {
27730
27731		if ( material.matcap ) {
27732
27733			uniforms.matcap.value = material.matcap;
27734
27735		}
27736
27737	}
27738
27739	function refreshUniformsDistance( uniforms, material ) {
27740
27741		const light = properties.get( material ).light;
27742
27743		uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld );
27744		uniforms.nearDistance.value = light.shadow.camera.near;
27745		uniforms.farDistance.value = light.shadow.camera.far;
27746
27747	}
27748
27749	return {
27750		refreshFogUniforms: refreshFogUniforms,
27751		refreshMaterialUniforms: refreshMaterialUniforms
27752	};
27753
27754}
27755
27756function WebGLUniformsGroups( gl, info, capabilities, state ) {
27757
27758	let buffers = {};
27759	let updateList = {};
27760	let allocatedBindingPoints = [];
27761
27762	const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program
27763
27764	function bind( uniformsGroup, program ) {
27765
27766		const webglProgram = program.program;
27767		state.uniformBlockBinding( uniformsGroup, webglProgram );
27768
27769	}
27770
27771	function update( uniformsGroup, program ) {
27772
27773		let buffer = buffers[ uniformsGroup.id ];
27774
27775		if ( buffer === undefined ) {
27776
27777			prepareUniformsGroup( uniformsGroup );
27778
27779			buffer = createBuffer( uniformsGroup );
27780			buffers[ uniformsGroup.id ] = buffer;
27781
27782			uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose );
27783
27784		}
27785
27786		// ensure to update the binding points/block indices mapping for this program
27787
27788		const webglProgram = program.program;
27789		state.updateUBOMapping( uniformsGroup, webglProgram );
27790
27791		// update UBO once per frame
27792
27793		const frame = info.render.frame;
27794
27795		if ( updateList[ uniformsGroup.id ] !== frame ) {
27796
27797			updateBufferData( uniformsGroup );
27798
27799			updateList[ uniformsGroup.id ] = frame;
27800
27801		}
27802
27803	}
27804
27805	function createBuffer( uniformsGroup ) {
27806
27807		// the setup of an UBO is independent of a particular shader program but global
27808
27809		const bindingPointIndex = allocateBindingPointIndex();
27810		uniformsGroup.__bindingPointIndex = bindingPointIndex;
27811
27812		const buffer = gl.createBuffer();
27813		const size = uniformsGroup.__size;
27814		const usage = uniformsGroup.usage;
27815
27816		gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
27817		gl.bufferData( gl.UNIFORM_BUFFER, size, usage );
27818		gl.bindBuffer( gl.UNIFORM_BUFFER, null );
27819		gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer );
27820
27821		return buffer;
27822
27823	}
27824
27825	function allocateBindingPointIndex() {
27826
27827		for ( let i = 0; i < maxBindingPoints; i ++ ) {
27828
27829			if ( allocatedBindingPoints.indexOf( i ) === - 
vendor: 6,630 bytes, lines 27829-28154
278291 ) {
27830
27831				allocatedBindingPoints.push( i );
27832				return i;
27833
27834			}
27835
27836		}
27837
27838		console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' );
27839
27840		return 0;
27841
27842	}
27843
27844	function updateBufferData( uniformsGroup ) {
27845
27846		const buffer = buffers[ uniformsGroup.id ];
27847		const uniforms = uniformsGroup.uniforms;
27848		const cache = uniformsGroup.__cache;
27849
27850		gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
27851
27852		for ( let i = 0, il = uniforms.length; i < il; i ++ ) {
27853
27854			const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ];
27855
27856			for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) {
27857
27858				const uniform = uniformArray[ j ];
27859
27860				if ( hasUniformChanged( uniform, i, j, cache ) === true ) {
27861
27862					const offset = uniform.__offset;
27863
27864					const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
27865
27866					let arrayOffset = 0;
27867
27868					for ( let k = 0; k < values.length; k ++ ) {
27869
27870						const value = values[ k ];
27871
27872						const info = getUniformSize( value );
27873
27874						// TODO add integer and struct support
27875						if ( typeof value === 'number' || typeof value === 'boolean' ) {
27876
27877							uniform.__data[ 0 ] = value;
27878							gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data );
27879
27880						} else if ( value.isMatrix3 ) {
27881
27882							// manually converting 3x3 to 3x4
27883
27884							uniform.__data[ 0 ] = value.elements[ 0 ];
27885							uniform.__data[ 1 ] = value.elements[ 1 ];
27886							uniform.__data[ 2 ] = value.elements[ 2 ];
27887							uniform.__data[ 3 ] = 0;
27888							uniform.__data[ 4 ] = value.elements[ 3 ];
27889							uniform.__data[ 5 ] = value.elements[ 4 ];
27890							uniform.__data[ 6 ] = value.elements[ 5 ];
27891							uniform.__data[ 7 ] = 0;
27892							uniform.__data[ 8 ] = value.elements[ 6 ];
27893							uniform.__data[ 9 ] = value.elements[ 7 ];
27894							uniform.__data[ 10 ] = value.elements[ 8 ];
27895							uniform.__data[ 11 ] = 0;
27896
27897						} else {
27898
27899							value.toArray( uniform.__data, arrayOffset );
27900
27901							arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
27902
27903						}
27904
27905					}
27906
27907					gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data );
27908
27909				}
27910
27911			}
27912
27913		}
27914
27915		gl.bindBuffer( gl.UNIFORM_BUFFER, null );
27916
27917	}
27918
27919	function hasUniformChanged( uniform, index, indexArray, cache ) {
27920
27921		const value = uniform.value;
27922		const indexString = index + '_' + indexArray;
27923
27924		if ( cache[ indexString ] === undefined ) {
27925
27926			// cache entry does not exist so far
27927
27928			if ( typeof value === 'number' || typeof value === 'boolean' ) {
27929
27930				cache[ indexString ] = value;
27931
27932			} else {
27933
27934				cache[ indexString ] = value.clone();
27935
27936			}
27937
27938			return true;
27939
27940		} else {
27941
27942			const cachedObject = cache[ indexString ];
27943
27944			// compare current value with cached entry
27945
27946			if ( typeof value === 'number' || typeof value === 'boolean' ) {
27947
27948				if ( cachedObject !== value ) {
27949
27950					cache[ indexString ] = value;
27951					return true;
27952
27953				}
27954
27955			} else {
27956
27957				if ( cachedObject.equals( value ) === false ) {
27958
27959					cachedObject.copy( value );
27960					return true;
27961
27962				}
27963
27964			}
27965
27966		}
27967
27968		return false;
27969
27970	}
27971
27972	function prepareUniformsGroup( uniformsGroup ) {
27973
27974		// determine total buffer size according to the STD140 layout
27975		// Hint: STD140 is the only supported layout in WebGL 2
27976
27977		const uniforms = uniformsGroup.uniforms;
27978
27979		let offset = 0; // global buffer offset in bytes
27980		const chunkSize = 16; // size of a chunk in bytes
27981
27982		for ( let i = 0, l = uniforms.length; i < l; i ++ ) {
27983
27984			const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ];
27985
27986			for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) {
27987
27988				const uniform = uniformArray[ j ];
27989
27990				const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
27991
27992				for ( let k = 0, kl = values.length; k < kl; k ++ ) {
27993
27994					const value = values[ k ];
27995
27996					const info = getUniformSize( value );
27997
27998					// Calculate the chunk offset
27999					const chunkOffsetUniform = offset % chunkSize;
28000
28001					// Check for chunk overflow
28002					if ( chunkOffsetUniform !== 0 && ( chunkSize - chunkOffsetUniform ) < info.boundary ) {
28003
28004						// Add padding and adjust offset
28005						offset += ( chunkSize - chunkOffsetUniform );
28006
28007					}
28008
28009					// the following two properties will be used for partial buffer updates
28010
28011					uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT );
28012					uniform.__offset = offset;
28013
28014
28015					// Update the global offset
28016					offset += info.storage;
28017
28018
28019				}
28020
28021			}
28022
28023		}
28024
28025		// ensure correct final padding
28026
28027		const chunkOffset = offset % chunkSize;
28028
28029		if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset );
28030
28031		//
28032
28033		uniformsGroup.__size = offset;
28034		uniformsGroup.__cache = {};
28035
28036		return this;
28037
28038	}
28039
28040	function getUniformSize( value ) {
28041
28042		const info = {
28043			boundary: 0, // bytes
28044			storage: 0 // bytes
28045		};
28046
28047		// determine sizes according to STD140
28048
28049		if ( typeof value === 'number' || typeof value === 'boolean' ) {
28050
28051			// float/int/bool
28052
28053			info.boundary = 4;
28054			info.storage = 4;
28055
28056		} else if ( value.isVector2 ) {
28057
28058			// vec2
28059
28060			info.boundary = 8;
28061			info.storage = 8;
28062
28063		} else if ( value.isVector3 || value.isColor ) {
28064
28065			// vec3
28066
28067			info.boundary = 16;
28068			info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes
28069
28070		} else if ( value.isVector4 ) {
28071
28072			// vec4
28073
28074			info.boundary = 16;
28075			info.storage = 16;
28076
28077		} else if ( value.isMatrix3 ) {
28078
28079			// mat3 (in STD140 a 3x3 matrix is represented as 3x4)
28080
28081			info.boundary = 48;
28082			info.storage = 48;
28083
28084		} else if ( value.isMatrix4 ) {
28085
28086			// mat4
28087
28088			info.boundary = 64;
28089			info.storage = 64;
28090
28091		} else if ( value.isTexture ) {
28092
28093			console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' );
28094
28095		} else {
28096
28097			console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value );
28098
28099		}
28100
28101		return info;
28102
28103	}
28104
28105	function onUniformsGroupsDispose( event ) {
28106
28107		const uniformsGroup = event.target;
28108
28109		uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose );
28110
28111		const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex );
28112		allocatedBindingPoints.splice( index, 1 );
28113
28114		gl.deleteBuffer( buffers[ uniformsGroup.id ] );
28115
28116		delete buffers[ uniformsGroup.id ];
28117		delete updateList[ uniformsGroup.id ];
28118
28119	}
28120
28121	function dispose() {
28122
28123		for ( const id in buffers ) {
28124
28125			gl.deleteBuffer( buffers[ id ] );
28126
28127		}
28128
28129		allocatedBindingPoints = [];
28130		buffers = {};
28131		updateList = {};
28132
28133	}
28134
28135	return {
28136
28137		bind: bind,
28138		update: update,
28139
28140		dispose: dispose
28141
28142	};
28143
28144}
28145
28146class WebGLRenderer {
28147
28148	constructor( parameters = {} ) {
28149
28150		const {
28151			canvas = createCanvasElement(),
28152			context = null,
28153			depth = true,
28154			stencil = 
vendor: 28,003 bytes, lines 28154-29448
28154false,
28155			alpha = false,
28156			antialias = false,
28157			premultipliedAlpha = true,
28158			preserveDrawingBuffer = false,
28159			powerPreference = 'default',
28160			failIfMajorPerformanceCaveat = false,
28161		} = parameters;
28162
28163		this.isWebGLRenderer = true;
28164
28165		let _alpha;
28166
28167		if ( context !== null ) {
28168
28169			if ( typeof WebGLRenderingContext !== 'undefined' && context instanceof WebGLRenderingContext ) {
28170
28171				throw new Error( 'THREE.WebGLRenderer: WebGL 1 is not supported since r163.' );
28172
28173			}
28174
28175			_alpha = context.getContextAttributes().alpha;
28176
28177		} else {
28178
28179			_alpha = alpha;
28180
28181		}
28182
28183		const uintClearColor = new Uint32Array( 4 );
28184		const intClearColor = new Int32Array( 4 );
28185
28186		let currentRenderList = null;
28187		let currentRenderState = null;
28188
28189		// render() can be called from within a callback triggered by another render.
28190		// We track this so that the nested render call gets its list and state isolated from the parent render call.
28191
28192		const renderListStack = [];
28193		const renderStateStack = [];
28194
28195		// public properties
28196
28197		this.domElement = canvas;
28198
28199		// Debug configuration container
28200		this.debug = {
28201
28202			/**
28203			 * Enables error checking and reporting when shader programs are being compiled
28204			 * @type {boolean}
28205			 */
28206			checkShaderErrors: true,
28207			/**
28208			 * Callback for custom error reporting.
28209			 * @type {?Function}
28210			 */
28211			onShaderError: null
28212		};
28213
28214		// clearing
28215
28216		this.autoClear = true;
28217		this.autoClearColor = true;
28218		this.autoClearDepth = true;
28219		this.autoClearStencil = true;
28220
28221		// scene graph
28222
28223		this.sortObjects = true;
28224
28225		// user-defined clipping
28226
28227		this.clippingPlanes = [];
28228		this.localClippingEnabled = false;
28229
28230		// physically based shading
28231
28232		this._outputColorSpace = SRGBColorSpace;
28233
28234		// physical lights
28235
28236		this._useLegacyLights = false;
28237
28238		// tone mapping
28239
28240		this.toneMapping = NoToneMapping;
28241		this.toneMappingExposure = 1.0;
28242
28243		// internal properties
28244
28245		const _this = this;
28246
28247		let _isContextLost = false;
28248
28249		// internal state cache
28250
28251		let _currentActiveCubeFace = 0;
28252		let _currentActiveMipmapLevel = 0;
28253		let _currentRenderTarget = null;
28254		let _currentMaterialId = - 1;
28255
28256		let _currentCamera = null;
28257
28258		const _currentViewport = new Vector4();
28259		const _currentScissor = new Vector4();
28260		let _currentScissorTest = null;
28261
28262		const _currentClearColor = new Color( 0x000000 );
28263		let _currentClearAlpha = 0;
28264
28265		//
28266
28267		let _width = canvas.width;
28268		let _height = canvas.height;
28269
28270		let _pixelRatio = 1;
28271		let _opaqueSort = null;
28272		let _transparentSort = null;
28273
28274		const _viewport = new Vector4( 0, 0, _width, _height );
28275		const _scissor = new Vector4( 0, 0, _width, _height );
28276		let _scissorTest = false;
28277
28278		// frustum
28279
28280		const _frustum = new Frustum();
28281
28282		// clipping
28283
28284		let _clippingEnabled = false;
28285		let _localClippingEnabled = false;
28286
28287		// camera matrices cache
28288
28289		const _projScreenMatrix = new Matrix4();
28290
28291		const _vector2 = new Vector2();
28292		const _vector3 = new Vector3();
28293
28294		const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
28295
28296		function getTargetPixelRatio() {
28297
28298			return _currentRenderTarget === null ? _pixelRatio : 1;
28299
28300		}
28301
28302		// initialize
28303
28304		let _gl = context;
28305
28306		function getContext( contextName, contextAttributes ) {
28307
28308			const context = canvas.getContext( contextName, contextAttributes );
28309			if ( context !== null ) return context;
28310
28311			return null;
28312
28313		}
28314
28315		try {
28316
28317			const contextAttributes = {
28318				alpha: true,
28319				depth,
28320				stencil,
28321				antialias,
28322				premultipliedAlpha,
28323				preserveDrawingBuffer,
28324				powerPreference,
28325				failIfMajorPerformanceCaveat,
28326			};
28327
28328			// OffscreenCanvas does not have setAttribute, see #22811
28329			if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` );
28330
28331			// event listeners must be registered before WebGL context is created, see #12753
28332			canvas.addEventListener( 'webglcontextlost', onContextLost, false );
28333			canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
28334			canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false );
28335
28336			if ( _gl === null ) {
28337
28338				const contextName = 'webgl2';
28339
28340				_gl = getContext( contextName, contextAttributes );
28341
28342				if ( _gl === null ) {
28343
28344					if ( getContext( contextName ) ) {
28345
28346						throw new Error( 'Error creating WebGL context with your selected attributes.' );
28347
28348					} else {
28349
28350						throw new Error( 'Error creating WebGL context.' );
28351
28352					}
28353
28354				}
28355
28356			}
28357
28358		} catch ( error ) {
28359
28360			console.error( 'THREE.WebGLRenderer: ' + error.message );
28361			throw error;
28362
28363		}
28364
28365		let extensions, capabilities, state, info;
28366		let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
28367		let programCache, materials, renderLists, renderStates, clipping, shadowMap;
28368
28369		let background, morphtargets, bufferRenderer, indexedBufferRenderer;
28370
28371		let utils, bindingStates, uniformsGroups;
28372
28373		function initGLContext() {
28374
28375			extensions = new WebGLExtensions( _gl );
28376			extensions.init();
28377
28378			capabilities = new WebGLCapabilities( _gl, extensions, parameters );
28379
28380			utils = new WebGLUtils( _gl, extensions );
28381
28382			state = new WebGLState( _gl );
28383
28384			info = new WebGLInfo( _gl );
28385			properties = new WebGLProperties();
28386			textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
28387			cubemaps = new WebGLCubeMaps( _this );
28388			cubeuvmaps = new WebGLCubeUVMaps( _this );
28389			attributes = new WebGLAttributes( _gl );
28390			bindingStates = new WebGLBindingStates( _gl, attributes );
28391			geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
28392			objects = new WebGLObjects( _gl, geometries, attributes, info );
28393			morphtargets = new WebGLMorphtargets( _gl, capabilities, textures );
28394			clipping = new WebGLClipping( properties );
28395			programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );
28396			materials = new WebGLMaterials( _this, properties );
28397			renderLists = new WebGLRenderLists();
28398			renderStates = new WebGLRenderStates( extensions );
28399			background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha );
28400			shadowMap = new WebGLShadowMap( _this, objects, capabilities );
28401			uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state );
28402
28403			bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
28404			indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
28405
28406			info.programs = programCache.programs;
28407
28408			_this.capabilities = capabilities;
28409			_this.extensions = extensions;
28410			_this.properties = properties;
28411			_this.renderLists = renderLists;
28412			_this.shadowMap = shadowMap;
28413			_this.state = state;
28414			_this.info = info;
28415
28416		}
28417
28418		initGLContext();
28419
28420		// xr
28421
28422		const xr = new WebXRManager( _this, _gl );
28423
28424		this.xr = xr;
28425
28426		// API
28427
28428		this.getContext = function () {
28429
28430			return _gl;
28431
28432		};
28433
28434		this.getContextAttributes = function () {
28435
28436			return _gl.getContextAttributes();
28437
28438		};
28439
28440		this.forceContextLoss = function () {
28441
28442			const extension = extensions.get( 'WEBGL_lose_context' );
28443			if ( extension ) extension.loseContext();
28444
28445		};
28446
28447		this.forceContextRestore = function () {
28448
28449			const extension = extensions.get( 'WEBGL_lose_context' );
28450			if ( extension ) extension.restoreContext();
28451
28452		};
28453
28454		this.getPixelRatio = function () {
28455
28456			return _pixelRatio;
28457
28458		};
28459
28460		this.setPixelRatio = function ( value ) {
28461
28462			if ( value === undefined ) return;
28463
28464			_pixelRatio = value;
28465
28466			this.setSize( _width, _height, false );
28467
28468		};
28469
28470		this.getSize = function ( target ) {
28471
28472			return target.set( _width, _height );
28473
28474		};
28475
28476		this.setSize = function ( width, height, updateStyle = true ) {
28477
28478			if ( xr.isPresenting ) {
28479
28480				console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
28481				return;
28482
28483			}
28484
28485			_width = width;
28486			_height = height;
28487
28488			canvas.width = Math.floor( width * _pixelRatio );
28489			canvas.height = Math.floor( height * _pixelRatio );
28490
28491			if ( updateStyle === true ) {
28492
28493				canvas.style.width = width + 'px';
28494				canvas.style.height = height + 'px';
28495
28496			}
28497
28498			this.setViewport( 0, 0, width, height );
28499
28500		};
28501
28502		this.getDrawingBufferSize = function ( target ) {
28503
28504			return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
28505
28506		};
28507
28508		this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
28509
28510			_width = width;
28511			_height = height;
28512
28513			_pixelRatio = pixelRatio;
28514
28515			canvas.width = Math.floor( width * pixelRatio );
28516			canvas.height = Math.floor( height * pixelRatio );
28517
28518			this.setViewport( 0, 0, width, height );
28519
28520		};
28521
28522		this.getCurrentViewport = function ( target ) {
28523
28524			return target.copy( _currentViewport );
28525
28526		};
28527
28528		this.getViewport = function ( target ) {
28529
28530			return target.copy( _viewport );
28531
28532		};
28533
28534		this.setViewport = function ( x, y, width, height ) {
28535
28536			if ( x.isVector4 ) {
28537
28538				_viewport.set( x.x, x.y, x.z, x.w );
28539
28540			} else {
28541
28542				_viewport.set( x, y, width, height );
28543
28544			}
28545
28546			state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() );
28547
28548		};
28549
28550		this.getScissor = function ( target ) {
28551
28552			return target.copy( _scissor );
28553
28554		};
28555
28556		this.setScissor = function ( x, y, width, height ) {
28557
28558			if ( x.isVector4 ) {
28559
28560				_scissor.set( x.x, x.y, x.z, x.w );
28561
28562			} else {
28563
28564				_scissor.set( x, y, width, height );
28565
28566			}
28567
28568			state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() );
28569
28570		};
28571
28572		this.getScissorTest = function () {
28573
28574			return _scissorTest;
28575
28576		};
28577
28578		this.setScissorTest = function ( boolean ) {
28579
28580			state.setScissorTest( _scissorTest = boolean );
28581
28582		};
28583
28584		this.setOpaqueSort = function ( method ) {
28585
28586			_opaqueSort = method;
28587
28588		};
28589
28590		this.setTransparentSort = function ( method ) {
28591
28592			_transparentSort = method;
28593
28594		};
28595
28596		// Clearing
28597
28598		this.getClearColor = function ( target ) {
28599
28600			return target.copy( background.getClearColor() );
28601
28602		};
28603
28604		this.setClearColor = function () {
28605
28606			background.setClearColor.apply( background, arguments );
28607
28608		};
28609
28610		this.getClearAlpha = function () {
28611
28612			return background.getClearAlpha();
28613
28614		};
28615
28616		this.setClearAlpha = function () {
28617
28618			background.setClearAlpha.apply( background, arguments );
28619
28620		};
28621
28622		this.clear = function ( color = true, depth = true, stencil = true ) {
28623
28624			let bits = 0;
28625
28626			if ( color ) {
28627
28628				// check if we're trying to clear an integer target
28629				let isIntegerFormat = false;
28630				if ( _currentRenderTarget !== null ) {
28631
28632					const targetFormat = _currentRenderTarget.texture.format;
28633					isIntegerFormat = targetFormat === RGBAIntegerFormat ||
28634						targetFormat === RGIntegerFormat ||
28635						targetFormat === RedIntegerFormat;
28636
28637				}
28638
28639				// use the appropriate clear functions to clear the target if it's a signed
28640				// or unsigned integer target
28641				if ( isIntegerFormat ) {
28642
28643					const targetType = _currentRenderTarget.texture.type;
28644					const isUnsignedType = targetType === UnsignedByteType ||
28645						targetType === UnsignedIntType ||
28646						targetType === UnsignedShortType ||
28647						targetType === UnsignedInt248Type ||
28648						targetType === UnsignedShort4444Type ||
28649						targetType === UnsignedShort5551Type;
28650
28651					const clearColor = background.getClearColor();
28652					const a = background.getClearAlpha();
28653					const r = clearColor.r;
28654					const g = clearColor.g;
28655					const b = clearColor.b;
28656
28657					if ( isUnsignedType ) {
28658
28659						uintClearColor[ 0 ] = r;
28660						uintClearColor[ 1 ] = g;
28661						uintClearColor[ 2 ] = b;
28662						uintClearColor[ 3 ] = a;
28663						_gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor );
28664
28665					} else {
28666
28667						intClearColor[ 0 ] = r;
28668						intClearColor[ 1 ] = g;
28669						intClearColor[ 2 ] = b;
28670						intClearColor[ 3 ] = a;
28671						_gl.clearBufferiv( _gl.COLOR, 0, intClearColor );
28672
28673					}
28674
28675				} else {
28676
28677					bits |= _gl.COLOR_BUFFER_BIT;
28678
28679				}
28680
28681			}
28682
28683			if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT;
28684			if ( stencil ) {
28685
28686				bits |= _gl.STENCIL_BUFFER_BIT;
28687				this.state.buffers.stencil.setMask( 0xffffffff );
28688
28689			}
28690
28691			_gl.clear( bits );
28692
28693		};
28694
28695		this.clearColor = function () {
28696
28697			this.clear( true, false, false );
28698
28699		};
28700
28701		this.clearDepth = function () {
28702
28703			this.clear( false, true, false );
28704
28705		};
28706
28707		this.clearStencil = function () {
28708
28709			this.clear( false, false, true );
28710
28711		};
28712
28713		//
28714
28715		this.dispose = function () {
28716
28717			canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
28718			canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
28719			canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false );
28720
28721			renderLists.dispose();
28722			renderStates.dispose();
28723			properties.dispose();
28724			cubemaps.dispose();
28725			cubeuvmaps.dispose();
28726			objects.dispose();
28727			bindingStates.dispose();
28728			uniformsGroups.dispose();
28729			programCache.dispose();
28730
28731			xr.dispose();
28732
28733			xr.removeEventListener( 'sessionstart', onXRSessionStart );
28734			xr.removeEventListener( 'sessionend', onXRSessionEnd );
28735
28736			animation.stop();
28737
28738		};
28739
28740		// Events
28741
28742		function onContextLost( event ) {
28743
28744			event.preventDefault();
28745
28746			console.log( 'THREE.WebGLRenderer: Context Lost.' );
28747
28748			_isContextLost = true;
28749
28750		}
28751
28752		function onContextRestore( /* event */ ) {
28753
28754			console.log( 'THREE.WebGLRenderer: Context Restored.' );
28755
28756			_isContextLost = false;
28757
28758			const infoAutoReset = info.autoReset;
28759			const shadowMapEnabled = shadowMap.enabled;
28760			const shadowMapAutoUpdate = shadowMap.autoUpdate;
28761			const shadowMapNeedsUpdate = shadowMap.needsUpdate;
28762			const shadowMapType = shadowMap.type;
28763
28764			initGLContext();
28765
28766			info.autoReset = infoAutoReset;
28767			shadowMap.enabled = shadowMapEnabled;
28768			shadowMap.autoUpdate = shadowMapAutoUpdate;
28769			shadowMap.needsUpdate = shadowMapNeedsUpdate;
28770			shadowMap.type = shadowMapType;
28771
28772		}
28773
28774		function onContextCreationError( event ) {
28775
28776			console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage );
28777
28778		}
28779
28780		function onMaterialDispose( event ) {
28781
28782			const material = event.target;
28783
28784			material.removeEventListener( 'dispose', onMaterialDispose );
28785
28786			deallocateMaterial( material );
28787
28788		}
28789
28790		// Buffer deallocation
28791
28792		function deallocateMaterial( material ) {
28793
28794			releaseMaterialProgramReferences( material );
28795
28796			properties.remove( material );
28797
28798		}
28799
28800
28801		function releaseMaterialProgramReferences( material ) {
28802
28803			const programs = properties.get( material ).programs;
28804
28805			if ( programs !== undefined ) {
28806
28807				programs.forEach( function ( program ) {
28808
28809					programCache.releaseProgram( program );
28810
28811				} );
28812
28813				if ( material.isShaderMaterial ) {
28814
28815					programCache.releaseShaderCache( material );
28816
28817				}
28818
28819			}
28820
28821		}
28822
28823		// Buffer rendering
28824
28825		this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
28826
28827			if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
28828
28829			const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
28830
28831			const program = setProgram( camera, scene, geometry, material, object );
28832
28833			state.setMaterial( material, frontFaceCW );
28834
28835			//
28836
28837			let index = geometry.index;
28838			let rangeFactor = 1;
28839
28840			if ( material.wireframe === true ) {
28841
28842				index = geometries.getWireframeAttribute( geometry );
28843
28844				if ( index === undefined ) return;
28845
28846				rangeFactor = 2;
28847
28848			}
28849
28850			//
28851
28852			const drawRange = geometry.drawRange;
28853			const position = geometry.attributes.position;
28854
28855			let drawStart = drawRange.start * rangeFactor;
28856			let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor;
28857
28858			if ( group !== null ) {
28859
28860				drawStart = Math.max( drawStart, group.start * rangeFactor );
28861				drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor );
28862
28863			}
28864
28865			if ( index !== null ) {
28866
28867				drawStart = Math.max( drawStart, 0 );
28868				drawEnd = Math.min( drawEnd, index.count );
28869
28870			} else if ( position !== undefined && position !== null ) {
28871
28872				drawStart = Math.max( drawStart, 0 );
28873				drawEnd = Math.min( drawEnd, position.count );
28874
28875			}
28876
28877			const drawCount = drawEnd - drawStart;
28878
28879			if ( drawCount < 0 || drawCount === Infinity ) return;
28880
28881			//
28882
28883			bindingStates.setup( object, material, program, geometry, index );
28884
28885			let attribute;
28886			let renderer = bufferRenderer;
28887
28888			if ( index !== null ) {
28889
28890				attribute = attributes.get( index );
28891
28892				renderer = indexedBufferRenderer;
28893				renderer.setIndex( attribute );
28894
28895			}
28896
28897			//
28898
28899			if ( object.isMesh ) {
28900
28901				if ( material.wireframe === true ) {
28902
28903					state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
28904					renderer.setMode( _gl.LINES );
28905
28906				} else {
28907
28908					renderer.setMode( _gl.TRIANGLES );
28909
28910				}
28911
28912			} else if ( object.isLine ) {
28913
28914				let lineWidth = material.linewidth;
28915
28916				if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
28917
28918				state.setLineWidth( lineWidth * getTargetPixelRatio() );
28919
28920				if ( object.isLineSegments ) {
28921
28922					renderer.setMode( _gl.LINES );
28923
28924				} else if ( object.isLineLoop ) {
28925
28926					renderer.setMode( _gl.LINE_LOOP );
28927
28928				} else {
28929
28930					renderer.setMode( _gl.LINE_STRIP );
28931
28932				}
28933
28934			} else if ( object.isPoints ) {
28935
28936				renderer.setMode( _gl.POINTS );
28937
28938			} else if ( object.isSprite ) {
28939
28940				renderer.setMode( _gl.TRIANGLES );
28941
28942			}
28943
28944			if ( object.isBatchedMesh ) {
28945
28946				renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount );
28947
28948			} else if ( object.isInstancedMesh ) {
28949
28950				renderer.renderInstances( drawStart, drawCount, object.count );
28951
28952			} else if ( geometry.isInstancedBufferGeometry ) {
28953
28954				const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity;
28955				const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount );
28956
28957				renderer.renderInstances( drawStart, drawCount, instanceCount );
28958
28959			} else {
28960
28961				renderer.render( drawStart, drawCount );
28962
28963			}
28964
28965		};
28966
28967		// Compile
28968
28969		function prepareMaterial( material, scene, object ) {
28970
28971			if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
28972
28973				material.side = BackSide;
28974				material.needsUpdate = true;
28975				getProgram( material, scene, object );
28976
28977				material.side = FrontSide;
28978				material.needsUpdate = true;
28979				getProgram( material, scene, object );
28980
28981				material.side = DoubleSide;
28982
28983			} else {
28984
28985				getProgram( material, scene, object );
28986
28987			}
28988
28989		}
28990
28991		this.compile = function ( scene, camera, targetScene = null ) {
28992
28993			if ( targetScene === null ) targetScene = scene;
28994
28995			currentRenderState = renderStates.get( targetScene );
28996			currentRenderState.init();
28997
28998			renderStateStack.push( currentRenderState );
28999
29000			// gather lights from both the target scene and the new object that will be added to the scene.
29001
29002			targetScene.traverseVisible( function ( object ) {
29003
29004				if ( object.isLight && object.layers.test( camera.layers ) ) {
29005
29006					currentRenderState.pushLight( object );
29007
29008					if ( object.castShadow ) {
29009
29010						currentRenderState.pushShadow( object );
29011
29012					}
29013
29014				}
29015
29016			} );
29017
29018			if ( scene !== targetScene ) {
29019
29020				scene.traverseVisible( function ( object ) {
29021
29022					if ( object.isLight && object.layers.test( camera.layers ) ) {
29023
29024						currentRenderState.pushLight( object );
29025
29026						if ( object.castShadow ) {
29027
29028							currentRenderState.pushShadow( object );
29029
29030						}
29031
29032					}
29033
29034				} );
29035
29036			}
29037
29038			currentRenderState.setupLights( _this._useLegacyLights );
29039
29040			// Only initialize materials in the new scene, not the targetScene.
29041
29042			const materials = new Set();
29043
29044			scene.traverse( function ( object ) {
29045
29046				const material = object.material;
29047
29048				if ( material ) {
29049
29050					if ( Array.isArray( material ) ) {
29051
29052						for ( let i = 0; i < material.length; i ++ ) {
29053
29054							const material2 = material[ i ];
29055
29056							prepareMaterial( material2, targetScene, object );
29057							materials.add( material2 );
29058
29059						}
29060
29061					} else {
29062
29063						prepareMaterial( material, targetScene, object );
29064						materials.add( material );
29065
29066					}
29067
29068				}
29069
29070			} );
29071
29072			renderStateStack.pop();
29073			currentRenderState = null;
29074
29075			return materials;
29076
29077		};
29078
29079		// compileAsync
29080
29081		this.compileAsync = function ( scene, camera, targetScene = null ) {
29082
29083			const materials = this.compile( scene, camera, targetScene );
29084
29085			// Wait for all the materials in the new object to indicate that they're
29086			// ready to be used before resolving the promise.
29087
29088			return new Promise( ( resolve ) => {
29089
29090				function checkMaterialsReady() {
29091
29092					materials.forEach( function ( material ) {
29093
29094						const materialProperties = properties.get( material );
29095						const program = materialProperties.currentProgram;
29096
29097						if ( program.isReady() ) {
29098
29099							// remove any programs that report they're ready to use from the list
29100							materials.delete( material );
29101
29102						}
29103
29104					} );
29105
29106					// once the list of compiling materials is empty, call the callback
29107
29108					if ( materials.size === 0 ) {
29109
29110						resolve( scene );
29111						return;
29112
29113					}
29114
29115					// if some materials are still not ready, wait a bit and check again
29116
29117					setTimeout( checkMaterialsReady, 10 );
29118
29119				}
29120
29121				if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) {
29122
29123					// If we can check the compilation status of the materials without
29124					// blocking then do so right away.
29125
29126					checkMaterialsReady();
29127
29128				} else {
29129
29130					// Otherwise start by waiting a bit to give the materials we just
29131					// initialized a chance to finish.
29132
29133					setTimeout( checkMaterialsReady, 10 );
29134
29135				}
29136
29137			} );
29138
29139		};
29140
29141		// Animation Loop
29142
29143		let onAnimationFrameCallback = null;
29144
29145		function onAnimationFrame( time ) {
29146
29147			if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
29148
29149		}
29150
29151		function onXRSessionStart() {
29152
29153			animation.stop();
29154
29155		}
29156
29157		function onXRSessionEnd() {
29158
29159			animation.start();
29160
29161		}
29162
29163		const animation = new WebGLAnimation();
29164		animation.setAnimationLoop( onAnimationFrame );
29165
29166		if ( typeof self !== 'undefined' ) animation.setContext( self );
29167
29168		this.setAnimationLoop = function ( callback ) {
29169
29170			onAnimationFrameCallback = callback;
29171			xr.setAnimationLoop( callback );
29172
29173			( callback === null ) ? animation.stop() : animation.start();
29174
29175		};
29176
29177		xr.addEventListener( 'sessionstart', onXRSessionStart );
29178		xr.addEventListener( 'sessionend', onXRSessionEnd );
29179
29180		// Rendering
29181
29182		this.render = function ( scene, camera ) {
29183
29184			if ( camera !== undefined && camera.isCamera !== true ) {
29185
29186				console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
29187				return;
29188
29189			}
29190
29191			if ( _isContextLost === true ) return;
29192
29193			// update scene graph
29194
29195			if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
29196
29197			// update camera matrices and frustum
29198
29199			if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
29200
29201			if ( xr.enabled === true && xr.isPresenting === true ) {
29202
29203				if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera );
29204
29205				camera = xr.getCamera(); // use XR camera for rendering
29206
29207			}
29208
29209			//
29210			if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget );
29211
29212			currentRenderState = renderStates.get( scene, renderStateStack.length );
29213			currentRenderState.init();
29214
29215			renderStateStack.push( currentRenderState );
29216
29217			_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
29218			_frustum.setFromProjectionMatrix( _projScreenMatrix );
29219
29220			_localClippingEnabled = this.localClippingEnabled;
29221			_clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled );
29222
29223			currentRenderList = renderLists.get( scene, renderListStack.length );
29224			currentRenderList.init();
29225
29226			renderListStack.push( currentRenderList );
29227
29228			projectObject( scene, camera, 0, _this.sortObjects );
29229
29230			currentRenderList.finish();
29231
29232			if ( _this.sortObjects === true ) {
29233
29234				currentRenderList.sort( _opaqueSort, _transparentSort );
29235
29236			}
29237
29238			//
29239
29240			this.info.render.frame ++;
29241
29242			if ( _clippingEnabled === true ) clipping.beginShadows();
29243
29244			const shadowsArray = currentRenderState.state.shadowsArray;
29245
29246			shadowMap.render( shadowsArray, scene, camera );
29247
29248			if ( _clippingEnabled === true ) clipping.endShadows();
29249
29250			//
29251
29252			if ( this.info.autoReset === true ) this.info.reset();
29253
29254
29255			//
29256
29257			if ( xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false ) {
29258
29259				background.render( currentRenderList, scene );
29260
29261			}
29262
29263			// render scene
29264
29265			currentRenderState.setupLights( _this._useLegacyLights );
29266
29267			if ( camera.isArrayCamera ) {
29268
29269				const cameras = camera.cameras;
29270
29271				for ( let i = 0, l = cameras.length; i < l; i ++ ) {
29272
29273					const camera2 = cameras[ i ];
29274
29275					renderScene( currentRenderList, scene, camera2, camera2.viewport );
29276
29277				}
29278
29279			} else {
29280
29281				renderScene( currentRenderList, scene, camera );
29282
29283			}
29284
29285			//
29286
29287			if ( _currentRenderTarget !== null ) {
29288
29289				// resolve multisample renderbuffers to a single-sample texture if necessary
29290
29291				textures.updateMultisampleRenderTarget( _currentRenderTarget );
29292
29293				// Generate mipmap if we're using any kind of mipmap filtering
29294
29295				textures.updateRenderTargetMipmap( _currentRenderTarget );
29296
29297			}
29298
29299			//
29300
29301			if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
29302
29303			// _gl.finish();
29304
29305			bindingStates.resetDefaultState();
29306			_currentMaterialId = - 1;
29307			_currentCamera = null;
29308
29309			renderStateStack.pop();
29310
29311			if ( renderStateStack.length > 0 ) {
29312
29313				currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
29314
29315			} else {
29316
29317				currentRenderState = null;
29318
29319			}
29320
29321			renderListStack.pop();
29322
29323			if ( renderListStack.length > 0 ) {
29324
29325				currentRenderList = renderListStack[ renderListStack.length - 1 ];
29326
29327			} else {
29328
29329				currentRenderList = null;
29330
29331			}
29332
29333		};
29334
29335		function projectObject( object, camera, groupOrder, sortObjects ) {
29336
29337			if ( object.visible === false ) return;
29338
29339			const visible = object.layers.test( camera.layers );
29340
29341			if ( visible ) {
29342
29343				if ( object.isGroup ) {
29344
29345					groupOrder = object.renderOrder;
29346
29347				} else if ( object.isLOD ) {
29348
29349					if ( object.autoUpdate === true ) object.update( camera );
29350
29351				} else if ( object.isLight ) {
29352
29353					currentRenderState.pushLight( object );
29354
29355					if ( object.castShadow ) {
29356
29357						currentRenderState.pushShadow( object );
29358
29359					}
29360
29361				} else if ( object.isSprite ) {
29362
29363					if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
29364
29365						if ( sortObjects ) {
29366
29367							_vector3.setFromMatrixPosition( object.matrixWorld )
29368								.applyMatrix4( _projScreenMatrix );
29369
29370						}
29371
29372						const geometry = objects.update( object );
29373						const material = object.material;
29374
29375						if ( material.visible ) {
29376
29377							currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
29378
29379						}
29380
29381					}
29382
29383				} else if ( object.isMesh || object.isLine || object.isPoints ) {
29384
29385					if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
29386
29387						const geometry = objects.update( object );
29388						const material = object.material;
29389
29390						if ( sortObjects ) {
29391
29392							if ( object.boundingSphere !== undefined ) {
29393
29394								if ( object.boundingSphere === null ) object.computeBoundingSphere();
29395								_vector3.copy( object.boundingSphere.center );
29396
29397							} else {
29398
29399								if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
29400								_vector3.copy( geometry.boundingSphere.center );
29401
29402							}
29403
29404							_vector3
29405								.applyMatrix4( object.matrixWorld )
29406								.applyMatrix4( _projScreenMatrix );
29407
29408						}
29409
29410						if ( Array.isArray( material ) ) {
29411
29412							const groups = geometry.groups;
29413
29414							for ( let i = 0, l = groups.length; i < l; i ++ ) {
29415
29416								const group = groups[ i ];
29417								const groupMaterial = material[ group.materialIndex ];
29418
29419								if ( groupMaterial && groupMaterial.visible ) {
29420
29421									currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
29422
29423								}
29424
29425							}
29426
29427						} else if ( material.visible ) {
29428
29429							currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
29430
29431						}
29432
29433					}
29434
29435				}
29436
29437			}
29438
29439			const children = object.children;
29440
29441			for ( let i = 0, l = children.length; i < l; i ++ ) {
29442
29443				projectObject( children[ i ], camera, groupOrder, sortObjects );
29444
29445			}
29446
29447		}
29448
29449		function renderScene( currentRenderList, scene, camera, viewport ) {
29450
29451			const opaqueObjects = currentRenderList.opaque;
29452			const transmissiveObjects = currentRenderList.transmissive;
29453			const transparentObjects = currentRenderList.transparent;
29454
29455			currentRenderState.setupLightsView( camera );
29456
29457			if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera );
29458
29459			if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera );
29460
29461			if ( viewport ) state.viewport( _currentViewport.copy( viewport ) );
29462
29463			if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
29464			if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera );
29465			if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
29466
29467			// Ensure depth buffer writing is enabled so it can be cleared on next render
29468
29469			state.buffers.depth.setTest( true );
29470			state.buffers.depth.setMask( true );
29471			state.buffers.color.setMask( true );
29472
29473			state.setPolygonOffset( false );
29474
29475		}
29476
29477		function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) {
29478
29479			const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
29480
29481			if ( overrideMaterial !== null ) {
29482
29483				return;
29484
29485			}
29486
29487			if ( currentRenderState.state.transmissionRenderTarget === null ) {
29488
29489				currentRenderState.state.transmissionRenderTarget = new WebGLRenderTarget( 1, 1, {
29490					generateMipmaps: true,
29491					type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType,
29492					minFilter: LinearMipmapLinearFilter,
29493					samples: 4,
29494					stencilBuffer: stencil
29495				} );
29496
29497				const renderTargetProperties = properties.get( currentRenderState.state.transmissionRenderTarget );
29498				renderTargetProperties.__isTransmissionRenderTarget = true;
29499
29500				// debug
29501
29502				/*
29503				const geometry = new PlaneGeometry();
29504				const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } );
29505
29506				const mesh = new Mesh( geometry, material );
29507				scene.add( mesh );
29508				*/
29509
29510			}
29511
29512			const transmissionRenderTarget = currentRenderState.state.transmissionRenderTarget;
29513
29514			_this.getDrawingBufferSize( _vector2 );
29515			transmissionRenderTarget.setSize( _vector2.x, _vector2.y );
29516
29517			//
29518
29519			const currentRenderTarget = _this.getRenderTarget();
29520			_this.setRenderTarget( transmissionRenderTarget );
29521
29522			_this.getClearColor( _currentClearColor );
29523			_currentClearAlpha = _this.getClearAlpha();
29524			if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 );
29525
29526			_this.clear();
29527
29528			// Turn off the features which can affect the frag color for opaque objects pass.
29529			// Otherwise they are applied twice in opaque objects pass and transmission objects pass.
29530			const currentToneMapping = _this.toneMapping;
29531			_this.toneMapping = NoToneMapping;
29532
29533			renderObjects( opaqueObjects, scene, camera );
29534
29535			textures.updateMultisampleRenderTarget( transmissionRenderTarget );
29536			textures.updateRenderTargetMipmap( transmissionRenderTarget );
29537
29538			let renderTargetNeedsUpdate = false;
29539
29540			for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) {
29541
29542				const renderItem = transmissiveObjects[ i ];
29543
29544				const object = renderItem.object;
29545				const geometry = renderItem.geometry;
29546				const material = renderItem.material;
29547				const group = renderItem.group;
29548
29549				if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) {
29550
29551					const currentSide = material.side;
29552
29553					material.side = BackSide;
29554					material.needsUpdate = true;
29555
29556					renderObject( object, scene, camera, geometry, material, group );
29557
29558					material.side = currentSide;
29559					material.needsUpdate = true;
29560
29561					renderTargetNeedsUpdate = true;
29562
29563				}
29564
29565			}
29566
29567			if ( renderTargetNeedsUpdate === true ) {
29568
29569				textures.updateMultisampleRenderTarget( transmissionRenderTarget );
29570				textures.updateRenderTargetMipmap( 
vendor: 12,137 bytes, lines 29570-29927
29570transmissionRenderTarget );
29571
29572			}
29573
29574			_this.setRenderTarget( currentRenderTarget );
29575
29576			_this.setClearColor( _currentClearColor, _currentClearAlpha );
29577
29578			_this.toneMapping = currentToneMapping;
29579
29580		}
29581
29582		function renderObjects( renderList, scene, camera ) {
29583
29584			const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
29585
29586			for ( let i = 0, l = renderList.length; i < l; i ++ ) {
29587
29588				const renderItem = renderList[ i ];
29589
29590				const object = renderItem.object;
29591				const geometry = renderItem.geometry;
29592				const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
29593				const group = renderItem.group;
29594
29595				if ( object.layers.test( camera.layers ) ) {
29596
29597					renderObject( object, scene, camera, geometry, material, group );
29598
29599				}
29600
29601			}
29602
29603		}
29604
29605		function renderObject( object, scene, camera, geometry, material, group ) {
29606
29607			object.onBeforeRender( _this, scene, camera, geometry, material, group );
29608
29609			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
29610			object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
29611
29612			material.onBeforeRender( _this, scene, camera, geometry, object, group );
29613
29614			if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
29615
29616				material.side = BackSide;
29617				material.needsUpdate = true;
29618				_this.renderBufferDirect( camera, scene, geometry, material, object, group );
29619
29620				material.side = FrontSide;
29621				material.needsUpdate = true;
29622				_this.renderBufferDirect( camera, scene, geometry, material, object, group );
29623
29624				material.side = DoubleSide;
29625
29626			} else {
29627
29628				_this.renderBufferDirect( camera, scene, geometry, material, object, group );
29629
29630			}
29631
29632			object.onAfterRender( _this, scene, camera, geometry, material, group );
29633
29634		}
29635
29636		function getProgram( material, scene, object ) {
29637
29638			if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
29639
29640			const materialProperties = properties.get( material );
29641
29642			const lights = currentRenderState.state.lights;
29643			const shadowsArray = currentRenderState.state.shadowsArray;
29644
29645			const lightsStateVersion = lights.state.version;
29646
29647			const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
29648			const programCacheKey = programCache.getProgramCacheKey( parameters );
29649
29650			let programs = materialProperties.programs;
29651
29652			// always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change
29653
29654			materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
29655			materialProperties.fog = scene.fog;
29656			materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment );
29657			materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation;
29658
29659			if ( programs === undefined ) {
29660
29661				// new material
29662
29663				material.addEventListener( 'dispose', onMaterialDispose );
29664
29665				programs = new Map();
29666				materialProperties.programs = programs;
29667
29668			}
29669
29670			let program = programs.get( programCacheKey );
29671
29672			if ( program !== undefined ) {
29673
29674				// early out if program and light state is identical
29675
29676				if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) {
29677
29678					updateCommonMaterialProperties( material, parameters );
29679
29680					return program;
29681
29682				}
29683
29684			} else {
29685
29686				parameters.uniforms = programCache.getUniforms( material );
29687
29688				material.onBuild( object, parameters, _this );
29689
29690				material.onBeforeCompile( parameters, _this );
29691
29692				program = programCache.acquireProgram( parameters, programCacheKey );
29693				programs.set( programCacheKey, program );
29694
29695				materialProperties.uniforms = parameters.uniforms;
29696
29697			}
29698
29699			const uniforms = materialProperties.uniforms;
29700
29701			if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) {
29702
29703				uniforms.clippingPlanes = clipping.uniform;
29704
29705			}
29706
29707			updateCommonMaterialProperties( material, parameters );
29708
29709			// store the light setup it was created for
29710
29711			materialProperties.needsLights = materialNeedsLights( material );
29712			materialProperties.lightsStateVersion = lightsStateVersion;
29713
29714			if ( materialProperties.needsLights ) {
29715
29716				// wire up the material to this renderer's lighting state
29717
29718				uniforms.ambientLightColor.value = lights.state.ambient;
29719				uniforms.lightProbe.value = lights.state.probe;
29720				uniforms.directionalLights.value = lights.state.directional;
29721				uniforms.directionalLightShadows.value = lights.state.directionalShadow;
29722				uniforms.spotLights.value = lights.state.spot;
29723				uniforms.spotLightShadows.value = lights.state.spotShadow;
29724				uniforms.rectAreaLights.value = lights.state.rectArea;
29725				uniforms.ltc_1.value = lights.state.rectAreaLTC1;
29726				uniforms.ltc_2.value = lights.state.rectAreaLTC2;
29727				uniforms.pointLights.value = lights.state.point;
29728				uniforms.pointLightShadows.value = lights.state.pointShadow;
29729				uniforms.hemisphereLights.value = lights.state.hemi;
29730
29731				uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
29732				uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
29733				uniforms.spotShadowMap.value = lights.state.spotShadowMap;
29734				uniforms.spotLightMatrix.value = lights.state.spotLightMatrix;
29735				uniforms.spotLightMap.value = lights.state.spotLightMap;
29736				uniforms.pointShadowMap.value = lights.state.pointShadowMap;
29737				uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
29738				// TODO (abelnation): add area lights shadow info to uniforms
29739
29740			}
29741
29742			materialProperties.currentProgram = program;
29743			materialProperties.uniformsList = null;
29744
29745			return program;
29746
29747		}
29748
29749		function getUniformList( materialProperties ) {
29750
29751			if ( materialProperties.uniformsList === null ) {
29752
29753				const progUniforms = materialProperties.currentProgram.getUniforms();
29754				materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms );
29755
29756			}
29757
29758			return materialProperties.uniformsList;
29759
29760		}
29761
29762		function updateCommonMaterialProperties( material, parameters ) {
29763
29764			const materialProperties = properties.get( material );
29765
29766			materialProperties.outputColorSpace = parameters.outputColorSpace;
29767			materialProperties.batching = parameters.batching;
29768			materialProperties.instancing = parameters.instancing;
29769			materialProperties.instancingColor = parameters.instancingColor;
29770			materialProperties.instancingMorph = parameters.instancingMorph;
29771			materialProperties.skinning = parameters.skinning;
29772			materialProperties.morphTargets = parameters.morphTargets;
29773			materialProperties.morphNormals = parameters.morphNormals;
29774			materialProperties.morphColors = parameters.morphColors;
29775			materialProperties.morphTargetsCount = parameters.morphTargetsCount;
29776			materialProperties.numClippingPlanes = parameters.numClippingPlanes;
29777			materialProperties.numIntersection = parameters.numClipIntersection;
29778			materialProperties.vertexAlphas = parameters.vertexAlphas;
29779			materialProperties.vertexTangents = parameters.vertexTangents;
29780			materialProperties.toneMapping = parameters.toneMapping;
29781
29782		}
29783
29784		function setProgram( camera, scene, geometry, material, object ) {
29785
29786			if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
29787
29788			textures.resetTextureUnits();
29789
29790			const fog = scene.fog;
29791			const environment = material.isMeshStandardMaterial ? scene.environment : null;
29792			const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace );
29793			const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
29794			const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4;
29795			const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 );
29796			const morphTargets = !! geometry.morphAttributes.position;
29797			const morphNormals = !! geometry.morphAttributes.normal;
29798			const morphColors = !! geometry.morphAttributes.color;
29799
29800			let toneMapping = NoToneMapping;
29801
29802			if ( material.toneMapped ) {
29803
29804				if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) {
29805
29806					toneMapping = _this.toneMapping;
29807
29808				}
29809
29810			}
29811
29812			const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
29813			const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
29814
29815			const materialProperties = properties.get( material );
29816			const lights = currentRenderState.state.lights;
29817
29818			if ( _clippingEnabled === true ) {
29819
29820				if ( _localClippingEnabled === true || camera !== _currentCamera ) {
29821
29822					const useCache =
29823						camera === _currentCamera &&
29824						material.id === _currentMaterialId;
29825
29826					// we might want to call this function with some ClippingGroup
29827					// object instead of the material, once it becomes feasible
29828					// (#8465, #8379)
29829					clipping.setState( material, camera, useCache );
29830
29831				}
29832
29833			}
29834
29835			//
29836
29837			let needsProgramChange = false;
29838
29839			if ( material.version === materialProperties.__version ) {
29840
29841				if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
29842
29843					needsProgramChange = true;
29844
29845				} else if ( materialProperties.outputColorSpace !== colorSpace ) {
29846
29847					needsProgramChange = true;
29848
29849				} else if ( object.isBatchedMesh && materialProperties.batching === false ) {
29850
29851					needsProgramChange = true;
29852
29853				} else if ( ! object.isBatchedMesh && materialProperties.batching === true ) {
29854
29855					needsProgramChange = true;
29856
29857				} else if ( object.isInstancedMesh && materialProperties.instancing === false ) {
29858
29859					needsProgramChange = true;
29860
29861				} else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) {
29862
29863					needsProgramChange = true;
29864
29865				} else if ( object.isSkinnedMesh && materialProperties.skinning === false ) {
29866
29867					needsProgramChange = true;
29868
29869				} else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) {
29870
29871					needsProgramChange = true;
29872
29873				} else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) {
29874
29875					needsProgramChange = true;
29876
29877				} else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) {
29878
29879					needsProgramChange = true;
29880
29881				} else if ( object.isInstancedMesh && materialProperties.instancingMorph === true && object.morphTexture === null ) {
29882
29883					needsProgramChange = true;
29884
29885				} else if ( object.isInstancedMesh && materialProperties.instancingMorph === false && object.morphTexture !== null ) {
29886
29887					needsProgramChange = true;
29888
29889				} else if ( materialProperties.envMap !== envMap ) {
29890
29891					needsProgramChange = true;
29892
29893				} else if ( material.fog === true && materialProperties.fog !== fog ) {
29894
29895					needsProgramChange = true;
29896
29897				} else if ( materialProperties.numClippingPlanes !== undefined &&
29898					( materialProperties.numClippingPlanes !== clipping.numPlanes ||
29899					materialProperties.numIntersection !== clipping.numIntersection ) ) {
29900
29901					needsProgramChange = true;
29902
29903				} else if ( materialProperties.vertexAlphas !== vertexAlphas ) {
29904
29905					needsProgramChange = true;
29906
29907				} else if ( materialProperties.vertexTangents !== vertexTangents ) {
29908
29909					needsProgramChange = true;
29910
29911				} else if ( materialProperties.morphTargets !== morphTargets ) {
29912
29913					needsProgramChange = true;
29914
29915				} else if ( materialProperties.morphNormals !== morphNormals ) {
29916
29917					needsProgramChange = true;
29918
29919				} else if ( materialProperties.morphColors !== morphColors ) {
29920
29921					needsProgramChange = true;
29922
29923				} else if ( materialProperties.toneMapping !== toneMapping ) {
29924
29925					needsProgramChange = true;
29926
29927				} else if ( 
29927materialProperties.morphTargetsCount !== morphTargetsCount ) {
29928
29929					needsProgramChange = true;
29930
29931				}
29932
29933			} else {
29934
29935				needsProgramChange = true;
29936				materialProperties.__version = material.version;
29937
29938			}
29939
29940			//
29941
29942			let program = materialProperties.currentProgram;
29943
29944			if ( needsProgramChange === true ) {
29945
29946				program = getProgram( material, scene, object );
29947
29948			}
29949
29950			let refreshProgram = false;
vendor: 4,839 bytes, lines 29951-30118
29951			let refreshMaterial = false;
29952			let refreshLights = false;
29953
29954			const p_uniforms = program.getUniforms(),
29955				m_uniforms = materialProperties.uniforms;
29956
29957			if ( state.useProgram( program.program ) ) {
29958
29959				refreshProgram = true;
29960				refreshMaterial = true;
29961				refreshLights = true;
29962
29963			}
29964
29965			if ( material.id !== _currentMaterialId ) {
29966
29967				_currentMaterialId = material.id;
29968
29969				refreshMaterial = true;
29970
29971			}
29972
29973			if ( refreshProgram || _currentCamera !== camera ) {
29974
29975				// common camera uniforms
29976
29977				p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
29978				p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
29979
29980				const uCamPos = p_uniforms.map.cameraPosition;
29981
29982				if ( uCamPos !== undefined ) {
29983
29984					uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) );
29985
29986				}
29987
29988				if ( capabilities.logarithmicDepthBuffer ) {
29989
29990					p_uniforms.setValue( _gl, 'logDepthBufFC',
29991						2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
29992
29993				}
29994
29995				// consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067
29996
29997				if ( material.isMeshPhongMaterial ||
29998					material.isMeshToonMaterial ||
29999					material.isMeshLambertMaterial ||
30000					material.isMeshBasicMaterial ||
30001					material.isMeshStandardMaterial ||
30002					material.isShaderMaterial ) {
30003
30004					p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
30005
30006				}
30007
30008				if ( _currentCamera !== camera ) {
30009
30010					_currentCamera = camera;
30011
30012					// lighting uniforms depend on the camera so enforce an update
30013					// now, in case this material supports lights - or later, when
30014					// the next material that does gets activated:
30015
30016					refreshMaterial = true;		// set to true on material change
30017					refreshLights = true;		// remains set until update done
30018
30019				}
30020
30021			}
30022
30023			// skinning and morph target uniforms must be set even if material didn't change
30024			// auto-setting of texture unit for bone and morph texture must go before other textures
30025			// otherwise textures used for skinning and morphing can take over texture units reserved for other material textures
30026
30027			if ( object.isSkinnedMesh ) {
30028
30029				p_uniforms.setOptional( _gl, object, 'bindMatrix' );
30030				p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
30031
30032				const skeleton = object.skeleton;
30033
30034				if ( skeleton ) {
30035
30036					if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture();
30037
30038					p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
30039
30040				}
30041
30042			}
30043
30044			if ( object.isBatchedMesh ) {
30045
30046				p_uniforms.setOptional( _gl, object, 'batchingTexture' );
30047				p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures );
30048
30049			}
30050
30051			const morphAttributes = geometry.morphAttributes;
30052
30053			if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined ) ) {
30054
30055				morphtargets.update( object, geometry, program );
30056
30057			}
30058
30059			if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
30060
30061				materialProperties.receiveShadow = object.receiveShadow;
30062				p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
30063
30064			}
30065
30066			// https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512
30067
30068			if ( material.isMeshGouraudMaterial && material.envMap !== null ) {
30069
30070				m_uniforms.envMap.value = envMap;
30071
30072				m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
30073
30074			}
30075
30076			if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) {
30077
30078				m_uniforms.envMapIntensity.value = scene.environmentIntensity;
30079
30080			}
30081
30082			if ( refreshMaterial ) {
30083
30084				p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
30085
30086				if ( materialProperties.needsLights ) {
30087
30088					// the current material requires lighting info
30089
30090					// note: all lighting uniforms are always set correctly
30091					// they simply reference the renderer's state for their
30092					// values
30093					//
30094					// use the current material's .needsUpdate flags to set
30095					// the GL state when required
30096
30097					markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
30098
30099				}
30100
30101				// refresh uniforms common to several materials
30102
30103				if ( fog && material.fog === true ) {
30104
30105					materials.refreshFogUniforms( m_uniforms, fog );
30106
30107				}
30108
30109				materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget );
30110
30111				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
30112
30113			}
30114
30115			if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
30116
30117				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
30118				material.uniformsNeedUpdate = false;
vendor: 15,414 bytes, lines 30119-30622
30119
30120			}
30121
30122			if ( material.isSpriteMaterial ) {
30123
30124				p_uniforms.setValue( _gl, 'center', object.center );
30125
30126			}
30127
30128			// common matrices
30129
30130			p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
30131			p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
30132			p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
30133
30134			// UBOs
30135
30136			if ( material.isShaderMaterial || material.isRawShaderMaterial ) {
30137
30138				const groups = material.uniformsGroups;
30139
30140				for ( let i = 0, l = groups.length; i < l; i ++ ) {
30141
30142					const group = groups[ i ];
30143
30144					uniformsGroups.update( group, program );
30145					uniformsGroups.bind( group, program );
30146
30147				}
30148
30149			}
30150
30151			return program;
30152
30153		}
30154
30155		// If uniforms are marked as clean, they don't need to be loaded to the GPU.
30156
30157		function markUniformsLightsNeedsUpdate( uniforms, value ) {
30158
30159			uniforms.ambientLightColor.needsUpdate = value;
30160			uniforms.lightProbe.needsUpdate = value;
30161
30162			uniforms.directionalLights.needsUpdate = value;
30163			uniforms.directionalLightShadows.needsUpdate = value;
30164			uniforms.pointLights.needsUpdate = value;
30165			uniforms.pointLightShadows.needsUpdate = value;
30166			uniforms.spotLights.needsUpdate = value;
30167			uniforms.spotLightShadows.needsUpdate = value;
30168			uniforms.rectAreaLights.needsUpdate = value;
30169			uniforms.hemisphereLights.needsUpdate = value;
30170
30171		}
30172
30173		function materialNeedsLights( material ) {
30174
30175			return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
30176				material.isMeshStandardMaterial || material.isShadowMaterial ||
30177				( material.isShaderMaterial && material.lights === true );
30178
30179		}
30180
30181		this.getActiveCubeFace = function () {
30182
30183			return _currentActiveCubeFace;
30184
30185		};
30186
30187		this.getActiveMipmapLevel = function () {
30188
30189			return _currentActiveMipmapLevel;
30190
30191		};
30192
30193		this.getRenderTarget = function () {
30194
30195			return _currentRenderTarget;
30196
30197		};
30198
30199		this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) {
30200
30201			properties.get( renderTarget.texture ).__webglTexture = colorTexture;
30202			properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture;
30203
30204			const renderTargetProperties = properties.get( renderTarget );
30205			renderTargetProperties.__hasExternalTextures = true;
30206
30207			renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined;
30208
30209			if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) {
30210
30211				// The multisample_render_to_texture extension doesn't work properly if there
30212				// are midframe flushes and an external depth buffer. Disable use of the extension.
30213				if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) {
30214
30215					console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' );
30216					renderTargetProperties.__useRenderToTexture = false;
30217
30218				}
30219
30220			}
30221
30222		};
30223
30224		this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) {
30225
30226			const renderTargetProperties = properties.get( renderTarget );
30227			renderTargetProperties.__webglFramebuffer = defaultFramebuffer;
30228			renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined;
30229
30230		};
30231
30232		this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
30233
30234			_currentRenderTarget = renderTarget;
30235			_currentActiveCubeFace = activeCubeFace;
30236			_currentActiveMipmapLevel = activeMipmapLevel;
30237
30238			let useDefaultFramebuffer = true;
30239			let framebuffer = null;
30240			let isCube = false;
30241			let isRenderTarget3D = false;
30242
30243			if ( renderTarget ) {
30244
30245				const renderTargetProperties = properties.get( renderTarget );
30246
30247				if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) {
30248
30249					// We need to make sure to rebind the framebuffer.
30250					state.bindFramebuffer( _gl.FRAMEBUFFER, null );
30251					useDefaultFramebuffer = false;
30252
30253				} else if ( renderTargetProperties.__webglFramebuffer === undefined ) {
30254
30255					textures.setupRenderTarget( renderTarget );
30256
30257				} else if ( renderTargetProperties.__hasExternalTextures ) {
30258
30259					// Color and depth texture must be rebound in order for the swapchain to update.
30260					textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture );
30261
30262				}
30263
30264				const texture = renderTarget.texture;
30265
30266				if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
30267
30268					isRenderTarget3D = true;
30269
30270				}
30271
30272				const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
30273
30274				if ( renderTarget.isWebGLCubeRenderTarget ) {
30275
30276					if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) {
30277
30278						framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ];
30279
30280					} else {
30281
30282						framebuffer = __webglFramebuffer[ activeCubeFace ];
30283
30284					}
30285
30286					isCube = true;
30287
30288				} else if ( ( renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) {
30289
30290					framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
30291
30292				} else {
30293
30294					if ( Array.isArray( __webglFramebuffer ) ) {
30295
30296						framebuffer = __webglFramebuffer[ activeMipmapLevel ];
30297
30298					} else {
30299
30300						framebuffer = __webglFramebuffer;
30301
30302					}
30303
30304				}
30305
30306				_currentViewport.copy( renderTarget.viewport );
30307				_currentScissor.copy( renderTarget.scissor );
30308				_currentScissorTest = renderTarget.scissorTest;
30309
30310			} else {
30311
30312				_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
30313				_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
30314				_currentScissorTest = _scissorTest;
30315
30316			}
30317
30318			const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30319
30320			if ( framebufferBound && useDefaultFramebuffer ) {
30321
30322				state.drawBuffers( renderTarget, framebuffer );
30323
30324			}
30325
30326			state.viewport( _currentViewport );
30327			state.scissor( _currentScissor );
30328			state.setScissorTest( _currentScissorTest );
30329
30330			if ( isCube ) {
30331
30332				const textureProperties = properties.get( renderTarget.texture );
30333				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
30334
30335			} else if ( isRenderTarget3D ) {
30336
30337				const textureProperties = properties.get( renderTarget.texture );
30338				const layer = activeCubeFace || 0;
30339				_gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer );
30340
30341			}
30342
30343			_currentMaterialId = - 1; // reset current material to ensure correct uniform bindings
30344
30345		};
30346
30347		this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
30348
30349			if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
30350
30351				console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
30352				return;
30353
30354			}
30355
30356			let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
30357
30358			if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
30359
30360				framebuffer = framebuffer[ activeCubeFaceIndex ];
30361
30362			}
30363
30364			if ( framebuffer ) {
30365
30366				state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30367
30368				try {
30369
30370					const texture = renderTarget.texture;
30371					const textureFormat = texture.format;
30372					const textureType = texture.type;
30373
30374					if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
30375
30376						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
30377						return;
30378
30379					}
30380
30381					const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) );
30382
30383					if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513)
30384						textureType !== FloatType && ! halfFloatSupportedByExt ) {
30385
30386						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
30387						return;
30388
30389					}
30390
30391					// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
30392
30393					if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
30394
30395						_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
30396
30397					}
30398
30399				} finally {
30400
30401					// restore framebuffer of current render target if necessary
30402
30403					const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null;
30404					state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30405
30406				}
30407
30408			}
30409
30410		};
30411
30412		this.copyFramebufferToTexture = function ( position, texture, level = 0 ) {
30413
30414			const levelScale = Math.pow( 2, - level );
30415			const width = Math.floor( texture.image.width * levelScale );
30416			const height = Math.floor( texture.image.height * levelScale );
30417
30418			textures.setTexture2D( texture, 0 );
30419
30420			_gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height );
30421
30422			state.unbindTexture();
30423
30424		};
30425
30426		this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level = 0 ) {
30427
30428			const width = srcTexture.image.width;
30429			const height = srcTexture.image.height;
30430			const glFormat = utils.convert( dstTexture.format );
30431			const glType = utils.convert( dstTexture.type );
30432
30433			textures.setTexture2D( dstTexture, 0 );
30434
30435			// As another texture upload may have changed pixelStorei
30436			// parameters, make sure they are correct for the dstTexture
30437			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
30438			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
30439			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
30440
30441			if ( srcTexture.isDataTexture ) {
30442
30443				_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );
30444
30445			} else {
30446
30447				if ( srcTexture.isCompressedTexture ) {
30448
30449					_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
30450
30451				} else {
30452
30453					_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image );
30454
30455				}
30456
30457			}
30458
30459			// Generate mipmaps only when copying level 0
30460			if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D );
30461
30462			state.unbindTexture();
30463
30464		};
30465
30466		this.copyTextureToTexture3D = function ( sourceBox, position, srcTexture, dstTexture, level = 0 ) {
30467
30468			const width = Math.round( sourceBox.max.x - sourceBox.min.x );
30469			const height = Math.round( sourceBox.max.y - sourceBox.min.y );
30470			const depth = sourceBox.max.z - sourceBox.min.z + 1;
30471			const glFormat = utils.convert( dstTexture.format );
30472			const glType = utils.convert( dstTexture.type );
30473			let glTarget;
30474
30475			if ( dstTexture.isData3DTexture ) {
30476
30477				textures.setTexture3D( dstTexture, 0 );
30478				glTarget = _gl.TEXTURE_3D;
30479
30480			} else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) {
30481
30482				textures.setTexture2DArray( dstTexture, 0 );
30483				glTarget = _gl.TEXTURE_2D_ARRAY;
30484
30485			} else {
30486
30487				console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' );
30488				return;
30489
30490			}
30491
30492			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
30493			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
30494			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
30495
30496			const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
30497			const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
30498			const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
30499			const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
30500			const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );
30501
30502			const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
30503
30504			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
30505			_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
30506			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x );
30507			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y );
30508			_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z );
30509
30510			if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
30511
30512				_gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data );
30513
30514			} else {
30515
30516				if ( dstTexture.isCompressedArrayTexture ) {
30517
30518					_gl.compressedTexSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data );
30519
30520				} else {
30521
30522					_gl.texSubImage3D( glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image );
30523
30524				}
30525
30526			}
30527
30528			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen );
30529			_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight );
30530			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels );
30531			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows );
30532			_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages );
30533
30534			// Generate mipmaps only when copying level 0
30535			if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget );
30536
30537			state.unbindTexture();
30538
30539		};
30540
30541		this.initTexture = function ( texture ) {
30542
30543			if ( texture.isCubeTexture ) {
30544
30545				textures.setTextureCube( texture, 0 );
30546
30547			} else if ( texture.isData3DTexture ) {
30548
30549				textures.setTexture3D( texture, 0 );
30550
30551			} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
30552
30553				textures.setTexture2DArray( texture, 0 );
30554
30555			} else {
30556
30557				textures.setTexture2D( texture, 0 );
30558
30559			}
30560
30561			state.unbindTexture();
30562
30563		};
30564
30565		this.resetState = function () {
30566
30567			_currentActiveCubeFace = 0;
30568			_currentActiveMipmapLevel = 0;
30569			_currentRenderTarget = null;
30570
30571			state.reset();
30572			bindingStates.reset();
30573
30574		};
30575
30576		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
30577
30578			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
30579
30580		}
30581
30582	}
30583
30584	get coordinateSystem() {
30585
30586		return WebGLCoordinateSystem;
30587
30588	}
30589
30590	get outputColorSpace() {
30591
30592		return this._outputColorSpace;
30593
30594	}
30595
30596	set outputColorSpace( colorSpace ) {
30597
30598		this._outputColorSpace = colorSpace;
30599
30600		const gl = this.getContext();
30601		gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb';
30602		gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb';
30603
30604	}
30605
30606	get useLegacyLights() { // @deprecated, r155
30607
30608		console.warn( 'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' );
30609		return this._useLegacyLights;
30610
30611	}
30612
30613	set useLegacyLights( value ) { // @deprecated, r155
30614
30615		console.warn( 'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' );
30616		this._useLegacyLights = value;
30617
30618	}
30619
30620}
30621
30622class FogExp2 {
vendor: 11,981 bytes, lines 30623-31309
30623
30624	constructor( color, density = 0.00025 ) {
30625
30626		this.isFogExp2 = true;
30627
30628		this.name = '';
30629
30630		this.color = new Color( color );
30631		this.density = density;
30632
30633	}
30634
30635	clone() {
30636
30637		return new FogExp2( this.color, this.density );
30638
30639	}
30640
30641	toJSON( /* meta */ ) {
30642
30643		return {
30644			type: 'FogExp2',
30645			name: this.name,
30646			color: this.color.getHex(),
30647			density: this.density
30648		};
30649
30650	}
30651
30652}
30653
30654class Fog {
30655
30656	constructor( color, near = 1, far = 1000 ) {
30657
30658		this.isFog = true;
30659
30660		this.name = '';
30661
30662		this.color = new Color( color );
30663
30664		this.near = near;
30665		this.far = far;
30666
30667	}
30668
30669	clone() {
30670
30671		return new Fog( this.color, this.near, this.far );
30672
30673	}
30674
30675	toJSON( /* meta */ ) {
30676
30677		return {
30678			type: 'Fog',
30679			name: this.name,
30680			color: this.color.getHex(),
30681			near: this.near,
30682			far: this.far
30683		};
30684
30685	}
30686
30687}
30688
30689class Scene extends Object3D {
30690
30691	constructor() {
30692
30693		super();
30694
30695		this.isScene = true;
30696
30697		this.type = 'Scene';
30698
30699		this.background = null;
30700		this.environment = null;
30701		this.fog = null;
30702
30703		this.backgroundBlurriness = 0;
30704		this.backgroundIntensity = 1;
30705		this.backgroundRotation = new Euler();
30706
30707		this.environmentIntensity = 1;
30708		this.environmentRotation = new Euler();
30709
30710		this.overrideMaterial = null;
30711
30712		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
30713
30714			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
30715
30716		}
30717
30718	}
30719
30720	copy( source, recursive ) {
30721
30722		super.copy( source, recursive );
30723
30724		if ( source.background !== null ) this.background = source.background.clone();
30725		if ( source.environment !== null ) this.environment = source.environment.clone();
30726		if ( source.fog !== null ) this.fog = source.fog.clone();
30727
30728		this.backgroundBlurriness = source.backgroundBlurriness;
30729		this.backgroundIntensity = source.backgroundIntensity;
30730		this.backgroundRotation.copy( source.backgroundRotation );
30731
30732		this.environmentIntensity = source.environmentIntensity;
30733		this.environmentRotation.copy( source.environmentRotation );
30734
30735		if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
30736
30737		this.matrixAutoUpdate = source.matrixAutoUpdate;
30738
30739		return this;
30740
30741	}
30742
30743	toJSON( meta ) {
30744
30745		const data = super.toJSON( meta );
30746
30747		if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
30748
30749		if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness;
30750		if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity;
30751		data.object.backgroundRotation = this.backgroundRotation.toArray();
30752
30753		if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity;
30754		data.object.environmentRotation = this.environmentRotation.toArray();
30755
30756		return data;
30757
30758	}
30759
30760}
30761
30762class InterleavedBuffer {
30763
30764	constructor( array, stride ) {
30765
30766		this.isInterleavedBuffer = true;
30767
30768		this.array = array;
30769		this.stride = stride;
30770		this.count = array !== undefined ? array.length / stride : 0;
30771
30772		this.usage = StaticDrawUsage;
30773		this._updateRange = { offset: 0, count: - 1 };
30774		this.updateRanges = [];
30775
30776		this.version = 0;
30777
30778		this.uuid = generateUUID();
30779
30780	}
30781
30782	onUploadCallback() {}
30783
30784	set needsUpdate( value ) {
30785
30786		if ( value === true ) this.version ++;
30787
30788	}
30789
30790	get updateRange() {
30791
30792		warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159
30793		return this._updateRange;
30794
30795	}
30796
30797	setUsage( value ) {
30798
30799		this.usage = value;
30800
30801		return this;
30802
30803	}
30804
30805	addUpdateRange( start, count ) {
30806
30807		this.updateRanges.push( { start, count } );
30808
30809	}
30810
30811	clearUpdateRanges() {
30812
30813		this.updateRanges.length = 0;
30814
30815	}
30816
30817	copy( source ) {
30818
30819		this.array = new source.array.constructor( source.array );
30820		this.count = source.count;
30821		this.stride = source.stride;
30822		this.usage = source.usage;
30823
30824		return this;
30825
30826	}
30827
30828	copyAt( index1, attribute, index2 ) {
30829
30830		index1 *= this.stride;
30831		index2 *= attribute.stride;
30832
30833		for ( let i = 0, l = this.stride; i < l; i ++ ) {
30834
30835			this.array[ index1 + i ] = attribute.array[ index2 + i ];
30836
30837		}
30838
30839		return this;
30840
30841	}
30842
30843	set( value, offset = 0 ) {
30844
30845		this.array.set( value, offset );
30846
30847		return this;
30848
30849	}
30850
30851	clone( data ) {
30852
30853		if ( data.arrayBuffers === undefined ) {
30854
30855			data.arrayBuffers = {};
30856
30857		}
30858
30859		if ( this.array.buffer._uuid === undefined ) {
30860
30861			this.array.buffer._uuid = generateUUID();
30862
30863		}
30864
30865		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
30866
30867			data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
30868
30869		}
30870
30871		const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
30872
30873		const ib = new this.constructor( array, this.stride );
30874		ib.setUsage( this.usage );
30875
30876		return ib;
30877
30878	}
30879
30880	onUpload( callback ) {
30881
30882		this.onUploadCallback = callback;
30883
30884		return this;
30885
30886	}
30887
30888	toJSON( data ) {
30889
30890		if ( data.arrayBuffers === undefined ) {
30891
30892			data.arrayBuffers = {};
30893
30894		}
30895
30896		// generate UUID for array buffer if necessary
30897
30898		if ( this.array.buffer._uuid === undefined ) {
30899
30900			this.array.buffer._uuid = generateUUID();
30901
30902		}
30903
30904		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
30905
30906			data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) );
30907
30908		}
30909
30910		//
30911
30912		return {
30913			uuid: this.uuid,
30914			buffer: this.array.buffer._uuid,
30915			type: this.array.constructor.name,
30916			stride: this.stride
30917		};
30918
30919	}
30920
30921}
30922
30923const _vector$6 = /*@__PURE__*/ new Vector3();
30924
30925class InterleavedBufferAttribute {
30926
30927	constructor( interleavedBuffer, itemSize, offset, normalized = false ) {
30928
30929		this.isInterleavedBufferAttribute = true;
30930
30931		this.name = '';
30932
30933		this.data = interleavedBuffer;
30934		this.itemSize = itemSize;
30935		this.offset = offset;
30936
30937		this.normalized = normalized;
30938
30939	}
30940
30941	get count() {
30942
30943		return this.data.count;
30944
30945	}
30946
30947	get array() {
30948
30949		return this.data.array;
30950
30951	}
30952
30953	set needsUpdate( value ) {
30954
30955		this.data.needsUpdate = value;
30956
30957	}
30958
30959	applyMatrix4( m ) {
30960
30961		for ( let i = 0, l = this.data.count; i < l; i ++ ) {
30962
30963			_vector$6.fromBufferAttribute( this, i );
30964
30965			_vector$6.applyMatrix4( m );
30966
30967			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
30968
30969		}
30970
30971		return this;
30972
30973	}
30974
30975	applyNormalMatrix( m ) {
30976
30977		for ( let i = 0, l = this.count; i < l; i ++ ) {
30978
30979			_vector$6.fromBufferAttribute( this, i );
30980
30981			_vector$6.applyNormalMatrix( m );
30982
30983			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
30984
30985		}
30986
30987		return this;
30988
30989	}
30990
30991	transformDirection( m ) {
30992
30993		for ( let i = 0, l = this.count; i < l; i ++ ) {
30994
30995			_vector$6.fromBufferAttribute( this, i );
30996
30997			_vector$6.transformDirection( m );
30998
30999			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
31000
31001		}
31002
31003		return this;
31004
31005	}
31006
31007	getComponent( index, component ) {
31008
31009		let value = this.array[ index * this.data.stride + this.offset + component ];
31010
31011		if ( this.normalized ) value = denormalize( value, this.array );
31012
31013		return value;
31014
31015	}
31016
31017	setComponent( index, component, value ) {
31018
31019		if ( this.normalized ) value = normalize( value, this.array );
31020
31021		this.data.array[ index * this.data.stride + this.offset + component ] = value;
31022
31023		return this;
31024
31025	}
31026
31027	setX( index, x ) {
31028
31029		if ( this.normalized ) x = normalize( x, this.array );
31030
31031		this.data.array[ index * this.data.stride + this.offset ] = x;
31032
31033		return this;
31034
31035	}
31036
31037	setY( index, y ) {
31038
31039		if ( this.normalized ) y = normalize( y, this.array );
31040
31041		this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
31042
31043		return this;
31044
31045	}
31046
31047	setZ( index, z ) {
31048
31049		if ( this.normalized ) z = normalize( z, this.array );
31050
31051		this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
31052
31053		return this;
31054
31055	}
31056
31057	setW( index, w ) {
31058
31059		if ( this.normalized ) w = normalize( w, this.array );
31060
31061		this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
31062
31063		return this;
31064
31065	}
31066
31067	getX( index ) {
31068
31069		let x = this.data.array[ index * this.data.stride + this.offset ];
31070
31071		if ( this.normalized ) x = denormalize( x, this.array );
31072
31073		return x;
31074
31075	}
31076
31077	getY( index ) {
31078
31079		let y = this.data.array[ index * this.data.stride + this.offset + 1 ];
31080
31081		if ( this.normalized ) y = denormalize( y, this.array );
31082
31083		return y;
31084
31085	}
31086
31087	getZ( index ) {
31088
31089		let z = this.data.array[ index * this.data.stride + this.offset + 2 ];
31090
31091		if ( this.normalized ) z = denormalize( z, this.array );
31092
31093		return z;
31094
31095	}
31096
31097	getW( index ) {
31098
31099		let w = this.data.array[ index * this.data.stride + this.offset + 3 ];
31100
31101		if ( this.normalized ) w = denormalize( w, this.array );
31102
31103		return w;
31104
31105	}
31106
31107	setXY( index, x, y ) {
31108
31109		index = index * this.data.stride + this.offset;
31110
31111		if ( this.normalized ) {
31112
31113			x = normalize( x, this.array );
31114			y = normalize( y, this.array );
31115
31116		}
31117
31118		this.data.array[ index + 0 ] = x;
31119		this.data.array[ index + 1 ] = y;
31120
31121		return this;
31122
31123	}
31124
31125	setXYZ( index, x, y, z ) {
31126
31127		index = index * this.data.stride + this.offset;
31128
31129		if ( this.normalized ) {
31130
31131			x = normalize( x, this.array );
31132			y = normalize( y, this.array );
31133			z = normalize( z, this.array );
31134
31135		}
31136
31137		this.data.array[ index + 0 ] = x;
31138		this.data.array[ index + 1 ] = y;
31139		this.data.array[ index + 2 ] = z;
31140
31141		return this;
31142
31143	}
31144
31145	setXYZW( index, x, y, z, w ) {
31146
31147		index = index * this.data.stride + this.offset;
31148
31149		if ( this.normalized ) {
31150
31151			x = normalize( x, this.array );
31152			y = normalize( y, this.array );
31153			z = normalize( z, this.array );
31154			w = normalize( w, this.array );
31155
31156		}
31157
31158		this.data.array[ index + 0 ] = x;
31159		this.data.array[ index + 1 ] = y;
31160		this.data.array[ index + 2 ] = z;
31161		this.data.array[ index + 3 ] = w;
31162
31163		return this;
31164
31165	}
31166
31167	clone( data ) {
31168
31169		if ( data === undefined ) {
31170
31171			console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' );
31172
31173			const array = [];
31174
31175			for ( let i = 0; i < this.count; i ++ ) {
31176
31177				const index = i * this.data.stride + this.offset;
31178
31179				for ( let j = 0; j < this.itemSize; j ++ ) {
31180
31181					array.push( this.data.array[ index + j ] );
31182
31183				}
31184
31185			}
31186
31187			return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
31188
31189		} else {
31190
31191			if ( data.interleavedBuffers === undefined ) {
31192
31193				data.interleavedBuffers = {};
31194
31195			}
31196
31197			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
31198
31199				data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
31200
31201			}
31202
31203			return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
31204
31205		}
31206
31207	}
31208
31209	toJSON( data ) {
31210
31211		if ( data === undefined ) {
31212
31213			console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' );
31214
31215			const array = [];
31216
31217			for ( let i = 0; i < this.count; i ++ ) {
31218
31219				const index = i * this.data.stride + this.offset;
31220
31221				for ( let j = 0; j < this.itemSize; j ++ ) {
31222
31223					array.push( this.data.array[ index + j ] );
31224
31225				}
31226
31227			}
31228
31229			// de-interleave data and save it as an ordinary buffer attribute for now
31230
31231			return {
31232				itemSize: this.itemSize,
31233				type: this.array.constructor.name,
31234				array: array,
31235				normalized: this.normalized
31236			};
31237
31238		} else {
31239
31240			// save as true interleaved attribute
31241
31242			if ( data.interleavedBuffers === undefined ) {
31243
31244				data.interleavedBuffers = {};
31245
31246			}
31247
31248			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
31249
31250				data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
31251
31252			}
31253
31254			return {
31255				isInterleavedBufferAttribute: true,
31256				itemSize: this.itemSize,
31257				data: this.data.uuid,
31258				offset: this.offset,
31259				normalized: this.normalized
31260			};
31261
31262		}
31263
31264	}
31265
31266}
31267
31268class SpriteMaterial extends Material {
31269
31270	constructor( parameters ) {
31271
31272		super();
31273
31274		this.isSpriteMaterial = true;
31275
31276		this.type = 'SpriteMaterial';
31277
31278		this.color = new Color( 0xffffff );
31279
31280		this.map = null;
31281
31282		this.alphaMap = null;
31283
31284		this.rotation = 0;
31285
31286		this.sizeAttenuation = true;
31287
31288		this.transparent = true;
31289
31290		this.fog = true;
31291
31292		this.setValues( parameters );
31293
31294	}
31295
31296	copy( source ) {
31297
31298		super.copy( source );
31299
31300		this.color.copy( source.color );
31301
31302		this.map = source.map;
31303
31304		this.alphaMap = source.alphaMap;
31305
31306		this.rotation = source.rotation;
31307
31308		this.sizeAttenuation = source.sizeAttenuation;
31309
vendor: 6,736 bytes, lines 31310-31646
31310		this.fog = source.fog;
31311
31312		return this;
31313
31314	}
31315
31316}
31317
31318let _geometry;
31319
31320const _intersectPoint = /*@__PURE__*/ new Vector3();
31321const _worldScale = /*@__PURE__*/ new Vector3();
31322const _mvPosition = /*@__PURE__*/ new Vector3();
31323
31324const _alignedPosition = /*@__PURE__*/ new Vector2();
31325const _rotatedPosition = /*@__PURE__*/ new Vector2();
31326const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
31327
31328const _vA = /*@__PURE__*/ new Vector3();
31329const _vB = /*@__PURE__*/ new Vector3();
31330const _vC = /*@__PURE__*/ new Vector3();
31331
31332const _uvA = /*@__PURE__*/ new Vector2();
31333const _uvB = /*@__PURE__*/ new Vector2();
31334const _uvC = /*@__PURE__*/ new Vector2();
31335
31336class Sprite extends Object3D {
31337
31338	constructor( material = new SpriteMaterial() ) {
31339
31340		super();
31341
31342		this.isSprite = true;
31343
31344		this.type = 'Sprite';
31345
31346		if ( _geometry === undefined ) {
31347
31348			_geometry = new BufferGeometry();
31349
31350			const float32Array = new Float32Array( [
31351				- 0.5, - 0.5, 0, 0, 0,
31352				0.5, - 0.5, 0, 1, 0,
31353				0.5, 0.5, 0, 1, 1,
31354				- 0.5, 0.5, 0, 0, 1
31355			] );
31356
31357			const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
31358
31359			_geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
31360			_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
31361			_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
31362
31363		}
31364
31365		this.geometry = _geometry;
31366		this.material = material;
31367
31368		this.center = new Vector2( 0.5, 0.5 );
31369
31370	}
31371
31372	raycast( raycaster, intersects ) {
31373
31374		if ( raycaster.camera === null ) {
31375
31376			console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
31377
31378		}
31379
31380		_worldScale.setFromMatrixScale( this.matrixWorld );
31381
31382		_viewWorldMatrix.copy( raycaster.camera.matrixWorld );
31383		this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
31384
31385		_mvPosition.setFromMatrixPosition( this.modelViewMatrix );
31386
31387		if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
31388
31389			_worldScale.multiplyScalar( - _mvPosition.z );
31390
31391		}
31392
31393		const rotation = this.material.rotation;
31394		let sin, cos;
31395
31396		if ( rotation !== 0 ) {
31397
31398			cos = Math.cos( rotation );
31399			sin = Math.sin( rotation );
31400
31401		}
31402
31403		const center = this.center;
31404
31405		transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31406		transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31407		transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31408
31409		_uvA.set( 0, 0 );
31410		_uvB.set( 1, 0 );
31411		_uvC.set( 1, 1 );
31412
31413		// check first triangle
31414		let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint );
31415
31416		if ( intersect === null ) {
31417
31418			// check second triangle
31419			transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31420			_uvB.set( 0, 1 );
31421
31422			intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint );
31423			if ( intersect === null ) {
31424
31425				return;
31426
31427			}
31428
31429		}
31430
31431		const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
31432
31433		if ( distance < raycaster.near || distance > raycaster.far ) return;
31434
31435		intersects.push( {
31436
31437			distance: distance,
31438			point: _intersectPoint.clone(),
31439			uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ),
31440			face: null,
31441			object: this
31442
31443		} );
31444
31445	}
31446
31447	copy( source, recursive ) {
31448
31449		super.copy( source, recursive );
31450
31451		if ( source.center !== undefined ) this.center.copy( source.center );
31452
31453		this.material = source.material;
31454
31455		return this;
31456
31457	}
31458
31459}
31460
31461function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
31462
31463	// compute position in camera space
31464	_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
31465
31466	// to check if rotation is not zero
31467	if ( sin !== undefined ) {
31468
31469		_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
31470		_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
31471
31472	} else {
31473
31474		_rotatedPosition.copy( _alignedPosition );
31475
31476	}
31477
31478
31479	vertexPosition.copy( mvPosition );
31480	vertexPosition.x += _rotatedPosition.x;
31481	vertexPosition.y += _rotatedPosition.y;
31482
31483	// transform to world space
31484	vertexPosition.applyMatrix4( _viewWorldMatrix );
31485
31486}
31487
31488const _v1$2 = /*@__PURE__*/ new Vector3();
31489const _v2$1 = /*@__PURE__*/ new Vector3();
31490
31491class LOD extends Object3D {
31492
31493	constructor() {
31494
31495		super();
31496
31497		this._currentLevel = 0;
31498
31499		this.type = 'LOD';
31500
31501		Object.defineProperties( this, {
31502			levels: {
31503				enumerable: true,
31504				value: []
31505			},
31506			isLOD: {
31507				value: true,
31508			}
31509		} );
31510
31511		this.autoUpdate = true;
31512
31513	}
31514
31515	copy( source ) {
31516
31517		super.copy( source, false );
31518
31519		const levels = source.levels;
31520
31521		for ( let i = 0, l = levels.length; i < l; i ++ ) {
31522
31523			const level = levels[ i ];
31524
31525			this.addLevel( level.object.clone(), level.distance, level.hysteresis );
31526
31527		}
31528
31529		this.autoUpdate = source.autoUpdate;
31530
31531		return this;
31532
31533	}
31534
31535	addLevel( object, distance = 0, hysteresis = 0 ) {
31536
31537		distance = Math.abs( distance );
31538
31539		const levels = this.levels;
31540
31541		let l;
31542
31543		for ( l = 0; l < levels.length; l ++ ) {
31544
31545			if ( distance < levels[ l ].distance ) {
31546
31547				break;
31548
31549			}
31550
31551		}
31552
31553		levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } );
31554
31555		this.add( object );
31556
31557		return this;
31558
31559	}
31560
31561	getCurrentLevel() {
31562
31563		return this._currentLevel;
31564
31565	}
31566
31567
31568
31569	getObjectForDistance( distance ) {
31570
31571		const levels = this.levels;
31572
31573		if ( levels.length > 0 ) {
31574
31575			let i, l;
31576
31577			for ( i = 1, l = levels.length; i < l; i ++ ) {
31578
31579				let levelDistance = levels[ i ].distance;
31580
31581				if ( levels[ i ].object.visible ) {
31582
31583					levelDistance -= levelDistance * levels[ i ].hysteresis;
31584
31585				}
31586
31587				if ( distance < levelDistance ) {
31588
31589					break;
31590
31591				}
31592
31593			}
31594
31595			return levels[ i - 1 ].object;
31596
31597		}
31598
31599		return null;
31600
31601	}
31602
31603	raycast( raycaster, intersects ) {
31604
31605		const levels = this.levels;
31606
31607		if ( levels.length > 0 ) {
31608
31609			_v1$2.setFromMatrixPosition( this.matrixWorld );
31610
31611			const distance = raycaster.ray.origin.distanceTo( _v1$2 );
31612
31613			this.getObjectForDistance( distance ).raycast( raycaster, intersects );
31614
31615		}
31616
31617	}
31618
31619	update( camera ) {
31620
31621		const levels = this.levels;
31622
31623		if ( levels.length > 1 ) {
31624
31625			_v1$2.setFromMatrixPosition( camera.matrixWorld );
31626			_v2$1.setFromMatrixPosition( this.matrixWorld );
31627
31628			const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom;
31629
31630			levels[ 0 ].object.visible = true;
31631
31632			let i, l;
31633
31634			for ( i = 1, l = levels.length; i < l; i ++ ) {
31635
31636				let levelDistance = levels[ i ].distance;
31637
31638				if ( levels[ i ].object.visible ) {
31639
31640					levelDistance -= levelDistance * levels[ i ].hysteresis;
31641
31642				}
31643
31644				if ( distance >= levelDistance ) {
31645
31646					levels[ i - 1 ].object.visible = false;
vendor: 4,383 bytes, lines 31647-31880
31647					levels[ i ].object.visible = true;
31648
31649				} else {
31650
31651					break;
31652
31653				}
31654
31655			}
31656
31657			this._currentLevel = i - 1;
31658
31659			for ( ; i < l; i ++ ) {
31660
31661				levels[ i ].object.visible = false;
31662
31663			}
31664
31665		}
31666
31667	}
31668
31669	toJSON( meta ) {
31670
31671		const data = super.toJSON( meta );
31672
31673		if ( this.autoUpdate === false ) data.object.autoUpdate = false;
31674
31675		data.object.levels = [];
31676
31677		const levels = this.levels;
31678
31679		for ( let i = 0, l = levels.length; i < l; i ++ ) {
31680
31681			const level = levels[ i ];
31682
31683			data.object.levels.push( {
31684				object: level.object.uuid,
31685				distance: level.distance,
31686				hysteresis: level.hysteresis
31687			} );
31688
31689		}
31690
31691		return data;
31692
31693	}
31694
31695}
31696
31697const _basePosition = /*@__PURE__*/ new Vector3();
31698
31699const _skinIndex = /*@__PURE__*/ new Vector4();
31700const _skinWeight = /*@__PURE__*/ new Vector4();
31701
31702const _vector3 = /*@__PURE__*/ new Vector3();
31703const _matrix4 = /*@__PURE__*/ new Matrix4();
31704const _vertex = /*@__PURE__*/ new Vector3();
31705
31706const _sphere$4 = /*@__PURE__*/ new Sphere();
31707const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4();
31708const _ray$2 = /*@__PURE__*/ new Ray();
31709
31710class SkinnedMesh extends Mesh {
31711
31712	constructor( geometry, material ) {
31713
31714		super( geometry, material );
31715
31716		this.isSkinnedMesh = true;
31717
31718		this.type = 'SkinnedMesh';
31719
31720		this.bindMode = AttachedBindMode;
31721		this.bindMatrix = new Matrix4();
31722		this.bindMatrixInverse = new Matrix4();
31723
31724		this.boundingBox = null;
31725		this.boundingSphere = null;
31726
31727	}
31728
31729	computeBoundingBox() {
31730
31731		const geometry = this.geometry;
31732
31733		if ( this.boundingBox === null ) {
31734
31735			this.boundingBox = new Box3();
31736
31737		}
31738
31739		this.boundingBox.makeEmpty();
31740
31741		const positionAttribute = geometry.getAttribute( 'position' );
31742
31743		for ( let i = 0; i < positionAttribute.count; i ++ ) {
31744
31745			this.getVertexPosition( i, _vertex );
31746			this.boundingBox.expandByPoint( _vertex );
31747
31748		}
31749
31750	}
31751
31752	computeBoundingSphere() {
31753
31754		const geometry = this.geometry;
31755
31756		if ( this.boundingSphere === null ) {
31757
31758			this.boundingSphere = new Sphere();
31759
31760		}
31761
31762		this.boundingSphere.makeEmpty();
31763
31764		const positionAttribute = geometry.getAttribute( 'position' );
31765
31766		for ( let i = 0; i < positionAttribute.count; i ++ ) {
31767
31768			this.getVertexPosition( i, _vertex );
31769			this.boundingSphere.expandByPoint( _vertex );
31770
31771		}
31772
31773	}
31774
31775	copy( source, recursive ) {
31776
31777		super.copy( source, recursive );
31778
31779		this.bindMode = source.bindMode;
31780		this.bindMatrix.copy( source.bindMatrix );
31781		this.bindMatrixInverse.copy( source.bindMatrixInverse );
31782
31783		this.skeleton = source.skeleton;
31784
31785		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
31786		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
31787
31788		return this;
31789
31790	}
31791
31792	raycast( raycaster, intersects ) {
31793
31794		const material = this.material;
31795		const matrixWorld = this.matrixWorld;
31796
31797		if ( material === undefined ) return;
31798
31799		// test with bounding sphere in world space
31800
31801		if ( this.boundingSphere === null ) this.computeBoundingSphere();
31802
31803		_sphere$4.copy( this.boundingSphere );
31804		_sphere$4.applyMatrix4( matrixWorld );
31805
31806		if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return;
31807
31808		// convert ray to local space of skinned mesh
31809
31810		_inverseMatrix$2.copy( matrixWorld ).invert();
31811		_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
31812
31813		// test with bounding box in local space
31814
31815		if ( this.boundingBox !== null ) {
31816
31817			if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return;
31818
31819		}
31820
31821		// test for intersections with geometry
31822
31823		this._computeIntersections( raycaster, intersects, _ray$2 );
31824
31825	}
31826
31827	getVertexPosition( index, target ) {
31828
31829		super.getVertexPosition( index, target );
31830
31831		this.applyBoneTransform( index, target );
31832
31833		return target;
31834
31835	}
31836
31837	bind( skeleton, bindMatrix ) {
31838
31839		this.skeleton = skeleton;
31840
31841		if ( bindMatrix === undefined ) {
31842
31843			this.updateMatrixWorld( true );
31844
31845			this.skeleton.calculateInverses();
31846
31847			bindMatrix = this.matrixWorld;
31848
31849		}
31850
31851		this.bindMatrix.copy( bindMatrix );
31852		this.bindMatrixInverse.copy( bindMatrix ).invert();
31853
31854	}
31855
31856	pose() {
31857
31858		this.skeleton.pose();
31859
31860	}
31861
31862	normalizeSkinWeights() {
31863
31864		const vector = new Vector4();
31865
31866		const skinWeight = this.geometry.attributes.skinWeight;
31867
31868		for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
31869
31870			vector.fromBufferAttribute( skinWeight, i );
31871
31872			const scale = 1.0 / vector.manhattanLength();
31873
31874			if ( scale !== Infinity ) {
31875
31876				vector.multiplyScalar( scale );
31877
31878			} else {
31879
31880				vector.set( 1, 0, 0, 0 );
vendor: 12,910 bytes, lines 31880-32552
31880 // do something reasonable
31881
31882			}
31883
31884			skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
31885
31886		}
31887
31888	}
31889
31890	updateMatrixWorld( force ) {
31891
31892		super.updateMatrixWorld( force );
31893
31894		if ( this.bindMode === AttachedBindMode ) {
31895
31896			this.bindMatrixInverse.copy( this.matrixWorld ).invert();
31897
31898		} else if ( this.bindMode === DetachedBindMode ) {
31899
31900			this.bindMatrixInverse.copy( this.bindMatrix ).invert();
31901
31902		} else {
31903
31904			console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
31905
31906		}
31907
31908	}
31909
31910	applyBoneTransform( index, vector ) {
31911
31912		const skeleton = this.skeleton;
31913		const geometry = this.geometry;
31914
31915		_skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
31916		_skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
31917
31918		_basePosition.copy( vector ).applyMatrix4( this.bindMatrix );
31919
31920		vector.set( 0, 0, 0 );
31921
31922		for ( let i = 0; i < 4; i ++ ) {
31923
31924			const weight = _skinWeight.getComponent( i );
31925
31926			if ( weight !== 0 ) {
31927
31928				const boneIndex = _skinIndex.getComponent( i );
31929
31930				_matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
31931
31932				vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight );
31933
31934			}
31935
31936		}
31937
31938		return vector.applyMatrix4( this.bindMatrixInverse );
31939
31940	}
31941
31942}
31943
31944class Bone extends Object3D {
31945
31946	constructor() {
31947
31948		super();
31949
31950		this.isBone = true;
31951
31952		this.type = 'Bone';
31953
31954	}
31955
31956}
31957
31958class DataTexture extends Texture {
31959
31960	constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) {
31961
31962		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
31963
31964		this.isDataTexture = true;
31965
31966		this.image = { data: data, width: width, height: height };
31967
31968		this.generateMipmaps = false;
31969		this.flipY = false;
31970		this.unpackAlignment = 1;
31971
31972	}
31973
31974}
31975
31976const _offsetMatrix = /*@__PURE__*/ new Matrix4();
31977const _identityMatrix$1 = /*@__PURE__*/ new Matrix4();
31978
31979class Skeleton {
31980
31981	constructor( bones = [], boneInverses = [] ) {
31982
31983		this.uuid = generateUUID();
31984
31985		this.bones = bones.slice( 0 );
31986		this.boneInverses = boneInverses;
31987		this.boneMatrices = null;
31988
31989		this.boneTexture = null;
31990
31991		this.init();
31992
31993	}
31994
31995	init() {
31996
31997		const bones = this.bones;
31998		const boneInverses = this.boneInverses;
31999
32000		this.boneMatrices = new Float32Array( bones.length * 16 );
32001
32002		// calculate inverse bone matrices if necessary
32003
32004		if ( boneInverses.length === 0 ) {
32005
32006			this.calculateInverses();
32007
32008		} else {
32009
32010			// handle special case
32011
32012			if ( bones.length !== boneInverses.length ) {
32013
32014				console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
32015
32016				this.boneInverses = [];
32017
32018				for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32019
32020					this.boneInverses.push( new Matrix4() );
32021
32022				}
32023
32024			}
32025
32026		}
32027
32028	}
32029
32030	calculateInverses() {
32031
32032		this.boneInverses.length = 0;
32033
32034		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32035
32036			const inverse = new Matrix4();
32037
32038			if ( this.bones[ i ] ) {
32039
32040				inverse.copy( this.bones[ i ].matrixWorld ).invert();
32041
32042			}
32043
32044			this.boneInverses.push( inverse );
32045
32046		}
32047
32048	}
32049
32050	pose() {
32051
32052		// recover the bind-time world matrices
32053
32054		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32055
32056			const bone = this.bones[ i ];
32057
32058			if ( bone ) {
32059
32060				bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
32061
32062			}
32063
32064		}
32065
32066		// compute the local matrices, positions, rotations and scales
32067
32068		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32069
32070			const bone = this.bones[ i ];
32071
32072			if ( bone ) {
32073
32074				if ( bone.parent && bone.parent.isBone ) {
32075
32076					bone.matrix.copy( bone.parent.matrixWorld ).invert();
32077					bone.matrix.multiply( bone.matrixWorld );
32078
32079				} else {
32080
32081					bone.matrix.copy( bone.matrixWorld );
32082
32083				}
32084
32085				bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
32086
32087			}
32088
32089		}
32090
32091	}
32092
32093	update() {
32094
32095		const bones = this.bones;
32096		const boneInverses = this.boneInverses;
32097		const boneMatrices = this.boneMatrices;
32098		const boneTexture = this.boneTexture;
32099
32100		// flatten bone matrices to array
32101
32102		for ( let i = 0, il = bones.length; i < il; i ++ ) {
32103
32104			// compute the offset between the current and the original transform
32105
32106			const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1;
32107
32108			_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
32109			_offsetMatrix.toArray( boneMatrices, i * 16 );
32110
32111		}
32112
32113		if ( boneTexture !== null ) {
32114
32115			boneTexture.needsUpdate = true;
32116
32117		}
32118
32119	}
32120
32121	clone() {
32122
32123		return new Skeleton( this.bones, this.boneInverses );
32124
32125	}
32126
32127	computeBoneTexture() {
32128
32129		// layout (1 matrix = 4 pixels)
32130		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
32131		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
32132		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
32133		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
32134		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
32135
32136		let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
32137		size = Math.ceil( size / 4 ) * 4;
32138		size = Math.max( size, 4 );
32139
32140		const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
32141		boneMatrices.set( this.boneMatrices ); // copy current values
32142
32143		const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
32144		boneTexture.needsUpdate = true;
32145
32146		this.boneMatrices = boneMatrices;
32147		this.boneTexture = boneTexture;
32148
32149		return this;
32150
32151	}
32152
32153	getBoneByName( name ) {
32154
32155		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32156
32157			const bone = this.bones[ i ];
32158
32159			if ( bone.name === name ) {
32160
32161				return bone;
32162
32163			}
32164
32165		}
32166
32167		return undefined;
32168
32169	}
32170
32171	dispose( ) {
32172
32173		if ( this.boneTexture !== null ) {
32174
32175			this.boneTexture.dispose();
32176
32177			this.boneTexture = null;
32178
32179		}
32180
32181	}
32182
32183	fromJSON( json, bones ) {
32184
32185		this.uuid = json.uuid;
32186
32187		for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
32188
32189			const uuid = json.bones[ i ];
32190			let bone = bones[ uuid ];
32191
32192			if ( bone === undefined ) {
32193
32194				console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid );
32195				bone = new Bone();
32196
32197			}
32198
32199			this.bones.push( bone );
32200			this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
32201
32202		}
32203
32204		this.init();
32205
32206		return this;
32207
32208	}
32209
32210	toJSON() {
32211
32212		const data = {
32213			metadata: {
32214				version: 4.6,
32215				type: 'Skeleton',
32216				generator: 'Skeleton.toJSON'
32217			},
32218			bones: [],
32219			boneInverses: []
32220		};
32221
32222		data.uuid = this.uuid;
32223
32224		const bones = this.bones;
32225		const boneInverses = this.boneInverses;
32226
32227		for ( let i = 0, l = bones.length; i < l; i ++ ) {
32228
32229			const bone = bones[ i ];
32230			data.bones.push( bone.uuid );
32231
32232			const boneInverse = boneInverses[ i ];
32233			data.boneInverses.push( boneInverse.toArray() );
32234
32235		}
32236
32237		return data;
32238
32239	}
32240
32241}
32242
32243class InstancedBufferAttribute extends BufferAttribute {
32244
32245	constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {
32246
32247		super( array, itemSize, normalized );
32248
32249		this.isInstancedBufferAttribute = true;
32250
32251		this.meshPerAttribute = meshPerAttribute;
32252
32253	}
32254
32255	copy( source ) {
32256
32257		super.copy( source );
32258
32259		this.meshPerAttribute = source.meshPerAttribute;
32260
32261		return this;
32262
32263	}
32264
32265	toJSON() {
32266
32267		const data = super.toJSON();
32268
32269		data.meshPerAttribute = this.meshPerAttribute;
32270
32271		data.isInstancedBufferAttribute = true;
32272
32273		return data;
32274
32275	}
32276
32277}
32278
32279const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
32280const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
32281
32282const _instanceIntersects = [];
32283
32284const _box3 = /*@__PURE__*/ new Box3();
32285const _identity = /*@__PURE__*/ new Matrix4();
32286const _mesh$1 = /*@__PURE__*/ new Mesh();
32287const _sphere$3 = /*@__PURE__*/ new Sphere();
32288
32289class InstancedMesh extends Mesh {
32290
32291	constructor( geometry, material, count ) {
32292
32293		super( geometry, material );
32294
32295		this.isInstancedMesh = true;
32296
32297		this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
32298		this.instanceColor = null;
32299		this.morphTexture = null;
32300
32301		this.count = count;
32302
32303		this.boundingBox = null;
32304		this.boundingSphere = null;
32305
32306		for ( let i = 0; i < count; i ++ ) {
32307
32308			this.setMatrixAt( i, _identity );
32309
32310		}
32311
32312	}
32313
32314	computeBoundingBox() {
32315
32316		const geometry = this.geometry;
32317		const count = this.count;
32318
32319		if ( this.boundingBox === null ) {
32320
32321			this.boundingBox = new Box3();
32322
32323		}
32324
32325		if ( geometry.boundingBox === null ) {
32326
32327			geometry.computeBoundingBox();
32328
32329		}
32330
32331		this.boundingBox.makeEmpty();
32332
32333		for ( let i = 0; i < count; i ++ ) {
32334
32335			this.getMatrixAt( i, _instanceLocalMatrix );
32336
32337			_box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix );
32338
32339			this.boundingBox.union( _box3 );
32340
32341		}
32342
32343	}
32344
32345	computeBoundingSphere() {
32346
32347		const geometry = this.geometry;
32348		const count = this.count;
32349
32350		if ( this.boundingSphere === null ) {
32351
32352			this.boundingSphere = new Sphere();
32353
32354		}
32355
32356		if ( geometry.boundingSphere === null ) {
32357
32358			geometry.computeBoundingSphere();
32359
32360		}
32361
32362		this.boundingSphere.makeEmpty();
32363
32364		for ( let i = 0; i < count; i ++ ) {
32365
32366			this.getMatrixAt( i, _instanceLocalMatrix );
32367
32368			_sphere$3.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix );
32369
32370			this.boundingSphere.union( _sphere$3 );
32371
32372		}
32373
32374	}
32375
32376	copy( source, recursive ) {
32377
32378		super.copy( source, recursive );
32379
32380		this.instanceMatrix.copy( source.instanceMatrix );
32381
32382		if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone();
32383		if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
32384
32385		this.count = source.count;
32386
32387		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
32388		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
32389
32390		return this;
32391
32392	}
32393
32394	getColorAt( index, color ) {
32395
32396		color.fromArray( this.instanceColor.array, index * 3 );
32397
32398	}
32399
32400	getMatrixAt( index, matrix ) {
32401
32402		matrix.fromArray( this.instanceMatrix.array, index * 16 );
32403
32404	}
32405
32406	getMorphAt( index, object ) {
32407
32408		const objectInfluences = object.morphTargetInfluences;
32409
32410		const array = this.morphTexture.source.data.data;
32411
32412		const len = objectInfluences.length + 1; // All influences + the baseInfluenceSum
32413
32414		const dataIndex = index * len + 1; // Skip the baseInfluenceSum at the beginning
32415
32416		for ( let i = 0; i < objectInfluences.length; i ++ ) {
32417
32418			objectInfluences[ i ] = array[ dataIndex + i ];
32419
32420		}
32421
32422	}
32423
32424	raycast( raycaster, intersects ) {
32425
32426		const matrixWorld = this.matrixWorld;
32427		const raycastTimes = this.count;
32428
32429		_mesh$1.geometry = this.geometry;
32430		_mesh$1.material = this.material;
32431
32432		if ( _mesh$1.material === undefined ) return;
32433
32434		// test with bounding sphere first
32435
32436		if ( this.boundingSphere === null ) this.computeBoundingSphere();
32437
32438		_sphere$3.copy( this.boundingSphere );
32439		_sphere$3.applyMatrix4( matrixWorld );
32440
32441		if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
32442
32443		// now test each instance
32444
32445		for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
32446
32447			// calculate the world matrix for each instance
32448
32449			this.getMatrixAt( instanceId, _instanceLocalMatrix );
32450
32451			_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
32452
32453			// the mesh represents this single instance
32454
32455			_mesh$1.matrixWorld = _instanceWorldMatrix;
32456
32457			_mesh$1.raycast( raycaster, _instanceIntersects );
32458
32459			// process the result of raycast
32460
32461			for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
32462
32463				const intersect = _instanceIntersects[ i ];
32464				intersect.instanceId = instanceId;
32465				intersect.object = this;
32466				intersects.push( intersect );
32467
32468			}
32469
32470			_instanceIntersects.length = 0;
32471
32472		}
32473
32474	}
32475
32476	setColorAt( index, color ) {
32477
32478		if ( this.instanceColor === null ) {
32479
32480			this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 );
32481
32482		}
32483
32484		color.toArray( this.instanceColor.array, index * 3 );
32485
32486	}
32487
32488	setMatrixAt( index, matrix ) {
32489
32490		matrix.toArray( this.instanceMatrix.array, index * 16 );
32491
32492	}
32493
32494	setMorphAt( index, object ) {
32495
32496		const objectInfluences = object.morphTargetInfluences;
32497
32498		const len = objectInfluences.length + 1; // morphBaseInfluence + all influences
32499
32500		if ( this.morphTexture === null ) {
32501
32502			this.morphTexture = new DataTexture( new Float32Array( len * this.count ), len, this.count, RedFormat, FloatType );
32503
32504		}
32505
32506		const array = this.morphTexture.source.data.data;
32507
32508		let morphInfluencesSum = 0;
32509
32510		for ( let i = 0; i < objectInfluences.length; i ++ ) {
32511
32512			morphInfluencesSum += objectInfluences[ i ];
32513
32514		}
32515
32516		const morphBaseInfluence = this.geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
32517
32518		const dataIndex = len * index;
32519
32520		array[ dataIndex ] = morphBaseInfluence;
32521
32522		array.set( objectInfluences, dataIndex + 1 );
32523
32524	}
32525
32526	updateMorphTargets() {
32527
32528	}
32529
32530	dispose() {
32531
32532		this.dispatchEvent( { type: 'dispose' } );
32533
32534		if ( this.morphTexture !== null ) {
32535
32536			this.morphTexture.dispose();
32537			this.morphTexture = null;
32538
32539		}
32540
32541		return this;
32542
32543	}
32544
32545}
32546
32547function sortOpaque( a, b ) {
32548
32549	return a.z - b.z;
32550
32551}
32552
vendor: 5,260 bytes, lines 32553-32761
32553function sortTransparent( a, b ) {
32554
32555	return b.z - a.z;
32556
32557}
32558
32559class MultiDrawRenderList {
32560
32561	constructor() {
32562
32563		this.index = 0;
32564		this.pool = [];
32565		this.list = [];
32566
32567	}
32568
32569	push( drawRange, z ) {
32570
32571		const pool = this.pool;
32572		const list = this.list;
32573		if ( this.index >= pool.length ) {
32574
32575			pool.push( {
32576
32577				start: - 1,
32578				count: - 1,
32579				z: - 1,
32580
32581			} );
32582
32583		}
32584
32585		const item = pool[ this.index ];
32586		list.push( item );
32587		this.index ++;
32588
32589		item.start = drawRange.start;
32590		item.count = drawRange.count;
32591		item.z = z;
32592
32593	}
32594
32595	reset() {
32596
32597		this.list.length = 0;
32598		this.index = 0;
32599
32600	}
32601
32602}
32603
32604const ID_ATTR_NAME = 'batchId';
32605const _matrix$1 = /*@__PURE__*/ new Matrix4();
32606const _invMatrixWorld = /*@__PURE__*/ new Matrix4();
32607const _identityMatrix = /*@__PURE__*/ new Matrix4();
32608const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4();
32609const _frustum = /*@__PURE__*/ new Frustum();
32610const _box$1 = /*@__PURE__*/ new Box3();
32611const _sphere$2 = /*@__PURE__*/ new Sphere();
32612const _vector$5 = /*@__PURE__*/ new Vector3();
32613const _renderList = /*@__PURE__*/ new MultiDrawRenderList();
32614const _mesh = /*@__PURE__*/ new Mesh();
32615const _batchIntersects = [];
32616
32617// @TODO: SkinnedMesh support?
32618// @TODO: geometry.groups support?
32619// @TODO: geometry.drawRange support?
32620// @TODO: geometry.morphAttributes support?
32621// @TODO: Support uniform parameter per geometry
32622// @TODO: Add an "optimize" function to pack geometry and remove data gaps
32623
32624// copies data from attribute "src" into "target" starting at "targetOffset"
32625function copyAttributeData( src, target, targetOffset = 0 ) {
32626
32627	const itemSize = target.itemSize;
32628	if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) {
32629
32630		// use the component getters and setters if the array data cannot
32631		// be copied directly
32632		const vertexCount = src.count;
32633		for ( let i = 0; i < vertexCount; i ++ ) {
32634
32635			for ( let c = 0; c < itemSize; c ++ ) {
32636
32637				target.setComponent( i + targetOffset, c, src.getComponent( i, c ) );
32638
32639			}
32640
32641		}
32642
32643	} else {
32644
32645		// faster copy approach using typed array set function
32646		target.array.set( src.array, targetOffset * itemSize );
32647
32648	}
32649
32650	target.needsUpdate = true;
32651
32652}
32653
32654class BatchedMesh extends Mesh {
32655
32656	get maxGeometryCount() {
32657
32658		return this._maxGeometryCount;
32659
32660	}
32661
32662	constructor( maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) {
32663
32664		super( new BufferGeometry(), material );
32665
32666		this.isBatchedMesh = true;
32667		this.perObjectFrustumCulled = true;
32668		this.sortObjects = true;
32669		this.boundingBox = null;
32670		this.boundingSphere = null;
32671		this.customSort = null;
32672
32673		this._drawRanges = [];
32674		this._reservedRanges = [];
32675
32676		this._visibility = [];
32677		this._active = [];
32678		this._bounds = [];
32679
32680		this._maxGeometryCount = maxGeometryCount;
32681		this._maxVertexCount = maxVertexCount;
32682		this._maxIndexCount = maxIndexCount;
32683
32684		this._geometryInitialized = false;
32685		this._geometryCount = 0;
32686		this._multiDrawCounts = new Int32Array( maxGeometryCount );
32687		this._multiDrawStarts = new Int32Array( maxGeometryCount );
32688		this._multiDrawCount = 0;
32689		this._visibilityChanged = true;
32690
32691		// Local matrix per geometry by using data texture
32692		this._matricesTexture = null;
32693
32694		this._initMatricesTexture();
32695
32696	}
32697
32698	_initMatricesTexture() {
32699
32700		// layout (1 matrix = 4 pixels)
32701		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
32702		//  with  8x8  pixel texture max   16 matrices * 4 pixels =  (8 * 8)
32703		//       16x16 pixel texture max   64 matrices * 4 pixels = (16 * 16)
32704		//       32x32 pixel texture max  256 matrices * 4 pixels = (32 * 32)
32705		//       64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64)
32706
32707		let size = Math.sqrt( this._maxGeometryCount * 4 ); // 4 pixels needed for 1 matrix
32708		size = Math.ceil( size / 4 ) * 4;
32709		size = Math.max( size, 4 );
32710
32711		const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
32712		const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType );
32713
32714		this._matricesTexture = matricesTexture;
32715
32716	}
32717
32718	_initializeGeometry( reference ) {
32719
32720		const geometry = this.geometry;
32721		const maxVertexCount = this._maxVertexCount;
32722		const maxGeometryCount = this._maxGeometryCount;
32723		const maxIndexCount = this._maxIndexCount;
32724		if ( this._geometryInitialized === false ) {
32725
32726			for ( const attributeName in reference.attributes ) {
32727
32728				const srcAttribute = reference.getAttribute( attributeName );
32729				const { array, itemSize, normalized } = srcAttribute;
32730
32731				const dstArray = new array.constructor( maxVertexCount * itemSize );
32732				const dstAttribute = new BufferAttribute( dstArray, itemSize, normalized );
32733
32734				geometry.setAttribute( attributeName, dstAttribute );
32735
32736			}
32737
32738			if ( reference.getIndex() !== null ) {
32739
32740				const indexArray = maxVertexCount > 65536
32741					? new Uint32Array( maxIndexCount )
32742					: new Uint16Array( maxIndexCount );
32743
32744				geometry.setIndex( new BufferAttribute( indexArray, 1 ) );
32745
32746			}
32747
32748			const idArray = maxGeometryCount > 65536
32749				? new Uint32Array( maxVertexCount )
32750				: new Uint16Array( maxVertexCount );
32751			geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) );
32752
32753			this._geometryInitialized = true;
32754
32755		}
32756
32757	}
32758
32759	// Make sure the geometry is compatible with the existing combined geometry attributes
32760	_validateGeometry( geometry ) {
32761
32762		// check that the geometry doesn't have a version of our reserved id attribute
32763		if ( geometry.getAttribute( ID_ATTR_NAME ) ) {
32764
32765			throw new Error( `BatchedMesh: Geometry cannot use attribute "${ ID_ATTR_NAME }"` );
32766
32767		}
32768
32769		// check to ensure the geometries are using consistent attributes and indices
32770		const batchGeometry = this.geometry;
32771		if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
32772
32773			throw new Error( 'BatchedMesh: All geometries must consistently have "index".' );
32774
32775		}
32776
32777		for ( const attributeName in batchGeometry.attributes ) {
32778
32779			if ( attributeName === ID_ATTR_NAME ) {
32780
32781				continue;
32782
32783			}
32784
32785			if ( ! geometry.hasAttribute( attributeName ) ) {
32786
32787				throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
32788
32789			}
32790
32791			const srcAttribute = geometry.getAttribute( attributeName );
32792			const dstAttribute = batchGeometry.getAttribute( attributeName );
32793			if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
32794
32795				throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
32796
32797			}
32798
32799		}
32800
32801	}
32802
32803	setCustomSort( func ) {
32804
32805		this.customSort = func;
32806		return this;
32807
32808	}
32809
32810	computeBoundingBox() {
32811
32812		if ( this.boundingBox === null ) {
32813
32814			this.boundingBox = new Box3();
32815
32816		}
32817
32818		const geometryCount = this._geometryCount;
32819		const boundingBox = this.boundingBox;
32820		const active = this._active;
32821
32822		boundingBox.makeEmpty();
32823		for ( let i = 0; i < geometryCount; i ++ ) {
32824
32825			if ( active[ i ] === false ) continue;
32826
32827			this.getMatrixAt( i, _matrix$1 );
32828			this.getBoundingBoxAt( i, _box$1 ).applyMatrix4( _matrix$1 );
32829			boundingBox.union( _box$1 );
32830
32831		}
32832
32833	}
32834
32835	computeBoundingSphere() {
32836
32837		if ( this.boundingSphere === null ) {
32838
32839			this.boundingSphere = new Sphere();
32840
32841		}
32842
32843		const geometryCount = this._geometryCount;
32844		const boundingSphere = this.boundingSphere;
32845		const active = this._active;
32846
32847		boundingSphere.makeEmpty();
32848		for ( let i = 0; i < geometryCount; i ++ ) {
32849
32850			if ( active[ i ] === false ) continue;
32851
32852			this.getMatrixAt( i, _matrix$1 );
32853			this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 );
32854			boundingSphere.union( _sphere$2 );
32855
32856		}
32857
32858	}
32859
32860	addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) {
32861
32862		this._initializeGeometry( geometry );
32863
32864		this._validateGeometry( geometry );
32865
32866		// ensure we're not over geometry
32867		if ( this._geometryCount >= this._maxGeometryCount ) {
32868
32869			throw new Error( 'BatchedMesh: Maximum geometry count reached.' );
32870
32871		}
32872
32873		// get the necessary range fo the geometry
32874		const reservedRange = {
32875			vertexStart: - 1,
32876			vertexCount: - 1,
32877			indexStart: - 1,
32878			indexCount: - 1,
32879		};
32880
32881		let lastRange = null;
32882		const reservedRanges = this._reservedRanges;
32883		const drawRanges = this._drawRanges;
32884		const bounds = this._bounds;
32885		if ( this._geometryCount !== 0 ) {
32886
32887			lastRange = reservedRanges[ reservedRanges.length - 1 ];
32888
32889		}
32890
32891		if ( vertexCount === - 1 ) {
32892
32893			reservedRange.vertexCount = geometry.getAttribute( 'position' ).count;
32894
32895		} else {
32896
32897			reservedRange.vertexCount = vertexCount;
32898
32899		}
32900
32901		if ( lastRange === null ) {
32902
32903			reservedRange.vertexStart = 0;
32904
32905		} else {
32906
32907			reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount;
32908
32909		}
32910
32911		const index = geometry.getIndex();
32912		const hasIndex = index !== null;
32913		if ( hasIndex ) {
32914
32915			if ( indexCount	=== - 1 ) {
32916
32917				reservedRange.indexCount = index.count;
32918
32919			} else {
32920
32921				reservedRange.indexCount = indexCount;
32922
32923			}
32924
32925			if ( lastRange === null ) {
32926
32927				reservedRange.indexStart = 0;
32928
32929			} else {
32930
32931				reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount;
32932
32933			}
32934
32935		}
32936
32937		if (
32938			reservedRange.indexStart !== - 1 &&
32939			reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount ||
32940			reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount
32941		) {
32942
32943			throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
32944
32945		}
32946
32947		const visibility = this._visibility;
32948		const active = this._active;
32949		const matricesTexture = this._matricesTexture;
32950		const matricesArray = this._matricesTexture.image.data;
32951
32952		// push new visibility states
32953		visibility.push( true );
32954		active.push( true );
32955
32956		// update id
32957		const geometryId = this._geometryCount;
32958		this._geometryCount ++;
32959
32960		// initialize matrix information
32961		_identityMatrix.toArray( matricesArray, geometryId * 16 );
32962		matricesTexture.needsUpdate = true;
32963
32964		// add the reserved range and draw range objects
32965		reservedRanges.push( reservedRange );
32966		drawRanges.push( {
32967			start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart,
32968			count: - 1
32969		} );
32970		bounds.push( {
32971			boxInitialized: false,
32972			box: new Box3(),
32973
32974			sphereInitialized: false,
32975			sphere: new Sphere()
32976		} );
32977
32978		// set the id for the geometry
32979		const idAttribute = this.geometry.getAttribute( ID_ATTR_NAME );
32980		for ( let i = 0; i < reservedRange.vertexCount; i ++ ) {
32981
32982			idAttribute.setX( reservedRange.vertexStart + i, geometryId );
32983
32984		}
32985
32986		idAttribute.needsUpdate = true;
32987
32988		// update the geometry
32989		this.setGeometryAt( geometryId, geometry );
32990
32991		return geometryId;
32992
32993	}
32994
32995	setGeometryAt( id, geometry ) {
32996
32997		if ( id >= this._geometryCount ) {
32998
32999			throw new Error( 'BatchedMesh: Maximum geometry count reached.' );
33000
33001		}
33002
33003		this._validateGeometry( geometry );
33004
33005		const batchGeometry = this.geometry;
33006		const hasIndex = batchGeometry.getIndex() !== null;
33007		const dstIndex = batchGeometry.getIndex();
33008		const srcIndex = geometry.getIndex();
33009		const reservedRange = this._reservedRanges[ id ];
33010		if (
33011			hasIndex &&
33012			srcIndex.count > reservedRange.indexCount ||
33013			geometry.attributes.position.count > reservedRange.vertexCount
33014		) {
33015
33016			throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' );
33017
33018		}
33019
33020		// copy geometry over
33021		const vertexStart = reservedRange.vertexStart;
33022		const vertexCount = reservedRange.vertexCount;
33023		for ( const attributeName in batchGeometry.attributes ) {
33024
33025			if ( attributeName === ID_ATTR_NAME ) {
33026
33027				continue;
33028
33029			}
33030
33031			// copy attribute data
33032			const srcAttribute = geometry.getAttribute( attributeName );
33033			const dstAttribute = batchGeometry.getAttribute( attributeName );
33034			copyAttributeData( srcAttribute, dstAttribute, vertexStart );
33035
33036			// fill the rest in with zeroes
33037			const itemSize = srcAttribute.itemSize;
33038			for ( let i = srcAttribute.count, l = vertexCount; i < l; i ++ ) {
33039
33040				const index = vertexStart + i;
33041				for ( let c = 0; c < itemSize; c ++ ) {
33042
33043					dstAttribute.setComponent( index, c, 0 );
33044
33045				}
33046
33047			}
33048
33049			dstAttribute.needsUpdate = true;
33050			dstAttribute.addUpdateRange( vertexStart * itemSize, vertexCount * itemSize );
33051
33052		}
33053
33054		// copy index
33055		if ( hasIndex ) {
33056
33057			const indexStart = reservedRange.indexStart;
33058
33059			// copy index data over
33060			for ( let i = 0; i < srcIndex.count; i ++ ) {
33061
33062				dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) );
33063
33064			}
33065
33066			// fill the rest in with zeroes
33067			for ( let i = srcIndex.count, l = reservedRange.indexCount; i < l; i ++ ) {
33068
33069				dstIndex.setX( indexStart + i, vertexStart );
33070
33071			}
33072
33073			dstIndex.needsUpdate = true;
33074			dstIndex.addUpdateRange( indexStart, reservedRange.indexCount );
33075
33076		}
33077
33078		// store the bounding boxes
33079		const bound = this._bounds[ id ];
33080		if ( geometry.boundingBox !== null ) {
33081
33082			bound.box.copy( geometry.boundingBox );
33083			bound.boxInitialized = true;
33084
33085		} else {
33086
33087			bound.boxInitialized = false;
33088
33089		}
33090
33091		if ( geometry.boundingSphere !== null ) {
33092
33093			bound.sphere.copy( geometry.boundingSphere );
33094			bound.sphereInitialized = true;
33095
33096		} else {
33097
33098			bound.sphereInitialized = false;
33099
33100		}
33101
33102		// set drawRange count
33103		const drawRange = this._drawRanges[ id ];
33104		const posAttr = geometry.getAttribute( 'position' );
33105		drawRange.count = hasIndex ? srcIndex.count : posAttr.count;
33106		this._visibilityChanged = true;
33107
33108		return id;
33109
33110	}
33111
33112	deleteGeometry( geometryId ) {
33113
33114		// Note: User needs to call optimize() afterward to pack the data.
33115
33116		const active = this._active;
33117		if ( geometryId >= active.length || active[ geometryId ] === false ) {
33118
33119			return this;
33120
33121		}
33122
33123		active[ geometryId ] = false;
33124		this._visibilityChanged = true;
33125
33126		return this;
33127
33128	}
33129
33130	// get bounding box and compute it if it doesn't exist
33131	getBoundingBoxAt( id, target ) {
33132
33133		const active = this._active;
33134		if ( active[ id ] === false ) {
33135
33136			return null;
33137
33138		}
33139
33140		// compute bounding box
33141		const bound = this._bounds[ id ];
33142		const box = bound.box;
33143		const geometry = this.geometry;
33144		if ( bound.boxInitialized === false ) {
33145
33146			box.makeEmpty();
33147
33148			const index = geometry.index;
33149			const position = geometry.attributes.position;
33150			const drawRange = this._drawRanges[ id ];
33151			for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) {
33152
33153				let iv = i;
33154				if ( index ) {
33155
33156					iv = index.getX( iv );
33157
33158				}
33159
33160				box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) );
33161
33162			}
33163
33164			bound.boxInitialized = true;
33165
33166		}
33167
33168		target.copy( box );
33169		return target;
33170
33171	}
33172
33173	// get bounding sphere and compute it if it doesn't exist
33174	getBoundingSphereAt( id, target ) {
33175
33176		const active = this._active;
33177		if ( active[ id ] === false ) {
33178
33179			return null;
33180
33181		}
33182
33183		// compute bounding sphere
33184		const bound = this._bounds[ id ];
33185		const sphere = bound.sphere;
33186		const geometry = this.geometry;
33187		if ( bound.sphereInitialized === false ) {
33188
33189			sphere.makeEmpty();
33190
33191			this.getBoundingBoxAt( id, _box$1 );
33192			_box$1.getCenter( sphere.center );
33193
33194			const index = geometry.index;
33195			const position = geometry.attributes.position;
33196			const drawRange = this._drawRanges[ id ];
33197
33198			let maxRadiusSq = 0;
33199			for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) {
33200
33201				let iv = i;
33202				if ( index ) {
33203
33204					iv = index.getX( iv );
33205
33206				}
33207
33208				_vector$5.fromBufferAttribute( position, iv );
33209				maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) );
33210
33211			}
33212
33213			sphere.radius = Math.sqrt( maxRadiusSq );
33214			bound.sphereInitialized = true;
33215
33216		}
33217
33218		target.copy( sphere );
33219		return target;
33220
33221	}
33222
33223	setMatrixAt( geometryId, matrix ) {
33224
33225		// @TODO: Map geometryId to index of the arrays because
33226		//        optimize() can make geometryId mismatch the index
33227
33228		const active = this._active;
33229		const matricesTexture = this._matricesTexture;
33230		const matricesArray = this._matricesTexture.image.data;
33231		const geometryCount = this._geometryCount;
33232		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33233
33234			return this;
33235
33236		}
33237
33238		matrix.toArray( matricesArray, geometryId * 16 );
33239		matricesTexture.needsUpdate = true;
33240
33241		return this;
33242
33243	}
33244
33245	getMatrixAt( geometryId, matrix ) {
33246
33247		const active = this._active;
33248		const matricesArray = this._matricesTexture.image.data;
33249		const geometryCount = this._geometryCount;
33250		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33251
33252			return null;
33253
33254		}
33255
33256		return matrix.fromArray( matricesArray, geometryId * 16 );
33257
33258	}
33259
33260	setVisibleAt( geometryId, value ) {
33261
33262		const visibility = this._visibility;
33263		const active = this._active;
33264		const geometryCount = this._geometryCount;
33265
33266		// if the geometry is out of range, not active, or visibility state
33267		// does not change then return early
33268		if (
33269			geometryId >= geometryCount ||
33270			active[ geometryId ] === false ||
33271			visibility[ geometryId ] === value
33272		) {
33273
33274			return this;
33275
33276		}
33277
33278		visibility[ geometryId ] = value;
33279		this._visibilityChanged = true;
33280
33281		return this;
33282
33283	}
33284
33285	getVisibleAt( geometryId ) {
33286
33287		const visibility = this._visibility;
33288		const active = this._active;
33289		const geometryCount = this._geometryCount;
33290
33291		// return early if the geometry is out of range or not active
33292		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33293
33294			return false;
33295
33296		}
33297
33298		return visibility[ geometryId ];
33299
33300	}
33301
33302	raycast( raycaster, intersects ) {
33303
33304		const visibility = this._visibility;
33305		const active = this._active;
33306		const drawRanges = this._drawRanges;
33307		const geometryCount = this._geometryCount;
33308		const matrixWorld = this.matrixWorld;
33309		const batchGeometry = this.geometry;
33310
33311		// iterate over each geometry
33312		_mesh.material = this.material;
33313		_mesh.geometry.index = batchGeometry.index;
33314		_mesh.geometry.attributes = batchGeometry.attributes;
33315		if ( _mesh.geometry.boundingBox === null ) {
33316
33317			_mesh.geometry.boundingBox = new Box3();
33318
33319		}
33320
33321		if ( _mesh.geometry.boundingSphere === null ) {
33322
33323			_mesh.geometry.boundingSphere = new Sphere();
33324
33325		}
33326
33327		for ( let i = 0; i < geometryCount; i ++ ) {
33328
33329			if ( ! visibility[ i ] || ! active[ i ] ) {
33330
33331				continue;
33332
33333			}
33334
33335			const drawRange = drawRanges[ i ];
33336			_mesh.geometry.setDrawRange( drawRange.start, drawRange.count );
33337
33338			// ge the intersects
33339			this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld );
33340			this.getBoundingBoxAt( i, _mesh.geometry.boundingBox );
33341			this.getBoundingSphereAt( i, _mesh.geometry.boundingSphere );
33342			_mesh.raycast( raycaster, _batchIntersects );
33343
33344			// add batch id to the intersects
33345			for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) {
33346
33347				const intersect = _batchIntersects[ j ];
33348				intersect.object = this;
33349				intersect.batchId = i;
33350				intersects.push( intersect );
33351
33352			}
33353
33354			_batchIntersects.length = 0;
33355
33356		}
33357
33358		_mesh.material = null;
33359		_mesh.geometry.index = null;
33360		_mesh.geometry.attributes = {};
33361		_mesh.geometry.setDrawRange( 0, Infinity );
33362
33363	}
33364
33365	copy( source ) {
33366
33367		super.copy( source );
33368
33369		this.geometry = source.geometry.clone();
33370		this.perObjectFrustumCulled = source.perObjectFrustumCulled;
33371		this.sortObjects = source.sortObjects;
33372		this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
33373		this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
33374
33375		this._drawRanges = source._drawRanges.map( range => ( { ...range } ) );
33376		this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) );
33377
33378		this._visibility = source._visibility.slice();
33379		this._active = source._active.slice();
33380		this._bounds = source._bounds.map( bound => ( {
33381			boxInitialized: bound.boxInitialized,
33382			box: bound.box.clone(),
33383
33384			sphereInitialized: bound.sphereInitialized,
33385			sphere: bound.sphere.clone()
33386		} ) );
33387
33388		this._maxGeometryCount = source._maxGeometryCount;
33389		this._maxVertexCount = source._maxVertexCount;
33390		this._maxIndexCount = source._maxIndexCount;
33391
33392		this._geometryInitialized = source._geometryInitialized;
33393		this._geometryCount = source._geometryCount;
33394		this._multiDrawCounts = source._multiDrawCounts.slice();
33395		this._multiDrawStarts = source._multiDrawStarts.slice();
33396
33397		this._matricesTexture = source._matricesTexture.clone();
33398		this._matricesTexture.image.data = this._matricesTexture.image.slice();
33399
33400		return this;
33401
33402	}
33403
33404	dispose() {
33405
33406		// Assuming the geometry is not shared with other meshes
33407		this.geometry.dispose();
33408
33409		this._matricesTexture.dispose();
33410		this._matricesTexture = null;
33411		return this;
33412
33413	}
33414
33415	onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) {
33416
33417		// if visibility has not changed and frustum culling and object sorting is not required
33418		// then skip iterating over all items
33419		if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) {
33420
33421			return;
33422
33423		}
33424
33425		// the indexed version of the multi draw function requires specifying the start
33426		// offset in bytes.
33427		const index = geometry.getIndex();
33428		const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
33429
33430		const active = this._active;
33431		const visibility = this._visibility;
33432		const multiDrawStarts = this._multiDrawStarts;
33433		const multiDrawCounts = this._multiDrawCounts;
33434		const drawRanges = this._drawRanges;
33435		const perObjectFrustumCulled = this.perObjectFrustumCulled;
33436
33437		// prepare the frustum in the local frame
33438		if ( perObjectFrustumCulled ) {
33439
33440			_projScreenMatrix$2
33441				.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse )
33442				.multiply( this.matrixWorld );
33443			_frustum.setFromProjectionMatrix(
33444				_projScreenMatrix$2,
33445				renderer.coordinateSystem
33446			);
33447
33448		}
33449
33450		let count = 0;
33451		if ( this.sortObjects ) {
33452
33453			// get the camera position in the local frame
33454			_invMatrixWorld.copy( this.matrixWorld ).invert();
33455			_vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _invMatrixWorld );
33456
33457			for ( let i = 0, l = visibility.length; i < l; i ++ ) {
33458
33459				if ( visibility[ i ] && active[ i ] ) {
33460
33461					// get the bounds in world space
33462					this.getMatrixAt( i, _matrix$1 );
33463					this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 );
33464
33465					// determine whether the batched geometry is within the frustum
vendor: 13,545 bytes, lines 33466-34086
33466					let culled = false;
33467					if ( perObjectFrustumCulled ) {
33468
33469						culled = ! _frustum.intersectsSphere( _sphere$2 );
33470
33471					}
33472
33473					if ( ! culled ) {
33474
33475						// get the distance from camera used for sorting
33476						const z = _vector$5.distanceTo( _sphere$2.center );
33477						_renderList.push( drawRanges[ i ], z );
33478
33479					}
33480
33481				}
33482
33483			}
33484
33485			// Sort the draw ranges and prep for rendering
33486			const list = _renderList.list;
33487			const customSort = this.customSort;
33488			if ( customSort === null ) {
33489
33490				list.sort( material.transparent ? sortTransparent : sortOpaque );
33491
33492			} else {
33493
33494				customSort.call( this, list, camera );
33495
33496			}
33497
33498			for ( let i = 0, l = list.length; i < l; i ++ ) {
33499
33500				const item = list[ i ];
33501				multiDrawStarts[ count ] = item.start * bytesPerElement;
33502				multiDrawCounts[ count ] = item.count;
33503				count ++;
33504
33505			}
33506
33507			_renderList.reset();
33508
33509		} else {
33510
33511			for ( let i = 0, l = visibility.length; i < l; i ++ ) {
33512
33513				if ( visibility[ i ] && active[ i ] ) {
33514
33515					// determine whether the batched geometry is within the frustum
33516					let culled = false;
33517					if ( perObjectFrustumCulled ) {
33518
33519						// get the bounds in world space
33520						this.getMatrixAt( i, _matrix$1 );
33521						this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 );
33522						culled = ! _frustum.intersectsSphere( _sphere$2 );
33523
33524					}
33525
33526					if ( ! culled ) {
33527
33528						const range = drawRanges[ i ];
33529						multiDrawStarts[ count ] = range.start * bytesPerElement;
33530						multiDrawCounts[ count ] = range.count;
33531						count ++;
33532
33533					}
33534
33535				}
33536
33537			}
33538
33539		}
33540
33541		this._multiDrawCount = count;
33542		this._visibilityChanged = false;
33543
33544	}
33545
33546	onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) {
33547
33548		this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial );
33549
33550	}
33551
33552}
33553
33554class LineBasicMaterial extends Material {
33555
33556	constructor( parameters ) {
33557
33558		super();
33559
33560		this.isLineBasicMaterial = true;
33561
33562		this.type = 'LineBasicMaterial';
33563
33564		this.color = new Color( 0xffffff );
33565
33566		this.map = null;
33567
33568		this.linewidth = 1;
33569		this.linecap = 'round';
33570		this.linejoin = 'round';
33571
33572		this.fog = true;
33573
33574		this.setValues( parameters );
33575
33576	}
33577
33578
33579	copy( source ) {
33580
33581		super.copy( source );
33582
33583		this.color.copy( source.color );
33584
33585		this.map = source.map;
33586
33587		this.linewidth = source.linewidth;
33588		this.linecap = source.linecap;
33589		this.linejoin = source.linejoin;
33590
33591		this.fog = source.fog;
33592
33593		return this;
33594
33595	}
33596
33597}
33598
33599const _start$1 = /*@__PURE__*/ new Vector3();
33600const _end$1 = /*@__PURE__*/ new Vector3();
33601const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4();
33602const _ray$1 = /*@__PURE__*/ new Ray();
33603const _sphere$1 = /*@__PURE__*/ new Sphere();
33604
33605class Line extends Object3D {
33606
33607	constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
33608
33609		super();
33610
33611		this.isLine = true;
33612
33613		this.type = 'Line';
33614
33615		this.geometry = geometry;
33616		this.material = material;
33617
33618		this.updateMorphTargets();
33619
33620	}
33621
33622	copy( source, recursive ) {
33623
33624		super.copy( source, recursive );
33625
33626		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
33627		this.geometry = source.geometry;
33628
33629		return this;
33630
33631	}
33632
33633	computeLineDistances() {
33634
33635		const geometry = this.geometry;
33636
33637		// we assume non-indexed geometry
33638
33639		if ( geometry.index === null ) {
33640
33641			const positionAttribute = geometry.attributes.position;
33642			const lineDistances = [ 0 ];
33643
33644			for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
33645
33646				_start$1.fromBufferAttribute( positionAttribute, i - 1 );
33647				_end$1.fromBufferAttribute( positionAttribute, i );
33648
33649				lineDistances[ i ] = lineDistances[ i - 1 ];
33650				lineDistances[ i ] += _start$1.distanceTo( _end$1 );
33651
33652			}
33653
33654			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
33655
33656		} else {
33657
33658			console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
33659
33660		}
33661
33662		return this;
33663
33664	}
33665
33666	raycast( raycaster, intersects ) {
33667
33668		const geometry = this.geometry;
33669		const matrixWorld = this.matrixWorld;
33670		const threshold = raycaster.params.Line.threshold;
33671		const drawRange = geometry.drawRange;
33672
33673		// Checking boundingSphere distance to ray
33674
33675		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
33676
33677		_sphere$1.copy( geometry.boundingSphere );
33678		_sphere$1.applyMatrix4( matrixWorld );
33679		_sphere$1.radius += threshold;
33680
33681		if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return;
33682
33683		//
33684
33685		_inverseMatrix$1.copy( matrixWorld ).invert();
33686		_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
33687
33688		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
33689		const localThresholdSq = localThreshold * localThreshold;
33690
33691		const vStart = new Vector3();
33692		const vEnd = new Vector3();
33693		const interSegment = new Vector3();
33694		const interRay = new Vector3();
33695		const step = this.isLineSegments ? 2 : 1;
33696
33697		const index = geometry.index;
33698		const attributes = geometry.attributes;
33699		const positionAttribute = attributes.position;
33700
33701		if ( index !== null ) {
33702
33703			const start = Math.max( 0, drawRange.start );
33704			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
33705
33706			for ( let i = start, l = end - 1; i < l; i += step ) {
33707
33708				const a = index.getX( i );
33709				const b = index.getX( i + 1 );
33710
33711				vStart.fromBufferAttribute( positionAttribute, a );
33712				vEnd.fromBufferAttribute( positionAttribute, b );
33713
33714				const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
33715
33716				if ( distSq > localThresholdSq ) continue;
33717
33718				interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
33719
33720				const distance = raycaster.ray.origin.distanceTo( interRay );
33721
33722				if ( distance < raycaster.near || distance > raycaster.far ) continue;
33723
33724				intersects.push( {
33725
33726					distance: distance,
33727					// What do we want? intersection point on the ray or on the segment??
33728					// point: raycaster.ray.at( distance ),
33729					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
33730					index: i,
33731					face: null,
33732					faceIndex: null,
33733					object: this
33734
33735				} );
33736
33737			}
33738
33739		} else {
33740
33741			const start = Math.max( 0, drawRange.start );
33742			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
33743
33744			for ( let i = start, l = end - 1; i < l; i += step ) {
33745
33746				vStart.fromBufferAttribute( positionAttribute, i );
33747				vEnd.fromBufferAttribute( positionAttribute, i + 1 );
33748
33749				const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
33750
33751				if ( distSq > localThresholdSq ) continue;
33752
33753				interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation
33754
33755				const distance = raycaster.ray.origin.distanceTo( interRay );
33756
33757				if ( distance < raycaster.near || distance > raycaster.far ) continue;
33758
33759				intersects.push( {
33760
33761					distance: distance,
33762					// What do we want? intersection point on the ray or on the segment??
33763					// point: raycaster.ray.at( distance ),
33764					point: interSegment.clone().applyMatrix4( this.matrixWorld ),
33765					index: i,
33766					face: null,
33767					faceIndex: null,
33768					object: this
33769
33770				} );
33771
33772			}
33773
33774		}
33775
33776	}
33777
33778	updateMorphTargets() {
33779
33780		const geometry = this.geometry;
33781
33782		const morphAttributes = geometry.morphAttributes;
33783		const keys = Object.keys( morphAttributes );
33784
33785		if ( keys.length > 0 ) {
33786
33787			const morphAttribute = morphAttributes[ keys[ 0 ] ];
33788
33789			if ( morphAttribute !== undefined ) {
33790
33791				this.morphTargetInfluences = [];
33792				this.morphTargetDictionary = {};
33793
33794				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
33795
33796					const name = morphAttribute[ m ].name || String( m );
33797
33798					this.morphTargetInfluences.push( 0 );
33799					this.morphTargetDictionary[ name ] = m;
33800
33801				}
33802
33803			}
33804
33805		}
33806
33807	}
33808
33809}
33810
33811const _start = /*@__PURE__*/ new Vector3();
33812const _end = /*@__PURE__*/ new Vector3();
33813
33814class LineSegments extends Line {
33815
33816	constructor( geometry, material ) {
33817
33818		super( geometry, material );
33819
33820		this.isLineSegments = true;
33821
33822		this.type = 'LineSegments';
33823
33824	}
33825
33826	computeLineDistances() {
33827
33828		const geometry = this.geometry;
33829
33830		// we assume non-indexed geometry
33831
33832		if ( geometry.index === null ) {
33833
33834			const positionAttribute = geometry.attributes.position;
33835			const lineDistances = [];
33836
33837			for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
33838
33839				_start.fromBufferAttribute( positionAttribute, i );
33840				_end.fromBufferAttribute( positionAttribute, i + 1 );
33841
33842				lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
33843				lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
33844
33845			}
33846
33847			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
33848
33849		} else {
33850
33851			console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
33852
33853		}
33854
33855		return this;
33856
33857	}
33858
33859}
33860
33861class LineLoop extends Line {
33862
33863	constructor( geometry, material ) {
33864
33865		super( geometry, material );
33866
33867		this.isLineLoop = true;
33868
33869		this.type = 'LineLoop';
33870
33871	}
33872
33873}
33874
33875class PointsMaterial extends Material {
33876
33877	constructor( parameters ) {
33878
33879		super();
33880
33881		this.isPointsMaterial = true;
33882
33883		this.type = 'PointsMaterial';
33884
33885		this.color = new Color( 0xffffff );
33886
33887		this.map = null;
33888
33889		this.alphaMap = null;
33890
33891		this.size = 1;
33892		this.sizeAttenuation = true;
33893
33894		this.fog = true;
33895
33896		this.setValues( parameters );
33897
33898	}
33899
33900	copy( source ) {
33901
33902		super.copy( source );
33903
33904		this.color.copy( source.color );
33905
33906		this.map = source.map;
33907
33908		this.alphaMap = source.alphaMap;
33909
33910		this.size = source.size;
33911		this.sizeAttenuation = source.sizeAttenuation;
33912
33913		this.fog = source.fog;
33914
33915		return this;
33916
33917	}
33918
33919}
33920
33921const _inverseMatrix = /*@__PURE__*/ new Matrix4();
33922const _ray = /*@__PURE__*/ new Ray();
33923const _sphere = /*@__PURE__*/ new Sphere();
33924const _position$2 = /*@__PURE__*/ new Vector3();
33925
33926class Points extends Object3D {
33927
33928	constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
33929
33930		super();
33931
33932		this.isPoints = true;
33933
33934		this.type = 'Points';
33935
33936		this.geometry = geometry;
33937		this.material = material;
33938
33939		this.updateMorphTargets();
33940
33941	}
33942
33943	copy( source, recursive ) {
33944
33945		super.copy( source, recursive );
33946
33947		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
33948		this.geometry = source.geometry;
33949
33950		return this;
33951
33952	}
33953
33954	raycast( raycaster, intersects ) {
33955
33956		const geometry = this.geometry;
33957		const matrixWorld = this.matrixWorld;
33958		const threshold = raycaster.params.Points.threshold;
33959		const drawRange = geometry.drawRange;
33960
33961		// Checking boundingSphere distance to ray
33962
33963		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
33964
33965		_sphere.copy( geometry.boundingSphere );
33966		_sphere.applyMatrix4( matrixWorld );
33967		_sphere.radius += threshold;
33968
33969		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
33970
33971		//
33972
33973		_inverseMatrix.copy( matrixWorld ).invert();
33974		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
33975
33976		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
33977		const localThresholdSq = localThreshold * localThreshold;
33978
33979		const index = geometry.index;
33980		const attributes = geometry.attributes;
33981		const positionAttribute = attributes.position;
33982
33983		if ( index !== null ) {
33984
33985			const start = Math.max( 0, drawRange.start );
33986			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
33987
33988			for ( let i = start, il = end; i < il; i ++ ) {
33989
33990				const a = index.getX( i );
33991
33992				_position$2.fromBufferAttribute( positionAttribute, a );
33993
33994				testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
33995
33996			}
33997
33998		} else {
33999
34000			const start = Math.max( 0, drawRange.start );
34001			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
34002
34003			for ( let i = start, l = end; i < l; i ++ ) {
34004
34005				_position$2.fromBufferAttribute( positionAttribute, i );
34006
34007				testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
34008
34009			}
34010
34011		}
34012
34013	}
34014
34015	updateMorphTargets() {
34016
34017		const geometry = this.geometry;
34018
34019		const morphAttributes = geometry.morphAttributes;
34020		const keys = Object.keys( morphAttributes );
34021
34022		if ( keys.length > 0 ) {
34023
34024			const morphAttribute = morphAttributes[ keys[ 0 ] ];
34025
34026			if ( morphAttribute !== undefined ) {
34027
34028				this.morphTargetInfluences = [];
34029				this.morphTargetDictionary = {};
34030
34031				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
34032
34033					const name = morphAttribute[ m ].name || String( m );
34034
34035					this.morphTargetInfluences.push( 0 );
34036					this.morphTargetDictionary[ name ] = m;
34037
34038				}
34039
34040			}
34041
34042		}
34043
34044	}
34045
34046}
34047
34048function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
34049
34050	const rayPointDistanceSq = _ray.distanceSqToPoint( point );
34051
34052	if ( rayPointDistanceSq < localThresholdSq ) {
34053
34054		const intersectPoint = new Vector3();
34055
34056		_ray.closestPointToPoint( point, intersectPoint );
34057		intersectPoint.applyMatrix4( matrixWorld );
34058
34059		const distance = raycaster.ray.origin.distanceTo( intersectPoint );
34060
34061		if ( distance < raycaster.near || distance > raycaster.far ) return;
34062
34063		intersects.push( {
34064
34065			distance: distance,
34066			distanceToRay: Math.sqrt( rayPointDistanceSq ),
34067			point: intersectPoint,
34068			index: index,
34069			face: null,
34070			object: object
34071
34072		} );
34073
34074	}
34075
34076}
34077
34078class VideoTexture extends Texture {
34079
34080	constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
34081
34082		super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
34083
34084		this.isVideoTexture = true;
34085
34086		this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
34087		this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
34088
34089		this.generateMipmaps = false;
34090
34091		const scope = this;
34092
34093		function updateVideo() {
34094
34095			scope.needsUpdate = true;
34096			video.requestVideoFrameCallback( updateVideo );
34097
34098		}
34099
34100		if ( 'requestVideoFrameCallback' in video ) {
34101
34102			video.requestVideoFrameCallback( updateVideo );
34103
34104		}
34105
34106	}
34107
34108	clone() {
34109
34110		return new this.constructor( this.image ).copy( this );
34111
34112	}
34113
34114	update() {
34115
34116		const video = this.image;
34117		const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
34118
34119		if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
34120
34121			this.needsUpdate = true;
34122
34123		}
34124
34125	}
34126
34127}
34128
34129class FramebufferTexture extends Texture {
34130
34131	constructor( width, height ) {
34132
34133		super( { width, height } );
34134
34135		this.isFramebufferTexture = true;
34136
34137		this.magFilter = NearestFilter;
34138		this.minFilter = NearestFilter;
34139
34140		this.generateMipmaps = false;
34141
34142		this.needsUpdate = true;
34143
34144	}
34145
34146}
34147
34148class CompressedTexture extends Texture {
34149
34150	constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) {
34151
34152		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
34153
34154		this.isCompressedTexture = true;
34155
34156		this.image = { width: width, height: height };
34157		this.mipmaps = mipmaps;
34158
34159		// no flipping for cube textures
34160		// (also flipping doesn't work for compressed textures )
34161
34162		this.flipY = false;
34163
34164		// can't generate mipmaps for compressed textures
34165		// mips must be embedded in DDS files
34166
34167		this.generateMipmaps = false;
34168
34169	}
34170
34171}
34172
34173class CompressedArrayTexture extends CompressedTexture {
34174
34175	constructor( mipmaps, width, height, depth, format, type ) {
34176
34177		super( mipmaps, width, height, format, type );
34178
34179		this.isCompressedArrayTexture = true;
34180		this.image.depth = depth;
34181		this.wrapR = ClampToEdgeWrapping;
34182
34183	}
34184
34185}
34186
34187class CompressedCubeTexture extends CompressedTexture {
34188
34189	constructor( images, format, type ) {
34190
34191		super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping );
34192
34193		this.isCompressedCubeTexture = true;
34194		this.isCubeTexture = true;
34195
34196		this.image = images;
34197
34198	}
34199
34200}
34201
34202class CanvasTexture extends Texture {
34203
34204	constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
34205
34206		super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
34207
34208		this.isCanvasTexture = true;
34209
34210		this.needsUpdate = true;
34211
34212	}
34213
34214}
34215
34216/**
34217 * Extensible curve object.
34218 *
34219 * Some common of curve methods:
34220 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
34221 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
34222 * .getPoints(), .getSpacedPoints()
34223 * .getLength()
34224 * .updateArcLengths()
34225 *
34226 * This following curves inherit from THREE.Curve:
34227 *
34228 * -- 2D curves --
34229 * THREE.ArcCurve
34230 * THREE.CubicBezierCurve
34231 * THREE.EllipseCurve
34232 * THREE.LineCurve
34233 * THREE.QuadraticBezierCurve
34234 * THREE.SplineCurve
34235 *
34236 * -- 3D curves --
34237 * THREE.CatmullRomCurve3
34238 * THREE.CubicBezierCurve3
34239 * THREE.LineCurve3
34240 * THREE.QuadraticBezierCurve3
34241 *
34242 * A series of curves can be represented as a THREE.CurvePath.
34243 *
34244 **/
34245
34246class Curve {
34247
34248	constructor() {
34249
34250		this.type = 'Curve';
34251
34252		this.arcLengthDivisions = 200;
34253
34254	}
34255
34256	// Virtual base class method to overwrite and implement in subclasses
34257	//	- t [0 .. 1]
34258
34259	getPoint( /* t, optionalTarget */ ) {
34260
34261		console.warn( 'THREE.Curve: .getPoint() not implemented.' );
34262		return null;
34263
34264	}
34265
34266	// Get point at relative position in curve according to arc length
34267	// - u [0 .. 1]
34268
34269	getPointAt( u, optionalTarget ) {
34270
34271		const t = this.getUtoTmapping( u );
34272		return this.getPoint( t, optionalTarget );
34273
34274	}
34275
34276	// Get sequence of points using getPoint( t )
34277
34278	getPoints( divisions = 5 ) {
34279
34280		const points = [];
34281
34282		for ( let d = 0; d <= divisions; d ++ ) {
34283
34284			points.push( this.getPoint( d / divisions ) );
34285
34286		}
34287
34288		return points;
34289
34290	}
34291
34292	// Get sequence of points using getPointAt( u )
34293
34294	getSpacedPoints( divisions = 5 ) {
34295
34296		const points = [];
34297
34298		for ( let d = 0; d <= divisions; d ++ ) {
34299
34300			points.push( this.getPointAt( d / divisions ) );
34301
34302		}
34303
34304		return points;
34305
34306	}
34307
34308	// Get total curve arc length
34309
34310	getLength() {
34311
34312		const lengths = this.getLengths();
34313		return lengths[ lengths.length - 1 ];
34314
34315	}
34316
34317	// Get list of cumulative segment lengths
34318
34319	getLengths( divisions = this.arcLengthDivisions ) {
34320
34321		if ( this.cacheArcLengths &&
34322			( this.cacheArcLengths.length === divisions + 1 ) &&
34323			! this.needsUpdate ) {
34324
34325			return this.cacheArcLengths;
34326
34327		}
34328
34329		this.needsUpdate = false;
vendor: 7,517 bytes, lines 34330-34721
34330
34331		const cache = [];
34332		let current, last = this.getPoint( 0 );
34333		let sum = 0;
34334
34335		cache.push( 0 );
34336
34337		for ( let p = 1; p <= divisions; p ++ ) {
34338
34339			current = this.getPoint( p / divisions );
34340			sum += current.distanceTo( last );
34341			cache.push( sum );
34342			last = current;
34343
34344		}
34345
34346		this.cacheArcLengths = cache;
34347
34348		return cache; // { sums: cache, sum: sum }; Sum is in the last element.
34349
34350	}
34351
34352	updateArcLengths() {
34353
34354		this.needsUpdate = true;
34355		this.getLengths();
34356
34357	}
34358
34359	// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
34360
34361	getUtoTmapping( u, distance ) {
34362
34363		const arcLengths = this.getLengths();
34364
34365		let i = 0;
34366		const il = arcLengths.length;
34367
34368		let targetArcLength; // The targeted u distance value to get
34369
34370		if ( distance ) {
34371
34372			targetArcLength = distance;
34373
34374		} else {
34375
34376			targetArcLength = u * arcLengths[ il - 1 ];
34377
34378		}
34379
34380		// binary search for the index with largest value smaller than target u distance
34381
34382		let low = 0, high = il - 1, comparison;
34383
34384		while ( low <= high ) {
34385
34386			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
34387
34388			comparison = arcLengths[ i ] - targetArcLength;
34389
34390			if ( comparison < 0 ) {
34391
34392				low = i + 1;
34393
34394			} else if ( comparison > 0 ) {
34395
34396				high = i - 1;
34397
34398			} else {
34399
34400				high = i;
34401				break;
34402
34403				// DONE
34404
34405			}
34406
34407		}
34408
34409		i = high;
34410
34411		if ( arcLengths[ i ] === targetArcLength ) {
34412
34413			return i / ( il - 1 );
34414
34415		}
34416
34417		// we could get finer grain at lengths, or use simple interpolation between two points
34418
34419		const lengthBefore = arcLengths[ i ];
34420		const lengthAfter = arcLengths[ i + 1 ];
34421
34422		const segmentLength = lengthAfter - lengthBefore;
34423
34424		// determine where we are between the 'before' and 'after' points
34425
34426		const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
34427
34428		// add that fractional amount to t
34429
34430		const t = ( i + segmentFraction ) / ( il - 1 );
34431
34432		return t;
34433
34434	}
34435
34436	// Returns a unit vector tangent at t
34437	// In case any sub curve does not implement its tangent derivation,
34438	// 2 points a small delta apart will be used to find its gradient
34439	// which seems to give a reasonable approximation
34440
34441	getTangent( t, optionalTarget ) {
34442
34443		const delta = 0.0001;
34444		let t1 = t - delta;
34445		let t2 = t + delta;
34446
34447		// Capping in case of danger
34448
34449		if ( t1 < 0 ) t1 = 0;
34450		if ( t2 > 1 ) t2 = 1;
34451
34452		const pt1 = this.getPoint( t1 );
34453		const pt2 = this.getPoint( t2 );
34454
34455		const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
34456
34457		tangent.copy( pt2 ).sub( pt1 ).normalize();
34458
34459		return tangent;
34460
34461	}
34462
34463	getTangentAt( u, optionalTarget ) {
34464
34465		const t = this.getUtoTmapping( u );
34466		return this.getTangent( t, optionalTarget );
34467
34468	}
34469
34470	computeFrenetFrames( segments, closed ) {
34471
34472		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
34473
34474		const normal = new Vector3();
34475
34476		const tangents = [];
34477		const normals = [];
34478		const binormals = [];
34479
34480		const vec = new Vector3();
34481		const mat = new Matrix4();
34482
34483		// compute the tangent vectors for each segment on the curve
34484
34485		for ( let i = 0; i <= segments; i ++ ) {
34486
34487			const u = i / segments;
34488
34489			tangents[ i ] = this.getTangentAt( u, new Vector3() );
34490
34491		}
34492
34493		// select an initial normal vector perpendicular to the first tangent vector,
34494		// and in the direction of the minimum tangent xyz component
34495
34496		normals[ 0 ] = new Vector3();
34497		binormals[ 0 ] = new Vector3();
34498		let min = Number.MAX_VALUE;
34499		const tx = Math.abs( tangents[ 0 ].x );
34500		const ty = Math.abs( tangents[ 0 ].y );
34501		const tz = Math.abs( tangents[ 0 ].z );
34502
34503		if ( tx <= min ) {
34504
34505			min = tx;
34506			normal.set( 1, 0, 0 );
34507
34508		}
34509
34510		if ( ty <= min ) {
34511
34512			min = ty;
34513			normal.set( 0, 1, 0 );
34514
34515		}
34516
34517		if ( tz <= min ) {
34518
34519			normal.set( 0, 0, 1 );
34520
34521		}
34522
34523		vec.crossVectors( tangents[ 0 ], normal ).normalize();
34524
34525		normals[ 0 ].crossVectors( tangents[ 0 ], vec );
34526		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
34527
34528
34529		// compute the slowly-varying normal and binormal vectors for each segment on the curve
34530
34531		for ( let i = 1; i <= segments; i ++ ) {
34532
34533			normals[ i ] = normals[ i - 1 ].clone();
34534
34535			binormals[ i ] = binormals[ i - 1 ].clone();
34536
34537			vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
34538
34539			if ( vec.length() > Number.EPSILON ) {
34540
34541				vec.normalize();
34542
34543				const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
34544
34545				normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
34546
34547			}
34548
34549			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
34550
34551		}
34552
34553		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
34554
34555		if ( closed === true ) {
34556
34557			let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
34558			theta /= segments;
34559
34560			if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
34561
34562				theta = - theta;
34563
34564			}
34565
34566			for ( let i = 1; i <= segments; i ++ ) {
34567
34568				// twist a little...
34569				normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
34570				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
34571
34572			}
34573
34574		}
34575
34576		return {
34577			tangents: tangents,
34578			normals: normals,
34579			binormals: binormals
34580		};
34581
34582	}
34583
34584	clone() {
34585
34586		return new this.constructor().copy( this );
34587
34588	}
34589
34590	copy( source ) {
34591
34592		this.arcLengthDivisions = source.arcLengthDivisions;
34593
34594		return this;
34595
34596	}
34597
34598	toJSON() {
34599
34600		const data = {
34601			metadata: {
34602				version: 4.6,
34603				type: 'Curve',
34604				generator: 'Curve.toJSON'
34605			}
34606		};
34607
34608		data.arcLengthDivisions = this.arcLengthDivisions;
34609		data.type = this.type;
34610
34611		return data;
34612
34613	}
34614
34615	fromJSON( json ) {
34616
34617		this.arcLengthDivisions = json.arcLengthDivisions;
34618
34619		return this;
34620
34621	}
34622
34623}
34624
34625class EllipseCurve extends Curve {
34626
34627	constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) {
34628
34629		super();
34630
34631		this.isEllipseCurve = true;
34632
34633		this.type = 'EllipseCurve';
34634
34635		this.aX = aX;
34636		this.aY = aY;
34637
34638		this.xRadius = xRadius;
34639		this.yRadius = yRadius;
34640
34641		this.aStartAngle = aStartAngle;
34642		this.aEndAngle = aEndAngle;
34643
34644		this.aClockwise = aClockwise;
34645
34646		this.aRotation = aRotation;
34647
34648	}
34649
34650	getPoint( t, optionalTarget = new Vector2() ) {
34651
34652		const point = optionalTarget;
34653
34654		const twoPi = Math.PI * 2;
34655		let deltaAngle = this.aEndAngle - this.aStartAngle;
34656		const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
34657
34658		// ensures that deltaAngle is 0 .. 2 PI
34659		while ( deltaAngle < 0 ) deltaAngle += twoPi;
34660		while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
34661
34662		if ( deltaAngle < Number.EPSILON ) {
34663
34664			if ( samePoints ) {
34665
34666				deltaAngle = 0;
34667
34668			} else {
34669
34670				deltaAngle = twoPi;
34671
34672			}
34673
34674		}
34675
34676		if ( this.aClockwise === true && ! samePoints ) {
34677
34678			if ( deltaAngle === twoPi ) {
34679
34680				deltaAngle = - twoPi;
34681
34682			} else {
34683
34684				deltaAngle = deltaAngle - twoPi;
34685
34686			}
34687
34688		}
34689
34690		const angle = this.aStartAngle + t * deltaAngle;
34691		let x = this.aX + this.xRadius * Math.cos( angle );
34692		let y = this.aY + this.yRadius * Math.sin( angle );
34693
34694		if ( this.aRotation !== 0 ) {
34695
34696			const cos = Math.cos( this.aRotation );
34697			const sin = Math.sin( this.aRotation );
34698
34699			const tx = x - this.aX;
34700			const ty = y - this.aY;
34701
34702			// Rotate the point about the center of the ellipse.
34703			x = tx * cos - ty * sin + this.aX;
34704			y = tx * sin + ty * cos + this.aY;
34705
34706		}
34707
34708		return point.set( x, y );
34709
34710	}
34711
34712	copy( source ) {
34713
34714		super.copy( source );
34715
34716		this.aX = source.aX;
34717		this.aY = source.aY;
34718
34719		this.xRadius = source.xRadius;
34720		this.yRadius = source.yRadius;
34721
vendor: 29,619 bytes, lines 34722-36404
34722		this.aStartAngle = source.aStartAngle;
34723		this.aEndAngle = source.aEndAngle;
34724
34725		this.aClockwise = source.aClockwise;
34726
34727		this.aRotation = source.aRotation;
34728
34729		return this;
34730
34731	}
34732
34733	toJSON() {
34734
34735		const data = super.toJSON();
34736
34737		data.aX = this.aX;
34738		data.aY = this.aY;
34739
34740		data.xRadius = this.xRadius;
34741		data.yRadius = this.yRadius;
34742
34743		data.aStartAngle = this.aStartAngle;
34744		data.aEndAngle = this.aEndAngle;
34745
34746		data.aClockwise = this.aClockwise;
34747
34748		data.aRotation = this.aRotation;
34749
34750		return data;
34751
34752	}
34753
34754	fromJSON( json ) {
34755
34756		super.fromJSON( json );
34757
34758		this.aX = json.aX;
34759		this.aY = json.aY;
34760
34761		this.xRadius = json.xRadius;
34762		this.yRadius = json.yRadius;
34763
34764		this.aStartAngle = json.aStartAngle;
34765		this.aEndAngle = json.aEndAngle;
34766
34767		this.aClockwise = json.aClockwise;
34768
34769		this.aRotation = json.aRotation;
34770
34771		return this;
34772
34773	}
34774
34775}
34776
34777class ArcCurve extends EllipseCurve {
34778
34779	constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
34780
34781		super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
34782
34783		this.isArcCurve = true;
34784
34785		this.type = 'ArcCurve';
34786
34787	}
34788
34789}
34790
34791/**
34792 * Centripetal CatmullRom Curve - which is useful for avoiding
34793 * cusps and self-intersections in non-uniform catmull rom curves.
34794 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
34795 *
34796 * curve.type accepts centripetal(default), chordal and catmullrom
34797 * curve.tension is used for catmullrom which defaults to 0.5
34798 */
34799
34800
34801/*
34802Based on an optimized c++ solution in
34803 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
34804 - http://ideone.com/NoEbVM
34805
34806This CubicPoly class could be used for reusing some variables and calculations,
34807but for three.js curve use, it could be possible inlined and flatten into a single function call
34808which can be placed in CurveUtils.
34809*/
34810
34811function CubicPoly() {
34812
34813	let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
34814
34815	/*
34816	 * Compute coefficients for a cubic polynomial
34817	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
34818	 * such that
34819	 *   p(0) = x0, p(1) = x1
34820	 *  and
34821	 *   p'(0) = t0, p'(1) = t1.
34822	 */
34823	function init( x0, x1, t0, t1 ) {
34824
34825		c0 = x0;
34826		c1 = t0;
34827		c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
34828		c3 = 2 * x0 - 2 * x1 + t0 + t1;
34829
34830	}
34831
34832	return {
34833
34834		initCatmullRom: function ( x0, x1, x2, x3, tension ) {
34835
34836			init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
34837
34838		},
34839
34840		initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
34841
34842			// compute tangents when parameterized in [t1,t2]
34843			let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
34844			let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
34845
34846			// rescale tangents for parametrization in [0,1]
34847			t1 *= dt1;
34848			t2 *= dt1;
34849
34850			init( x1, x2, t1, t2 );
34851
34852		},
34853
34854		calc: function ( t ) {
34855
34856			const t2 = t * t;
34857			const t3 = t2 * t;
34858			return c0 + c1 * t + c2 * t2 + c3 * t3;
34859
34860		}
34861
34862	};
34863
34864}
34865
34866//
34867
34868const tmp = /*@__PURE__*/ new Vector3();
34869const px = /*@__PURE__*/ new CubicPoly();
34870const py = /*@__PURE__*/ new CubicPoly();
34871const pz = /*@__PURE__*/ new CubicPoly();
34872
34873class CatmullRomCurve3 extends Curve {
34874
34875	constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
34876
34877		super();
34878
34879		this.isCatmullRomCurve3 = true;
34880
34881		this.type = 'CatmullRomCurve3';
34882
34883		this.points = points;
34884		this.closed = closed;
34885		this.curveType = curveType;
34886		this.tension = tension;
34887
34888	}
34889
34890	getPoint( t, optionalTarget = new Vector3() ) {
34891
34892		const point = optionalTarget;
34893
34894		const points = this.points;
34895		const l = points.length;
34896
34897		const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
34898		let intPoint = Math.floor( p );
34899		let weight = p - intPoint;
34900
34901		if ( this.closed ) {
34902
34903			intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
34904
34905		} else if ( weight === 0 && intPoint === l - 1 ) {
34906
34907			intPoint = l - 2;
34908			weight = 1;
34909
34910		}
34911
34912		let p0, p3; // 4 points (p1 & p2 defined below)
34913
34914		if ( this.closed || intPoint > 0 ) {
34915
34916			p0 = points[ ( intPoint - 1 ) % l ];
34917
34918		} else {
34919
34920			// extrapolate first point
34921			tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
34922			p0 = tmp;
34923
34924		}
34925
34926		const p1 = points[ intPoint % l ];
34927		const p2 = points[ ( intPoint + 1 ) % l ];
34928
34929		if ( this.closed || intPoint + 2 < l ) {
34930
34931			p3 = points[ ( intPoint + 2 ) % l ];
34932
34933		} else {
34934
34935			// extrapolate last point
34936			tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
34937			p3 = tmp;
34938
34939		}
34940
34941		if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
34942
34943			// init Centripetal / Chordal Catmull-Rom
34944			const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
34945			let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
34946			let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
34947			let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
34948
34949			// safety check for repeated points
34950			if ( dt1 < 1e-4 ) dt1 = 1.0;
34951			if ( dt0 < 1e-4 ) dt0 = dt1;
34952			if ( dt2 < 1e-4 ) dt2 = dt1;
34953
34954			px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
34955			py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
34956			pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
34957
34958		} else if ( this.curveType === 'catmullrom' ) {
34959
34960			px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
34961			py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
34962			pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
34963
34964		}
34965
34966		point.set(
34967			px.calc( weight ),
34968			py.calc( weight ),
34969			pz.calc( weight )
34970		);
34971
34972		return point;
34973
34974	}
34975
34976	copy( source ) {
34977
34978		super.copy( source );
34979
34980		this.points = [];
34981
34982		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
34983
34984			const point = source.points[ i ];
34985
34986			this.points.push( point.clone() );
34987
34988		}
34989
34990		this.closed = source.closed;
34991		this.curveType = source.curveType;
34992		this.tension = source.tension;
34993
34994		return this;
34995
34996	}
34997
34998	toJSON() {
34999
35000		const data = super.toJSON();
35001
35002		data.points = [];
35003
35004		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
35005
35006			const point = this.points[ i ];
35007			data.points.push( point.toArray() );
35008
35009		}
35010
35011		data.closed = this.closed;
35012		data.curveType = this.curveType;
35013		data.tension = this.tension;
35014
35015		return data;
35016
35017	}
35018
35019	fromJSON( json ) {
35020
35021		super.fromJSON( json );
35022
35023		this.points = [];
35024
35025		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
35026
35027			const point = json.points[ i ];
35028			this.points.push( new Vector3().fromArray( point ) );
35029
35030		}
35031
35032		this.closed = json.closed;
35033		this.curveType = json.curveType;
35034		this.tension = json.tension;
35035
35036		return this;
35037
35038	}
35039
35040}
35041
35042/**
35043 * Bezier Curves formulas obtained from
35044 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
35045 */
35046
35047function CatmullRom( t, p0, p1, p2, p3 ) {
35048
35049	const v0 = ( p2 - p0 ) * 0.5;
35050	const v1 = ( p3 - p1 ) * 0.5;
35051	const t2 = t * t;
35052	const t3 = t * t2;
35053	return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
35054
35055}
35056
35057//
35058
35059function QuadraticBezierP0( t, p ) {
35060
35061	const k = 1 - t;
35062	return k * k * p;
35063
35064}
35065
35066function QuadraticBezierP1( t, p ) {
35067
35068	return 2 * ( 1 - t ) * t * p;
35069
35070}
35071
35072function QuadraticBezierP2( t, p ) {
35073
35074	return t * t * p;
35075
35076}
35077
35078function QuadraticBezier( t, p0, p1, p2 ) {
35079
35080	return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
35081		QuadraticBezierP2( t, p2 );
35082
35083}
35084
35085//
35086
35087function CubicBezierP0( t, p ) {
35088
35089	const k = 1 - t;
35090	return k * k * k * p;
35091
35092}
35093
35094function CubicBezierP1( t, p ) {
35095
35096	const k = 1 - t;
35097	return 3 * k * k * t * p;
35098
35099}
35100
35101function CubicBezierP2( t, p ) {
35102
35103	return 3 * ( 1 - t ) * t * t * p;
35104
35105}
35106
35107function CubicBezierP3( t, p ) {
35108
35109	return t * t * t * p;
35110
35111}
35112
35113function CubicBezier( t, p0, p1, p2, p3 ) {
35114
35115	return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
35116		CubicBezierP3( t, p3 );
35117
35118}
35119
35120class CubicBezierCurve extends Curve {
35121
35122	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
35123
35124		super();
35125
35126		this.isCubicBezierCurve = true;
35127
35128		this.type = 'CubicBezierCurve';
35129
35130		this.v0 = v0;
35131		this.v1 = v1;
35132		this.v2 = v2;
35133		this.v3 = v3;
35134
35135	}
35136
35137	getPoint( t, optionalTarget = new Vector2() ) {
35138
35139		const point = optionalTarget;
35140
35141		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35142
35143		point.set(
35144			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
35145			CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
35146		);
35147
35148		return point;
35149
35150	}
35151
35152	copy( source ) {
35153
35154		super.copy( source );
35155
35156		this.v0.copy( source.v0 );
35157		this.v1.copy( source.v1 );
35158		this.v2.copy( source.v2 );
35159		this.v3.copy( source.v3 );
35160
35161		return this;
35162
35163	}
35164
35165	toJSON() {
35166
35167		const data = super.toJSON();
35168
35169		data.v0 = this.v0.toArray();
35170		data.v1 = this.v1.toArray();
35171		data.v2 = this.v2.toArray();
35172		data.v3 = this.v3.toArray();
35173
35174		return data;
35175
35176	}
35177
35178	fromJSON( json ) {
35179
35180		super.fromJSON( json );
35181
35182		this.v0.fromArray( json.v0 );
35183		this.v1.fromArray( json.v1 );
35184		this.v2.fromArray( json.v2 );
35185		this.v3.fromArray( json.v3 );
35186
35187		return this;
35188
35189	}
35190
35191}
35192
35193class CubicBezierCurve3 extends Curve {
35194
35195	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
35196
35197		super();
35198
35199		this.isCubicBezierCurve3 = true;
35200
35201		this.type = 'CubicBezierCurve3';
35202
35203		this.v0 = v0;
35204		this.v1 = v1;
35205		this.v2 = v2;
35206		this.v3 = v3;
35207
35208	}
35209
35210	getPoint( t, optionalTarget = new Vector3() ) {
35211
35212		const point = optionalTarget;
35213
35214		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35215
35216		point.set(
35217			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
35218			CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
35219			CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
35220		);
35221
35222		return point;
35223
35224	}
35225
35226	copy( source ) {
35227
35228		super.copy( source );
35229
35230		this.v0.copy( source.v0 );
35231		this.v1.copy( source.v1 );
35232		this.v2.copy( source.v2 );
35233		this.v3.copy( source.v3 );
35234
35235		return this;
35236
35237	}
35238
35239	toJSON() {
35240
35241		const data = super.toJSON();
35242
35243		data.v0 = this.v0.toArray();
35244		data.v1 = this.v1.toArray();
35245		data.v2 = this.v2.toArray();
35246		data.v3 = this.v3.toArray();
35247
35248		return data;
35249
35250	}
35251
35252	fromJSON( json ) {
35253
35254		super.fromJSON( json );
35255
35256		this.v0.fromArray( json.v0 );
35257		this.v1.fromArray( json.v1 );
35258		this.v2.fromArray( json.v2 );
35259		this.v3.fromArray( json.v3 );
35260
35261		return this;
35262
35263	}
35264
35265}
35266
35267class LineCurve extends Curve {
35268
35269	constructor( v1 = new Vector2(), v2 = new Vector2() ) {
35270
35271		super();
35272
35273		this.isLineCurve = true;
35274
35275		this.type = 'LineCurve';
35276
35277		this.v1 = v1;
35278		this.v2 = v2;
35279
35280	}
35281
35282	getPoint( t, optionalTarget = new Vector2() ) {
35283
35284		const point = optionalTarget;
35285
35286		if ( t === 1 ) {
35287
35288			point.copy( this.v2 );
35289
35290		} else {
35291
35292			point.copy( this.v2 ).sub( this.v1 );
35293			point.multiplyScalar( t ).add( this.v1 );
35294
35295		}
35296
35297		return point;
35298
35299	}
35300
35301	// Line curve is linear, so we can overwrite default getPointAt
35302	getPointAt( u, optionalTarget ) {
35303
35304		return this.getPoint( u, optionalTarget );
35305
35306	}
35307
35308	getTangent( t, optionalTarget = new Vector2() ) {
35309
35310		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
35311
35312	}
35313
35314	getTangentAt( u, optionalTarget ) {
35315
35316		return this.getTangent( u, optionalTarget );
35317
35318	}
35319
35320	copy( source ) {
35321
35322		super.copy( source );
35323
35324		this.v1.copy( source.v1 );
35325		this.v2.copy( source.v2 );
35326
35327		return this;
35328
35329	}
35330
35331	toJSON() {
35332
35333		const data = super.toJSON();
35334
35335		data.v1 = this.v1.toArray();
35336		data.v2 = this.v2.toArray();
35337
35338		return data;
35339
35340	}
35341
35342	fromJSON( json ) {
35343
35344		super.fromJSON( json );
35345
35346		this.v1.fromArray( json.v1 );
35347		this.v2.fromArray( json.v2 );
35348
35349		return this;
35350
35351	}
35352
35353}
35354
35355class LineCurve3 extends Curve {
35356
35357	constructor( v1 = new Vector3(), v2 = new Vector3() ) {
35358
35359		super();
35360
35361		this.isLineCurve3 = true;
35362
35363		this.type = 'LineCurve3';
35364
35365		this.v1 = v1;
35366		this.v2 = v2;
35367
35368	}
35369
35370	getPoint( t, optionalTarget = new Vector3() ) {
35371
35372		const point = optionalTarget;
35373
35374		if ( t === 1 ) {
35375
35376			point.copy( this.v2 );
35377
35378		} else {
35379
35380			point.copy( this.v2 ).sub( this.v1 );
35381			point.multiplyScalar( t ).add( this.v1 );
35382
35383		}
35384
35385		return point;
35386
35387	}
35388
35389	// Line curve is linear, so we can overwrite default getPointAt
35390	getPointAt( u, optionalTarget ) {
35391
35392		return this.getPoint( u, optionalTarget );
35393
35394	}
35395
35396	getTangent( t, optionalTarget = new Vector3() ) {
35397
35398		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
35399
35400	}
35401
35402	getTangentAt( u, optionalTarget ) {
35403
35404		return this.getTangent( u, optionalTarget );
35405
35406	}
35407
35408	copy( source ) {
35409
35410		super.copy( source );
35411
35412		this.v1.copy( source.v1 );
35413		this.v2.copy( source.v2 );
35414
35415		return this;
35416
35417	}
35418
35419	toJSON() {
35420
35421		const data = super.toJSON();
35422
35423		data.v1 = this.v1.toArray();
35424		data.v2 = this.v2.toArray();
35425
35426		return data;
35427
35428	}
35429
35430	fromJSON( json ) {
35431
35432		super.fromJSON( json );
35433
35434		this.v1.fromArray( json.v1 );
35435		this.v2.fromArray( json.v2 );
35436
35437		return this;
35438
35439	}
35440
35441}
35442
35443class QuadraticBezierCurve extends Curve {
35444
35445	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
35446
35447		super();
35448
35449		this.isQuadraticBezierCurve = true;
35450
35451		this.type = 'QuadraticBezierCurve';
35452
35453		this.v0 = v0;
35454		this.v1 = v1;
35455		this.v2 = v2;
35456
35457	}
35458
35459	getPoint( t, optionalTarget = new Vector2() ) {
35460
35461		const point = optionalTarget;
35462
35463		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
35464
35465		point.set(
35466			QuadraticBezier( t, v0.x, v1.x, v2.x ),
35467			QuadraticBezier( t, v0.y, v1.y, v2.y )
35468		);
35469
35470		return point;
35471
35472	}
35473
35474	copy( source ) {
35475
35476		super.copy( source );
35477
35478		this.v0.copy( source.v0 );
35479		this.v1.copy( source.v1 );
35480		this.v2.copy( source.v2 );
35481
35482		return this;
35483
35484	}
35485
35486	toJSON() {
35487
35488		const data = super.toJSON();
35489
35490		data.v0 = this.v0.toArray();
35491		data.v1 = this.v1.toArray();
35492		data.v2 = this.v2.toArray();
35493
35494		return data;
35495
35496	}
35497
35498	fromJSON( json ) {
35499
35500		super.fromJSON( json );
35501
35502		this.v0.fromArray( json.v0 );
35503		this.v1.fromArray( json.v1 );
35504		this.v2.fromArray( json.v2 );
35505
35506		return this;
35507
35508	}
35509
35510}
35511
35512class QuadraticBezierCurve3 extends Curve {
35513
35514	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
35515
35516		super();
35517
35518		this.isQuadraticBezierCurve3 = true;
35519
35520		this.type = 'QuadraticBezierCurve3';
35521
35522		this.v0 = v0;
35523		this.v1 = v1;
35524		this.v2 = v2;
35525
35526	}
35527
35528	getPoint( t, optionalTarget = new Vector3() ) {
35529
35530		const point = optionalTarget;
35531
35532		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
35533
35534		point.set(
35535			QuadraticBezier( t, v0.x, v1.x, v2.x ),
35536			QuadraticBezier( t, v0.y, v1.y, v2.y ),
35537			QuadraticBezier( t, v0.z, v1.z, v2.z )
35538		);
35539
35540		return point;
35541
35542	}
35543
35544	copy( source ) {
35545
35546		super.copy( source );
35547
35548		this.v0.copy( source.v0 );
35549		this.v1.copy( source.v1 );
35550		this.v2.copy( source.v2 );
35551
35552		return this;
35553
35554	}
35555
35556	toJSON() {
35557
35558		const data = super.toJSON();
35559
35560		data.v0 = this.v0.toArray();
35561		data.v1 = this.v1.toArray();
35562		data.v2 = this.v2.toArray();
35563
35564		return data;
35565
35566	}
35567
35568	fromJSON( json ) {
35569
35570		super.fromJSON( json );
35571
35572		this.v0.fromArray( json.v0 );
35573		this.v1.fromArray( json.v1 );
35574		this.v2.fromArray( json.v2 );
35575
35576		return this;
35577
35578	}
35579
35580}
35581
35582class SplineCurve extends Curve {
35583
35584	constructor( points = [] ) {
35585
35586		super();
35587
35588		this.isSplineCurve = true;
35589
35590		this.type = 'SplineCurve';
35591
35592		this.points = points;
35593
35594	}
35595
35596	getPoint( t, optionalTarget = new Vector2() ) {
35597
35598		const point = optionalTarget;
35599
35600		const points = this.points;
35601		const p = ( points.length - 1 ) * t;
35602
35603		const intPoint = Math.floor( p );
35604		const weight = p - intPoint;
35605
35606		const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
35607		const p1 = points[ intPoint ];
35608		const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
35609		const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
35610
35611		point.set(
35612			CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
35613			CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
35614		);
35615
35616		return point;
35617
35618	}
35619
35620	copy( source ) {
35621
35622		super.copy( source );
35623
35624		this.points = [];
35625
35626		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
35627
35628			const point = source.points[ i ];
35629
35630			this.points.push( point.clone() );
35631
35632		}
35633
35634		return this;
35635
35636	}
35637
35638	toJSON() {
35639
35640		const data = super.toJSON();
35641
35642		data.points = [];
35643
35644		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
35645
35646			const point = this.points[ i ];
35647			data.points.push( point.toArray() );
35648
35649		}
35650
35651		return data;
35652
35653	}
35654
35655	fromJSON( json ) {
35656
35657		super.fromJSON( json );
35658
35659		this.points = [];
35660
35661		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
35662
35663			const point = json.points[ i ];
35664			this.points.push( new Vector2().fromArray( point ) );
35665
35666		}
35667
35668		return this;
35669
35670	}
35671
35672}
35673
35674var Curves = /*#__PURE__*/Object.freeze({
35675	__proto__: null,
35676	ArcCurve: ArcCurve,
35677	CatmullRomCurve3: CatmullRomCurve3,
35678	CubicBezierCurve: CubicBezierCurve,
35679	CubicBezierCurve3: CubicBezierCurve3,
35680	EllipseCurve: EllipseCurve,
35681	LineCurve: LineCurve,
35682	LineCurve3: LineCurve3,
35683	QuadraticBezierCurve: QuadraticBezierCurve,
35684	QuadraticBezierCurve3: QuadraticBezierCurve3,
35685	SplineCurve: SplineCurve
35686});
35687
35688/**************************************************************
35689 *	Curved Path - a curve path is simply a array of connected
35690 *  curves, but retains the api of a curve
35691 **************************************************************/
35692
35693class CurvePath extends Curve {
35694
35695	constructor() {
35696
35697		super();
35698
35699		this.type = 'CurvePath';
35700
35701		this.curves = [];
35702		this.autoClose = false; // Automatically closes the path
35703
35704	}
35705
35706	add( curve ) {
35707
35708		this.curves.push( curve );
35709
35710	}
35711
35712	closePath() {
35713
35714		// Add a line curve if start and end of lines are not connected
35715		const startPoint = this.curves[ 0 ].getPoint( 0 );
35716		const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
35717
35718		if ( ! startPoint.equals( endPoint ) ) {
35719
35720			const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3';
35721			this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) );
35722
35723		}
35724
35725		return this;
35726
35727	}
35728
35729	// To get accurate point with reference to
35730	// entire path distance at time t,
35731	// following has to be done:
35732
35733	// 1. Length of each sub path have to be known
35734	// 2. Locate and identify type of curve
35735	// 3. Get t for the curve
35736	// 4. Return curve.getPointAt(t')
35737
35738	getPoint( t, optionalTarget ) {
35739
35740		const d = t * this.getLength();
35741		const curveLengths = this.getCurveLengths();
35742		let i = 0;
35743
35744		// To think about boundaries points.
35745
35746		while ( i < curveLengths.length ) {
35747
35748			if ( curveLengths[ i ] >= d ) {
35749
35750				const diff = curveLengths[ i ] - d;
35751				const curve = this.curves[ i ];
35752
35753				const segmentLength = curve.getLength();
35754				const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
35755
35756				return curve.getPointAt( u, optionalTarget );
35757
35758			}
35759
35760			i ++;
35761
35762		}
35763
35764		return null;
35765
35766		// loop where sum != 0, sum > d , sum+1 <d
35767
35768	}
35769
35770	// We cannot use the default THREE.Curve getPoint() with getLength() because in
35771	// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
35772	// getPoint() depends on getLength
35773
35774	getLength() {
35775
35776		const lens = this.getCurveLengths();
35777		return lens[ lens.length - 1 ];
35778
35779	}
35780
35781	// cacheLengths must be recalculated.
35782	updateArcLengths() {
35783
35784		this.needsUpdate = true;
35785		this.cacheLengths = null;
35786		this.getCurveLengths();
35787
35788	}
35789
35790	// Compute lengths and cache them
35791	// We cannot overwrite getLengths() because UtoT mapping uses it.
35792
35793	getCurveLengths() {
35794
35795		// We use cache values if curves and cache array are same length
35796
35797		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
35798
35799			return this.cacheLengths;
35800
35801		}
35802
35803		// Get length of sub-curve
35804		// Push sums into cached array
35805
35806		const lengths = [];
35807		let sums = 0;
35808
35809		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
35810
35811			sums += this.curves[ i ].getLength();
35812			lengths.push( sums );
35813
35814		}
35815
35816		this.cacheLengths = lengths;
35817
35818		return lengths;
35819
35820	}
35821
35822	getSpacedPoints( divisions = 40 ) {
35823
35824		const points = [];
35825
35826		for ( let i = 0; i <= divisions; i ++ ) {
35827
35828			points.push( this.getPoint( i / divisions ) );
35829
35830		}
35831
35832		if ( this.autoClose ) {
35833
35834			points.push( points[ 0 ] );
35835
35836		}
35837
35838		return points;
35839
35840	}
35841
35842	getPoints( divisions = 12 ) {
35843
35844		const points = [];
35845		let last;
35846
35847		for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
35848
35849			const curve = curves[ i ];
35850			const resolution = curve.isEllipseCurve ? divisions * 2
35851				: ( curve.isLineCurve || curve.isLineCurve3 ) ? 1
35852					: curve.isSplineCurve ? divisions * curve.points.length
35853						: divisions;
35854
35855			const pts = curve.getPoints( resolution );
35856
35857			for ( let j = 0; j < pts.length; j ++ ) {
35858
35859				const point = pts[ j ];
35860
35861				if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
35862
35863				points.push( point );
35864				last = point;
35865
35866			}
35867
35868		}
35869
35870		if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
35871
35872			points.push( points[ 0 ] );
35873
35874		}
35875
35876		return points;
35877
35878	}
35879
35880	copy( source ) {
35881
35882		super.copy( source );
35883
35884		this.curves = [];
35885
35886		for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
35887
35888			const curve = source.curves[ i ];
35889
35890			this.curves.push( curve.clone() );
35891
35892		}
35893
35894		this.autoClose = source.autoClose;
35895
35896		return this;
35897
35898	}
35899
35900	toJSON() {
35901
35902		const data = super.toJSON();
35903
35904		data.autoClose = this.autoClose;
35905		data.curves = [];
35906
35907		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
35908
35909			const curve = this.curves[ i ];
35910			data.curves.push( curve.toJSON() );
35911
35912		}
35913
35914		return data;
35915
35916	}
35917
35918	fromJSON( json ) {
35919
35920		super.fromJSON( json );
35921
35922		this.autoClose = json.autoClose;
35923		this.curves = [];
35924
35925		for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
35926
35927			const curve = json.curves[ i ];
35928			this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
35929
35930		}
35931
35932		return this;
35933
35934	}
35935
35936}
35937
35938class Path extends CurvePath {
35939
35940	constructor( points ) {
35941
35942		super();
35943
35944		this.type = 'Path';
35945
35946		this.currentPoint = new Vector2();
35947
35948		if ( points ) {
35949
35950			this.setFromPoints( points );
35951
35952		}
35953
35954	}
35955
35956	setFromPoints( points ) {
35957
35958		this.moveTo( points[ 0 ].x, points[ 0 ].y );
35959
35960		for ( let i = 1, l = points.length; i < l; i ++ ) {
35961
35962			this.lineTo( points[ i ].x, points[ i ].y );
35963
35964		}
35965
35966		return this;
35967
35968	}
35969
35970	moveTo( x, y ) {
35971
35972		this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
35973
35974		return this;
35975
35976	}
35977
35978	lineTo( x, y ) {
35979
35980		const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
35981		this.curves.push( curve );
35982
35983		this.currentPoint.set( x, y );
35984
35985		return this;
35986
35987	}
35988
35989	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
35990
35991		const curve = new QuadraticBezierCurve(
35992			this.currentPoint.clone(),
35993			new Vector2( aCPx, aCPy ),
35994			new Vector2( aX, aY )
35995		);
35996
35997		this.curves.push( curve );
35998
35999		this.currentPoint.set( aX, aY );
36000
36001		return this;
36002
36003	}
36004
36005	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
36006
36007		const curve = new CubicBezierCurve(
36008			this.currentPoint.clone(),
36009			new Vector2( aCP1x, aCP1y ),
36010			new Vector2( aCP2x, aCP2y ),
36011			new Vector2( aX, aY )
36012		);
36013
36014		this.curves.push( curve );
36015
36016		this.currentPoint.set( aX, aY );
36017
36018		return this;
36019
36020	}
36021
36022	splineThru( pts /*Array of Vector*/ ) {
36023
36024		const npts = [ this.currentPoint.clone() ].concat( pts );
36025
36026		const curve = new SplineCurve( npts );
36027		this.curves.push( curve );
36028
36029		this.currentPoint.copy( pts[ pts.length - 1 ] );
36030
36031		return this;
36032
36033	}
36034
36035	arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36036
36037		const x0 = this.currentPoint.x;
36038		const y0 = this.currentPoint.y;
36039
36040		this.absarc( aX + x0, aY + y0, aRadius,
36041			aStartAngle, aEndAngle, aClockwise );
36042
36043		return this;
36044
36045	}
36046
36047	absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36048
36049		this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
36050
36051		return this;
36052
36053	}
36054
36055	ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36056
36057		const x0 = this.currentPoint.x;
36058		const y0 = this.currentPoint.y;
36059
36060		this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36061
36062		return this;
36063
36064	}
36065
36066	absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36067
36068		const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36069
36070		if ( this.curves.length > 0 ) {
36071
36072			// if a previous curve is present, attempt to join
36073			const firstPoint = curve.getPoint( 0 );
36074
36075			if ( ! firstPoint.equals( this.currentPoint ) ) {
36076
36077				this.lineTo( firstPoint.x, firstPoint.y );
36078
36079			}
36080
36081		}
36082
36083		this.curves.push( curve );
36084
36085		const lastPoint = curve.getPoint( 1 );
36086		this.currentPoint.copy( lastPoint );
36087
36088		return this;
36089
36090	}
36091
36092	copy( source ) {
36093
36094		super.copy( source );
36095
36096		this.currentPoint.copy( source.currentPoint );
36097
36098		return this;
36099
36100	}
36101
36102	toJSON() {
36103
36104		const data = super.toJSON();
36105
36106		data.currentPoint = this.currentPoint.toArray();
36107
36108		return data;
36109
36110	}
36111
36112	fromJSON( json ) {
36113
36114		super.fromJSON( json );
36115
36116		this.currentPoint.fromArray( json.currentPoint );
36117
36118		return this;
36119
36120	}
36121
36122}
36123
36124class LatheGeometry extends BufferGeometry {
36125
36126	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 ) {
36127
36128		super();
36129
36130		this.type = 'LatheGeometry';
36131
36132		this.parameters = {
36133			points: points,
36134			segments: segments,
36135			phiStart: phiStart,
36136			phiLength: phiLength
36137		};
36138
36139		segments = Math.floor( segments );
36140
36141		// clamp phiLength so it's in range of [ 0, 2PI ]
36142
36143		phiLength = clamp( phiLength, 0, Math.PI * 2 );
36144
36145		// buffers
36146
36147		const indices = [];
36148		const vertices = [];
36149		const uvs = [];
36150		const initNormals = [];
36151		const normals = [];
36152
36153		// helper variables
36154
36155		const inverseSegments = 1.0 / segments;
36156		const vertex = new Vector3();
36157		const uv = new Vector2();
36158		const normal = new Vector3();
36159		const curNormal = new Vector3();
36160		const prevNormal = new Vector3();
36161		let dx = 0;
36162		let dy = 0;
36163
36164		// pre-compute normals for initial "meridian"
36165
36166		for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
36167
36168			switch ( j ) {
36169
36170				case 0:				// special handling for 1st vertex on path
36171
36172					dx = points[ j + 1 ].x - points[ j ].x;
36173					dy = points[ j + 1 ].y - points[ j ].y;
36174
36175					normal.x = dy * 1.0;
36176					normal.y = - dx;
36177					normal.z = dy * 0.0;
36178
36179					prevNormal.copy( normal );
36180
36181					normal.normalize();
36182
36183					initNormals.push( normal.x, normal.y, normal.z );
36184
36185					break;
36186
36187				case ( points.length - 1 ):	// special handling for last Vertex on path
36188
36189					initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z );
36190
36191					break;
36192
36193				default:			// default handling for all vertices in between
36194
36195					dx = points[ j + 1 ].x - points[ j ].x;
36196					dy = points[ j + 1 ].y - points[ j ].y;
36197
36198					normal.x = dy * 1.0;
36199					normal.y = - dx;
36200					normal.z = dy * 0.0;
36201
36202					curNormal.copy( normal );
36203
36204					normal.x += prevNormal.x;
36205					normal.y += prevNormal.y;
36206					normal.z += prevNormal.z;
36207
36208					normal.normalize();
36209
36210					initNormals.push( normal.x, normal.y, normal.z );
36211
36212					prevNormal.copy( curNormal );
36213
36214			}
36215
36216		}
36217
36218		// generate vertices, uvs and normals
36219
36220		for ( let i = 0; i <= segments; i ++ ) {
36221
36222			const phi = phiStart + i * inverseSegments * phiLength;
36223
36224			const sin = Math.sin( phi );
36225			const cos = Math.cos( phi );
36226
36227			for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
36228
36229				// vertex
36230
36231				vertex.x = points[ j ].x * sin;
36232				vertex.y = points[ j ].y;
36233				vertex.z = points[ j ].x * cos;
36234
36235				vertices.push( vertex.x, vertex.y, vertex.z );
36236
36237				// uv
36238
36239				uv.x = i / segments;
36240				uv.y = j / ( points.length - 1 );
36241
36242				uvs.push( uv.x, uv.y );
36243
36244				// normal
36245
36246				const x = initNormals[ 3 * j + 0 ] * sin;
36247				const y = initNormals[ 3 * j + 1 ];
36248				const z = initNormals[ 3 * j + 0 ] * cos;
36249
36250				normals.push( x, y, z );
36251
36252			}
36253
36254		}
36255
36256		// indices
36257
36258		for ( let i = 0; i < segments; i ++ ) {
36259
36260			for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
36261
36262				const base = j + i * points.length;
36263
36264				const a = base;
36265				const b = base + points.length;
36266				const c = base + points.length + 1;
36267				const d = base + 1;
36268
36269				// faces
36270
36271				indices.push( a, b, d );
36272				indices.push( c, d, b );
36273
36274			}
36275
36276		}
36277
36278		// build geometry
36279
36280		this.setIndex( indices );
36281		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36282		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36283		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36284
36285	}
36286
36287	copy( source ) {
36288
36289		super.copy( source );
36290
36291		this.parameters = Object.assign( {}, source.parameters );
36292
36293		return this;
36294
36295	}
36296
36297	static fromJSON( data ) {
36298
36299		return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength );
36300
36301	}
36302
36303}
36304
36305class CapsuleGeometry extends LatheGeometry {
36306
36307	constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) {
36308
36309		const path = new Path();
36310		path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 );
36311		path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 );
36312
36313		super( path.getPoints( capSegments ), radialSegments );
36314
36315		this.type = 'CapsuleGeometry';
36316
36317		this.parameters = {
36318			radius: radius,
36319			length: length,
36320			capSegments: capSegments,
36321			radialSegments: radialSegments,
36322		};
36323
36324	}
36325
36326	static fromJSON( data ) {
36327
36328		return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments );
36329
36330	}
36331
36332}
36333
36334class CircleGeometry extends BufferGeometry {
36335
36336	constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) {
36337
36338		super();
36339
36340		this.type = 'CircleGeometry';
36341
36342		this.parameters = {
36343			radius: radius,
36344			segments: segments,
36345			thetaStart: thetaStart,
36346			thetaLength: thetaLength
36347		};
36348
36349		segments = Math.max( 3, segments );
36350
36351		// buffers
36352
36353		const indices = [];
36354		const vertices = [];
36355		const normals = [];
36356		const uvs = [];
36357
36358		// helper variables
36359
36360		const vertex = new Vector3();
36361		const uv = new Vector2();
36362
36363		// center point
36364
36365		vertices.push( 0, 0, 0 );
36366		normals.push( 0, 0, 1 );
36367		uvs.push( 0.5, 0.5 );
36368
36369		for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
36370
36371			const segment = thetaStart + s / segments * thetaLength;
36372
36373			// vertex
36374
36375			vertex.x = radius * Math.cos( segment );
36376			vertex.y = radius * Math.sin( segment );
36377
36378			vertices.push( vertex.x, vertex.y, vertex.z );
36379
36380			// normal
36381
36382			normals.push( 0, 0, 1 );
36383
36384			// uvs
36385
36386			uv.x = ( vertices[ i ] / radius + 1 ) / 2;
36387			uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
36388
36389			uvs.push( uv.x, uv.y );
36390
36391		}
36392
36393		// indices
36394
36395		for ( let i = 1; i <= segments; i ++ ) {
36396
36397			indices.push( i, i + 1, 0 );
36398
36399		}
36400
36401		// build geometry
36402
36403		this.setIndex( indices );
36404		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,756 bytes, lines 36405-36630
36405		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36406		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36407
36408	}
36409
36410	copy( source ) {
36411
36412		super.copy( source );
36413
36414		this.parameters = Object.assign( {}, source.parameters );
36415
36416		return this;
36417
36418	}
36419
36420	static fromJSON( data ) {
36421
36422		return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength );
36423
36424	}
36425
36426}
36427
36428class CylinderGeometry extends BufferGeometry {
36429
36430	constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
36431
36432		super();
36433
36434		this.type = 'CylinderGeometry';
36435
36436		this.parameters = {
36437			radiusTop: radiusTop,
36438			radiusBottom: radiusBottom,
36439			height: height,
36440			radialSegments: radialSegments,
36441			heightSegments: heightSegments,
36442			openEnded: openEnded,
36443			thetaStart: thetaStart,
36444			thetaLength: thetaLength
36445		};
36446
36447		const scope = this;
36448
36449		radialSegments = Math.floor( radialSegments );
36450		heightSegments = Math.floor( heightSegments );
36451
36452		// buffers
36453
36454		const indices = [];
36455		const vertices = [];
36456		const normals = [];
36457		const uvs = [];
36458
36459		// helper variables
36460
36461		let index = 0;
36462		const indexArray = [];
36463		const halfHeight = height / 2;
36464		let groupStart = 0;
36465
36466		// generate geometry
36467
36468		generateTorso();
36469
36470		if ( openEnded === false ) {
36471
36472			if ( radiusTop > 0 ) generateCap( true );
36473			if ( radiusBottom > 0 ) generateCap( false );
36474
36475		}
36476
36477		// build geometry
36478
36479		this.setIndex( indices );
36480		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36481		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36482		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36483
36484		function generateTorso() {
36485
36486			const normal = new Vector3();
36487			const vertex = new Vector3();
36488
36489			let groupCount = 0;
36490
36491			// this will be used to calculate the normal
36492			const slope = ( radiusBottom - radiusTop ) / height;
36493
36494			// generate vertices, normals and uvs
36495
36496			for ( let y = 0; y <= heightSegments; y ++ ) {
36497
36498				const indexRow = [];
36499
36500				const v = y / heightSegments;
36501
36502				// calculate the radius of the current row
36503
36504				const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
36505
36506				for ( let x = 0; x <= radialSegments; x ++ ) {
36507
36508					const u = x / radialSegments;
36509
36510					const theta = u * thetaLength + thetaStart;
36511
36512					const sinTheta = Math.sin( theta );
36513					const cosTheta = Math.cos( theta );
36514
36515					// vertex
36516
36517					vertex.x = radius * sinTheta;
36518					vertex.y = - v * height + halfHeight;
36519					vertex.z = radius * cosTheta;
36520					vertices.push( vertex.x, vertex.y, vertex.z );
36521
36522					// normal
36523
36524					normal.set( sinTheta, slope, cosTheta ).normalize();
36525					normals.push( normal.x, normal.y, normal.z );
36526
36527					// uv
36528
36529					uvs.push( u, 1 - v );
36530
36531					// save index of vertex in respective row
36532
36533					indexRow.push( index ++ );
36534
36535				}
36536
36537				// now save vertices of the row in our index array
36538
36539				indexArray.push( indexRow );
36540
36541			}
36542
36543			// generate indices
36544
36545			for ( let x = 0; x < radialSegments; x ++ ) {
36546
36547				for ( let y = 0; y < heightSegments; y ++ ) {
36548
36549					// we use the index array to access the correct indices
36550
36551					const a = indexArray[ y ][ x ];
36552					const b = indexArray[ y + 1 ][ x ];
36553					const c = indexArray[ y + 1 ][ x + 1 ];
36554					const d = indexArray[ y ][ x + 1 ];
36555
36556					// faces
36557
36558					indices.push( a, b, d );
36559					indices.push( b, c, d );
36560
36561					// update group counter
36562
36563					groupCount += 6;
36564
36565				}
36566
36567			}
36568
36569			// add a group to the geometry. this will ensure multi material support
36570
36571			scope.addGroup( groupStart, groupCount, 0 );
36572
36573			// calculate new start value for groups
36574
36575			groupStart += groupCount;
36576
36577		}
36578
36579		function generateCap( top ) {
36580
36581			// save the index of the first center vertex
36582			const centerIndexStart = index;
36583
36584			const uv = new Vector2();
36585			const vertex = new Vector3();
36586
36587			let groupCount = 0;
36588
36589			const radius = ( top === true ) ? radiusTop : radiusBottom;
36590			const sign = ( top === true ) ? 1 : - 1;
36591
36592			// first we generate the center vertex data of the cap.
36593			// because the geometry needs one set of uvs per face,
36594			// we must generate a center vertex per face/segment
36595
36596			for ( let x = 1; x <= radialSegments; x ++ ) {
36597
36598				// vertex
36599
36600				vertices.push( 0, halfHeight * sign, 0 );
36601
36602				// normal
36603
36604				normals.push( 0, sign, 0 );
36605
36606				// uv
36607
36608				uvs.push( 0.5, 0.5 );
36609
36610				// increase index
36611
36612				index ++;
36613
36614			}
36615
36616			// save the index of the last center vertex
36617			const centerIndexEnd = index;
36618
36619			// now we generate the surrounding vertices, normals and uvs
36620
36621			for ( let x = 0; x <= radialSegments; x ++ ) {
36622
36623				const u = x / radialSegments;
36624				const theta = u * thetaLength + thetaStart;
36625
36626				const cosTheta = Math.cos( theta );
36627				const sinTheta = Math.sin( theta );
36628
36629				// vertex
36630
vendor: 16,069 bytes, lines 36631-37409
36631				vertex.x = radius * sinTheta;
36632				vertex.y = halfHeight * sign;
36633				vertex.z = radius * cosTheta;
36634				vertices.push( vertex.x, vertex.y, vertex.z );
36635
36636				// normal
36637
36638				normals.push( 0, sign, 0 );
36639
36640				// uv
36641
36642				uv.x = ( cosTheta * 0.5 ) + 0.5;
36643				uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
36644				uvs.push( uv.x, uv.y );
36645
36646				// increase index
36647
36648				index ++;
36649
36650			}
36651
36652			// generate indices
36653
36654			for ( let x = 0; x < radialSegments; x ++ ) {
36655
36656				const c = centerIndexStart + x;
36657				const i = centerIndexEnd + x;
36658
36659				if ( top === true ) {
36660
36661					// face top
36662
36663					indices.push( i, i + 1, c );
36664
36665				} else {
36666
36667					// face bottom
36668
36669					indices.push( i + 1, i, c );
36670
36671				}
36672
36673				groupCount += 3;
36674
36675			}
36676
36677			// add a group to the geometry. this will ensure multi material support
36678
36679			scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
36680
36681			// calculate new start value for groups
36682
36683			groupStart += groupCount;
36684
36685		}
36686
36687	}
36688
36689	copy( source ) {
36690
36691		super.copy( source );
36692
36693		this.parameters = Object.assign( {}, source.parameters );
36694
36695		return this;
36696
36697	}
36698
36699	static fromJSON( data ) {
36700
36701		return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
36702
36703	}
36704
36705}
36706
36707class ConeGeometry extends CylinderGeometry {
36708
36709	constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
36710
36711		super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
36712
36713		this.type = 'ConeGeometry';
36714
36715		this.parameters = {
36716			radius: radius,
36717			height: height,
36718			radialSegments: radialSegments,
36719			heightSegments: heightSegments,
36720			openEnded: openEnded,
36721			thetaStart: thetaStart,
36722			thetaLength: thetaLength
36723		};
36724
36725	}
36726
36727	static fromJSON( data ) {
36728
36729		return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
36730
36731	}
36732
36733}
36734
36735class PolyhedronGeometry extends BufferGeometry {
36736
36737	constructor( vertices = [], indices = [], radius = 1, detail = 0 ) {
36738
36739		super();
36740
36741		this.type = 'PolyhedronGeometry';
36742
36743		this.parameters = {
36744			vertices: vertices,
36745			indices: indices,
36746			radius: radius,
36747			detail: detail
36748		};
36749
36750		// default buffer data
36751
36752		const vertexBuffer = [];
36753		const uvBuffer = [];
36754
36755		// the subdivision creates the vertex buffer data
36756
36757		subdivide( detail );
36758
36759		// all vertices should lie on a conceptual sphere with a given radius
36760
36761		applyRadius( radius );
36762
36763		// finally, create the uv data
36764
36765		generateUVs();
36766
36767		// build non-indexed geometry
36768
36769		this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
36770		this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
36771		this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
36772
36773		if ( detail === 0 ) {
36774
36775			this.computeVertexNormals(); // flat normals
36776
36777		} else {
36778
36779			this.normalizeNormals(); // smooth normals
36780
36781		}
36782
36783		// helper functions
36784
36785		function subdivide( detail ) {
36786
36787			const a = new Vector3();
36788			const b = new Vector3();
36789			const c = new Vector3();
36790
36791			// iterate over all faces and apply a subdivision with the given detail value
36792
36793			for ( let i = 0; i < indices.length; i += 3 ) {
36794
36795				// get the vertices of the face
36796
36797				getVertexByIndex( indices[ i + 0 ], a );
36798				getVertexByIndex( indices[ i + 1 ], b );
36799				getVertexByIndex( indices[ i + 2 ], c );
36800
36801				// perform subdivision
36802
36803				subdivideFace( a, b, c, detail );
36804
36805			}
36806
36807		}
36808
36809		function subdivideFace( a, b, c, detail ) {
36810
36811			const cols = detail + 1;
36812
36813			// we use this multidimensional array as a data structure for creating the subdivision
36814
36815			const v = [];
36816
36817			// construct all of the vertices for this subdivision
36818
36819			for ( let i = 0; i <= cols; i ++ ) {
36820
36821				v[ i ] = [];
36822
36823				const aj = a.clone().lerp( c, i / cols );
36824				const bj = b.clone().lerp( c, i / cols );
36825
36826				const rows = cols - i;
36827
36828				for ( let j = 0; j <= rows; j ++ ) {
36829
36830					if ( j === 0 && i === cols ) {
36831
36832						v[ i ][ j ] = aj;
36833
36834					} else {
36835
36836						v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
36837
36838					}
36839
36840				}
36841
36842			}
36843
36844			// construct all of the faces
36845
36846			for ( let i = 0; i < cols; i ++ ) {
36847
36848				for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
36849
36850					const k = Math.floor( j / 2 );
36851
36852					if ( j % 2 === 0 ) {
36853
36854						pushVertex( v[ i ][ k + 1 ] );
36855						pushVertex( v[ i + 1 ][ k ] );
36856						pushVertex( v[ i ][ k ] );
36857
36858					} else {
36859
36860						pushVertex( v[ i ][ k + 1 ] );
36861						pushVertex( v[ i + 1 ][ k + 1 ] );
36862						pushVertex( v[ i + 1 ][ k ] );
36863
36864					}
36865
36866				}
36867
36868			}
36869
36870		}
36871
36872		function applyRadius( radius ) {
36873
36874			const vertex = new Vector3();
36875
36876			// iterate over the entire buffer and apply the radius to each vertex
36877
36878			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
36879
36880				vertex.x = vertexBuffer[ i + 0 ];
36881				vertex.y = vertexBuffer[ i + 1 ];
36882				vertex.z = vertexBuffer[ i + 2 ];
36883
36884				vertex.normalize().multiplyScalar( radius );
36885
36886				vertexBuffer[ i + 0 ] = vertex.x;
36887				vertexBuffer[ i + 1 ] = vertex.y;
36888				vertexBuffer[ i + 2 ] = vertex.z;
36889
36890			}
36891
36892		}
36893
36894		function generateUVs() {
36895
36896			const vertex = new Vector3();
36897
36898			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
36899
36900				vertex.x = vertexBuffer[ i + 0 ];
36901				vertex.y = vertexBuffer[ i + 1 ];
36902				vertex.z = vertexBuffer[ i + 2 ];
36903
36904				const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
36905				const v = inclination( vertex ) / Math.PI + 0.5;
36906				uvBuffer.push( u, 1 - v );
36907
36908			}
36909
36910			correctUVs();
36911
36912			correctSeam();
36913
36914		}
36915
36916		function correctSeam() {
36917
36918			// handle case when face straddles the seam, see #3269
36919
36920			for ( let i = 0; i < uvBuffer.length; i += 6 ) {
36921
36922				// uv data of a single face
36923
36924				const x0 = uvBuffer[ i + 0 ];
36925				const x1 = uvBuffer[ i + 2 ];
36926				const x2 = uvBuffer[ i + 4 ];
36927
36928				const max = Math.max( x0, x1, x2 );
36929				const min = Math.min( x0, x1, x2 );
36930
36931				// 0.9 is somewhat arbitrary
36932
36933				if ( max > 0.9 && min < 0.1 ) {
36934
36935					if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
36936					if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
36937					if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
36938
36939				}
36940
36941			}
36942
36943		}
36944
36945		function pushVertex( vertex ) {
36946
36947			vertexBuffer.push( vertex.x, vertex.y, vertex.z );
36948
36949		}
36950
36951		function getVertexByIndex( index, vertex ) {
36952
36953			const stride = index * 3;
36954
36955			vertex.x = vertices[ stride + 0 ];
36956			vertex.y = vertices[ stride + 1 ];
36957			vertex.z = vertices[ stride + 2 ];
36958
36959		}
36960
36961		function correctUVs() {
36962
36963			const a = new Vector3();
36964			const b = new Vector3();
36965			const c = new Vector3();
36966
36967			const centroid = new Vector3();
36968
36969			const uvA = new Vector2();
36970			const uvB = new Vector2();
36971			const uvC = new Vector2();
36972
36973			for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
36974
36975				a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
36976				b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
36977				c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
36978
36979				uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
36980				uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
36981				uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
36982
36983				centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
36984
36985				const azi = azimuth( centroid );
36986
36987				correctUV( uvA, j + 0, a, azi );
36988				correctUV( uvB, j + 2, b, azi );
36989				correctUV( uvC, j + 4, c, azi );
36990
36991			}
36992
36993		}
36994
36995		function correctUV( uv, stride, vector, azimuth ) {
36996
36997			if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
36998
36999				uvBuffer[ stride ] = uv.x - 1;
37000
37001			}
37002
37003			if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
37004
37005				uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
37006
37007			}
37008
37009		}
37010
37011		// Angle around the Y axis, counter-clockwise when looking from above.
37012
37013		function azimuth( vector ) {
37014
37015			return Math.atan2( vector.z, - vector.x );
37016
37017		}
37018
37019
37020		// Angle above the XZ plane.
37021
37022		function inclination( vector ) {
37023
37024			return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
37025
37026		}
37027
37028	}
37029
37030	copy( source ) {
37031
37032		super.copy( source );
37033
37034		this.parameters = Object.assign( {}, source.parameters );
37035
37036		return this;
37037
37038	}
37039
37040	static fromJSON( data ) {
37041
37042		return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details );
37043
37044	}
37045
37046}
37047
37048class DodecahedronGeometry extends PolyhedronGeometry {
37049
37050	constructor( radius = 1, detail = 0 ) {
37051
37052		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
37053		const r = 1 / t;
37054
37055		const vertices = [
37056
37057			// (±1, ±1, ±1)
37058			- 1, - 1, - 1,	- 1, - 1, 1,
37059			- 1, 1, - 1, - 1, 1, 1,
37060			1, - 1, - 1, 1, - 1, 1,
37061			1, 1, - 1, 1, 1, 1,
37062
37063			// (0, ±1/φ, ±φ)
37064			0, - r, - t, 0, - r, t,
37065			0, r, - t, 0, r, t,
37066
37067			// (±1/φ, ±φ, 0)
37068			- r, - t, 0, - r, t, 0,
37069			r, - t, 0, r, t, 0,
37070
37071			// (±φ, 0, ±1/φ)
37072			- t, 0, - r, t, 0, - r,
37073			- t, 0, r, t, 0, r
37074		];
37075
37076		const indices = [
37077			3, 11, 7, 	3, 7, 15, 	3, 15, 13,
37078			7, 19, 17, 	7, 17, 6, 	7, 6, 15,
37079			17, 4, 8, 	17, 8, 10, 	17, 10, 6,
37080			8, 0, 16, 	8, 16, 2, 	8, 2, 10,
37081			0, 12, 1, 	0, 1, 18, 	0, 18, 16,
37082			6, 10, 2, 	6, 2, 13, 	6, 13, 15,
37083			2, 16, 18, 	2, 18, 3, 	2, 3, 13,
37084			18, 1, 9, 	18, 9, 11, 	18, 11, 3,
37085			4, 14, 12, 	4, 12, 0, 	4, 0, 8,
37086			11, 9, 5, 	11, 5, 19, 	11, 19, 7,
37087			19, 5, 14, 	19, 14, 4, 	19, 4, 17,
37088			1, 12, 14, 	1, 14, 5, 	1, 5, 9
37089		];
37090
37091		super( vertices, indices, radius, detail );
37092
37093		this.type = 'DodecahedronGeometry';
37094
37095		this.parameters = {
37096			radius: radius,
37097			detail: detail
37098		};
37099
37100	}
37101
37102	static fromJSON( data ) {
37103
37104		return new DodecahedronGeometry( data.radius, data.detail );
37105
37106	}
37107
37108}
37109
37110const _v0 = /*@__PURE__*/ new Vector3();
37111const _v1$1 = /*@__PURE__*/ new Vector3();
37112const _normal = /*@__PURE__*/ new Vector3();
37113const _triangle = /*@__PURE__*/ new Triangle();
37114
37115class EdgesGeometry extends BufferGeometry {
37116
37117	constructor( geometry = null, thresholdAngle = 1 ) {
37118
37119		super();
37120
37121		this.type = 'EdgesGeometry';
37122
37123		this.parameters = {
37124			geometry: geometry,
37125			thresholdAngle: thresholdAngle
37126		};
37127
37128		if ( geometry !== null ) {
37129
37130			const precisionPoints = 4;
37131			const precision = Math.pow( 10, precisionPoints );
37132			const thresholdDot = Math.cos( DEG2RAD * thresholdAngle );
37133
37134			const indexAttr = geometry.getIndex();
37135			const positionAttr = geometry.getAttribute( 'position' );
37136			const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
37137
37138			const indexArr = [ 0, 0, 0 ];
37139			const vertKeys = [ 'a', 'b', 'c' ];
37140			const hashes = new Array( 3 );
37141
37142			const edgeData = {};
37143			const vertices = [];
37144			for ( let i = 0; i < indexCount; i += 3 ) {
37145
37146				if ( indexAttr ) {
37147
37148					indexArr[ 0 ] = indexAttr.getX( i );
37149					indexArr[ 1 ] = indexAttr.getX( i + 1 );
37150					indexArr[ 2 ] = indexAttr.getX( i + 2 );
37151
37152				} else {
37153
37154					indexArr[ 0 ] = i;
37155					indexArr[ 1 ] = i + 1;
37156					indexArr[ 2 ] = i + 2;
37157
37158				}
37159
37160				const { a, b, c } = _triangle;
37161				a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
37162				b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
37163				c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
37164				_triangle.getNormal( _normal );
37165
37166				// create hashes for the edge from the vertices
37167				hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
37168				hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
37169				hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
37170
37171				// skip degenerate triangles
37172				if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
37173
37174					continue;
37175
37176				}
37177
37178				// iterate over every edge
37179				for ( let j = 0; j < 3; j ++ ) {
37180
37181					// get the first and next vertex making up the edge
37182					const jNext = ( j + 1 ) % 3;
37183					const vecHash0 = hashes[ j ];
37184					const vecHash1 = hashes[ jNext ];
37185					const v0 = _triangle[ vertKeys[ j ] ];
37186					const v1 = _triangle[ vertKeys[ jNext ] ];
37187
37188					const hash = `${ vecHash0 }_${ vecHash1 }`;
37189					const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
37190
37191					if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
37192
37193						// if we found a sibling edge add it into the vertex array if
37194						// it meets the angle threshold and delete the edge from the map.
37195						if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
37196
37197							vertices.push( v0.x, v0.y, v0.z );
37198							vertices.push( v1.x, v1.y, v1.z );
37199
37200						}
37201
37202						edgeData[ reverseHash ] = null;
37203
37204					} else if ( ! ( hash in edgeData ) ) {
37205
37206						// if we've already got an edge here then skip adding a new one
37207						edgeData[ hash ] = {
37208
37209							index0: indexArr[ j ],
37210							index1: indexArr[ jNext ],
37211							normal: _normal.clone(),
37212
37213						};
37214
37215					}
37216
37217				}
37218
37219			}
37220
37221			// iterate over all remaining, unmatched edges and add them to the vertex array
37222			for ( const key in edgeData ) {
37223
37224				if ( edgeData[ key ] ) {
37225
37226					const { index0, index1 } = edgeData[ key ];
37227					_v0.fromBufferAttribute( positionAttr, index0 );
37228					_v1$1.fromBufferAttribute( positionAttr, index1 );
37229
37230					vertices.push( _v0.x, _v0.y, _v0.z );
37231					vertices.push( _v1$1.x, _v1$1.y, _v1$1.z );
37232
37233				}
37234
37235			}
37236
37237			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37238
37239		}
37240
37241	}
37242
37243	copy( source ) {
37244
37245		super.copy( source );
37246
37247		this.parameters = Object.assign( {}, source.parameters );
37248
37249		return this;
37250
37251	}
37252
37253}
37254
37255class Shape extends Path {
37256
37257	constructor( points ) {
37258
37259		super( points );
37260
37261		this.uuid = generateUUID();
37262
37263		this.type = 'Shape';
37264
37265		this.holes = [];
37266
37267	}
37268
37269	getPointsHoles( divisions ) {
37270
37271		const holesPts = [];
37272
37273		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
37274
37275			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
37276
37277		}
37278
37279		return holesPts;
37280
37281	}
37282
37283	// get points of shape and holes (keypoints based on segments parameter)
37284
37285	extractPoints( divisions ) {
37286
37287		return {
37288
37289			shape: this.getPoints( divisions ),
37290			holes: this.getPointsHoles( divisions )
37291
37292		};
37293
37294	}
37295
37296	copy( source ) {
37297
37298		super.copy( source );
37299
37300		this.holes = [];
37301
37302		for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
37303
37304			const hole = source.holes[ i ];
37305
37306			this.holes.push( hole.clone() );
37307
37308		}
37309
37310		return this;
37311
37312	}
37313
37314	toJSON() {
37315
37316		const data = super.toJSON();
37317
37318		data.uuid = this.uuid;
37319		data.holes = [];
37320
37321		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
37322
37323			const hole = this.holes[ i ];
37324			data.holes.push( hole.toJSON() );
37325
37326		}
37327
37328		return data;
37329
37330	}
37331
37332	fromJSON( json ) {
37333
37334		super.fromJSON( json );
37335
37336		this.uuid = json.uuid;
37337		this.holes = [];
37338
37339		for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
37340
37341			const hole = json.holes[ i ];
37342			this.holes.push( new Path().fromJSON( hole ) );
37343
37344		}
37345
37346		return this;
37347
37348	}
37349
37350}
37351
37352/**
37353 * Port from https://github.com/mapbox/earcut (v2.2.4)
37354 */
37355
37356const Earcut = {
37357
37358	triangulate: function ( data, holeIndices, dim = 2 ) {
37359
37360		const hasHoles = holeIndices && holeIndices.length;
37361		const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
37362		let outerNode = linkedList( data, 0, outerLen, dim, true );
37363		const triangles = [];
37364
37365		if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
37366
37367		let minX, minY, maxX, maxY, x, y, invSize;
37368
37369		if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
37370
37371		// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
37372		if ( data.length > 80 * dim ) {
37373
37374			minX = maxX = data[ 0 ];
37375			minY = maxY = data[ 1 ];
37376
37377			for ( let i = dim; i < outerLen; i += dim ) {
37378
37379				x = data[ i ];
37380				y = data[ i + 1 ];
37381				if ( x < minX ) minX = x;
37382				if ( y < minY ) minY = y;
37383				if ( x > maxX ) maxX = x;
37384				if ( y > maxY ) maxY = y;
37385
37386			}
37387
37388			// minX, minY and invSize are later used to transform coords into integers for z-order calculation
37389			invSize = Math.max( maxX - minX, maxY - minY );
37390			invSize = invSize !== 0 ? 32767 / invSize : 0;
37391
37392		}
37393
37394		earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 );
37395
37396		return triangles;
37397
37398	}
37399
37400};
37401
37402// create a circular doubly linked list from polygon points in the specified winding order
37403function linkedList( data, start, end, dim, clockwise ) {
37404
37405	let i, last;
37406
37407	if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
37408
37409		for ( i = start; i < end;
vendor: 10,405 bytes, lines 37409-37882
37409 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
37410
37411	} else {
37412
37413		for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
37414
37415	}
37416
37417	if ( last && equals( last, last.next ) ) {
37418
37419		removeNode( last );
37420		last = last.next;
37421
37422	}
37423
37424	return last;
37425
37426}
37427
37428// eliminate colinear or duplicate points
37429function filterPoints( start, end ) {
37430
37431	if ( ! start ) return start;
37432	if ( ! end ) end = start;
37433
37434	let p = start,
37435		again;
37436	do {
37437
37438		again = false;
37439
37440		if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
37441
37442			removeNode( p );
37443			p = end = p.prev;
37444			if ( p === p.next ) break;
37445			again = true;
37446
37447		} else {
37448
37449			p = p.next;
37450
37451		}
37452
37453	} while ( again || p !== end );
37454
37455	return end;
37456
37457}
37458
37459// main ear slicing loop which triangulates a polygon (given as a linked list)
37460function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
37461
37462	if ( ! ear ) return;
37463
37464	// interlink polygon nodes in z-order
37465	if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
37466
37467	let stop = ear,
37468		prev, next;
37469
37470	// iterate through ears, slicing them one by one
37471	while ( ear.prev !== ear.next ) {
37472
37473		prev = ear.prev;
37474		next = ear.next;
37475
37476		if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
37477
37478			// cut off the triangle
37479			triangles.push( prev.i / dim | 0 );
37480			triangles.push( ear.i / dim | 0 );
37481			triangles.push( next.i / dim | 0 );
37482
37483			removeNode( ear );
37484
37485			// skipping the next vertex leads to less sliver triangles
37486			ear = next.next;
37487			stop = next.next;
37488
37489			continue;
37490
37491		}
37492
37493		ear = next;
37494
37495		// if we looped through the whole remaining polygon and can't find any more ears
37496		if ( ear === stop ) {
37497
37498			// try filtering points and slicing again
37499			if ( ! pass ) {
37500
37501				earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
37502
37503				// if this didn't work, try curing all small self-intersections locally
37504
37505			} else if ( pass === 1 ) {
37506
37507				ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
37508				earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
37509
37510				// as a last resort, try splitting the remaining polygon into two
37511
37512			} else if ( pass === 2 ) {
37513
37514				splitEarcut( ear, triangles, dim, minX, minY, invSize );
37515
37516			}
37517
37518			break;
37519
37520		}
37521
37522	}
37523
37524}
37525
37526// check whether a polygon node forms a valid ear with adjacent nodes
37527function isEar( ear ) {
37528
37529	const a = ear.prev,
37530		b = ear,
37531		c = ear.next;
37532
37533	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
37534
37535	// now make sure we don't have other points inside the potential ear
37536	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
37537
37538	// triangle bbox; min & max are calculated like this for speed
37539	const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
37540		y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
37541		x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
37542		y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
37543
37544	let p = c.next;
37545	while ( p !== a ) {
37546
37547		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
37548			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) &&
37549			area( p.prev, p, p.next ) >= 0 ) return false;
37550		p = p.next;
37551
37552	}
37553
37554	return true;
37555
37556}
37557
37558function isEarHashed( ear, minX, minY, invSize ) {
37559
37560	const a = ear.prev,
37561		b = ear,
37562		c = ear.next;
37563
37564	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
37565
37566	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
37567
37568	// triangle bbox; min & max are calculated like this for speed
37569	const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
37570		y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
37571		x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
37572		y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
37573
37574	// z-order range for the current triangle bbox;
37575	const minZ = zOrder( x0, y0, minX, minY, invSize ),
37576		maxZ = zOrder( x1, y1, minX, minY, invSize );
37577
37578	let p = ear.prevZ,
37579		n = ear.nextZ;
37580
37581	// look for points inside the triangle in both directions
37582	while ( p && p.z >= minZ && n && n.z <= maxZ ) {
37583
37584		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
37585			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
37586		p = p.prevZ;
37587
37588		if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
37589			pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
37590		n = n.nextZ;
37591
37592	}
37593
37594	// look for remaining points in decreasing z-order
37595	while ( p && p.z >= minZ ) {
37596
37597		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
37598			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
37599		p = p.prevZ;
37600
37601	}
37602
37603	// look for remaining points in increasing z-order
37604	while ( n && n.z <= maxZ ) {
37605
37606		if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
37607			pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
37608		n = n.nextZ;
37609
37610	}
37611
37612	return true;
37613
37614}
37615
37616// go through all polygon nodes and cure small local self-intersections
37617function cureLocalIntersections( start, triangles, dim ) {
37618
37619	let p = start;
37620	do {
37621
37622		const a = p.prev,
37623			b = p.next.next;
37624
37625		if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
37626
37627			triangles.push( a.i / dim | 0 );
37628			triangles.push( p.i / dim | 0 );
37629			triangles.push( b.i / dim | 0 );
37630
37631			// remove two nodes involved
37632			removeNode( p );
37633			removeNode( p.next );
37634
37635			p = start = b;
37636
37637		}
37638
37639		p = p.next;
37640
37641	} while ( p !== start );
37642
37643	return filterPoints( p );
37644
37645}
37646
37647// try splitting polygon into two and triangulate them independently
37648function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
37649
37650	// look for a valid diagonal that divides the polygon into two
37651	let a = start;
37652	do {
37653
37654		let b = a.next.next;
37655		while ( b !== a.prev ) {
37656
37657			if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
37658
37659				// split the polygon in two by the diagonal
37660				let c = splitPolygon( a, b );
37661
37662				// filter colinear points around the cuts
37663				a = filterPoints( a, a.next );
37664				c = filterPoints( c, c.next );
37665
37666				// run earcut on each half
37667				earcutLinked( a, triangles, dim, minX, minY, invSize, 0 );
37668				earcutLinked( c, triangles, dim, minX, minY, invSize, 0 );
37669				return;
37670
37671			}
37672
37673			b = b.next;
37674
37675		}
37676
37677		a = a.next;
37678
37679	} while ( a !== start );
37680
37681}
37682
37683// link every hole into the outer loop, producing a single-ring polygon without holes
37684function eliminateHoles( data, holeIndices, outerNode, dim ) {
37685
37686	const queue = [];
37687	let i, len, start, end, list;
37688
37689	for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
37690
37691		start = holeIndices[ i ] * dim;
37692		end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
37693		list = linkedList( data, start, end, dim, false );
37694		if ( list === list.next ) list.steiner = true;
37695		queue.push( getLeftmost( list ) );
37696
37697	}
37698
37699	queue.sort( compareX );
37700
37701	// process holes from left to right
37702	for ( i = 0; i < queue.length; i ++ ) {
37703
37704		outerNode = eliminateHole( queue[ i ], outerNode );
37705
37706	}
37707
37708	return outerNode;
37709
37710}
37711
37712function compareX( a, b ) {
37713
37714	return a.x - b.x;
37715
37716}
37717
37718// find a bridge between vertices that connects hole with an outer ring and link it
37719function eliminateHole( hole, outerNode ) {
37720
37721	const bridge = findHoleBridge( hole, outerNode );
37722	if ( ! bridge ) {
37723
37724		return outerNode;
37725
37726	}
37727
37728	const bridgeReverse = splitPolygon( bridge, hole );
37729
37730	// filter collinear points around the cuts
37731	filterPoints( bridgeReverse, bridgeReverse.next );
37732	return filterPoints( bridge, bridge.next );
37733
37734}
37735
37736// David Eberly's algorithm for finding a bridge between hole and outer polygon
37737function findHoleBridge( hole, outerNode ) {
37738
37739	let p = outerNode,
37740		qx = - Infinity,
37741		m;
37742
37743	const hx = hole.x, hy = hole.y;
37744
37745	// find a segment intersected by a ray from the hole's leftmost point to the left;
37746	// segment's endpoint with lesser x will be potential connection point
37747	do {
37748
37749		if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
37750
37751			const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
37752			if ( x <= hx && x > qx ) {
37753
37754				qx = x;
37755				m = p.x < p.next.x ? p : p.next;
37756				if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint
37757
37758			}
37759
37760		}
37761
37762		p = p.next;
37763
37764	} while ( p !== outerNode );
37765
37766	if ( ! m ) return null;
37767
37768	// look for points inside the triangle of hole point, segment intersection and endpoint;
37769	// if there are no points found, we have a valid connection;
37770	// otherwise choose the point of the minimum angle with the ray as connection point
37771
37772	const stop = m,
37773		mx = m.x,
37774		my = m.y;
37775	let tanMin = Infinity, tan;
37776
37777	p = m;
37778
37779	do {
37780
37781		if ( hx >= p.x && p.x >= mx && hx !== p.x &&
37782				pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
37783
37784			tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
37785
37786			if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
37787
37788				m = p;
37789				tanMin = tan;
37790
37791			}
37792
37793		}
37794
37795		p = p.next;
37796
37797	} while ( p !== stop );
37798
37799	return m;
37800
37801}
37802
37803// whether sector in vertex m contains sector in vertex p in the same coordinates
37804function sectorContainsSector( m, p ) {
37805
37806	return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
37807
37808}
37809
37810// interlink polygon nodes in z-order
37811function indexCurve( start, minX, minY, invSize ) {
37812
37813	let p = start;
37814	do {
37815
37816		if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
37817		p.prevZ = p.prev;
37818		p.nextZ = p.next;
37819		p = p.next;
37820
37821	} while ( p !== start );
37822
37823	p.prevZ.nextZ = null;
37824	p.prevZ = null;
37825
37826	sortLinked( p );
37827
37828}
37829
37830// Simon Tatham's linked list merge sort algorithm
37831// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
37832function sortLinked( list ) {
37833
37834	let i, p, q, e, tail, numMerges, pSize, qSize,
37835		inSize = 1;
37836
37837	do {
37838
37839		p = list;
37840		list = null;
37841		tail = null;
37842		numMerges = 0;
37843
37844		while ( p ) {
37845
37846			numMerges ++;
37847			q = p;
37848			pSize = 0;
37849			for ( i = 0; i < inSize; i ++ ) {
37850
37851				pSize ++;
37852				q = q.nextZ;
37853				if ( ! q ) break;
37854
37855			}
37856
37857			qSize = inSize;
37858
37859			while ( pSize > 0 || ( qSize > 0 && q ) ) {
37860
37861				if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
37862
37863					e = p;
37864					p = p.nextZ;
37865					pSize --;
37866
37867				} else {
37868
37869					e = q;
37870					q = q.nextZ;
37871					qSize --;
37872
37873				}
37874
37875				if ( tail ) tail.nextZ = e;
37876				else list = e;
37877
37878				e.prevZ = tail;
37879				tail = e;
37880
37881			}
37882
vendor: 9,707 bytes, lines 37883-38310
37883			p = q;
37884
37885		}
37886
37887		tail.nextZ = null;
37888		inSize *= 2;
37889
37890	} while ( numMerges > 1 );
37891
37892	return list;
37893
37894}
37895
37896// z-order of a point given coords and inverse of the longer side of data bbox
37897function zOrder( x, y, minX, minY, invSize ) {
37898
37899	// coords are transformed into non-negative 15-bit integer range
37900	x = ( x - minX ) * invSize | 0;
37901	y = ( y - minY ) * invSize | 0;
37902
37903	x = ( x | ( x << 8 ) ) & 0x00FF00FF;
37904	x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
37905	x = ( x | ( x << 2 ) ) & 0x33333333;
37906	x = ( x | ( x << 1 ) ) & 0x55555555;
37907
37908	y = ( y | ( y << 8 ) ) & 0x00FF00FF;
37909	y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
37910	y = ( y | ( y << 2 ) ) & 0x33333333;
37911	y = ( y | ( y << 1 ) ) & 0x55555555;
37912
37913	return x | ( y << 1 );
37914
37915}
37916
37917// find the leftmost node of a polygon ring
37918function getLeftmost( start ) {
37919
37920	let p = start,
37921		leftmost = start;
37922	do {
37923
37924		if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
37925		p = p.next;
37926
37927	} while ( p !== start );
37928
37929	return leftmost;
37930
37931}
37932
37933// check if a point lies within a convex triangle
37934function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
37935
37936	return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) &&
37937           ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) &&
37938           ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py );
37939
37940}
37941
37942// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
37943function isValidDiagonal( a, b ) {
37944
37945	return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges
37946           ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
37947            ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
37948            equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
37949
37950}
37951
37952// signed area of a triangle
37953function area( p, q, r ) {
37954
37955	return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
37956
37957}
37958
37959// check if two points are equal
37960function equals( p1, p2 ) {
37961
37962	return p1.x === p2.x && p1.y === p2.y;
37963
37964}
37965
37966// check if two segments intersect
37967function intersects( p1, q1, p2, q2 ) {
37968
37969	const o1 = sign( area( p1, q1, p2 ) );
37970	const o2 = sign( area( p1, q1, q2 ) );
37971	const o3 = sign( area( p2, q2, p1 ) );
37972	const o4 = sign( area( p2, q2, q1 ) );
37973
37974	if ( o1 !== o2 && o3 !== o4 ) return true; // general case
37975
37976	if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
37977	if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
37978	if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
37979	if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
37980
37981	return false;
37982
37983}
37984
37985// for collinear points p, q, r, check if point q lies on segment pr
37986function onSegment( p, q, r ) {
37987
37988	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 );
37989
37990}
37991
37992function sign( num ) {
37993
37994	return num > 0 ? 1 : num < 0 ? - 1 : 0;
37995
37996}
37997
37998// check if a polygon diagonal intersects any polygon segments
37999function intersectsPolygon( a, b ) {
38000
38001	let p = a;
38002	do {
38003
38004		if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
38005			intersects( p, p.next, a, b ) ) return true;
38006		p = p.next;
38007
38008	} while ( p !== a );
38009
38010	return false;
38011
38012}
38013
38014// check if a polygon diagonal is locally inside the polygon
38015function locallyInside( a, b ) {
38016
38017	return area( a.prev, a, a.next ) < 0 ?
38018		area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
38019		area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
38020
38021}
38022
38023// check if the middle point of a polygon diagonal is inside the polygon
38024function middleInside( a, b ) {
38025
38026	let p = a,
38027		inside = false;
38028	const px = ( a.x + b.x ) / 2,
38029		py = ( a.y + b.y ) / 2;
38030	do {
38031
38032		if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
38033			( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
38034			inside = ! inside;
38035		p = p.next;
38036
38037	} while ( p !== a );
38038
38039	return inside;
38040
38041}
38042
38043// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
38044// if one belongs to the outer ring and another to a hole, it merges it into a single ring
38045function splitPolygon( a, b ) {
38046
38047	const a2 = new Node( a.i, a.x, a.y ),
38048		b2 = new Node( b.i, b.x, b.y ),
38049		an = a.next,
38050		bp = b.prev;
38051
38052	a.next = b;
38053	b.prev = a;
38054
38055	a2.next = an;
38056	an.prev = a2;
38057
38058	b2.next = a2;
38059	a2.prev = b2;
38060
38061	bp.next = b2;
38062	b2.prev = bp;
38063
38064	return b2;
38065
38066}
38067
38068// create a node and optionally link it with previous one (in a circular doubly linked list)
38069function insertNode( i, x, y, last ) {
38070
38071	const p = new Node( i, x, y );
38072
38073	if ( ! last ) {
38074
38075		p.prev = p;
38076		p.next = p;
38077
38078	} else {
38079
38080		p.next = last.next;
38081		p.prev = last;
38082		last.next.prev = p;
38083		last.next = p;
38084
38085	}
38086
38087	return p;
38088
38089}
38090
38091function removeNode( p ) {
38092
38093	p.next.prev = p.prev;
38094	p.prev.next = p.next;
38095
38096	if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
38097	if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
38098
38099}
38100
38101function Node( i, x, y ) {
38102
38103	// vertex index in coordinates array
38104	this.i = i;
38105
38106	// vertex coordinates
38107	this.x = x;
38108	this.y = y;
38109
38110	// previous and next vertex nodes in a polygon ring
38111	this.prev = null;
38112	this.next = null;
38113
38114	// z-order curve value
38115	this.z = 0;
38116
38117	// previous and next nodes in z-order
38118	this.prevZ = null;
38119	this.nextZ = null;
38120
38121	// indicates whether this is a steiner point
38122	this.steiner = false;
38123
38124}
38125
38126function signedArea( data, start, end, dim ) {
38127
38128	let sum = 0;
38129	for ( let i = start, j = end - dim; i < end; i += dim ) {
38130
38131		sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
38132		j = i;
38133
38134	}
38135
38136	return sum;
38137
38138}
38139
38140class ShapeUtils {
38141
38142	// calculate area of the contour polygon
38143
38144	static area( contour ) {
38145
38146		const n = contour.length;
38147		let a = 0.0;
38148
38149		for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
38150
38151			a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
38152
38153		}
38154
38155		return a * 0.5;
38156
38157	}
38158
38159	static isClockWise( pts ) {
38160
38161		return ShapeUtils.area( pts ) < 0;
38162
38163	}
38164
38165	static triangulateShape( contour, holes ) {
38166
38167		const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
38168		const holeIndices = []; // array of hole indices
38169		const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
38170
38171		removeDupEndPts( contour );
38172		addContour( vertices, contour );
38173
38174		//
38175
38176		let holeIndex = contour.length;
38177
38178		holes.forEach( removeDupEndPts );
38179
38180		for ( let i = 0; i < holes.length; i ++ ) {
38181
38182			holeIndices.push( holeIndex );
38183			holeIndex += holes[ i ].length;
38184			addContour( vertices, holes[ i ] );
38185
38186		}
38187
38188		//
38189
38190		const triangles = Earcut.triangulate( vertices, holeIndices );
38191
38192		//
38193
38194		for ( let i = 0; i < triangles.length; i += 3 ) {
38195
38196			faces.push( triangles.slice( i, i + 3 ) );
38197
38198		}
38199
38200		return faces;
38201
38202	}
38203
38204}
38205
38206function removeDupEndPts( points ) {
38207
38208	const l = points.length;
38209
38210	if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
38211
38212		points.pop();
38213
38214	}
38215
38216}
38217
38218function addContour( vertices, contour ) {
38219
38220	for ( let i = 0; i < contour.length; i ++ ) {
38221
38222		vertices.push( contour[ i ].x );
38223		vertices.push( contour[ i ].y );
38224
38225	}
38226
38227}
38228
38229/**
38230 * Creates extruded geometry from a path shape.
38231 *
38232 * parameters = {
38233 *
38234 *  curveSegments: <int>, // number of points on the curves
38235 *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
38236 *  depth: <float>, // Depth to extrude the shape
38237 *
38238 *  bevelEnabled: <bool>, // turn on bevel
38239 *  bevelThickness: <float>, // how deep into the original shape bevel goes
38240 *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
38241 *  bevelOffset: <float>, // how far from shape outline does bevel start
38242 *  bevelSegments: <int>, // number of bevel layers
38243 *
38244 *  extrudePath: <THREE.Curve> // curve to extrude shape along
38245 *
38246 *  UVGenerator: <Object> // object that provides UV generator functions
38247 *
38248 * }
38249 */
38250
38251
38252class ExtrudeGeometry extends BufferGeometry {
38253
38254	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 = {} ) {
38255
38256		super();
38257
38258		this.type = 'ExtrudeGeometry';
38259
38260		this.parameters = {
38261			shapes: shapes,
38262			options: options
38263		};
38264
38265		shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
38266
38267		const scope = this;
38268
38269		const verticesArray = [];
38270		const uvArray = [];
38271
38272		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
38273
38274			const shape = shapes[ i ];
38275			addShape( shape );
38276
38277		}
38278
38279		// build geometry
38280
38281		this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
38282		this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
38283
38284		this.computeVertexNormals();
38285
38286		// functions
38287
38288		function addShape( shape ) {
38289
38290			const placeholder = [];
38291
38292			// options
38293
38294			const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
38295			const steps = options.steps !== undefined ? options.steps : 1;
38296			const depth = options.depth !== undefined ? options.depth : 1;
38297
38298			let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
38299			let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
38300			let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
38301			let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
38302			let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
38303
38304			const extrudePath = options.extrudePath;
38305
38306			const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
38307
38308			//
38309
38310			let extrudePts, extrudeByPath = false;
vendor: 2,791 bytes, lines 38311-38424
38311			let splineTube, binormal, normal, position2;
38312
38313			if ( extrudePath ) {
38314
38315				extrudePts = extrudePath.getSpacedPoints( steps );
38316
38317				extrudeByPath = true;
38318				bevelEnabled = false; // bevels not supported for path extrusion
38319
38320				// SETUP TNB variables
38321
38322				// TODO1 - have a .isClosed in spline?
38323
38324				splineTube = extrudePath.computeFrenetFrames( steps, false );
38325
38326				// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
38327
38328				binormal = new Vector3();
38329				normal = new Vector3();
38330				position2 = new Vector3();
38331
38332			}
38333
38334			// Safeguards if bevels are not enabled
38335
38336			if ( ! bevelEnabled ) {
38337
38338				bevelSegments = 0;
38339				bevelThickness = 0;
38340				bevelSize = 0;
38341				bevelOffset = 0;
38342
38343			}
38344
38345			// Variables initialization
38346
38347			const shapePoints = shape.extractPoints( curveSegments );
38348
38349			let vertices = shapePoints.shape;
38350			const holes = shapePoints.holes;
38351
38352			const reverse = ! ShapeUtils.isClockWise( vertices );
38353
38354			if ( reverse ) {
38355
38356				vertices = vertices.reverse();
38357
38358				// Maybe we should also check if holes are in the opposite direction, just to be safe ...
38359
38360				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
38361
38362					const ahole = holes[ h ];
38363
38364					if ( ShapeUtils.isClockWise( ahole ) ) {
38365
38366						holes[ h ] = ahole.reverse();
38367
38368					}
38369
38370				}
38371
38372			}
38373
38374
38375			const faces = ShapeUtils.triangulateShape( vertices, holes );
38376
38377			/* Vertices */
38378
38379			const contour = vertices; // vertices has all points but contour has only points of circumference
38380
38381			for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
38382
38383				const ahole = holes[ h ];
38384
38385				vertices = vertices.concat( ahole );
38386
38387			}
38388
38389
38390			function scalePt2( pt, vec, size ) {
38391
38392				if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
38393
38394				return pt.clone().addScaledVector( vec, size );
38395
38396			}
38397
38398			const vlen = vertices.length, flen = faces.length;
38399
38400
38401			// Find directions for point movement
38402
38403
38404			function getBevelVec( inPt, inPrev, inNext ) {
38405
38406				// computes for inPt the corresponding point inPt' on a new contour
38407				//   shifted by 1 unit (length of normalized vector) to the left
38408				// if we walk along contour clockwise, this new contour is outside the old one
38409				//
38410				// inPt' is the intersection of the two lines parallel to the two
38411				//  adjacent edges of inPt at a distance of 1 unit on the left side.
38412
38413				let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
38414
38415				// good reading for geometry algorithms (here: line-line intersection)
38416				// http://geomalgorithms.com/a05-_intersect-1.html
38417
38418				const v_prev_x = inPt.x - inPrev.x,
38419					v_prev_y = inPt.y - inPrev.y;
38420				const v_next_x = inNext.x - inPt.x,
38421					v_next_y = inNext.y - inPt.y;
38422
38423				const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
38424
vendor: 17,452 bytes, lines 38425-39276
38425				// check for collinear edges
38426				const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
38427
38428				if ( Math.abs( collinear0 ) > Number.EPSILON ) {
38429
38430					// not collinear
38431
38432					// length of vectors for normalizing
38433
38434					const v_prev_len = Math.sqrt( v_prev_lensq );
38435					const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
38436
38437					// shift adjacent points by unit vectors to the left
38438
38439					const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
38440					const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
38441
38442					const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
38443					const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
38444
38445					// scaling factor for v_prev to intersection point
38446
38447					const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
38448							( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
38449						( v_prev_x * v_next_y - v_prev_y * v_next_x );
38450
38451					// vector from inPt to intersection point
38452
38453					v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
38454					v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
38455
38456					// Don't normalize!, otherwise sharp corners become ugly
38457					//  but prevent crazy spikes
38458					const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
38459					if ( v_trans_lensq <= 2 ) {
38460
38461						return new Vector2( v_trans_x, v_trans_y );
38462
38463					} else {
38464
38465						shrink_by = Math.sqrt( v_trans_lensq / 2 );
38466
38467					}
38468
38469				} else {
38470
38471					// handle special case of collinear edges
38472
38473					let direction_eq = false; // assumes: opposite
38474
38475					if ( v_prev_x > Number.EPSILON ) {
38476
38477						if ( v_next_x > Number.EPSILON ) {
38478
38479							direction_eq = true;
38480
38481						}
38482
38483					} else {
38484
38485						if ( v_prev_x < - Number.EPSILON ) {
38486
38487							if ( v_next_x < - Number.EPSILON ) {
38488
38489								direction_eq = true;
38490
38491							}
38492
38493						} else {
38494
38495							if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
38496
38497								direction_eq = true;
38498
38499							}
38500
38501						}
38502
38503					}
38504
38505					if ( direction_eq ) {
38506
38507						// console.log("Warning: lines are a straight sequence");
38508						v_trans_x = - v_prev_y;
38509						v_trans_y = v_prev_x;
38510						shrink_by = Math.sqrt( v_prev_lensq );
38511
38512					} else {
38513
38514						// console.log("Warning: lines are a straight spike");
38515						v_trans_x = v_prev_x;
38516						v_trans_y = v_prev_y;
38517						shrink_by = Math.sqrt( v_prev_lensq / 2 );
38518
38519					}
38520
38521				}
38522
38523				return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
38524
38525			}
38526
38527
38528			const contourMovements = [];
38529
38530			for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
38531
38532				if ( j === il ) j = 0;
38533				if ( k === il ) k = 0;
38534
38535				//  (j)---(i)---(k)
38536				// console.log('i,j,k', i, j , k)
38537
38538				contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
38539
38540			}
38541
38542			const holesMovements = [];
38543			let oneHoleMovements, verticesMovements = contourMovements.concat();
38544
38545			for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
38546
38547				const ahole = holes[ h ];
38548
38549				oneHoleMovements = [];
38550
38551				for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
38552
38553					if ( j === il ) j = 0;
38554					if ( k === il ) k = 0;
38555
38556					//  (j)---(i)---(k)
38557					oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
38558
38559				}
38560
38561				holesMovements.push( oneHoleMovements );
38562				verticesMovements = verticesMovements.concat( oneHoleMovements );
38563
38564			}
38565
38566
38567			// Loop bevelSegments, 1 for the front, 1 for the back
38568
38569			for ( let b = 0; b < bevelSegments; b ++ ) {
38570
38571				//for ( b = bevelSegments; b > 0; b -- ) {
38572
38573				const t = b / bevelSegments;
38574				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
38575				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
38576
38577				// contract shape
38578
38579				for ( let i = 0, il = contour.length; i < il; i ++ ) {
38580
38581					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
38582
38583					v( vert.x, vert.y, - z );
38584
38585				}
38586
38587				// expand holes
38588
38589				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
38590
38591					const ahole = holes[ h ];
38592					oneHoleMovements = holesMovements[ h ];
38593
38594					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
38595
38596						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
38597
38598						v( vert.x, vert.y, - z );
38599
38600					}
38601
38602				}
38603
38604			}
38605
38606			const bs = bevelSize + bevelOffset;
38607
38608			// Back facing vertices
38609
38610			for ( let i = 0; i < vlen; i ++ ) {
38611
38612				const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
38613
38614				if ( ! extrudeByPath ) {
38615
38616					v( vert.x, vert.y, 0 );
38617
38618				} else {
38619
38620					// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
38621
38622					normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
38623					binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
38624
38625					position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
38626
38627					v( position2.x, position2.y, position2.z );
38628
38629				}
38630
38631			}
38632
38633			// Add stepped vertices...
38634			// Including front facing vertices
38635
38636			for ( let s = 1; s <= steps; s ++ ) {
38637
38638				for ( let i = 0; i < vlen; i ++ ) {
38639
38640					const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
38641
38642					if ( ! extrudeByPath ) {
38643
38644						v( vert.x, vert.y, depth / steps * s );
38645
38646					} else {
38647
38648						// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
38649
38650						normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
38651						binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
38652
38653						position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
38654
38655						v( position2.x, position2.y, position2.z );
38656
38657					}
38658
38659				}
38660
38661			}
38662
38663
38664			// Add bevel segments planes
38665
38666			//for ( b = 1; b <= bevelSegments; b ++ ) {
38667			for ( let b = bevelSegments - 1; b >= 0; b -- ) {
38668
38669				const t = b / bevelSegments;
38670				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
38671				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
38672
38673				// contract shape
38674
38675				for ( let i = 0, il = contour.length; i < il; i ++ ) {
38676
38677					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
38678					v( vert.x, vert.y, depth + z );
38679
38680				}
38681
38682				// expand holes
38683
38684				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
38685
38686					const ahole = holes[ h ];
38687					oneHoleMovements = holesMovements[ h ];
38688
38689					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
38690
38691						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
38692
38693						if ( ! extrudeByPath ) {
38694
38695							v( vert.x, vert.y, depth + z );
38696
38697						} else {
38698
38699							v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
38700
38701						}
38702
38703					}
38704
38705				}
38706
38707			}
38708
38709			/* Faces */
38710
38711			// Top and bottom faces
38712
38713			buildLidFaces();
38714
38715			// Sides faces
38716
38717			buildSideFaces();
38718
38719
38720			/////  Internal functions
38721
38722			function buildLidFaces() {
38723
38724				const start = verticesArray.length / 3;
38725
38726				if ( bevelEnabled ) {
38727
38728					let layer = 0; // steps + 1
38729					let offset = vlen * layer;
38730
38731					// Bottom faces
38732
38733					for ( let i = 0; i < flen; i ++ ) {
38734
38735						const face = faces[ i ];
38736						f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
38737
38738					}
38739
38740					layer = steps + bevelSegments * 2;
38741					offset = vlen * layer;
38742
38743					// Top faces
38744
38745					for ( let i = 0; i < flen; i ++ ) {
38746
38747						const face = faces[ i ];
38748						f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
38749
38750					}
38751
38752				} else {
38753
38754					// Bottom faces
38755
38756					for ( let i = 0; i < flen; i ++ ) {
38757
38758						const face = faces[ i ];
38759						f3( face[ 2 ], face[ 1 ], face[ 0 ] );
38760
38761					}
38762
38763					// Top faces
38764
38765					for ( let i = 0; i < flen; i ++ ) {
38766
38767						const face = faces[ i ];
38768						f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
38769
38770					}
38771
38772				}
38773
38774				scope.addGroup( start, verticesArray.length / 3 - start, 0 );
38775
38776			}
38777
38778			// Create faces for the z-sides of the shape
38779
38780			function buildSideFaces() {
38781
38782				const start = verticesArray.length / 3;
38783				let layeroffset = 0;
38784				sidewalls( contour, layeroffset );
38785				layeroffset += contour.length;
38786
38787				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
38788
38789					const ahole = holes[ h ];
38790					sidewalls( ahole, layeroffset );
38791
38792					//, true
38793					layeroffset += ahole.length;
38794
38795				}
38796
38797
38798				scope.addGroup( start, verticesArray.length / 3 - start, 1 );
38799
38800
38801			}
38802
38803			function sidewalls( contour, layeroffset ) {
38804
38805				let i = contour.length;
38806
38807				while ( -- i >= 0 ) {
38808
38809					const j = i;
38810					let k = i - 1;
38811					if ( k < 0 ) k = contour.length - 1;
38812
38813					//console.log('b', i,j, i-1, k,vertices.length);
38814
38815					for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
38816
38817						const slen1 = vlen * s;
38818						const slen2 = vlen * ( s + 1 );
38819
38820						const a = layeroffset + j + slen1,
38821							b = layeroffset + k + slen1,
38822							c = layeroffset + k + slen2,
38823							d = layeroffset + j + slen2;
38824
38825						f4( a, b, c, d );
38826
38827					}
38828
38829				}
38830
38831			}
38832
38833			function v( x, y, z ) {
38834
38835				placeholder.push( x );
38836				placeholder.push( y );
38837				placeholder.push( z );
38838
38839			}
38840
38841
38842			function f3( a, b, c ) {
38843
38844				addVertex( a );
38845				addVertex( b );
38846				addVertex( c );
38847
38848				const nextIndex = verticesArray.length / 3;
38849				const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
38850
38851				addUV( uvs[ 0 ] );
38852				addUV( uvs[ 1 ] );
38853				addUV( uvs[ 2 ] );
38854
38855			}
38856
38857			function f4( a, b, c, d ) {
38858
38859				addVertex( a );
38860				addVertex( b );
38861				addVertex( d );
38862
38863				addVertex( b );
38864				addVertex( c );
38865				addVertex( d );
38866
38867
38868				const nextIndex = verticesArray.length / 3;
38869				const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
38870
38871				addUV( uvs[ 0 ] );
38872				addUV( uvs[ 1 ] );
38873				addUV( uvs[ 3 ] );
38874
38875				addUV( uvs[ 1 ] );
38876				addUV( uvs[ 2 ] );
38877				addUV( uvs[ 3 ] );
38878
38879			}
38880
38881			function addVertex( index ) {
38882
38883				verticesArray.push( placeholder[ index * 3 + 0 ] );
38884				verticesArray.push( placeholder[ index * 3 + 1 ] );
38885				verticesArray.push( placeholder[ index * 3 + 2 ] );
38886
38887			}
38888
38889
38890			function addUV( vector2 ) {
38891
38892				uvArray.push( vector2.x );
38893				uvArray.push( vector2.y );
38894
38895			}
38896
38897		}
38898
38899	}
38900
38901	copy( source ) {
38902
38903		super.copy( source );
38904
38905		this.parameters = Object.assign( {}, source.parameters );
38906
38907		return this;
38908
38909	}
38910
38911	toJSON() {
38912
38913		const data = super.toJSON();
38914
38915		const shapes = this.parameters.shapes;
38916		const options = this.parameters.options;
38917
38918		return toJSON$1( shapes, options, data );
38919
38920	}
38921
38922	static fromJSON( data, shapes ) {
38923
38924		const geometryShapes = [];
38925
38926		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
38927
38928			const shape = shapes[ data.shapes[ j ] ];
38929
38930			geometryShapes.push( shape );
38931
38932		}
38933
38934		const extrudePath = data.options.extrudePath;
38935
38936		if ( extrudePath !== undefined ) {
38937
38938			data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
38939
38940		}
38941
38942		return new ExtrudeGeometry( geometryShapes, data.options );
38943
38944	}
38945
38946}
38947
38948const WorldUVGenerator = {
38949
38950	generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
38951
38952		const a_x = vertices[ indexA * 3 ];
38953		const a_y = vertices[ indexA * 3 + 1 ];
38954		const b_x = vertices[ indexB * 3 ];
38955		const b_y = vertices[ indexB * 3 + 1 ];
38956		const c_x = vertices[ indexC * 3 ];
38957		const c_y = vertices[ indexC * 3 + 1 ];
38958
38959		return [
38960			new Vector2( a_x, a_y ),
38961			new Vector2( b_x, b_y ),
38962			new Vector2( c_x, c_y )
38963		];
38964
38965	},
38966
38967	generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
38968
38969		const a_x = vertices[ indexA * 3 ];
38970		const a_y = vertices[ indexA * 3 + 1 ];
38971		const a_z = vertices[ indexA * 3 + 2 ];
38972		const b_x = vertices[ indexB * 3 ];
38973		const b_y = vertices[ indexB * 3 + 1 ];
38974		const b_z = vertices[ indexB * 3 + 2 ];
38975		const c_x = vertices[ indexC * 3 ];
38976		const c_y = vertices[ indexC * 3 + 1 ];
38977		const c_z = vertices[ indexC * 3 + 2 ];
38978		const d_x = vertices[ indexD * 3 ];
38979		const d_y = vertices[ indexD * 3 + 1 ];
38980		const d_z = vertices[ indexD * 3 + 2 ];
38981
38982		if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) {
38983
38984			return [
38985				new Vector2( a_x, 1 - a_z ),
38986				new Vector2( b_x, 1 - b_z ),
38987				new Vector2( c_x, 1 - c_z ),
38988				new Vector2( d_x, 1 - d_z )
38989			];
38990
38991		} else {
38992
38993			return [
38994				new Vector2( a_y, 1 - a_z ),
38995				new Vector2( b_y, 1 - b_z ),
38996				new Vector2( c_y, 1 - c_z ),
38997				new Vector2( d_y, 1 - d_z )
38998			];
38999
39000		}
39001
39002	}
39003
39004};
39005
39006function toJSON$1( shapes, options, data ) {
39007
39008	data.shapes = [];
39009
39010	if ( Array.isArray( shapes ) ) {
39011
39012		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
39013
39014			const shape = shapes[ i ];
39015
39016			data.shapes.push( shape.uuid );
39017
39018		}
39019
39020	} else {
39021
39022		data.shapes.push( shapes.uuid );
39023
39024	}
39025
39026	data.options = Object.assign( {}, options );
39027
39028	if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
39029
39030	return data;
39031
39032}
39033
39034class IcosahedronGeometry extends PolyhedronGeometry {
39035
39036	constructor( radius = 1, detail = 0 ) {
39037
39038		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
39039
39040		const vertices = [
39041			- 1, t, 0, 	1, t, 0, 	- 1, - t, 0, 	1, - t, 0,
39042			0, - 1, t, 	0, 1, t,	0, - 1, - t, 	0, 1, - t,
39043			t, 0, - 1, 	t, 0, 1, 	- t, 0, - 1, 	- t, 0, 1
39044		];
39045
39046		const indices = [
39047			0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
39048			1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
39049			3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
39050			4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
39051		];
39052
39053		super( vertices, indices, radius, detail );
39054
39055		this.type = 'IcosahedronGeometry';
39056
39057		this.parameters = {
39058			radius: radius,
39059			detail: detail
39060		};
39061
39062	}
39063
39064	static fromJSON( data ) {
39065
39066		return new IcosahedronGeometry( data.radius, data.detail );
39067
39068	}
39069
39070}
39071
39072class OctahedronGeometry extends PolyhedronGeometry {
39073
39074	constructor( radius = 1, detail = 0 ) {
39075
39076		const vertices = [
39077			1, 0, 0, 	- 1, 0, 0,	0, 1, 0,
39078			0, - 1, 0, 	0, 0, 1,	0, 0, - 1
39079		];
39080
39081		const indices = [
39082			0, 2, 4,	0, 4, 3,	0, 3, 5,
39083			0, 5, 2,	1, 2, 5,	1, 5, 3,
39084			1, 3, 4,	1, 4, 2
39085		];
39086
39087		super( vertices, indices, radius, detail );
39088
39089		this.type = 'OctahedronGeometry';
39090
39091		this.parameters = {
39092			radius: radius,
39093			detail: detail
39094		};
39095
39096	}
39097
39098	static fromJSON( data ) {
39099
39100		return new OctahedronGeometry( data.radius, data.detail );
39101
39102	}
39103
39104}
39105
39106class RingGeometry extends BufferGeometry {
39107
39108	constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
39109
39110		super();
39111
39112		this.type = 'RingGeometry';
39113
39114		this.parameters = {
39115			innerRadius: innerRadius,
39116			outerRadius: outerRadius,
39117			thetaSegments: thetaSegments,
39118			phiSegments: phiSegments,
39119			thetaStart: thetaStart,
39120			thetaLength: thetaLength
39121		};
39122
39123		thetaSegments = Math.max( 3, thetaSegments );
39124		phiSegments = Math.max( 1, phiSegments );
39125
39126		// buffers
39127
39128		const indices = [];
39129		const vertices = [];
39130		const normals = [];
39131		const uvs = [];
39132
39133		// some helper variables
39134
39135		let radius = innerRadius;
39136		const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
39137		const vertex = new Vector3();
39138		const uv = new Vector2();
39139
39140		// generate vertices, normals and uvs
39141
39142		for ( let j = 0; j <= phiSegments; j ++ ) {
39143
39144			for ( let i = 0; i <= thetaSegments; i ++ ) {
39145
39146				// values are generate from the inside of the ring to the outside
39147
39148				const segment = thetaStart + i / thetaSegments * thetaLength;
39149
39150				// vertex
39151
39152				vertex.x = radius * Math.cos( segment );
39153				vertex.y = radius * Math.sin( segment );
39154
39155				vertices.push( vertex.x, vertex.y, vertex.z );
39156
39157				// normal
39158
39159				normals.push( 0, 0, 1 );
39160
39161				// uv
39162
39163				uv.x = ( vertex.x / outerRadius + 1 ) / 2;
39164				uv.y = ( vertex.y / outerRadius + 1 ) / 2;
39165
39166				uvs.push( uv.x, uv.y );
39167
39168			}
39169
39170			// increase the radius for next row of vertices
39171
39172			radius += radiusStep;
39173
39174		}
39175
39176		// indices
39177
39178		for ( let j = 0; j < phiSegments; j ++ ) {
39179
39180			const thetaSegmentLevel = j * ( thetaSegments + 1 );
39181
39182			for ( let i = 0; i < thetaSegments; i ++ ) {
39183
39184				const segment = i + thetaSegmentLevel;
39185
39186				const a = segment;
39187				const b = segment + thetaSegments + 1;
39188				const c = segment + thetaSegments + 2;
39189				const d = segment + 1;
39190
39191				// faces
39192
39193				indices.push( a, b, d );
39194				indices.push( b, c, d );
39195
39196			}
39197
39198		}
39199
39200		// build geometry
39201
39202		this.setIndex( indices );
39203		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
39204		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39205		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39206
39207	}
39208
39209	copy( source ) {
39210
39211		super.copy( source );
39212
39213		this.parameters = Object.assign( {}, source.parameters );
39214
39215		return this;
39216
39217	}
39218
39219	static fromJSON( data ) {
39220
39221		return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength );
39222
39223	}
39224
39225}
39226
39227class ShapeGeometry extends BufferGeometry {
39228
39229	constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) {
39230
39231		super();
39232
39233		this.type = 'ShapeGeometry';
39234
39235		this.parameters = {
39236			shapes: shapes,
39237			curveSegments: curveSegments
39238		};
39239
39240		// buffers
39241
39242		const indices = [];
39243		const vertices = [];
39244		const normals = [];
39245		const uvs = [];
39246
39247		// helper variables
39248
39249		let groupStart = 0;
39250		let groupCount = 0;
39251
39252		// allow single and array values for "shapes" parameter
39253
39254		if ( Array.isArray( shapes ) === false ) {
39255
39256			addShape( shapes );
39257
39258		} else {
39259
39260			for ( let i = 0; i < shapes.length; i ++ ) {
39261
39262				addShape( shapes[ i ] );
39263
39264				this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
39265
39266				groupStart += groupCount;
39267				groupCount = 0;
39268
39269			}
39270
39271		}
39272
39273		// build geometry
39274
39275		this.setIndex( indices );
39276		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,878 bytes, lines 39277-39523
39277		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39278		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39279
39280
39281		// helper functions
39282
39283		function addShape( shape ) {
39284
39285			const indexOffset = vertices.length / 3;
39286			const points = shape.extractPoints( curveSegments );
39287
39288			let shapeVertices = points.shape;
39289			const shapeHoles = points.holes;
39290
39291			// check direction of vertices
39292
39293			if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
39294
39295				shapeVertices = shapeVertices.reverse();
39296
39297			}
39298
39299			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
39300
39301				const shapeHole = shapeHoles[ i ];
39302
39303				if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
39304
39305					shapeHoles[ i ] = shapeHole.reverse();
39306
39307				}
39308
39309			}
39310
39311			const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
39312
39313			// join vertices of inner and outer paths to a single array
39314
39315			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
39316
39317				const shapeHole = shapeHoles[ i ];
39318				shapeVertices = shapeVertices.concat( shapeHole );
39319
39320			}
39321
39322			// vertices, normals, uvs
39323
39324			for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
39325
39326				const vertex = shapeVertices[ i ];
39327
39328				vertices.push( vertex.x, vertex.y, 0 );
39329				normals.push( 0, 0, 1 );
39330				uvs.push( vertex.x, vertex.y ); // world uvs
39331
39332			}
39333
39334			// indices
39335
39336			for ( let i = 0, l = faces.length; i < l; i ++ ) {
39337
39338				const face = faces[ i ];
39339
39340				const a = face[ 0 ] + indexOffset;
39341				const b = face[ 1 ] + indexOffset;
39342				const c = face[ 2 ] + indexOffset;
39343
39344				indices.push( a, b, c );
39345				groupCount += 3;
39346
39347			}
39348
39349		}
39350
39351	}
39352
39353	copy( source ) {
39354
39355		super.copy( source );
39356
39357		this.parameters = Object.assign( {}, source.parameters );
39358
39359		return this;
39360
39361	}
39362
39363	toJSON() {
39364
39365		const data = super.toJSON();
39366
39367		const shapes = this.parameters.shapes;
39368
39369		return toJSON( shapes, data );
39370
39371	}
39372
39373	static fromJSON( data, shapes ) {
39374
39375		const geometryShapes = [];
39376
39377		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
39378
39379			const shape = shapes[ data.shapes[ j ] ];
39380
39381			geometryShapes.push( shape );
39382
39383		}
39384
39385		return new ShapeGeometry( geometryShapes, data.curveSegments );
39386
39387	}
39388
39389}
39390
39391function toJSON( shapes, data ) {
39392
39393	data.shapes = [];
39394
39395	if ( Array.isArray( shapes ) ) {
39396
39397		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
39398
39399			const shape = shapes[ i ];
39400
39401			data.shapes.push( shape.uuid );
39402
39403		}
39404
39405	} else {
39406
39407		data.shapes.push( shapes.uuid );
39408
39409	}
39410
39411	return data;
39412
39413}
39414
39415class SphereGeometry extends BufferGeometry {
39416
39417	constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
39418
39419		super();
39420
39421		this.type = 'SphereGeometry';
39422
39423		this.parameters = {
39424			radius: radius,
39425			widthSegments: widthSegments,
39426			heightSegments: heightSegments,
39427			phiStart: phiStart,
39428			phiLength: phiLength,
39429			thetaStart: thetaStart,
39430			thetaLength: thetaLength
39431		};
39432
39433		widthSegments = Math.max( 3, Math.floor( widthSegments ) );
39434		heightSegments = Math.max( 2, Math.floor( heightSegments ) );
39435
39436		const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
39437
39438		let index = 0;
39439		const grid = [];
39440
39441		const vertex = new Vector3();
39442		const normal = new Vector3();
39443
39444		// buffers
39445
39446		const indices = [];
39447		const vertices = [];
39448		const normals = [];
39449		const uvs = [];
39450
39451		// generate vertices, normals and uvs
39452
39453		for ( let iy = 0; iy <= heightSegments; iy ++ ) {
39454
39455			const verticesRow = [];
39456
39457			const v = iy / heightSegments;
39458
39459			// special case for the poles
39460
39461			let uOffset = 0;
39462
39463			if ( iy === 0 && thetaStart === 0 ) {
39464
39465				uOffset = 0.5 / widthSegments;
39466
39467			} else if ( iy === heightSegments && thetaEnd === Math.PI ) {
39468
39469				uOffset = - 0.5 / widthSegments;
39470
39471			}
39472
39473			for ( let ix = 0; ix <= widthSegments; ix ++ ) {
39474
39475				const u = ix / widthSegments;
39476
39477				// vertex
39478
39479				vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
39480				vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
39481				vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
39482
39483				vertices.push( vertex.x, vertex.y, vertex.z );
39484
39485				// normal
39486
39487				normal.copy( vertex ).normalize();
39488				normals.push( normal.x, normal.y, normal.z );
39489
39490				// uv
39491
39492				uvs.push( u + uOffset, 1 - v );
39493
39494				verticesRow.push( index ++ );
39495
39496			}
39497
39498			grid.push( verticesRow );
39499
39500		}
39501
39502		// indices
39503
39504		for ( let iy = 0; iy < heightSegments; iy ++ ) {
39505
39506			for ( let ix = 0; ix < widthSegments; ix ++ ) {
39507
39508				const a = grid[ iy ][ ix + 1 ];
39509				const b = grid[ iy ][ ix ];
39510				const c = grid[ iy + 1 ][ ix ];
39511				const d = grid[ iy + 1 ][ ix + 1 ];
39512
39513				if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
39514				if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
39515
39516			}
39517
39518		}
39519
39520		// build geometry
39521
39522		this.setIndex( indices );
39523		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 6,566 bytes, lines 39524-39816
39524		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39525		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39526
39527	}
39528
39529	copy( source ) {
39530
39531		super.copy( source );
39532
39533		this.parameters = Object.assign( {}, source.parameters );
39534
39535		return this;
39536
39537	}
39538
39539	static fromJSON( data ) {
39540
39541		return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength );
39542
39543	}
39544
39545}
39546
39547class TetrahedronGeometry extends PolyhedronGeometry {
39548
39549	constructor( radius = 1, detail = 0 ) {
39550
39551		const vertices = [
39552			1, 1, 1, 	- 1, - 1, 1, 	- 1, 1, - 1, 	1, - 1, - 1
39553		];
39554
39555		const indices = [
39556			2, 1, 0, 	0, 3, 2,	1, 3, 0,	2, 3, 1
39557		];
39558
39559		super( vertices, indices, radius, detail );
39560
39561		this.type = 'TetrahedronGeometry';
39562
39563		this.parameters = {
39564			radius: radius,
39565			detail: detail
39566		};
39567
39568	}
39569
39570	static fromJSON( data ) {
39571
39572		return new TetrahedronGeometry( data.radius, data.detail );
39573
39574	}
39575
39576}
39577
39578class TorusGeometry extends BufferGeometry {
39579
39580	constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) {
39581
39582		super();
39583
39584		this.type = 'TorusGeometry';
39585
39586		this.parameters = {
39587			radius: radius,
39588			tube: tube,
39589			radialSegments: radialSegments,
39590			tubularSegments: tubularSegments,
39591			arc: arc
39592		};
39593
39594		radialSegments = Math.floor( radialSegments );
39595		tubularSegments = Math.floor( tubularSegments );
39596
39597		// buffers
39598
39599		const indices = [];
39600		const vertices = [];
39601		const normals = [];
39602		const uvs = [];
39603
39604		// helper variables
39605
39606		const center = new Vector3();
39607		const vertex = new Vector3();
39608		const normal = new Vector3();
39609
39610		// generate vertices, normals and uvs
39611
39612		for ( let j = 0; j <= radialSegments; j ++ ) {
39613
39614			for ( let i = 0; i <= tubularSegments; i ++ ) {
39615
39616				const u = i / tubularSegments * arc;
39617				const v = j / radialSegments * Math.PI * 2;
39618
39619				// vertex
39620
39621				vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
39622				vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
39623				vertex.z = tube * Math.sin( v );
39624
39625				vertices.push( vertex.x, vertex.y, vertex.z );
39626
39627				// normal
39628
39629				center.x = radius * Math.cos( u );
39630				center.y = radius * Math.sin( u );
39631				normal.subVectors( vertex, center ).normalize();
39632
39633				normals.push( normal.x, normal.y, normal.z );
39634
39635				// uv
39636
39637				uvs.push( i / tubularSegments );
39638				uvs.push( j / radialSegments );
39639
39640			}
39641
39642		}
39643
39644		// generate indices
39645
39646		for ( let j = 1; j <= radialSegments; j ++ ) {
39647
39648			for ( let i = 1; i <= tubularSegments; i ++ ) {
39649
39650				// indices
39651
39652				const a = ( tubularSegments + 1 ) * j + i - 1;
39653				const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
39654				const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
39655				const d = ( tubularSegments + 1 ) * j + i;
39656
39657				// faces
39658
39659				indices.push( a, b, d );
39660				indices.push( b, c, d );
39661
39662			}
39663
39664		}
39665
39666		// build geometry
39667
39668		this.setIndex( indices );
39669		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
39670		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39671		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39672
39673	}
39674
39675	copy( source ) {
39676
39677		super.copy( source );
39678
39679		this.parameters = Object.assign( {}, source.parameters );
39680
39681		return this;
39682
39683	}
39684
39685	static fromJSON( data ) {
39686
39687		return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc );
39688
39689	}
39690
39691}
39692
39693class TorusKnotGeometry extends BufferGeometry {
39694
39695	constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
39696
39697		super();
39698
39699		this.type = 'TorusKnotGeometry';
39700
39701		this.parameters = {
39702			radius: radius,
39703			tube: tube,
39704			tubularSegments: tubularSegments,
39705			radialSegments: radialSegments,
39706			p: p,
39707			q: q
39708		};
39709
39710		tubularSegments = Math.floor( tubularSegments );
39711		radialSegments = Math.floor( radialSegments );
39712
39713		// buffers
39714
39715		const indices = [];
39716		const vertices = [];
39717		const normals = [];
39718		const uvs = [];
39719
39720		// helper variables
39721
39722		const vertex = new Vector3();
39723		const normal = new Vector3();
39724
39725		const P1 = new Vector3();
39726		const P2 = new Vector3();
39727
39728		const B = new Vector3();
39729		const T = new Vector3();
39730		const N = new Vector3();
39731
39732		// generate vertices, normals and uvs
39733
39734		for ( let i = 0; i <= tubularSegments; ++ i ) {
39735
39736			// the radian "u" is used to calculate the position on the torus curve of the current tubular segment
39737
39738			const u = i / tubularSegments * p * Math.PI * 2;
39739
39740			// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
39741			// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
39742
39743			calculatePositionOnCurve( u, p, q, radius, P1 );
39744			calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
39745
39746			// calculate orthonormal basis
39747
39748			T.subVectors( P2, P1 );
39749			N.addVectors( P2, P1 );
39750			B.crossVectors( T, N );
39751			N.crossVectors( B, T );
39752
39753			// normalize B, N. T can be ignored, we don't use it
39754
39755			B.normalize();
39756			N.normalize();
39757
39758			for ( let j = 0; j <= radialSegments; ++ j ) {
39759
39760				// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
39761				// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
39762
39763				const v = j / radialSegments * Math.PI * 2;
39764				const cx = - tube * Math.cos( v );
39765				const cy = tube * Math.sin( v );
39766
39767				// now calculate the final vertex position.
39768				// first we orient the extrusion with our basis vectors, then we add it to the current position on the curve
39769
39770				vertex.x = P1.x + ( cx * N.x + cy * B.x );
39771				vertex.y = P1.y + ( cx * N.y + cy * B.y );
39772				vertex.z = P1.z + ( cx * N.z + cy * B.z );
39773
39774				vertices.push( vertex.x, vertex.y, vertex.z );
39775
39776				// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
39777
39778				normal.subVectors( vertex, P1 ).normalize();
39779
39780				normals.push( normal.x, normal.y, normal.z );
39781
39782				// uv
39783
39784				uvs.push( i / tubularSegments );
39785				uvs.push( j / radialSegments );
39786
39787			}
39788
39789		}
39790
39791		// generate indices
39792
39793		for ( let j = 1; j <= tubularSegments; j ++ ) {
39794
39795			for ( let i = 1; i <= radialSegments; i ++ ) {
39796
39797				// indices
39798
39799				const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
39800				const b = ( radialSegments + 1 ) * j + ( i - 1 );
39801				const c = ( radialSegments + 1 ) * j + i;
39802				const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
39803
39804				// faces
39805
39806				indices.push( a, b, d );
39807				indices.push( b, c, d );
39808
39809			}
39810
39811		}
39812
39813		// build geometry
39814
39815		this.setIndex( indices );
39816		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 7,450 bytes, lines 39817-40175
39817		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39818		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39819
39820		// this function calculates the current position on the torus curve
39821
39822		function calculatePositionOnCurve( u, p, q, radius, position ) {
39823
39824			const cu = Math.cos( u );
39825			const su = Math.sin( u );
39826			const quOverP = q / p * u;
39827			const cs = Math.cos( quOverP );
39828
39829			position.x = radius * ( 2 + cs ) * 0.5 * cu;
39830			position.y = radius * ( 2 + cs ) * su * 0.5;
39831			position.z = radius * Math.sin( quOverP ) * 0.5;
39832
39833		}
39834
39835	}
39836
39837	copy( source ) {
39838
39839		super.copy( source );
39840
39841		this.parameters = Object.assign( {}, source.parameters );
39842
39843		return this;
39844
39845	}
39846
39847	static fromJSON( data ) {
39848
39849		return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q );
39850
39851	}
39852
39853}
39854
39855class TubeGeometry extends BufferGeometry {
39856
39857	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 ) {
39858
39859		super();
39860
39861		this.type = 'TubeGeometry';
39862
39863		this.parameters = {
39864			path: path,
39865			tubularSegments: tubularSegments,
39866			radius: radius,
39867			radialSegments: radialSegments,
39868			closed: closed
39869		};
39870
39871		const frames = path.computeFrenetFrames( tubularSegments, closed );
39872
39873		// expose internals
39874
39875		this.tangents = frames.tangents;
39876		this.normals = frames.normals;
39877		this.binormals = frames.binormals;
39878
39879		// helper variables
39880
39881		const vertex = new Vector3();
39882		const normal = new Vector3();
39883		const uv = new Vector2();
39884		let P = new Vector3();
39885
39886		// buffer
39887
39888		const vertices = [];
39889		const normals = [];
39890		const uvs = [];
39891		const indices = [];
39892
39893		// create buffer data
39894
39895		generateBufferData();
39896
39897		// build geometry
39898
39899		this.setIndex( indices );
39900		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
39901		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39902		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39903
39904		// functions
39905
39906		function generateBufferData() {
39907
39908			for ( let i = 0; i < tubularSegments; i ++ ) {
39909
39910				generateSegment( i );
39911
39912			}
39913
39914			// if the geometry is not closed, generate the last row of vertices and normals
39915			// at the regular position on the given path
39916			//
39917			// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
39918
39919			generateSegment( ( closed === false ) ? tubularSegments : 0 );
39920
39921			// uvs are generated in a separate function.
39922			// this makes it easy compute correct values for closed geometries
39923
39924			generateUVs();
39925
39926			// finally create faces
39927
39928			generateIndices();
39929
39930		}
39931
39932		function generateSegment( i ) {
39933
39934			// we use getPointAt to sample evenly distributed points from the given path
39935
39936			P = path.getPointAt( i / tubularSegments, P );
39937
39938			// retrieve corresponding normal and binormal
39939
39940			const N = frames.normals[ i ];
39941			const B = frames.binormals[ i ];
39942
39943			// generate normals and vertices for the current segment
39944
39945			for ( let j = 0; j <= radialSegments; j ++ ) {
39946
39947				const v = j / radialSegments * Math.PI * 2;
39948
39949				const sin = Math.sin( v );
39950				const cos = - Math.cos( v );
39951
39952				// normal
39953
39954				normal.x = ( cos * N.x + sin * B.x );
39955				normal.y = ( cos * N.y + sin * B.y );
39956				normal.z = ( cos * N.z + sin * B.z );
39957				normal.normalize();
39958
39959				normals.push( normal.x, normal.y, normal.z );
39960
39961				// vertex
39962
39963				vertex.x = P.x + radius * normal.x;
39964				vertex.y = P.y + radius * normal.y;
39965				vertex.z = P.z + radius * normal.z;
39966
39967				vertices.push( vertex.x, vertex.y, vertex.z );
39968
39969			}
39970
39971		}
39972
39973		function generateIndices() {
39974
39975			for ( let j = 1; j <= tubularSegments; j ++ ) {
39976
39977				for ( let i = 1; i <= radialSegments; i ++ ) {
39978
39979					const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
39980					const b = ( radialSegments + 1 ) * j + ( i - 1 );
39981					const c = ( radialSegments + 1 ) * j + i;
39982					const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
39983
39984					// faces
39985
39986					indices.push( a, b, d );
39987					indices.push( b, c, d );
39988
39989				}
39990
39991			}
39992
39993		}
39994
39995		function generateUVs() {
39996
39997			for ( let i = 0; i <= tubularSegments; i ++ ) {
39998
39999				for ( let j = 0; j <= radialSegments; j ++ ) {
40000
40001					uv.x = i / tubularSegments;
40002					uv.y = j / radialSegments;
40003
40004					uvs.push( uv.x, uv.y );
40005
40006				}
40007
40008			}
40009
40010		}
40011
40012	}
40013
40014	copy( source ) {
40015
40016		super.copy( source );
40017
40018		this.parameters = Object.assign( {}, source.parameters );
40019
40020		return this;
40021
40022	}
40023
40024	toJSON() {
40025
40026		const data = super.toJSON();
40027
40028		data.path = this.parameters.path.toJSON();
40029
40030		return data;
40031
40032	}
40033
40034	static fromJSON( data ) {
40035
40036		// This only works for built-in curves (e.g. CatmullRomCurve3).
40037		// User defined curves or instances of CurvePath will not be deserialized.
40038		return new TubeGeometry(
40039			new Curves[ data.path.type ]().fromJSON( data.path ),
40040			data.tubularSegments,
40041			data.radius,
40042			data.radialSegments,
40043			data.closed
40044		);
40045
40046	}
40047
40048}
40049
40050class WireframeGeometry extends BufferGeometry {
40051
40052	constructor( geometry = null ) {
40053
40054		super();
40055
40056		this.type = 'WireframeGeometry';
40057
40058		this.parameters = {
40059			geometry: geometry
40060		};
40061
40062		if ( geometry !== null ) {
40063
40064			// buffer
40065
40066			const vertices = [];
40067			const edges = new Set();
40068
40069			// helper variables
40070
40071			const start = new Vector3();
40072			const end = new Vector3();
40073
40074			if ( geometry.index !== null ) {
40075
40076				// indexed BufferGeometry
40077
40078				const position = geometry.attributes.position;
40079				const indices = geometry.index;
40080				let groups = geometry.groups;
40081
40082				if ( groups.length === 0 ) {
40083
40084					groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
40085
40086				}
40087
40088				// create a data structure that contains all edges without duplicates
40089
40090				for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
40091
40092					const group = groups[ o ];
40093
40094					const groupStart = group.start;
40095					const groupCount = group.count;
40096
40097					for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) {
40098
40099						for ( let j = 0; j < 3; j ++ ) {
40100
40101							const index1 = indices.getX( i + j );
40102							const index2 = indices.getX( i + ( j + 1 ) % 3 );
40103
40104							start.fromBufferAttribute( position, index1 );
40105							end.fromBufferAttribute( position, index2 );
40106
40107							if ( isUniqueEdge( start, end, edges ) === true ) {
40108
40109								vertices.push( start.x, start.y, start.z );
40110								vertices.push( end.x, end.y, end.z );
40111
40112							}
40113
40114						}
40115
40116					}
40117
40118				}
40119
40120			} else {
40121
40122				// non-indexed BufferGeometry
40123
40124				const position = geometry.attributes.position;
40125
40126				for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
40127
40128					for ( let j = 0; j < 3; j ++ ) {
40129
40130						// three edges per triangle, an edge is represented as (index1, index2)
40131						// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
40132
40133						const index1 = 3 * i + j;
40134						const index2 = 3 * i + ( ( j + 1 ) % 3 );
40135
40136						start.fromBufferAttribute( position, index1 );
40137						end.fromBufferAttribute( position, index2 );
40138
40139						if ( isUniqueEdge( start, end, edges ) === true ) {
40140
40141							vertices.push( start.x, start.y, start.z );
40142							vertices.push( end.x, end.y, end.z );
40143
40144						}
40145
40146					}
40147
40148				}
40149
40150			}
40151
40152			// build geometry
40153
40154			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
40155
40156		}
40157
40158	}
40159
40160	copy( source ) {
40161
40162		super.copy( source );
40163
40164		this.parameters = Object.assign( {}, source.parameters );
40165
40166		return this;
40167
40168	}
40169
40170}
40171
40172function isUniqueEdge( start, end, edges ) {
40173
40174	const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`;
40175	const hash2 = `${end.x}
40175,${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge
40176
40177	if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) {
40178
40179		return false;
40180
40181	} else {
40182
40183		edges.add( hash1 );
40184		edges.add( hash2 );
40185		return true;
40186
40187	}
40188
40189}
40190
40191var Geometries = /*#__PURE__*/Object.freeze({
40192	__proto__: null,
40193	BoxGeometry: BoxGeometry,
40194	CapsuleGeometry: CapsuleGeometry,
40195	CircleGeometry: CircleGeometry,
40196	ConeGeometry: ConeGeometry,
40197	CylinderGeometry: CylinderGeometry,
40198	DodecahedronGeometry: DodecahedronGeometry,
40199	EdgesGeometry: EdgesGeometry,
40200	ExtrudeGeometry: ExtrudeGeometry,
40201	IcosahedronGeometry: IcosahedronGeometry,
40202	LatheGeometry: LatheGeometry,
40203	OctahedronGeometry: OctahedronGeometry,
40204	PlaneGeometry: PlaneGeometry,
40205	PolyhedronGeometry: PolyhedronGeometry,
40206	RingGeometry: RingGeometry,
40207	ShapeGeometry: ShapeGeometry,
40208	SphereGeometry: SphereGeometry,
40209	TetrahedronGeometry: TetrahedronGeometry,
40210	TorusGeometry: TorusGeometry,
40211	TorusKnotGeometry: TorusKnotGeometry,
40212	TubeGeometry: TubeGeometry,
40213	WireframeGeometry: WireframeGeometry
40214});
40215
40216class ShadowMaterial extends Material {
40217
40218	constructor( parameters ) {
40219
40220		super();
40221
40222		this.isShadowMaterial = true;
40223
40224		this.type = 'ShadowMaterial';
40225
40226		this.color = new Color( 0x000000 );
40227		this.transparent = true;
40228
40229		this.fog = true;
40230
40231		this.setValues( parameters );
40232
40233	}
40234
40235	copy( source ) {
40236
40237		super.copy( source );
40238
40239		this.color.copy( source.color );
40240
40241		this.fog = source.fog;
40242
40243		return this;
40244
40245	}
40246
40247}
40248
40249class RawShaderMaterial extends ShaderMaterial {
40250
40251	constructor( parameters ) {
40252
40253		super( parameters );
40254
40255		this.isRawShaderMaterial = true;
40256
40257		this.type = 'RawShaderMaterial';
40258
40259	}
40260
40261}
40262
40263class MeshStandardMaterial extends Material {
40264
40265	constructor( parameters ) {
40266
40267		super();
40268
40269		this.isMeshStandardMaterial = true;
40270
40271		this.defines = { 'STANDARD': '' };
40272
40273		this.type = 'MeshStandardMaterial';
40274
40275		this.color = new Color( 0xffffff ); // diffuse
40276		this.roughness = 1.0;
40277		this.metalness = 0.0;
40278
40279		this.map = null;
40280
40281		this.lightMap = null;
40282		this.lightMapIntensity = 1.0;
40283
40284		this.aoMap = null;
40285		this.aoMapIntensity = 1.0;
40286
40287		this.emissive = new Color( 0x000000 );
40288		this.emissiveIntensity = 1.0;
40289		this.emissiveMap = null;
40290
40291		this.bumpMap = null;
40292		this.bumpScale = 1;
40293
40294		this.normalMap = null;
40295		this.normalMapType = TangentSpaceNormalMap;
40296		this.normalScale = new Vector2( 1, 1 );
40297
40298		this.displacementMap = null;
40299		this.displacementScale = 1;
40300		this.displacementBias = 0;
40301
40302		this.roughnessMap = null;
40303
40304		this.metalnessMap = null;
40305
40306		this.alphaMap = null;
40307
40308		this.envMap = null;
40309		this.envMapRotation = new Euler();
40310		this.envMapIntensity = 1.0;
40311
40312		this.wireframe = false;
40313		this.wireframeLinewidth = 1;
40314		this.wireframeLinecap = 'round';
40315		this.wireframeLinejoin = 'round';
40316
40317		this.flatShading = false;
40318
40319		this.fog = true;
40320
40321		this.setValues( parameters );
40322
40323	}
40324
40325	copy( source ) {
40326
40327		super.copy( source );
40328
40329		this.defines = { 'STANDARD': '' };
40330
40331		this.color.copy( source.color );
40332		this.roughness = source.roughness;
40333		this.metalness = source.metalness;
40334
40335		this.map = source.map;
40336
40337		this.lightMap = source.lightMap;
40338		this.lightMapIntensity = source.lightMapIntensity;
40339
40340		this.aoMap = source.aoMap;
40341		this.aoMapIntensity = source.aoMapIntensity;
40342
40343		this.emissive.copy( source.emissive );
40344		this.emissiveMap = source.emissiveMap;
40345		this.emissiveIntensity = source.emissiveIntensity;
40346
40347		this.bumpMap = source.bumpMap;
40348		this.bumpScale = source.bumpScale;
40349
40350		this.normalMap = source.normalMap;
40351		this.normalMapType = source.normalMapType;
40352		this.normalScale.copy( source.normalScale );
40353
40354		this.displacementMap = source.displacementMap;
40355		this.displacementScale = source.displacementScale;
40356		this.displacementBias = source.displacementBias;
40357
40358		this.roughnessMap = source.roughnessMap;
40359
40360		this.metalnessMap = source.metalnessMap;
40361
40362		this.alphaMap = source.alphaMap;
40363
40364		this.envMap = source.envMap;
40365		this.envMapRotation.copy( source.envMapRotation );
40366		this.envMapIntensity = source.envMapIntensity;
40367
40368		this.wireframe = source.wireframe;
40369		this.wireframeLinewidth = source.wireframeLinewidth;
40370		this.wireframeLinecap = source.wireframeLinecap;
40371		this.wireframeLinejoin = source.wireframeLinejoin;
40372
vendor: 5,146 bytes, lines 40373-40648
40373		this.flatShading = source.flatShading;
40374
40375		this.fog = source.fog;
40376
40377		return this;
40378
40379	}
40380
40381}
40382
40383class MeshPhysicalMaterial extends MeshStandardMaterial {
40384
40385	constructor( parameters ) {
40386
40387		super();
40388
40389		this.isMeshPhysicalMaterial = true;
40390
40391		this.defines = {
40392
40393			'STANDARD': '',
40394			'PHYSICAL': ''
40395
40396		};
40397
40398		this.type = 'MeshPhysicalMaterial';
40399
40400		this.anisotropyRotation = 0;
40401		this.anisotropyMap = null;
40402
40403		this.clearcoatMap = null;
40404		this.clearcoatRoughness = 0.0;
40405		this.clearcoatRoughnessMap = null;
40406		this.clearcoatNormalScale = new Vector2( 1, 1 );
40407		this.clearcoatNormalMap = null;
40408
40409		this.ior = 1.5;
40410
40411		Object.defineProperty( this, 'reflectivity', {
40412			get: function () {
40413
40414				return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) );
40415
40416			},
40417			set: function ( reflectivity ) {
40418
40419				this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity );
40420
40421			}
40422		} );
40423
40424		this.iridescenceMap = null;
40425		this.iridescenceIOR = 1.3;
40426		this.iridescenceThicknessRange = [ 100, 400 ];
40427		this.iridescenceThicknessMap = null;
40428
40429		this.sheenColor = new Color( 0x000000 );
40430		this.sheenColorMap = null;
40431		this.sheenRoughness = 1.0;
40432		this.sheenRoughnessMap = null;
40433
40434		this.transmissionMap = null;
40435
40436		this.thickness = 0;
40437		this.thicknessMap = null;
40438		this.attenuationDistance = Infinity;
40439		this.attenuationColor = new Color( 1, 1, 1 );
40440
40441		this.specularIntensity = 1.0;
40442		this.specularIntensityMap = null;
40443		this.specularColor = new Color( 1, 1, 1 );
40444		this.specularColorMap = null;
40445
40446		this._anisotropy = 0;
40447		this._clearcoat = 0;
40448		this._iridescence = 0;
40449		this._sheen = 0.0;
40450		this._transmission = 0;
40451
40452		this.setValues( parameters );
40453
40454	}
40455
40456	get anisotropy() {
40457
40458		return this._anisotropy;
40459
40460	}
40461
40462	set anisotropy( value ) {
40463
40464		if ( this._anisotropy > 0 !== value > 0 ) {
40465
40466			this.version ++;
40467
40468		}
40469
40470		this._anisotropy = value;
40471
40472	}
40473
40474	get clearcoat() {
40475
40476		return this._clearcoat;
40477
40478	}
40479
40480	set clearcoat( value ) {
40481
40482		if ( this._clearcoat > 0 !== value > 0 ) {
40483
40484			this.version ++;
40485
40486		}
40487
40488		this._clearcoat = value;
40489
40490	}
40491
40492	get iridescence() {
40493
40494		return this._iridescence;
40495
40496	}
40497
40498	set iridescence( value ) {
40499
40500		if ( this._iridescence > 0 !== value > 0 ) {
40501
40502			this.version ++;
40503
40504		}
40505
40506		this._iridescence = value;
40507
40508	}
40509
40510	get sheen() {
40511
40512		return this._sheen;
40513
40514	}
40515
40516	set sheen( value ) {
40517
40518		if ( this._sheen > 0 !== value > 0 ) {
40519
40520			this.version ++;
40521
40522		}
40523
40524		this._sheen = value;
40525
40526	}
40527
40528	get transmission() {
40529
40530		return this._transmission;
40531
40532	}
40533
40534	set transmission( value ) {
40535
40536		if ( this._transmission > 0 !== value > 0 ) {
40537
40538			this.version ++;
40539
40540		}
40541
40542		this._transmission = value;
40543
40544	}
40545
40546	copy( source ) {
40547
40548		super.copy( source );
40549
40550		this.defines = {
40551
40552			'STANDARD': '',
40553			'PHYSICAL': ''
40554
40555		};
40556
40557		this.anisotropy = source.anisotropy;
40558		this.anisotropyRotation = source.anisotropyRotation;
40559		this.anisotropyMap = source.anisotropyMap;
40560
40561		this.clearcoat = source.clearcoat;
40562		this.clearcoatMap = source.clearcoatMap;
40563		this.clearcoatRoughness = source.clearcoatRoughness;
40564		this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
40565		this.clearcoatNormalMap = source.clearcoatNormalMap;
40566		this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
40567
40568		this.ior = source.ior;
40569
40570		this.iridescence = source.iridescence;
40571		this.iridescenceMap = source.iridescenceMap;
40572		this.iridescenceIOR = source.iridescenceIOR;
40573		this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ];
40574		this.iridescenceThicknessMap = source.iridescenceThicknessMap;
40575
40576		this.sheen = source.sheen;
40577		this.sheenColor.copy( source.sheenColor );
40578		this.sheenColorMap = source.sheenColorMap;
40579		this.sheenRoughness = source.sheenRoughness;
40580		this.sheenRoughnessMap = source.sheenRoughnessMap;
40581
40582		this.transmission = source.transmission;
40583		this.transmissionMap = source.transmissionMap;
40584
40585		this.thickness = source.thickness;
40586		this.thicknessMap = source.thicknessMap;
40587		this.attenuationDistance = source.attenuationDistance;
40588		this.attenuationColor.copy( source.attenuationColor );
40589
40590		this.specularIntensity = source.specularIntensity;
40591		this.specularIntensityMap = source.specularIntensityMap;
40592		this.specularColor.copy( source.specularColor );
40593		this.specularColorMap = source.specularColorMap;
40594
40595		return this;
40596
40597	}
40598
40599}
40600
40601class MeshPhongMaterial extends Material {
40602
40603	constructor( parameters ) {
40604
40605		super();
40606
40607		this.isMeshPhongMaterial = true;
40608
40609		this.type = 'MeshPhongMaterial';
40610
40611		this.color = new Color( 0xffffff ); // diffuse
40612		this.specular = new Color( 0x111111 );
40613		this.shininess = 30;
40614
40615		this.map = null;
40616
40617		this.lightMap = null;
40618		this.lightMapIntensity = 1.0;
40619
40620		this.aoMap = null;
40621		this.aoMapIntensity = 1.0;
40622
40623		this.emissive = new Color( 0x000000 );
40624		this.emissiveIntensity = 1.0;
40625		this.emissiveMap = null;
40626
40627		this.bumpMap = null;
40628		this.bumpScale = 1;
40629
40630		this.normalMap = null;
40631		this.normalMapType = TangentSpaceNormalMap;
40632		this.normalScale = new Vector2( 1, 1 );
40633
40634		this.displacementMap = null;
40635		this.displacementScale = 1;
40636		this.displacementBias = 0;
40637
40638		this.specularMap = null;
40639
40640		this.alphaMap = null;
40641
40642		this.envMap = null;
40643		this.envMapRotation = new Euler();
40644		this.combine = MultiplyOperation;
40645		this.reflectivity = 1;
40646		this.refractionRatio = 0.98;
40647
40648		this.wireframe = false;
40649		this.wireframeLinewidth = 1;
40650		this.wireframeLinecap = 'round';
40651		this.wireframeLinejoin = 'round';
40652
40653		this.flatShading = false;
40654
40655		this.fog = true;
40656
40657		this.setValues( parameters );
40658
40659	}
40660
40661	copy( source ) {
40662
40663		super.copy( source );
40664
40665		this.color.copy( source.color );
40666		this.specular.copy( source.specular );
40667		this.shininess = source.shininess;
40668
40669		this.map = source.map;
40670
40671		this.lightMap = source.lightMap;
40672		this.lightMapIntensity = source.lightMapIntensity;
40673
40674		this.aoMap = source.aoMap;
40675		this.aoMapIntensity = source.aoMapIntensity;
40676
40677		this.emissive.copy( source.emissive );
40678		this.emissiveMap = source.emissiveMap;
40679		this.emissiveIntensity = source.emissiveIntensity;
40680
40681		this.bumpMap = source.bumpMap;
40682		this.bumpScale = source.bumpScale;
40683
40684		this.normalMap = source.normalMap;
40685		this.normalMapType = source.normalMapType;
40686		this.normalScale.copy( source.normalScale );
40687
40688		this.displacementMap = source.displacementMap;
40689		this.displacementScale = source.displacementScale;
40690		this.displacementBias = source.displacementBias;
40691
40692		this.specularMap = source.specularMap;
40693
40694		this.alphaMap = source.alphaMap;
40695
40696		this.envMap = source.envMap;
40697		this.envMapRotation.copy( source.envMapRotation );
40698		this.combine = source.combine;
40699		this.reflectivity = source.reflectivity;
40700		this.refractionRatio = source.refractionRatio;
40701
40702		this.wireframe = source.wireframe;
40703		this.wireframeLinewidth = source.wireframeLinewidth;
40704		this.wireframeLinecap = source.wireframeLinecap;
40705		this.wireframeLinejoin = source.wireframeLinejoin;
40706
40707		this.flatShading = source.flatShading;
40708
40709		this.fog = source.fog;
40710
40711		return this;
40712
40713	}
40714
40715}
40716
40717class MeshToonMaterial extends Material {
40718
40719	constructor( parameters ) {
40720
40721		super();
40722
40723		this.isMeshToonMaterial = true;
40724
40725		this.defines = { 'TOON': '' };
40726
40727		this.type = 'MeshToonMaterial';
40728
40729		this.color = new Color( 0xffffff );
40730
40731		this.map = null;
40732		this.gradientMap = null;
40733
40734		this.lightMap = null;
40735		this.lightMapIntensity = 1.0;
40736
40737		this.aoMap = null;
40738		this.aoMapIntensity = 1.0;
40739
40740		this.emissive = new Color( 0x000000 );
40741		this.emissiveIntensity = 1.0;
40742		this.emissiveMap = null;
40743
40744		this.bumpMap = null;
40745		this.bumpScale = 1;
40746
40747		this.normalMap = null;
40748		this.normalMapType = TangentSpaceNormalMap;
40749		this.normalScale = new Vector2( 1, 1 );
40750
40751		this.displacementMap = null;
40752		this.displacementScale = 1;
40753		this.displacementBias = 0;
40754
40755		this.alphaMap = null;
40756
40757		this.wireframe = false;
40758		this.wireframeLinewidth = 1;
40759		this.wireframeLinecap = 'round';
40760		this.wireframeLinejoin = 'round';
40761
40762		this.fog = true;
40763
40764		this.setValues( parameters );
40765
40766	}
40767
40768	copy( source ) {
40769
40770		super.copy( source );
40771
40772		this.color.copy( source.color );
40773
40774		this.map = source.map;
40775		this.gradientMap = source.gradientMap;
40776
40777		this.lightMap = source.lightMap;
40778		this.lightMapIntensity = source.lightMapIntensity;
40779
40780		this.aoMap = source.aoMap;
40781		this.aoMapIntensity = source.aoMapIntensity;
40782
40783		this.emissive.copy( source.emissive );
40784		this.emissiveMap = source.emissiveMap;
40785		this.emissiveIntensity = source.emissiveIntensity;
40786
40787		this.bumpMap = source.bumpMap;
40788		this.bumpScale = source.bumpScale;
40789
40790		this.normalMap = source.normalMap;
40791		this.normalMapType = source.normalMapType;
40792		this.normalScale.copy( source.normalScale );
40793
40794		this.displacementMap = source.displacementMap;
40795		this.displacementScale = source.displacementScale;
40796		this.displacementBias = source.displacementBias;
40797
40798		this.alphaMap = source.alphaMap;
40799
40800		this.wireframe = source.wireframe;
40801		this.wireframeLinewidth = source.wireframeLinewidth;
40802		this.wireframeLinecap = source.wireframeLinecap;
40803		this.wireframeLinejoin = source.wireframeLinejoin;
40804
40805		this.fog = source.fog;
40806
40807		return this;
40808
40809	}
40810
40811}
40812
40813class MeshNormalMaterial extends Material {
40814
40815	constructor( parameters ) {
40816
40817		super();
40818
40819		this.isMeshNormalMaterial = true;
40820
40821		this.type = 'MeshNormalMaterial';
40822
40823		this.bumpMap = null;
40824		this.bumpScale = 1;
40825
40826		this.normalMap = null;
40827		this.normalMapType = TangentSpaceNormalMap;
40828		this.normalScale = new Vector2( 1, 1 );
40829
40830		this.displacementMap = null;
40831		this.displacementScale = 1;
40832		this.displacementBias = 0;
40833
40834		this.wireframe = false;
40835		this.wireframeLinewidth = 1;
40836
40837		this.flatShading = false;
vendor: 20,656 bytes, lines 40838-41878
40838
40839		this.setValues( parameters );
40840
40841	}
40842
40843	copy( source ) {
40844
40845		super.copy( source );
40846
40847		this.bumpMap = source.bumpMap;
40848		this.bumpScale = source.bumpScale;
40849
40850		this.normalMap = source.normalMap;
40851		this.normalMapType = source.normalMapType;
40852		this.normalScale.copy( source.normalScale );
40853
40854		this.displacementMap = source.displacementMap;
40855		this.displacementScale = source.displacementScale;
40856		this.displacementBias = source.displacementBias;
40857
40858		this.wireframe = source.wireframe;
40859		this.wireframeLinewidth = source.wireframeLinewidth;
40860
40861		this.flatShading = source.flatShading;
40862
40863		return this;
40864
40865	}
40866
40867}
40868
40869class MeshLambertMaterial extends Material {
40870
40871	constructor( parameters ) {
40872
40873		super();
40874
40875		this.isMeshLambertMaterial = true;
40876
40877		this.type = 'MeshLambertMaterial';
40878
40879		this.color = new Color( 0xffffff ); // diffuse
40880
40881		this.map = null;
40882
40883		this.lightMap = null;
40884		this.lightMapIntensity = 1.0;
40885
40886		this.aoMap = null;
40887		this.aoMapIntensity = 1.0;
40888
40889		this.emissive = new Color( 0x000000 );
40890		this.emissiveIntensity = 1.0;
40891		this.emissiveMap = null;
40892
40893		this.bumpMap = null;
40894		this.bumpScale = 1;
40895
40896		this.normalMap = null;
40897		this.normalMapType = TangentSpaceNormalMap;
40898		this.normalScale = new Vector2( 1, 1 );
40899
40900		this.displacementMap = null;
40901		this.displacementScale = 1;
40902		this.displacementBias = 0;
40903
40904		this.specularMap = null;
40905
40906		this.alphaMap = null;
40907
40908		this.envMap = null;
40909		this.envMapRotation = new Euler();
40910		this.combine = MultiplyOperation;
40911		this.reflectivity = 1;
40912		this.refractionRatio = 0.98;
40913
40914		this.wireframe = false;
40915		this.wireframeLinewidth = 1;
40916		this.wireframeLinecap = 'round';
40917		this.wireframeLinejoin = 'round';
40918
40919		this.flatShading = false;
40920
40921		this.fog = true;
40922
40923		this.setValues( parameters );
40924
40925	}
40926
40927	copy( source ) {
40928
40929		super.copy( source );
40930
40931		this.color.copy( source.color );
40932
40933		this.map = source.map;
40934
40935		this.lightMap = source.lightMap;
40936		this.lightMapIntensity = source.lightMapIntensity;
40937
40938		this.aoMap = source.aoMap;
40939		this.aoMapIntensity = source.aoMapIntensity;
40940
40941		this.emissive.copy( source.emissive );
40942		this.emissiveMap = source.emissiveMap;
40943		this.emissiveIntensity = source.emissiveIntensity;
40944
40945		this.bumpMap = source.bumpMap;
40946		this.bumpScale = source.bumpScale;
40947
40948		this.normalMap = source.normalMap;
40949		this.normalMapType = source.normalMapType;
40950		this.normalScale.copy( source.normalScale );
40951
40952		this.displacementMap = source.displacementMap;
40953		this.displacementScale = source.displacementScale;
40954		this.displacementBias = source.displacementBias;
40955
40956		this.specularMap = source.specularMap;
40957
40958		this.alphaMap = source.alphaMap;
40959
40960		this.envMap = source.envMap;
40961		this.envMapRotation.copy( source.envMapRotation );
40962		this.combine = source.combine;
40963		this.reflectivity = source.reflectivity;
40964		this.refractionRatio = source.refractionRatio;
40965
40966		this.wireframe = source.wireframe;
40967		this.wireframeLinewidth = source.wireframeLinewidth;
40968		this.wireframeLinecap = source.wireframeLinecap;
40969		this.wireframeLinejoin = source.wireframeLinejoin;
40970
40971		this.flatShading = source.flatShading;
40972
40973		this.fog = source.fog;
40974
40975		return this;
40976
40977	}
40978
40979}
40980
40981class MeshMatcapMaterial extends Material {
40982
40983	constructor( parameters ) {
40984
40985		super();
40986
40987		this.isMeshMatcapMaterial = true;
40988
40989		this.defines = { 'MATCAP': '' };
40990
40991		this.type = 'MeshMatcapMaterial';
40992
40993		this.color = new Color( 0xffffff ); // diffuse
40994
40995		this.matcap = null;
40996
40997		this.map = null;
40998
40999		this.bumpMap = null;
41000		this.bumpScale = 1;
41001
41002		this.normalMap = null;
41003		this.normalMapType = TangentSpaceNormalMap;
41004		this.normalScale = new Vector2( 1, 1 );
41005
41006		this.displacementMap = null;
41007		this.displacementScale = 1;
41008		this.displacementBias = 0;
41009
41010		this.alphaMap = null;
41011
41012		this.flatShading = false;
41013
41014		this.fog = true;
41015
41016		this.setValues( parameters );
41017
41018	}
41019
41020
41021	copy( source ) {
41022
41023		super.copy( source );
41024
41025		this.defines = { 'MATCAP': '' };
41026
41027		this.color.copy( source.color );
41028
41029		this.matcap = source.matcap;
41030
41031		this.map = source.map;
41032
41033		this.bumpMap = source.bumpMap;
41034		this.bumpScale = source.bumpScale;
41035
41036		this.normalMap = source.normalMap;
41037		this.normalMapType = source.normalMapType;
41038		this.normalScale.copy( source.normalScale );
41039
41040		this.displacementMap = source.displacementMap;
41041		this.displacementScale = source.displacementScale;
41042		this.displacementBias = source.displacementBias;
41043
41044		this.alphaMap = source.alphaMap;
41045
41046		this.flatShading = source.flatShading;
41047
41048		this.fog = source.fog;
41049
41050		return this;
41051
41052	}
41053
41054}
41055
41056class LineDashedMaterial extends LineBasicMaterial {
41057
41058	constructor( parameters ) {
41059
41060		super();
41061
41062		this.isLineDashedMaterial = true;
41063
41064		this.type = 'LineDashedMaterial';
41065
41066		this.scale = 1;
41067		this.dashSize = 3;
41068		this.gapSize = 1;
41069
41070		this.setValues( parameters );
41071
41072	}
41073
41074	copy( source ) {
41075
41076		super.copy( source );
41077
41078		this.scale = source.scale;
41079		this.dashSize = source.dashSize;
41080		this.gapSize = source.gapSize;
41081
41082		return this;
41083
41084	}
41085
41086}
41087
41088// converts an array to a specific type
41089function convertArray( array, type, forceClone ) {
41090
41091	if ( ! array || // let 'undefined' and 'null' pass
41092		! forceClone && array.constructor === type ) return array;
41093
41094	if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
41095
41096		return new type( array ); // create typed array
41097
41098	}
41099
41100	return Array.prototype.slice.call( array ); // create Array
41101
41102}
41103
41104function isTypedArray( object ) {
41105
41106	return ArrayBuffer.isView( object ) &&
41107		! ( object instanceof DataView );
41108
41109}
41110
41111// returns an array by which times and values can be sorted
41112function getKeyframeOrder( times ) {
41113
41114	function compareTime( i, j ) {
41115
41116		return times[ i ] - times[ j ];
41117
41118	}
41119
41120	const n = times.length;
41121	const result = new Array( n );
41122	for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
41123
41124	result.sort( compareTime );
41125
41126	return result;
41127
41128}
41129
41130// uses the array previously returned by 'getKeyframeOrder' to sort data
41131function sortedArray( values, stride, order ) {
41132
41133	const nValues = values.length;
41134	const result = new values.constructor( nValues );
41135
41136	for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
41137
41138		const srcOffset = order[ i ] * stride;
41139
41140		for ( let j = 0; j !== stride; ++ j ) {
41141
41142			result[ dstOffset ++ ] = values[ srcOffset + j ];
41143
41144		}
41145
41146	}
41147
41148	return result;
41149
41150}
41151
41152// function for parsing AOS keyframe formats
41153function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
41154
41155	let i = 1, key = jsonKeys[ 0 ];
41156
41157	while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
41158
41159		key = jsonKeys[ i ++ ];
41160
41161	}
41162
41163	if ( key === undefined ) return; // no data
41164
41165	let value = key[ valuePropertyName ];
41166	if ( value === undefined ) return; // no data
41167
41168	if ( Array.isArray( value ) ) {
41169
41170		do {
41171
41172			value = key[ valuePropertyName ];
41173
41174			if ( value !== undefined ) {
41175
41176				times.push( key.time );
41177				values.push.apply( values, value ); // push all elements
41178
41179			}
41180
41181			key = jsonKeys[ i ++ ];
41182
41183		} while ( key !== undefined );
41184
41185	} else if ( value.toArray !== undefined ) {
41186
41187		// ...assume THREE.Math-ish
41188
41189		do {
41190
41191			value = key[ valuePropertyName ];
41192
41193			if ( value !== undefined ) {
41194
41195				times.push( key.time );
41196				value.toArray( values, values.length );
41197
41198			}
41199
41200			key = jsonKeys[ i ++ ];
41201
41202		} while ( key !== undefined );
41203
41204	} else {
41205
41206		// otherwise push as-is
41207
41208		do {
41209
41210			value = key[ valuePropertyName ];
41211
41212			if ( value !== undefined ) {
41213
41214				times.push( key.time );
41215				values.push( value );
41216
41217			}
41218
41219			key = jsonKeys[ i ++ ];
41220
41221		} while ( key !== undefined );
41222
41223	}
41224
41225}
41226
41227function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
41228
41229	const clip = sourceClip.clone();
41230
41231	clip.name = name;
41232
41233	const tracks = [];
41234
41235	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41236
41237		const track = clip.tracks[ i ];
41238		const valueSize = track.getValueSize();
41239
41240		const times = [];
41241		const values = [];
41242
41243		for ( let j = 0; j < track.times.length; ++ j ) {
41244
41245			const frame = track.times[ j ] * fps;
41246
41247			if ( frame < startFrame || frame >= endFrame ) continue;
41248
41249			times.push( track.times[ j ] );
41250
41251			for ( let k = 0; k < valueSize; ++ k ) {
41252
41253				values.push( track.values[ j * valueSize + k ] );
41254
41255			}
41256
41257		}
41258
41259		if ( times.length === 0 ) continue;
41260
41261		track.times = convertArray( times, track.times.constructor );
41262		track.values = convertArray( values, track.values.constructor );
41263
41264		tracks.push( track );
41265
41266	}
41267
41268	clip.tracks = tracks;
41269
41270	// find minimum .times value across all tracks in the trimmed clip
41271
41272	let minStartTime = Infinity;
41273
41274	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41275
41276		if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
41277
41278			minStartTime = clip.tracks[ i ].times[ 0 ];
41279
41280		}
41281
41282	}
41283
41284	// shift all tracks such that clip begins at t=0
41285
41286	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41287
41288		clip.tracks[ i ].shift( - 1 * minStartTime );
41289
41290	}
41291
41292	clip.resetDuration();
41293
41294	return clip;
41295
41296}
41297
41298function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
41299
41300	if ( fps <= 0 ) fps = 30;
41301
41302	const numTracks = referenceClip.tracks.length;
41303	const referenceTime = referenceFrame / fps;
41304
41305	// Make each track's values relative to the values at the reference frame
41306	for ( let i = 0; i < numTracks; ++ i ) {
41307
41308		const referenceTrack = referenceClip.tracks[ i ];
41309		const referenceTrackType = referenceTrack.ValueTypeName;
41310
41311		// Skip this track if it's non-numeric
41312		if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
41313
41314		// Find the track in the target clip whose name and type matches the reference track
41315		const targetTrack = targetClip.tracks.find( function ( track ) {
41316
41317			return track.name === referenceTrack.name
41318				&& track.ValueTypeName === referenceTrackType;
41319
41320		} );
41321
41322		if ( targetTrack === undefined ) continue;
41323
41324		let referenceOffset = 0;
41325		const referenceValueSize = referenceTrack.getValueSize();
41326
41327		if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
41328
41329			referenceOffset = referenceValueSize / 3;
41330
41331		}
41332
41333		let targetOffset = 0;
41334		const targetValueSize = targetTrack.getValueSize();
41335
41336		if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
41337
41338			targetOffset = targetValueSize / 3;
41339
41340		}
41341
41342		const lastIndex = referenceTrack.times.length - 1;
41343		let referenceValue;
41344
41345		// Find the value to subtract out of the track
41346		if ( referenceTime <= referenceTrack.times[ 0 ] ) {
41347
41348			// Reference frame is earlier than the first keyframe, so just use the first keyframe
41349			const startIndex = referenceOffset;
41350			const endIndex = referenceValueSize - referenceOffset;
41351			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
41352
41353		} else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
41354
41355			// Reference frame is after the last keyframe, so just use the last keyframe
41356			const startIndex = lastIndex * referenceValueSize + referenceOffset;
41357			const endIndex = startIndex + referenceValueSize - referenceOffset;
41358			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
41359
41360		} else {
41361
41362			// Interpolate to the reference value
41363			const interpolant = referenceTrack.createInterpolant();
41364			const startIndex = referenceOffset;
41365			const endIndex = referenceValueSize - referenceOffset;
41366			interpolant.evaluate( referenceTime );
41367			referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex );
41368
41369		}
41370
41371		// Conjugate the quaternion
41372		if ( referenceTrackType === 'quaternion' ) {
41373
41374			const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
41375			referenceQuat.toArray( referenceValue );
41376
41377		}
41378
41379		// Subtract the reference value from all of the track values
41380
41381		const numTimes = targetTrack.times.length;
41382		for ( let j = 0; j < numTimes; ++ j ) {
41383
41384			const valueStart = j * targetValueSize + targetOffset;
41385
41386			if ( referenceTrackType === 'quaternion' ) {
41387
41388				// Multiply the conjugate for quaternion track types
41389				Quaternion.multiplyQuaternionsFlat(
41390					targetTrack.values,
41391					valueStart,
41392					referenceValue,
41393					0,
41394					targetTrack.values,
41395					valueStart
41396				);
41397
41398			} else {
41399
41400				const valueEnd = targetValueSize - targetOffset * 2;
41401
41402				// Subtract each value for all other numeric track types
41403				for ( let k = 0; k < valueEnd; ++ k ) {
41404
41405					targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
41406
41407				}
41408
41409			}
41410
41411		}
41412
41413	}
41414
41415	targetClip.blendMode = AdditiveAnimationBlendMode;
41416
41417	return targetClip;
41418
41419}
41420
41421const AnimationUtils = {
41422	convertArray: convertArray,
41423	isTypedArray: isTypedArray,
41424	getKeyframeOrder: getKeyframeOrder,
41425	sortedArray: sortedArray,
41426	flattenJSON: flattenJSON,
41427	subclip: subclip,
41428	makeClipAdditive: makeClipAdditive
41429};
41430
41431/**
41432 * Abstract base class of interpolants over parametric samples.
41433 *
41434 * The parameter domain is one dimensional, typically the time or a path
41435 * along a curve defined by the data.
41436 *
41437 * The sample values can have any dimensionality and derived classes may
41438 * apply special interpretations to the data.
41439 *
41440 * This class provides the interval seek in a Template Method, deferring
41441 * the actual interpolation to derived classes.
41442 *
41443 * Time complexity is O(1) for linear access crossing at most two points
41444 * and O(log N) for random access, where N is the number of positions.
41445 *
41446 * References:
41447 *
41448 * 		http://www.oodesign.com/template-method-pattern.html
41449 *
41450 */
41451
41452class Interpolant {
41453
41454	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41455
41456		this.parameterPositions = parameterPositions;
41457		this._cachedIndex = 0;
41458
41459		this.resultBuffer = resultBuffer !== undefined ?
41460			resultBuffer : new sampleValues.constructor( sampleSize );
41461		this.sampleValues = sampleValues;
41462		this.valueSize = sampleSize;
41463
41464		this.settings = null;
41465		this.DefaultSettings_ = {};
41466
41467	}
41468
41469	evaluate( t ) {
41470
41471		const pp = this.parameterPositions;
41472		let i1 = this._cachedIndex,
41473			t1 = pp[ i1 ],
41474			t0 = pp[ i1 - 1 ];
41475
41476		validate_interval: {
41477
41478			seek: {
41479
41480				let right;
41481
41482				linear_scan: {
41483
41484					//- See http://jsperf.com/comparison-to-undefined/3
41485					//- slower code:
41486					//-
41487					//- 				if ( t >= t1 || t1 === undefined ) {
41488					forward_scan: if ( ! ( t < t1 ) ) {
41489
41490						for ( let giveUpAt = i1 + 2; ; ) {
41491
41492							if ( t1 === undefined ) {
41493
41494								if ( t < t0 ) break forward_scan;
41495
41496								// after end
41497
41498								i1 = pp.length;
41499								this._cachedIndex = i1;
41500								return this.copySampleValue_( i1 - 1 );
41501
41502							}
41503
41504							if ( i1 === giveUpAt ) break; // this loop
41505
41506							t0 = t1;
41507							t1 = pp[ ++ i1 ];
41508
41509							if ( t < t1 ) {
41510
41511								// we have arrived at the sought interval
41512								break seek;
41513
41514							}
41515
41516						}
41517
41518						// prepare binary search on the right side of the index
41519						right = pp.length;
41520						break linear_scan;
41521
41522					}
41523
41524					//- slower code:
41525					//-					if ( t < t0 || t0 === undefined ) {
41526					if ( ! ( t >= t0 ) ) {
41527
41528						// looping?
41529
41530						const t1global = pp[ 1 ];
41531
41532						if ( t < t1global ) {
41533
41534							i1 = 2; // + 1, using the scan for the details
41535							t0 = t1global;
41536
41537						}
41538
41539						// linear reverse scan
41540
41541						for ( let giveUpAt = i1 - 2; ; ) {
41542
41543							if ( t0 === undefined ) {
41544
41545								// before start
41546
41547								this._cachedIndex = 0;
41548								return this.copySampleValue_( 0 );
41549
41550							}
41551
41552							if ( i1 === giveUpAt ) break; // this loop
41553
41554							t1 = t0;
41555							t0 = pp[ -- i1 - 1 ];
41556
41557							if ( t >= t0 ) {
41558
41559								// we have arrived at the sought interval
41560								break seek;
41561
41562							}
41563
41564						}
41565
41566						// prepare binary search on the left side of the index
41567						right = i1;
41568						i1 = 0;
41569						break linear_scan;
41570
41571					}
41572
41573					// the interval is valid
41574
41575					break validate_interval;
41576
41577				} // linear scan
41578
41579				// binary search
41580
41581				while ( i1 < right ) {
41582
41583					const mid = ( i1 + right ) >>> 1;
41584
41585					if ( t < pp[ mid ] ) {
41586
41587						right = mid;
41588
41589					} else {
41590
41591						i1 = mid + 1;
41592
41593					}
41594
41595				}
41596
41597				t1 = pp[ i1 ];
41598				t0 = pp[ i1 - 1 ];
41599
41600				// check boundary cases, again
41601
41602				if ( t0 === undefined ) {
41603
41604					this._cachedIndex = 0;
41605					return this.copySampleValue_( 0 );
41606
41607				}
41608
41609				if ( t1 === undefined ) {
41610
41611					i1 = pp.length;
41612					this._cachedIndex = i1;
41613					return this.copySampleValue_( i1 - 1 );
41614
41615				}
41616
41617			} // seek
41618
41619			this._cachedIndex = i1;
41620
41621			this.intervalChanged_( i1, t0, t1 );
41622
41623		} // validate_interval
41624
41625		return this.interpolate_( i1, t0, t, t1 );
41626
41627	}
41628
41629	getSettings_() {
41630
41631		return this.settings || this.DefaultSettings_;
41632
41633	}
41634
41635	copySampleValue_( index ) {
41636
41637		// copies a sample value to the result buffer
41638
41639		const result = this.resultBuffer,
41640			values = this.sampleValues,
41641			stride = this.valueSize,
41642			offset = index * stride;
41643
41644		for ( let i = 0; i !== stride; ++ i ) {
41645
41646			result[ i ] = values[ offset + i ];
41647
41648		}
41649
41650		return result;
41651
41652	}
41653
41654	// Template methods for derived classes:
41655
41656	interpolate_( /* i1, t0, t, t1 */ ) {
41657
41658		throw new Error( 'call to abstract method' );
41659		// implementations shall return this.resultBuffer
41660
41661	}
41662
41663	intervalChanged_( /* i1, t0, t1 */ ) {
41664
41665		// empty
41666
41667	}
41668
41669}
41670
41671/**
41672 * Fast and simple cubic spline interpolant.
41673 *
41674 * It was derived from a Hermitian construction setting the first derivative
41675 * at each sample position to the linear slope between neighboring positions
41676 * over their parameter interval.
41677 */
41678
41679class CubicInterpolant extends Interpolant {
41680
41681	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41682
41683		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
41684
41685		this._weightPrev = - 0;
41686		this._offsetPrev = - 0;
41687		this._weightNext = - 0;
41688		this._offsetNext = - 0;
41689
41690		this.DefaultSettings_ = {
41691
41692			endingStart: ZeroCurvatureEnding,
41693			endingEnd: ZeroCurvatureEnding
41694
41695		};
41696
41697	}
41698
41699	intervalChanged_( i1, t0, t1 ) {
41700
41701		const pp = this.parameterPositions;
41702		let iPrev = i1 - 2,
41703			iNext = i1 + 1,
41704
41705			tPrev = pp[ iPrev ],
41706			tNext = pp[ iNext ];
41707
41708		if ( tPrev === undefined ) {
41709
41710			switch ( this.getSettings_().endingStart ) {
41711
41712				case ZeroSlopeEnding:
41713
41714					// f'(t0) = 0
41715					iPrev = i1;
41716					tPrev = 2 * t0 - t1;
41717
41718					break;
41719
41720				case WrapAroundEnding:
41721
41722					// use the other end of the curve
41723					iPrev = pp.length - 2;
41724					tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
41725
41726					break;
41727
41728				default: // ZeroCurvatureEnding
41729
41730					// f''(t0) = 0 a.k.a. Natural Spline
41731					iPrev = i1;
41732					tPrev = t1;
41733
41734			}
41735
41736		}
41737
41738		if ( tNext === undefined ) {
41739
41740			switch ( this.getSettings_().endingEnd ) {
41741
41742				case ZeroSlopeEnding:
41743
41744					// f'(tN) = 0
41745					iNext = i1;
41746					tNext = 2 * t1 - t0;
41747
41748					break;
41749
41750				case WrapAroundEnding:
41751
41752					// use the other end of the curve
41753					iNext = 1;
41754					tNext = t1 + pp[ 1 ] - pp[ 0 ];
41755
41756					break;
41757
41758				default: // ZeroCurvatureEnding
41759
41760					// f''(tN) = 0, a.k.a. Natural Spline
41761					iNext = i1 - 1;
41762					tNext = t0;
41763
41764			}
41765
41766		}
41767
41768		const halfDt = ( t1 - t0 ) * 0.5,
41769			stride = this.valueSize;
41770
41771		this._weightPrev = halfDt / ( t0 - tPrev );
41772		this._weightNext = halfDt / ( tNext - t1 );
41773		this._offsetPrev = iPrev * stride;
41774		this._offsetNext = iNext * stride;
41775
41776	}
41777
41778	interpolate_( i1, t0, t, t1 ) {
41779
41780		const result = this.resultBuffer,
41781			values = this.sampleValues,
41782			stride = this.valueSize,
41783
41784			o1 = i1 * stride,		o0 = o1 - stride,
41785			oP = this._offsetPrev, 	oN = this._offsetNext,
41786			wP = this._weightPrev,	wN = this._weightNext,
41787
41788			p = ( t - t0 ) / ( t1 - t0 ),
41789			pp = p * p,
41790			ppp = pp * p;
41791
41792		// evaluate polynomials
41793
41794		const sP = - wP * ppp + 2 * wP * pp - wP * p;
41795		const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
41796		const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
41797		const sN = wN * ppp - wN * pp;
41798
41799		// combine data linearly
41800
41801		for ( let i = 0; i !== stride; ++ i ) {
41802
41803			result[ i ] =
41804					sP * values[ oP + i ] +
41805					s0 * values[ o0 + i ] +
41806					s1 * values[ o1 + i ] +
41807					sN * values[ oN + i ];
41808
41809		}
41810
41811		return result;
41812
41813	}
41814
41815}
41816
41817class LinearInterpolant extends Interpolant {
41818
41819	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41820
41821		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
41822
41823	}
41824
41825	interpolate_( i1, t0, t, t1 ) {
41826
41827		const result = this.resultBuffer,
41828			values = this.sampleValues,
41829			stride = this.valueSize,
41830
41831			offset1 = i1 * stride,
41832			offset0 = offset1 - stride,
41833
41834			weight1 = ( t - t0 ) / ( t1 - t0 ),
41835			weight0 = 1 - weight1;
41836
41837		for ( let i = 0; i !== stride; ++ i ) {
41838
41839			result[ i ] =
41840					values[ offset0 + i ] * weight0 +
41841					values[ offset1 + i ] * weight1;
41842
41843		}
41844
41845		return result;
41846
41847	}
41848
41849}
41850
41851/**
41852 *
41853 * Interpolant that evaluates to the sample value at the position preceding
41854 * the parameter.
41855 */
41856
41857class DiscreteInterpolant extends Interpolant {
41858
41859	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41860
41861		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
41862
41863	}
41864
41865	interpolate_( i1 /*, t0, t, t1 */ ) {
41866
41867		return this.copySampleValue_( i1 - 1 );
41868
41869	}
41870
41871}
41872
41873class KeyframeTrack {
41874
41875	constructor( name, times, values, interpolation ) {
41876
41877		if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
41878		if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 22,253 bytes, lines 41878-43068
41878ame );
41879
41880		this.name = name;
41881
41882		this.times = convertArray( times, this.TimeBufferType );
41883		this.values = convertArray( values, this.ValueBufferType );
41884
41885		this.setInterpolation( interpolation || this.DefaultInterpolation );
41886
41887	}
41888
41889	// Serialization (in static context, because of constructor invocation
41890	// and automatic invocation of .toJSON):
41891
41892	static toJSON( track ) {
41893
41894		const trackType = track.constructor;
41895
41896		let json;
41897
41898		// derived classes can define a static toJSON method
41899		if ( trackType.toJSON !== this.toJSON ) {
41900
41901			json = trackType.toJSON( track );
41902
41903		} else {
41904
41905			// by default, we assume the data can be serialized as-is
41906			json = {
41907
41908				'name': track.name,
41909				'times': convertArray( track.times, Array ),
41910				'values': convertArray( track.values, Array )
41911
41912			};
41913
41914			const interpolation = track.getInterpolation();
41915
41916			if ( interpolation !== track.DefaultInterpolation ) {
41917
41918				json.interpolation = interpolation;
41919
41920			}
41921
41922		}
41923
41924		json.type = track.ValueTypeName; // mandatory
41925
41926		return json;
41927
41928	}
41929
41930	InterpolantFactoryMethodDiscrete( result ) {
41931
41932		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
41933
41934	}
41935
41936	InterpolantFactoryMethodLinear( result ) {
41937
41938		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
41939
41940	}
41941
41942	InterpolantFactoryMethodSmooth( result ) {
41943
41944		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
41945
41946	}
41947
41948	setInterpolation( interpolation ) {
41949
41950		let factoryMethod;
41951
41952		switch ( interpolation ) {
41953
41954			case InterpolateDiscrete:
41955
41956				factoryMethod = this.InterpolantFactoryMethodDiscrete;
41957
41958				break;
41959
41960			case InterpolateLinear:
41961
41962				factoryMethod = this.InterpolantFactoryMethodLinear;
41963
41964				break;
41965
41966			case InterpolateSmooth:
41967
41968				factoryMethod = this.InterpolantFactoryMethodSmooth;
41969
41970				break;
41971
41972		}
41973
41974		if ( factoryMethod === undefined ) {
41975
41976			const message = 'unsupported interpolation for ' +
41977				this.ValueTypeName + ' keyframe track named ' + this.name;
41978
41979			if ( this.createInterpolant === undefined ) {
41980
41981				// fall back to default, unless the default itself is messed up
41982				if ( interpolation !== this.DefaultInterpolation ) {
41983
41984					this.setInterpolation( this.DefaultInterpolation );
41985
41986				} else {
41987
41988					throw new Error( message ); // fatal, in this case
41989
41990				}
41991
41992			}
41993
41994			console.warn( 'THREE.KeyframeTrack:', message );
41995			return this;
41996
41997		}
41998
41999		this.createInterpolant = factoryMethod;
42000
42001		return this;
42002
42003	}
42004
42005	getInterpolation() {
42006
42007		switch ( this.createInterpolant ) {
42008
42009			case this.InterpolantFactoryMethodDiscrete:
42010
42011				return InterpolateDiscrete;
42012
42013			case this.InterpolantFactoryMethodLinear:
42014
42015				return InterpolateLinear;
42016
42017			case this.InterpolantFactoryMethodSmooth:
42018
42019				return InterpolateSmooth;
42020
42021		}
42022
42023	}
42024
42025	getValueSize() {
42026
42027		return this.values.length / this.times.length;
42028
42029	}
42030
42031	// move all keyframes either forwards or backwards in time
42032	shift( timeOffset ) {
42033
42034		if ( timeOffset !== 0.0 ) {
42035
42036			const times = this.times;
42037
42038			for ( let i = 0, n = times.length; i !== n; ++ i ) {
42039
42040				times[ i ] += timeOffset;
42041
42042			}
42043
42044		}
42045
42046		return this;
42047
42048	}
42049
42050	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
42051	scale( timeScale ) {
42052
42053		if ( timeScale !== 1.0 ) {
42054
42055			const times = this.times;
42056
42057			for ( let i = 0, n = times.length; i !== n; ++ i ) {
42058
42059				times[ i ] *= timeScale;
42060
42061			}
42062
42063		}
42064
42065		return this;
42066
42067	}
42068
42069	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
42070	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
42071	trim( startTime, endTime ) {
42072
42073		const times = this.times,
42074			nKeys = times.length;
42075
42076		let from = 0,
42077			to = nKeys - 1;
42078
42079		while ( from !== nKeys && times[ from ] < startTime ) {
42080
42081			++ from;
42082
42083		}
42084
42085		while ( to !== - 1 && times[ to ] > endTime ) {
42086
42087			-- to;
42088
42089		}
42090
42091		++ to; // inclusive -> exclusive bound
42092
42093		if ( from !== 0 || to !== nKeys ) {
42094
42095			// empty tracks are forbidden, so keep at least one keyframe
42096			if ( from >= to ) {
42097
42098				to = Math.max( to, 1 );
42099				from = to - 1;
42100
42101			}
42102
42103			const stride = this.getValueSize();
42104			this.times = times.slice( from, to );
42105			this.values = this.values.slice( from * stride, to * stride );
42106
42107		}
42108
42109		return this;
42110
42111	}
42112
42113	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
42114	validate() {
42115
42116		let valid = true;
42117
42118		const valueSize = this.getValueSize();
42119		if ( valueSize - Math.floor( valueSize ) !== 0 ) {
42120
42121			console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
42122			valid = false;
42123
42124		}
42125
42126		const times = this.times,
42127			values = this.values,
42128
42129			nKeys = times.length;
42130
42131		if ( nKeys === 0 ) {
42132
42133			console.error( 'THREE.KeyframeTrack: Track is empty.', this );
42134			valid = false;
42135
42136		}
42137
42138		let prevTime = null;
42139
42140		for ( let i = 0; i !== nKeys; i ++ ) {
42141
42142			const currTime = times[ i ];
42143
42144			if ( typeof currTime === 'number' && isNaN( currTime ) ) {
42145
42146				console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
42147				valid = false;
42148				break;
42149
42150			}
42151
42152			if ( prevTime !== null && prevTime > currTime ) {
42153
42154				console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
42155				valid = false;
42156				break;
42157
42158			}
42159
42160			prevTime = currTime;
42161
42162		}
42163
42164		if ( values !== undefined ) {
42165
42166			if ( isTypedArray( values ) ) {
42167
42168				for ( let i = 0, n = values.length; i !== n; ++ i ) {
42169
42170					const value = values[ i ];
42171
42172					if ( isNaN( value ) ) {
42173
42174						console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
42175						valid = false;
42176						break;
42177
42178					}
42179
42180				}
42181
42182			}
42183
42184		}
42185
42186		return valid;
42187
42188	}
42189
42190	// removes equivalent sequential keys as common in morph target sequences
42191	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
42192	optimize() {
42193
42194		// times or values may be shared with other tracks, so overwriting is unsafe
42195		const times = this.times.slice(),
42196			values = this.values.slice(),
42197			stride = this.getValueSize(),
42198
42199			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
42200
42201			lastIndex = times.length - 1;
42202
42203		let writeIndex = 1;
42204
42205		for ( let i = 1; i < lastIndex; ++ i ) {
42206
42207			let keep = false;
42208
42209			const time = times[ i ];
42210			const timeNext = times[ i + 1 ];
42211
42212			// remove adjacent keyframes scheduled at the same time
42213
42214			if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
42215
42216				if ( ! smoothInterpolation ) {
42217
42218					// remove unnecessary keyframes same as their neighbors
42219
42220					const offset = i * stride,
42221						offsetP = offset - stride,
42222						offsetN = offset + stride;
42223
42224					for ( let j = 0; j !== stride; ++ j ) {
42225
42226						const value = values[ offset + j ];
42227
42228						if ( value !== values[ offsetP + j ] ||
42229							value !== values[ offsetN + j ] ) {
42230
42231							keep = true;
42232							break;
42233
42234						}
42235
42236					}
42237
42238				} else {
42239
42240					keep = true;
42241
42242				}
42243
42244			}
42245
42246			// in-place compaction
42247
42248			if ( keep ) {
42249
42250				if ( i !== writeIndex ) {
42251
42252					times[ writeIndex ] = times[ i ];
42253
42254					const readOffset = i * stride,
42255						writeOffset = writeIndex * stride;
42256
42257					for ( let j = 0; j !== stride; ++ j ) {
42258
42259						values[ writeOffset + j ] = values[ readOffset + j ];
42260
42261					}
42262
42263				}
42264
42265				++ writeIndex;
42266
42267			}
42268
42269		}
42270
42271		// flush last keyframe (compaction looks ahead)
42272
42273		if ( lastIndex > 0 ) {
42274
42275			times[ writeIndex ] = times[ lastIndex ];
42276
42277			for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
42278
42279				values[ writeOffset + j ] = values[ readOffset + j ];
42280
42281			}
42282
42283			++ writeIndex;
42284
42285		}
42286
42287		if ( writeIndex !== times.length ) {
42288
42289			this.times = times.slice( 0, writeIndex );
42290			this.values = values.slice( 0, writeIndex * stride );
42291
42292		} else {
42293
42294			this.times = times;
42295			this.values = values;
42296
42297		}
42298
42299		return this;
42300
42301	}
42302
42303	clone() {
42304
42305		const times = this.times.slice();
42306		const values = this.values.slice();
42307
42308		const TypedKeyframeTrack = this.constructor;
42309		const track = new TypedKeyframeTrack( this.name, times, values );
42310
42311		// Interpolant argument to constructor is not saved, so copy the factory method directly.
42312		track.createInterpolant = this.createInterpolant;
42313
42314		return track;
42315
42316	}
42317
42318}
42319
42320KeyframeTrack.prototype.TimeBufferType = Float32Array;
42321KeyframeTrack.prototype.ValueBufferType = Float32Array;
42322KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42323
42324/**
42325 * A Track of Boolean keyframe values.
42326 */
42327class BooleanKeyframeTrack extends KeyframeTrack {}
42328
42329BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
42330BooleanKeyframeTrack.prototype.ValueBufferType = Array;
42331BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42332BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
42333BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42334
42335/**
42336 * A Track of keyframe values that represent color.
42337 */
42338class ColorKeyframeTrack extends KeyframeTrack {}
42339
42340ColorKeyframeTrack.prototype.ValueTypeName = 'color';
42341
42342/**
42343 * A Track of numeric keyframe values.
42344 */
42345class NumberKeyframeTrack extends KeyframeTrack {}
42346
42347NumberKeyframeTrack.prototype.ValueTypeName = 'number';
42348
42349/**
42350 * Spherical linear unit quaternion interpolant.
42351 */
42352
42353class QuaternionLinearInterpolant extends Interpolant {
42354
42355	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42356
42357		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42358
42359	}
42360
42361	interpolate_( i1, t0, t, t1 ) {
42362
42363		const result = this.resultBuffer,
42364			values = this.sampleValues,
42365			stride = this.valueSize,
42366
42367			alpha = ( t - t0 ) / ( t1 - t0 );
42368
42369		let offset = i1 * stride;
42370
42371		for ( let end = offset + stride; offset !== end; offset += 4 ) {
42372
42373			Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
42374
42375		}
42376
42377		return result;
42378
42379	}
42380
42381}
42382
42383/**
42384 * A Track of quaternion keyframe values.
42385 */
42386class QuaternionKeyframeTrack extends KeyframeTrack {
42387
42388	InterpolantFactoryMethodLinear( result ) {
42389
42390		return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
42391
42392	}
42393
42394}
42395
42396QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
42397// ValueBufferType is inherited
42398QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42399QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42400
42401/**
42402 * A Track that interpolates Strings
42403 */
42404class StringKeyframeTrack extends KeyframeTrack {}
42405
42406StringKeyframeTrack.prototype.ValueTypeName = 'string';
42407StringKeyframeTrack.prototype.ValueBufferType = Array;
42408StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42409StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
42410StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42411
42412/**
42413 * A Track of vectored keyframe values.
42414 */
42415class VectorKeyframeTrack extends KeyframeTrack {}
42416
42417VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
42418
42419class AnimationClip {
42420
42421	constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) {
42422
42423		this.name = name;
42424		this.tracks = tracks;
42425		this.duration = duration;
42426		this.blendMode = blendMode;
42427
42428		this.uuid = generateUUID();
42429
42430		// this means it should figure out its duration by scanning the tracks
42431		if ( this.duration < 0 ) {
42432
42433			this.resetDuration();
42434
42435		}
42436
42437	}
42438
42439
42440	static parse( json ) {
42441
42442		const tracks = [],
42443			jsonTracks = json.tracks,
42444			frameTime = 1.0 / ( json.fps || 1.0 );
42445
42446		for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
42447
42448			tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
42449
42450		}
42451
42452		const clip = new this( json.name, json.duration, tracks, json.blendMode );
42453		clip.uuid = json.uuid;
42454
42455		return clip;
42456
42457	}
42458
42459	static toJSON( clip ) {
42460
42461		const tracks = [],
42462			clipTracks = clip.tracks;
42463
42464		const json = {
42465
42466			'name': clip.name,
42467			'duration': clip.duration,
42468			'tracks': tracks,
42469			'uuid': clip.uuid,
42470			'blendMode': clip.blendMode
42471
42472		};
42473
42474		for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
42475
42476			tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
42477
42478		}
42479
42480		return json;
42481
42482	}
42483
42484	static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
42485
42486		const numMorphTargets = morphTargetSequence.length;
42487		const tracks = [];
42488
42489		for ( let i = 0; i < numMorphTargets; i ++ ) {
42490
42491			let times = [];
42492			let values = [];
42493
42494			times.push(
42495				( i + numMorphTargets - 1 ) % numMorphTargets,
42496				i,
42497				( i + 1 ) % numMorphTargets );
42498
42499			values.push( 0, 1, 0 );
42500
42501			const order = getKeyframeOrder( times );
42502			times = sortedArray( times, 1, order );
42503			values = sortedArray( values, 1, order );
42504
42505			// if there is a key at the first frame, duplicate it as the
42506			// last frame as well for perfect loop.
42507			if ( ! noLoop && times[ 0 ] === 0 ) {
42508
42509				times.push( numMorphTargets );
42510				values.push( values[ 0 ] );
42511
42512			}
42513
42514			tracks.push(
42515				new NumberKeyframeTrack(
42516					'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
42517					times, values
42518				).scale( 1.0 / fps ) );
42519
42520		}
42521
42522		return new this( name, - 1, tracks );
42523
42524	}
42525
42526	static findByName( objectOrClipArray, name ) {
42527
42528		let clipArray = objectOrClipArray;
42529
42530		if ( ! Array.isArray( objectOrClipArray ) ) {
42531
42532			const o = objectOrClipArray;
42533			clipArray = o.geometry && o.geometry.animations || o.animations;
42534
42535		}
42536
42537		for ( let i = 0; i < clipArray.length; i ++ ) {
42538
42539			if ( clipArray[ i ].name === name ) {
42540
42541				return clipArray[ i ];
42542
42543			}
42544
42545		}
42546
42547		return null;
42548
42549	}
42550
42551	static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
42552
42553		const animationToMorphTargets = {};
42554
42555		// tested with https://regex101.com/ on trick sequences
42556		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
42557		const pattern = /^([\w-]*?)([\d]+)$/;
42558
42559		// sort morph target names into animation groups based
42560		// patterns like Walk_001, Walk_002, Run_001, Run_002
42561		for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
42562
42563			const morphTarget = morphTargets[ i ];
42564			const parts = morphTarget.name.match( pattern );
42565
42566			if ( parts && parts.length > 1 ) {
42567
42568				const name = parts[ 1 ];
42569
42570				let animationMorphTargets = animationToMorphTargets[ name ];
42571
42572				if ( ! animationMorphTargets ) {
42573
42574					animationToMorphTargets[ name ] = animationMorphTargets = [];
42575
42576				}
42577
42578				animationMorphTargets.push( morphTarget );
42579
42580			}
42581
42582		}
42583
42584		const clips = [];
42585
42586		for ( const name in animationToMorphTargets ) {
42587
42588			clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
42589
42590		}
42591
42592		return clips;
42593
42594	}
42595
42596	// parse the animation.hierarchy format
42597	static parseAnimation( animation, bones ) {
42598
42599		if ( ! animation ) {
42600
42601			console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
42602			return null;
42603
42604		}
42605
42606		const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
42607
42608			// only return track if there are actually keys.
42609			if ( animationKeys.length !== 0 ) {
42610
42611				const times = [];
42612				const values = [];
42613
42614				flattenJSON( animationKeys, times, values, propertyName );
42615
42616				// empty keys are filtered out, so check again
42617				if ( times.length !== 0 ) {
42618
42619					destTracks.push( new trackType( trackName, times, values ) );
42620
42621				}
42622
42623			}
42624
42625		};
42626
42627		const tracks = [];
42628
42629		const clipName = animation.name || 'default';
42630		const fps = animation.fps || 30;
42631		const blendMode = animation.blendMode;
42632
42633		// automatic length determination in AnimationClip.
42634		let duration = animation.length || - 1;
42635
42636		const hierarchyTracks = animation.hierarchy || [];
42637
42638		for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
42639
42640			const animationKeys = hierarchyTracks[ h ].keys;
42641
42642			// skip empty tracks
42643			if ( ! animationKeys || animationKeys.length === 0 ) continue;
42644
42645			// process morph targets
42646			if ( animationKeys[ 0 ].morphTargets ) {
42647
42648				// figure out all morph targets used in this track
42649				const morphTargetNames = {};
42650
42651				let k;
42652
42653				for ( k = 0; k < animationKeys.length; k ++ ) {
42654
42655					if ( animationKeys[ k ].morphTargets ) {
42656
42657						for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
42658
42659							morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
42660
42661						}
42662
42663					}
42664
42665				}
42666
42667				// create a track for each morph target with all zero
42668				// morphTargetInfluences except for the keys in which
42669				// the morphTarget is named.
42670				for ( const morphTargetName in morphTargetNames ) {
42671
42672					const times = [];
42673					const values = [];
42674
42675					for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
42676
42677						const animationKey = animationKeys[ k ];
42678
42679						times.push( animationKey.time );
42680						values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
42681
42682					}
42683
42684					tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
42685
42686				}
42687
42688				duration = morphTargetNames.length * fps;
42689
42690			} else {
42691
42692				// ...assume skeletal animation
42693
42694				const boneName = '.bones[' + bones[ h ].name + ']';
42695
42696				addNonemptyTrack(
42697					VectorKeyframeTrack, boneName + '.position',
42698					animationKeys, 'pos', tracks );
42699
42700				addNonemptyTrack(
42701					QuaternionKeyframeTrack, boneName + '.quaternion',
42702					animationKeys, 'rot', tracks );
42703
42704				addNonemptyTrack(
42705					VectorKeyframeTrack, boneName + '.scale',
42706					animationKeys, 'scl', tracks );
42707
42708			}
42709
42710		}
42711
42712		if ( tracks.length === 0 ) {
42713
42714			return null;
42715
42716		}
42717
42718		const clip = new this( clipName, duration, tracks, blendMode );
42719
42720		return clip;
42721
42722	}
42723
42724	resetDuration() {
42725
42726		const tracks = this.tracks;
42727		let duration = 0;
42728
42729		for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
42730
42731			const track = this.tracks[ i ];
42732
42733			duration = Math.max( duration, track.times[ track.times.length - 1 ] );
42734
42735		}
42736
42737		this.duration = duration;
42738
42739		return this;
42740
42741	}
42742
42743	trim() {
42744
42745		for ( let i = 0; i < this.tracks.length; i ++ ) {
42746
42747			this.tracks[ i ].trim( 0, this.duration );
42748
42749		}
42750
42751		return this;
42752
42753	}
42754
42755	validate() {
42756
42757		let valid = true;
42758
42759		for ( let i = 0; i < this.tracks.length; i ++ ) {
42760
42761			valid = valid && this.tracks[ i ].validate();
42762
42763		}
42764
42765		return valid;
42766
42767	}
42768
42769	optimize() {
42770
42771		for ( let i = 0; i < this.tracks.length; i ++ ) {
42772
42773			this.tracks[ i ].optimize();
42774
42775		}
42776
42777		return this;
42778
42779	}
42780
42781	clone() {
42782
42783		const tracks = [];
42784
42785		for ( let i = 0; i < this.tracks.length; i ++ ) {
42786
42787			tracks.push( this.tracks[ i ].clone() );
42788
42789		}
42790
42791		return new this.constructor( this.name, this.duration, tracks, this.blendMode );
42792
42793	}
42794
42795	toJSON() {
42796
42797		return this.constructor.toJSON( this );
42798
42799	}
42800
42801}
42802
42803function getTrackTypeForValueTypeName( typeName ) {
42804
42805	switch ( typeName.toLowerCase() ) {
42806
42807		case 'scalar':
42808		case 'double':
42809		case 'float':
42810		case 'number':
42811		case 'integer':
42812
42813			return NumberKeyframeTrack;
42814
42815		case 'vector':
42816		case 'vector2':
42817		case 'vector3':
42818		case 'vector4':
42819
42820			return VectorKeyframeTrack;
42821
42822		case 'color':
42823
42824			return ColorKeyframeTrack;
42825
42826		case 'quaternion':
42827
42828			return QuaternionKeyframeTrack;
42829
42830		case 'bool':
42831		case 'boolean':
42832
42833			return BooleanKeyframeTrack;
42834
42835		case 'string':
42836
42837			return StringKeyframeTrack;
42838
42839	}
42840
42841	throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
42842
42843}
42844
42845function parseKeyframeTrack( json ) {
42846
42847	if ( json.type === undefined ) {
42848
42849		throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
42850
42851	}
42852
42853	const trackType = getTrackTypeForValueTypeName( json.type );
42854
42855	if ( json.times === undefined ) {
42856
42857		const times = [], values = [];
42858
42859		flattenJSON( json.keys, times, values, 'value' );
42860
42861		json.times = times;
42862		json.values = values;
42863
42864	}
42865
42866	// derived classes can define a static parse method
42867	if ( trackType.parse !== undefined ) {
42868
42869		return trackType.parse( json );
42870
42871	} else {
42872
42873		// by default, we assume a constructor compatible with the base
42874		return new trackType( json.name, json.times, json.values, json.interpolation );
42875
42876	}
42877
42878}
42879
42880const Cache = {
42881
42882	enabled: false,
42883
42884	files: {},
42885
42886	add: function ( key, file ) {
42887
42888		if ( this.enabled === false ) return;
42889
42890		// console.log( 'THREE.Cache', 'Adding key:', key );
42891
42892		this.files[ key ] = file;
42893
42894	},
42895
42896	get: function ( key ) {
42897
42898		if ( this.enabled === false ) return;
42899
42900		// console.log( 'THREE.Cache', 'Checking key:', key );
42901
42902		return this.files[ key ];
42903
42904	},
42905
42906	remove: function ( key ) {
42907
42908		delete this.files[ key ];
42909
42910	},
42911
42912	clear: function () {
42913
42914		this.files = {};
42915
42916	}
42917
42918};
42919
42920class LoadingManager {
42921
42922	constructor( onLoad, onProgress, onError ) {
42923
42924		const scope = this;
42925
42926		let isLoading = false;
42927		let itemsLoaded = 0;
42928		let itemsTotal = 0;
42929		let urlModifier = undefined;
42930		const handlers = [];
42931
42932		// Refer to #5689 for the reason why we don't set .onStart
42933		// in the constructor
42934
42935		this.onStart = undefined;
42936		this.onLoad = onLoad;
42937		this.onProgress = onProgress;
42938		this.onError = onError;
42939
42940		this.itemStart = function ( url ) {
42941
42942			itemsTotal ++;
42943
42944			if ( isLoading === false ) {
42945
42946				if ( scope.onStart !== undefined ) {
42947
42948					scope.onStart( url, itemsLoaded, itemsTotal );
42949
42950				}
42951
42952			}
42953
42954			isLoading = true;
42955
42956		};
42957
42958		this.itemEnd = function ( url ) {
42959
42960			itemsLoaded ++;
42961
42962			if ( scope.onProgress !== undefined ) {
42963
42964				scope.onProgress( url, itemsLoaded, itemsTotal );
42965
42966			}
42967
42968			if ( itemsLoaded === itemsTotal ) {
42969
42970				isLoading = false;
42971
42972				if ( scope.onLoad !== undefined ) {
42973
42974					scope.onLoad();
42975
42976				}
42977
42978			}
42979
42980		};
42981
42982		this.itemError = function ( url ) {
42983
42984			if ( scope.onError !== undefined ) {
42985
42986				scope.onError( url );
42987
42988			}
42989
42990		};
42991
42992		this.resolveURL = function ( url ) {
42993
42994			if ( urlModifier ) {
42995
42996				return urlModifier( url );
42997
42998			}
42999
43000			return url;
43001
43002		};
43003
43004		this.setURLModifier = function ( transform ) {
43005
43006			urlModifier = transform;
43007
43008			return this;
43009
43010		};
43011
43012		this.addHandler = function ( regex, loader ) {
43013
43014			handlers.push( regex, loader );
43015
43016			return this;
43017
43018		};
43019
43020		this.removeHandler = function ( regex ) {
43021
43022			const index = handlers.indexOf( regex );
43023
43024			if ( index !== - 1 ) {
43025
43026				handlers.splice( index, 2 );
43027
43028			}
43029
43030			return this;
43031
43032		};
43033
43034		this.getHandler = function ( file ) {
43035
43036			for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
43037
43038				const regex = handlers[ i ];
43039				const loader = handlers[ i + 1 ];
43040
43041				if ( regex.global ) regex.lastIndex = 0; // see #17920
43042
43043				if ( regex.test( file ) ) {
43044
43045					return loader;
43046
43047				}
43048
43049			}
43050
43051			return null;
43052
43053		};
43054
43055	}
43056
43057}
43058
43059const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager();
43060
43061class Loader {
43062
43063	constructor( manager ) {
43064
43065		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
43066
43067		this.crossOrigin = 'anonymous';
43068		this.withCredentials = false;
vendor: 12,888 bytes, lines 43069-43794
43069		this.path = '';
43070		this.resourcePath = '';
43071		this.requestHeader = {};
43072
43073	}
43074
43075	load( /* url, onLoad, onProgress, onError */ ) {}
43076
43077	loadAsync( url, onProgress ) {
43078
43079		const scope = this;
43080
43081		return new Promise( function ( resolve, reject ) {
43082
43083			scope.load( url, resolve, onProgress, reject );
43084
43085		} );
43086
43087	}
43088
43089	parse( /* data */ ) {}
43090
43091	setCrossOrigin( crossOrigin ) {
43092
43093		this.crossOrigin = crossOrigin;
43094		return this;
43095
43096	}
43097
43098	setWithCredentials( value ) {
43099
43100		this.withCredentials = value;
43101		return this;
43102
43103	}
43104
43105	setPath( path ) {
43106
43107		this.path = path;
43108		return this;
43109
43110	}
43111
43112	setResourcePath( resourcePath ) {
43113
43114		this.resourcePath = resourcePath;
43115		return this;
43116
43117	}
43118
43119	setRequestHeader( requestHeader ) {
43120
43121		this.requestHeader = requestHeader;
43122		return this;
43123
43124	}
43125
43126}
43127
43128Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT';
43129
43130const loading = {};
43131
43132class HttpError extends Error {
43133
43134	constructor( message, response ) {
43135
43136		super( message );
43137		this.response = response;
43138
43139	}
43140
43141}
43142
43143class FileLoader extends Loader {
43144
43145	constructor( manager ) {
43146
43147		super( manager );
43148
43149	}
43150
43151	load( url, onLoad, onProgress, onError ) {
43152
43153		if ( url === undefined ) url = '';
43154
43155		if ( this.path !== undefined ) url = this.path + url;
43156
43157		url = this.manager.resolveURL( url );
43158
43159		const cached = Cache.get( url );
43160
43161		if ( cached !== undefined ) {
43162
43163			this.manager.itemStart( url );
43164
43165			setTimeout( () => {
43166
43167				if ( onLoad ) onLoad( cached );
43168
43169				this.manager.itemEnd( url );
43170
43171			}, 0 );
43172
43173			return cached;
43174
43175		}
43176
43177		// Check if request is duplicate
43178
43179		if ( loading[ url ] !== undefined ) {
43180
43181			loading[ url ].push( {
43182
43183				onLoad: onLoad,
43184				onProgress: onProgress,
43185				onError: onError
43186
43187			} );
43188
43189			return;
43190
43191		}
43192
43193		// Initialise array for duplicate requests
43194		loading[ url ] = [];
43195
43196		loading[ url ].push( {
43197			onLoad: onLoad,
43198			onProgress: onProgress,
43199			onError: onError,
43200		} );
43201
43202		// create request
43203		const req = new Request( url, {
43204			headers: new Headers( this.requestHeader ),
43205			credentials: this.withCredentials ? 'include' : 'same-origin',
43206			// An abort controller could be added within a future PR
43207		} );
43208
43209		// record states ( avoid data race )
43210		const mimeType = this.mimeType;
43211		const responseType = this.responseType;
43212
43213		// start the fetch
43214		fetch( req )
43215			.then( response => {
43216
43217				if ( response.status === 200 || response.status === 0 ) {
43218
43219					// Some browsers return HTTP Status 0 when using non-http protocol
43220					// e.g. 'file://' or 'data://'. Handle as success.
43221
43222					if ( response.status === 0 ) {
43223
43224						console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
43225
43226					}
43227
43228					// Workaround: Checking if response.body === undefined for Alipay browser #23548
43229
43230					if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) {
43231
43232						return response;
43233
43234					}
43235
43236					const callbacks = loading[ url ];
43237					const reader = response.body.getReader();
43238
43239					// Nginx needs X-File-Size check
43240					// https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content
43241					const contentLength = response.headers.get( 'Content-Length' ) || response.headers.get( 'X-File-Size' );
43242					const total = contentLength ? parseInt( contentLength ) : 0;
43243					const lengthComputable = total !== 0;
43244					let loaded = 0;
43245
43246					// periodically read data into the new stream tracking while download progress
43247					const stream = new ReadableStream( {
43248						start( controller ) {
43249
43250							readData();
43251
43252							function readData() {
43253
43254								reader.read().then( ( { done, value } ) => {
43255
43256									if ( done ) {
43257
43258										controller.close();
43259
43260									} else {
43261
43262										loaded += value.byteLength;
43263
43264										const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } );
43265										for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
43266
43267											const callback = callbacks[ i ];
43268											if ( callback.onProgress ) callback.onProgress( event );
43269
43270										}
43271
43272										controller.enqueue( value );
43273										readData();
43274
43275									}
43276
43277								} );
43278
43279							}
43280
43281						}
43282
43283					} );
43284
43285					return new Response( stream );
43286
43287				} else {
43288
43289					throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response );
43290
43291				}
43292
43293			} )
43294			.then( response => {
43295
43296				switch ( responseType ) {
43297
43298					case 'arraybuffer':
43299
43300						return response.arrayBuffer();
43301
43302					case 'blob':
43303
43304						return response.blob();
43305
43306					case 'document':
43307
43308						return response.text()
43309							.then( text => {
43310
43311								const parser = new DOMParser();
43312								return parser.parseFromString( text, mimeType );
43313
43314							} );
43315
43316					case 'json':
43317
43318						return response.json();
43319
43320					default:
43321
43322						if ( mimeType === undefined ) {
43323
43324							return response.text();
43325
43326						} else {
43327
43328							// sniff encoding
43329							const re = /charset="?([^;"\s]*)"?/i;
43330							const exec = re.exec( mimeType );
43331							const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined;
43332							const decoder = new TextDecoder( label );
43333							return response.arrayBuffer().then( ab => decoder.decode( ab ) );
43334
43335						}
43336
43337				}
43338
43339			} )
43340			.then( data => {
43341
43342				// Add to cache only on HTTP success, so that we do not cache
43343				// error response bodies as proper responses to requests.
43344				Cache.add( url, data );
43345
43346				const callbacks = loading[ url ];
43347				delete loading[ url ];
43348
43349				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
43350
43351					const callback = callbacks[ i ];
43352					if ( callback.onLoad ) callback.onLoad( data );
43353
43354				}
43355
43356			} )
43357			.catch( err => {
43358
43359				// Abort errors and other errors are handled the same
43360
43361				const callbacks = loading[ url ];
43362
43363				if ( callbacks === undefined ) {
43364
43365					// When onLoad was called and url was deleted in `loading`
43366					this.manager.itemError( url );
43367					throw err;
43368
43369				}
43370
43371				delete loading[ url ];
43372
43373				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
43374
43375					const callback = callbacks[ i ];
43376					if ( callback.onError ) callback.onError( err );
43377
43378				}
43379
43380				this.manager.itemError( url );
43381
43382			} )
43383			.finally( () => {
43384
43385				this.manager.itemEnd( url );
43386
43387			} );
43388
43389		this.manager.itemStart( url );
43390
43391	}
43392
43393	setResponseType( value ) {
43394
43395		this.responseType = value;
43396		return this;
43397
43398	}
43399
43400	setMimeType( value ) {
43401
43402		this.mimeType = value;
43403		return this;
43404
43405	}
43406
43407}
43408
43409class AnimationLoader extends Loader {
43410
43411	constructor( manager ) {
43412
43413		super( manager );
43414
43415	}
43416
43417	load( url, onLoad, onProgress, onError ) {
43418
43419		const scope = this;
43420
43421		const loader = new FileLoader( this.manager );
43422		loader.setPath( this.path );
43423		loader.setRequestHeader( this.requestHeader );
43424		loader.setWithCredentials( this.withCredentials );
43425		loader.load( url, function ( text ) {
43426
43427			try {
43428
43429				onLoad( scope.parse( JSON.parse( text ) ) );
43430
43431			} catch ( e ) {
43432
43433				if ( onError ) {
43434
43435					onError( e );
43436
43437				} else {
43438
43439					console.error( e );
43440
43441				}
43442
43443				scope.manager.itemError( url );
43444
43445			}
43446
43447		}, onProgress, onError );
43448
43449	}
43450
43451	parse( json ) {
43452
43453		const animations = [];
43454
43455		for ( let i = 0; i < json.length; i ++ ) {
43456
43457			const clip = AnimationClip.parse( json[ i ] );
43458
43459			animations.push( clip );
43460
43461		}
43462
43463		return animations;
43464
43465	}
43466
43467}
43468
43469/**
43470 * Abstract Base class to block based textures loader (dds, pvr, ...)
43471 *
43472 * Sub classes have to implement the parse() method which will be used in load().
43473 */
43474
43475class CompressedTextureLoader extends Loader {
43476
43477	constructor( manager ) {
43478
43479		super( manager );
43480
43481	}
43482
43483	load( url, onLoad, onProgress, onError ) {
43484
43485		const scope = this;
43486
43487		const images = [];
43488
43489		const texture = new CompressedTexture();
43490
43491		const loader = new FileLoader( this.manager );
43492		loader.setPath( this.path );
43493		loader.setResponseType( 'arraybuffer' );
43494		loader.setRequestHeader( this.requestHeader );
43495		loader.setWithCredentials( scope.withCredentials );
43496
43497		let loaded = 0;
43498
43499		function loadTexture( i ) {
43500
43501			loader.load( url[ i ], function ( buffer ) {
43502
43503				const texDatas = scope.parse( buffer, true );
43504
43505				images[ i ] = {
43506					width: texDatas.width,
43507					height: texDatas.height,
43508					format: texDatas.format,
43509					mipmaps: texDatas.mipmaps
43510				};
43511
43512				loaded += 1;
43513
43514				if ( loaded === 6 ) {
43515
43516					if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
43517
43518					texture.image = images;
43519					texture.format = texDatas.format;
43520					texture.needsUpdate = true;
43521
43522					if ( onLoad ) onLoad( texture );
43523
43524				}
43525
43526			}, onProgress, onError );
43527
43528		}
43529
43530		if ( Array.isArray( url ) ) {
43531
43532			for ( let i = 0, il = url.length; i < il; ++ i ) {
43533
43534				loadTexture( i );
43535
43536			}
43537
43538		} else {
43539
43540			// compressed cubemap texture stored in a single DDS file
43541
43542			loader.load( url, function ( buffer ) {
43543
43544				const texDatas = scope.parse( buffer, true );
43545
43546				if ( texDatas.isCubemap ) {
43547
43548					const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
43549
43550					for ( let f = 0; f < faces; f ++ ) {
43551
43552						images[ f ] = { mipmaps: [] };
43553
43554						for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
43555
43556							images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
43557							images[ f ].format = texDatas.format;
43558							images[ f ].width = texDatas.width;
43559							images[ f ].height = texDatas.height;
43560
43561						}
43562
43563					}
43564
43565					texture.image = images;
43566
43567				} else {
43568
43569					texture.image.width = texDatas.width;
43570					texture.image.height = texDatas.height;
43571					texture.mipmaps = texDatas.mipmaps;
43572
43573				}
43574
43575				if ( texDatas.mipmapCount === 1 ) {
43576
43577					texture.minFilter = LinearFilter;
43578
43579				}
43580
43581				texture.format = texDatas.format;
43582				texture.needsUpdate = true;
43583
43584				if ( onLoad ) onLoad( texture );
43585
43586			}, onProgress, onError );
43587
43588		}
43589
43590		return texture;
43591
43592	}
43593
43594}
43595
43596class ImageLoader extends Loader {
43597
43598	constructor( manager ) {
43599
43600		super( manager );
43601
43602	}
43603
43604	load( url, onLoad, onProgress, onError ) {
43605
43606		if ( this.path !== undefined ) url = this.path + url;
43607
43608		url = this.manager.resolveURL( url );
43609
43610		const scope = this;
43611
43612		const cached = Cache.get( url );
43613
43614		if ( cached !== undefined ) {
43615
43616			scope.manager.itemStart( url );
43617
43618			setTimeout( function () {
43619
43620				if ( onLoad ) onLoad( cached );
43621
43622				scope.manager.itemEnd( url );
43623
43624			}, 0 );
43625
43626			return cached;
43627
43628		}
43629
43630		const image = createElementNS( 'img' );
43631
43632		function onImageLoad() {
43633
43634			removeEventListeners();
43635
43636			Cache.add( url, this );
43637
43638			if ( onLoad ) onLoad( this );
43639
43640			scope.manager.itemEnd( url );
43641
43642		}
43643
43644		function onImageError( event ) {
43645
43646			removeEventListeners();
43647
43648			if ( onError ) onError( event );
43649
43650			scope.manager.itemError( url );
43651			scope.manager.itemEnd( url );
43652
43653		}
43654
43655		function removeEventListeners() {
43656
43657			image.removeEventListener( 'load', onImageLoad, false );
43658			image.removeEventListener( 'error', onImageError, false );
43659
43660		}
43661
43662		image.addEventListener( 'load', onImageLoad, false );
43663		image.addEventListener( 'error', onImageError, false );
43664
43665		if ( url.slice( 0, 5 ) !== 'data:' ) {
43666
43667			if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
43668
43669		}
43670
43671		scope.manager.itemStart( url );
43672
43673		image.src = url;
43674
43675		return image;
43676
43677	}
43678
43679}
43680
43681class CubeTextureLoader extends Loader {
43682
43683	constructor( manager ) {
43684
43685		super( manager );
43686
43687	}
43688
43689	load( urls, onLoad, onProgress, onError ) {
43690
43691		const texture = new CubeTexture();
43692		texture.colorSpace = SRGBColorSpace;
43693
43694		const loader = new ImageLoader( this.manager );
43695		loader.setCrossOrigin( this.crossOrigin );
43696		loader.setPath( this.path );
43697
43698		let loaded = 0;
43699
43700		function loadTexture( i ) {
43701
43702			loader.load( urls[ i ], function ( image ) {
43703
43704				texture.images[ i ] = image;
43705
43706				loaded ++;
43707
43708				if ( loaded === 6 ) {
43709
43710					texture.needsUpdate = true;
43711
43712					if ( onLoad ) onLoad( texture );
43713
43714				}
43715
43716			}, undefined, onError );
43717
43718		}
43719
43720		for ( let i = 0; i < urls.length; ++ i ) {
43721
43722			loadTexture( i );
43723
43724		}
43725
43726		return texture;
43727
43728	}
43729
43730}
43731
43732/**
43733 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
43734 *
43735 * Sub classes have to implement the parse() method which will be used in load().
43736 */
43737
43738class DataTextureLoader extends Loader {
43739
43740	constructor( manager ) {
43741
43742		super( manager );
43743
43744	}
43745
43746	load( url, onLoad, onProgress, onError ) {
43747
43748		const scope = this;
43749
43750		const texture = new DataTexture();
43751
43752		const loader = new FileLoader( this.manager );
43753		loader.setResponseType( 'arraybuffer' );
43754		loader.setRequestHeader( this.requestHeader );
43755		loader.setPath( this.path );
43756		loader.setWithCredentials( scope.withCredentials );
43757		loader.load( url, function ( buffer ) {
43758
43759			let texData;
43760
43761			try {
43762
43763				texData = scope.parse( buffer );
43764
43765			} catch ( error ) {
43766
43767				if ( onError !== undefined ) {
43768
43769					onError( error );
43770
43771				} else {
43772
43773					console.error( error );
43774					return;
43775
43776				}
43777
43778			}
43779
43780			if ( texData.image !== undefined ) {
43781
43782				texture.image = texData.image;
43783
43784			} else if ( texData.data !== undefined ) {
43785
43786				texture.image.width = texData.width;
43787				texture.image.height = texData.height;
43788				texture.image.data = texData.data;
43789
43790			}
43791
43792			texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
43793			texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
43794
vendor: 4,953 bytes, lines 43795-44081
43795			texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
43796			texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
43797
43798			texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
43799
43800			if ( texData.colorSpace !== undefined ) {
43801
43802				texture.colorSpace = texData.colorSpace;
43803
43804			}
43805
43806			if ( texData.flipY !== undefined ) {
43807
43808				texture.flipY = texData.flipY;
43809
43810			}
43811
43812			if ( texData.format !== undefined ) {
43813
43814				texture.format = texData.format;
43815
43816			}
43817
43818			if ( texData.type !== undefined ) {
43819
43820				texture.type = texData.type;
43821
43822			}
43823
43824			if ( texData.mipmaps !== undefined ) {
43825
43826				texture.mipmaps = texData.mipmaps;
43827				texture.minFilter = LinearMipmapLinearFilter; // presumably...
43828
43829			}
43830
43831			if ( texData.mipmapCount === 1 ) {
43832
43833				texture.minFilter = LinearFilter;
43834
43835			}
43836
43837			if ( texData.generateMipmaps !== undefined ) {
43838
43839				texture.generateMipmaps = texData.generateMipmaps;
43840
43841			}
43842
43843			texture.needsUpdate = true;
43844
43845			if ( onLoad ) onLoad( texture, texData );
43846
43847		}, onProgress, onError );
43848
43849
43850		return texture;
43851
43852	}
43853
43854}
43855
43856class TextureLoader extends Loader {
43857
43858	constructor( manager ) {
43859
43860		super( manager );
43861
43862	}
43863
43864	load( url, onLoad, onProgress, onError ) {
43865
43866		const texture = new Texture();
43867
43868		const loader = new ImageLoader( this.manager );
43869		loader.setCrossOrigin( this.crossOrigin );
43870		loader.setPath( this.path );
43871
43872		loader.load( url, function ( image ) {
43873
43874			texture.image = image;
43875			texture.needsUpdate = true;
43876
43877			if ( onLoad !== undefined ) {
43878
43879				onLoad( texture );
43880
43881			}
43882
43883		}, onProgress, onError );
43884
43885		return texture;
43886
43887	}
43888
43889}
43890
43891class Light extends Object3D {
43892
43893	constructor( color, intensity = 1 ) {
43894
43895		super();
43896
43897		this.isLight = true;
43898
43899		this.type = 'Light';
43900
43901		this.color = new Color( color );
43902		this.intensity = intensity;
43903
43904	}
43905
43906	dispose() {
43907
43908		// Empty here in base class; some subclasses override.
43909
43910	}
43911
43912	copy( source, recursive ) {
43913
43914		super.copy( source, recursive );
43915
43916		this.color.copy( source.color );
43917		this.intensity = source.intensity;
43918
43919		return this;
43920
43921	}
43922
43923	toJSON( meta ) {
43924
43925		const data = super.toJSON( meta );
43926
43927		data.object.color = this.color.getHex();
43928		data.object.intensity = this.intensity;
43929
43930		if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
43931
43932		if ( this.distance !== undefined ) data.object.distance = this.distance;
43933		if ( this.angle !== undefined ) data.object.angle = this.angle;
43934		if ( this.decay !== undefined ) data.object.decay = this.decay;
43935		if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
43936
43937		if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
43938
43939		return data;
43940
43941	}
43942
43943}
43944
43945class HemisphereLight extends Light {
43946
43947	constructor( skyColor, groundColor, intensity ) {
43948
43949		super( skyColor, intensity );
43950
43951		this.isHemisphereLight = true;
43952
43953		this.type = 'HemisphereLight';
43954
43955		this.position.copy( Object3D.DEFAULT_UP );
43956		this.updateMatrix();
43957
43958		this.groundColor = new Color( groundColor );
43959
43960	}
43961
43962	copy( source, recursive ) {
43963
43964		super.copy( source, recursive );
43965
43966		this.groundColor.copy( source.groundColor );
43967
43968		return this;
43969
43970	}
43971
43972}
43973
43974const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
43975const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3();
43976const _lookTarget$1 = /*@__PURE__*/ new Vector3();
43977
43978class LightShadow {
43979
43980	constructor( camera ) {
43981
43982		this.camera = camera;
43983
43984		this.bias = 0;
43985		this.normalBias = 0;
43986		this.radius = 1;
43987		this.blurSamples = 8;
43988
43989		this.mapSize = new Vector2( 512, 512 );
43990
43991		this.map = null;
43992		this.mapPass = null;
43993		this.matrix = new Matrix4();
43994
43995		this.autoUpdate = true;
43996		this.needsUpdate = false;
43997
43998		this._frustum = new Frustum();
43999		this._frameExtents = new Vector2( 1, 1 );
44000
44001		this._viewportCount = 1;
44002
44003		this._viewports = [
44004
44005			new Vector4( 0, 0, 1, 1 )
44006
44007		];
44008
44009	}
44010
44011	getViewportCount() {
44012
44013		return this._viewportCount;
44014
44015	}
44016
44017	getFrustum() {
44018
44019		return this._frustum;
44020
44021	}
44022
44023	updateMatrices( light ) {
44024
44025		const shadowCamera = this.camera;
44026		const shadowMatrix = this.matrix;
44027
44028		_lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld );
44029		shadowCamera.position.copy( _lightPositionWorld$1 );
44030
44031		_lookTarget$1.setFromMatrixPosition( light.target.matrixWorld );
44032		shadowCamera.lookAt( _lookTarget$1 );
44033		shadowCamera.updateMatrixWorld();
44034
44035		_projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
44036		this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 );
44037
44038		shadowMatrix.set(
44039			0.5, 0.0, 0.0, 0.5,
44040			0.0, 0.5, 0.0, 0.5,
44041			0.0, 0.0, 0.5, 0.5,
44042			0.0, 0.0, 0.0, 1.0
44043		);
44044
44045		shadowMatrix.multiply( _projScreenMatrix$1 );
44046
44047	}
44048
44049	getViewport( viewportIndex ) {
44050
44051		return this._viewports[ viewportIndex ];
44052
44053	}
44054
44055	getFrameExtents() {
44056
44057		return this._frameExtents;
44058
44059	}
44060
44061	dispose() {
44062
44063		if ( this.map ) {
44064
44065			this.map.dispose();
44066
44067		}
44068
44069		if ( this.mapPass ) {
44070
44071			this.mapPass.dispose();
44072
44073		}
44074
44075	}
44076
44077	copy( source ) {
44078
44079		this.camera = source.camera.clone();
44080
44081		this.bias = source.bias;
vendor: 5,709 bytes, lines 44082-44369
44082		this.radius = source.radius;
44083
44084		this.mapSize.copy( source.mapSize );
44085
44086		return this;
44087
44088	}
44089
44090	clone() {
44091
44092		return new this.constructor().copy( this );
44093
44094	}
44095
44096	toJSON() {
44097
44098		const object = {};
44099
44100		if ( this.bias !== 0 ) object.bias = this.bias;
44101		if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
44102		if ( this.radius !== 1 ) object.radius = this.radius;
44103		if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
44104
44105		object.camera = this.camera.toJSON( false ).object;
44106		delete object.camera.matrix;
44107
44108		return object;
44109
44110	}
44111
44112}
44113
44114class SpotLightShadow extends LightShadow {
44115
44116	constructor() {
44117
44118		super( new PerspectiveCamera( 50, 1, 0.5, 500 ) );
44119
44120		this.isSpotLightShadow = true;
44121
44122		this.focus = 1;
44123
44124	}
44125
44126	updateMatrices( light ) {
44127
44128		const camera = this.camera;
44129
44130		const fov = RAD2DEG * 2 * light.angle * this.focus;
44131		const aspect = this.mapSize.width / this.mapSize.height;
44132		const far = light.distance || camera.far;
44133
44134		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
44135
44136			camera.fov = fov;
44137			camera.aspect = aspect;
44138			camera.far = far;
44139			camera.updateProjectionMatrix();
44140
44141		}
44142
44143		super.updateMatrices( light );
44144
44145	}
44146
44147	copy( source ) {
44148
44149		super.copy( source );
44150
44151		this.focus = source.focus;
44152
44153		return this;
44154
44155	}
44156
44157}
44158
44159class SpotLight extends Light {
44160
44161	constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) {
44162
44163		super( color, intensity );
44164
44165		this.isSpotLight = true;
44166
44167		this.type = 'SpotLight';
44168
44169		this.position.copy( Object3D.DEFAULT_UP );
44170		this.updateMatrix();
44171
44172		this.target = new Object3D();
44173
44174		this.distance = distance;
44175		this.angle = angle;
44176		this.penumbra = penumbra;
44177		this.decay = decay;
44178
44179		this.map = null;
44180
44181		this.shadow = new SpotLightShadow();
44182
44183	}
44184
44185	get power() {
44186
44187		// compute the light's luminous power (in lumens) from its intensity (in candela)
44188		// by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
44189		return this.intensity * Math.PI;
44190
44191	}
44192
44193	set power( power ) {
44194
44195		// set the light's intensity (in candela) from the desired luminous power (in lumens)
44196		this.intensity = power / Math.PI;
44197
44198	}
44199
44200	dispose() {
44201
44202		this.shadow.dispose();
44203
44204	}
44205
44206	copy( source, recursive ) {
44207
44208		super.copy( source, recursive );
44209
44210		this.distance = source.distance;
44211		this.angle = source.angle;
44212		this.penumbra = source.penumbra;
44213		this.decay = source.decay;
44214
44215		this.target = source.target.clone();
44216
44217		this.shadow = source.shadow.clone();
44218
44219		return this;
44220
44221	}
44222
44223}
44224
44225const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
44226const _lightPositionWorld = /*@__PURE__*/ new Vector3();
44227const _lookTarget = /*@__PURE__*/ new Vector3();
44228
44229class PointLightShadow extends LightShadow {
44230
44231	constructor() {
44232
44233		super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
44234
44235		this.isPointLightShadow = true;
44236
44237		this._frameExtents = new Vector2( 4, 2 );
44238
44239		this._viewportCount = 6;
44240
44241		this._viewports = [
44242			// These viewports map a cube-map onto a 2D texture with the
44243			// following orientation:
44244			//
44245			//  xzXZ
44246			//   y Y
44247			//
44248			// X - Positive x direction
44249			// x - Negative x direction
44250			// Y - Positive y direction
44251			// y - Negative y direction
44252			// Z - Positive z direction
44253			// z - Negative z direction
44254
44255			// positive X
44256			new Vector4( 2, 1, 1, 1 ),
44257			// negative X
44258			new Vector4( 0, 1, 1, 1 ),
44259			// positive Z
44260			new Vector4( 3, 1, 1, 1 ),
44261			// negative Z
44262			new Vector4( 1, 1, 1, 1 ),
44263			// positive Y
44264			new Vector4( 3, 0, 1, 1 ),
44265			// negative Y
44266			new Vector4( 1, 0, 1, 1 )
44267		];
44268
44269		this._cubeDirections = [
44270			new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
44271			new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
44272		];
44273
44274		this._cubeUps = [
44275			new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
44276			new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),	new Vector3( 0, 0, - 1 )
44277		];
44278
44279	}
44280
44281	updateMatrices( light, viewportIndex = 0 ) {
44282
44283		const camera = this.camera;
44284		const shadowMatrix = this.matrix;
44285
44286		const far = light.distance || camera.far;
44287
44288		if ( far !== camera.far ) {
44289
44290			camera.far = far;
44291			camera.updateProjectionMatrix();
44292
44293		}
44294
44295		_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
44296		camera.position.copy( _lightPositionWorld );
44297
44298		_lookTarget.copy( camera.position );
44299		_lookTarget.add( this._cubeDirections[ viewportIndex ] );
44300		camera.up.copy( this._cubeUps[ viewportIndex ] );
44301		camera.lookAt( _lookTarget );
44302		camera.updateMatrixWorld();
44303
44304		shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
44305
44306		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
44307		this._frustum.setFromProjectionMatrix( _projScreenMatrix );
44308
44309	}
44310
44311}
44312
44313class PointLight extends Light {
44314
44315	constructor( color, intensity, distance = 0, decay = 2 ) {
44316
44317		super( color, intensity );
44318
44319		this.isPointLight = true;
44320
44321		this.type = 'PointLight';
44322
44323		this.distance = distance;
44324		this.decay = decay;
44325
44326		this.shadow = new PointLightShadow();
44327
44328	}
44329
44330	get power() {
44331
44332		// compute the light's luminous power (in lumens) from its intensity (in candela)
44333		// for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
44334		return this.intensity * 4 * Math.PI;
44335
44336	}
44337
44338	set power( power ) {
44339
44340		// set the light's intensity (in candela) from the desired luminous power (in lumens)
44341		this.intensity = power / ( 4 * Math.PI );
44342
44343	}
44344
44345	dispose() {
44346
44347		this.shadow.dispose();
44348
44349	}
44350
44351	copy( source, recursive ) {
44352
44353		super.copy( source, recursive );
44354
44355		this.distance = source.distance;
44356		this.decay = source.decay;
44357
44358		this.shadow = source.shadow.clone();
44359
44360		return this;
44361
44362	}
44363
44364}
44365
44366class DirectionalLightShadow extends LightShadow {
44367
44368	constructor() {
44369
vendor: 4,273 bytes, lines 44370-44591
44370		super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
44371
44372		this.isDirectionalLightShadow = true;
44373
44374	}
44375
44376}
44377
44378class DirectionalLight extends Light {
44379
44380	constructor( color, intensity ) {
44381
44382		super( color, intensity );
44383
44384		this.isDirectionalLight = true;
44385
44386		this.type = 'DirectionalLight';
44387
44388		this.position.copy( Object3D.DEFAULT_UP );
44389		this.updateMatrix();
44390
44391		this.target = new Object3D();
44392
44393		this.shadow = new DirectionalLightShadow();
44394
44395	}
44396
44397	dispose() {
44398
44399		this.shadow.dispose();
44400
44401	}
44402
44403	copy( source ) {
44404
44405		super.copy( source );
44406
44407		this.target = source.target.clone();
44408		this.shadow = source.shadow.clone();
44409
44410		return this;
44411
44412	}
44413
44414}
44415
44416class AmbientLight extends Light {
44417
44418	constructor( color, intensity ) {
44419
44420		super( color, intensity );
44421
44422		this.isAmbientLight = true;
44423
44424		this.type = 'AmbientLight';
44425
44426	}
44427
44428}
44429
44430class RectAreaLight extends Light {
44431
44432	constructor( color, intensity, width = 10, height = 10 ) {
44433
44434		super( color, intensity );
44435
44436		this.isRectAreaLight = true;
44437
44438		this.type = 'RectAreaLight';
44439
44440		this.width = width;
44441		this.height = height;
44442
44443	}
44444
44445	get power() {
44446
44447		// compute the light's luminous power (in lumens) from its intensity (in nits)
44448		return this.intensity * this.width * this.height * Math.PI;
44449
44450	}
44451
44452	set power( power ) {
44453
44454		// set the light's intensity (in nits) from the desired luminous power (in lumens)
44455		this.intensity = power / ( this.width * this.height * Math.PI );
44456
44457	}
44458
44459	copy( source ) {
44460
44461		super.copy( source );
44462
44463		this.width = source.width;
44464		this.height = source.height;
44465
44466		return this;
44467
44468	}
44469
44470	toJSON( meta ) {
44471
44472		const data = super.toJSON( meta );
44473
44474		data.object.width = this.width;
44475		data.object.height = this.height;
44476
44477		return data;
44478
44479	}
44480
44481}
44482
44483/**
44484 * Primary reference:
44485 *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
44486 *
44487 * Secondary reference:
44488 *   https://www.ppsloan.org/publications/StupidSH36.pdf
44489 */
44490
44491// 3-band SH defined by 9 coefficients
44492
44493class SphericalHarmonics3 {
44494
44495	constructor() {
44496
44497		this.isSphericalHarmonics3 = true;
44498
44499		this.coefficients = [];
44500
44501		for ( let i = 0; i < 9; i ++ ) {
44502
44503			this.coefficients.push( new Vector3() );
44504
44505		}
44506
44507	}
44508
44509	set( coefficients ) {
44510
44511		for ( let i = 0; i < 9; i ++ ) {
44512
44513			this.coefficients[ i ].copy( coefficients[ i ] );
44514
44515		}
44516
44517		return this;
44518
44519	}
44520
44521	zero() {
44522
44523		for ( let i = 0; i < 9; i ++ ) {
44524
44525			this.coefficients[ i ].set( 0, 0, 0 );
44526
44527		}
44528
44529		return this;
44530
44531	}
44532
44533	// get the radiance in the direction of the normal
44534	// target is a Vector3
44535	getAt( normal, target ) {
44536
44537		// normal is assumed to be unit length
44538
44539		const x = normal.x, y = normal.y, z = normal.z;
44540
44541		const coeff = this.coefficients;
44542
44543		// band 0
44544		target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
44545
44546		// band 1
44547		target.addScaledVector( coeff[ 1 ], 0.488603 * y );
44548		target.addScaledVector( coeff[ 2 ], 0.488603 * z );
44549		target.addScaledVector( coeff[ 3 ], 0.488603 * x );
44550
44551		// band 2
44552		target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
44553		target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
44554		target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
44555		target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
44556		target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
44557
44558		return target;
44559
44560	}
44561
44562	// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
44563	// target is a Vector3
44564	// https://graphics.stanford.edu/papers/envmap/envmap.pdf
44565	getIrradianceAt( normal, target ) {
44566
44567		// normal is assumed to be unit length
44568
44569		const x = normal.x, y = normal.y, z = normal.z;
44570
44571		const coeff = this.coefficients;
44572
44573		// band 0
44574		target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
44575
44576		// band 1
44577		target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
44578		target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
44579		target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
44580
44581		// band 2
44582		target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
44583		target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
44584		target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
44585		target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
44586		target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
44587
44588		return target;
44589
44590	}
44591
vendor: 39,804 bytes, lines 44592-46235
44592	add( sh ) {
44593
44594		for ( let i = 0; i < 9; i ++ ) {
44595
44596			this.coefficients[ i ].add( sh.coefficients[ i ] );
44597
44598		}
44599
44600		return this;
44601
44602	}
44603
44604	addScaledSH( sh, s ) {
44605
44606		for ( let i = 0; i < 9; i ++ ) {
44607
44608			this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
44609
44610		}
44611
44612		return this;
44613
44614	}
44615
44616	scale( s ) {
44617
44618		for ( let i = 0; i < 9; i ++ ) {
44619
44620			this.coefficients[ i ].multiplyScalar( s );
44621
44622		}
44623
44624		return this;
44625
44626	}
44627
44628	lerp( sh, alpha ) {
44629
44630		for ( let i = 0; i < 9; i ++ ) {
44631
44632			this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
44633
44634		}
44635
44636		return this;
44637
44638	}
44639
44640	equals( sh ) {
44641
44642		for ( let i = 0; i < 9; i ++ ) {
44643
44644			if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
44645
44646				return false;
44647
44648			}
44649
44650		}
44651
44652		return true;
44653
44654	}
44655
44656	copy( sh ) {
44657
44658		return this.set( sh.coefficients );
44659
44660	}
44661
44662	clone() {
44663
44664		return new this.constructor().copy( this );
44665
44666	}
44667
44668	fromArray( array, offset = 0 ) {
44669
44670		const coefficients = this.coefficients;
44671
44672		for ( let i = 0; i < 9; i ++ ) {
44673
44674			coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
44675
44676		}
44677
44678		return this;
44679
44680	}
44681
44682	toArray( array = [], offset = 0 ) {
44683
44684		const coefficients = this.coefficients;
44685
44686		for ( let i = 0; i < 9; i ++ ) {
44687
44688			coefficients[ i ].toArray( array, offset + ( i * 3 ) );
44689
44690		}
44691
44692		return array;
44693
44694	}
44695
44696	// evaluate the basis functions
44697	// shBasis is an Array[ 9 ]
44698	static getBasisAt( normal, shBasis ) {
44699
44700		// normal is assumed to be unit length
44701
44702		const x = normal.x, y = normal.y, z = normal.z;
44703
44704		// band 0
44705		shBasis[ 0 ] = 0.282095;
44706
44707		// band 1
44708		shBasis[ 1 ] = 0.488603 * y;
44709		shBasis[ 2 ] = 0.488603 * z;
44710		shBasis[ 3 ] = 0.488603 * x;
44711
44712		// band 2
44713		shBasis[ 4 ] = 1.092548 * x * y;
44714		shBasis[ 5 ] = 1.092548 * y * z;
44715		shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
44716		shBasis[ 7 ] = 1.092548 * x * z;
44717		shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
44718
44719	}
44720
44721}
44722
44723class LightProbe extends Light {
44724
44725	constructor( sh = new SphericalHarmonics3(), intensity = 1 ) {
44726
44727		super( undefined, intensity );
44728
44729		this.isLightProbe = true;
44730
44731		this.sh = sh;
44732
44733	}
44734
44735	copy( source ) {
44736
44737		super.copy( source );
44738
44739		this.sh.copy( source.sh );
44740
44741		return this;
44742
44743	}
44744
44745	fromJSON( json ) {
44746
44747		this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
44748		this.sh.fromArray( json.sh );
44749
44750		return this;
44751
44752	}
44753
44754	toJSON( meta ) {
44755
44756		const data = super.toJSON( meta );
44757
44758		data.object.sh = this.sh.toArray();
44759
44760		return data;
44761
44762	}
44763
44764}
44765
44766class MaterialLoader extends Loader {
44767
44768	constructor( manager ) {
44769
44770		super( manager );
44771		this.textures = {};
44772
44773	}
44774
44775	load( url, onLoad, onProgress, onError ) {
44776
44777		const scope = this;
44778
44779		const loader = new FileLoader( scope.manager );
44780		loader.setPath( scope.path );
44781		loader.setRequestHeader( scope.requestHeader );
44782		loader.setWithCredentials( scope.withCredentials );
44783		loader.load( url, function ( text ) {
44784
44785			try {
44786
44787				onLoad( scope.parse( JSON.parse( text ) ) );
44788
44789			} catch ( e ) {
44790
44791				if ( onError ) {
44792
44793					onError( e );
44794
44795				} else {
44796
44797					console.error( e );
44798
44799				}
44800
44801				scope.manager.itemError( url );
44802
44803			}
44804
44805		}, onProgress, onError );
44806
44807	}
44808
44809	parse( json ) {
44810
44811		const textures = this.textures;
44812
44813		function getTexture( name ) {
44814
44815			if ( textures[ name ] === undefined ) {
44816
44817				console.warn( 'THREE.MaterialLoader: Undefined texture', name );
44818
44819			}
44820
44821			return textures[ name ];
44822
44823		}
44824
44825		const material = MaterialLoader.createMaterialFromType( json.type );
44826
44827		if ( json.uuid !== undefined ) material.uuid = json.uuid;
44828		if ( json.name !== undefined ) material.name = json.name;
44829		if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
44830		if ( json.roughness !== undefined ) material.roughness = json.roughness;
44831		if ( json.metalness !== undefined ) material.metalness = json.metalness;
44832		if ( json.sheen !== undefined ) material.sheen = json.sheen;
44833		if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor );
44834		if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness;
44835		if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
44836		if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
44837		if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity;
44838		if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor );
44839		if ( json.shininess !== undefined ) material.shininess = json.shininess;
44840		if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
44841		if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
44842		if ( json.iridescence !== undefined ) material.iridescence = json.iridescence;
44843		if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR;
44844		if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange;
44845		if ( json.transmission !== undefined ) material.transmission = json.transmission;
44846		if ( json.thickness !== undefined ) material.thickness = json.thickness;
44847		if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance;
44848		if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor );
44849		if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy;
44850		if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation;
44851		if ( json.fog !== undefined ) material.fog = json.fog;
44852		if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
44853		if ( json.blending !== undefined ) material.blending = json.blending;
44854		if ( json.combine !== undefined ) material.combine = json.combine;
44855		if ( json.side !== undefined ) material.side = json.side;
44856		if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide;
44857		if ( json.opacity !== undefined ) material.opacity = json.opacity;
44858		if ( json.transparent !== undefined ) material.transparent = json.transparent;
44859		if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
44860		if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash;
44861		if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc;
44862		if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
44863		if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
44864		if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
44865		if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc;
44866		if ( json.blendDst !== undefined ) material.blendDst = json.blendDst;
44867		if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation;
44868		if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha;
44869		if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha;
44870		if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha;
44871		if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor );
44872		if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha;
44873		if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
44874		if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
44875		if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
44876		if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
44877		if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
44878		if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
44879		if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
44880		if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
44881
44882		if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
44883		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
44884		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
44885		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
44886
44887		if ( json.rotation !== undefined ) material.rotation = json.rotation;
44888
44889		if ( json.linewidth !== undefined ) material.linewidth = json.linewidth;
44890		if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
44891		if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
44892		if ( json.scale !== undefined ) material.scale = json.scale;
44893
44894		if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
44895		if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
44896		if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
44897
44898		if ( json.dithering !== undefined ) material.dithering = json.dithering;
44899
44900		if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage;
44901		if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha;
44902		if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass;
44903
44904		if ( json.visible !== undefined ) material.visible = json.visible;
44905
44906		if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
44907
44908		if ( json.userData !== undefined ) material.userData = json.userData;
44909
44910		if ( json.vertexColors !== undefined ) {
44911
44912			if ( typeof json.vertexColors === 'number' ) {
44913
44914				material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
44915
44916			} else {
44917
44918				material.vertexColors = json.vertexColors;
44919
44920			}
44921
44922		}
44923
44924		// Shader Material
44925
44926		if ( json.uniforms !== undefined ) {
44927
44928			for ( const name in json.uniforms ) {
44929
44930				const uniform = json.uniforms[ name ];
44931
44932				material.uniforms[ name ] = {};
44933
44934				switch ( uniform.type ) {
44935
44936					case 't':
44937						material.uniforms[ name ].value = getTexture( uniform.value );
44938						break;
44939
44940					case 'c':
44941						material.uniforms[ name ].value = new Color().setHex( uniform.value );
44942						break;
44943
44944					case 'v2':
44945						material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
44946						break;
44947
44948					case 'v3':
44949						material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
44950						break;
44951
44952					case 'v4':
44953						material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
44954						break;
44955
44956					case 'm3':
44957						material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
44958						break;
44959
44960					case 'm4':
44961						material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
44962						break;
44963
44964					default:
44965						material.uniforms[ name ].value = uniform.value;
44966
44967				}
44968
44969			}
44970
44971		}
44972
44973		if ( json.defines !== undefined ) material.defines = json.defines;
44974		if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
44975		if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
44976		if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion;
44977
44978		if ( json.extensions !== undefined ) {
44979
44980			for ( const key in json.extensions ) {
44981
44982				material.extensions[ key ] = json.extensions[ key ];
44983
44984			}
44985
44986		}
44987
44988		if ( json.lights !== undefined ) material.lights = json.lights;
44989		if ( json.clipping !== undefined ) material.clipping = json.clipping;
44990
44991		// for PointsMaterial
44992
44993		if ( json.size !== undefined ) material.size = json.size;
44994		if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
44995
44996		// maps
44997
44998		if ( json.map !== undefined ) material.map = getTexture( json.map );
44999		if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
45000
45001		if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
45002
45003		if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
45004		if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
45005
45006		if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
45007		if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
45008		if ( json.normalScale !== undefined ) {
45009
45010			let normalScale = json.normalScale;
45011
45012			if ( Array.isArray( normalScale ) === false ) {
45013
45014				// Blender exporter used to export a scalar. See #7459
45015
45016				normalScale = [ normalScale, normalScale ];
45017
45018			}
45019
45020			material.normalScale = new Vector2().fromArray( normalScale );
45021
45022		}
45023
45024		if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
45025		if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
45026		if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
45027
45028		if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
45029		if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
45030
45031		if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
45032		if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
45033
45034		if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
45035		if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap );
45036		if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap );
45037
45038		if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
45039		if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation );
45040		if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
45041
45042		if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
45043		if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
45044
45045		if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
45046		if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
45047
45048		if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
45049		if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
45050
45051		if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
45052
45053		if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
45054		if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
45055		if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
45056		if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
45057
45058		if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap );
45059		if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap );
45060
45061		if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
45062		if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap );
45063
45064		if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap );
45065
45066		if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap );
45067		if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap );
45068
45069		return material;
45070
45071	}
45072
45073	setTextures( value ) {
45074
45075		this.textures = value;
45076		return this;
45077
45078	}
45079
45080	static createMaterialFromType( type ) {
45081
45082		const materialLib = {
45083			ShadowMaterial,
45084			SpriteMaterial,
45085			RawShaderMaterial,
45086			ShaderMaterial,
45087			PointsMaterial,
45088			MeshPhysicalMaterial,
45089			MeshStandardMaterial,
45090			MeshPhongMaterial,
45091			MeshToonMaterial,
45092			MeshNormalMaterial,
45093			MeshLambertMaterial,
45094			MeshDepthMaterial,
45095			MeshDistanceMaterial,
45096			MeshBasicMaterial,
45097			MeshMatcapMaterial,
45098			LineDashedMaterial,
45099			LineBasicMaterial,
45100			Material
45101		};
45102
45103		return new materialLib[ type ]();
45104
45105	}
45106
45107}
45108
45109class LoaderUtils {
45110
45111	static decodeText( array ) {
45112
45113		if ( typeof TextDecoder !== 'undefined' ) {
45114
45115			return new TextDecoder().decode( array );
45116
45117		}
45118
45119		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
45120		// throws a "maximum call stack size exceeded" error for large arrays.
45121
45122		let s = '';
45123
45124		for ( let i = 0, il = array.length; i < il; i ++ ) {
45125
45126			// Implicitly assumes little-endian.
45127			s += String.fromCharCode( array[ i ] );
45128
45129		}
45130
45131		try {
45132
45133			// merges multi-byte utf-8 characters.
45134
45135			return decodeURIComponent( escape( s ) );
45136
45137		} catch ( e ) { // see #16358
45138
45139			return s;
45140
45141		}
45142
45143	}
45144
45145	static extractUrlBase( url ) {
45146
45147		const index = url.lastIndexOf( '/' );
45148
45149		if ( index === - 1 ) return './';
45150
45151		return url.slice( 0, index + 1 );
45152
45153	}
45154
45155	static resolveURL( url, path ) {
45156
45157		// Invalid URL
45158		if ( typeof url !== 'string' || url === '' ) return '';
45159
45160		// Host Relative URL
45161		if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
45162
45163			path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
45164
45165		}
45166
45167		// Absolute URL http://,https://,//
45168		if ( /^(https?:)?\/\//i.test( url ) ) return url;
45169
45170		// Data URI
45171		if ( /^data:.*,.*$/i.test( url ) ) return url;
45172
45173		// Blob URL
45174		if ( /^blob:.*$/i.test( url ) ) return url;
45175
45176		// Relative URL
45177		return path + url;
45178
45179	}
45180
45181}
45182
45183class InstancedBufferGeometry extends BufferGeometry {
45184
45185	constructor() {
45186
45187		super();
45188
45189		this.isInstancedBufferGeometry = true;
45190
45191		this.type = 'InstancedBufferGeometry';
45192		this.instanceCount = Infinity;
45193
45194	}
45195
45196	copy( source ) {
45197
45198		super.copy( source );
45199
45200		this.instanceCount = source.instanceCount;
45201
45202		return this;
45203
45204	}
45205
45206	toJSON() {
45207
45208		const data = super.toJSON();
45209
45210		data.instanceCount = this.instanceCount;
45211
45212		data.isInstancedBufferGeometry = true;
45213
45214		return data;
45215
45216	}
45217
45218}
45219
45220class BufferGeometryLoader extends Loader {
45221
45222	constructor( manager ) {
45223
45224		super( manager );
45225
45226	}
45227
45228	load( url, onLoad, onProgress, onError ) {
45229
45230		const scope = this;
45231
45232		const loader = new FileLoader( scope.manager );
45233		loader.setPath( scope.path );
45234		loader.setRequestHeader( scope.requestHeader );
45235		loader.setWithCredentials( scope.withCredentials );
45236		loader.load( url, function ( text ) {
45237
45238			try {
45239
45240				onLoad( scope.parse( JSON.parse( text ) ) );
45241
45242			} catch ( e ) {
45243
45244				if ( onError ) {
45245
45246					onError( e );
45247
45248				} else {
45249
45250					console.error( e );
45251
45252				}
45253
45254				scope.manager.itemError( url );
45255
45256			}
45257
45258		}, onProgress, onError );
45259
45260	}
45261
45262	parse( json ) {
45263
45264		const interleavedBufferMap = {};
45265		const arrayBufferMap = {};
45266
45267		function getInterleavedBuffer( json, uuid ) {
45268
45269			if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
45270
45271			const interleavedBuffers = json.interleavedBuffers;
45272			const interleavedBuffer = interleavedBuffers[ uuid ];
45273
45274			const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
45275
45276			const array = getTypedArray( interleavedBuffer.type, buffer );
45277			const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
45278			ib.uuid = interleavedBuffer.uuid;
45279
45280			interleavedBufferMap[ uuid ] = ib;
45281
45282			return ib;
45283
45284		}
45285
45286		function getArrayBuffer( json, uuid ) {
45287
45288			if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
45289
45290			const arrayBuffers = json.arrayBuffers;
45291			const arrayBuffer = arrayBuffers[ uuid ];
45292
45293			const ab = new Uint32Array( arrayBuffer ).buffer;
45294
45295			arrayBufferMap[ uuid ] = ab;
45296
45297			return ab;
45298
45299		}
45300
45301		const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
45302
45303		const index = json.data.index;
45304
45305		if ( index !== undefined ) {
45306
45307			const typedArray = getTypedArray( index.type, index.array );
45308			geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
45309
45310		}
45311
45312		const attributes = json.data.attributes;
45313
45314		for ( const key in attributes ) {
45315
45316			const attribute = attributes[ key ];
45317			let bufferAttribute;
45318
45319			if ( attribute.isInterleavedBufferAttribute ) {
45320
45321				const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
45322				bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
45323
45324			} else {
45325
45326				const typedArray = getTypedArray( attribute.type, attribute.array );
45327				const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
45328				bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
45329
45330			}
45331
45332			if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
45333			if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
45334
45335			geometry.setAttribute( key, bufferAttribute );
45336
45337		}
45338
45339		const morphAttributes = json.data.morphAttributes;
45340
45341		if ( morphAttributes ) {
45342
45343			for ( const key in morphAttributes ) {
45344
45345				const attributeArray = morphAttributes[ key ];
45346
45347				const array = [];
45348
45349				for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
45350
45351					const attribute = attributeArray[ i ];
45352					let bufferAttribute;
45353
45354					if ( attribute.isInterleavedBufferAttribute ) {
45355
45356						const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
45357						bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
45358
45359					} else {
45360
45361						const typedArray = getTypedArray( attribute.type, attribute.array );
45362						bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
45363
45364					}
45365
45366					if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
45367					array.push( bufferAttribute );
45368
45369				}
45370
45371				geometry.morphAttributes[ key ] = array;
45372
45373			}
45374
45375		}
45376
45377		const morphTargetsRelative = json.data.morphTargetsRelative;
45378
45379		if ( morphTargetsRelative ) {
45380
45381			geometry.morphTargetsRelative = true;
45382
45383		}
45384
45385		const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
45386
45387		if ( groups !== undefined ) {
45388
45389			for ( let i = 0, n = groups.length; i !== n; ++ i ) {
45390
45391				const group = groups[ i ];
45392
45393				geometry.addGroup( group.start, group.count, group.materialIndex );
45394
45395			}
45396
45397		}
45398
45399		const boundingSphere = json.data.boundingSphere;
45400
45401		if ( boundingSphere !== undefined ) {
45402
45403			const center = new Vector3();
45404
45405			if ( boundingSphere.center !== undefined ) {
45406
45407				center.fromArray( boundingSphere.center );
45408
45409			}
45410
45411			geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
45412
45413		}
45414
45415		if ( json.name ) geometry.name = json.name;
45416		if ( json.userData ) geometry.userData = json.userData;
45417
45418		return geometry;
45419
45420	}
45421
45422}
45423
45424class ObjectLoader extends Loader {
45425
45426	constructor( manager ) {
45427
45428		super( manager );
45429
45430	}
45431
45432	load( url, onLoad, onProgress, onError ) {
45433
45434		const scope = this;
45435
45436		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
45437		this.resourcePath = this.resourcePath || path;
45438
45439		const loader = new FileLoader( this.manager );
45440		loader.setPath( this.path );
45441		loader.setRequestHeader( this.requestHeader );
45442		loader.setWithCredentials( this.withCredentials );
45443		loader.load( url, function ( text ) {
45444
45445			let json = null;
45446
45447			try {
45448
45449				json = JSON.parse( text );
45450
45451			} catch ( error ) {
45452
45453				if ( onError !== undefined ) onError( error );
45454
45455				console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
45456
45457				return;
45458
45459			}
45460
45461			const metadata = json.metadata;
45462
45463			if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
45464
45465				if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) );
45466
45467				console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
45468				return;
45469
45470			}
45471
45472			scope.parse( json, onLoad );
45473
45474		}, onProgress, onError );
45475
45476	}
45477
45478	async loadAsync( url, onProgress ) {
45479
45480		const scope = this;
45481
45482		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
45483		this.resourcePath = this.resourcePath || path;
45484
45485		const loader = new FileLoader( this.manager );
45486		loader.setPath( this.path );
45487		loader.setRequestHeader( this.requestHeader );
45488		loader.setWithCredentials( this.withCredentials );
45489
45490		const text = await loader.loadAsync( url, onProgress );
45491
45492		const json = JSON.parse( text );
45493
45494		const metadata = json.metadata;
45495
45496		if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
45497
45498			throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url );
45499
45500		}
45501
45502		return await scope.parseAsync( json );
45503
45504	}
45505
45506	parse( json, onLoad ) {
45507
45508		const animations = this.parseAnimations( json.animations );
45509		const shapes = this.parseShapes( json.shapes );
45510		const geometries = this.parseGeometries( json.geometries, shapes );
45511
45512		const images = this.parseImages( json.images, function () {
45513
45514			if ( onLoad !== undefined ) onLoad( object );
45515
45516		} );
45517
45518		const textures = this.parseTextures( json.textures, images );
45519		const materials = this.parseMaterials( json.materials, textures );
45520
45521		const object = this.parseObject( json.object, geometries, materials, textures, animations );
45522		const skeletons = this.parseSkeletons( json.skeletons, object );
45523
45524		this.bindSkeletons( object, skeletons );
45525
45526		//
45527
45528		if ( onLoad !== undefined ) {
45529
45530			let hasImages = false;
45531
45532			for ( const uuid in images ) {
45533
45534				if ( images[ uuid ].data instanceof HTMLImageElement ) {
45535
45536					hasImages = true;
45537					break;
45538
45539				}
45540
45541			}
45542
45543			if ( hasImages === false ) onLoad( object );
45544
45545		}
45546
45547		return object;
45548
45549	}
45550
45551	async parseAsync( json ) {
45552
45553		const animations = this.parseAnimations( json.animations );
45554		const shapes = this.parseShapes( json.shapes );
45555		const geometries = this.parseGeometries( json.geometries, shapes );
45556
45557		const images = await this.parseImagesAsync( json.images );
45558
45559		const textures = this.parseTextures( json.textures, images );
45560		const materials = this.parseMaterials( json.materials, textures );
45561
45562		const object = this.parseObject( json.object, geometries, materials, textures, animations );
45563		const skeletons = this.parseSkeletons( json.skeletons, object );
45564
45565		this.bindSkeletons( object, skeletons );
45566
45567		return object;
45568
45569	}
45570
45571	parseShapes( json ) {
45572
45573		const shapes = {};
45574
45575		if ( json !== undefined ) {
45576
45577			for ( let i = 0, l = json.length; i < l; i ++ ) {
45578
45579				const shape = new Shape().fromJSON( json[ i ] );
45580
45581				shapes[ shape.uuid ] = shape;
45582
45583			}
45584
45585		}
45586
45587		return shapes;
45588
45589	}
45590
45591	parseSkeletons( json, object ) {
45592
45593		const skeletons = {};
45594		const bones = {};
45595
45596		// generate bone lookup table
45597
45598		object.traverse( function ( child ) {
45599
45600			if ( child.isBone ) bones[ child.uuid ] = child;
45601
45602		} );
45603
45604		// create skeletons
45605
45606		if ( json !== undefined ) {
45607
45608			for ( let i = 0, l = json.length; i < l; i ++ ) {
45609
45610				const skeleton = new Skeleton().fromJSON( json[ i ], bones );
45611
45612				skeletons[ skeleton.uuid ] = skeleton;
45613
45614			}
45615
45616		}
45617
45618		return skeletons;
45619
45620	}
45621
45622	parseGeometries( json, shapes ) {
45623
45624		const geometries = {};
45625
45626		if ( json !== undefined ) {
45627
45628			const bufferGeometryLoader = new BufferGeometryLoader();
45629
45630			for ( let i = 0, l = json.length; i < l; i ++ ) {
45631
45632				let geometry;
45633				const data = json[ i ];
45634
45635				switch ( data.type ) {
45636
45637					case 'BufferGeometry':
45638					case 'InstancedBufferGeometry':
45639
45640						geometry = bufferGeometryLoader.parse( data );
45641						break;
45642
45643					default:
45644
45645						if ( data.type in Geometries ) {
45646
45647							geometry = Geometries[ data.type ].fromJSON( data, shapes );
45648
45649						} else {
45650
45651							console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` );
45652
45653						}
45654
45655				}
45656
45657				geometry.uuid = data.uuid;
45658
45659				if ( data.name !== undefined ) geometry.name = data.name;
45660				if ( data.userData !== undefined ) geometry.userData = data.userData;
45661
45662				geometries[ data.uuid ] = geometry;
45663
45664			}
45665
45666		}
45667
45668		return geometries;
45669
45670	}
45671
45672	parseMaterials( json, textures ) {
45673
45674		const cache = {}; // MultiMaterial
45675		const materials = {};
45676
45677		if ( json !== undefined ) {
45678
45679			const loader = new MaterialLoader();
45680			loader.setTextures( textures );
45681
45682			for ( let i = 0, l = json.length; i < l; i ++ ) {
45683
45684				const data = json[ i ];
45685
45686				if ( cache[ data.uuid ] === undefined ) {
45687
45688					cache[ data.uuid ] = loader.parse( data );
45689
45690				}
45691
45692				materials[ data.uuid ] = cache[ data.uuid ];
45693
45694			}
45695
45696		}
45697
45698		return materials;
45699
45700	}
45701
45702	parseAnimations( json ) {
45703
45704		const animations = {};
45705
45706		if ( json !== undefined ) {
45707
45708			for ( let i = 0; i < json.length; i ++ ) {
45709
45710				const data = json[ i ];
45711
45712				const clip = AnimationClip.parse( data );
45713
45714				animations[ clip.uuid ] = clip;
45715
45716			}
45717
45718		}
45719
45720		return animations;
45721
45722	}
45723
45724	parseImages( json, onLoad ) {
45725
45726		const scope = this;
45727		const images = {};
45728
45729		let loader;
45730
45731		function loadImage( url ) {
45732
45733			scope.manager.itemStart( url );
45734
45735			return loader.load( url, function () {
45736
45737				scope.manager.itemEnd( url );
45738
45739			}, undefined, function () {
45740
45741				scope.manager.itemError( url );
45742				scope.manager.itemEnd( url );
45743
45744			} );
45745
45746		}
45747
45748		function deserializeImage( image ) {
45749
45750			if ( typeof image === 'string' ) {
45751
45752				const url = image;
45753
45754				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
45755
45756				return loadImage( path );
45757
45758			} else {
45759
45760				if ( image.data ) {
45761
45762					return {
45763						data: getTypedArray( image.type, image.data ),
45764						width: image.width,
45765						height: image.height
45766					};
45767
45768				} else {
45769
45770					return null;
45771
45772				}
45773
45774			}
45775
45776		}
45777
45778		if ( json !== undefined && json.length > 0 ) {
45779
45780			const manager = new LoadingManager( onLoad );
45781
45782			loader = new ImageLoader( manager );
45783			loader.setCrossOrigin( this.crossOrigin );
45784
45785			for ( let i = 0, il = json.length; i < il; i ++ ) {
45786
45787				const image = json[ i ];
45788				const url = image.url;
45789
45790				if ( Array.isArray( url ) ) {
45791
45792					// load array of images e.g CubeTexture
45793
45794					const imageArray = [];
45795
45796					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
45797
45798						const currentUrl = url[ j ];
45799
45800						const deserializedImage = deserializeImage( currentUrl );
45801
45802						if ( deserializedImage !== null ) {
45803
45804							if ( deserializedImage instanceof HTMLImageElement ) {
45805
45806								imageArray.push( deserializedImage );
45807
45808							} else {
45809
45810								// special case: handle array of data textures for cube textures
45811
45812								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
45813
45814							}
45815
45816						}
45817
45818					}
45819
45820					images[ image.uuid ] = new Source( imageArray );
45821
45822				} else {
45823
45824					// load single image
45825
45826					const deserializedImage = deserializeImage( image.url );
45827					images[ image.uuid ] = new Source( deserializedImage );
45828
45829
45830				}
45831
45832			}
45833
45834		}
45835
45836		return images;
45837
45838	}
45839
45840	async parseImagesAsync( json ) {
45841
45842		const scope = this;
45843		const images = {};
45844
45845		let loader;
45846
45847		async function deserializeImage( image ) {
45848
45849			if ( typeof image === 'string' ) {
45850
45851				const url = image;
45852
45853				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
45854
45855				return await loader.loadAsync( path );
45856
45857			} else {
45858
45859				if ( image.data ) {
45860
45861					return {
45862						data: getTypedArray( image.type, image.data ),
45863						width: image.width,
45864						height: image.height
45865					};
45866
45867				} else {
45868
45869					return null;
45870
45871				}
45872
45873			}
45874
45875		}
45876
45877		if ( json !== undefined && json.length > 0 ) {
45878
45879			loader = new ImageLoader( this.manager );
45880			loader.setCrossOrigin( this.crossOrigin );
45881
45882			for ( let i = 0, il = json.length; i < il; i ++ ) {
45883
45884				const image = json[ i ];
45885				const url = image.url;
45886
45887				if ( Array.isArray( url ) ) {
45888
45889					// load array of images e.g CubeTexture
45890
45891					const imageArray = [];
45892
45893					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
45894
45895						const currentUrl = url[ j ];
45896
45897						const deserializedImage = await deserializeImage( currentUrl );
45898
45899						if ( deserializedImage !== null ) {
45900
45901							if ( deserializedImage instanceof HTMLImageElement ) {
45902
45903								imageArray.push( deserializedImage );
45904
45905							} else {
45906
45907								// special case: handle array of data textures for cube textures
45908
45909								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
45910
45911							}
45912
45913						}
45914
45915					}
45916
45917					images[ image.uuid ] = new Source( imageArray );
45918
45919				} else {
45920
45921					// load single image
45922
45923					const deserializedImage = await deserializeImage( image.url );
45924					images[ image.uuid ] = new Source( deserializedImage );
45925
45926				}
45927
45928			}
45929
45930		}
45931
45932		return images;
45933
45934	}
45935
45936	parseTextures( json, images ) {
45937
45938		function parseConstant( value, type ) {
45939
45940			if ( typeof value === 'number' ) return value;
45941
45942			console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
45943
45944			return type[ value ];
45945
45946		}
45947
45948		const textures = {};
45949
45950		if ( json !== undefined ) {
45951
45952			for ( let i = 0, l = json.length; i < l; i ++ ) {
45953
45954				const data = json[ i ];
45955
45956				if ( data.image === undefined ) {
45957
45958					console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
45959
45960				}
45961
45962				if ( images[ data.image ] === undefined ) {
45963
45964					console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
45965
45966				}
45967
45968				const source = images[ data.image ];
45969				const image = source.data;
45970
45971				let texture;
45972
45973				if ( Array.isArray( image ) ) {
45974
45975					texture = new CubeTexture();
45976
45977					if ( image.length === 6 ) texture.needsUpdate = true;
45978
45979				} else {
45980
45981					if ( image && image.data ) {
45982
45983						texture = new DataTexture();
45984
45985					} else {
45986
45987						texture = new Texture();
45988
45989					}
45990
45991					if ( image ) texture.needsUpdate = true; // textures can have undefined image data
45992
45993				}
45994
45995				texture.source = source;
45996
45997				texture.uuid = data.uuid;
45998
45999				if ( data.name !== undefined ) texture.name = data.name;
46000
46001				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
46002				if ( data.channel !== undefined ) texture.channel = data.channel;
46003
46004				if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
46005				if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
46006				if ( data.center !== undefined ) texture.center.fromArray( data.center );
46007				if ( data.rotation !== undefined ) texture.rotation = data.rotation;
46008
46009				if ( data.wrap !== undefined ) {
46010
46011					texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
46012					texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
46013
46014				}
46015
46016				if ( data.format !== undefined ) texture.format = data.format;
46017				if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat;
46018				if ( data.type !== undefined ) texture.type = data.type;
46019				if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace;
46020
46021				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
46022				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
46023				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
46024
46025				if ( data.flipY !== undefined ) texture.flipY = data.flipY;
46026
46027				if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps;
46028				if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
46029				if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
46030				if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction;
46031
46032				if ( data.userData !== undefined ) texture.userData = data.userData;
46033
46034				textures[ data.uuid ] = texture;
46035
46036			}
46037
46038		}
46039
46040		return textures;
46041
46042	}
46043
46044	parseObject( data, geometries, materials, textures, animations ) {
46045
46046		let object;
46047
46048		function getGeometry( name ) {
46049
46050			if ( geometries[ name ] === undefined ) {
46051
46052				console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
46053
46054			}
46055
46056			return geometries[ name ];
46057
46058		}
46059
46060		function getMaterial( name ) {
46061
46062			if ( name === undefined ) return undefined;
46063
46064			if ( Array.isArray( name ) ) {
46065
46066				const array = [];
46067
46068				for ( let i = 0, l = name.length; i < l; i ++ ) {
46069
46070					const uuid = name[ i ];
46071
46072					if ( materials[ uuid ] === undefined ) {
46073
46074						console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
46075
46076					}
46077
46078					array.push( materials[ uuid ] );
46079
46080				}
46081
46082				return array;
46083
46084			}
46085
46086			if ( materials[ name ] === undefined ) {
46087
46088				console.warn( 'THREE.ObjectLoader: Undefined material', name );
46089
46090			}
46091
46092			return materials[ name ];
46093
46094		}
46095
46096		function getTexture( uuid ) {
46097
46098			if ( textures[ uuid ] === undefined ) {
46099
46100				console.warn( 'THREE.ObjectLoader: Undefined texture', uuid );
46101
46102			}
46103
46104			return textures[ uuid ];
46105
46106		}
46107
46108		let geometry, material;
46109
46110		switch ( data.type ) {
46111
46112			case 'Scene':
46113
46114				object = new Scene();
46115
46116				if ( data.background !== undefined ) {
46117
46118					if ( Number.isInteger( data.background ) ) {
46119
46120						object.background = new Color( data.background );
46121
46122					} else {
46123
46124						object.background = getTexture( data.background );
46125
46126					}
46127
46128				}
46129
46130				if ( data.environment !== undefined ) {
46131
46132					object.environment = getTexture( data.environment );
46133
46134				}
46135
46136				if ( data.fog !== undefined ) {
46137
46138					if ( data.fog.type === 'Fog' ) {
46139
46140						object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
46141
46142					} else if ( data.fog.type === 'FogExp2' ) {
46143
46144						object.fog = new FogExp2( data.fog.color, data.fog.density );
46145
46146					}
46147
46148					if ( data.fog.name !== '' ) {
46149
46150						object.fog.name = data.fog.name;
46151
46152					}
46153
46154				}
46155
46156				if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness;
46157				if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity;
46158				if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation );
46159
46160				if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity;
46161				if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation );
46162
46163				break;
46164
46165			case 'PerspectiveCamera':
46166
46167				object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
46168
46169				if ( data.focus !== undefined ) object.focus = data.focus;
46170				if ( data.zoom !== undefined ) object.zoom = data.zoom;
46171				if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
46172				if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
46173				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46174
46175				break;
46176
46177			case 'OrthographicCamera':
46178
46179				object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
46180
46181				if ( data.zoom !== undefined ) object.zoom = data.zoom;
46182				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46183
46184				break;
46185
46186			case 'AmbientLight':
46187
46188				object = new AmbientLight( data.color, data.intensity );
46189
46190				break;
46191
46192			case 'DirectionalLight':
46193
46194				object = new DirectionalLight( data.color, data.intensity );
46195
46196				break;
46197
46198			case 'PointLight':
46199
46200				object = new PointLight( data.color, data.intensity, data.distance, data.decay );
46201
46202				break;
46203
46204			case 'RectAreaLight':
46205
46206				object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
46207
46208				break;
46209
46210			case 'SpotLight':
46211
46212				object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
46213
46214				break;
46215
46216			case 'HemisphereLight':
46217
46218				object = new HemisphereLight( data.color, data.groundColor, data.intensity );
46219
46220				break;
46221
46222			case 'LightProbe':
46223
46224				object = new LightProbe().fromJSON( data );
46225
46226				break;
46227
46228			case 'SkinnedMesh':
46229
46230				geometry = getGeometry( data.geometry );
46231			 	material = getMaterial( data.material );
46232
46233				object = new SkinnedMesh( geometry, material );
46234
46235				if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
vendor: 17,451 bytes, lines 46236-47066
46236				if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
46237				if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
46238
46239				break;
46240
46241			case 'Mesh':
46242
46243				geometry = getGeometry( data.geometry );
46244				material = getMaterial( data.material );
46245
46246				object = new Mesh( geometry, material );
46247
46248				break;
46249
46250			case 'InstancedMesh':
46251
46252				geometry = getGeometry( data.geometry );
46253				material = getMaterial( data.material );
46254				const count = data.count;
46255				const instanceMatrix = data.instanceMatrix;
46256				const instanceColor = data.instanceColor;
46257
46258				object = new InstancedMesh( geometry, material, count );
46259				object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
46260				if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
46261
46262				break;
46263
46264			case 'BatchedMesh':
46265
46266				geometry = getGeometry( data.geometry );
46267				material = getMaterial( data.material );
46268
46269				object = new BatchedMesh( data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material );
46270				object.geometry = geometry;
46271				object.perObjectFrustumCulled = data.perObjectFrustumCulled;
46272				object.sortObjects = data.sortObjects;
46273
46274				object._drawRanges = data.drawRanges;
46275				object._reservedRanges = data.reservedRanges;
46276
46277				object._visibility = data.visibility;
46278				object._active = data.active;
46279				object._bounds = data.bounds.map( bound => {
46280
46281					const box = new Box3();
46282					box.min.fromArray( bound.boxMin );
46283					box.max.fromArray( bound.boxMax );
46284
46285					const sphere = new Sphere();
46286					sphere.radius = bound.sphereRadius;
46287					sphere.center.fromArray( bound.sphereCenter );
46288
46289					return {
46290						boxInitialized: bound.boxInitialized,
46291						box: box,
46292
46293						sphereInitialized: bound.sphereInitialized,
46294						sphere: sphere
46295					};
46296
46297				} );
46298
46299				object._maxGeometryCount = data.maxGeometryCount;
46300				object._maxVertexCount = data.maxVertexCount;
46301				object._maxIndexCount = data.maxIndexCount;
46302
46303				object._geometryInitialized = data.geometryInitialized;
46304				object._geometryCount = data.geometryCount;
46305
46306				object._matricesTexture = getTexture( data.matricesTexture.uuid );
46307
46308				break;
46309
46310			case 'LOD':
46311
46312				object = new LOD();
46313
46314				break;
46315
46316			case 'Line':
46317
46318				object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
46319
46320				break;
46321
46322			case 'LineLoop':
46323
46324				object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
46325
46326				break;
46327
46328			case 'LineSegments':
46329
46330				object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
46331
46332				break;
46333
46334			case 'PointCloud':
46335			case 'Points':
46336
46337				object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
46338
46339				break;
46340
46341			case 'Sprite':
46342
46343				object = new Sprite( getMaterial( data.material ) );
46344
46345				break;
46346
46347			case 'Group':
46348
46349				object = new Group();
46350
46351				break;
46352
46353			case 'Bone':
46354
46355				object = new Bone();
46356
46357				break;
46358
46359			default:
46360
46361				object = new Object3D();
46362
46363		}
46364
46365		object.uuid = data.uuid;
46366
46367		if ( data.name !== undefined ) object.name = data.name;
46368
46369		if ( data.matrix !== undefined ) {
46370
46371			object.matrix.fromArray( data.matrix );
46372
46373			if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
46374			if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
46375
46376		} else {
46377
46378			if ( data.position !== undefined ) object.position.fromArray( data.position );
46379			if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
46380			if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
46381			if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
46382
46383		}
46384
46385		if ( data.up !== undefined ) object.up.fromArray( data.up );
46386
46387		if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
46388		if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
46389
46390		if ( data.shadow ) {
46391
46392			if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
46393			if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
46394			if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
46395			if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
46396			if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
46397
46398		}
46399
46400		if ( data.visible !== undefined ) object.visible = data.visible;
46401		if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
46402		if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
46403		if ( data.userData !== undefined ) object.userData = data.userData;
46404		if ( data.layers !== undefined ) object.layers.mask = data.layers;
46405
46406		if ( data.children !== undefined ) {
46407
46408			const children = data.children;
46409
46410			for ( let i = 0; i < children.length; i ++ ) {
46411
46412				object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) );
46413
46414			}
46415
46416		}
46417
46418		if ( data.animations !== undefined ) {
46419
46420			const objectAnimations = data.animations;
46421
46422			for ( let i = 0; i < objectAnimations.length; i ++ ) {
46423
46424				const uuid = objectAnimations[ i ];
46425
46426				object.animations.push( animations[ uuid ] );
46427
46428			}
46429
46430		}
46431
46432		if ( data.type === 'LOD' ) {
46433
46434			if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
46435
46436			const levels = data.levels;
46437
46438			for ( let l = 0; l < levels.length; l ++ ) {
46439
46440				const level = levels[ l ];
46441				const child = object.getObjectByProperty( 'uuid', level.object );
46442
46443				if ( child !== undefined ) {
46444
46445					object.addLevel( child, level.distance, level.hysteresis );
46446
46447				}
46448
46449			}
46450
46451		}
46452
46453		return object;
46454
46455	}
46456
46457	bindSkeletons( object, skeletons ) {
46458
46459		if ( Object.keys( skeletons ).length === 0 ) return;
46460
46461		object.traverse( function ( child ) {
46462
46463			if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
46464
46465				const skeleton = skeletons[ child.skeleton ];
46466
46467				if ( skeleton === undefined ) {
46468
46469					console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton );
46470
46471				} else {
46472
46473					child.bind( skeleton, child.bindMatrix );
46474
46475				}
46476
46477			}
46478
46479		} );
46480
46481	}
46482
46483}
46484
46485const TEXTURE_MAPPING = {
46486	UVMapping: UVMapping,
46487	CubeReflectionMapping: CubeReflectionMapping,
46488	CubeRefractionMapping: CubeRefractionMapping,
46489	EquirectangularReflectionMapping: EquirectangularReflectionMapping,
46490	EquirectangularRefractionMapping: EquirectangularRefractionMapping,
46491	CubeUVReflectionMapping: CubeUVReflectionMapping
46492};
46493
46494const TEXTURE_WRAPPING = {
46495	RepeatWrapping: RepeatWrapping,
46496	ClampToEdgeWrapping: ClampToEdgeWrapping,
46497	MirroredRepeatWrapping: MirroredRepeatWrapping
46498};
46499
46500const TEXTURE_FILTER = {
46501	NearestFilter: NearestFilter,
46502	NearestMipmapNearestFilter: NearestMipmapNearestFilter,
46503	NearestMipmapLinearFilter: NearestMipmapLinearFilter,
46504	LinearFilter: LinearFilter,
46505	LinearMipmapNearestFilter: LinearMipmapNearestFilter,
46506	LinearMipmapLinearFilter: LinearMipmapLinearFilter
46507};
46508
46509class ImageBitmapLoader extends Loader {
46510
46511	constructor( manager ) {
46512
46513		super( manager );
46514
46515		this.isImageBitmapLoader = true;
46516
46517		if ( typeof createImageBitmap === 'undefined' ) {
46518
46519			console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
46520
46521		}
46522
46523		if ( typeof fetch === 'undefined' ) {
46524
46525			console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
46526
46527		}
46528
46529		this.options = { premultiplyAlpha: 'none' };
46530
46531	}
46532
46533	setOptions( options ) {
46534
46535		this.options = options;
46536
46537		return this;
46538
46539	}
46540
46541	load( url, onLoad, onProgress, onError ) {
46542
46543		if ( url === undefined ) url = '';
46544
46545		if ( this.path !== undefined ) url = this.path + url;
46546
46547		url = this.manager.resolveURL( url );
46548
46549		const scope = this;
46550
46551		const cached = Cache.get( url );
46552
46553		if ( cached !== undefined ) {
46554
46555			scope.manager.itemStart( url );
46556
46557			// If cached is a promise, wait for it to resolve
46558			if ( cached.then ) {
46559
46560				cached.then( imageBitmap => {
46561
46562					if ( onLoad ) onLoad( imageBitmap );
46563
46564					scope.manager.itemEnd( url );
46565
46566				} ).catch( e => {
46567
46568					if ( onError ) onError( e );
46569
46570				} );
46571				return;
46572
46573			}
46574
46575			// If cached is not a promise (i.e., it's already an imageBitmap)
46576			setTimeout( function () {
46577
46578				if ( onLoad ) onLoad( cached );
46579
46580				scope.manager.itemEnd( url );
46581
46582			}, 0 );
46583
46584			return cached;
46585
46586		}
46587
46588		const fetchOptions = {};
46589		fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
46590		fetchOptions.headers = this.requestHeader;
46591
46592		const promise = fetch( url, fetchOptions ).then( function ( res ) {
46593
46594			return res.blob();
46595
46596		} ).then( function ( blob ) {
46597
46598			return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) );
46599
46600		} ).then( function ( imageBitmap ) {
46601
46602			Cache.add( url, imageBitmap );
46603
46604			if ( onLoad ) onLoad( imageBitmap );
46605
46606			scope.manager.itemEnd( url );
46607
46608			return imageBitmap;
46609
46610		} ).catch( function ( e ) {
46611
46612			if ( onError ) onError( e );
46613
46614			Cache.remove( url );
46615
46616			scope.manager.itemError( url );
46617			scope.manager.itemEnd( url );
46618
46619		} );
46620
46621		Cache.add( url, promise );
46622		scope.manager.itemStart( url );
46623
46624	}
46625
46626}
46627
46628let _context;
46629
46630class AudioContext {
46631
46632	static getContext() {
46633
46634		if ( _context === undefined ) {
46635
46636			_context = new ( window.AudioContext || window.webkitAudioContext )();
46637
46638		}
46639
46640		return _context;
46641
46642	}
46643
46644	static setContext( value ) {
46645
46646		_context = value;
46647
46648	}
46649
46650}
46651
46652class AudioLoader extends Loader {
46653
46654	constructor( manager ) {
46655
46656		super( manager );
46657
46658	}
46659
46660	load( url, onLoad, onProgress, onError ) {
46661
46662		const scope = this;
46663
46664		const loader = new FileLoader( this.manager );
46665		loader.setResponseType( 'arraybuffer' );
46666		loader.setPath( this.path );
46667		loader.setRequestHeader( this.requestHeader );
46668		loader.setWithCredentials( this.withCredentials );
46669		loader.load( url, function ( buffer ) {
46670
46671			try {
46672
46673				// Create a copy of the buffer. The `decodeAudioData` method
46674				// detaches the buffer when complete, preventing reuse.
46675				const bufferCopy = buffer.slice( 0 );
46676
46677				const context = AudioContext.getContext();
46678				context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
46679
46680					onLoad( audioBuffer );
46681
46682				} ).catch( handleError );
46683
46684			} catch ( e ) {
46685
46686				handleError( e );
46687
46688			}
46689
46690		}, onProgress, onError );
46691
46692		function handleError( e ) {
46693
46694			if ( onError ) {
46695
46696				onError( e );
46697
46698			} else {
46699
46700				console.error( e );
46701
46702			}
46703
46704			scope.manager.itemError( url );
46705
46706		}
46707
46708	}
46709
46710}
46711
46712const _eyeRight = /*@__PURE__*/ new Matrix4();
46713const _eyeLeft = /*@__PURE__*/ new Matrix4();
46714const _projectionMatrix = /*@__PURE__*/ new Matrix4();
46715
46716class StereoCamera {
46717
46718	constructor() {
46719
46720		this.type = 'StereoCamera';
46721
46722		this.aspect = 1;
46723
46724		this.eyeSep = 0.064;
46725
46726		this.cameraL = new PerspectiveCamera();
46727		this.cameraL.layers.enable( 1 );
46728		this.cameraL.matrixAutoUpdate = false;
46729
46730		this.cameraR = new PerspectiveCamera();
46731		this.cameraR.layers.enable( 2 );
46732		this.cameraR.matrixAutoUpdate = false;
46733
46734		this._cache = {
46735			focus: null,
46736			fov: null,
46737			aspect: null,
46738			near: null,
46739			far: null,
46740			zoom: null,
46741			eyeSep: null
46742		};
46743
46744	}
46745
46746	update( camera ) {
46747
46748		const cache = this._cache;
46749
46750		const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
46751			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
46752			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
46753
46754		if ( needsUpdate ) {
46755
46756			cache.focus = camera.focus;
46757			cache.fov = camera.fov;
46758			cache.aspect = camera.aspect * this.aspect;
46759			cache.near = camera.near;
46760			cache.far = camera.far;
46761			cache.zoom = camera.zoom;
46762			cache.eyeSep = this.eyeSep;
46763
46764			// Off-axis stereoscopic effect based on
46765			// http://paulbourke.net/stereographics/stereorender/
46766
46767			_projectionMatrix.copy( camera.projectionMatrix );
46768			const eyeSepHalf = cache.eyeSep / 2;
46769			const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
46770			const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
46771			let xmin, xmax;
46772
46773			// translate xOffset
46774
46775			_eyeLeft.elements[ 12 ] = - eyeSepHalf;
46776			_eyeRight.elements[ 12 ] = eyeSepHalf;
46777
46778			// for left eye
46779
46780			xmin = - ymax * cache.aspect + eyeSepOnProjection;
46781			xmax = ymax * cache.aspect + eyeSepOnProjection;
46782
46783			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
46784			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
46785
46786			this.cameraL.projectionMatrix.copy( _projectionMatrix );
46787
46788			// for right eye
46789
46790			xmin = - ymax * cache.aspect - eyeSepOnProjection;
46791			xmax = ymax * cache.aspect - eyeSepOnProjection;
46792
46793			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
46794			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
46795
46796			this.cameraR.projectionMatrix.copy( _projectionMatrix );
46797
46798		}
46799
46800		this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
46801		this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
46802
46803	}
46804
46805}
46806
46807class Clock {
46808
46809	constructor( autoStart = true ) {
46810
46811		this.autoStart = autoStart;
46812
46813		this.startTime = 0;
46814		this.oldTime = 0;
46815		this.elapsedTime = 0;
46816
46817		this.running = false;
46818
46819	}
46820
46821	start() {
46822
46823		this.startTime = now();
46824
46825		this.oldTime = this.startTime;
46826		this.elapsedTime = 0;
46827		this.running = true;
46828
46829	}
46830
46831	stop() {
46832
46833		this.getElapsedTime();
46834		this.running = false;
46835		this.autoStart = false;
46836
46837	}
46838
46839	getElapsedTime() {
46840
46841		this.getDelta();
46842		return this.elapsedTime;
46843
46844	}
46845
46846	getDelta() {
46847
46848		let diff = 0;
46849
46850		if ( this.autoStart && ! this.running ) {
46851
46852			this.start();
46853			return 0;
46854
46855		}
46856
46857		if ( this.running ) {
46858
46859			const newTime = now();
46860
46861			diff = ( newTime - this.oldTime ) / 1000;
46862			this.oldTime = newTime;
46863
46864			this.elapsedTime += diff;
46865
46866		}
46867
46868		return diff;
46869
46870	}
46871
46872}
46873
46874function now() {
46875
46876	return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
46877
46878}
46879
46880const _position$1 = /*@__PURE__*/ new Vector3();
46881const _quaternion$1 = /*@__PURE__*/ new Quaternion();
46882const _scale$1 = /*@__PURE__*/ new Vector3();
46883const _orientation$1 = /*@__PURE__*/ new Vector3();
46884
46885class AudioListener extends Object3D {
46886
46887	constructor() {
46888
46889		super();
46890
46891		this.type = 'AudioListener';
46892
46893		this.context = AudioContext.getContext();
46894
46895		this.gain = this.context.createGain();
46896		this.gain.connect( this.context.destination );
46897
46898		this.filter = null;
46899
46900		this.timeDelta = 0;
46901
46902		// private
46903
46904		this._clock = new Clock();
46905
46906	}
46907
46908	getInput() {
46909
46910		return this.gain;
46911
46912	}
46913
46914	removeFilter() {
46915
46916		if ( this.filter !== null ) {
46917
46918			this.gain.disconnect( this.filter );
46919			this.filter.disconnect( this.context.destination );
46920			this.gain.connect( this.context.destination );
46921			this.filter = null;
46922
46923		}
46924
46925		return this;
46926
46927	}
46928
46929	getFilter() {
46930
46931		return this.filter;
46932
46933	}
46934
46935	setFilter( value ) {
46936
46937		if ( this.filter !== null ) {
46938
46939			this.gain.disconnect( this.filter );
46940			this.filter.disconnect( this.context.destination );
46941
46942		} else {
46943
46944			this.gain.disconnect( this.context.destination );
46945
46946		}
46947
46948		this.filter = value;
46949		this.gain.connect( this.filter );
46950		this.filter.connect( this.context.destination );
46951
46952		return this;
46953
46954	}
46955
46956	getMasterVolume() {
46957
46958		return this.gain.gain.value;
46959
46960	}
46961
46962	setMasterVolume( value ) {
46963
46964		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
46965
46966		return this;
46967
46968	}
46969
46970	updateMatrixWorld( force ) {
46971
46972		super.updateMatrixWorld( force );
46973
46974		const listener = this.context.listener;
46975		const up = this.up;
46976
46977		this.timeDelta = this._clock.getDelta();
46978
46979		this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 );
46980
46981		_orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 );
46982
46983		if ( listener.positionX ) {
46984
46985			// code path for Chrome (see #14393)
46986
46987			const endTime = this.context.currentTime + this.timeDelta;
46988
46989			listener.positionX.linearRampToValueAtTime( _position$1.x, endTime );
46990			listener.positionY.linearRampToValueAtTime( _position$1.y, endTime );
46991			listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime );
46992			listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime );
46993			listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime );
46994			listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime );
46995			listener.upX.linearRampToValueAtTime( up.x, endTime );
46996			listener.upY.linearRampToValueAtTime( up.y, endTime );
46997			listener.upZ.linearRampToValueAtTime( up.z, endTime );
46998
46999		} else {
47000
47001			listener.setPosition( _position$1.x, _position$1.y, _position$1.z );
47002			listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z );
47003
47004		}
47005
47006	}
47007
47008}
47009
47010class Audio extends Object3D {
47011
47012	constructor( listener ) {
47013
47014		super();
47015
47016		this.type = 'Audio';
47017
47018		this.listener = listener;
47019		this.context = listener.context;
47020
47021		this.gain = this.context.createGain();
47022		this.gain.connect( listener.getInput() );
47023
47024		this.autoplay = false;
47025
47026		this.buffer = null;
47027		this.detune = 0;
47028		this.loop = false;
47029		this.loopStart = 0;
47030		this.loopEnd = 0;
47031		this.offset = 0;
47032		this.duration = undefined;
47033		this.playbackRate = 1;
47034		this.isPlaying = false;
47035		this.hasPlaybackControl = true;
47036		this.source = null;
47037		this.sourceType = 'empty';
47038
47039		this._startedAt = 0;
47040		this._progress = 0;
47041		this._connected = false;
47042
47043		this.filters = [];
47044
47045	}
47046
47047	getOutput() {
47048
47049		return this.gain;
47050
47051	}
47052
47053	setNodeSource( audioNode ) {
47054
47055		this.hasPlaybackControl = false;
47056		this.sourceType = 'audioNode';
47057		this.source = audioNode;
47058		this.connect();
47059
47060		return this;
47061
47062	}
47063
47064	setMediaElementSource( mediaElement ) {
47065
47066		this.hasPlaybackControl = false;
vendor: 8,682 bytes, lines 47067-47610
47067		this.sourceType = 'mediaNode';
47068		this.source = this.context.createMediaElementSource( mediaElement );
47069		this.connect();
47070
47071		return this;
47072
47073	}
47074
47075	setMediaStreamSource( mediaStream ) {
47076
47077		this.hasPlaybackControl = false;
47078		this.sourceType = 'mediaStreamNode';
47079		this.source = this.context.createMediaStreamSource( mediaStream );
47080		this.connect();
47081
47082		return this;
47083
47084	}
47085
47086	setBuffer( audioBuffer ) {
47087
47088		this.buffer = audioBuffer;
47089		this.sourceType = 'buffer';
47090
47091		if ( this.autoplay ) this.play();
47092
47093		return this;
47094
47095	}
47096
47097	play( delay = 0 ) {
47098
47099		if ( this.isPlaying === true ) {
47100
47101			console.warn( 'THREE.Audio: Audio is already playing.' );
47102			return;
47103
47104		}
47105
47106		if ( this.hasPlaybackControl === false ) {
47107
47108			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47109			return;
47110
47111		}
47112
47113		this._startedAt = this.context.currentTime + delay;
47114
47115		const source = this.context.createBufferSource();
47116		source.buffer = this.buffer;
47117		source.loop = this.loop;
47118		source.loopStart = this.loopStart;
47119		source.loopEnd = this.loopEnd;
47120		source.onended = this.onEnded.bind( this );
47121		source.start( this._startedAt, this._progress + this.offset, this.duration );
47122
47123		this.isPlaying = true;
47124
47125		this.source = source;
47126
47127		this.setDetune( this.detune );
47128		this.setPlaybackRate( this.playbackRate );
47129
47130		return this.connect();
47131
47132	}
47133
47134	pause() {
47135
47136		if ( this.hasPlaybackControl === false ) {
47137
47138			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47139			return;
47140
47141		}
47142
47143		if ( this.isPlaying === true ) {
47144
47145			// update current progress
47146
47147			this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
47148
47149			if ( this.loop === true ) {
47150
47151				// ensure _progress does not exceed duration with looped audios
47152
47153				this._progress = this._progress % ( this.duration || this.buffer.duration );
47154
47155			}
47156
47157			this.source.stop();
47158			this.source.onended = null;
47159
47160			this.isPlaying = false;
47161
47162		}
47163
47164		return this;
47165
47166	}
47167
47168	stop() {
47169
47170		if ( this.hasPlaybackControl === false ) {
47171
47172			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47173			return;
47174
47175		}
47176
47177		this._progress = 0;
47178
47179		if ( this.source !== null ) {
47180
47181			this.source.stop();
47182			this.source.onended = null;
47183
47184		}
47185
47186		this.isPlaying = false;
47187
47188		return this;
47189
47190	}
47191
47192	connect() {
47193
47194		if ( this.filters.length > 0 ) {
47195
47196			this.source.connect( this.filters[ 0 ] );
47197
47198			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
47199
47200				this.filters[ i - 1 ].connect( this.filters[ i ] );
47201
47202			}
47203
47204			this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
47205
47206		} else {
47207
47208			this.source.connect( this.getOutput() );
47209
47210		}
47211
47212		this._connected = true;
47213
47214		return this;
47215
47216	}
47217
47218	disconnect() {
47219
47220		if ( this._connected === false ) {
47221
47222			return;
47223
47224		}
47225
47226		if ( this.filters.length > 0 ) {
47227
47228			this.source.disconnect( this.filters[ 0 ] );
47229
47230			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
47231
47232				this.filters[ i - 1 ].disconnect( this.filters[ i ] );
47233
47234			}
47235
47236			this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
47237
47238		} else {
47239
47240			this.source.disconnect( this.getOutput() );
47241
47242		}
47243
47244		this._connected = false;
47245
47246		return this;
47247
47248	}
47249
47250	getFilters() {
47251
47252		return this.filters;
47253
47254	}
47255
47256	setFilters( value ) {
47257
47258		if ( ! value ) value = [];
47259
47260		if ( this._connected === true ) {
47261
47262			this.disconnect();
47263			this.filters = value.slice();
47264			this.connect();
47265
47266		} else {
47267
47268			this.filters = value.slice();
47269
47270		}
47271
47272		return this;
47273
47274	}
47275
47276	setDetune( value ) {
47277
47278		this.detune = value;
47279
47280		if ( this.isPlaying === true && this.source.detune !== undefined ) {
47281
47282			this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
47283
47284		}
47285
47286		return this;
47287
47288	}
47289
47290	getDetune() {
47291
47292		return this.detune;
47293
47294	}
47295
47296	getFilter() {
47297
47298		return this.getFilters()[ 0 ];
47299
47300	}
47301
47302	setFilter( filter ) {
47303
47304		return this.setFilters( filter ? [ filter ] : [] );
47305
47306	}
47307
47308	setPlaybackRate( value ) {
47309
47310		if ( this.hasPlaybackControl === false ) {
47311
47312			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47313			return;
47314
47315		}
47316
47317		this.playbackRate = value;
47318
47319		if ( this.isPlaying === true ) {
47320
47321			this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
47322
47323		}
47324
47325		return this;
47326
47327	}
47328
47329	getPlaybackRate() {
47330
47331		return this.playbackRate;
47332
47333	}
47334
47335	onEnded() {
47336
47337		this.isPlaying = false;
47338
47339	}
47340
47341	getLoop() {
47342
47343		if ( this.hasPlaybackControl === false ) {
47344
47345			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47346			return false;
47347
47348		}
47349
47350		return this.loop;
47351
47352	}
47353
47354	setLoop( value ) {
47355
47356		if ( this.hasPlaybackControl === false ) {
47357
47358			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47359			return;
47360
47361		}
47362
47363		this.loop = value;
47364
47365		if ( this.isPlaying === true ) {
47366
47367			this.source.loop = this.loop;
47368
47369		}
47370
47371		return this;
47372
47373	}
47374
47375	setLoopStart( value ) {
47376
47377		this.loopStart = value;
47378
47379		return this;
47380
47381	}
47382
47383	setLoopEnd( value ) {
47384
47385		this.loopEnd = value;
47386
47387		return this;
47388
47389	}
47390
47391	getVolume() {
47392
47393		return this.gain.gain.value;
47394
47395	}
47396
47397	setVolume( value ) {
47398
47399		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
47400
47401		return this;
47402
47403	}
47404
47405}
47406
47407const _position = /*@__PURE__*/ new Vector3();
47408const _quaternion = /*@__PURE__*/ new Quaternion();
47409const _scale = /*@__PURE__*/ new Vector3();
47410const _orientation = /*@__PURE__*/ new Vector3();
47411
47412class PositionalAudio extends Audio {
47413
47414	constructor( listener ) {
47415
47416		super( listener );
47417
47418		this.panner = this.context.createPanner();
47419		this.panner.panningModel = 'HRTF';
47420		this.panner.connect( this.gain );
47421
47422	}
47423
47424	connect() {
47425
47426		super.connect();
47427
47428		this.panner.connect( this.gain );
47429
47430	}
47431
47432	disconnect() {
47433
47434		super.disconnect();
47435
47436		this.panner.disconnect( this.gain );
47437
47438	}
47439
47440	getOutput() {
47441
47442		return this.panner;
47443
47444	}
47445
47446	getRefDistance() {
47447
47448		return this.panner.refDistance;
47449
47450	}
47451
47452	setRefDistance( value ) {
47453
47454		this.panner.refDistance = value;
47455
47456		return this;
47457
47458	}
47459
47460	getRolloffFactor() {
47461
47462		return this.panner.rolloffFactor;
47463
47464	}
47465
47466	setRolloffFactor( value ) {
47467
47468		this.panner.rolloffFactor = value;
47469
47470		return this;
47471
47472	}
47473
47474	getDistanceModel() {
47475
47476		return this.panner.distanceModel;
47477
47478	}
47479
47480	setDistanceModel( value ) {
47481
47482		this.panner.distanceModel = value;
47483
47484		return this;
47485
47486	}
47487
47488	getMaxDistance() {
47489
47490		return this.panner.maxDistance;
47491
47492	}
47493
47494	setMaxDistance( value ) {
47495
47496		this.panner.maxDistance = value;
47497
47498		return this;
47499
47500	}
47501
47502	setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
47503
47504		this.panner.coneInnerAngle = coneInnerAngle;
47505		this.panner.coneOuterAngle = coneOuterAngle;
47506		this.panner.coneOuterGain = coneOuterGain;
47507
47508		return this;
47509
47510	}
47511
47512	updateMatrixWorld( force ) {
47513
47514		super.updateMatrixWorld( force );
47515
47516		if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
47517
47518		this.matrixWorld.decompose( _position, _quaternion, _scale );
47519
47520		_orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
47521
47522		const panner = this.panner;
47523
47524		if ( panner.positionX ) {
47525
47526			// code path for Chrome and Firefox (see #14393)
47527
47528			const endTime = this.context.currentTime + this.listener.timeDelta;
47529
47530			panner.positionX.linearRampToValueAtTime( _position.x, endTime );
47531			panner.positionY.linearRampToValueAtTime( _position.y, endTime );
47532			panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
47533			panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
47534			panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
47535			panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
47536
47537		} else {
47538
47539			panner.setPosition( _position.x, _position.y, _position.z );
47540			panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
47541
47542		}
47543
47544	}
47545
47546}
47547
47548class AudioAnalyser {
47549
47550	constructor( audio, fftSize = 2048 ) {
47551
47552		this.analyser = audio.context.createAnalyser();
47553		this.analyser.fftSize = fftSize;
47554
47555		this.data = new Uint8Array( this.analyser.frequencyBinCount );
47556
47557		audio.getOutput().connect( this.analyser );
47558
47559	}
47560
47561
47562	getFrequencyData() {
47563
47564		this.analyser.getByteFrequencyData( this.data );
47565
47566		return this.data;
47567
47568	}
47569
47570	getAverageFrequency() {
47571
47572		let value = 0;
47573		const data = this.getFrequencyData();
47574
47575		for ( let i = 0; i < data.length; i ++ ) {
47576
47577			value += data[ i ];
47578
47579		}
47580
47581		return value / data.length;
47582
47583	}
47584
47585}
47586
47587class PropertyMixer {
47588
47589	constructor( binding, typeName, valueSize ) {
47590
47591		this.binding = binding;
47592		this.valueSize = valueSize;
47593
47594		let mixFunction,
47595			mixFunctionAdditive,
47596			setIdentity;
47597
47598		// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
47599		//
47600		// interpolators can use .buffer as their .result
47601		// the data then goes to 'incoming'
47602		//
47603		// 'accu0' and 'accu1' are used frame-interleaved for
47604		// the cumulative result and are compared to detect
47605		// changes
47606		//
47607		// 'orig' stores the original state of the property
47608		//
47609		// 'add' is used for additive cumulative results
47610		//
vendor: 13,778 bytes, lines 47611-48241
47611		// 'work' is optional and is only present for quaternion types. It is used
47612		// to store intermediate quaternion multiplication results
47613
47614		switch ( typeName ) {
47615
47616			case 'quaternion':
47617				mixFunction = this._slerp;
47618				mixFunctionAdditive = this._slerpAdditive;
47619				setIdentity = this._setAdditiveIdentityQuaternion;
47620
47621				this.buffer = new Float64Array( valueSize * 6 );
47622				this._workIndex = 5;
47623				break;
47624
47625			case 'string':
47626			case 'bool':
47627				mixFunction = this._select;
47628
47629				// Use the regular mix function and for additive on these types,
47630				// additive is not relevant for non-numeric types
47631				mixFunctionAdditive = this._select;
47632
47633				setIdentity = this._setAdditiveIdentityOther;
47634
47635				this.buffer = new Array( valueSize * 5 );
47636				break;
47637
47638			default:
47639				mixFunction = this._lerp;
47640				mixFunctionAdditive = this._lerpAdditive;
47641				setIdentity = this._setAdditiveIdentityNumeric;
47642
47643				this.buffer = new Float64Array( valueSize * 5 );
47644
47645		}
47646
47647		this._mixBufferRegion = mixFunction;
47648		this._mixBufferRegionAdditive = mixFunctionAdditive;
47649		this._setIdentity = setIdentity;
47650		this._origIndex = 3;
47651		this._addIndex = 4;
47652
47653		this.cumulativeWeight = 0;
47654		this.cumulativeWeightAdditive = 0;
47655
47656		this.useCount = 0;
47657		this.referenceCount = 0;
47658
47659	}
47660
47661	// accumulate data in the 'incoming' region into 'accu<i>'
47662	accumulate( accuIndex, weight ) {
47663
47664		// note: happily accumulating nothing when weight = 0, the caller knows
47665		// the weight and shouldn't have made the call in the first place
47666
47667		const buffer = this.buffer,
47668			stride = this.valueSize,
47669			offset = accuIndex * stride + stride;
47670
47671		let currentWeight = this.cumulativeWeight;
47672
47673		if ( currentWeight === 0 ) {
47674
47675			// accuN := incoming * weight
47676
47677			for ( let i = 0; i !== stride; ++ i ) {
47678
47679				buffer[ offset + i ] = buffer[ i ];
47680
47681			}
47682
47683			currentWeight = weight;
47684
47685		} else {
47686
47687			// accuN := accuN + incoming * weight
47688
47689			currentWeight += weight;
47690			const mix = weight / currentWeight;
47691			this._mixBufferRegion( buffer, offset, 0, mix, stride );
47692
47693		}
47694
47695		this.cumulativeWeight = currentWeight;
47696
47697	}
47698
47699	// accumulate data in the 'incoming' region into 'add'
47700	accumulateAdditive( weight ) {
47701
47702		const buffer = this.buffer,
47703			stride = this.valueSize,
47704			offset = stride * this._addIndex;
47705
47706		if ( this.cumulativeWeightAdditive === 0 ) {
47707
47708			// add = identity
47709
47710			this._setIdentity();
47711
47712		}
47713
47714		// add := add + incoming * weight
47715
47716		this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
47717		this.cumulativeWeightAdditive += weight;
47718
47719	}
47720
47721	// apply the state of 'accu<i>' to the binding when accus differ
47722	apply( accuIndex ) {
47723
47724		const stride = this.valueSize,
47725			buffer = this.buffer,
47726			offset = accuIndex * stride + stride,
47727
47728			weight = this.cumulativeWeight,
47729			weightAdditive = this.cumulativeWeightAdditive,
47730
47731			binding = this.binding;
47732
47733		this.cumulativeWeight = 0;
47734		this.cumulativeWeightAdditive = 0;
47735
47736		if ( weight < 1 ) {
47737
47738			// accuN := accuN + original * ( 1 - cumulativeWeight )
47739
47740			const originalValueOffset = stride * this._origIndex;
47741
47742			this._mixBufferRegion(
47743				buffer, offset, originalValueOffset, 1 - weight, stride );
47744
47745		}
47746
47747		if ( weightAdditive > 0 ) {
47748
47749			// accuN := accuN + additive accuN
47750
47751			this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
47752
47753		}
47754
47755		for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
47756
47757			if ( buffer[ i ] !== buffer[ i + stride ] ) {
47758
47759				// value has changed -> update scene graph
47760
47761				binding.setValue( buffer, offset );
47762				break;
47763
47764			}
47765
47766		}
47767
47768	}
47769
47770	// remember the state of the bound property and copy it to both accus
47771	saveOriginalState() {
47772
47773		const binding = this.binding;
47774
47775		const buffer = this.buffer,
47776			stride = this.valueSize,
47777
47778			originalValueOffset = stride * this._origIndex;
47779
47780		binding.getValue( buffer, originalValueOffset );
47781
47782		// accu[0..1] := orig -- initially detect changes against the original
47783		for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
47784
47785			buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
47786
47787		}
47788
47789		// Add to identity for additive
47790		this._setIdentity();
47791
47792		this.cumulativeWeight = 0;
47793		this.cumulativeWeightAdditive = 0;
47794
47795	}
47796
47797	// apply the state previously taken via 'saveOriginalState' to the binding
47798	restoreOriginalState() {
47799
47800		const originalValueOffset = this.valueSize * 3;
47801		this.binding.setValue( this.buffer, originalValueOffset );
47802
47803	}
47804
47805	_setAdditiveIdentityNumeric() {
47806
47807		const startIndex = this._addIndex * this.valueSize;
47808		const endIndex = startIndex + this.valueSize;
47809
47810		for ( let i = startIndex; i < endIndex; i ++ ) {
47811
47812			this.buffer[ i ] = 0;
47813
47814		}
47815
47816	}
47817
47818	_setAdditiveIdentityQuaternion() {
47819
47820		this._setAdditiveIdentityNumeric();
47821		this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
47822
47823	}
47824
47825	_setAdditiveIdentityOther() {
47826
47827		const startIndex = this._origIndex * this.valueSize;
47828		const targetIndex = this._addIndex * this.valueSize;
47829
47830		for ( let i = 0; i < this.valueSize; i ++ ) {
47831
47832			this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
47833
47834		}
47835
47836	}
47837
47838
47839	// mix functions
47840
47841	_select( buffer, dstOffset, srcOffset, t, stride ) {
47842
47843		if ( t >= 0.5 ) {
47844
47845			for ( let i = 0; i !== stride; ++ i ) {
47846
47847				buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
47848
47849			}
47850
47851		}
47852
47853	}
47854
47855	_slerp( buffer, dstOffset, srcOffset, t ) {
47856
47857		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
47858
47859	}
47860
47861	_slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
47862
47863		const workOffset = this._workIndex * stride;
47864
47865		// Store result in intermediate buffer offset
47866		Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
47867
47868		// Slerp to the intermediate result
47869		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
47870
47871	}
47872
47873	_lerp( buffer, dstOffset, srcOffset, t, stride ) {
47874
47875		const s = 1 - t;
47876
47877		for ( let i = 0; i !== stride; ++ i ) {
47878
47879			const j = dstOffset + i;
47880
47881			buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
47882
47883		}
47884
47885	}
47886
47887	_lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
47888
47889		for ( let i = 0; i !== stride; ++ i ) {
47890
47891			const j = dstOffset + i;
47892
47893			buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
47894
47895		}
47896
47897	}
47898
47899}
47900
47901// Characters [].:/ are reserved for track binding syntax.
47902const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
47903const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
47904
47905// Attempts to allow node names from any language. ES5's `\w` regexp matches
47906// only latin characters, and the unicode \p{L} is not yet supported. So
47907// instead, we exclude reserved characters and match everything else.
47908const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
47909const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
47910
47911// Parent directories, delimited by '/' or ':'. Currently unused, but must
47912// be matched to parse the rest of the track name.
47913const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
47914
47915// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
47916const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
47917
47918// Object on target node, and accessor. May not contain reserved
47919// characters. Accessor may contain any character except closing bracket.
47920const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
47921
47922// Property and accessor. May not contain reserved characters. Accessor may
47923// contain any non-bracket characters.
47924const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
47925
47926const _trackRe = new RegExp( ''
47927	+ '^'
47928	+ _directoryRe
47929	+ _nodeRe
47930	+ _objectRe
47931	+ _propertyRe
47932	+ '$'
47933);
47934
47935const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ];
47936
47937class Composite {
47938
47939	constructor( targetGroup, path, optionalParsedPath ) {
47940
47941		const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
47942
47943		this._targetGroup = targetGroup;
47944		this._bindings = targetGroup.subscribe_( path, parsedPath );
47945
47946	}
47947
47948	getValue( array, offset ) {
47949
47950		this.bind(); // bind all binding
47951
47952		const firstValidIndex = this._targetGroup.nCachedObjects_,
47953			binding = this._bindings[ firstValidIndex ];
47954
47955		// and only call .getValue on the first
47956		if ( binding !== undefined ) binding.getValue( array, offset );
47957
47958	}
47959
47960	setValue( array, offset ) {
47961
47962		const bindings = this._bindings;
47963
47964		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
47965
47966			bindings[ i ].setValue( array, offset );
47967
47968		}
47969
47970	}
47971
47972	bind() {
47973
47974		const bindings = this._bindings;
47975
47976		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
47977
47978			bindings[ i ].bind();
47979
47980		}
47981
47982	}
47983
47984	unbind() {
47985
47986		const bindings = this._bindings;
47987
47988		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
47989
47990			bindings[ i ].unbind();
47991
47992		}
47993
47994	}
47995
47996}
47997
47998// Note: This class uses a State pattern on a per-method basis:
47999// 'bind' sets 'this.getValue' / 'setValue' and shadows the
48000// prototype version of these methods with one that represents
48001// the bound state. When the property is not found, the methods
48002// become no-ops.
48003class PropertyBinding {
48004
48005	constructor( rootNode, path, parsedPath ) {
48006
48007		this.path = path;
48008		this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
48009
48010		this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
48011
48012		this.rootNode = rootNode;
48013
48014		// initial state of these methods that calls 'bind'
48015		this.getValue = this._getValue_unbound;
48016		this.setValue = this._setValue_unbound;
48017
48018	}
48019
48020
48021	static create( root, path, parsedPath ) {
48022
48023		if ( ! ( root && root.isAnimationObjectGroup ) ) {
48024
48025			return new PropertyBinding( root, path, parsedPath );
48026
48027		} else {
48028
48029			return new PropertyBinding.Composite( root, path, parsedPath );
48030
48031		}
48032
48033	}
48034
48035	/**
48036	 * Replaces spaces with underscores and removes unsupported characters from
48037	 * node names, to ensure compatibility with parseTrackName().
48038	 *
48039	 * @param {string} name Node name to be sanitized.
48040	 * @return {string}
48041	 */
48042	static sanitizeNodeName( name ) {
48043
48044		return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
48045
48046	}
48047
48048	static parseTrackName( trackName ) {
48049
48050		const matches = _trackRe.exec( trackName );
48051
48052		if ( matches === null ) {
48053
48054			throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
48055
48056		}
48057
48058		const results = {
48059			// directoryName: matches[ 1 ], // (tschw) currently unused
48060			nodeName: matches[ 2 ],
48061			objectName: matches[ 3 ],
48062			objectIndex: matches[ 4 ],
48063			propertyName: matches[ 5 ], // required
48064			propertyIndex: matches[ 6 ]
48065		};
48066
48067		const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
48068
48069		if ( lastDot !== undefined && lastDot !== - 1 ) {
48070
48071			const objectName = results.nodeName.substring( lastDot + 1 );
48072
48073			// Object names must be checked against an allowlist. Otherwise, there
48074			// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
48075			// 'bar' could be the objectName, or part of a nodeName (which can
48076			// include '.' characters).
48077			if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
48078
48079				results.nodeName = results.nodeName.substring( 0, lastDot );
48080				results.objectName = objectName;
48081
48082			}
48083
48084		}
48085
48086		if ( results.propertyName === null || results.propertyName.length === 0 ) {
48087
48088			throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
48089
48090		}
48091
48092		return results;
48093
48094	}
48095
48096	static findNode( root, nodeName ) {
48097
48098		if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
48099
48100			return root;
48101
48102		}
48103
48104		// search into skeleton bones.
48105		if ( root.skeleton ) {
48106
48107			const bone = root.skeleton.getBoneByName( nodeName );
48108
48109			if ( bone !== undefined ) {
48110
48111				return bone;
48112
48113			}
48114
48115		}
48116
48117		// search into node subtree.
48118		if ( root.children ) {
48119
48120			const searchNodeSubtree = function ( children ) {
48121
48122				for ( let i = 0; i < children.length; i ++ ) {
48123
48124					const childNode = children[ i ];
48125
48126					if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
48127
48128						return childNode;
48129
48130					}
48131
48132					const result = searchNodeSubtree( childNode.children );
48133
48134					if ( result ) return result;
48135
48136				}
48137
48138				return null;
48139
48140			};
48141
48142			const subTreeNode = searchNodeSubtree( root.children );
48143
48144			if ( subTreeNode ) {
48145
48146				return subTreeNode;
48147
48148			}
48149
48150		}
48151
48152		return null;
48153
48154	}
48155
48156	// these are used to "bind" a nonexistent property
48157	_getValue_unavailable() {}
48158	_setValue_unavailable() {}
48159
48160	// Getters
48161
48162	_getValue_direct( buffer, offset ) {
48163
48164		buffer[ offset ] = this.targetObject[ this.propertyName ];
48165
48166	}
48167
48168	_getValue_array( buffer, offset ) {
48169
48170		const source = this.resolvedProperty;
48171
48172		for ( let i = 0, n = source.length; i !== n; ++ i ) {
48173
48174			buffer[ offset ++ ] = source[ i ];
48175
48176		}
48177
48178	}
48179
48180	_getValue_arrayElement( buffer, offset ) {
48181
48182		buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
48183
48184	}
48185
48186	_getValue_toArray( buffer, offset ) {
48187
48188		this.resolvedProperty.toArray( buffer, offset );
48189
48190	}
48191
48192	// Direct
48193
48194	_setValue_direct( buffer, offset ) {
48195
48196		this.targetObject[ this.propertyName ] = buffer[ offset ];
48197
48198	}
48199
48200	_setValue_direct_setNeedsUpdate( buffer, offset ) {
48201
48202		this.targetObject[ this.propertyName ] = buffer[ offset ];
48203		this.targetObject.needsUpdate = true;
48204
48205	}
48206
48207	_setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
48208
48209		this.targetObject[ this.propertyName ] = buffer[ offset ];
48210		this.targetObject.matrixWorldNeedsUpdate = true;
48211
48212	}
48213
48214	// EntireArray
48215
48216	_setValue_array( buffer, offset ) {
48217
48218		const dest = this.resolvedProperty;
48219
48220		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48221
48222			dest[ i ] = buffer[ offset ++ ];
48223
48224		}
48225
48226	}
48227
48228	_setValue_array_setNeedsUpdate( buffer, offset ) {
48229
48230		const dest = this.resolvedProperty;
48231
48232		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48233
48234			dest[ i ] = buffer[ offset ++ ];
48235
48236		}
48237
48238		this.targetObject.needsUpdate = true;
48239
48240	}
48241
vendor: 8,185 bytes, lines 48242-48597
48242	_setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
48243
48244		const dest = this.resolvedProperty;
48245
48246		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48247
48248			dest[ i ] = buffer[ offset ++ ];
48249
48250		}
48251
48252		this.targetObject.matrixWorldNeedsUpdate = true;
48253
48254	}
48255
48256	// ArrayElement
48257
48258	_setValue_arrayElement( buffer, offset ) {
48259
48260		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48261
48262	}
48263
48264	_setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
48265
48266		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48267		this.targetObject.needsUpdate = true;
48268
48269	}
48270
48271	_setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
48272
48273		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48274		this.targetObject.matrixWorldNeedsUpdate = true;
48275
48276	}
48277
48278	// HasToFromArray
48279
48280	_setValue_fromArray( buffer, offset ) {
48281
48282		this.resolvedProperty.fromArray( buffer, offset );
48283
48284	}
48285
48286	_setValue_fromArray_setNeedsUpdate( buffer, offset ) {
48287
48288		this.resolvedProperty.fromArray( buffer, offset );
48289		this.targetObject.needsUpdate = true;
48290
48291	}
48292
48293	_setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
48294
48295		this.resolvedProperty.fromArray( buffer, offset );
48296		this.targetObject.matrixWorldNeedsUpdate = true;
48297
48298	}
48299
48300	_getValue_unbound( targetArray, offset ) {
48301
48302		this.bind();
48303		this.getValue( targetArray, offset );
48304
48305	}
48306
48307	_setValue_unbound( sourceArray, offset ) {
48308
48309		this.bind();
48310		this.setValue( sourceArray, offset );
48311
48312	}
48313
48314	// create getter / setter pair for a property in the scene graph
48315	bind() {
48316
48317		let targetObject = this.node;
48318		const parsedPath = this.parsedPath;
48319
48320		const objectName = parsedPath.objectName;
48321		const propertyName = parsedPath.propertyName;
48322		let propertyIndex = parsedPath.propertyIndex;
48323
48324		if ( ! targetObject ) {
48325
48326			targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName );
48327
48328			this.node = targetObject;
48329
48330		}
48331
48332		// set fail state so we can just 'return' on error
48333		this.getValue = this._getValue_unavailable;
48334		this.setValue = this._setValue_unavailable;
48335
48336		// ensure there is a value node
48337		if ( ! targetObject ) {
48338
48339			console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' );
48340			return;
48341
48342		}
48343
48344		if ( objectName ) {
48345
48346			let objectIndex = parsedPath.objectIndex;
48347
48348			// special cases were we need to reach deeper into the hierarchy to get the face materials....
48349			switch ( objectName ) {
48350
48351				case 'materials':
48352
48353					if ( ! targetObject.material ) {
48354
48355						console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
48356						return;
48357
48358					}
48359
48360					if ( ! targetObject.material.materials ) {
48361
48362						console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
48363						return;
48364
48365					}
48366
48367					targetObject = targetObject.material.materials;
48368
48369					break;
48370
48371				case 'bones':
48372
48373					if ( ! targetObject.skeleton ) {
48374
48375						console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
48376						return;
48377
48378					}
48379
48380					// potential future optimization: skip this if propertyIndex is already an integer
48381					// and convert the integer string to a true integer.
48382
48383					targetObject = targetObject.skeleton.bones;
48384
48385					// support resolving morphTarget names into indices.
48386					for ( let i = 0; i < targetObject.length; i ++ ) {
48387
48388						if ( targetObject[ i ].name === objectIndex ) {
48389
48390							objectIndex = i;
48391							break;
48392
48393						}
48394
48395					}
48396
48397					break;
48398
48399				case 'map':
48400
48401					if ( 'map' in targetObject ) {
48402
48403						targetObject = targetObject.map;
48404						break;
48405
48406					}
48407
48408					if ( ! targetObject.material ) {
48409
48410						console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
48411						return;
48412
48413					}
48414
48415					if ( ! targetObject.material.map ) {
48416
48417						console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this );
48418						return;
48419
48420					}
48421
48422					targetObject = targetObject.material.map;
48423					break;
48424
48425				default:
48426
48427					if ( targetObject[ objectName ] === undefined ) {
48428
48429						console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
48430						return;
48431
48432					}
48433
48434					targetObject = targetObject[ objectName ];
48435
48436			}
48437
48438
48439			if ( objectIndex !== undefined ) {
48440
48441				if ( targetObject[ objectIndex ] === undefined ) {
48442
48443					console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
48444					return;
48445
48446				}
48447
48448				targetObject = targetObject[ objectIndex ];
48449
48450			}
48451
48452		}
48453
48454		// resolve property
48455		const nodeProperty = targetObject[ propertyName ];
48456
48457		if ( nodeProperty === undefined ) {
48458
48459			const nodeName = parsedPath.nodeName;
48460
48461			console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
48462				'.' + propertyName + ' but it wasn\'t found.', targetObject );
48463			return;
48464
48465		}
48466
48467		// determine versioning scheme
48468		let versioning = this.Versioning.None;
48469
48470		this.targetObject = targetObject;
48471
48472		if ( targetObject.needsUpdate !== undefined ) { // material
48473
48474			versioning = this.Versioning.NeedsUpdate;
48475
48476		} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
48477
48478			versioning = this.Versioning.MatrixWorldNeedsUpdate;
48479
48480		}
48481
48482		// determine how the property gets bound
48483		let bindingType = this.BindingType.Direct;
48484
48485		if ( propertyIndex !== undefined ) {
48486
48487			// access a sub element of the property array (only primitives are supported right now)
48488
48489			if ( propertyName === 'morphTargetInfluences' ) {
48490
48491				// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
48492
48493				// support resolving morphTarget names into indices.
48494				if ( ! targetObject.geometry ) {
48495
48496					console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
48497					return;
48498
48499				}
48500
48501				if ( ! targetObject.geometry.morphAttributes ) {
48502
48503					console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
48504					return;
48505
48506				}
48507
48508				if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
48509
48510					propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
48511
48512				}
48513
48514			}
48515
48516			bindingType = this.BindingType.ArrayElement;
48517
48518			this.resolvedProperty = nodeProperty;
48519			this.propertyIndex = propertyIndex;
48520
48521		} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
48522
48523			// must use copy for Object3D.Euler/Quaternion
48524
48525			bindingType = this.BindingType.HasFromToArray;
48526
48527			this.resolvedProperty = nodeProperty;
48528
48529		} else if ( Array.isArray( nodeProperty ) ) {
48530
48531			bindingType = this.BindingType.EntireArray;
48532
48533			this.resolvedProperty = nodeProperty;
48534
48535		} else {
48536
48537			this.propertyName = propertyName;
48538
48539		}
48540
48541		// select getter / setter
48542		this.getValue = this.GetterByBindingType[ bindingType ];
48543		this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
48544
48545	}
48546
48547	unbind() {
48548
48549		this.node = null;
48550
48551		// back to the prototype version of getValue / setValue
48552		// note: avoiding to mutate the shape of 'this' via 'delete'
48553		this.getValue = this._getValue_unbound;
48554		this.setValue = this._setValue_unbound;
48555
48556	}
48557
48558}
48559
48560PropertyBinding.Composite = Composite;
48561
48562PropertyBinding.prototype.BindingType = {
48563	Direct: 0,
48564	EntireArray: 1,
48565	ArrayElement: 2,
48566	HasFromToArray: 3
48567};
48568
48569PropertyBinding.prototype.Versioning = {
48570	None: 0,
48571	NeedsUpdate: 1,
48572	MatrixWorldNeedsUpdate: 2
48573};
48574
48575PropertyBinding.prototype.GetterByBindingType = [
48576
48577	PropertyBinding.prototype._getValue_direct,
48578	PropertyBinding.prototype._getValue_array,
48579	PropertyBinding.prototype._getValue_arrayElement,
48580	PropertyBinding.prototype._getValue_toArray,
48581
48582];
48583
48584PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
48585
48586	[
48587		// Direct
48588		PropertyBinding.prototype._setValue_direct,
48589		PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
48590		PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
48591
48592	], [
48593
48594		// EntireArray
48595
48596		PropertyBinding.prototype._setValue_array,
48597		PropertyBinding.prototype._setValue_array_setNeedsUpdate,
vendor: 4,282 bytes, lines 48598-48778
48598		PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
48599
48600	], [
48601
48602		// ArrayElement
48603		PropertyBinding.prototype._setValue_arrayElement,
48604		PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
48605		PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
48606
48607	], [
48608
48609		// HasToFromArray
48610		PropertyBinding.prototype._setValue_fromArray,
48611		PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
48612		PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
48613
48614	]
48615
48616];
48617
48618/**
48619 *
48620 * A group of objects that receives a shared animation state.
48621 *
48622 * Usage:
48623 *
48624 *  - Add objects you would otherwise pass as 'root' to the
48625 *    constructor or the .clipAction method of AnimationMixer.
48626 *
48627 *  - Instead pass this object as 'root'.
48628 *
48629 *  - You can also add and remove objects later when the mixer
48630 *    is running.
48631 *
48632 * Note:
48633 *
48634 *    Objects of this class appear as one object to the mixer,
48635 *    so cache control of the individual objects must be done
48636 *    on the group.
48637 *
48638 * Limitation:
48639 *
48640 *  - The animated properties must be compatible among the
48641 *    all objects in the group.
48642 *
48643 *  - A single property can either be controlled through a
48644 *    target group or directly, but not both.
48645 */
48646
48647class AnimationObjectGroup {
48648
48649	constructor() {
48650
48651		this.isAnimationObjectGroup = true;
48652
48653		this.uuid = generateUUID();
48654
48655		// cached objects followed by the active ones
48656		this._objects = Array.prototype.slice.call( arguments );
48657
48658		this.nCachedObjects_ = 0; // threshold
48659		// note: read by PropertyBinding.Composite
48660
48661		const indices = {};
48662		this._indicesByUUID = indices; // for bookkeeping
48663
48664		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
48665
48666			indices[ arguments[ i ].uuid ] = i;
48667
48668		}
48669
48670		this._paths = []; // inside: string
48671		this._parsedPaths = []; // inside: { we don't care, here }
48672		this._bindings = []; // inside: Array< PropertyBinding >
48673		this._bindingsIndicesByPath = {}; // inside: indices in these arrays
48674
48675		const scope = this;
48676
48677		this.stats = {
48678
48679			objects: {
48680				get total() {
48681
48682					return scope._objects.length;
48683
48684				},
48685				get inUse() {
48686
48687					return this.total - scope.nCachedObjects_;
48688
48689				}
48690			},
48691			get bindingsPerObject() {
48692
48693				return scope._bindings.length;
48694
48695			}
48696
48697		};
48698
48699	}
48700
48701	add() {
48702
48703		const objects = this._objects,
48704			indicesByUUID = this._indicesByUUID,
48705			paths = this._paths,
48706			parsedPaths = this._parsedPaths,
48707			bindings = this._bindings,
48708			nBindings = bindings.length;
48709
48710		let knownObject = undefined,
48711			nObjects = objects.length,
48712			nCachedObjects = this.nCachedObjects_;
48713
48714		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
48715
48716			const object = arguments[ i ],
48717				uuid = object.uuid;
48718			let index = indicesByUUID[ uuid ];
48719
48720			if ( index === undefined ) {
48721
48722				// unknown object -> add it to the ACTIVE region
48723
48724				index = nObjects ++;
48725				indicesByUUID[ uuid ] = index;
48726				objects.push( object );
48727
48728				// accounting is done, now do the same for all bindings
48729
48730				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
48731
48732					bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
48733
48734				}
48735
48736			} else if ( index < nCachedObjects ) {
48737
48738				knownObject = objects[ index ];
48739
48740				// move existing object to the ACTIVE region
48741
48742				const firstActiveIndex = -- nCachedObjects,
48743					lastCachedObject = objects[ firstActiveIndex ];
48744
48745				indicesByUUID[ lastCachedObject.uuid ] = index;
48746				objects[ index ] = lastCachedObject;
48747
48748				indicesByUUID[ uuid ] = firstActiveIndex;
48749				objects[ firstActiveIndex ] = object;
48750
48751				// accounting is done, now do the same for all bindings
48752
48753				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
48754
48755					const bindingsForPath = bindings[ j ],
48756						lastCached = bindingsForPath[ firstActiveIndex ];
48757
48758					let binding = bindingsForPath[ index ];
48759
48760					bindingsForPath[ index ] = lastCached;
48761
48762					if ( binding === undefined ) {
48763
48764						// since we do not bother to create new bindings
48765						// for objects that are cached, the binding may
48766						// or may not exist
48767
48768						binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
48769
48770					}
48771
48772					bindingsForPath[ firstActiveIndex ] = binding;
48773
48774				}
48775
48776			} else if ( objects[ index ] !== knownObject ) {
48777
48778				console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
vendor: 4,120 bytes, lines 48779-48945
48779					'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
48780
48781			} // else the object is already where we want it to be
48782
48783		} // for arguments
48784
48785		this.nCachedObjects_ = nCachedObjects;
48786
48787	}
48788
48789	remove() {
48790
48791		const objects = this._objects,
48792			indicesByUUID = this._indicesByUUID,
48793			bindings = this._bindings,
48794			nBindings = bindings.length;
48795
48796		let nCachedObjects = this.nCachedObjects_;
48797
48798		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
48799
48800			const object = arguments[ i ],
48801				uuid = object.uuid,
48802				index = indicesByUUID[ uuid ];
48803
48804			if ( index !== undefined && index >= nCachedObjects ) {
48805
48806				// move existing object into the CACHED region
48807
48808				const lastCachedIndex = nCachedObjects ++,
48809					firstActiveObject = objects[ lastCachedIndex ];
48810
48811				indicesByUUID[ firstActiveObject.uuid ] = index;
48812				objects[ index ] = firstActiveObject;
48813
48814				indicesByUUID[ uuid ] = lastCachedIndex;
48815				objects[ lastCachedIndex ] = object;
48816
48817				// accounting is done, now do the same for all bindings
48818
48819				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
48820
48821					const bindingsForPath = bindings[ j ],
48822						firstActive = bindingsForPath[ lastCachedIndex ],
48823						binding = bindingsForPath[ index ];
48824
48825					bindingsForPath[ index ] = firstActive;
48826					bindingsForPath[ lastCachedIndex ] = binding;
48827
48828				}
48829
48830			}
48831
48832		} // for arguments
48833
48834		this.nCachedObjects_ = nCachedObjects;
48835
48836	}
48837
48838	// remove & forget
48839	uncache() {
48840
48841		const objects = this._objects,
48842			indicesByUUID = this._indicesByUUID,
48843			bindings = this._bindings,
48844			nBindings = bindings.length;
48845
48846		let nCachedObjects = this.nCachedObjects_,
48847			nObjects = objects.length;
48848
48849		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
48850
48851			const object = arguments[ i ],
48852				uuid = object.uuid,
48853				index = indicesByUUID[ uuid ];
48854
48855			if ( index !== undefined ) {
48856
48857				delete indicesByUUID[ uuid ];
48858
48859				if ( index < nCachedObjects ) {
48860
48861					// object is cached, shrink the CACHED region
48862
48863					const firstActiveIndex = -- nCachedObjects,
48864						lastCachedObject = objects[ firstActiveIndex ],
48865						lastIndex = -- nObjects,
48866						lastObject = objects[ lastIndex ];
48867
48868					// last cached object takes this object's place
48869					indicesByUUID[ lastCachedObject.uuid ] = index;
48870					objects[ index ] = lastCachedObject;
48871
48872					// last object goes to the activated slot and pop
48873					indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
48874					objects[ firstActiveIndex ] = lastObject;
48875					objects.pop();
48876
48877					// accounting is done, now do the same for all bindings
48878
48879					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
48880
48881						const bindingsForPath = bindings[ j ],
48882							lastCached = bindingsForPath[ firstActiveIndex ],
48883							last = bindingsForPath[ lastIndex ];
48884
48885						bindingsForPath[ index ] = lastCached;
48886						bindingsForPath[ firstActiveIndex ] = last;
48887						bindingsForPath.pop();
48888
48889					}
48890
48891				} else {
48892
48893					// object is active, just swap with the last and pop
48894
48895					const lastIndex = -- nObjects,
48896						lastObject = objects[ lastIndex ];
48897
48898					if ( lastIndex > 0 ) {
48899
48900						indicesByUUID[ lastObject.uuid ] = index;
48901
48902					}
48903
48904					objects[ index ] = lastObject;
48905					objects.pop();
48906
48907					// accounting is done, now do the same for all bindings
48908
48909					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
48910
48911						const bindingsForPath = bindings[ j ];
48912
48913						bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
48914						bindingsForPath.pop();
48915
48916					}
48917
48918				} // cached or active
48919
48920			} // if object is known
48921
48922		} // for arguments
48923
48924		this.nCachedObjects_ = nCachedObjects;
48925
48926	}
48927
48928	// Internal interface used by befriended PropertyBinding.Composite:
48929
48930	subscribe_( path, parsedPath ) {
48931
48932		// returns an array of bindings for the given path that is changed
48933		// according to the contained objects in the group
48934
48935		const indicesByPath = this._bindingsIndicesByPath;
48936		let index = indicesByPath[ path ];
48937		const bindings = this._bindings;
48938
48939		if ( index !== undefined ) return bindings[ index ];
48940
48941		const paths = this._paths,
48942			parsedPaths = this._parsedPaths,
48943			objects = this._objects,
48944			nObjects = objects.length,
48945			nCachedObjects = this.nCachedObjects_,
vendor: 7,613 bytes, lines 48946-49339
48946			bindingsForPath = new Array( nObjects );
48947
48948		index = bindings.length;
48949
48950		indicesByPath[ path ] = index;
48951
48952		paths.push( path );
48953		parsedPaths.push( parsedPath );
48954		bindings.push( bindingsForPath );
48955
48956		for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
48957
48958			const object = objects[ i ];
48959			bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
48960
48961		}
48962
48963		return bindingsForPath;
48964
48965	}
48966
48967	unsubscribe_( path ) {
48968
48969		// tells the group to forget about a property path and no longer
48970		// update the array previously obtained with 'subscribe_'
48971
48972		const indicesByPath = this._bindingsIndicesByPath,
48973			index = indicesByPath[ path ];
48974
48975		if ( index !== undefined ) {
48976
48977			const paths = this._paths,
48978				parsedPaths = this._parsedPaths,
48979				bindings = this._bindings,
48980				lastBindingsIndex = bindings.length - 1,
48981				lastBindings = bindings[ lastBindingsIndex ],
48982				lastBindingsPath = path[ lastBindingsIndex ];
48983
48984			indicesByPath[ lastBindingsPath ] = index;
48985
48986			bindings[ index ] = lastBindings;
48987			bindings.pop();
48988
48989			parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
48990			parsedPaths.pop();
48991
48992			paths[ index ] = paths[ lastBindingsIndex ];
48993			paths.pop();
48994
48995		}
48996
48997	}
48998
48999}
49000
49001class AnimationAction {
49002
49003	constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
49004
49005		this._mixer = mixer;
49006		this._clip = clip;
49007		this._localRoot = localRoot;
49008		this.blendMode = blendMode;
49009
49010		const tracks = clip.tracks,
49011			nTracks = tracks.length,
49012			interpolants = new Array( nTracks );
49013
49014		const interpolantSettings = {
49015			endingStart: ZeroCurvatureEnding,
49016			endingEnd: ZeroCurvatureEnding
49017		};
49018
49019		for ( let i = 0; i !== nTracks; ++ i ) {
49020
49021			const interpolant = tracks[ i ].createInterpolant( null );
49022			interpolants[ i ] = interpolant;
49023			interpolant.settings = interpolantSettings;
49024
49025		}
49026
49027		this._interpolantSettings = interpolantSettings;
49028
49029		this._interpolants = interpolants; // bound by the mixer
49030
49031		// inside: PropertyMixer (managed by the mixer)
49032		this._propertyBindings = new Array( nTracks );
49033
49034		this._cacheIndex = null; // for the memory manager
49035		this._byClipCacheIndex = null; // for the memory manager
49036
49037		this._timeScaleInterpolant = null;
49038		this._weightInterpolant = null;
49039
49040		this.loop = LoopRepeat;
49041		this._loopCount = - 1;
49042
49043		// global mixer time when the action is to be started
49044		// it's set back to 'null' upon start of the action
49045		this._startTime = null;
49046
49047		// scaled local time of the action
49048		// gets clamped or wrapped to 0..clip.duration according to loop
49049		this.time = 0;
49050
49051		this.timeScale = 1;
49052		this._effectiveTimeScale = 1;
49053
49054		this.weight = 1;
49055		this._effectiveWeight = 1;
49056
49057		this.repetitions = Infinity; // no. of repetitions when looping
49058
49059		this.paused = false; // true -> zero effective time scale
49060		this.enabled = true; // false -> zero effective weight
49061
49062		this.clampWhenFinished = false;// keep feeding the last frame?
49063
49064		this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
49065		this.zeroSlopeAtEnd = true;// clips for start, loop and end
49066
49067	}
49068
49069	// State & Scheduling
49070
49071	play() {
49072
49073		this._mixer._activateAction( this );
49074
49075		return this;
49076
49077	}
49078
49079	stop() {
49080
49081		this._mixer._deactivateAction( this );
49082
49083		return this.reset();
49084
49085	}
49086
49087	reset() {
49088
49089		this.paused = false;
49090		this.enabled = true;
49091
49092		this.time = 0; // restart clip
49093		this._loopCount = - 1;// forget previous loops
49094		this._startTime = null;// forget scheduling
49095
49096		return this.stopFading().stopWarping();
49097
49098	}
49099
49100	isRunning() {
49101
49102		return this.enabled && ! this.paused && this.timeScale !== 0 &&
49103			this._startTime === null && this._mixer._isActiveAction( this );
49104
49105	}
49106
49107	// return true when play has been called
49108	isScheduled() {
49109
49110		return this._mixer._isActiveAction( this );
49111
49112	}
49113
49114	startAt( time ) {
49115
49116		this._startTime = time;
49117
49118		return this;
49119
49120	}
49121
49122	setLoop( mode, repetitions ) {
49123
49124		this.loop = mode;
49125		this.repetitions = repetitions;
49126
49127		return this;
49128
49129	}
49130
49131	// Weight
49132
49133	// set the weight stopping any scheduled fading
49134	// although .enabled = false yields an effective weight of zero, this
49135	// method does *not* change .enabled, because it would be confusing
49136	setEffectiveWeight( weight ) {
49137
49138		this.weight = weight;
49139
49140		// note: same logic as when updated at runtime
49141		this._effectiveWeight = this.enabled ? weight : 0;
49142
49143		return this.stopFading();
49144
49145	}
49146
49147	// return the weight considering fading and .enabled
49148	getEffectiveWeight() {
49149
49150		return this._effectiveWeight;
49151
49152	}
49153
49154	fadeIn( duration ) {
49155
49156		return this._scheduleFading( duration, 0, 1 );
49157
49158	}
49159
49160	fadeOut( duration ) {
49161
49162		return this._scheduleFading( duration, 1, 0 );
49163
49164	}
49165
49166	crossFadeFrom( fadeOutAction, duration, warp ) {
49167
49168		fadeOutAction.fadeOut( duration );
49169		this.fadeIn( duration );
49170
49171		if ( warp ) {
49172
49173			const fadeInDuration = this._clip.duration,
49174				fadeOutDuration = fadeOutAction._clip.duration,
49175
49176				startEndRatio = fadeOutDuration / fadeInDuration,
49177				endStartRatio = fadeInDuration / fadeOutDuration;
49178
49179			fadeOutAction.warp( 1.0, startEndRatio, duration );
49180			this.warp( endStartRatio, 1.0, duration );
49181
49182		}
49183
49184		return this;
49185
49186	}
49187
49188	crossFadeTo( fadeInAction, duration, warp ) {
49189
49190		return fadeInAction.crossFadeFrom( this, duration, warp );
49191
49192	}
49193
49194	stopFading() {
49195
49196		const weightInterpolant = this._weightInterpolant;
49197
49198		if ( weightInterpolant !== null ) {
49199
49200			this._weightInterpolant = null;
49201			this._mixer._takeBackControlInterpolant( weightInterpolant );
49202
49203		}
49204
49205		return this;
49206
49207	}
49208
49209	// Time Scale Control
49210
49211	// set the time scale stopping any scheduled warping
49212	// although .paused = true yields an effective time scale of zero, this
49213	// method does *not* change .paused, because it would be confusing
49214	setEffectiveTimeScale( timeScale ) {
49215
49216		this.timeScale = timeScale;
49217		this._effectiveTimeScale = this.paused ? 0 : timeScale;
49218
49219		return this.stopWarping();
49220
49221	}
49222
49223	// return the time scale considering warping and .paused
49224	getEffectiveTimeScale() {
49225
49226		return this._effectiveTimeScale;
49227
49228	}
49229
49230	setDuration( duration ) {
49231
49232		this.timeScale = this._clip.duration / duration;
49233
49234		return this.stopWarping();
49235
49236	}
49237
49238	syncWith( action ) {
49239
49240		this.time = action.time;
49241		this.timeScale = action.timeScale;
49242
49243		return this.stopWarping();
49244
49245	}
49246
49247	halt( duration ) {
49248
49249		return this.warp( this._effectiveTimeScale, 0, duration );
49250
49251	}
49252
49253	warp( startTimeScale, endTimeScale, duration ) {
49254
49255		const mixer = this._mixer,
49256			now = mixer.time,
49257			timeScale = this.timeScale;
49258
49259		let interpolant = this._timeScaleInterpolant;
49260
49261		if ( interpolant === null ) {
49262
49263			interpolant = mixer._lendControlInterpolant();
49264			this._timeScaleInterpolant = interpolant;
49265
49266		}
49267
49268		const times = interpolant.parameterPositions,
49269			values = interpolant.sampleValues;
49270
49271		times[ 0 ] = now;
49272		times[ 1 ] = now + duration;
49273
49274		values[ 0 ] = startTimeScale / timeScale;
49275		values[ 1 ] = endTimeScale / timeScale;
49276
49277		return this;
49278
49279	}
49280
49281	stopWarping() {
49282
49283		const timeScaleInterpolant = this._timeScaleInterpolant;
49284
49285		if ( timeScaleInterpolant !== null ) {
49286
49287			this._timeScaleInterpolant = null;
49288			this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
49289
49290		}
49291
49292		return this;
49293
49294	}
49295
49296	// Object Accessors
49297
49298	getMixer() {
49299
49300		return this._mixer;
49301
49302	}
49303
49304	getClip() {
49305
49306		return this._clip;
49307
49308	}
49309
49310	getRoot() {
49311
49312		return this._localRoot || this._mixer._root;
49313
49314	}
49315
49316	// Interna
49317
49318	_update( time, deltaTime, timeDirection, accuIndex ) {
49319
49320		// called by the mixer
49321
49322		if ( ! this.enabled ) {
49323
49324			// call ._updateWeight() to update ._effectiveWeight
49325
49326			this._updateWeight( time );
49327			return;
49328
49329		}
49330
49331		const startTime = this._startTime;
49332
49333		if ( startTime !== null ) {
49334
49335			// check for scheduled start of action
49336
49337			const timeRunning = ( time - startTime ) * timeDirection;
49338			if ( timeRunning < 0 || timeDirection === 0 ) {
49339
vendor: 6,044 bytes, lines 49340-49698
49340				deltaTime = 0;
49341
49342			} else {
49343
49344
49345				this._startTime = null; // unschedule
49346				deltaTime = timeDirection * timeRunning;
49347
49348			}
49349
49350		}
49351
49352		// apply time scale and advance time
49353
49354		deltaTime *= this._updateTimeScale( time );
49355		const clipTime = this._updateTime( deltaTime );
49356
49357		// note: _updateTime may disable the action resulting in
49358		// an effective weight of 0
49359
49360		const weight = this._updateWeight( time );
49361
49362		if ( weight > 0 ) {
49363
49364			const interpolants = this._interpolants;
49365			const propertyMixers = this._propertyBindings;
49366
49367			switch ( this.blendMode ) {
49368
49369				case AdditiveAnimationBlendMode:
49370
49371					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
49372
49373						interpolants[ j ].evaluate( clipTime );
49374						propertyMixers[ j ].accumulateAdditive( weight );
49375
49376					}
49377
49378					break;
49379
49380				case NormalAnimationBlendMode:
49381				default:
49382
49383					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
49384
49385						interpolants[ j ].evaluate( clipTime );
49386						propertyMixers[ j ].accumulate( accuIndex, weight );
49387
49388					}
49389
49390			}
49391
49392		}
49393
49394	}
49395
49396	_updateWeight( time ) {
49397
49398		let weight = 0;
49399
49400		if ( this.enabled ) {
49401
49402			weight = this.weight;
49403			const interpolant = this._weightInterpolant;
49404
49405			if ( interpolant !== null ) {
49406
49407				const interpolantValue = interpolant.evaluate( time )[ 0 ];
49408
49409				weight *= interpolantValue;
49410
49411				if ( time > interpolant.parameterPositions[ 1 ] ) {
49412
49413					this.stopFading();
49414
49415					if ( interpolantValue === 0 ) {
49416
49417						// faded out, disable
49418						this.enabled = false;
49419
49420					}
49421
49422				}
49423
49424			}
49425
49426		}
49427
49428		this._effectiveWeight = weight;
49429		return weight;
49430
49431	}
49432
49433	_updateTimeScale( time ) {
49434
49435		let timeScale = 0;
49436
49437		if ( ! this.paused ) {
49438
49439			timeScale = this.timeScale;
49440
49441			const interpolant = this._timeScaleInterpolant;
49442
49443			if ( interpolant !== null ) {
49444
49445				const interpolantValue = interpolant.evaluate( time )[ 0 ];
49446
49447				timeScale *= interpolantValue;
49448
49449				if ( time > interpolant.parameterPositions[ 1 ] ) {
49450
49451					this.stopWarping();
49452
49453					if ( timeScale === 0 ) {
49454
49455						// motion has halted, pause
49456						this.paused = true;
49457
49458					} else {
49459
49460						// warp done - apply final time scale
49461						this.timeScale = timeScale;
49462
49463					}
49464
49465				}
49466
49467			}
49468
49469		}
49470
49471		this._effectiveTimeScale = timeScale;
49472		return timeScale;
49473
49474	}
49475
49476	_updateTime( deltaTime ) {
49477
49478		const duration = this._clip.duration;
49479		const loop = this.loop;
49480
49481		let time = this.time + deltaTime;
49482		let loopCount = this._loopCount;
49483
49484		const pingPong = ( loop === LoopPingPong );
49485
49486		if ( deltaTime === 0 ) {
49487
49488			if ( loopCount === - 1 ) return time;
49489
49490			return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
49491
49492		}
49493
49494		if ( loop === LoopOnce ) {
49495
49496			if ( loopCount === - 1 ) {
49497
49498				// just started
49499
49500				this._loopCount = 0;
49501				this._setEndings( true, true, false );
49502
49503			}
49504
49505			handle_stop: {
49506
49507				if ( time >= duration ) {
49508
49509					time = duration;
49510
49511				} else if ( time < 0 ) {
49512
49513					time = 0;
49514
49515				} else {
49516
49517					this.time = time;
49518
49519					break handle_stop;
49520
49521				}
49522
49523				if ( this.clampWhenFinished ) this.paused = true;
49524				else this.enabled = false;
49525
49526				this.time = time;
49527
49528				this._mixer.dispatchEvent( {
49529					type: 'finished', action: this,
49530					direction: deltaTime < 0 ? - 1 : 1
49531				} );
49532
49533			}
49534
49535		} else { // repetitive Repeat or PingPong
49536
49537			if ( loopCount === - 1 ) {
49538
49539				// just started
49540
49541				if ( deltaTime >= 0 ) {
49542
49543					loopCount = 0;
49544
49545					this._setEndings( true, this.repetitions === 0, pingPong );
49546
49547				} else {
49548
49549					// when looping in reverse direction, the initial
49550					// transition through zero counts as a repetition,
49551					// so leave loopCount at -1
49552
49553					this._setEndings( this.repetitions === 0, true, pingPong );
49554
49555				}
49556
49557			}
49558
49559			if ( time >= duration || time < 0 ) {
49560
49561				// wrap around
49562
49563				const loopDelta = Math.floor( time / duration ); // signed
49564				time -= duration * loopDelta;
49565
49566				loopCount += Math.abs( loopDelta );
49567
49568				const pending = this.repetitions - loopCount;
49569
49570				if ( pending <= 0 ) {
49571
49572					// have to stop (switch state, clamp time, fire event)
49573
49574					if ( this.clampWhenFinished ) this.paused = true;
49575					else this.enabled = false;
49576
49577					time = deltaTime > 0 ? duration : 0;
49578
49579					this.time = time;
49580
49581					this._mixer.dispatchEvent( {
49582						type: 'finished', action: this,
49583						direction: deltaTime > 0 ? 1 : - 1
49584					} );
49585
49586				} else {
49587
49588					// keep running
49589
49590					if ( pending === 1 ) {
49591
49592						// entering the last round
49593
49594						const atStart = deltaTime < 0;
49595						this._setEndings( atStart, ! atStart, pingPong );
49596
49597					} else {
49598
49599						this._setEndings( false, false, pingPong );
49600
49601					}
49602
49603					this._loopCount = loopCount;
49604
49605					this.time = time;
49606
49607					this._mixer.dispatchEvent( {
49608						type: 'loop', action: this, loopDelta: loopDelta
49609					} );
49610
49611				}
49612
49613			} else {
49614
49615				this.time = time;
49616
49617			}
49618
49619			if ( pingPong && ( loopCount & 1 ) === 1 ) {
49620
49621				// invert time for the "pong round"
49622
49623				return duration - time;
49624
49625			}
49626
49627		}
49628
49629		return time;
49630
49631	}
49632
49633	_setEndings( atStart, atEnd, pingPong ) {
49634
49635		const settings = this._interpolantSettings;
49636
49637		if ( pingPong ) {
49638
49639			settings.endingStart = ZeroSlopeEnding;
49640			settings.endingEnd = ZeroSlopeEnding;
49641
49642		} else {
49643
49644			// assuming for LoopOnce atStart == atEnd == true
49645
49646			if ( atStart ) {
49647
49648				settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
49649
49650			} else {
49651
49652				settings.endingStart = WrapAroundEnding;
49653
49654			}
49655
49656			if ( atEnd ) {
49657
49658				settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
49659
49660			} else {
49661
49662				settings.endingEnd 	 = WrapAroundEnding;
49663
49664			}
49665
49666		}
49667
49668	}
49669
49670	_scheduleFading( duration, weightNow, weightThen ) {
49671
49672		const mixer = this._mixer, now = mixer.time;
49673		let interpolant = this._weightInterpolant;
49674
49675		if ( interpolant === null ) {
49676
49677			interpolant = mixer._lendControlInterpolant();
49678			this._weightInterpolant = interpolant;
49679
49680		}
49681
49682		const times = interpolant.parameterPositions,
49683			values = interpolant.sampleValues;
49684
49685		times[ 0 ] = now;
49686		values[ 0 ] = weightNow;
49687		times[ 1 ] = now + duration;
49688		values[ 1 ] = weightThen;
49689
49690		return this;
49691
49692	}
49693
49694}
49695
49696const _controlInterpolantsResultBuffer = new Float32Array( 1 );
49697
49698
vendor: 13,381 bytes, lines 49699-50339
49699class AnimationMixer extends EventDispatcher {
49700
49701	constructor( root ) {
49702
49703		super();
49704
49705		this._root = root;
49706		this._initMemoryManager();
49707		this._accuIndex = 0;
49708		this.time = 0;
49709		this.timeScale = 1.0;
49710
49711	}
49712
49713	_bindAction( action, prototypeAction ) {
49714
49715		const root = action._localRoot || this._root,
49716			tracks = action._clip.tracks,
49717			nTracks = tracks.length,
49718			bindings = action._propertyBindings,
49719			interpolants = action._interpolants,
49720			rootUuid = root.uuid,
49721			bindingsByRoot = this._bindingsByRootAndName;
49722
49723		let bindingsByName = bindingsByRoot[ rootUuid ];
49724
49725		if ( bindingsByName === undefined ) {
49726
49727			bindingsByName = {};
49728			bindingsByRoot[ rootUuid ] = bindingsByName;
49729
49730		}
49731
49732		for ( let i = 0; i !== nTracks; ++ i ) {
49733
49734			const track = tracks[ i ],
49735				trackName = track.name;
49736
49737			let binding = bindingsByName[ trackName ];
49738
49739			if ( binding !== undefined ) {
49740
49741				++ binding.referenceCount;
49742				bindings[ i ] = binding;
49743
49744			} else {
49745
49746				binding = bindings[ i ];
49747
49748				if ( binding !== undefined ) {
49749
49750					// existing binding, make sure the cache knows
49751
49752					if ( binding._cacheIndex === null ) {
49753
49754						++ binding.referenceCount;
49755						this._addInactiveBinding( binding, rootUuid, trackName );
49756
49757					}
49758
49759					continue;
49760
49761				}
49762
49763				const path = prototypeAction && prototypeAction.
49764					_propertyBindings[ i ].binding.parsedPath;
49765
49766				binding = new PropertyMixer(
49767					PropertyBinding.create( root, trackName, path ),
49768					track.ValueTypeName, track.getValueSize() );
49769
49770				++ binding.referenceCount;
49771				this._addInactiveBinding( binding, rootUuid, trackName );
49772
49773				bindings[ i ] = binding;
49774
49775			}
49776
49777			interpolants[ i ].resultBuffer = binding.buffer;
49778
49779		}
49780
49781	}
49782
49783	_activateAction( action ) {
49784
49785		if ( ! this._isActiveAction( action ) ) {
49786
49787			if ( action._cacheIndex === null ) {
49788
49789				// this action has been forgotten by the cache, but the user
49790				// appears to be still using it -> rebind
49791
49792				const rootUuid = ( action._localRoot || this._root ).uuid,
49793					clipUuid = action._clip.uuid,
49794					actionsForClip = this._actionsByClip[ clipUuid ];
49795
49796				this._bindAction( action,
49797					actionsForClip && actionsForClip.knownActions[ 0 ] );
49798
49799				this._addInactiveAction( action, clipUuid, rootUuid );
49800
49801			}
49802
49803			const bindings = action._propertyBindings;
49804
49805			// increment reference counts / sort out state
49806			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
49807
49808				const binding = bindings[ i ];
49809
49810				if ( binding.useCount ++ === 0 ) {
49811
49812					this._lendBinding( binding );
49813					binding.saveOriginalState();
49814
49815				}
49816
49817			}
49818
49819			this._lendAction( action );
49820
49821		}
49822
49823	}
49824
49825	_deactivateAction( action ) {
49826
49827		if ( this._isActiveAction( action ) ) {
49828
49829			const bindings = action._propertyBindings;
49830
49831			// decrement reference counts / sort out state
49832			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
49833
49834				const binding = bindings[ i ];
49835
49836				if ( -- binding.useCount === 0 ) {
49837
49838					binding.restoreOriginalState();
49839					this._takeBackBinding( binding );
49840
49841				}
49842
49843			}
49844
49845			this._takeBackAction( action );
49846
49847		}
49848
49849	}
49850
49851	// Memory manager
49852
49853	_initMemoryManager() {
49854
49855		this._actions = []; // 'nActiveActions' followed by inactive ones
49856		this._nActiveActions = 0;
49857
49858		this._actionsByClip = {};
49859		// inside:
49860		// {
49861		// 	knownActions: Array< AnimationAction > - used as prototypes
49862		// 	actionByRoot: AnimationAction - lookup
49863		// }
49864
49865
49866		this._bindings = []; // 'nActiveBindings' followed by inactive ones
49867		this._nActiveBindings = 0;
49868
49869		this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
49870
49871
49872		this._controlInterpolants = []; // same game as above
49873		this._nActiveControlInterpolants = 0;
49874
49875		const scope = this;
49876
49877		this.stats = {
49878
49879			actions: {
49880				get total() {
49881
49882					return scope._actions.length;
49883
49884				},
49885				get inUse() {
49886
49887					return scope._nActiveActions;
49888
49889				}
49890			},
49891			bindings: {
49892				get total() {
49893
49894					return scope._bindings.length;
49895
49896				},
49897				get inUse() {
49898
49899					return scope._nActiveBindings;
49900
49901				}
49902			},
49903			controlInterpolants: {
49904				get total() {
49905
49906					return scope._controlInterpolants.length;
49907
49908				},
49909				get inUse() {
49910
49911					return scope._nActiveControlInterpolants;
49912
49913				}
49914			}
49915
49916		};
49917
49918	}
49919
49920	// Memory management for AnimationAction objects
49921
49922	_isActiveAction( action ) {
49923
49924		const index = action._cacheIndex;
49925		return index !== null && index < this._nActiveActions;
49926
49927	}
49928
49929	_addInactiveAction( action, clipUuid, rootUuid ) {
49930
49931		const actions = this._actions,
49932			actionsByClip = this._actionsByClip;
49933
49934		let actionsForClip = actionsByClip[ clipUuid ];
49935
49936		if ( actionsForClip === undefined ) {
49937
49938			actionsForClip = {
49939
49940				knownActions: [ action ],
49941				actionByRoot: {}
49942
49943			};
49944
49945			action._byClipCacheIndex = 0;
49946
49947			actionsByClip[ clipUuid ] = actionsForClip;
49948
49949		} else {
49950
49951			const knownActions = actionsForClip.knownActions;
49952
49953			action._byClipCacheIndex = knownActions.length;
49954			knownActions.push( action );
49955
49956		}
49957
49958		action._cacheIndex = actions.length;
49959		actions.push( action );
49960
49961		actionsForClip.actionByRoot[ rootUuid ] = action;
49962
49963	}
49964
49965	_removeInactiveAction( action ) {
49966
49967		const actions = this._actions,
49968			lastInactiveAction = actions[ actions.length - 1 ],
49969			cacheIndex = action._cacheIndex;
49970
49971		lastInactiveAction._cacheIndex = cacheIndex;
49972		actions[ cacheIndex ] = lastInactiveAction;
49973		actions.pop();
49974
49975		action._cacheIndex = null;
49976
49977
49978		const clipUuid = action._clip.uuid,
49979			actionsByClip = this._actionsByClip,
49980			actionsForClip = actionsByClip[ clipUuid ],
49981			knownActionsForClip = actionsForClip.knownActions,
49982
49983			lastKnownAction =
49984				knownActionsForClip[ knownActionsForClip.length - 1 ],
49985
49986			byClipCacheIndex = action._byClipCacheIndex;
49987
49988		lastKnownAction._byClipCacheIndex = byClipCacheIndex;
49989		knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
49990		knownActionsForClip.pop();
49991
49992		action._byClipCacheIndex = null;
49993
49994
49995		const actionByRoot = actionsForClip.actionByRoot,
49996			rootUuid = ( action._localRoot || this._root ).uuid;
49997
49998		delete actionByRoot[ rootUuid ];
49999
50000		if ( knownActionsForClip.length === 0 ) {
50001
50002			delete actionsByClip[ clipUuid ];
50003
50004		}
50005
50006		this._removeInactiveBindingsForAction( action );
50007
50008	}
50009
50010	_removeInactiveBindingsForAction( action ) {
50011
50012		const bindings = action._propertyBindings;
50013
50014		for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
50015
50016			const binding = bindings[ i ];
50017
50018			if ( -- binding.referenceCount === 0 ) {
50019
50020				this._removeInactiveBinding( binding );
50021
50022			}
50023
50024		}
50025
50026	}
50027
50028	_lendAction( action ) {
50029
50030		// [ active actions |  inactive actions  ]
50031		// [  active actions >| inactive actions ]
50032		//                 s        a
50033		//                  <-swap->
50034		//                 a        s
50035
50036		const actions = this._actions,
50037			prevIndex = action._cacheIndex,
50038
50039			lastActiveIndex = this._nActiveActions ++,
50040
50041			firstInactiveAction = actions[ lastActiveIndex ];
50042
50043		action._cacheIndex = lastActiveIndex;
50044		actions[ lastActiveIndex ] = action;
50045
50046		firstInactiveAction._cacheIndex = prevIndex;
50047		actions[ prevIndex ] = firstInactiveAction;
50048
50049	}
50050
50051	_takeBackAction( action ) {
50052
50053		// [  active actions  | inactive actions ]
50054		// [ active actions |< inactive actions  ]
50055		//        a        s
50056		//         <-swap->
50057		//        s        a
50058
50059		const actions = this._actions,
50060			prevIndex = action._cacheIndex,
50061
50062			firstInactiveIndex = -- this._nActiveActions,
50063
50064			lastActiveAction = actions[ firstInactiveIndex ];
50065
50066		action._cacheIndex = firstInactiveIndex;
50067		actions[ firstInactiveIndex ] = action;
50068
50069		lastActiveAction._cacheIndex = prevIndex;
50070		actions[ prevIndex ] = lastActiveAction;
50071
50072	}
50073
50074	// Memory management for PropertyMixer objects
50075
50076	_addInactiveBinding( binding, rootUuid, trackName ) {
50077
50078		const bindingsByRoot = this._bindingsByRootAndName,
50079			bindings = this._bindings;
50080
50081		let bindingByName = bindingsByRoot[ rootUuid ];
50082
50083		if ( bindingByName === undefined ) {
50084
50085			bindingByName = {};
50086			bindingsByRoot[ rootUuid ] = bindingByName;
50087
50088		}
50089
50090		bindingByName[ trackName ] = binding;
50091
50092		binding._cacheIndex = bindings.length;
50093		bindings.push( binding );
50094
50095	}
50096
50097	_removeInactiveBinding( binding ) {
50098
50099		const bindings = this._bindings,
50100			propBinding = binding.binding,
50101			rootUuid = propBinding.rootNode.uuid,
50102			trackName = propBinding.path,
50103			bindingsByRoot = this._bindingsByRootAndName,
50104			bindingByName = bindingsByRoot[ rootUuid ],
50105
50106			lastInactiveBinding = bindings[ bindings.length - 1 ],
50107			cacheIndex = binding._cacheIndex;
50108
50109		lastInactiveBinding._cacheIndex = cacheIndex;
50110		bindings[ cacheIndex ] = lastInactiveBinding;
50111		bindings.pop();
50112
50113		delete bindingByName[ trackName ];
50114
50115		if ( Object.keys( bindingByName ).length === 0 ) {
50116
50117			delete bindingsByRoot[ rootUuid ];
50118
50119		}
50120
50121	}
50122
50123	_lendBinding( binding ) {
50124
50125		const bindings = this._bindings,
50126			prevIndex = binding._cacheIndex,
50127
50128			lastActiveIndex = this._nActiveBindings ++,
50129
50130			firstInactiveBinding = bindings[ lastActiveIndex ];
50131
50132		binding._cacheIndex = lastActiveIndex;
50133		bindings[ lastActiveIndex ] = binding;
50134
50135		firstInactiveBinding._cacheIndex = prevIndex;
50136		bindings[ prevIndex ] = firstInactiveBinding;
50137
50138	}
50139
50140	_takeBackBinding( binding ) {
50141
50142		const bindings = this._bindings,
50143			prevIndex = binding._cacheIndex,
50144
50145			firstInactiveIndex = -- this._nActiveBindings,
50146
50147			lastActiveBinding = bindings[ firstInactiveIndex ];
50148
50149		binding._cacheIndex = firstInactiveIndex;
50150		bindings[ firstInactiveIndex ] = binding;
50151
50152		lastActiveBinding._cacheIndex = prevIndex;
50153		bindings[ prevIndex ] = lastActiveBinding;
50154
50155	}
50156
50157
50158	// Memory management of Interpolants for weight and time scale
50159
50160	_lendControlInterpolant() {
50161
50162		const interpolants = this._controlInterpolants,
50163			lastActiveIndex = this._nActiveControlInterpolants ++;
50164
50165		let interpolant = interpolants[ lastActiveIndex ];
50166
50167		if ( interpolant === undefined ) {
50168
50169			interpolant = new LinearInterpolant(
50170				new Float32Array( 2 ), new Float32Array( 2 ),
50171				1, _controlInterpolantsResultBuffer );
50172
50173			interpolant.__cacheIndex = lastActiveIndex;
50174			interpolants[ lastActiveIndex ] = interpolant;
50175
50176		}
50177
50178		return interpolant;
50179
50180	}
50181
50182	_takeBackControlInterpolant( interpolant ) {
50183
50184		const interpolants = this._controlInterpolants,
50185			prevIndex = interpolant.__cacheIndex,
50186
50187			firstInactiveIndex = -- this._nActiveControlInterpolants,
50188
50189			lastActiveInterpolant = interpolants[ firstInactiveIndex ];
50190
50191		interpolant.__cacheIndex = firstInactiveIndex;
50192		interpolants[ firstInactiveIndex ] = interpolant;
50193
50194		lastActiveInterpolant.__cacheIndex = prevIndex;
50195		interpolants[ prevIndex ] = lastActiveInterpolant;
50196
50197	}
50198
50199	// return an action for a clip optionally using a custom root target
50200	// object (this method allocates a lot of dynamic memory in case a
50201	// previously unknown clip/root combination is specified)
50202	clipAction( clip, optionalRoot, blendMode ) {
50203
50204		const root = optionalRoot || this._root,
50205			rootUuid = root.uuid;
50206
50207		let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
50208
50209		const clipUuid = clipObject !== null ? clipObject.uuid : clip;
50210
50211		const actionsForClip = this._actionsByClip[ clipUuid ];
50212		let prototypeAction = null;
50213
50214		if ( blendMode === undefined ) {
50215
50216			if ( clipObject !== null ) {
50217
50218				blendMode = clipObject.blendMode;
50219
50220			} else {
50221
50222				blendMode = NormalAnimationBlendMode;
50223
50224			}
50225
50226		}
50227
50228		if ( actionsForClip !== undefined ) {
50229
50230			const existingAction = actionsForClip.actionByRoot[ rootUuid ];
50231
50232			if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
50233
50234				return existingAction;
50235
50236			}
50237
50238			// we know the clip, so we don't have to parse all
50239			// the bindings again but can just copy
50240			prototypeAction = actionsForClip.knownActions[ 0 ];
50241
50242			// also, take the clip from the prototype action
50243			if ( clipObject === null )
50244				clipObject = prototypeAction._clip;
50245
50246		}
50247
50248		// clip must be known when specified via string
50249		if ( clipObject === null ) return null;
50250
50251		// allocate all resources required to run it
50252		const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
50253
50254		this._bindAction( newAction, prototypeAction );
50255
50256		// and make the action known to the memory manager
50257		this._addInactiveAction( newAction, clipUuid, rootUuid );
50258
50259		return newAction;
50260
50261	}
50262
50263	// get an existing action
50264	existingAction( clip, optionalRoot ) {
50265
50266		const root = optionalRoot || this._root,
50267			rootUuid = root.uuid,
50268
50269			clipObject = typeof clip === 'string' ?
50270				AnimationClip.findByName( root, clip ) : clip,
50271
50272			clipUuid = clipObject ? clipObject.uuid : clip,
50273
50274			actionsForClip = this._actionsByClip[ clipUuid ];
50275
50276		if ( actionsForClip !== undefined ) {
50277
50278			return actionsForClip.actionByRoot[ rootUuid ] || null;
50279
50280		}
50281
50282		return null;
50283
50284	}
50285
50286	// deactivates all previously scheduled actions
50287	stopAllAction() {
50288
50289		const actions = this._actions,
50290			nActions = this._nActiveActions;
50291
50292		for ( let i = nActions - 1; i >= 0; -- i ) {
50293
50294			actions[ i ].stop();
50295
50296		}
50297
50298		return this;
50299
50300	}
50301
50302	// advance the time and update apply the animation
50303	update( deltaTime ) {
50304
50305		deltaTime *= this.timeScale;
50306
50307		const actions = this._actions,
50308			nActions = this._nActiveActions,
50309
50310			time = this.time += deltaTime,
50311			timeDirection = Math.sign( deltaTime ),
50312
50313			accuIndex = this._accuIndex ^= 1;
50314
50315		// run active actions
50316
50317		for ( let i = 0; i !== nActions; ++ i ) {
50318
50319			const action = actions[ i ];
50320
50321			action._update( time, deltaTime, timeDirection, accuIndex );
50322
50323		}
50324
50325		// update scene graph
50326
50327		const bindings = this._bindings,
50328			nBindings = this._nActiveBindings;
50329
50330		for ( let i = 0; i !== nBindings; ++ i ) {
50331
50332			bindings[ i ].apply( accuIndex );
50333
50334		}
50335
50336		return this;
50337
50338	}
50339
vendor: 2,763 bytes, lines 50340-50473
50340	// Allows you to seek to a specific time in an animation.
50341	setTime( timeInSeconds ) {
50342
50343		this.time = 0; // Zero out time attribute for AnimationMixer object;
50344		for ( let i = 0; i < this._actions.length; i ++ ) {
50345
50346			this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
50347
50348		}
50349
50350		return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
50351
50352	}
50353
50354	// return this mixer's root target object
50355	getRoot() {
50356
50357		return this._root;
50358
50359	}
50360
50361	// free all resources specific to a particular clip
50362	uncacheClip( clip ) {
50363
50364		const actions = this._actions,
50365			clipUuid = clip.uuid,
50366			actionsByClip = this._actionsByClip,
50367			actionsForClip = actionsByClip[ clipUuid ];
50368
50369		if ( actionsForClip !== undefined ) {
50370
50371			// note: just calling _removeInactiveAction would mess up the
50372			// iteration state and also require updating the state we can
50373			// just throw away
50374
50375			const actionsToRemove = actionsForClip.knownActions;
50376
50377			for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
50378
50379				const action = actionsToRemove[ i ];
50380
50381				this._deactivateAction( action );
50382
50383				const cacheIndex = action._cacheIndex,
50384					lastInactiveAction = actions[ actions.length - 1 ];
50385
50386				action._cacheIndex = null;
50387				action._byClipCacheIndex = null;
50388
50389				lastInactiveAction._cacheIndex = cacheIndex;
50390				actions[ cacheIndex ] = lastInactiveAction;
50391				actions.pop();
50392
50393				this._removeInactiveBindingsForAction( action );
50394
50395			}
50396
50397			delete actionsByClip[ clipUuid ];
50398
50399		}
50400
50401	}
50402
50403	// free all resources specific to a particular root target object
50404	uncacheRoot( root ) {
50405
50406		const rootUuid = root.uuid,
50407			actionsByClip = this._actionsByClip;
50408
50409		for ( const clipUuid in actionsByClip ) {
50410
50411			const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
50412				action = actionByRoot[ rootUuid ];
50413
50414			if ( action !== undefined ) {
50415
50416				this._deactivateAction( action );
50417				this._removeInactiveAction( action );
50418
50419			}
50420
50421		}
50422
50423		const bindingsByRoot = this._bindingsByRootAndName,
50424			bindingByName = bindingsByRoot[ rootUuid ];
50425
50426		if ( bindingByName !== undefined ) {
50427
50428			for ( const trackName in bindingByName ) {
50429
50430				const binding = bindingByName[ trackName ];
50431				binding.restoreOriginalState();
50432				this._removeInactiveBinding( binding );
50433
50434			}
50435
50436		}
50437
50438	}
50439
50440	// remove a targeted clip from the cache
50441	uncacheAction( clip, optionalRoot ) {
50442
50443		const action = this.existingAction( clip, optionalRoot );
50444
50445		if ( action !== null ) {
50446
50447			this._deactivateAction( action );
50448			this._removeInactiveAction( action );
50449
50450		}
50451
50452	}
50453
50454}
50455
50456class Uniform {
50457
50458	constructor( value ) {
50459
50460		this.value = value;
50461
50462	}
50463
50464	clone() {
50465
50466		return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
50467
50468	}
50469
50470}
50471
50472let _id = 0;
50473
vendor: 5,200 bytes, lines 50474-50796
50474class UniformsGroup extends EventDispatcher {
50475
50476	constructor() {
50477
50478		super();
50479
50480		this.isUniformsGroup = true;
50481
50482		Object.defineProperty( this, 'id', { value: _id ++ } );
50483
50484		this.name = '';
50485
50486		this.usage = StaticDrawUsage;
50487		this.uniforms = [];
50488
50489	}
50490
50491	add( uniform ) {
50492
50493		this.uniforms.push( uniform );
50494
50495		return this;
50496
50497	}
50498
50499	remove( uniform ) {
50500
50501		const index = this.uniforms.indexOf( uniform );
50502
50503		if ( index !== - 1 ) this.uniforms.splice( index, 1 );
50504
50505		return this;
50506
50507	}
50508
50509	setName( name ) {
50510
50511		this.name = name;
50512
50513		return this;
50514
50515	}
50516
50517	setUsage( value ) {
50518
50519		this.usage = value;
50520
50521		return this;
50522
50523	}
50524
50525	dispose() {
50526
50527		this.dispatchEvent( { type: 'dispose' } );
50528
50529		return this;
50530
50531	}
50532
50533	copy( source ) {
50534
50535		this.name = source.name;
50536		this.usage = source.usage;
50537
50538		const uniformsSource = source.uniforms;
50539
50540		this.uniforms.length = 0;
50541
50542		for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) {
50543
50544			const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ];
50545
50546			for ( let j = 0; j < uniforms.length; j ++ ) {
50547
50548				this.uniforms.push( uniforms[ j ].clone() );
50549
50550			}
50551
50552		}
50553
50554		return this;
50555
50556	}
50557
50558	clone() {
50559
50560		return new this.constructor().copy( this );
50561
50562	}
50563
50564}
50565
50566class InstancedInterleavedBuffer extends InterleavedBuffer {
50567
50568	constructor( array, stride, meshPerAttribute = 1 ) {
50569
50570		super( array, stride );
50571
50572		this.isInstancedInterleavedBuffer = true;
50573
50574		this.meshPerAttribute = meshPerAttribute;
50575
50576	}
50577
50578	copy( source ) {
50579
50580		super.copy( source );
50581
50582		this.meshPerAttribute = source.meshPerAttribute;
50583
50584		return this;
50585
50586	}
50587
50588	clone( data ) {
50589
50590		const ib = super.clone( data );
50591
50592		ib.meshPerAttribute = this.meshPerAttribute;
50593
50594		return ib;
50595
50596	}
50597
50598	toJSON( data ) {
50599
50600		const json = super.toJSON( data );
50601
50602		json.isInstancedInterleavedBuffer = true;
50603		json.meshPerAttribute = this.meshPerAttribute;
50604
50605		return json;
50606
50607	}
50608
50609}
50610
50611class GLBufferAttribute {
50612
50613	constructor( buffer, type, itemSize, elementSize, count ) {
50614
50615		this.isGLBufferAttribute = true;
50616
50617		this.name = '';
50618
50619		this.buffer = buffer;
50620		this.type = type;
50621		this.itemSize = itemSize;
50622		this.elementSize = elementSize;
50623		this.count = count;
50624
50625		this.version = 0;
50626
50627	}
50628
50629	set needsUpdate( value ) {
50630
50631		if ( value === true ) this.version ++;
50632
50633	}
50634
50635	setBuffer( buffer ) {
50636
50637		this.buffer = buffer;
50638
50639		return this;
50640
50641	}
50642
50643	setType( type, elementSize ) {
50644
50645		this.type = type;
50646		this.elementSize = elementSize;
50647
50648		return this;
50649
50650	}
50651
50652	setItemSize( itemSize ) {
50653
50654		this.itemSize = itemSize;
50655
50656		return this;
50657
50658	}
50659
50660	setCount( count ) {
50661
50662		this.count = count;
50663
50664		return this;
50665
50666	}
50667
50668}
50669
50670const _matrix = /*@__PURE__*/ new Matrix4();
50671
50672class Raycaster {
50673
50674	constructor( origin, direction, near = 0, far = Infinity ) {
50675
50676		this.ray = new Ray( origin, direction );
50677		// direction is assumed to be normalized (for accurate distance calculations)
50678
50679		this.near = near;
50680		this.far = far;
50681		this.camera = null;
50682		this.layers = new Layers();
50683
50684		this.params = {
50685			Mesh: {},
50686			Line: { threshold: 1 },
50687			LOD: {},
50688			Points: { threshold: 1 },
50689			Sprite: {}
50690		};
50691
50692	}
50693
50694	set( origin, direction ) {
50695
50696		// direction is assumed to be normalized (for accurate distance calculations)
50697
50698		this.ray.set( origin, direction );
50699
50700	}
50701
50702	setFromCamera( coords, camera ) {
50703
50704		if ( camera.isPerspectiveCamera ) {
50705
50706			this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
50707			this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
50708			this.camera = camera;
50709
50710		} else if ( camera.isOrthographicCamera ) {
50711
50712			this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
50713			this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
50714			this.camera = camera;
50715
50716		} else {
50717
50718			console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
50719
50720		}
50721
50722	}
50723
50724	setFromXRController( controller ) {
50725
50726		_matrix.identity().extractRotation( controller.matrixWorld );
50727
50728		this.ray.origin.setFromMatrixPosition( controller.matrixWorld );
50729		this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix );
50730
50731		return this;
50732
50733	}
50734
50735	intersectObject( object, recursive = true, intersects = [] ) {
50736
50737		intersect( object, this, intersects, recursive );
50738
50739		intersects.sort( ascSort );
50740
50741		return intersects;
50742
50743	}
50744
50745	intersectObjects( objects, recursive = true, intersects = [] ) {
50746
50747		for ( let i = 0, l = objects.length; i < l; i ++ ) {
50748
50749			intersect( objects[ i ], this, intersects, recursive );
50750
50751		}
50752
50753		intersects.sort( ascSort );
50754
50755		return intersects;
50756
50757	}
50758
50759}
50760
50761function ascSort( a, b ) {
50762
50763	return a.distance - b.distance;
50764
50765}
50766
50767function intersect( object, raycaster, intersects, recursive ) {
50768
50769	if ( object.layers.test( raycaster.layers ) ) {
50770
50771		object.raycast( raycaster, intersects );
50772
50773	}
50774
50775	if ( recursive === true ) {
50776
50777		const children = object.children;
50778
50779		for ( let i = 0, l = children.length; i < l; i ++ ) {
50780
50781			intersect( children[ i ], raycaster, intersects, true );
50782
50783		}
50784
50785	}
50786
50787}
50788
50789/**
50790 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
50791 *
50792 * phi (the polar angle) is measured from the positive y-axis. The positive y-axis is up.
50793 * theta (the azimuthal angle) is measured from the positive z-axis.
50794 */
50795class Spherical {
50796
vendor: 21,135 bytes, lines 50797-51949
50797	constructor( radius = 1, phi = 0, theta = 0 ) {
50798
50799		this.radius = radius;
50800		this.phi = phi; // polar angle
50801		this.theta = theta; // azimuthal angle
50802
50803		return this;
50804
50805	}
50806
50807	set( radius, phi, theta ) {
50808
50809		this.radius = radius;
50810		this.phi = phi;
50811		this.theta = theta;
50812
50813		return this;
50814
50815	}
50816
50817	copy( other ) {
50818
50819		this.radius = other.radius;
50820		this.phi = other.phi;
50821		this.theta = other.theta;
50822
50823		return this;
50824
50825	}
50826
50827	// restrict phi to be between EPS and PI-EPS
50828	makeSafe() {
50829
50830		const EPS = 0.000001;
50831		this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
50832
50833		return this;
50834
50835	}
50836
50837	setFromVector3( v ) {
50838
50839		return this.setFromCartesianCoords( v.x, v.y, v.z );
50840
50841	}
50842
50843	setFromCartesianCoords( x, y, z ) {
50844
50845		this.radius = Math.sqrt( x * x + y * y + z * z );
50846
50847		if ( this.radius === 0 ) {
50848
50849			this.theta = 0;
50850			this.phi = 0;
50851
50852		} else {
50853
50854			this.theta = Math.atan2( x, z );
50855			this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) );
50856
50857		}
50858
50859		return this;
50860
50861	}
50862
50863	clone() {
50864
50865		return new this.constructor().copy( this );
50866
50867	}
50868
50869}
50870
50871/**
50872 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
50873 */
50874
50875class Cylindrical {
50876
50877	constructor( radius = 1, theta = 0, y = 0 ) {
50878
50879		this.radius = radius; // distance from the origin to a point in the x-z plane
50880		this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
50881		this.y = y; // height above the x-z plane
50882
50883		return this;
50884
50885	}
50886
50887	set( radius, theta, y ) {
50888
50889		this.radius = radius;
50890		this.theta = theta;
50891		this.y = y;
50892
50893		return this;
50894
50895	}
50896
50897	copy( other ) {
50898
50899		this.radius = other.radius;
50900		this.theta = other.theta;
50901		this.y = other.y;
50902
50903		return this;
50904
50905	}
50906
50907	setFromVector3( v ) {
50908
50909		return this.setFromCartesianCoords( v.x, v.y, v.z );
50910
50911	}
50912
50913	setFromCartesianCoords( x, y, z ) {
50914
50915		this.radius = Math.sqrt( x * x + z * z );
50916		this.theta = Math.atan2( x, z );
50917		this.y = y;
50918
50919		return this;
50920
50921	}
50922
50923	clone() {
50924
50925		return new this.constructor().copy( this );
50926
50927	}
50928
50929}
50930
50931const _vector$4 = /*@__PURE__*/ new Vector2();
50932
50933class Box2 {
50934
50935	constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) {
50936
50937		this.isBox2 = true;
50938
50939		this.min = min;
50940		this.max = max;
50941
50942	}
50943
50944	set( min, max ) {
50945
50946		this.min.copy( min );
50947		this.max.copy( max );
50948
50949		return this;
50950
50951	}
50952
50953	setFromPoints( points ) {
50954
50955		this.makeEmpty();
50956
50957		for ( let i = 0, il = points.length; i < il; i ++ ) {
50958
50959			this.expandByPoint( points[ i ] );
50960
50961		}
50962
50963		return this;
50964
50965	}
50966
50967	setFromCenterAndSize( center, size ) {
50968
50969		const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 );
50970		this.min.copy( center ).sub( halfSize );
50971		this.max.copy( center ).add( halfSize );
50972
50973		return this;
50974
50975	}
50976
50977	clone() {
50978
50979		return new this.constructor().copy( this );
50980
50981	}
50982
50983	copy( box ) {
50984
50985		this.min.copy( box.min );
50986		this.max.copy( box.max );
50987
50988		return this;
50989
50990	}
50991
50992	makeEmpty() {
50993
50994		this.min.x = this.min.y = + Infinity;
50995		this.max.x = this.max.y = - Infinity;
50996
50997		return this;
50998
50999	}
51000
51001	isEmpty() {
51002
51003		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
51004
51005		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
51006
51007	}
51008
51009	getCenter( target ) {
51010
51011		return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
51012
51013	}
51014
51015	getSize( target ) {
51016
51017		return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
51018
51019	}
51020
51021	expandByPoint( point ) {
51022
51023		this.min.min( point );
51024		this.max.max( point );
51025
51026		return this;
51027
51028	}
51029
51030	expandByVector( vector ) {
51031
51032		this.min.sub( vector );
51033		this.max.add( vector );
51034
51035		return this;
51036
51037	}
51038
51039	expandByScalar( scalar ) {
51040
51041		this.min.addScalar( - scalar );
51042		this.max.addScalar( scalar );
51043
51044		return this;
51045
51046	}
51047
51048	containsPoint( point ) {
51049
51050		return point.x < this.min.x || point.x > this.max.x ||
51051			point.y < this.min.y || point.y > this.max.y ? false : true;
51052
51053	}
51054
51055	containsBox( box ) {
51056
51057		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
51058			this.min.y <= box.min.y && box.max.y <= this.max.y;
51059
51060	}
51061
51062	getParameter( point, target ) {
51063
51064		// This can potentially have a divide by zero if the box
51065		// has a size dimension of 0.
51066
51067		return target.set(
51068			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
51069			( point.y - this.min.y ) / ( this.max.y - this.min.y )
51070		);
51071
51072	}
51073
51074	intersectsBox( box ) {
51075
51076		// using 4 splitting planes to rule out intersections
51077
51078		return box.max.x < this.min.x || box.min.x > this.max.x ||
51079			box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
51080
51081	}
51082
51083	clampPoint( point, target ) {
51084
51085		return target.copy( point ).clamp( this.min, this.max );
51086
51087	}
51088
51089	distanceToPoint( point ) {
51090
51091		return this.clampPoint( point, _vector$4 ).distanceTo( point );
51092
51093	}
51094
51095	intersect( box ) {
51096
51097		this.min.max( box.min );
51098		this.max.min( box.max );
51099
51100		if ( this.isEmpty() ) this.makeEmpty();
51101
51102		return this;
51103
51104	}
51105
51106	union( box ) {
51107
51108		this.min.min( box.min );
51109		this.max.max( box.max );
51110
51111		return this;
51112
51113	}
51114
51115	translate( offset ) {
51116
51117		this.min.add( offset );
51118		this.max.add( offset );
51119
51120		return this;
51121
51122	}
51123
51124	equals( box ) {
51125
51126		return box.min.equals( this.min ) && box.max.equals( this.max );
51127
51128	}
51129
51130}
51131
51132const _startP = /*@__PURE__*/ new Vector3();
51133const _startEnd = /*@__PURE__*/ new Vector3();
51134
51135class Line3 {
51136
51137	constructor( start = new Vector3(), end = new Vector3() ) {
51138
51139		this.start = start;
51140		this.end = end;
51141
51142	}
51143
51144	set( start, end ) {
51145
51146		this.start.copy( start );
51147		this.end.copy( end );
51148
51149		return this;
51150
51151	}
51152
51153	copy( line ) {
51154
51155		this.start.copy( line.start );
51156		this.end.copy( line.end );
51157
51158		return this;
51159
51160	}
51161
51162	getCenter( target ) {
51163
51164		return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
51165
51166	}
51167
51168	delta( target ) {
51169
51170		return target.subVectors( this.end, this.start );
51171
51172	}
51173
51174	distanceSq() {
51175
51176		return this.start.distanceToSquared( this.end );
51177
51178	}
51179
51180	distance() {
51181
51182		return this.start.distanceTo( this.end );
51183
51184	}
51185
51186	at( t, target ) {
51187
51188		return this.delta( target ).multiplyScalar( t ).add( this.start );
51189
51190	}
51191
51192	closestPointToPointParameter( point, clampToLine ) {
51193
51194		_startP.subVectors( point, this.start );
51195		_startEnd.subVectors( this.end, this.start );
51196
51197		const startEnd2 = _startEnd.dot( _startEnd );
51198		const startEnd_startP = _startEnd.dot( _startP );
51199
51200		let t = startEnd_startP / startEnd2;
51201
51202		if ( clampToLine ) {
51203
51204			t = clamp( t, 0, 1 );
51205
51206		}
51207
51208		return t;
51209
51210	}
51211
51212	closestPointToPoint( point, clampToLine, target ) {
51213
51214		const t = this.closestPointToPointParameter( point, clampToLine );
51215
51216		return this.delta( target ).multiplyScalar( t ).add( this.start );
51217
51218	}
51219
51220	applyMatrix4( matrix ) {
51221
51222		this.start.applyMatrix4( matrix );
51223		this.end.applyMatrix4( matrix );
51224
51225		return this;
51226
51227	}
51228
51229	equals( line ) {
51230
51231		return line.start.equals( this.start ) && line.end.equals( this.end );
51232
51233	}
51234
51235	clone() {
51236
51237		return new this.constructor().copy( this );
51238
51239	}
51240
51241}
51242
51243const _vector$3 = /*@__PURE__*/ new Vector3();
51244
51245class SpotLightHelper extends Object3D {
51246
51247	constructor( light, color ) {
51248
51249		super();
51250
51251		this.light = light;
51252
51253		this.matrixAutoUpdate = false;
51254
51255		this.color = color;
51256
51257		this.type = 'SpotLightHelper';
51258
51259		const geometry = new BufferGeometry();
51260
51261		const positions = [
51262			0, 0, 0, 	0, 0, 1,
51263			0, 0, 0, 	1, 0, 1,
51264			0, 0, 0,	- 1, 0, 1,
51265			0, 0, 0, 	0, 1, 1,
51266			0, 0, 0, 	0, - 1, 1
51267		];
51268
51269		for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
51270
51271			const p1 = ( i / l ) * Math.PI * 2;
51272			const p2 = ( j / l ) * Math.PI * 2;
51273
51274			positions.push(
51275				Math.cos( p1 ), Math.sin( p1 ), 1,
51276				Math.cos( p2 ), Math.sin( p2 ), 1
51277			);
51278
51279		}
51280
51281		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
51282
51283		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
51284
51285		this.cone = new LineSegments( geometry, material );
51286		this.add( this.cone );
51287
51288		this.update();
51289
51290	}
51291
51292	dispose() {
51293
51294		this.cone.geometry.dispose();
51295		this.cone.material.dispose();
51296
51297	}
51298
51299	update() {
51300
51301		this.light.updateWorldMatrix( true, false );
51302		this.light.target.updateWorldMatrix( true, false );
51303
51304		// update the local matrix based on the parent and light target transforms
51305		if ( this.parent ) {
51306
51307			this.parent.updateWorldMatrix( true );
51308
51309			this.matrix
51310				.copy( this.parent.matrixWorld )
51311				.invert()
51312				.multiply( this.light.matrixWorld );
51313
51314		} else {
51315
51316			this.matrix.copy( this.light.matrixWorld );
51317
51318		}
51319
51320		this.matrixWorld.copy( this.light.matrixWorld );
51321
51322		const coneLength = this.light.distance ? this.light.distance : 1000;
51323		const coneWidth = coneLength * Math.tan( this.light.angle );
51324
51325		this.cone.scale.set( coneWidth, coneWidth, coneLength );
51326
51327		_vector$3.setFromMatrixPosition( this.light.target.matrixWorld );
51328
51329		this.cone.lookAt( _vector$3 );
51330
51331		if ( this.color !== undefined ) {
51332
51333			this.cone.material.color.set( this.color );
51334
51335		} else {
51336
51337			this.cone.material.color.copy( this.light.color );
51338
51339		}
51340
51341	}
51342
51343}
51344
51345const _vector$2 = /*@__PURE__*/ new Vector3();
51346const _boneMatrix = /*@__PURE__*/ new Matrix4();
51347const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
51348
51349
51350class SkeletonHelper extends LineSegments {
51351
51352	constructor( object ) {
51353
51354		const bones = getBoneList( object );
51355
51356		const geometry = new BufferGeometry();
51357
51358		const vertices = [];
51359		const colors = [];
51360
51361		const color1 = new Color( 0, 0, 1 );
51362		const color2 = new Color( 0, 1, 0 );
51363
51364		for ( let i = 0; i < bones.length; i ++ ) {
51365
51366			const bone = bones[ i ];
51367
51368			if ( bone.parent && bone.parent.isBone ) {
51369
51370				vertices.push( 0, 0, 0 );
51371				vertices.push( 0, 0, 0 );
51372				colors.push( color1.r, color1.g, color1.b );
51373				colors.push( color2.r, color2.g, color2.b );
51374
51375			}
51376
51377		}
51378
51379		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
51380		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
51381
51382		const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
51383
51384		super( geometry, material );
51385
51386		this.isSkeletonHelper = true;
51387
51388		this.type = 'SkeletonHelper';
51389
51390		this.root = object;
51391		this.bones = bones;
51392
51393		this.matrix = object.matrixWorld;
51394		this.matrixAutoUpdate = false;
51395
51396	}
51397
51398	updateMatrixWorld( force ) {
51399
51400		const bones = this.bones;
51401
51402		const geometry = this.geometry;
51403		const position = geometry.getAttribute( 'position' );
51404
51405		_matrixWorldInv.copy( this.root.matrixWorld ).invert();
51406
51407		for ( let i = 0, j = 0; i < bones.length; i ++ ) {
51408
51409			const bone = bones[ i ];
51410
51411			if ( bone.parent && bone.parent.isBone ) {
51412
51413				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
51414				_vector$2.setFromMatrixPosition( _boneMatrix );
51415				position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z );
51416
51417				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
51418				_vector$2.setFromMatrixPosition( _boneMatrix );
51419				position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z );
51420
51421				j += 2;
51422
51423			}
51424
51425		}
51426
51427		geometry.getAttribute( 'position' ).needsUpdate = true;
51428
51429		super.updateMatrixWorld( force );
51430
51431	}
51432
51433	dispose() {
51434
51435		this.geometry.dispose();
51436		this.material.dispose();
51437
51438	}
51439
51440}
51441
51442
51443function getBoneList( object ) {
51444
51445	const boneList = [];
51446
51447	if ( object.isBone === true ) {
51448
51449		boneList.push( object );
51450
51451	}
51452
51453	for ( let i = 0; i < object.children.length; i ++ ) {
51454
51455		boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
51456
51457	}
51458
51459	return boneList;
51460
51461}
51462
51463class PointLightHelper extends Mesh {
51464
51465	constructor( light, sphereSize, color ) {
51466
51467		const geometry = new SphereGeometry( sphereSize, 4, 2 );
51468		const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
51469
51470		super( geometry, material );
51471
51472		this.light = light;
51473
51474		this.color = color;
51475
51476		this.type = 'PointLightHelper';
51477
51478		this.matrix = this.light.matrixWorld;
51479		this.matrixAutoUpdate = false;
51480
51481		this.update();
51482
51483
51484		/*
51485	// TODO: delete this comment?
51486	const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
51487	const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
51488
51489	this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
51490	this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
51491
51492	const d = light.distance;
51493
51494	if ( d === 0.0 ) {
51495
51496		this.lightDistance.visible = false;
51497
51498	} else {
51499
51500		this.lightDistance.scale.set( d, d, d );
51501
51502	}
51503
51504	this.add( this.lightDistance );
51505	*/
51506
51507	}
51508
51509	dispose() {
51510
51511		this.geometry.dispose();
51512		this.material.dispose();
51513
51514	}
51515
51516	update() {
51517
51518		this.light.updateWorldMatrix( true, false );
51519
51520		if ( this.color !== undefined ) {
51521
51522			this.material.color.set( this.color );
51523
51524		} else {
51525
51526			this.material.color.copy( this.light.color );
51527
51528		}
51529
51530		/*
51531		const d = this.light.distance;
51532
51533		if ( d === 0.0 ) {
51534
51535			this.lightDistance.visible = false;
51536
51537		} else {
51538
51539			this.lightDistance.visible = true;
51540			this.lightDistance.scale.set( d, d, d );
51541
51542		}
51543		*/
51544
51545	}
51546
51547}
51548
51549const _vector$1 = /*@__PURE__*/ new Vector3();
51550const _color1 = /*@__PURE__*/ new Color();
51551const _color2 = /*@__PURE__*/ new Color();
51552
51553class HemisphereLightHelper extends Object3D {
51554
51555	constructor( light, size, color ) {
51556
51557		super();
51558
51559		this.light = light;
51560
51561		this.matrix = light.matrixWorld;
51562		this.matrixAutoUpdate = false;
51563
51564		this.color = color;
51565
51566		this.type = 'HemisphereLightHelper';
51567
51568		const geometry = new OctahedronGeometry( size );
51569		geometry.rotateY( Math.PI * 0.5 );
51570
51571		this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
51572		if ( this.color === undefined ) this.material.vertexColors = true;
51573
51574		const position = geometry.getAttribute( 'position' );
51575		const colors = new Float32Array( position.count * 3 );
51576
51577		geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
51578
51579		this.add( new Mesh( geometry, this.material ) );
51580
51581		this.update();
51582
51583	}
51584
51585	dispose() {
51586
51587		this.children[ 0 ].geometry.dispose();
51588		this.children[ 0 ].material.dispose();
51589
51590	}
51591
51592	update() {
51593
51594		const mesh = this.children[ 0 ];
51595
51596		if ( this.color !== undefined ) {
51597
51598			this.material.color.set( this.color );
51599
51600		} else {
51601
51602			const colors = mesh.geometry.getAttribute( 'color' );
51603
51604			_color1.copy( this.light.color );
51605			_color2.copy( this.light.groundColor );
51606
51607			for ( let i = 0, l = colors.count; i < l; i ++ ) {
51608
51609				const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
51610
51611				colors.setXYZ( i, color.r, color.g, color.b );
51612
51613			}
51614
51615			colors.needsUpdate = true;
51616
51617		}
51618
51619		this.light.updateWorldMatrix( true, false );
51620
51621		mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() );
51622
51623	}
51624
51625}
51626
51627class GridHelper extends LineSegments {
51628
51629	constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
51630
51631		color1 = new Color( color1 );
51632		color2 = new Color( color2 );
51633
51634		const center = divisions / 2;
51635		const step = size / divisions;
51636		const halfSize = size / 2;
51637
51638		const vertices = [], colors = [];
51639
51640		for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
51641
51642			vertices.push( - halfSize, 0, k, halfSize, 0, k );
51643			vertices.push( k, 0, - halfSize, k, 0, halfSize );
51644
51645			const color = i === center ? color1 : color2;
51646
51647			color.toArray( colors, j ); j += 3;
51648			color.toArray( colors, j ); j += 3;
51649			color.toArray( colors, j ); j += 3;
51650			color.toArray( colors, j ); j += 3;
51651
51652		}
51653
51654		const geometry = new BufferGeometry();
51655		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
51656		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
51657
51658		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
51659
51660		super( geometry, material );
51661
51662		this.type = 'GridHelper';
51663
51664	}
51665
51666	dispose() {
51667
51668		this.geometry.dispose();
51669		this.material.dispose();
51670
51671	}
51672
51673}
51674
51675class PolarGridHelper extends LineSegments {
51676
51677	constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
51678
51679		color1 = new Color( color1 );
51680		color2 = new Color( color2 );
51681
51682		const vertices = [];
51683		const colors = [];
51684
51685		// create the sectors
51686
51687		if ( sectors > 1 ) {
51688
51689			for ( let i = 0; i < sectors; i ++ ) {
51690
51691				const v = ( i / sectors ) * ( Math.PI * 2 );
51692
51693				const x = Math.sin( v ) * radius;
51694				const z = Math.cos( v ) * radius;
51695
51696				vertices.push( 0, 0, 0 );
51697				vertices.push( x, 0, z );
51698
51699				const color = ( i & 1 ) ? color1 : color2;
51700
51701				colors.push( color.r, color.g, color.b );
51702				colors.push( color.r, color.g, color.b );
51703
51704			}
51705
51706		}
51707
51708		// create the rings
51709
51710		for ( let i = 0; i < rings; i ++ ) {
51711
51712			const color = ( i & 1 ) ? color1 : color2;
51713
51714			const r = radius - ( radius / rings * i );
51715
51716			for ( let j = 0; j < divisions; j ++ ) {
51717
51718				// first vertex
51719
51720				let v = ( j / divisions ) * ( Math.PI * 2 );
51721
51722				let x = Math.sin( v ) * r;
51723				let z = Math.cos( v ) * r;
51724
51725				vertices.push( x, 0, z );
51726				colors.push( color.r, color.g, color.b );
51727
51728				// second vertex
51729
51730				v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
51731
51732				x = Math.sin( v ) * r;
51733				z = Math.cos( v ) * r;
51734
51735				vertices.push( x, 0, z );
51736				colors.push( color.r, color.g, color.b );
51737
51738			}
51739
51740		}
51741
51742		const geometry = new BufferGeometry();
51743		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
51744		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
51745
51746		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
51747
51748		super( geometry, material );
51749
51750		this.type = 'PolarGridHelper';
51751
51752	}
51753
51754	dispose() {
51755
51756		this.geometry.dispose();
51757		this.material.dispose();
51758
51759	}
51760
51761}
51762
51763const _v1 = /*@__PURE__*/ new Vector3();
51764const _v2 = /*@__PURE__*/ new Vector3();
51765const _v3 = /*@__PURE__*/ new Vector3();
51766
51767class DirectionalLightHelper extends Object3D {
51768
51769	constructor( light, size, color ) {
51770
51771		super();
51772
51773		this.light = light;
51774
51775		this.matrix = light.matrixWorld;
51776		this.matrixAutoUpdate = false;
51777
51778		this.color = color;
51779
51780		this.type = 'DirectionalLightHelper';
51781
51782		if ( size === undefined ) size = 1;
51783
51784		let geometry = new BufferGeometry();
51785		geometry.setAttribute( 'position', new Float32BufferAttribute( [
51786			- size, size, 0,
51787			size, size, 0,
51788			size, - size, 0,
51789			- size, - size, 0,
51790			- size, size, 0
51791		], 3 ) );
51792
51793		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
51794
51795		this.lightPlane = new Line( geometry, material );
51796		this.add( this.lightPlane );
51797
51798		geometry = new BufferGeometry();
51799		geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
51800
51801		this.targetLine = new Line( geometry, material );
51802		this.add( this.targetLine );
51803
51804		this.update();
51805
51806	}
51807
51808	dispose() {
51809
51810		this.lightPlane.geometry.dispose();
51811		this.lightPlane.material.dispose();
51812		this.targetLine.geometry.dispose();
51813		this.targetLine.material.dispose();
51814
51815	}
51816
51817	update() {
51818
51819		this.light.updateWorldMatrix( true, false );
51820		this.light.target.updateWorldMatrix( true, false );
51821
51822		_v1.setFromMatrixPosition( this.light.matrixWorld );
51823		_v2.setFromMatrixPosition( this.light.target.matrixWorld );
51824		_v3.subVectors( _v2, _v1 );
51825
51826		this.lightPlane.lookAt( _v2 );
51827
51828		if ( this.color !== undefined ) {
51829
51830			this.lightPlane.material.color.set( this.color );
51831			this.targetLine.material.color.set( this.color );
51832
51833		} else {
51834
51835			this.lightPlane.material.color.copy( this.light.color );
51836			this.targetLine.material.color.copy( this.light.color );
51837
51838		}
51839
51840		this.targetLine.lookAt( _v2 );
51841		this.targetLine.scale.z = _v3.length();
51842
51843	}
51844
51845}
51846
51847const _vector = /*@__PURE__*/ new Vector3();
51848const _camera = /*@__PURE__*/ new Camera();
51849
51850/**
51851 *	- shows frustum, line of sight and up of the camera
51852 *	- suitable for fast updates
51853 * 	- based on frustum visualization in lightgl.js shadowmap example
51854 *		https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html
51855 */
51856
51857class CameraHelper extends LineSegments {
51858
51859	constructor( camera ) {
51860
51861		const geometry = new BufferGeometry();
51862		const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
51863
51864		const vertices = [];
51865		const colors = [];
51866
51867		const pointMap = {};
51868
51869		// near
51870
51871		addLine( 'n1', 'n2' );
51872		addLine( 'n2', 'n4' );
51873		addLine( 'n4', 'n3' );
51874		addLine( 'n3', 'n1' );
51875
51876		// far
51877
51878		addLine( 'f1', 'f2' );
51879		addLine( 'f2', 'f4' );
51880		addLine( 'f4', 'f3' );
51881		addLine( 'f3', 'f1' );
51882
51883		// sides
51884
51885		addLine( 'n1', 'f1' );
51886		addLine( 'n2', 'f2' );
51887		addLine( 'n3', 'f3' );
51888		addLine( 'n4', 'f4' );
51889
51890		// cone
51891
51892		addLine( 'p', 'n1' );
51893		addLine( 'p', 'n2' );
51894		addLine( 'p', 'n3' );
51895		addLine( 'p', 'n4' );
51896
51897		// up
51898
51899		addLine( 'u1', 'u2' );
51900		addLine( 'u2', 'u3' );
51901		addLine( 'u3', 'u1' );
51902
51903		// target
51904
51905		addLine( 'c', 't' );
51906		addLine( 'p', 'c' );
51907
51908		// cross
51909
51910		addLine( 'cn1', 'cn2' );
51911		addLine( 'cn3', 'cn4' );
51912
51913		addLine( 'cf1', 'cf2' );
51914		addLine( 'cf3', 'cf4' );
51915
51916		function addLine( a, b ) {
51917
51918			addPoint( a );
51919			addPoint( b );
51920
51921		}
51922
51923		function addPoint( id ) {
51924
51925			vertices.push( 0, 0, 0 );
51926			colors.push( 0, 0, 0 );
51927
51928			if ( pointMap[ id ] === undefined ) {
51929
51930				pointMap[ id ] = [];
51931
51932			}
51933
51934			pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
51935
51936		}
51937
51938		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
51939		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
51940
51941		super( geometry, material );
51942
51943		this.type = 'CameraHelper';
51944
51945		this.camera = camera;
51946		if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
51947
51948		this.matrix = camera.matrixWorld;
51949		this.matrixAutoUpdate = false;
51950
51951		this.pointMap = pointMap;
51952
51953		this.update();
51954
51955		// colors
51956
51957		const colorFrustum = new Color( 0xffaa00 );
51958		const colorCone = new Color( 0xff0000 );
51959		const colorUp = new Color( 0x00aaff );
51960		const colorTarget = new Color( 0xffffff );
51961		const colorCross = new Color( 0x333333 );
51962
51963		this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross );
51964
51965	}
51966
51967	setColors( frustum, cone, up, target, cross ) {
51968
51969		const geometry = this.geometry;
51970
51971		const colorAttribute = geometry.getAttribute( 'color' );
51972
51973		// near
51974
51975		colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2
51976		colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4
51977		colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3
51978		colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1
51979
51980		// far
51981
51982		colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2
51983		colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4
51984		colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3
51985		colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1
51986
51987		// sides
51988
51989		colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1
51990		colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2
51991		colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3
51992		colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4
51993
51994		// cone
51995
51996		colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1
51997		colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2
51998		colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3
51999		colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4
52000
52001		// up
52002
52003		colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2
52004		colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3
52005		colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1
52006
52007		// target
52008
52009		colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t
52010		colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c
52011
52012		// cross
52013
52014		colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2
52015		colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4
52016
52017		colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2
52018		colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4
52019
52020		colorAttribute.needsUpdate = true;
52021
52022	}
52023
52024	update() {
52025
52026		const geometry = this.geometry;
52027		const pointMap = this.pointMap;
52028
52029		const w = 1, h = 1;
52030
52031		// we need just camera projection matrix inverse
52032		// world matrix must be identity
52033
52034		_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
52035
52036		// center / target
52037
52038		setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
52039		setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
52040
52041		// near
52042
52043		setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
52044		setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
52045		setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
52046		setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
52047
52048		// far
52049
52050		setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
52051		setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
52052		setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
52053		setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
52054
52055		// up
52056
52057		setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
52058		setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
52059		setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
52060
52061		// cross
52062
52063		setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
52064		setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
52065		setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
52066		setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
52067
52068		setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
52069		setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
52070		setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
52071		setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
52072
52073		geometry.getAttribute( 'position' ).needsUpdate = true;
52074
52075	}
52076
52077	dispose() {
52078
52079		this.geometry.dispose();
52080		this.material.dispose();
52081
52082	}
52083
52084}
52085
52086
52087function setPoint( point, pointMap, geometry, camera, x, y, z ) {
52088
52089	_vector.set( x, y, z ).unproject( camera );
52090
52091	const points = pointMap[ point ];
52092
52093	if ( points !== undefined ) {
52094
52095		const position = geometry.getAttribute( 'position' );
52096
52097		for ( let i = 0, l = points.length; i < l; i ++ ) {
52098
52099			position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z );
52100
52101		}
52102
52103	}
52104
52105}
52106
52107const _box = /*@__PURE__*/ new Box3();
52108
52109class BoxHelper extends LineSegments {
52110
52111	constructor( object, color = 0xffff00 ) {
52112
52113		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 ] );
52114		const positions = new Float32Array( 8 * 3 );
52115
52116		const geometry = new BufferGeometry();
52117		geometry.setIndex( new BufferAttribute( indices, 1 ) );
52118		geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
52119
52120		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52121
52122		this.object = object;
52123		this.type = 'BoxHelper';
52124
52125		this.matrixAutoUpdate = false;
vendor: 4,705 bytes, lines 52126-52342
52126
52127		this.update();
52128
52129	}
52130
52131	update( object ) {
52132
52133		if ( object !== undefined ) {
52134
52135			console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
52136
52137		}
52138
52139		if ( this.object !== undefined ) {
52140
52141			_box.setFromObject( this.object );
52142
52143		}
52144
52145		if ( _box.isEmpty() ) return;
52146
52147		const min = _box.min;
52148		const max = _box.max;
52149
52150		/*
52151			5____4
52152		1/___0/|
52153		| 6__|_7
52154		2/___3/
52155
52156		0: max.x, max.y, max.z
52157		1: min.x, max.y, max.z
52158		2: min.x, min.y, max.z
52159		3: max.x, min.y, max.z
52160		4: max.x, max.y, min.z
52161		5: min.x, max.y, min.z
52162		6: min.x, min.y, min.z
52163		7: max.x, min.y, min.z
52164		*/
52165
52166		const position = this.geometry.attributes.position;
52167		const array = position.array;
52168
52169		array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
52170		array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
52171		array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
52172		array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
52173		array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
52174		array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
52175		array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
52176		array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
52177
52178		position.needsUpdate = true;
52179
52180		this.geometry.computeBoundingSphere();
52181
52182	}
52183
52184	setFromObject( object ) {
52185
52186		this.object = object;
52187		this.update();
52188
52189		return this;
52190
52191	}
52192
52193	copy( source, recursive ) {
52194
52195		super.copy( source, recursive );
52196
52197		this.object = source.object;
52198
52199		return this;
52200
52201	}
52202
52203	dispose() {
52204
52205		this.geometry.dispose();
52206		this.material.dispose();
52207
52208	}
52209
52210}
52211
52212class Box3Helper extends LineSegments {
52213
52214	constructor( box, color = 0xffff00 ) {
52215
52216		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 ] );
52217
52218		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 ];
52219
52220		const geometry = new BufferGeometry();
52221
52222		geometry.setIndex( new BufferAttribute( indices, 1 ) );
52223
52224		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52225
52226		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52227
52228		this.box = box;
52229
52230		this.type = 'Box3Helper';
52231
52232		this.geometry.computeBoundingSphere();
52233
52234	}
52235
52236	updateMatrixWorld( force ) {
52237
52238		const box = this.box;
52239
52240		if ( box.isEmpty() ) return;
52241
52242		box.getCenter( this.position );
52243
52244		box.getSize( this.scale );
52245
52246		this.scale.multiplyScalar( 0.5 );
52247
52248		super.updateMatrixWorld( force );
52249
52250	}
52251
52252	dispose() {
52253
52254		this.geometry.dispose();
52255		this.material.dispose();
52256
52257	}
52258
52259}
52260
52261class PlaneHelper extends Line {
52262
52263	constructor( plane, size = 1, hex = 0xffff00 ) {
52264
52265		const color = hex;
52266
52267		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 ];
52268
52269		const geometry = new BufferGeometry();
52270		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52271		geometry.computeBoundingSphere();
52272
52273		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52274
52275		this.type = 'PlaneHelper';
52276
52277		this.plane = plane;
52278
52279		this.size = size;
52280
52281		const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];
52282
52283		const geometry2 = new BufferGeometry();
52284		geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
52285		geometry2.computeBoundingSphere();
52286
52287		this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
52288
52289	}
52290
52291	updateMatrixWorld( force ) {
52292
52293		this.position.set( 0, 0, 0 );
52294
52295		this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 );
52296
52297		this.lookAt( this.plane.normal );
52298
52299		this.translateZ( - this.plane.constant );
52300
52301		super.updateMatrixWorld( force );
52302
52303	}
52304
52305	dispose() {
52306
52307		this.geometry.dispose();
52308		this.material.dispose();
52309		this.children[ 0 ].geometry.dispose();
52310		this.children[ 0 ].material.dispose();
52311
52312	}
52313
52314}
52315
52316const _axis = /*@__PURE__*/ new Vector3();
52317let _lineGeometry, _coneGeometry;
52318
52319class ArrowHelper extends Object3D {
52320
52321	// dir is assumed to be normalized
52322
52323	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 ) {
52324
52325		super();
52326
52327		this.type = 'ArrowHelper';
52328
52329		if ( _lineGeometry === undefined ) {
52330
52331			_lineGeometry = new BufferGeometry();
52332			_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
52333
52334			_coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 );
52335			_coneGeometry.translate( 0, - 0.5, 0 );
52336
52337		}
52338
52339		this.position.copy( origin );
52340
52341		this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52342		this.line.matrixAutoUpdate = false;
vendor: 3,957 bytes, lines 52343-52562
52343		this.add( this.line );
52344
52345		this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
52346		this.cone.matrixAutoUpdate = false;
52347		this.add( this.cone );
52348
52349		this.setDirection( dir );
52350		this.setLength( length, headLength, headWidth );
52351
52352	}
52353
52354	setDirection( dir ) {
52355
52356		// dir is assumed to be normalized
52357
52358		if ( dir.y > 0.99999 ) {
52359
52360			this.quaternion.set( 0, 0, 0, 1 );
52361
52362		} else if ( dir.y < - 0.99999 ) {
52363
52364			this.quaternion.set( 1, 0, 0, 0 );
52365
52366		} else {
52367
52368			_axis.set( dir.z, 0, - dir.x ).normalize();
52369
52370			const radians = Math.acos( dir.y );
52371
52372			this.quaternion.setFromAxisAngle( _axis, radians );
52373
52374		}
52375
52376	}
52377
52378	setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
52379
52380		this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
52381		this.line.updateMatrix();
52382
52383		this.cone.scale.set( headWidth, headLength, headWidth );
52384		this.cone.position.y = length;
52385		this.cone.updateMatrix();
52386
52387	}
52388
52389	setColor( color ) {
52390
52391		this.line.material.color.set( color );
52392		this.cone.material.color.set( color );
52393
52394	}
52395
52396	copy( source ) {
52397
52398		super.copy( source, false );
52399
52400		this.line.copy( source.line );
52401		this.cone.copy( source.cone );
52402
52403		return this;
52404
52405	}
52406
52407	dispose() {
52408
52409		this.line.geometry.dispose();
52410		this.line.material.dispose();
52411		this.cone.geometry.dispose();
52412		this.cone.material.dispose();
52413
52414	}
52415
52416}
52417
52418class AxesHelper extends LineSegments {
52419
52420	constructor( size = 1 ) {
52421
52422		const vertices = [
52423			0, 0, 0,	size, 0, 0,
52424			0, 0, 0,	0, size, 0,
52425			0, 0, 0,	0, 0, size
52426		];
52427
52428		const colors = [
52429			1, 0, 0,	1, 0.6, 0,
52430			0, 1, 0,	0.6, 1, 0,
52431			0, 0, 1,	0, 0.6, 1
52432		];
52433
52434		const geometry = new BufferGeometry();
52435		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52436		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52437
52438		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
52439
52440		super( geometry, material );
52441
52442		this.type = 'AxesHelper';
52443
52444	}
52445
52446	setColors( xAxisColor, yAxisColor, zAxisColor ) {
52447
52448		const color = new Color();
52449		const array = this.geometry.attributes.color.array;
52450
52451		color.set( xAxisColor );
52452		color.toArray( array, 0 );
52453		color.toArray( array, 3 );
52454
52455		color.set( yAxisColor );
52456		color.toArray( array, 6 );
52457		color.toArray( array, 9 );
52458
52459		color.set( zAxisColor );
52460		color.toArray( array, 12 );
52461		color.toArray( array, 15 );
52462
52463		this.geometry.attributes.color.needsUpdate = true;
52464
52465		return this;
52466
52467	}
52468
52469	dispose() {
52470
52471		this.geometry.dispose();
52472		this.material.dispose();
52473
52474	}
52475
52476}
52477
52478class ShapePath {
52479
52480	constructor() {
52481
52482		this.type = 'ShapePath';
52483
52484		this.color = new Color();
52485
52486		this.subPaths = [];
52487		this.currentPath = null;
52488
52489	}
52490
52491	moveTo( x, y ) {
52492
52493		this.currentPath = new Path();
52494		this.subPaths.push( this.currentPath );
52495		this.currentPath.moveTo( x, y );
52496
52497		return this;
52498
52499	}
52500
52501	lineTo( x, y ) {
52502
52503		this.currentPath.lineTo( x, y );
52504
52505		return this;
52506
52507	}
52508
52509	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
52510
52511		this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
52512
52513		return this;
52514
52515	}
52516
52517	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
52518
52519		this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
52520
52521		return this;
52522
52523	}
52524
52525	splineThru( pts ) {
52526
52527		this.currentPath.splineThru( pts );
52528
52529		return this;
52530
52531	}
52532
52533	toShapes( isCCW ) {
52534
52535		function toShapesNoHoles( inSubpaths ) {
52536
52537			const shapes = [];
52538
52539			for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
52540
52541				const tmpPath = inSubpaths[ i ];
52542
52543				const tmpShape = new Shape();
52544				tmpShape.curves = tmpPath.curves;
52545
52546				shapes.push( tmpShape );
52547
52548			}
52549
52550			return shapes;
52551
52552		}
52553
52554		function isPointInsidePolygon( inPt, inPolygon ) {
52555
52556			const polyLen = inPolygon.length;
52557
52558			// inPt on polygon contour => immediate success    or
52559			// toggling of inside/outside at every single! intersection point of an edge
52560			//  with the horizontal line through inPt, left of inPt
52561			//  not counting lowerY endpoints of edges and whole edges on that line
52562			let inside = false;
52563			for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
52564
52565				let edgeLowPt = inPolygon[ p ];
52566				let edgeHighPt = inPolygon[ q ];
52567
52568				let edgeDx = edgeHighPt.x - edgeLowPt.x;
52569				let edgeDy = edgeHighPt.y - edgeLowPt.y;
52570
52571				if ( Math.abs( edgeDy ) > Number.EPSILON ) {
52572
52573					// not parallel
52574					if ( edgeDy < 0 ) {
52575
52576						edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
52577						edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
52578
52579					}
52580
52581					if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) 		continue;
52582
52583					if ( inPt.y === edgeLowPt.y ) {
52584
52585						if ( inPt.x === edgeLowPt.x )		return	true;		// inPt is on contour ?
52586						// continue;				// no intersection or edgeLowPt => doesn't count !!!
52587
52588					} else {
52589
52590						const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
52591						if ( perpEdge === 0 )				return	true;		// inPt is on contour ?
52592						if ( perpEdge < 0 ) 				continue;
52593						inside = ! inside;		// true intersection left of inPt
52594
52595					}
52596
52597				} else {
52598
52599					// parallel or collinear
52600					if ( inPt.y !== edgeLowPt.y ) 		continue;			// parallel
52601					// edge lies on the same horizontal line as inPt
52602					if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
52603						 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )		return	true;	// inPt: Point on contour !
52604					// continue;
52605
52606				}
52607
52608			}
52609
52610			return	inside;
52611
52612		}
52613
52614		const isClockWise = ShapeUtils.isClockWise;
52615
52616		const subPaths = this.subPaths;
52617		if ( subPaths.length === 0 ) return [];
52618
52619		let solid, tmpPath, tmpShape;
52620		const shapes = [];
52621
52622		if ( subPaths.length === 1 ) {
52623
52624			tmpPath = subPaths[ 0 ];
52625			tmpShape = new Shape();
52626			tmpShape.curves = tmpPath.curves;
52627			shapes.push( tmpShape );
52628			return shapes;
52629
52630		}
52631
52632		let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
52633		holesFirst = isCCW ? ! holesFirst : holesFirst;
52634
52635		// console.log("Holes first", holesFirst);
52636
52637		const betterShapeHoles = [];
52638		const newShapes = [];
52639		let newShapeHoles = [];
52640		let mainIdx = 0;
52641		let tmpPoints;
52642
52643		newShapes[ mainIdx ] = undefined;
52644		newShapeHoles[ mainIdx ] = [];
52645
52646		for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
52647
52648			tmpPath = subPaths[ i ];
52649			tmpPoints = tmpPath.getPoints();
52650			solid = isClockWise( tmpPoints );
52651			solid = isCCW ? ! solid : solid;
52652
52653			if ( solid ) {
52654
52655				if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )	mainIdx ++;
52656
52657				newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
52658				newShapes[ mainIdx ].s.curves = tmpPath.curves;
52659
52660				if ( holesFirst )	mainIdx ++;
52661				newShapeHoles[ mainIdx ] = [];
52662
52663				//console.log('cw', i);
52664
52665			} else {
52666
52667				newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
52668
52669				//console.log('ccw', i);
52670
52671			}
52672
52673		}
52674
52675		// only Holes? -> probably all Shapes with wrong orientation
52676		if ( ! newShapes[ 0 ] )	return	toShapesNoHoles( subPaths );
52677
52678
52679		if ( newShapes.length > 1 ) {
52680
52681			let ambiguous = false;
52682			let toChange = 0;
52683
52684			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
52685
52686				betterShapeHoles[ sIdx ] = [];
52687
52688			}
52689
52690			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
52691
52692				const sho = newShapeHoles[ sIdx ];
52693
52694				for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
52695
52696					const ho = sho[ hIdx ];
52697					let hole_unassigned = true;
52698
52699					for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
52700
52701						if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
52702
52703							if ( sIdx !== s2Idx )	toChange ++;
52704
52705							if ( hole_unassigned ) {
52706
52707								hole_unassigned = false;
52708								betterShapeHoles[ s2Idx ].push( ho );
52709
52710							} else {
52711
52712								ambiguous = true;
52713
52714							}
52715
52716						}
52717
52718					}
52719
52720					if ( hole_unassigned ) {
52721
52722						betterShapeHoles[ sIdx ].push( ho );
52723
52724					}
52725
52726				}
52727
52728			}
52729
52730			if ( toChange > 0 && ambiguous === false ) {
52731
52732				newShapeHoles = betterShapeHoles;
52733
52734			}
52735
52736		}
52737
52738		let tmpHoles;
52739
52740		for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
52741
52742			tmpShape = newShapes[ i ].s;
52743			shapes.push( tmpShape );
52744			tmpHoles = newShapeHoles[ i ];
52745
52746			for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
52747
52748				tmpShape.holes.push( tmpHoles[ j ].h );
52749
52750			}
52751
52752		}
52753
52754		//console.log("shape", shapes);
52755
52756		return shapes;
52757
52758	}
52759
52760}
52761
52762class WebGLMultipleRenderTargets extends WebGLRenderTarget { // @deprecated, r162
52763
52764	constructor( width = 1, height = 1, count = 1, options = {} ) {
52765
52766		console.warn( 'THREE.WebGLMultipleRenderTargets has been deprecated and will be removed in r172. Use THREE.WebGLRenderTarget and set the "count" parameter to enable MRT.' );
52767
52768		super( width, height, { ...options, count } );
52769
52770		this.isWebGLMultipleRenderTargets = true;
52771
52772	}
52773
52774	get texture() {
52775
52776		return this.textures;
52777
52778	}
52779
52780}
52781
52782if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
52783
52784	__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
52785		revision: REVISION,
52786	} } ) );
52787
52788}
52789
52790if ( typeof window !== 'undefined' ) {
52791
52792	if ( window.__THREE__ ) {
52793
52794		console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
52795
52796	} else {
52797
52798		window.__THREE__ = REVISION;
52799
52800	}
52801
52802}
52803
52804export { ACESFilmicToneMapping, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrowHelper, AttachedBindMode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BackSide, BasicDepthPacking, BasicShadowMap, BatchedMesh, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, ConstantAlphaFactor, ConstantColorFactor, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DepthFormat, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearDisplayP3ColorSpace, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, 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, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, Orthogra
52804phicCamera, P3Primaries, PCFShadowMap, PCFSoftShadowMap, PMREMGenerator, Path, PerspectiveCamera, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, 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, RGBFormat, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, Rec709Primaries, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RenderTarget, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, RingGeometry, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, Scene, ShaderChunk, ShaderLib, ShaderMaterial, ShadowMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SpotLight, SpotLightHelper, Sprite, SpriteMaterial, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TOUCH, TangentSpaceNormalMap, TetrahedronGeometry, Texture, TextureLoader, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, createCanvasElement };

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.