PageSourceSearch

https://rorybowcott.com/vendor/three/three.module.js

js rorybowcott.com collected 2026-10-07 03:25:45 UTC 1,284,652 bytes, 53,479 lines download raw bytes

1/**
2 * @license
3 * Copyright 2010-2024 Three.js Authors
4 * SPDX-License-Identifier: MIT
5 */
6const REVISION = '165';
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
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
1563function probeAsync( gl, sync, interval ) {
1564
1565	return new Promise( function ( resolve, reject ) {
1566
1567		function probe() {
1568
1569			switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) {
1570
1571				case gl.WAIT_FAILED:
1572					reject();
1573					break;
1574
1575				case gl.TIMEOUT_EXPIRED:
1576					setTimeout( probe, interval );
1577					break;
1578
1579				default:
1580					resolve();
1581
1582			}
1583
1584		}
1585
1586		setTimeout( probe, interval );
1587
1588	} );
1589
1590}
1591
1592/**
1593 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping
1594 * or clipping. Based on W3C specifications for sRGB and Display P3,
1595 * and ICC specifications for the D50 connection space. Values in/out
1596 * are _linear_ sRGB and _linear_ Display P3.
1597 *
1598 * Note that both sRGB and Display P3 use the sRGB transfer functions.
1599 *
1600 * Reference:
1601 * - http://www.russellcottrell.com/photo/matrixCalculator.htm
1602 */
1603
1604const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set(
1605	0.8224621, 0.177538, 0.0,
1606	0.0331941, 0.9668058, 0.0,
1607	0.0170827, 0.0723974, 0.9105199,
1608);
1609
1610const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set(
1611	1.2249401, - 0.2249404, 0.0,
1612	- 0.0420569, 1.0420571, 0.0,
1613	- 0.0196376, - 0.0786361, 1.0982735
1614);
1615
1616/**
1617 * Defines supported color spaces by transfer function and primaries,
1618 * and provides conversions to/from the Linear-sRGB reference space.
1619 */
1620const COLOR_SPACES = {
1621	[ LinearSRGBColorSpace ]: {
1622		transfer: LinearTransfer,
1623		primaries: Rec709Primaries,
1624		toReference: ( color ) => color,
1625		fromReference: ( color ) => color,
1626	},
1627	[ SRGBColorSpace ]: {
vendor: 8,719 bytes, lines 1628-2067
1628		transfer: SRGBTransfer,
1629		primaries: Rec709Primaries,
1630		toReference: ( color ) => color.convertSRGBToLinear(),
1631		fromReference: ( color ) => color.convertLinearToSRGB(),
1632	},
1633	[ LinearDisplayP3ColorSpace ]: {
1634		transfer: LinearTransfer,
1635		primaries: P3Primaries,
1636		toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
1637		fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ),
1638	},
1639	[ DisplayP3ColorSpace ]: {
1640		transfer: SRGBTransfer,
1641		primaries: P3Primaries,
1642		toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
1643		fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(),
1644	},
1645};
1646
1647const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] );
1648
1649const ColorManagement = {
1650
1651	enabled: true,
1652
1653	_workingColorSpace: LinearSRGBColorSpace,
1654
1655	get workingColorSpace() {
1656
1657		return this._workingColorSpace;
1658
1659	},
1660
1661	set workingColorSpace( colorSpace ) {
1662
1663		if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) {
1664
1665			throw new Error( `Unsupported working color space, "${ colorSpace }".` );
1666
1667		}
1668
1669		this._workingColorSpace = colorSpace;
1670
1671	},
1672
1673	convert: function ( color, sourceColorSpace, targetColorSpace ) {
1674
1675		if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) {
1676
1677			return color;
1678
1679		}
1680
1681		const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference;
1682		const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference;
1683
1684		return targetFromReference( sourceToReference( color ) );
1685
1686	},
1687
1688	fromWorkingColorSpace: function ( color, targetColorSpace ) {
1689
1690		return this.convert( color, this._workingColorSpace, targetColorSpace );
1691
1692	},
1693
1694	toWorkingColorSpace: function ( color, sourceColorSpace ) {
1695
1696		return this.convert( color, sourceColorSpace, this._workingColorSpace );
1697
1698	},
1699
1700	getPrimaries: function ( colorSpace ) {
1701
1702		return COLOR_SPACES[ colorSpace ].primaries;
1703
1704	},
1705
1706	getTransfer: function ( colorSpace ) {
1707
1708		if ( colorSpace === NoColorSpace ) return LinearTransfer;
1709
1710		return COLOR_SPACES[ colorSpace ].transfer;
1711
1712	},
1713
1714};
1715
1716
1717function SRGBToLinear( c ) {
1718
1719	return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
1720
1721}
1722
1723function LinearToSRGB( c ) {
1724
1725	return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
1726
1727}
1728
1729let _canvas;
1730
1731class ImageUtils {
1732
1733	static getDataURL( image ) {
1734
1735		if ( /^data:/i.test( image.src ) ) {
1736
1737			return image.src;
1738
1739		}
1740
1741		if ( typeof HTMLCanvasElement === 'undefined' ) {
1742
1743			return image.src;
1744
1745		}
1746
1747		let canvas;
1748
1749		if ( image instanceof HTMLCanvasElement ) {
1750
1751			canvas = image;
1752
1753		} else {
1754
1755			if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' );
1756
1757			_canvas.width = image.width;
1758			_canvas.height = image.height;
1759
1760			const context = _canvas.getContext( '2d' );
1761
1762			if ( image instanceof ImageData ) {
1763
1764				context.putImageData( image, 0, 0 );
1765
1766			} else {
1767
1768				context.drawImage( image, 0, 0, image.width, image.height );
1769
1770			}
1771
1772			canvas = _canvas;
1773
1774		}
1775
1776		if ( canvas.width > 2048 || canvas.height > 2048 ) {
1777
1778			console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image );
1779
1780			return canvas.toDataURL( 'image/jpeg', 0.6 );
1781
1782		} else {
1783
1784			return canvas.toDataURL( 'image/png' );
1785
1786		}
1787
1788	}
1789
1790	static sRGBToLinear( image ) {
1791
1792		if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
1793			( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
1794			( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
1795
1796			const canvas = createElementNS( 'canvas' );
1797
1798			canvas.width = image.width;
1799			canvas.height = image.height;
1800
1801			const context = canvas.getContext( '2d' );
1802			context.drawImage( image, 0, 0, image.width, image.height );
1803
1804			const imageData = context.getImageData( 0, 0, image.width, image.height );
1805			const data = imageData.data;
1806
1807			for ( let i = 0; i < data.length; i ++ ) {
1808
1809				data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;
1810
1811			}
1812
1813			context.putImageData( imageData, 0, 0 );
1814
1815			return canvas;
1816
1817		} else if ( image.data ) {
1818
1819			const data = image.data.slice( 0 );
1820
1821			for ( let i = 0; i < data.length; i ++ ) {
1822
1823				if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {
1824
1825					data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );
1826
1827				} else {
1828
1829					// assuming float
1830
1831					data[ i ] = SRGBToLinear( data[ i ] );
1832
1833				}
1834
1835			}
1836
1837			return {
1838				data: data,
1839				width: image.width,
1840				height: image.height
1841			};
1842
1843		} else {
1844
1845			console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
1846			return image;
1847
1848		}
1849
1850	}
1851
1852}
1853
1854let _sourceId = 0;
1855
1856class Source {
1857
1858	constructor( data = null ) {
1859
1860		this.isSource = true;
1861
1862		Object.defineProperty( this, 'id', { value: _sourceId ++ } );
1863
1864		this.uuid = generateUUID();
1865
1866		this.data = data;
1867		this.dataReady = true;
1868
1869		this.version = 0;
1870
1871	}
1872
1873	set needsUpdate( value ) {
1874
1875		if ( value === true ) this.version ++;
1876
1877	}
1878
1879	toJSON( meta ) {
1880
1881		const isRootObject = ( meta === undefined || typeof meta === 'string' );
1882
1883		if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) {
1884
1885			return meta.images[ this.uuid ];
1886
1887		}
1888
1889		const output = {
1890			uuid: this.uuid,
1891			url: ''
1892		};
1893
1894		const data = this.data;
1895
1896		if ( data !== null ) {
1897
1898			let url;
1899
1900			if ( Array.isArray( data ) ) {
1901
1902				// cube texture
1903
1904				url = [];
1905
1906				for ( let i = 0, l = data.length; i < l; i ++ ) {
1907
1908					if ( data[ i ].isDataTexture ) {
1909
1910						url.push( serializeImage( data[ i ].image ) );
1911
1912					} else {
1913
1914						url.push( serializeImage( data[ i ] ) );
1915
1916					}
1917
1918				}
1919
1920			} else {
1921
1922				// texture
1923
1924				url = serializeImage( data );
1925
1926			}
1927
1928			output.url = url;
1929
1930		}
1931
1932		if ( ! isRootObject ) {
1933
1934			meta.images[ this.uuid ] = output;
1935
1936		}
1937
1938		return output;
1939
1940	}
1941
1942}
1943
1944function serializeImage( image ) {
1945
1946	if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
1947		( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
1948		( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
1949
1950		// default images
1951
1952		return ImageUtils.getDataURL( image );
1953
1954	} else {
1955
1956		if ( image.data ) {
1957
1958			// images of DataTexture
1959
1960			return {
1961				data: Array.from( image.data ),
1962				width: image.width,
1963				height: image.height,
1964				type: image.data.constructor.name
1965			};
1966
1967		} else {
1968
1969			console.warn( 'THREE.Texture: Unable to serialize Texture.' );
1970			return {};
1971
1972		}
1973
1974	}
1975
1976}
1977
1978let _textureId = 0;
1979
1980class Texture extends EventDispatcher {
1981
1982	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 ) {
1983
1984		super();
1985
1986		this.isTexture = true;
1987
1988		Object.defineProperty( this, 'id', { value: _textureId ++ } );
1989
1990		this.uuid = generateUUID();
1991
1992		this.name = '';
1993
1994		this.source = new Source( image );
1995		this.mipmaps = [];
1996
1997		this.mapping = mapping;
1998		this.channel = 0;
1999
2000		this.wrapS = wrapS;
2001		this.wrapT = wrapT;
2002
2003		this.magFilter = magFilter;
2004		this.minFilter = minFilter;
2005
2006		this.anisotropy = anisotropy;
2007
2008		this.format = format;
2009		this.internalFormat = null;
2010		this.type = type;
2011
2012		this.offset = new Vector2( 0, 0 );
2013		this.repeat = new Vector2( 1, 1 );
2014		this.center = new Vector2( 0, 0 );
2015		this.rotation = 0;
2016
2017		this.matrixAutoUpdate = true;
2018		this.matrix = new Matrix3();
2019
2020		this.generateMipmaps = true;
2021		this.premultiplyAlpha = false;
2022		this.flipY = true;
2023		this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
2024
2025		this.colorSpace = colorSpace;
2026
2027		this.userData = {};
2028
2029		this.version = 0;
2030		this.onUpdate = null;
2031
2032		this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not
2033		this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures)
2034
2035	}
2036
2037	get image() {
2038
2039		return this.source.data;
2040
2041	}
2042
2043	set image( value = null ) {
2044
2045		this.source.data = value;
2046
2047	}
2048
2049	updateMatrix() {
2050
2051		this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
2052
2053	}
2054
2055	clone() {
2056
2057		return new this.constructor().copy( this );
2058
2059	}
2060
2061	copy( source ) {
2062
2063		this.name = source.name;
2064
2065		this.source = source.source;
2066		this.mipmaps = source.mipmaps.slice( 0 );
2067
vendor: 3,428 bytes, lines 2068-2268
2068		this.mapping = source.mapping;
2069		this.channel = source.channel;
2070
2071		this.wrapS = source.wrapS;
2072		this.wrapT = source.wrapT;
2073
2074		this.magFilter = source.magFilter;
2075		this.minFilter = source.minFilter;
2076
2077		this.anisotropy = source.anisotropy;
2078
2079		this.format = source.format;
2080		this.internalFormat = source.internalFormat;
2081		this.type = source.type;
2082
2083		this.offset.copy( source.offset );
2084		this.repeat.copy( source.repeat );
2085		this.center.copy( source.center );
2086		this.rotation = source.rotation;
2087
2088		this.matrixAutoUpdate = source.matrixAutoUpdate;
2089		this.matrix.copy( source.matrix );
2090
2091		this.generateMipmaps = source.generateMipmaps;
2092		this.premultiplyAlpha = source.premultiplyAlpha;
2093		this.flipY = source.flipY;
2094		this.unpackAlignment = source.unpackAlignment;
2095		this.colorSpace = source.colorSpace;
2096
2097		this.userData = JSON.parse( JSON.stringify( source.userData ) );
2098
2099		this.needsUpdate = true;
2100
2101		return this;
2102
2103	}
2104
2105	toJSON( meta ) {
2106
2107		const isRootObject = ( meta === undefined || typeof meta === 'string' );
2108
2109		if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
2110
2111			return meta.textures[ this.uuid ];
2112
2113		}
2114
2115		const output = {
2116
2117			metadata: {
2118				version: 4.6,
2119				type: 'Texture',
2120				generator: 'Texture.toJSON'
2121			},
2122
2123			uuid: this.uuid,
2124			name: this.name,
2125
2126			image: this.source.toJSON( meta ).uuid,
2127
2128			mapping: this.mapping,
2129			channel: this.channel,
2130
2131			repeat: [ this.repeat.x, this.repeat.y ],
2132			offset: [ this.offset.x, this.offset.y ],
2133			center: [ this.center.x, this.center.y ],
2134			rotation: this.rotation,
2135
2136			wrap: [ this.wrapS, this.wrapT ],
2137
2138			format: this.format,
2139			internalFormat: this.internalFormat,
2140			type: this.type,
2141			colorSpace: this.colorSpace,
2142
2143			minFilter: this.minFilter,
2144			magFilter: this.magFilter,
2145			anisotropy: this.anisotropy,
2146
2147			flipY: this.flipY,
2148
2149			generateMipmaps: this.generateMipmaps,
2150			premultiplyAlpha: this.premultiplyAlpha,
2151			unpackAlignment: this.unpackAlignment
2152
2153		};
2154
2155		if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData;
2156
2157		if ( ! isRootObject ) {
2158
2159			meta.textures[ this.uuid ] = output;
2160
2161		}
2162
2163		return output;
2164
2165	}
2166
2167	dispose() {
2168
2169		this.dispatchEvent( { type: 'dispose' } );
2170
2171	}
2172
2173	transformUv( uv ) {
2174
2175		if ( this.mapping !== UVMapping ) return uv;
2176
2177		uv.applyMatrix3( this.matrix );
2178
2179		if ( uv.x < 0 || uv.x > 1 ) {
2180
2181			switch ( this.wrapS ) {
2182
2183				case RepeatWrapping:
2184
2185					uv.x = uv.x - Math.floor( uv.x );
2186					break;
2187
2188				case ClampToEdgeWrapping:
2189
2190					uv.x = uv.x < 0 ? 0 : 1;
2191					break;
2192
2193				case MirroredRepeatWrapping:
2194
2195					if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
2196
2197						uv.x = Math.ceil( uv.x ) - uv.x;
2198
2199					} else {
2200
2201						uv.x = uv.x - Math.floor( uv.x );
2202
2203					}
2204
2205					break;
2206
2207			}
2208
2209		}
2210
2211		if ( uv.y < 0 || uv.y > 1 ) {
2212
2213			switch ( this.wrapT ) {
2214
2215				case RepeatWrapping:
2216
2217					uv.y = uv.y - Math.floor( uv.y );
2218					break;
2219
2220				case ClampToEdgeWrapping:
2221
2222					uv.y = uv.y < 0 ? 0 : 1;
2223					break;
2224
2225				case MirroredRepeatWrapping:
2226
2227					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
2228
2229						uv.y = Math.ceil( uv.y ) - uv.y;
2230
2231					} else {
2232
2233						uv.y = uv.y - Math.floor( uv.y );
2234
2235					}
2236
2237					break;
2238
2239			}
2240
2241		}
2242
2243		if ( this.flipY ) {
2244
2245			uv.y = 1 - uv.y;
2246
2247		}
2248
2249		return uv;
2250
2251	}
2252
2253	set needsUpdate( value ) {
2254
2255		if ( value === true ) {
2256
2257			this.version ++;
2258			this.source.needsUpdate = true;
2259
2260		}
2261
2262	}
2263
2264	set needsPMREMUpdate( value ) {
2265
2266		if ( value === true ) {
2267
2268			this.pmremVersion ++
vendor: 10,919 bytes, lines 2268-2953
2268;
2269
2270		}
2271
2272	}
2273
2274}
2275
2276Texture.DEFAULT_IMAGE = null;
2277Texture.DEFAULT_MAPPING = UVMapping;
2278Texture.DEFAULT_ANISOTROPY = 1;
2279
2280class Vector4 {
2281
2282	constructor( x = 0, y = 0, z = 0, w = 1 ) {
2283
2284		Vector4.prototype.isVector4 = true;
2285
2286		this.x = x;
2287		this.y = y;
2288		this.z = z;
2289		this.w = w;
2290
2291	}
2292
2293	get width() {
2294
2295		return this.z;
2296
2297	}
2298
2299	set width( value ) {
2300
2301		this.z = value;
2302
2303	}
2304
2305	get height() {
2306
2307		return this.w;
2308
2309	}
2310
2311	set height( value ) {
2312
2313		this.w = value;
2314
2315	}
2316
2317	set( x, y, z, w ) {
2318
2319		this.x = x;
2320		this.y = y;
2321		this.z = z;
2322		this.w = w;
2323
2324		return this;
2325
2326	}
2327
2328	setScalar( scalar ) {
2329
2330		this.x = scalar;
2331		this.y = scalar;
2332		this.z = scalar;
2333		this.w = scalar;
2334
2335		return this;
2336
2337	}
2338
2339	setX( x ) {
2340
2341		this.x = x;
2342
2343		return this;
2344
2345	}
2346
2347	setY( y ) {
2348
2349		this.y = y;
2350
2351		return this;
2352
2353	}
2354
2355	setZ( z ) {
2356
2357		this.z = z;
2358
2359		return this;
2360
2361	}
2362
2363	setW( w ) {
2364
2365		this.w = w;
2366
2367		return this;
2368
2369	}
2370
2371	setComponent( index, value ) {
2372
2373		switch ( index ) {
2374
2375			case 0: this.x = value; break;
2376			case 1: this.y = value; break;
2377			case 2: this.z = value; break;
2378			case 3: this.w = value; break;
2379			default: throw new Error( 'index is out of range: ' + index );
2380
2381		}
2382
2383		return this;
2384
2385	}
2386
2387	getComponent( index ) {
2388
2389		switch ( index ) {
2390
2391			case 0: return this.x;
2392			case 1: return this.y;
2393			case 2: return this.z;
2394			case 3: return this.w;
2395			default: throw new Error( 'index is out of range: ' + index );
2396
2397		}
2398
2399	}
2400
2401	clone() {
2402
2403		return new this.constructor( this.x, this.y, this.z, this.w );
2404
2405	}
2406
2407	copy( v ) {
2408
2409		this.x = v.x;
2410		this.y = v.y;
2411		this.z = v.z;
2412		this.w = ( v.w !== undefined ) ? v.w : 1;
2413
2414		return this;
2415
2416	}
2417
2418	add( v ) {
2419
2420		this.x += v.x;
2421		this.y += v.y;
2422		this.z += v.z;
2423		this.w += v.w;
2424
2425		return this;
2426
2427	}
2428
2429	addScalar( s ) {
2430
2431		this.x += s;
2432		this.y += s;
2433		this.z += s;
2434		this.w += s;
2435
2436		return this;
2437
2438	}
2439
2440	addVectors( a, b ) {
2441
2442		this.x = a.x + b.x;
2443		this.y = a.y + b.y;
2444		this.z = a.z + b.z;
2445		this.w = a.w + b.w;
2446
2447		return this;
2448
2449	}
2450
2451	addScaledVector( v, s ) {
2452
2453		this.x += v.x * s;
2454		this.y += v.y * s;
2455		this.z += v.z * s;
2456		this.w += v.w * s;
2457
2458		return this;
2459
2460	}
2461
2462	sub( v ) {
2463
2464		this.x -= v.x;
2465		this.y -= v.y;
2466		this.z -= v.z;
2467		this.w -= v.w;
2468
2469		return this;
2470
2471	}
2472
2473	subScalar( s ) {
2474
2475		this.x -= s;
2476		this.y -= s;
2477		this.z -= s;
2478		this.w -= s;
2479
2480		return this;
2481
2482	}
2483
2484	subVectors( a, b ) {
2485
2486		this.x = a.x - b.x;
2487		this.y = a.y - b.y;
2488		this.z = a.z - b.z;
2489		this.w = a.w - b.w;
2490
2491		return this;
2492
2493	}
2494
2495	multiply( v ) {
2496
2497		this.x *= v.x;
2498		this.y *= v.y;
2499		this.z *= v.z;
2500		this.w *= v.w;
2501
2502		return this;
2503
2504	}
2505
2506	multiplyScalar( scalar ) {
2507
2508		this.x *= scalar;
2509		this.y *= scalar;
2510		this.z *= scalar;
2511		this.w *= scalar;
2512
2513		return this;
2514
2515	}
2516
2517	applyMatrix4( m ) {
2518
2519		const x = this.x, y = this.y, z = this.z, w = this.w;
2520		const e = m.elements;
2521
2522		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
2523		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
2524		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
2525		this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
2526
2527		return this;
2528
2529	}
2530
2531	divideScalar( scalar ) {
2532
2533		return this.multiplyScalar( 1 / scalar );
2534
2535	}
2536
2537	setAxisAngleFromQuaternion( q ) {
2538
2539		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
2540
2541		// q is assumed to be normalized
2542
2543		this.w = 2 * Math.acos( q.w );
2544
2545		const s = Math.sqrt( 1 - q.w * q.w );
2546
2547		if ( s < 0.0001 ) {
2548
2549			this.x = 1;
2550			this.y = 0;
2551			this.z = 0;
2552
2553		} else {
2554
2555			this.x = q.x / s;
2556			this.y = q.y / s;
2557			this.z = q.z / s;
2558
2559		}
2560
2561		return this;
2562
2563	}
2564
2565	setAxisAngleFromRotationMatrix( m ) {
2566
2567		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2568
2569		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2570
2571		let angle, x, y, z; // variables for result
2572		const epsilon = 0.01,		// margin to allow for rounding errors
2573			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
2574
2575			te = m.elements,
2576
2577			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
2578			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
2579			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
2580
2581		if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
2582		     ( Math.abs( m13 - m31 ) < epsilon ) &&
2583		     ( Math.abs( m23 - m32 ) < epsilon ) ) {
2584
2585			// singularity found
2586			// first check for identity matrix which must have +1 for all terms
2587			// in leading diagonal and zero in other terms
2588
2589			if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
2590			     ( Math.abs( m13 + m31 ) < epsilon2 ) &&
2591			     ( Math.abs( m23 + m32 ) < epsilon2 ) &&
2592			     ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
2593
2594				// this singularity is identity matrix so angle = 0
2595
2596				this.set( 1, 0, 0, 0 );
2597
2598				return this; // zero angle, arbitrary axis
2599
2600			}
2601
2602			// otherwise this singularity is angle = 180
2603
2604			angle = Math.PI;
2605
2606			const xx = ( m11 + 1 ) / 2;
2607			const yy = ( m22 + 1 ) / 2;
2608			const zz = ( m33 + 1 ) / 2;
2609			const xy = ( m12 + m21 ) / 4;
2610			const xz = ( m13 + m31 ) / 4;
2611			const yz = ( m23 + m32 ) / 4;
2612
2613			if ( ( xx > yy ) && ( xx > zz ) ) {
2614
2615				// m11 is the largest diagonal term
2616
2617				if ( xx < epsilon ) {
2618
2619					x = 0;
2620					y = 0.707106781;
2621					z = 0.707106781;
2622
2623				} else {
2624
2625					x = Math.sqrt( xx );
2626					y = xy / x;
2627					z = xz / x;
2628
2629				}
2630
2631			} else if ( yy > zz ) {
2632
2633				// m22 is the largest diagonal term
2634
2635				if ( yy < epsilon ) {
2636
2637					x = 0.707106781;
2638					y = 0;
2639					z = 0.707106781;
2640
2641				} else {
2642
2643					y = Math.sqrt( yy );
2644					x = xy / y;
2645					z = yz / y;
2646
2647				}
2648
2649			} else {
2650
2651				// m33 is the largest diagonal term so base result on this
2652
2653				if ( zz < epsilon ) {
2654
2655					x = 0.707106781;
2656					y = 0.707106781;
2657					z = 0;
2658
2659				} else {
2660
2661					z = Math.sqrt( zz );
2662					x = xz / z;
2663					y = yz / z;
2664
2665				}
2666
2667			}
2668
2669			this.set( x, y, z, angle );
2670
2671			return this; // return 180 deg rotation
2672
2673		}
2674
2675		// as we have reached here there are no singularities so we can handle normally
2676
2677		let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
2678			( m13 - m31 ) * ( m13 - m31 ) +
2679			( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
2680
2681		if ( Math.abs( s ) < 0.001 ) s = 1;
2682
2683		// prevent divide by zero, should not happen if matrix is orthogonal and should be
2684		// caught by singularity test above, but I've left it in just in case
2685
2686		this.x = ( m32 - m23 ) / s;
2687		this.y = ( m13 - m31 ) / s;
2688		this.z = ( m21 - m12 ) / s;
2689		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
2690
2691		return this;
2692
2693	}
2694
2695	min( v ) {
2696
2697		this.x = Math.min( this.x, v.x );
2698		this.y = Math.min( this.y, v.y );
2699		this.z = Math.min( this.z, v.z );
2700		this.w = Math.min( this.w, v.w );
2701
2702		return this;
2703
2704	}
2705
2706	max( v ) {
2707
2708		this.x = Math.max( this.x, v.x );
2709		this.y = Math.max( this.y, v.y );
2710		this.z = Math.max( this.z, v.z );
2711		this.w = Math.max( this.w, v.w );
2712
2713		return this;
2714
2715	}
2716
2717	clamp( min, max ) {
2718
2719		// assumes min < max, componentwise
2720
2721		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
2722		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
2723		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
2724		this.w = Math.max( min.w, Math.min( max.w, this.w ) );
2725
2726		return this;
2727
2728	}
2729
2730	clampScalar( minVal, maxVal ) {
2731
2732		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
2733		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
2734		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
2735		this.w = Math.max( minVal, Math.min( maxVal, this.w ) );
2736
2737		return this;
2738
2739	}
2740
2741	clampLength( min, max ) {
2742
2743		const length = this.length();
2744
2745		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
2746
2747	}
2748
2749	floor() {
2750
2751		this.x = Math.floor( this.x );
2752		this.y = Math.floor( this.y );
2753		this.z = Math.floor( this.z );
2754		this.w = Math.floor( this.w );
2755
2756		return this;
2757
2758	}
2759
2760	ceil() {
2761
2762		this.x = Math.ceil( this.x );
2763		this.y = Math.ceil( this.y );
2764		this.z = Math.ceil( this.z );
2765		this.w = Math.ceil( this.w );
2766
2767		return this;
2768
2769	}
2770
2771	round() {
2772
2773		this.x = Math.round( this.x );
2774		this.y = Math.round( this.y );
2775		this.z = Math.round( this.z );
2776		this.w = Math.round( this.w );
2777
2778		return this;
2779
2780	}
2781
2782	roundToZero() {
2783
2784		this.x = Math.trunc( this.x );
2785		this.y = Math.trunc( this.y );
2786		this.z = Math.trunc( this.z );
2787		this.w = Math.trunc( this.w );
2788
2789		return this;
2790
2791	}
2792
2793	negate() {
2794
2795		this.x = - this.x;
2796		this.y = - this.y;
2797		this.z = - this.z;
2798		this.w = - this.w;
2799
2800		return this;
2801
2802	}
2803
2804	dot( v ) {
2805
2806		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
2807
2808	}
2809
2810	lengthSq() {
2811
2812		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
2813
2814	}
2815
2816	length() {
2817
2818		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
2819
2820	}
2821
2822	manhattanLength() {
2823
2824		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
2825
2826	}
2827
2828	normalize() {
2829
2830		return this.divideScalar( this.length() || 1 );
2831
2832	}
2833
2834	setLength( length ) {
2835
2836		return this.normalize().multiplyScalar( length );
2837
2838	}
2839
2840	lerp( v, alpha ) {
2841
2842		this.x += ( v.x - this.x ) * alpha;
2843		this.y += ( v.y - this.y ) * alpha;
2844		this.z += ( v.z - this.z ) * alpha;
2845		this.w += ( v.w - this.w ) * alpha;
2846
2847		return this;
2848
2849	}
2850
2851	lerpVectors( v1, v2, alpha ) {
2852
2853		this.x = v1.x + ( v2.x - v1.x ) * alpha;
2854		this.y = v1.y + ( v2.y - v1.y ) * alpha;
2855		this.z = v1.z + ( v2.z - v1.z ) * alpha;
2856		this.w = v1.w + ( v2.w - v1.w ) * alpha;
2857
2858		return this;
2859
2860	}
2861
2862	equals( v ) {
2863
2864		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
2865
2866	}
2867
2868	fromArray( array, offset = 0 ) {
2869
2870		this.x = array[ offset ];
2871		this.y = array[ offset + 1 ];
2872		this.z = array[ offset + 2 ];
2873		this.w = array[ offset + 3 ];
2874
2875		return this;
2876
2877	}
2878
2879	toArray( array = [], offset = 0 ) {
2880
2881		array[ offset ] = this.x;
2882		array[ offset + 1 ] = this.y;
2883		array[ offset + 2 ] = this.z;
2884		array[ offset + 3 ] = this.w;
2885
2886		return array;
2887
2888	}
2889
2890	fromBufferAttribute( attribute, index ) {
2891
2892		this.x = attribute.getX( index );
2893		this.y = attribute.getY( index );
2894		this.z = attribute.getZ( index );
2895		this.w = attribute.getW( index );
2896
2897		return this;
2898
2899	}
2900
2901	random() {
2902
2903		this.x = Math.random();
2904		this.y = Math.random();
2905		this.z = Math.random();
2906		this.w = Math.random();
2907
2908		return this;
2909
2910	}
2911
2912	*[ Symbol.iterator ]() {
2913
2914		yield this.x;
2915		yield this.y;
2916		yield this.z;
2917		yield this.w;
2918
2919	}
2920
2921}
2922
2923/*
2924 In options, we can specify:
2925 * Texture parameters for an auto-generated target texture
2926 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
2927*/
2928class RenderTarget extends EventDispatcher {
2929
2930	constructor( width = 1, height = 1, options = {} ) {
2931
2932		super();
2933
2934		this.isRenderTarget = true;
2935
2936		this.width = width;
2937		this.height = height;
2938		this.depth = 1;
2939
2940		this.scissor = new Vector4( 0, 0, width, height );
2941		this.scissorTest = false;
2942
2943		this.viewport = new Vector4( 0, 0, width, height );
2944
2945		const image = { width: width, height: height, depth: 1 };
2946
2947		options = Object.assign( {
2948			generateMipmaps: false,
2949			internalFormat: null,
2950			minFilter: LinearFilter,
2951			depthBuffer: true,
2952			stencilBuffer: false,
2953			
vendor: 25,148 bytes, lines 2953-4406
2953resolveDepthBuffer: true,
2954			resolveStencilBuffer: true,
2955			depthTexture: null,
2956			samples: 0,
2957			count: 1
2958		}, options );
2959
2960		const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
2961
2962		texture.flipY = false;
2963		texture.generateMipmaps = options.generateMipmaps;
2964		texture.internalFormat = options.internalFormat;
2965
2966		this.textures = [];
2967
2968		const count = options.count;
2969		for ( let i = 0; i < count; i ++ ) {
2970
2971			this.textures[ i ] = texture.clone();
2972			this.textures[ i ].isRenderTargetTexture = true;
2973
2974		}
2975
2976		this.depthBuffer = options.depthBuffer;
2977		this.stencilBuffer = options.stencilBuffer;
2978
2979		this.resolveDepthBuffer = options.resolveDepthBuffer;
2980		this.resolveStencilBuffer = options.resolveStencilBuffer;
2981
2982		this.depthTexture = options.depthTexture;
2983
2984		this.samples = options.samples;
2985
2986	}
2987
2988	get texture() {
2989
2990		return this.textures[ 0 ];
2991
2992	}
2993
2994	set texture( value ) {
2995
2996		this.textures[ 0 ] = value;
2997
2998	}
2999
3000	setSize( width, height, depth = 1 ) {
3001
3002		if ( this.width !== width || this.height !== height || this.depth !== depth ) {
3003
3004			this.width = width;
3005			this.height = height;
3006			this.depth = depth;
3007
3008			for ( let i = 0, il = this.textures.length; i < il; i ++ ) {
3009
3010				this.textures[ i ].image.width = width;
3011				this.textures[ i ].image.height = height;
3012				this.textures[ i ].image.depth = depth;
3013
3014			}
3015
3016			this.dispose();
3017
3018		}
3019
3020		this.viewport.set( 0, 0, width, height );
3021		this.scissor.set( 0, 0, width, height );
3022
3023	}
3024
3025	clone() {
3026
3027		return new this.constructor().copy( this );
3028
3029	}
3030
3031	copy( source ) {
3032
3033		this.width = source.width;
3034		this.height = source.height;
3035		this.depth = source.depth;
3036
3037		this.scissor.copy( source.scissor );
3038		this.scissorTest = source.scissorTest;
3039
3040		this.viewport.copy( source.viewport );
3041
3042		this.textures.length = 0;
3043
3044		for ( let i = 0, il = source.textures.length; i < il; i ++ ) {
3045
3046			this.textures[ i ] = source.textures[ i ].clone();
3047			this.textures[ i ].isRenderTargetTexture = true;
3048
3049		}
3050
3051		// ensure image object is not shared, see #20328
3052
3053		const image = Object.assign( {}, source.texture.image );
3054		this.texture.source = new Source( image );
3055
3056		this.depthBuffer = source.depthBuffer;
3057		this.stencilBuffer = source.stencilBuffer;
3058
3059		this.resolveDepthBuffer = source.resolveDepthBuffer;
3060		this.resolveStencilBuffer = source.resolveStencilBuffer;
3061
3062		if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
3063
3064		this.samples = source.samples;
3065
3066		return this;
3067
3068	}
3069
3070	dispose() {
3071
3072		this.dispatchEvent( { type: 'dispose' } );
3073
3074	}
3075
3076}
3077
3078class WebGLRenderTarget extends RenderTarget {
3079
3080	constructor( width = 1, height = 1, options = {} ) {
3081
3082		super( width, height, options );
3083
3084		this.isWebGLRenderTarget = true;
3085
3086	}
3087
3088}
3089
3090class DataArrayTexture extends Texture {
3091
3092	constructor( data = null, width = 1, height = 1, depth = 1 ) {
3093
3094		super( null );
3095
3096		this.isDataArrayTexture = true;
3097
3098		this.image = { data, width, height, depth };
3099
3100		this.magFilter = NearestFilter;
3101		this.minFilter = NearestFilter;
3102
3103		this.wrapR = ClampToEdgeWrapping;
3104
3105		this.generateMipmaps = false;
3106		this.flipY = false;
3107		this.unpackAlignment = 1;
3108
3109		this.layerUpdates = new Set();
3110
3111	}
3112
3113	addLayerUpdate( layerIndex ) {
3114
3115		this.layerUpdates.add( layerIndex );
3116
3117	}
3118
3119	clearLayerUpdates() {
3120
3121		this.layerUpdates.clear();
3122
3123	}
3124
3125}
3126
3127class WebGLArrayRenderTarget extends WebGLRenderTarget {
3128
3129	constructor( width = 1, height = 1, depth = 1, options = {} ) {
3130
3131		super( width, height, options );
3132
3133		this.isWebGLArrayRenderTarget = true;
3134
3135		this.depth = depth;
3136
3137		this.texture = new DataArrayTexture( null, width, height, depth );
3138
3139		this.texture.isRenderTargetTexture = true;
3140
3141	}
3142
3143}
3144
3145class Data3DTexture extends Texture {
3146
3147	constructor( data = null, width = 1, height = 1, depth = 1 ) {
3148
3149		// We're going to add .setXXX() methods for setting properties later.
3150		// Users can still set in DataTexture3D directly.
3151		//
3152		//	const texture = new THREE.DataTexture3D( data, width, height, depth );
3153		// 	texture.anisotropy = 16;
3154		//
3155		// See #14839
3156
3157		super( null );
3158
3159		this.isData3DTexture = true;
3160
3161		this.image = { data, width, height, depth };
3162
3163		this.magFilter = NearestFilter;
3164		this.minFilter = NearestFilter;
3165
3166		this.wrapR = ClampToEdgeWrapping;
3167
3168		this.generateMipmaps = false;
3169		this.flipY = false;
3170		this.unpackAlignment = 1;
3171
3172	}
3173
3174}
3175
3176class WebGL3DRenderTarget extends WebGLRenderTarget {
3177
3178	constructor( width = 1, height = 1, depth = 1, options = {} ) {
3179
3180		super( width, height, options );
3181
3182		this.isWebGL3DRenderTarget = true;
3183
3184		this.depth = depth;
3185
3186		this.texture = new Data3DTexture( null, width, height, depth );
3187
3188		this.texture.isRenderTargetTexture = true;
3189
3190	}
3191
3192}
3193
3194class Quaternion {
3195
3196	constructor( x = 0, y = 0, z = 0, w = 1 ) {
3197
3198		this.isQuaternion = true;
3199
3200		this._x = x;
3201		this._y = y;
3202		this._z = z;
3203		this._w = w;
3204
3205	}
3206
3207	static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
3208
3209		// fuzz-free, array-based Quaternion SLERP operation
3210
3211		let x0 = src0[ srcOffset0 + 0 ],
3212			y0 = src0[ srcOffset0 + 1 ],
3213			z0 = src0[ srcOffset0 + 2 ],
3214			w0 = src0[ srcOffset0 + 3 ];
3215
3216		const x1 = src1[ srcOffset1 + 0 ],
3217			y1 = src1[ srcOffset1 + 1 ],
3218			z1 = src1[ srcOffset1 + 2 ],
3219			w1 = src1[ srcOffset1 + 3 ];
3220
3221		if ( t === 0 ) {
3222
3223			dst[ dstOffset + 0 ] = x0;
3224			dst[ dstOffset + 1 ] = y0;
3225			dst[ dstOffset + 2 ] = z0;
3226			dst[ dstOffset + 3 ] = w0;
3227			return;
3228
3229		}
3230
3231		if ( t === 1 ) {
3232
3233			dst[ dstOffset + 0 ] = x1;
3234			dst[ dstOffset + 1 ] = y1;
3235			dst[ dstOffset + 2 ] = z1;
3236			dst[ dstOffset + 3 ] = w1;
3237			return;
3238
3239		}
3240
3241		if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
3242
3243			let s = 1 - t;
3244			const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
3245				dir = ( cos >= 0 ? 1 : - 1 ),
3246				sqrSin = 1 - cos * cos;
3247
3248			// Skip the Slerp for tiny steps to avoid numeric problems:
3249			if ( sqrSin > Number.EPSILON ) {
3250
3251				const sin = Math.sqrt( sqrSin ),
3252					len = Math.atan2( sin, cos * dir );
3253
3254				s = Math.sin( s * len ) / sin;
3255				t = Math.sin( t * len ) / sin;
3256
3257			}
3258
3259			const tDir = t * dir;
3260
3261			x0 = x0 * s + x1 * tDir;
3262			y0 = y0 * s + y1 * tDir;
3263			z0 = z0 * s + z1 * tDir;
3264			w0 = w0 * s + w1 * tDir;
3265
3266			// Normalize in case we just did a lerp:
3267			if ( s === 1 - t ) {
3268
3269				const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
3270
3271				x0 *= f;
3272				y0 *= f;
3273				z0 *= f;
3274				w0 *= f;
3275
3276			}
3277
3278		}
3279
3280		dst[ dstOffset ] = x0;
3281		dst[ dstOffset + 1 ] = y0;
3282		dst[ dstOffset + 2 ] = z0;
3283		dst[ dstOffset + 3 ] = w0;
3284
3285	}
3286
3287	static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
3288
3289		const x0 = src0[ srcOffset0 ];
3290		const y0 = src0[ srcOffset0 + 1 ];
3291		const z0 = src0[ srcOffset0 + 2 ];
3292		const w0 = src0[ srcOffset0 + 3 ];
3293
3294		const x1 = src1[ srcOffset1 ];
3295		const y1 = src1[ srcOffset1 + 1 ];
3296		const z1 = src1[ srcOffset1 + 2 ];
3297		const w1 = src1[ srcOffset1 + 3 ];
3298
3299		dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
3300		dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
3301		dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
3302		dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
3303
3304		return dst;
3305
3306	}
3307
3308	get x() {
3309
3310		return this._x;
3311
3312	}
3313
3314	set x( value ) {
3315
3316		this._x = value;
3317		this._onChangeCallback();
3318
3319	}
3320
3321	get y() {
3322
3323		return this._y;
3324
3325	}
3326
3327	set y( value ) {
3328
3329		this._y = value;
3330		this._onChangeCallback();
3331
3332	}
3333
3334	get z() {
3335
3336		return this._z;
3337
3338	}
3339
3340	set z( value ) {
3341
3342		this._z = value;
3343		this._onChangeCallback();
3344
3345	}
3346
3347	get w() {
3348
3349		return this._w;
3350
3351	}
3352
3353	set w( value ) {
3354
3355		this._w = value;
3356		this._onChangeCallback();
3357
3358	}
3359
3360	set( x, y, z, w ) {
3361
3362		this._x = x;
3363		this._y = y;
3364		this._z = z;
3365		this._w = w;
3366
3367		this._onChangeCallback();
3368
3369		return this;
3370
3371	}
3372
3373	clone() {
3374
3375		return new this.constructor( this._x, this._y, this._z, this._w );
3376
3377	}
3378
3379	copy( quaternion ) {
3380
3381		this._x = quaternion.x;
3382		this._y = quaternion.y;
3383		this._z = quaternion.z;
3384		this._w = quaternion.w;
3385
3386		this._onChangeCallback();
3387
3388		return this;
3389
3390	}
3391
3392	setFromEuler( euler, update = true ) {
3393
3394		const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
3395
3396		// http://www.mathworks.com/matlabcentral/fileexchange/
3397		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
3398		//	content/SpinCalc.m
3399
3400		const cos = Math.cos;
3401		const sin = Math.sin;
3402
3403		const c1 = cos( x / 2 );
3404		const c2 = cos( y / 2 );
3405		const c3 = cos( z / 2 );
3406
3407		const s1 = sin( x / 2 );
3408		const s2 = sin( y / 2 );
3409		const s3 = sin( z / 2 );
3410
3411		switch ( order ) {
3412
3413			case 'XYZ':
3414				this._x = s1 * c2 * c3 + c1 * s2 * s3;
3415				this._y = c1 * s2 * c3 - s1 * c2 * s3;
3416				this._z = c1 * c2 * s3 + s1 * s2 * c3;
3417				this._w = c1 * c2 * c3 - s1 * s2 * s3;
3418				break;
3419
3420			case 'YXZ':
3421				this._x = s1 * c2 * c3 + c1 * s2 * s3;
3422				this._y = c1 * s2 * c3 - s1 * c2 * s3;
3423				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3424				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3425				break;
3426
3427			case 'ZXY':
3428				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3429				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3430				this._z = c1 * c2 * s3 + s1 * s2 * c3;
3431				this._w = c1 * c2 * c3 - s1 * s2 * s3;
3432				break;
3433
3434			case 'ZYX':
3435				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3436				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3437				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3438				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3439				break;
3440
3441			case 'YZX':
3442				this._x = s1 * c2 * c3 + c1 * s2 * s3;
3443				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3444				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3445				this._w = c1 * c2 * c3 - s1 * s2 * s3;
3446				break;
3447
3448			case 'XZY':
3449				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3450				this._y = c1 * s2 * c3 - s1 * c2 * s3;
3451				this._z = c1 * c2 * s3 + s1 * s2 * c3;
3452				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3453				break;
3454
3455			default:
3456				console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
3457
3458		}
3459
3460		if ( update === true ) this._onChangeCallback();
3461
3462		return this;
3463
3464	}
3465
3466	setFromAxisAngle( axis, angle ) {
3467
3468		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
3469
3470		// assumes axis is normalized
3471
3472		const halfAngle = angle / 2, s = Math.sin( halfAngle );
3473
3474		this._x = axis.x * s;
3475		this._y = axis.y * s;
3476		this._z = axis.z * s;
3477		this._w = Math.cos( halfAngle );
3478
3479		this._onChangeCallback();
3480
3481		return this;
3482
3483	}
3484
3485	setFromRotationMatrix( m ) {
3486
3487		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
3488
3489		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
3490
3491		const te = m.elements,
3492
3493			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
3494			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
3495			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
3496
3497			trace = m11 + m22 + m33;
3498
3499		if ( trace > 0 ) {
3500
3501			const s = 0.5 / Math.sqrt( trace + 1.0 );
3502
3503			this._w = 0.25 / s;
3504			this._x = ( m32 - m23 ) * s;
3505			this._y = ( m13 - m31 ) * s;
3506			this._z = ( m21 - m12 ) * s;
3507
3508		} else if ( m11 > m22 && m11 > m33 ) {
3509
3510			const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
3511
3512			this._w = ( m32 - m23 ) / s;
3513			this._x = 0.25 * s;
3514			this._y = ( m12 + m21 ) / s;
3515			this._z = ( m13 + m31 ) / s;
3516
3517		} else if ( m22 > m33 ) {
3518
3519			const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
3520
3521			this._w = ( m13 - m31 ) / s;
3522			this._x = ( m12 + m21 ) / s;
3523			this._y = 0.25 * s;
3524			this._z = ( m23 + m32 ) / s;
3525
3526		} else {
3527
3528			const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
3529
3530			this._w = ( m21 - m12 ) / s;
3531			this._x = ( m13 + m31 ) / s;
3532			this._y = ( m23 + m32 ) / s;
3533			this._z = 0.25 * s;
3534
3535		}
3536
3537		this._onChangeCallback();
3538
3539		return this;
3540
3541	}
3542
3543	setFromUnitVectors( vFrom, vTo ) {
3544
3545		// assumes direction vectors vFrom and vTo are normalized
3546
3547		let r = vFrom.dot( vTo ) + 1;
3548
3549		if ( r < Number.EPSILON ) {
3550
3551			// vFrom and vTo point in opposite directions
3552
3553			r = 0;
3554
3555			if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
3556
3557				this._x = - vFrom.y;
3558				this._y = vFrom.x;
3559				this._z = 0;
3560				this._w = r;
3561
3562			} else {
3563
3564				this._x = 0;
3565				this._y = - vFrom.z;
3566				this._z = vFrom.y;
3567				this._w = r;
3568
3569			}
3570
3571		} else {
3572
3573			// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
3574
3575			this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
3576			this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
3577			this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
3578			this._w = r;
3579
3580		}
3581
3582		return this.normalize();
3583
3584	}
3585
3586	angleTo( q ) {
3587
3588		return 2 * Math.acos( Math.abs( clamp( this.dot( q ), - 1, 1 ) ) );
3589
3590	}
3591
3592	rotateTowards( q, step ) {
3593
3594		const angle = this.angleTo( q );
3595
3596		if ( angle === 0 ) return this;
3597
3598		const t = Math.min( 1, step / angle );
3599
3600		this.slerp( q, t );
3601
3602		return this;
3603
3604	}
3605
3606	identity() {
3607
3608		return this.set( 0, 0, 0, 1 );
3609
3610	}
3611
3612	invert() {
3613
3614		// quaternion is assumed to have unit length
3615
3616		return this.conjugate();
3617
3618	}
3619
3620	conjugate() {
3621
3622		this._x *= - 1;
3623		this._y *= - 1;
3624		this._z *= - 1;
3625
3626		this._onChangeCallback();
3627
3628		return this;
3629
3630	}
3631
3632	dot( v ) {
3633
3634		return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
3635
3636	}
3637
3638	lengthSq() {
3639
3640		return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
3641
3642	}
3643
3644	length() {
3645
3646		return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
3647
3648	}
3649
3650	normalize() {
3651
3652		let l = this.length();
3653
3654		if ( l === 0 ) {
3655
3656			this._x = 0;
3657			this._y = 0;
3658			this._z = 0;
3659			this._w = 1;
3660
3661		} else {
3662
3663			l = 1 / l;
3664
3665			this._x = this._x * l;
3666			this._y = this._y * l;
3667			this._z = this._z * l;
3668			this._w = this._w * l;
3669
3670		}
3671
3672		this._onChangeCallback();
3673
3674		return this;
3675
3676	}
3677
3678	multiply( q ) {
3679
3680		return this.multiplyQuaternions( this, q );
3681
3682	}
3683
3684	premultiply( q ) {
3685
3686		return this.multiplyQuaternions( q, this );
3687
3688	}
3689
3690	multiplyQuaternions( a, b ) {
3691
3692		// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
3693
3694		const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
3695		const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
3696
3697		this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
3698		this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
3699		this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
3700		this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
3701
3702		this._onChangeCallback();
3703
3704		return this;
3705
3706	}
3707
3708	slerp( qb, t ) {
3709
3710		if ( t === 0 ) return this;
3711		if ( t === 1 ) return this.copy( qb );
3712
3713		const x = this._x, y = this._y, z = this._z, w = this._w;
3714
3715		// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
3716
3717		let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
3718
3719		if ( cosHalfTheta < 0 ) {
3720
3721			this._w = - qb._w;
3722			this._x = - qb._x;
3723			this._y = - qb._y;
3724			this._z = - qb._z;
3725
3726			cosHalfTheta = - cosHalfTheta;
3727
3728		} else {
3729
3730			this.copy( qb );
3731
3732		}
3733
3734		if ( cosHalfTheta >= 1.0 ) {
3735
3736			this._w = w;
3737			this._x = x;
3738			this._y = y;
3739			this._z = z;
3740
3741			return this;
3742
3743		}
3744
3745		const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
3746
3747		if ( sqrSinHalfTheta <= Number.EPSILON ) {
3748
3749			const s = 1 - t;
3750			this._w = s * w + t * this._w;
3751			this._x = s * x + t * this._x;
3752			this._y = s * y + t * this._y;
3753			this._z = s * z + t * this._z;
3754
3755			this.normalize(); // normalize calls _onChangeCallback()
3756
3757			return this;
3758
3759		}
3760
3761		const sinHalfTheta = Math.sqrt( sqrSinHalfTheta );
3762		const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
3763		const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
3764			ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
3765
3766		this._w = ( w * ratioA + this._w * ratioB );
3767		this._x = ( x * ratioA + this._x * ratioB );
3768		this._y = ( y * ratioA + this._y * ratioB );
3769		this._z = ( z * ratioA + this._z * ratioB );
3770
3771		this._onChangeCallback();
3772
3773		return this;
3774
3775	}
3776
3777	slerpQuaternions( qa, qb, t ) {
3778
3779		return this.copy( qa ).slerp( qb, t );
3780
3781	}
3782
3783	random() {
3784
3785		// sets this quaternion to a uniform random unit quaternnion
3786
3787		// Ken Shoemake
3788		// Uniform random rotations
3789		// D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992.
3790
3791		const theta1 = 2 * Math.PI * Math.random();
3792		const theta2 = 2 * Math.PI * Math.random();
3793
3794		const x0 = Math.random();
3795		const r1 = Math.sqrt( 1 - x0 );
3796		const r2 = Math.sqrt( x0 );
3797
3798		return this.set(
3799			r1 * Math.sin( theta1 ),
3800			r1 * Math.cos( theta1 ),
3801			r2 * Math.sin( theta2 ),
3802			r2 * Math.cos( theta2 ),
3803		);
3804
3805	}
3806
3807	equals( quaternion ) {
3808
3809		return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
3810
3811	}
3812
3813	fromArray( array, offset = 0 ) {
3814
3815		this._x = array[ offset ];
3816		this._y = array[ offset + 1 ];
3817		this._z = array[ offset + 2 ];
3818		this._w = array[ offset + 3 ];
3819
3820		this._onChangeCallback();
3821
3822		return this;
3823
3824	}
3825
3826	toArray( array = [], offset = 0 ) {
3827
3828		array[ offset ] = this._x;
3829		array[ offset + 1 ] = this._y;
3830		array[ offset + 2 ] = this._z;
3831		array[ offset + 3 ] = this._w;
3832
3833		return array;
3834
3835	}
3836
3837	fromBufferAttribute( attribute, index ) {
3838
3839		this._x = attribute.getX( index );
3840		this._y = attribute.getY( index );
3841		this._z = attribute.getZ( index );
3842		this._w = attribute.getW( index );
3843
3844		this._onChangeCallback();
3845
3846		return this;
3847
3848	}
3849
3850	toJSON() {
3851
3852		return this.toArray();
3853
3854	}
3855
3856	_onChange( callback ) {
3857
3858		this._onChangeCallback = callback;
3859
3860		return this;
3861
3862	}
3863
3864	_onChangeCallback() {}
3865
3866	*[ Symbol.iterator ]() {
3867
3868		yield this._x;
3869		yield this._y;
3870		yield this._z;
3871		yield this._w;
3872
3873	}
3874
3875}
3876
3877class Vector3 {
3878
3879	constructor( x = 0, y = 0, z = 0 ) {
3880
3881		Vector3.prototype.isVector3 = true;
3882
3883		this.x = x;
3884		this.y = y;
3885		this.z = z;
3886
3887	}
3888
3889	set( x, y, z ) {
3890
3891		if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
3892
3893		this.x = x;
3894		this.y = y;
3895		this.z = z;
3896
3897		return this;
3898
3899	}
3900
3901	setScalar( scalar ) {
3902
3903		this.x = scalar;
3904		this.y = scalar;
3905		this.z = scalar;
3906
3907		return this;
3908
3909	}
3910
3911	setX( x ) {
3912
3913		this.x = x;
3914
3915		return this;
3916
3917	}
3918
3919	setY( y ) {
3920
3921		this.y = y;
3922
3923		return this;
3924
3925	}
3926
3927	setZ( z ) {
3928
3929		this.z = z;
3930
3931		return this;
3932
3933	}
3934
3935	setComponent( index, value ) {
3936
3937		switch ( index ) {
3938
3939			case 0: this.x = value; break;
3940			case 1: this.y = value; break;
3941			case 2: this.z = value; break;
3942			default: throw new Error( 'index is out of range: ' + index );
3943
3944		}
3945
3946		return this;
3947
3948	}
3949
3950	getComponent( index ) {
3951
3952		switch ( index ) {
3953
3954			case 0: return this.x;
3955			case 1: return this.y;
3956			case 2: return this.z;
3957			default: throw new Error( 'index is out of range: ' + index );
3958
3959		}
3960
3961	}
3962
3963	clone() {
3964
3965		return new this.constructor( this.x, this.y, this.z );
3966
3967	}
3968
3969	copy( v ) {
3970
3971		this.x = v.x;
3972		this.y = v.y;
3973		this.z = v.z;
3974
3975		return this;
3976
3977	}
3978
3979	add( v ) {
3980
3981		this.x += v.x;
3982		this.y += v.y;
3983		this.z += v.z;
3984
3985		return this;
3986
3987	}
3988
3989	addScalar( s ) {
3990
3991		this.x += s;
3992		this.y += s;
3993		this.z += s;
3994
3995		return this;
3996
3997	}
3998
3999	addVectors( a, b ) {
4000
4001		this.x = a.x + b.x;
4002		this.y = a.y + b.y;
4003		this.z = a.z + b.z;
4004
4005		return this;
4006
4007	}
4008
4009	addScaledVector( v, s ) {
4010
4011		this.x += v.x * s;
4012		this.y += v.y * s;
4013		this.z += v.z * s;
4014
4015		return this;
4016
4017	}
4018
4019	sub( v ) {
4020
4021		this.x -= v.x;
4022		this.y -= v.y;
4023		this.z -= v.z;
4024
4025		return this;
4026
4027	}
4028
4029	subScalar( s ) {
4030
4031		this.x -= s;
4032		this.y -= s;
4033		this.z -= s;
4034
4035		return this;
4036
4037	}
4038
4039	subVectors( a, b ) {
4040
4041		this.x = a.x - b.x;
4042		this.y = a.y - b.y;
4043		this.z = a.z - b.z;
4044
4045		return this;
4046
4047	}
4048
4049	multiply( v ) {
4050
4051		this.x *= v.x;
4052		this.y *= v.y;
4053		this.z *= v.z;
4054
4055		return this;
4056
4057	}
4058
4059	multiplyScalar( scalar ) {
4060
4061		this.x *= scalar;
4062		this.y *= scalar;
4063		this.z *= scalar;
4064
4065		return this;
4066
4067	}
4068
4069	multiplyVectors( a, b ) {
4070
4071		this.x = a.x * b.x;
4072		this.y = a.y * b.y;
4073		this.z = a.z * b.z;
4074
4075		return this;
4076
4077	}
4078
4079	applyEuler( euler ) {
4080
4081		return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) );
4082
4083	}
4084
4085	applyAxisAngle( axis, angle ) {
4086
4087		return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) );
4088
4089	}
4090
4091	applyMatrix3( m ) {
4092
4093		const x = this.x, y = this.y, z = this.z;
4094		const e = m.elements;
4095
4096		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
4097		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
4098		this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
4099
4100		return this;
4101
4102	}
4103
4104	applyNormalMatrix( m ) {
4105
4106		return this.applyMatrix3( m ).normalize();
4107
4108	}
4109
4110	applyMatrix4( m ) {
4111
4112		const x = this.x, y = this.y, z = this.z;
4113		const e = m.elements;
4114
4115		const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
4116
4117		this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
4118		this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
4119		this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
4120
4121		return this;
4122
4123	}
4124
4125	applyQuaternion( q ) {
4126
4127		// quaternion q is assumed to have unit length
4128
4129		const vx = this.x, vy = this.y, vz = this.z;
4130		const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
4131
4132		// t = 2 * cross( q.xyz, v );
4133		const tx = 2 * ( qy * vz - qz * vy );
4134		const ty = 2 * ( qz * vx - qx * vz );
4135		const tz = 2 * ( qx * vy - qy * vx );
4136
4137		// v + q.w * t + cross( q.xyz, t );
4138		this.x = vx + qw * tx + qy * tz - qz * ty;
4139		this.y = vy + qw * ty + qz * tx - qx * tz;
4140		this.z = vz + qw * tz + qx * ty - qy * tx;
4141
4142		return this;
4143
4144	}
4145
4146	project( camera ) {
4147
4148		return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
4149
4150	}
4151
4152	unproject( camera ) {
4153
4154		return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
4155
4156	}
4157
4158	transformDirection( m ) {
4159
4160		// input: THREE.Matrix4 affine matrix
4161		// vector interpreted as a direction
4162
4163		const x = this.x, y = this.y, z = this.z;
4164		const e = m.elements;
4165
4166		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
4167		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
4168		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
4169
4170		return this.normalize();
4171
4172	}
4173
4174	divide( v ) {
4175
4176		this.x /= v.x;
4177		this.y /= v.y;
4178		this.z /= v.z;
4179
4180		return this;
4181
4182	}
4183
4184	divideScalar( scalar ) {
4185
4186		return this.multiplyScalar( 1 / scalar );
4187
4188	}
4189
4190	min( v ) {
4191
4192		this.x = Math.min( this.x, v.x );
4193		this.y = Math.min( this.y, v.y );
4194		this.z = Math.min( this.z, v.z );
4195
4196		return this;
4197
4198	}
4199
4200	max( v ) {
4201
4202		this.x = Math.max( this.x, v.x );
4203		this.y = Math.max( this.y, v.y );
4204		this.z = Math.max( this.z, v.z );
4205
4206		return this;
4207
4208	}
4209
4210	clamp( min, max ) {
4211
4212		// assumes min < max, componentwise
4213
4214		this.x = Math.max( min.x, Math.min( max.x, this.x ) );
4215		this.y = Math.max( min.y, Math.min( max.y, this.y ) );
4216		this.z = Math.max( min.z, Math.min( max.z, this.z ) );
4217
4218		return this;
4219
4220	}
4221
4222	clampScalar( minVal, maxVal ) {
4223
4224		this.x = Math.max( minVal, Math.min( maxVal, this.x ) );
4225		this.y = Math.max( minVal, Math.min( maxVal, this.y ) );
4226		this.z = Math.max( minVal, Math.min( maxVal, this.z ) );
4227
4228		return this;
4229
4230	}
4231
4232	clampLength( min, max ) {
4233
4234		const length = this.length();
4235
4236		return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );
4237
4238	}
4239
4240	floor() {
4241
4242		this.x = Math.floor( this.x );
4243		this.y = Math.floor( this.y );
4244		this.z = Math.floor( this.z );
4245
4246		return this;
4247
4248	}
4249
4250	ceil() {
4251
4252		this.x = Math.ceil( this.x );
4253		this.y = Math.ceil( this.y );
4254		this.z = Math.ceil( this.z );
4255
4256		return this;
4257
4258	}
4259
4260	round() {
4261
4262		this.x = Math.round( this.x );
4263		this.y = Math.round( this.y );
4264		this.z = Math.round( this.z );
4265
4266		return this;
4267
4268	}
4269
4270	roundToZero() {
4271
4272		this.x = Math.trunc( this.x );
4273		this.y = Math.trunc( this.y );
4274		this.z = Math.trunc( this.z );
4275
4276		return this;
4277
4278	}
4279
4280	negate() {
4281
4282		this.x = - this.x;
4283		this.y = - this.y;
4284		this.z = - this.z;
4285
4286		return this;
4287
4288	}
4289
4290	dot( v ) {
4291
4292		return this.x * v.x + this.y * v.y + this.z * v.z;
4293
4294	}
4295
4296	// TODO lengthSquared?
4297
4298	lengthSq() {
4299
4300		return this.x * this.x + this.y * this.y + this.z * this.z;
4301
4302	}
4303
4304	length() {
4305
4306		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
4307
4308	}
4309
4310	manhattanLength() {
4311
4312		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
4313
4314	}
4315
4316	normalize() {
4317
4318		return this.divideScalar( this.length() || 1 );
4319
4320	}
4321
4322	setLength( length ) {
4323
4324		return this.normalize().multiplyScalar( length );
4325
4326	}
4327
4328	lerp( v, alpha ) {
4329
4330		this.x += ( v.x - this.x ) * alpha;
4331		this.y += ( v.y - this.y ) * alpha;
4332		this.z += ( v.z - this.z ) * alpha;
4333
4334		return this;
4335
4336	}
4337
4338	lerpVectors( v1, v2, alpha ) {
4339
4340		this.x = v1.x + ( v2.x - v1.x ) * alpha;
4341		this.y = v1.y + ( v2.y - v1.y ) * alpha;
4342		this.z = v1.z + ( v2.z - v1.z ) * alpha;
4343
4344		return this;
4345
4346	}
4347
4348	cross( v ) {
4349
4350		return this.crossVectors( this, v );
4351
4352	}
4353
4354	crossVectors( a, b ) {
4355
4356		const ax = a.x, ay = a.y, az = a.z;
4357		const bx = b.x, by = b.y, bz = b.z;
4358
4359		this.x = ay * bz - az * by;
4360		this.y = az * bx - ax * bz;
4361		this.z = ax * by - ay * bx;
4362
4363		return this;
4364
4365	}
4366
4367	projectOnVector( v ) {
4368
4369		const denominator = v.lengthSq();
4370
4371		if ( denominator === 0 ) return this.set( 0, 0, 0 );
4372
4373		const scalar = v.dot( this ) / denominator;
4374
4375		return this.copy( v ).multiplyScalar( scalar );
4376
4377	}
4378
4379	projectOnPlane( planeNormal ) {
4380
4381		_vector$c.copy( this ).projectOnVector( planeNormal );
4382
4383		return this.sub( _vector$c );
4384
4385	}
4386
4387	reflect( normal ) {
4388
4389		// reflect incident vector off plane orthogonal to normal
4390		// normal is assumed to have unit length
4391
4392		return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
4393
4394	}
4395
4396	angleTo( v ) {
4397
4398		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
4399
4400		if ( denominator === 0 ) return Math.PI / 2;
4401
4402		const theta = this.dot( v ) / denominator;
4403
4404		// clamp, to handle numerical problems
4405
4406		return Math.acos( clamp( theta, - 
vendor: 14,574 bytes, lines 4406-5134
44061, 1 ) );
4407
4408	}
4409
4410	distanceTo( v ) {
4411
4412		return Math.sqrt( this.distanceToSquared( v ) );
4413
4414	}
4415
4416	distanceToSquared( v ) {
4417
4418		const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
4419
4420		return dx * dx + dy * dy + dz * dz;
4421
4422	}
4423
4424	manhattanDistanceTo( v ) {
4425
4426		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
4427
4428	}
4429
4430	setFromSpherical( s ) {
4431
4432		return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
4433
4434	}
4435
4436	setFromSphericalCoords( radius, phi, theta ) {
4437
4438		const sinPhiRadius = Math.sin( phi ) * radius;
4439
4440		this.x = sinPhiRadius * Math.sin( theta );
4441		this.y = Math.cos( phi ) * radius;
4442		this.z = sinPhiRadius * Math.cos( theta );
4443
4444		return this;
4445
4446	}
4447
4448	setFromCylindrical( c ) {
4449
4450		return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
4451
4452	}
4453
4454	setFromCylindricalCoords( radius, theta, y ) {
4455
4456		this.x = radius * Math.sin( theta );
4457		this.y = y;
4458		this.z = radius * Math.cos( theta );
4459
4460		return this;
4461
4462	}
4463
4464	setFromMatrixPosition( m ) {
4465
4466		const e = m.elements;
4467
4468		this.x = e[ 12 ];
4469		this.y = e[ 13 ];
4470		this.z = e[ 14 ];
4471
4472		return this;
4473
4474	}
4475
4476	setFromMatrixScale( m ) {
4477
4478		const sx = this.setFromMatrixColumn( m, 0 ).length();
4479		const sy = this.setFromMatrixColumn( m, 1 ).length();
4480		const sz = this.setFromMatrixColumn( m, 2 ).length();
4481
4482		this.x = sx;
4483		this.y = sy;
4484		this.z = sz;
4485
4486		return this;
4487
4488	}
4489
4490	setFromMatrixColumn( m, index ) {
4491
4492		return this.fromArray( m.elements, index * 4 );
4493
4494	}
4495
4496	setFromMatrix3Column( m, index ) {
4497
4498		return this.fromArray( m.elements, index * 3 );
4499
4500	}
4501
4502	setFromEuler( e ) {
4503
4504		this.x = e._x;
4505		this.y = e._y;
4506		this.z = e._z;
4507
4508		return this;
4509
4510	}
4511
4512	setFromColor( c ) {
4513
4514		this.x = c.r;
4515		this.y = c.g;
4516		this.z = c.b;
4517
4518		return this;
4519
4520	}
4521
4522	equals( v ) {
4523
4524		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
4525
4526	}
4527
4528	fromArray( array, offset = 0 ) {
4529
4530		this.x = array[ offset ];
4531		this.y = array[ offset + 1 ];
4532		this.z = array[ offset + 2 ];
4533
4534		return this;
4535
4536	}
4537
4538	toArray( array = [], offset = 0 ) {
4539
4540		array[ offset ] = this.x;
4541		array[ offset + 1 ] = this.y;
4542		array[ offset + 2 ] = this.z;
4543
4544		return array;
4545
4546	}
4547
4548	fromBufferAttribute( attribute, index ) {
4549
4550		this.x = attribute.getX( index );
4551		this.y = attribute.getY( index );
4552		this.z = attribute.getZ( index );
4553
4554		return this;
4555
4556	}
4557
4558	random() {
4559
4560		this.x = Math.random();
4561		this.y = Math.random();
4562		this.z = Math.random();
4563
4564		return this;
4565
4566	}
4567
4568	randomDirection() {
4569
4570		// https://mathworld.wolfram.com/SpherePointPicking.html
4571
4572		const theta = Math.random() * Math.PI * 2;
4573		const u = Math.random() * 2 - 1;
4574		const c = Math.sqrt( 1 - u * u );
4575
4576		this.x = c * Math.cos( theta );
4577		this.y = u;
4578		this.z = c * Math.sin( theta );
4579
4580		return this;
4581
4582	}
4583
4584	*[ Symbol.iterator ]() {
4585
4586		yield this.x;
4587		yield this.y;
4588		yield this.z;
4589
4590	}
4591
4592}
4593
4594const _vector$c = /*@__PURE__*/ new Vector3();
4595const _quaternion$4 = /*@__PURE__*/ new Quaternion();
4596
4597class Box3 {
4598
4599	constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) {
4600
4601		this.isBox3 = true;
4602
4603		this.min = min;
4604		this.max = max;
4605
4606	}
4607
4608	set( min, max ) {
4609
4610		this.min.copy( min );
4611		this.max.copy( max );
4612
4613		return this;
4614
4615	}
4616
4617	setFromArray( array ) {
4618
4619		this.makeEmpty();
4620
4621		for ( let i = 0, il = array.length; i < il; i += 3 ) {
4622
4623			this.expandByPoint( _vector$b.fromArray( array, i ) );
4624
4625		}
4626
4627		return this;
4628
4629	}
4630
4631	setFromBufferAttribute( attribute ) {
4632
4633		this.makeEmpty();
4634
4635		for ( let i = 0, il = attribute.count; i < il; i ++ ) {
4636
4637			this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) );
4638
4639		}
4640
4641		return this;
4642
4643	}
4644
4645	setFromPoints( points ) {
4646
4647		this.makeEmpty();
4648
4649		for ( let i = 0, il = points.length; i < il; i ++ ) {
4650
4651			this.expandByPoint( points[ i ] );
4652
4653		}
4654
4655		return this;
4656
4657	}
4658
4659	setFromCenterAndSize( center, size ) {
4660
4661		const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 );
4662
4663		this.min.copy( center ).sub( halfSize );
4664		this.max.copy( center ).add( halfSize );
4665
4666		return this;
4667
4668	}
4669
4670	setFromObject( object, precise = false ) {
4671
4672		this.makeEmpty();
4673
4674		return this.expandByObject( object, precise );
4675
4676	}
4677
4678	clone() {
4679
4680		return new this.constructor().copy( this );
4681
4682	}
4683
4684	copy( box ) {
4685
4686		this.min.copy( box.min );
4687		this.max.copy( box.max );
4688
4689		return this;
4690
4691	}
4692
4693	makeEmpty() {
4694
4695		this.min.x = this.min.y = this.min.z = + Infinity;
4696		this.max.x = this.max.y = this.max.z = - Infinity;
4697
4698		return this;
4699
4700	}
4701
4702	isEmpty() {
4703
4704		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4705
4706		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
4707
4708	}
4709
4710	getCenter( target ) {
4711
4712		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
4713
4714	}
4715
4716	getSize( target ) {
4717
4718		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
4719
4720	}
4721
4722	expandByPoint( point ) {
4723
4724		this.min.min( point );
4725		this.max.max( point );
4726
4727		return this;
4728
4729	}
4730
4731	expandByVector( vector ) {
4732
4733		this.min.sub( vector );
4734		this.max.add( vector );
4735
4736		return this;
4737
4738	}
4739
4740	expandByScalar( scalar ) {
4741
4742		this.min.addScalar( - scalar );
4743		this.max.addScalar( scalar );
4744
4745		return this;
4746
4747	}
4748
4749	expandByObject( object, precise = false ) {
4750
4751		// Computes the world-axis-aligned bounding box of an object (including its children),
4752		// accounting for both the object's, and children's, world transforms
4753
4754		object.updateWorldMatrix( false, false );
4755
4756		const geometry = object.geometry;
4757
4758		if ( geometry !== undefined ) {
4759
4760			const positionAttribute = geometry.getAttribute( 'position' );
4761
4762			// precise AABB computation based on vertex data requires at least a position attribute.
4763			// instancing isn't supported so far and uses the normal (conservative) code path.
4764
4765			if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) {
4766
4767				for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
4768
4769					if ( object.isMesh === true ) {
4770
4771						object.getVertexPosition( i, _vector$b );
4772
4773					} else {
4774
4775						_vector$b.fromBufferAttribute( positionAttribute, i );
4776
4777					}
4778
4779					_vector$b.applyMatrix4( object.matrixWorld );
4780					this.expandByPoint( _vector$b );
4781
4782				}
4783
4784			} else {
4785
4786				if ( object.boundingBox !== undefined ) {
4787
4788					// object-level bounding box
4789
4790					if ( object.boundingBox === null ) {
4791
4792						object.computeBoundingBox();
4793
4794					}
4795
4796					_box$4.copy( object.boundingBox );
4797
4798
4799				} else {
4800
4801					// geometry-level bounding box
4802
4803					if ( geometry.boundingBox === null ) {
4804
4805						geometry.computeBoundingBox();
4806
4807					}
4808
4809					_box$4.copy( geometry.boundingBox );
4810
4811				}
4812
4813				_box$4.applyMatrix4( object.matrixWorld );
4814
4815				this.union( _box$4 );
4816
4817			}
4818
4819		}
4820
4821		const children = object.children;
4822
4823		for ( let i = 0, l = children.length; i < l; i ++ ) {
4824
4825			this.expandByObject( children[ i ], precise );
4826
4827		}
4828
4829		return this;
4830
4831	}
4832
4833	containsPoint( point ) {
4834
4835		return point.x < this.min.x || point.x > this.max.x ||
4836			point.y < this.min.y || point.y > this.max.y ||
4837			point.z < this.min.z || point.z > this.max.z ? false : true;
4838
4839	}
4840
4841	containsBox( box ) {
4842
4843		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4844			this.min.y <= box.min.y && box.max.y <= this.max.y &&
4845			this.min.z <= box.min.z && box.max.z <= this.max.z;
4846
4847	}
4848
4849	getParameter( point, target ) {
4850
4851		// This can potentially have a divide by zero if the box
4852		// has a size dimension of 0.
4853
4854		return target.set(
4855			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
4856			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
4857			( point.z - this.min.z ) / ( this.max.z - this.min.z )
4858		);
4859
4860	}
4861
4862	intersectsBox( box ) {
4863
4864		// using 6 splitting planes to rule out intersections.
4865		return box.max.x < this.min.x || box.min.x > this.max.x ||
4866			box.max.y < this.min.y || box.min.y > this.max.y ||
4867			box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
4868
4869	}
4870
4871	intersectsSphere( sphere ) {
4872
4873		// Find the point on the AABB closest to the sphere center.
4874		this.clampPoint( sphere.center, _vector$b );
4875
4876		// If that point is inside the sphere, the AABB and sphere intersect.
4877		return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
4878
4879	}
4880
4881	intersectsPlane( plane ) {
4882
4883		// We compute the minimum and maximum dot product values. If those values
4884		// are on the same side (back or front) of the plane, then there is no intersection.
4885
4886		let min, max;
4887
4888		if ( plane.normal.x > 0 ) {
4889
4890			min = plane.normal.x * this.min.x;
4891			max = plane.normal.x * this.max.x;
4892
4893		} else {
4894
4895			min = plane.normal.x * this.max.x;
4896			max = plane.normal.x * this.min.x;
4897
4898		}
4899
4900		if ( plane.normal.y > 0 ) {
4901
4902			min += plane.normal.y * this.min.y;
4903			max += plane.normal.y * this.max.y;
4904
4905		} else {
4906
4907			min += plane.normal.y * this.max.y;
4908			max += plane.normal.y * this.min.y;
4909
4910		}
4911
4912		if ( plane.normal.z > 0 ) {
4913
4914			min += plane.normal.z * this.min.z;
4915			max += plane.normal.z * this.max.z;
4916
4917		} else {
4918
4919			min += plane.normal.z * this.max.z;
4920			max += plane.normal.z * this.min.z;
4921
4922		}
4923
4924		return ( min <= - plane.constant && max >= - plane.constant );
4925
4926	}
4927
4928	intersectsTriangle( triangle ) {
4929
4930		if ( this.isEmpty() ) {
4931
4932			return false;
4933
4934		}
4935
4936		// compute box center and extents
4937		this.getCenter( _center );
4938		_extents.subVectors( this.max, _center );
4939
4940		// translate triangle to aabb origin
4941		_v0$2.subVectors( triangle.a, _center );
4942		_v1$7.subVectors( triangle.b, _center );
4943		_v2$4.subVectors( triangle.c, _center );
4944
4945		// compute edge vectors for triangle
4946		_f0.subVectors( _v1$7, _v0$2 );
4947		_f1.subVectors( _v2$4, _v1$7 );
4948		_f2.subVectors( _v0$2, _v2$4 );
4949
4950		// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
4951		// 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
4952		// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
4953		let axes = [
4954			0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
4955			_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
4956			- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
4957		];
4958		if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
4959
4960			return false;
4961
4962		}
4963
4964		// test 3 face normals from the aabb
4965		axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
4966		if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
4967
4968			return false;
4969
4970		}
4971
4972		// finally testing the face normal of the triangle
4973		// use already existing triangle edge vectors here
4974		_triangleNormal.crossVectors( _f0, _f1 );
4975		axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
4976
4977		return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents );
4978
4979	}
4980
4981	clampPoint( point, target ) {
4982
4983		return target.copy( point ).clamp( this.min, this.max );
4984
4985	}
4986
4987	distanceToPoint( point ) {
4988
4989		return this.clampPoint( point, _vector$b ).distanceTo( point );
4990
4991	}
4992
4993	getBoundingSphere( target ) {
4994
4995		if ( this.isEmpty() ) {
4996
4997			target.makeEmpty();
4998
4999		} else {
5000
5001			this.getCenter( target.center );
5002
5003			target.radius = this.getSize( _vector$b ).length() * 0.5;
5004
5005		}
5006
5007		return target;
5008
5009	}
5010
5011	intersect( box ) {
5012
5013		this.min.max( box.min );
5014		this.max.min( box.max );
5015
5016		// 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.
5017		if ( this.isEmpty() ) this.makeEmpty();
5018
5019		return this;
5020
5021	}
5022
5023	union( box ) {
5024
5025		this.min.min( box.min );
5026		this.max.max( box.max );
5027
5028		return this;
5029
5030	}
5031
5032	applyMatrix4( matrix ) {
5033
5034		// transform of empty box is an empty box.
5035		if ( this.isEmpty() ) return this;
5036
5037		// NOTE: I am using a binary pattern to specify all 2^3 combinations below
5038		_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
5039		_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
5040		_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
5041		_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
5042		_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
5043		_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
5044		_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
5045		_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
5046
5047		this.setFromPoints( _points );
5048
5049		return this;
5050
5051	}
5052
5053	translate( offset ) {
5054
5055		this.min.add( offset );
5056		this.max.add( offset );
5057
5058		return this;
5059
5060	}
5061
5062	equals( box ) {
5063
5064		return box.min.equals( this.min ) && box.max.equals( this.max );
5065
5066	}
5067
5068}
5069
5070const _points = [
5071	/*@__PURE__*/ new Vector3(),
5072	/*@__PURE__*/ new Vector3(),
5073	/*@__PURE__*/ new Vector3(),
5074	/*@__PURE__*/ new Vector3(),
5075	/*@__PURE__*/ new Vector3(),
5076	/*@__PURE__*/ new Vector3(),
5077	/*@__PURE__*/ new Vector3(),
5078	/*@__PURE__*/ new Vector3()
5079];
5080
5081const _vector$b = /*@__PURE__*/ new Vector3();
5082
5083const _box$4 = /*@__PURE__*/ new Box3();
5084
5085// triangle centered vertices
5086
5087const _v0$2 = /*@__PURE__*/ new Vector3();
5088const _v1$7 = /*@__PURE__*/ new Vector3();
5089const _v2$4 = /*@__PURE__*/ new Vector3();
5090
5091// triangle edge vectors
5092
5093const _f0 = /*@__PURE__*/ new Vector3();
5094const _f1 = /*@__PURE__*/ new Vector3();
5095const _f2 = /*@__PURE__*/ new Vector3();
5096
5097const _center = /*@__PURE__*/ new Vector3();
5098const _extents = /*@__PURE__*/ new Vector3();
5099const _triangleNormal = /*@__PURE__*/ new Vector3();
5100const _testAxis = /*@__PURE__*/ new Vector3();
5101
5102function satForAxes( axes, v0, v1, v2, extents ) {
5103
5104	for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
5105
5106		_testAxis.fromArray( axes, i );
5107		// project the aabb onto the separating axis
5108		const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
5109		// project all 3 vertices of the triangle onto the separating axis
5110		const p0 = v0.dot( _testAxis );
5111		const p1 = v1.dot( _testAxis );
5112		const p2 = v2.dot( _testAxis );
5113		// actual test, basically see if either of the most extreme of the triangle points intersects r
5114		if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
5115
5116			// points of the projected triangle are outside the projected half-length of the aabb
5117			// the axis is separating and we can exit
5118			return false;
5119
5120		}
5121
5122	}
5123
5124	return true;
5125
5126}
5127
5128const _box$3 = /*@__PURE__*/ new Box3();
5129const _v1$6 = /*@__PURE__*/ new Vector3();
5130const _v2$3 = /*@__PURE__*/ new Vector3();
5131
5132class Sphere {
5133
5134	constructor( center = new Vector3(), radius = -
vendor: 3,824 bytes, lines 5134-5380
5134 1 ) {
5135
5136		this.isSphere = true;
5137
5138		this.center = center;
5139		this.radius = radius;
5140
5141	}
5142
5143	set( center, radius ) {
5144
5145		this.center.copy( center );
5146		this.radius = radius;
5147
5148		return this;
5149
5150	}
5151
5152	setFromPoints( points, optionalCenter ) {
5153
5154		const center = this.center;
5155
5156		if ( optionalCenter !== undefined ) {
5157
5158			center.copy( optionalCenter );
5159
5160		} else {
5161
5162			_box$3.setFromPoints( points ).getCenter( center );
5163
5164		}
5165
5166		let maxRadiusSq = 0;
5167
5168		for ( let i = 0, il = points.length; i < il; i ++ ) {
5169
5170			maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
5171
5172		}
5173
5174		this.radius = Math.sqrt( maxRadiusSq );
5175
5176		return this;
5177
5178	}
5179
5180	copy( sphere ) {
5181
5182		this.center.copy( sphere.center );
5183		this.radius = sphere.radius;
5184
5185		return this;
5186
5187	}
5188
5189	isEmpty() {
5190
5191		return ( this.radius < 0 );
5192
5193	}
5194
5195	makeEmpty() {
5196
5197		this.center.set( 0, 0, 0 );
5198		this.radius = - 1;
5199
5200		return this;
5201
5202	}
5203
5204	containsPoint( point ) {
5205
5206		return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
5207
5208	}
5209
5210	distanceToPoint( point ) {
5211
5212		return ( point.distanceTo( this.center ) - this.radius );
5213
5214	}
5215
5216	intersectsSphere( sphere ) {
5217
5218		const radiusSum = this.radius + sphere.radius;
5219
5220		return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
5221
5222	}
5223
5224	intersectsBox( box ) {
5225
5226		return box.intersectsSphere( this );
5227
5228	}
5229
5230	intersectsPlane( plane ) {
5231
5232		return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
5233
5234	}
5235
5236	clampPoint( point, target ) {
5237
5238		const deltaLengthSq = this.center.distanceToSquared( point );
5239
5240		target.copy( point );
5241
5242		if ( deltaLengthSq > ( this.radius * this.radius ) ) {
5243
5244			target.sub( this.center ).normalize();
5245			target.multiplyScalar( this.radius ).add( this.center );
5246
5247		}
5248
5249		return target;
5250
5251	}
5252
5253	getBoundingBox( target ) {
5254
5255		if ( this.isEmpty() ) {
5256
5257			// Empty sphere produces empty bounding box
5258			target.makeEmpty();
5259			return target;
5260
5261		}
5262
5263		target.set( this.center, this.center );
5264		target.expandByScalar( this.radius );
5265
5266		return target;
5267
5268	}
5269
5270	applyMatrix4( matrix ) {
5271
5272		this.center.applyMatrix4( matrix );
5273		this.radius = this.radius * matrix.getMaxScaleOnAxis();
5274
5275		return this;
5276
5277	}
5278
5279	translate( offset ) {
5280
5281		this.center.add( offset );
5282
5283		return this;
5284
5285	}
5286
5287	expandByPoint( point ) {
5288
5289		if ( this.isEmpty() ) {
5290
5291			this.center.copy( point );
5292
5293			this.radius = 0;
5294
5295			return this;
5296
5297		}
5298
5299		_v1$6.subVectors( point, this.center );
5300
5301		const lengthSq = _v1$6.lengthSq();
5302
5303		if ( lengthSq > ( this.radius * this.radius ) ) {
5304
5305			// calculate the minimal sphere
5306
5307			const length = Math.sqrt( lengthSq );
5308
5309			const delta = ( length - this.radius ) * 0.5;
5310
5311			this.center.addScaledVector( _v1$6, delta / length );
5312
5313			this.radius += delta;
5314
5315		}
5316
5317		return this;
5318
5319	}
5320
5321	union( sphere ) {
5322
5323		if ( sphere.isEmpty() ) {
5324
5325			return this;
5326
5327		}
5328
5329		if ( this.isEmpty() ) {
5330
5331			this.copy( sphere );
5332
5333			return this;
5334
5335		}
5336
5337		if ( this.center.equals( sphere.center ) === true ) {
5338
5339			 this.radius = Math.max( this.radius, sphere.radius );
5340
5341		} else {
5342
5343			_v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius );
5344
5345			this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) );
5346
5347			this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) );
5348
5349		}
5350
5351		return this;
5352
5353	}
5354
5355	equals( sphere ) {
5356
5357		return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
5358
5359	}
5360
5361	clone() {
5362
5363		return new this.constructor().copy( this );
5364
5365	}
5366
5367}
5368
5369const _vector$a = /*@__PURE__*/ new Vector3();
5370const _segCenter = /*@__PURE__*/ new Vector3();
5371const _segDir = /*@__PURE__*/ new Vector3();
5372const _diff = /*@__PURE__*/ new Vector3();
5373
5374const _edge1 = /*@__PURE__*/ new Vector3();
5375const _edge2 = /*@__PURE__*/ new Vector3();
5376const _normal$1 = /*@__PURE__*/ new Vector3();
5377
5378class Ray {
5379
5380	constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 
vendor: 8,510 bytes, lines 5380-5786
53801 ) ) {
5381
5382		this.origin = origin;
5383		this.direction = direction;
5384
5385	}
5386
5387	set( origin, direction ) {
5388
5389		this.origin.copy( origin );
5390		this.direction.copy( direction );
5391
5392		return this;
5393
5394	}
5395
5396	copy( ray ) {
5397
5398		this.origin.copy( ray.origin );
5399		this.direction.copy( ray.direction );
5400
5401		return this;
5402
5403	}
5404
5405	at( t, target ) {
5406
5407		return target.copy( this.origin ).addScaledVector( this.direction, t );
5408
5409	}
5410
5411	lookAt( v ) {
5412
5413		this.direction.copy( v ).sub( this.origin ).normalize();
5414
5415		return this;
5416
5417	}
5418
5419	recast( t ) {
5420
5421		this.origin.copy( this.at( t, _vector$a ) );
5422
5423		return this;
5424
5425	}
5426
5427	closestPointToPoint( point, target ) {
5428
5429		target.subVectors( point, this.origin );
5430
5431		const directionDistance = target.dot( this.direction );
5432
5433		if ( directionDistance < 0 ) {
5434
5435			return target.copy( this.origin );
5436
5437		}
5438
5439		return target.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5440
5441	}
5442
5443	distanceToPoint( point ) {
5444
5445		return Math.sqrt( this.distanceSqToPoint( point ) );
5446
5447	}
5448
5449	distanceSqToPoint( point ) {
5450
5451		const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction );
5452
5453		// point behind the ray
5454
5455		if ( directionDistance < 0 ) {
5456
5457			return this.origin.distanceToSquared( point );
5458
5459		}
5460
5461		_vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5462
5463		return _vector$a.distanceToSquared( point );
5464
5465	}
5466
5467	distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
5468
5469		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
5470		// It returns the min distance between the ray and the segment
5471		// defined by v0 and v1
5472		// It can also set two optional targets :
5473		// - The closest point on the ray
5474		// - The closest point on the segment
5475
5476		_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
5477		_segDir.copy( v1 ).sub( v0 ).normalize();
5478		_diff.copy( this.origin ).sub( _segCenter );
5479
5480		const segExtent = v0.distanceTo( v1 ) * 0.5;
5481		const a01 = - this.direction.dot( _segDir );
5482		const b0 = _diff.dot( this.direction );
5483		const b1 = - _diff.dot( _segDir );
5484		const c = _diff.lengthSq();
5485		const det = Math.abs( 1 - a01 * a01 );
5486		let s0, s1, sqrDist, extDet;
5487
5488		if ( det > 0 ) {
5489
5490			// The ray and segment are not parallel.
5491
5492			s0 = a01 * b1 - b0;
5493			s1 = a01 * b0 - b1;
5494			extDet = segExtent * det;
5495
5496			if ( s0 >= 0 ) {
5497
5498				if ( s1 >= - extDet ) {
5499
5500					if ( s1 <= extDet ) {
5501
5502						// region 0
5503						// Minimum at interior points of ray and segment.
5504
5505						const invDet = 1 / det;
5506						s0 *= invDet;
5507						s1 *= invDet;
5508						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
5509
5510					} else {
5511
5512						// region 1
5513
5514						s1 = segExtent;
5515						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5516						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5517
5518					}
5519
5520				} else {
5521
5522					// region 5
5523
5524					s1 = - segExtent;
5525					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5526					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5527
5528				}
5529
5530			} else {
5531
5532				if ( s1 <= - extDet ) {
5533
5534					// region 4
5535
5536					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
5537					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5538					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5539
5540				} else if ( s1 <= extDet ) {
5541
5542					// region 3
5543
5544					s0 = 0;
5545					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
5546					sqrDist = s1 * ( s1 + 2 * b1 ) + c;
5547
5548				} else {
5549
5550					// region 2
5551
5552					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
5553					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
5554					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5555
5556				}
5557
5558			}
5559
5560		} else {
5561
5562			// Ray and segment are parallel.
5563
5564			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
5565			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
5566			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
5567
5568		}
5569
5570		if ( optionalPointOnRay ) {
5571
5572			optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 );
5573
5574		}
5575
5576		if ( optionalPointOnSegment ) {
5577
5578			optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 );
5579
5580		}
5581
5582		return sqrDist;
5583
5584	}
5585
5586	intersectSphere( sphere, target ) {
5587
5588		_vector$a.subVectors( sphere.center, this.origin );
5589		const tca = _vector$a.dot( this.direction );
5590		const d2 = _vector$a.dot( _vector$a ) - tca * tca;
5591		const radius2 = sphere.radius * sphere.radius;
5592
5593		if ( d2 > radius2 ) return null;
5594
5595		const thc = Math.sqrt( radius2 - d2 );
5596
5597		// t0 = first intersect point - entrance on front of sphere
5598		const t0 = tca - thc;
5599
5600		// t1 = second intersect point - exit point on back of sphere
5601		const t1 = tca + thc;
5602
5603		// test to see if t1 is behind the ray - if so, return null
5604		if ( t1 < 0 ) return null;
5605
5606		// test to see if t0 is behind the ray:
5607		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
5608		// in order to always return an intersect point that is in front of the ray.
5609		if ( t0 < 0 ) return this.at( t1, target );
5610
5611		// else t0 is in front of the ray, so return the first collision point scaled by t0
5612		return this.at( t0, target );
5613
5614	}
5615
5616	intersectsSphere( sphere ) {
5617
5618		return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
5619
5620	}
5621
5622	distanceToPlane( plane ) {
5623
5624		const denominator = plane.normal.dot( this.direction );
5625
5626		if ( denominator === 0 ) {
5627
5628			// line is coplanar, return origin
5629			if ( plane.distanceToPoint( this.origin ) === 0 ) {
5630
5631				return 0;
5632
5633			}
5634
5635			// Null is preferable to undefined since undefined means.... it is undefined
5636
5637			return null;
5638
5639		}
5640
5641		const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
5642
5643		// Return if the ray never intersects the plane
5644
5645		return t >= 0 ? t : null;
5646
5647	}
5648
5649	intersectPlane( plane, target ) {
5650
5651		const t = this.distanceToPlane( plane );
5652
5653		if ( t === null ) {
5654
5655			return null;
5656
5657		}
5658
5659		return this.at( t, target );
5660
5661	}
5662
5663	intersectsPlane( plane ) {
5664
5665		// check if the ray lies on the plane first
5666
5667		const distToPoint = plane.distanceToPoint( this.origin );
5668
5669		if ( distToPoint === 0 ) {
5670
5671			return true;
5672
5673		}
5674
5675		const denominator = plane.normal.dot( this.direction );
5676
5677		if ( denominator * distToPoint < 0 ) {
5678
5679			return true;
5680
5681		}
5682
5683		// ray origin is behind the plane (and is pointing behind it)
5684
5685		return false;
5686
5687	}
5688
5689	intersectBox( box, target ) {
5690
5691		let tmin, tmax, tymin, tymax, tzmin, tzmax;
5692
5693		const invdirx = 1 / this.direction.x,
5694			invdiry = 1 / this.direction.y,
5695			invdirz = 1 / this.direction.z;
5696
5697		const origin = this.origin;
5698
5699		if ( invdirx >= 0 ) {
5700
5701			tmin = ( box.min.x - origin.x ) * invdirx;
5702			tmax = ( box.max.x - origin.x ) * invdirx;
5703
5704		} else {
5705
5706			tmin = ( box.max.x - origin.x ) * invdirx;
5707			tmax = ( box.min.x - origin.x ) * invdirx;
5708
5709		}
5710
5711		if ( invdiry >= 0 ) {
5712
5713			tymin = ( box.min.y - origin.y ) * invdiry;
5714			tymax = ( box.max.y - origin.y ) * invdiry;
5715
5716		} else {
5717
5718			tymin = ( box.max.y - origin.y ) * invdiry;
5719			tymax = ( box.min.y - origin.y ) * invdiry;
5720
5721		}
5722
5723		if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
5724
5725		if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin;
5726
5727		if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax;
5728
5729		if ( invdirz >= 0 ) {
5730
5731			tzmin = ( box.min.z - origin.z ) * invdirz;
5732			tzmax = ( box.max.z - origin.z ) * invdirz;
5733
5734		} else {
5735
5736			tzmin = ( box.max.z - origin.z ) * invdirz;
5737			tzmax = ( box.min.z - origin.z ) * invdirz;
5738
5739		}
5740
5741		if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
5742
5743		if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
5744
5745		if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
5746
5747		//return point closest to the ray (positive side)
5748
5749		if ( tmax < 0 ) return null;
5750
5751		return this.at( tmin >= 0 ? tmin : tmax, target );
5752
5753	}
5754
5755	intersectsBox( box ) {
5756
5757		return this.intersectBox( box, _vector$a ) !== null;
5758
5759	}
5760
5761	intersectTriangle( a, b, c, backfaceCulling, target ) {
5762
5763		// Compute the offset origin, edges, and normal.
5764
5765		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
5766
5767		_edge1.subVectors( b, a );
5768		_edge2.subVectors( c, a );
5769		_normal$1.crossVectors( _edge1, _edge2 );
5770
5771		// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
5772		// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
5773		//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
5774		//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
5775		//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
5776		let DdN = this.direction.dot( _normal$1 );
5777		let sign;
5778
5779		if ( DdN > 0 ) {
5780
5781			if ( backfaceCulling ) return null;
5782			sign = 1;
5783
5784		} else if ( DdN < 0 ) {
5785
5786			sign = -
5786 
vendor: 17,907 bytes, lines 5786-6646
57861;
5787			DdN = - DdN;
5788
5789		} else {
5790
5791			return null;
5792
5793		}
5794
5795		_diff.subVectors( this.origin, a );
5796		const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
5797
5798		// b1 < 0, no intersection
5799		if ( DdQxE2 < 0 ) {
5800
5801			return null;
5802
5803		}
5804
5805		const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
5806
5807		// b2 < 0, no intersection
5808		if ( DdE1xQ < 0 ) {
5809
5810			return null;
5811
5812		}
5813
5814		// b1+b2 > 1, no intersection
5815		if ( DdQxE2 + DdE1xQ > DdN ) {
5816
5817			return null;
5818
5819		}
5820
5821		// Line intersects triangle, check if ray does.
5822		const QdN = - sign * _diff.dot( _normal$1 );
5823
5824		// t < 0, no intersection
5825		if ( QdN < 0 ) {
5826
5827			return null;
5828
5829		}
5830
5831		// Ray intersects triangle.
5832		return this.at( QdN / DdN, target );
5833
5834	}
5835
5836	applyMatrix4( matrix4 ) {
5837
5838		this.origin.applyMatrix4( matrix4 );
5839		this.direction.transformDirection( matrix4 );
5840
5841		return this;
5842
5843	}
5844
5845	equals( ray ) {
5846
5847		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
5848
5849	}
5850
5851	clone() {
5852
5853		return new this.constructor().copy( this );
5854
5855	}
5856
5857}
5858
5859class Matrix4 {
5860
5861	constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5862
5863		Matrix4.prototype.isMatrix4 = true;
5864
5865		this.elements = [
5866
5867			1, 0, 0, 0,
5868			0, 1, 0, 0,
5869			0, 0, 1, 0,
5870			0, 0, 0, 1
5871
5872		];
5873
5874		if ( n11 !== undefined ) {
5875
5876			this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 );
5877
5878		}
5879
5880	}
5881
5882	set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5883
5884		const te = this.elements;
5885
5886		te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
5887		te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
5888		te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
5889		te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
5890
5891		return this;
5892
5893	}
5894
5895	identity() {
5896
5897		this.set(
5898
5899			1, 0, 0, 0,
5900			0, 1, 0, 0,
5901			0, 0, 1, 0,
5902			0, 0, 0, 1
5903
5904		);
5905
5906		return this;
5907
5908	}
5909
5910	clone() {
5911
5912		return new Matrix4().fromArray( this.elements );
5913
5914	}
5915
5916	copy( m ) {
5917
5918		const te = this.elements;
5919		const me = m.elements;
5920
5921		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
5922		te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
5923		te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
5924		te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
5925
5926		return this;
5927
5928	}
5929
5930	copyPosition( m ) {
5931
5932		const te = this.elements, me = m.elements;
5933
5934		te[ 12 ] = me[ 12 ];
5935		te[ 13 ] = me[ 13 ];
5936		te[ 14 ] = me[ 14 ];
5937
5938		return this;
5939
5940	}
5941
5942	setFromMatrix3( m ) {
5943
5944		const me = m.elements;
5945
5946		this.set(
5947
5948			me[ 0 ], me[ 3 ], me[ 6 ], 0,
5949			me[ 1 ], me[ 4 ], me[ 7 ], 0,
5950			me[ 2 ], me[ 5 ], me[ 8 ], 0,
5951			0, 0, 0, 1
5952
5953		);
5954
5955		return this;
5956
5957	}
5958
5959	extractBasis( xAxis, yAxis, zAxis ) {
5960
5961		xAxis.setFromMatrixColumn( this, 0 );
5962		yAxis.setFromMatrixColumn( this, 1 );
5963		zAxis.setFromMatrixColumn( this, 2 );
5964
5965		return this;
5966
5967	}
5968
5969	makeBasis( xAxis, yAxis, zAxis ) {
5970
5971		this.set(
5972			xAxis.x, yAxis.x, zAxis.x, 0,
5973			xAxis.y, yAxis.y, zAxis.y, 0,
5974			xAxis.z, yAxis.z, zAxis.z, 0,
5975			0, 0, 0, 1
5976		);
5977
5978		return this;
5979
5980	}
5981
5982	extractRotation( m ) {
5983
5984		// this method does not support reflection matrices
5985
5986		const te = this.elements;
5987		const me = m.elements;
5988
5989		const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length();
5990		const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length();
5991		const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length();
5992
5993		te[ 0 ] = me[ 0 ] * scaleX;
5994		te[ 1 ] = me[ 1 ] * scaleX;
5995		te[ 2 ] = me[ 2 ] * scaleX;
5996		te[ 3 ] = 0;
5997
5998		te[ 4 ] = me[ 4 ] * scaleY;
5999		te[ 5 ] = me[ 5 ] * scaleY;
6000		te[ 6 ] = me[ 6 ] * scaleY;
6001		te[ 7 ] = 0;
6002
6003		te[ 8 ] = me[ 8 ] * scaleZ;
6004		te[ 9 ] = me[ 9 ] * scaleZ;
6005		te[ 10 ] = me[ 10 ] * scaleZ;
6006		te[ 11 ] = 0;
6007
6008		te[ 12 ] = 0;
6009		te[ 13 ] = 0;
6010		te[ 14 ] = 0;
6011		te[ 15 ] = 1;
6012
6013		return this;
6014
6015	}
6016
6017	makeRotationFromEuler( euler ) {
6018
6019		const te = this.elements;
6020
6021		const x = euler.x, y = euler.y, z = euler.z;
6022		const a = Math.cos( x ), b = Math.sin( x );
6023		const c = Math.cos( y ), d = Math.sin( y );
6024		const e = Math.cos( z ), f = Math.sin( z );
6025
6026		if ( euler.order === 'XYZ' ) {
6027
6028			const ae = a * e, af = a * f, be = b * e, bf = b * f;
6029
6030			te[ 0 ] = c * e;
6031			te[ 4 ] = - c * f;
6032			te[ 8 ] = d;
6033
6034			te[ 1 ] = af + be * d;
6035			te[ 5 ] = ae - bf * d;
6036			te[ 9 ] = - b * c;
6037
6038			te[ 2 ] = bf - ae * d;
6039			te[ 6 ] = be + af * d;
6040			te[ 10 ] = a * c;
6041
6042		} else if ( euler.order === 'YXZ' ) {
6043
6044			const ce = c * e, cf = c * f, de = d * e, df = d * f;
6045
6046			te[ 0 ] = ce + df * b;
6047			te[ 4 ] = de * b - cf;
6048			te[ 8 ] = a * d;
6049
6050			te[ 1 ] = a * f;
6051			te[ 5 ] = a * e;
6052			te[ 9 ] = - b;
6053
6054			te[ 2 ] = cf * b - de;
6055			te[ 6 ] = df + ce * b;
6056			te[ 10 ] = a * c;
6057
6058		} else if ( euler.order === 'ZXY' ) {
6059
6060			const ce = c * e, cf = c * f, de = d * e, df = d * f;
6061
6062			te[ 0 ] = ce - df * b;
6063			te[ 4 ] = - a * f;
6064			te[ 8 ] = de + cf * b;
6065
6066			te[ 1 ] = cf + de * b;
6067			te[ 5 ] = a * e;
6068			te[ 9 ] = df - ce * b;
6069
6070			te[ 2 ] = - a * d;
6071			te[ 6 ] = b;
6072			te[ 10 ] = a * c;
6073
6074		} else if ( euler.order === 'ZYX' ) {
6075
6076			const ae = a * e, af = a * f, be = b * e, bf = b * f;
6077
6078			te[ 0 ] = c * e;
6079			te[ 4 ] = be * d - af;
6080			te[ 8 ] = ae * d + bf;
6081
6082			te[ 1 ] = c * f;
6083			te[ 5 ] = bf * d + ae;
6084			te[ 9 ] = af * d - be;
6085
6086			te[ 2 ] = - d;
6087			te[ 6 ] = b * c;
6088			te[ 10 ] = a * c;
6089
6090		} else if ( euler.order === 'YZX' ) {
6091
6092			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
6093
6094			te[ 0 ] = c * e;
6095			te[ 4 ] = bd - ac * f;
6096			te[ 8 ] = bc * f + ad;
6097
6098			te[ 1 ] = f;
6099			te[ 5 ] = a * e;
6100			te[ 9 ] = - b * e;
6101
6102			te[ 2 ] = - d * e;
6103			te[ 6 ] = ad * f + bc;
6104			te[ 10 ] = ac - bd * f;
6105
6106		} else if ( euler.order === 'XZY' ) {
6107
6108			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
6109
6110			te[ 0 ] = c * e;
6111			te[ 4 ] = - f;
6112			te[ 8 ] = d * e;
6113
6114			te[ 1 ] = ac * f + bd;
6115			te[ 5 ] = a * e;
6116			te[ 9 ] = ad * f - bc;
6117
6118			te[ 2 ] = bc * f - ad;
6119			te[ 6 ] = b * e;
6120			te[ 10 ] = bd * f + ac;
6121
6122		}
6123
6124		// bottom row
6125		te[ 3 ] = 0;
6126		te[ 7 ] = 0;
6127		te[ 11 ] = 0;
6128
6129		// last column
6130		te[ 12 ] = 0;
6131		te[ 13 ] = 0;
6132		te[ 14 ] = 0;
6133		te[ 15 ] = 1;
6134
6135		return this;
6136
6137	}
6138
6139	makeRotationFromQuaternion( q ) {
6140
6141		return this.compose( _zero, q, _one );
6142
6143	}
6144
6145	lookAt( eye, target, up ) {
6146
6147		const te = this.elements;
6148
6149		_z.subVectors( eye, target );
6150
6151		if ( _z.lengthSq() === 0 ) {
6152
6153			// eye and target are in the same position
6154
6155			_z.z = 1;
6156
6157		}
6158
6159		_z.normalize();
6160		_x.crossVectors( up, _z );
6161
6162		if ( _x.lengthSq() === 0 ) {
6163
6164			// up and z are parallel
6165
6166			if ( Math.abs( up.z ) === 1 ) {
6167
6168				_z.x += 0.0001;
6169
6170			} else {
6171
6172				_z.z += 0.0001;
6173
6174			}
6175
6176			_z.normalize();
6177			_x.crossVectors( up, _z );
6178
6179		}
6180
6181		_x.normalize();
6182		_y.crossVectors( _z, _x );
6183
6184		te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
6185		te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
6186		te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
6187
6188		return this;
6189
6190	}
6191
6192	multiply( m ) {
6193
6194		return this.multiplyMatrices( this, m );
6195
6196	}
6197
6198	premultiply( m ) {
6199
6200		return this.multiplyMatrices( m, this );
6201
6202	}
6203
6204	multiplyMatrices( a, b ) {
6205
6206		const ae = a.elements;
6207		const be = b.elements;
6208		const te = this.elements;
6209
6210		const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
6211		const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
6212		const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
6213		const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
6214
6215		const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
6216		const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
6217		const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
6218		const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
6219
6220		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
6221		te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
6222		te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
6223		te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
6224
6225		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
6226		te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
6227		te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
6228		te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
6229
6230		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
6231		te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
6232		te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
6233		te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
6234
6235		te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
6236		te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
6237		te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
6238		te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
6239
6240		return this;
6241
6242	}
6243
6244	multiplyScalar( s ) {
6245
6246		const te = this.elements;
6247
6248		te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
6249		te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
6250		te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
6251		te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
6252
6253		return this;
6254
6255	}
6256
6257	determinant() {
6258
6259		const te = this.elements;
6260
6261		const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
6262		const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
6263		const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
6264		const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
6265
6266		//TODO: make this more efficient
6267		//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
6268
6269		return (
6270			n41 * (
6271				+ n14 * n23 * n32
6272				 - n13 * n24 * n32
6273				 - n14 * n22 * n33
6274				 + n12 * n24 * n33
6275				 + n13 * n22 * n34
6276				 - n12 * n23 * n34
6277			) +
6278			n42 * (
6279				+ n11 * n23 * n34
6280				 - n11 * n24 * n33
6281				 + n14 * n21 * n33
6282				 - n13 * n21 * n34
6283				 + n13 * n24 * n31
6284				 - n14 * n23 * n31
6285			) +
6286			n43 * (
6287				+ n11 * n24 * n32
6288				 - n11 * n22 * n34
6289				 - n14 * n21 * n32
6290				 + n12 * n21 * n34
6291				 + n14 * n22 * n31
6292				 - n12 * n24 * n31
6293			) +
6294			n44 * (
6295				- n13 * n22 * n31
6296				 - n11 * n23 * n32
6297				 + n11 * n22 * n33
6298				 + n13 * n21 * n32
6299				 - n12 * n21 * n33
6300				 + n12 * n23 * n31
6301			)
6302
6303		);
6304
6305	}
6306
6307	transpose() {
6308
6309		const te = this.elements;
6310		let tmp;
6311
6312		tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
6313		tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
6314		tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
6315
6316		tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
6317		tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
6318		tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
6319
6320		return this;
6321
6322	}
6323
6324	setPosition( x, y, z ) {
6325
6326		const te = this.elements;
6327
6328		if ( x.isVector3 ) {
6329
6330			te[ 12 ] = x.x;
6331			te[ 13 ] = x.y;
6332			te[ 14 ] = x.z;
6333
6334		} else {
6335
6336			te[ 12 ] = x;
6337			te[ 13 ] = y;
6338			te[ 14 ] = z;
6339
6340		}
6341
6342		return this;
6343
6344	}
6345
6346	invert() {
6347
6348		// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
6349		const te = this.elements,
6350
6351			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
6352			n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
6353			n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
6354			n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
6355
6356			t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
6357			t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
6358			t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
6359			t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
6360
6361		const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
6362
6363		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
6364
6365		const detInv = 1 / det;
6366
6367		te[ 0 ] = t11 * detInv;
6368		te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
6369		te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
6370		te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
6371
6372		te[ 4 ] = t12 * detInv;
6373		te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
6374		te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
6375		te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
6376
6377		te[ 8 ] = t13 * detInv;
6378		te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
6379		te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
6380		te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
6381
6382		te[ 12 ] = t14 * detInv;
6383		te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
6384		te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
6385		te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
6386
6387		return this;
6388
6389	}
6390
6391	scale( v ) {
6392
6393		const te = this.elements;
6394		const x = v.x, y = v.y, z = v.z;
6395
6396		te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
6397		te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
6398		te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
6399		te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
6400
6401		return this;
6402
6403	}
6404
6405	getMaxScaleOnAxis() {
6406
6407		const te = this.elements;
6408
6409		const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
6410		const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
6411		const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
6412
6413		return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
6414
6415	}
6416
6417	makeTranslation( x, y, z ) {
6418
6419		if ( x.isVector3 ) {
6420
6421			this.set(
6422
6423				1, 0, 0, x.x,
6424				0, 1, 0, x.y,
6425				0, 0, 1, x.z,
6426				0, 0, 0, 1
6427
6428			);
6429
6430		} else {
6431
6432			this.set(
6433
6434				1, 0, 0, x,
6435				0, 1, 0, y,
6436				0, 0, 1, z,
6437				0, 0, 0, 1
6438
6439			);
6440
6441		}
6442
6443		return this;
6444
6445	}
6446
6447	makeRotationX( theta ) {
6448
6449		const c = Math.cos( theta ), s = Math.sin( theta );
6450
6451		this.set(
6452
6453			1, 0, 0, 0,
6454			0, c, - s, 0,
6455			0, s, c, 0,
6456			0, 0, 0, 1
6457
6458		);
6459
6460		return this;
6461
6462	}
6463
6464	makeRotationY( theta ) {
6465
6466		const c = Math.cos( theta ), s = Math.sin( theta );
6467
6468		this.set(
6469
6470			 c, 0, s, 0,
6471			 0, 1, 0, 0,
6472			- s, 0, c, 0,
6473			 0, 0, 0, 1
6474
6475		);
6476
6477		return this;
6478
6479	}
6480
6481	makeRotationZ( theta ) {
6482
6483		const c = Math.cos( theta ), s = Math.sin( theta );
6484
6485		this.set(
6486
6487			c, - s, 0, 0,
6488			s, c, 0, 0,
6489			0, 0, 1, 0,
6490			0, 0, 0, 1
6491
6492		);
6493
6494		return this;
6495
6496	}
6497
6498	makeRotationAxis( axis, angle ) {
6499
6500		// Based on http://www.gamedev.net/reference/articles/article1199.asp
6501
6502		const c = Math.cos( angle );
6503		const s = Math.sin( angle );
6504		const t = 1 - c;
6505		const x = axis.x, y = axis.y, z = axis.z;
6506		const tx = t * x, ty = t * y;
6507
6508		this.set(
6509
6510			tx * x + c, tx * y - s * z, tx * z + s * y, 0,
6511			tx * y + s * z, ty * y + c, ty * z - s * x, 0,
6512			tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
6513			0, 0, 0, 1
6514
6515		);
6516
6517		return this;
6518
6519	}
6520
6521	makeScale( x, y, z ) {
6522
6523		this.set(
6524
6525			x, 0, 0, 0,
6526			0, y, 0, 0,
6527			0, 0, z, 0,
6528			0, 0, 0, 1
6529
6530		);
6531
6532		return this;
6533
6534	}
6535
6536	makeShear( xy, xz, yx, yz, zx, zy ) {
6537
6538		this.set(
6539
6540			1, yx, zx, 0,
6541			xy, 1, zy, 0,
6542			xz, yz, 1, 0,
6543			0, 0, 0, 1
6544
6545		);
6546
6547		return this;
6548
6549	}
6550
6551	compose( position, quaternion, scale ) {
6552
6553		const te = this.elements;
6554
6555		const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
6556		const x2 = x + x,	y2 = y + y, z2 = z + z;
6557		const xx = x * x2, xy = x * y2, xz = x * z2;
6558		const yy = y * y2, yz = y * z2, zz = z * z2;
6559		const wx = w * x2, wy = w * y2, wz = w * z2;
6560
6561		const sx = scale.x, sy = scale.y, sz = scale.z;
6562
6563		te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
6564		te[ 1 ] = ( xy + wz ) * sx;
6565		te[ 2 ] = ( xz - wy ) * sx;
6566		te[ 3 ] = 0;
6567
6568		te[ 4 ] = ( xy - wz ) * sy;
6569		te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
6570		te[ 6 ] = ( yz + wx ) * sy;
6571		te[ 7 ] = 0;
6572
6573		te[ 8 ] = ( xz + wy ) * sz;
6574		te[ 9 ] = ( yz - wx ) * sz;
6575		te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
6576		te[ 11 ] = 0;
6577
6578		te[ 12 ] = position.x;
6579		te[ 13 ] = position.y;
6580		te[ 14 ] = position.z;
6581		te[ 15 ] = 1;
6582
6583		return this;
6584
6585	}
6586
6587	decompose( position, quaternion, scale ) {
6588
6589		const te = this.elements;
6590
6591		let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
6592		const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
6593		const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
6594
6595		// if determine is negative, we need to invert one scale
6596		const det = this.determinant();
6597		if ( det < 0 ) sx = - sx;
6598
6599		position.x = te[ 12 ];
6600		position.y = te[ 13 ];
6601		position.z = te[ 14 ];
6602
6603		// scale the rotation part
6604		_m1$4.copy( this );
6605
6606		const invSX = 1 / sx;
6607		const invSY = 1 / sy;
6608		const invSZ = 1 / sz;
6609
6610		_m1$4.elements[ 0 ] *= invSX;
6611		_m1$4.elements[ 1 ] *= invSX;
6612		_m1$4.elements[ 2 ] *= invSX;
6613
6614		_m1$4.elements[ 4 ] *= invSY;
6615		_m1$4.elements[ 5 ] *= invSY;
6616		_m1$4.elements[ 6 ] *= invSY;
6617
6618		_m1$4.elements[ 8 ] *= invSZ;
6619		_m1$4.elements[ 9 ] *= invSZ;
6620		_m1$4.elements[ 10 ] *= invSZ;
6621
6622		quaternion.setFromRotationMatrix( _m1$4 );
6623
6624		scale.x = sx;
6625		scale.y = sy;
6626		scale.z = sz;
6627
6628		return this;
6629
6630	}
6631
6632	makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
6633
6634		const te = this.elements;
6635		const x = 2 * near / ( right - left );
6636		const y = 2 * near / ( top - bottom );
6637
6638		const a = ( right + left ) / ( right - left );
6639		const b = ( top + bottom ) / ( top - bottom );
6640
6641		let c, d;
6642
6643		if ( coordinateSystem === WebGLCoordinateSystem ) {
6644
6645			c = - ( far + near ) / ( far - near );
6646			d = ( -
vendor: 8,642 bytes, lines 6646-7158
6646 2 * far * near ) / ( far - near );
6647
6648		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
6649
6650			c = - far / ( far - near );
6651			d = ( - far * near ) / ( far - near );
6652
6653		} else {
6654
6655			throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
6656
6657		}
6658
6659		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a; 	te[ 12 ] = 0;
6660		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b; 	te[ 13 ] = 0;
6661		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c; 	te[ 14 ] = d;
6662		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = - 1;	te[ 15 ] = 0;
6663
6664		return this;
6665
6666	}
6667
6668	makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
6669
6670		const te = this.elements;
6671		const w = 1.0 / ( right - left );
6672		const h = 1.0 / ( top - bottom );
6673		const p = 1.0 / ( far - near );
6674
6675		const x = ( right + left ) * w;
6676		const y = ( top + bottom ) * h;
6677
6678		let z, zInv;
6679
6680		if ( coordinateSystem === WebGLCoordinateSystem ) {
6681
6682			z = ( far + near ) * p;
6683			zInv = - 2 * p;
6684
6685		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
6686
6687			z = near * p;
6688			zInv = - 1 * p;
6689
6690		} else {
6691
6692			throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );
6693
6694		}
6695
6696		te[ 0 ] = 2 * w;	te[ 4 ] = 0;		te[ 8 ] = 0; 		te[ 12 ] = - x;
6697		te[ 1 ] = 0; 		te[ 5 ] = 2 * h;	te[ 9 ] = 0; 		te[ 13 ] = - y;
6698		te[ 2 ] = 0; 		te[ 6 ] = 0;		te[ 10 ] = zInv;	te[ 14 ] = - z;
6699		te[ 3 ] = 0; 		te[ 7 ] = 0;		te[ 11 ] = 0;		te[ 15 ] = 1;
6700
6701		return this;
6702
6703	}
6704
6705	equals( matrix ) {
6706
6707		const te = this.elements;
6708		const me = matrix.elements;
6709
6710		for ( let i = 0; i < 16; i ++ ) {
6711
6712			if ( te[ i ] !== me[ i ] ) return false;
6713
6714		}
6715
6716		return true;
6717
6718	}
6719
6720	fromArray( array, offset = 0 ) {
6721
6722		for ( let i = 0; i < 16; i ++ ) {
6723
6724			this.elements[ i ] = array[ i + offset ];
6725
6726		}
6727
6728		return this;
6729
6730	}
6731
6732	toArray( array = [], offset = 0 ) {
6733
6734		const te = this.elements;
6735
6736		array[ offset ] = te[ 0 ];
6737		array[ offset + 1 ] = te[ 1 ];
6738		array[ offset + 2 ] = te[ 2 ];
6739		array[ offset + 3 ] = te[ 3 ];
6740
6741		array[ offset + 4 ] = te[ 4 ];
6742		array[ offset + 5 ] = te[ 5 ];
6743		array[ offset + 6 ] = te[ 6 ];
6744		array[ offset + 7 ] = te[ 7 ];
6745
6746		array[ offset + 8 ] = te[ 8 ];
6747		array[ offset + 9 ] = te[ 9 ];
6748		array[ offset + 10 ] = te[ 10 ];
6749		array[ offset + 11 ] = te[ 11 ];
6750
6751		array[ offset + 12 ] = te[ 12 ];
6752		array[ offset + 13 ] = te[ 13 ];
6753		array[ offset + 14 ] = te[ 14 ];
6754		array[ offset + 15 ] = te[ 15 ];
6755
6756		return array;
6757
6758	}
6759
6760}
6761
6762const _v1$5 = /*@__PURE__*/ new Vector3();
6763const _m1$4 = /*@__PURE__*/ new Matrix4();
6764const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
6765const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
6766const _x = /*@__PURE__*/ new Vector3();
6767const _y = /*@__PURE__*/ new Vector3();
6768const _z = /*@__PURE__*/ new Vector3();
6769
6770const _matrix$2 = /*@__PURE__*/ new Matrix4();
6771const _quaternion$3 = /*@__PURE__*/ new Quaternion();
6772
6773class Euler {
6774
6775	constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) {
6776
6777		this.isEuler = true;
6778
6779		this._x = x;
6780		this._y = y;
6781		this._z = z;
6782		this._order = order;
6783
6784	}
6785
6786	get x() {
6787
6788		return this._x;
6789
6790	}
6791
6792	set x( value ) {
6793
6794		this._x = value;
6795		this._onChangeCallback();
6796
6797	}
6798
6799	get y() {
6800
6801		return this._y;
6802
6803	}
6804
6805	set y( value ) {
6806
6807		this._y = value;
6808		this._onChangeCallback();
6809
6810	}
6811
6812	get z() {
6813
6814		return this._z;
6815
6816	}
6817
6818	set z( value ) {
6819
6820		this._z = value;
6821		this._onChangeCallback();
6822
6823	}
6824
6825	get order() {
6826
6827		return this._order;
6828
6829	}
6830
6831	set order( value ) {
6832
6833		this._order = value;
6834		this._onChangeCallback();
6835
6836	}
6837
6838	set( x, y, z, order = this._order ) {
6839
6840		this._x = x;
6841		this._y = y;
6842		this._z = z;
6843		this._order = order;
6844
6845		this._onChangeCallback();
6846
6847		return this;
6848
6849	}
6850
6851	clone() {
6852
6853		return new this.constructor( this._x, this._y, this._z, this._order );
6854
6855	}
6856
6857	copy( euler ) {
6858
6859		this._x = euler._x;
6860		this._y = euler._y;
6861		this._z = euler._z;
6862		this._order = euler._order;
6863
6864		this._onChangeCallback();
6865
6866		return this;
6867
6868	}
6869
6870	setFromRotationMatrix( m, order = this._order, update = true ) {
6871
6872		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6873
6874		const te = m.elements;
6875		const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
6876		const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
6877		const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
6878
6879		switch ( order ) {
6880
6881			case 'XYZ':
6882
6883				this._y = Math.asin( clamp( m13, - 1, 1 ) );
6884
6885				if ( Math.abs( m13 ) < 0.9999999 ) {
6886
6887					this._x = Math.atan2( - m23, m33 );
6888					this._z = Math.atan2( - m12, m11 );
6889
6890				} else {
6891
6892					this._x = Math.atan2( m32, m22 );
6893					this._z = 0;
6894
6895				}
6896
6897				break;
6898
6899			case 'YXZ':
6900
6901				this._x = Math.asin( - clamp( m23, - 1, 1 ) );
6902
6903				if ( Math.abs( m23 ) < 0.9999999 ) {
6904
6905					this._y = Math.atan2( m13, m33 );
6906					this._z = Math.atan2( m21, m22 );
6907
6908				} else {
6909
6910					this._y = Math.atan2( - m31, m11 );
6911					this._z = 0;
6912
6913				}
6914
6915				break;
6916
6917			case 'ZXY':
6918
6919				this._x = Math.asin( clamp( m32, - 1, 1 ) );
6920
6921				if ( Math.abs( m32 ) < 0.9999999 ) {
6922
6923					this._y = Math.atan2( - m31, m33 );
6924					this._z = Math.atan2( - m12, m22 );
6925
6926				} else {
6927
6928					this._y = 0;
6929					this._z = Math.atan2( m21, m11 );
6930
6931				}
6932
6933				break;
6934
6935			case 'ZYX':
6936
6937				this._y = Math.asin( - clamp( m31, - 1, 1 ) );
6938
6939				if ( Math.abs( m31 ) < 0.9999999 ) {
6940
6941					this._x = Math.atan2( m32, m33 );
6942					this._z = Math.atan2( m21, m11 );
6943
6944				} else {
6945
6946					this._x = 0;
6947					this._z = Math.atan2( - m12, m22 );
6948
6949				}
6950
6951				break;
6952
6953			case 'YZX':
6954
6955				this._z = Math.asin( clamp( m21, - 1, 1 ) );
6956
6957				if ( Math.abs( m21 ) < 0.9999999 ) {
6958
6959					this._x = Math.atan2( - m23, m22 );
6960					this._y = Math.atan2( - m31, m11 );
6961
6962				} else {
6963
6964					this._x = 0;
6965					this._y = Math.atan2( m13, m33 );
6966
6967				}
6968
6969				break;
6970
6971			case 'XZY':
6972
6973				this._z = Math.asin( - clamp( m12, - 1, 1 ) );
6974
6975				if ( Math.abs( m12 ) < 0.9999999 ) {
6976
6977					this._x = Math.atan2( m32, m22 );
6978					this._y = Math.atan2( m13, m11 );
6979
6980				} else {
6981
6982					this._x = Math.atan2( - m23, m33 );
6983					this._y = 0;
6984
6985				}
6986
6987				break;
6988
6989			default:
6990
6991				console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
6992
6993		}
6994
6995		this._order = order;
6996
6997		if ( update === true ) this._onChangeCallback();
6998
6999		return this;
7000
7001	}
7002
7003	setFromQuaternion( q, order, update ) {
7004
7005		_matrix$2.makeRotationFromQuaternion( q );
7006
7007		return this.setFromRotationMatrix( _matrix$2, order, update );
7008
7009	}
7010
7011	setFromVector3( v, order = this._order ) {
7012
7013		return this.set( v.x, v.y, v.z, order );
7014
7015	}
7016
7017	reorder( newOrder ) {
7018
7019		// WARNING: this discards revolution information -bhouston
7020
7021		_quaternion$3.setFromEuler( this );
7022
7023		return this.setFromQuaternion( _quaternion$3, newOrder );
7024
7025	}
7026
7027	equals( euler ) {
7028
7029		return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
7030
7031	}
7032
7033	fromArray( array ) {
7034
7035		this._x = array[ 0 ];
7036		this._y = array[ 1 ];
7037		this._z = array[ 2 ];
7038		if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
7039
7040		this._onChangeCallback();
7041
7042		return this;
7043
7044	}
7045
7046	toArray( array = [], offset = 0 ) {
7047
7048		array[ offset ] = this._x;
7049		array[ offset + 1 ] = this._y;
7050		array[ offset + 2 ] = this._z;
7051		array[ offset + 3 ] = this._order;
7052
7053		return array;
7054
7055	}
7056
7057	_onChange( callback ) {
7058
7059		this._onChangeCallback = callback;
7060
7061		return this;
7062
7063	}
7064
7065	_onChangeCallback() {}
7066
7067	*[ Symbol.iterator ]() {
7068
7069		yield this._x;
7070		yield this._y;
7071		yield this._z;
7072		yield this._order;
7073
7074	}
7075
7076}
7077
7078Euler.DEFAULT_ORDER = 'XYZ';
7079
7080class Layers {
7081
7082	constructor() {
7083
7084		this.mask = 1 | 0;
7085
7086	}
7087
7088	set( channel ) {
7089
7090		this.mask = ( 1 << channel | 0 ) >>> 0;
7091
7092	}
7093
7094	enable( channel ) {
7095
7096		this.mask |= 1 << channel | 0;
7097
7098	}
7099
7100	enableAll() {
7101
7102		this.mask = 0xffffffff | 0;
7103
7104	}
7105
7106	toggle( channel ) {
7107
7108		this.mask ^= 1 << channel | 0;
7109
7110	}
7111
7112	disable( channel ) {
7113
7114		this.mask &= ~ ( 1 << channel | 0 );
7115
7116	}
7117
7118	disableAll() {
7119
7120		this.mask = 0;
7121
7122	}
7123
7124	test( layers ) {
7125
7126		return ( this.mask & layers.mask ) !== 0;
7127
7128	}
7129
7130	isEnabled( channel ) {
7131
7132		return ( this.mask & ( 1 << channel | 0 ) ) !== 0;
7133
7134	}
7135
7136}
7137
7138let _object3DId = 0;
7139
7140const _v1$4 = /*@__PURE__*/ new Vector3();
7141const _q1 = /*@__PURE__*/ new Quaternion();
7142const _m1$3 = /*@__PURE__*/ new Matrix4();
7143const _target = /*@__PURE__*/ new Vector3();
7144
7145const _position$3 = /*@__PURE__*/ new Vector3();
7146const _scale$2 = /*@__PURE__*/ new Vector3();
7147const _quaternion$2 = /*@__PURE__*/ new Quaternion();
7148
7149const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
7150const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
7151const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
7152
7153const _addedEvent = { type: 'added' };
7154const _removedEvent = { type: 'removed' };
7155
7156const _childaddedEvent = { type: 'childadded', child: null };
7157const _childremovedEvent = { type: 'childremoved', child: null };
7158
vendor: 9,737 bytes, lines 7159-7730
7159class Object3D extends EventDispatcher {
7160
7161	constructor() {
7162
7163		super();
7164
7165		this.isObject3D = true;
7166
7167		Object.defineProperty( this, 'id', { value: _object3DId ++ } );
7168
7169		this.uuid = generateUUID();
7170
7171		this.name = '';
7172		this.type = 'Object3D';
7173
7174		this.parent = null;
7175		this.children = [];
7176
7177		this.up = Object3D.DEFAULT_UP.clone();
7178
7179		const position = new Vector3();
7180		const rotation = new Euler();
7181		const quaternion = new Quaternion();
7182		const scale = new Vector3( 1, 1, 1 );
7183
7184		function onRotationChange() {
7185
7186			quaternion.setFromEuler( rotation, false );
7187
7188		}
7189
7190		function onQuaternionChange() {
7191
7192			rotation.setFromQuaternion( quaternion, undefined, false );
7193
7194		}
7195
7196		rotation._onChange( onRotationChange );
7197		quaternion._onChange( onQuaternionChange );
7198
7199		Object.defineProperties( this, {
7200			position: {
7201				configurable: true,
7202				enumerable: true,
7203				value: position
7204			},
7205			rotation: {
7206				configurable: true,
7207				enumerable: true,
7208				value: rotation
7209			},
7210			quaternion: {
7211				configurable: true,
7212				enumerable: true,
7213				value: quaternion
7214			},
7215			scale: {
7216				configurable: true,
7217				enumerable: true,
7218				value: scale
7219			},
7220			modelViewMatrix: {
7221				value: new Matrix4()
7222			},
7223			normalMatrix: {
7224				value: new Matrix3()
7225			}
7226		} );
7227
7228		this.matrix = new Matrix4();
7229		this.matrixWorld = new Matrix4();
7230
7231		this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
7232
7233		this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
7234		this.matrixWorldNeedsUpdate = false;
7235
7236		this.layers = new Layers();
7237		this.visible = true;
7238
7239		this.castShadow = false;
7240		this.receiveShadow = false;
7241
7242		this.frustumCulled = true;
7243		this.renderOrder = 0;
7244
7245		this.animations = [];
7246
7247		this.userData = {};
7248
7249	}
7250
7251	onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
7252
7253	onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
7254
7255	onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
7256
7257	onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
7258
7259	applyMatrix4( matrix ) {
7260
7261		if ( this.matrixAutoUpdate ) this.updateMatrix();
7262
7263		this.matrix.premultiply( matrix );
7264
7265		this.matrix.decompose( this.position, this.quaternion, this.scale );
7266
7267	}
7268
7269	applyQuaternion( q ) {
7270
7271		this.quaternion.premultiply( q );
7272
7273		return this;
7274
7275	}
7276
7277	setRotationFromAxisAngle( axis, angle ) {
7278
7279		// assumes axis is normalized
7280
7281		this.quaternion.setFromAxisAngle( axis, angle );
7282
7283	}
7284
7285	setRotationFromEuler( euler ) {
7286
7287		this.quaternion.setFromEuler( euler, true );
7288
7289	}
7290
7291	setRotationFromMatrix( m ) {
7292
7293		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7294
7295		this.quaternion.setFromRotationMatrix( m );
7296
7297	}
7298
7299	setRotationFromQuaternion( q ) {
7300
7301		// assumes q is normalized
7302
7303		this.quaternion.copy( q );
7304
7305	}
7306
7307	rotateOnAxis( axis, angle ) {
7308
7309		// rotate object on axis in object space
7310		// axis is assumed to be normalized
7311
7312		_q1.setFromAxisAngle( axis, angle );
7313
7314		this.quaternion.multiply( _q1 );
7315
7316		return this;
7317
7318	}
7319
7320	rotateOnWorldAxis( axis, angle ) {
7321
7322		// rotate object on axis in world space
7323		// axis is assumed to be normalized
7324		// method assumes no rotated parent
7325
7326		_q1.setFromAxisAngle( axis, angle );
7327
7328		this.quaternion.premultiply( _q1 );
7329
7330		return this;
7331
7332	}
7333
7334	rotateX( angle ) {
7335
7336		return this.rotateOnAxis( _xAxis, angle );
7337
7338	}
7339
7340	rotateY( angle ) {
7341
7342		return this.rotateOnAxis( _yAxis, angle );
7343
7344	}
7345
7346	rotateZ( angle ) {
7347
7348		return this.rotateOnAxis( _zAxis, angle );
7349
7350	}
7351
7352	translateOnAxis( axis, distance ) {
7353
7354		// translate object by distance along axis in object space
7355		// axis is assumed to be normalized
7356
7357		_v1$4.copy( axis ).applyQuaternion( this.quaternion );
7358
7359		this.position.add( _v1$4.multiplyScalar( distance ) );
7360
7361		return this;
7362
7363	}
7364
7365	translateX( distance ) {
7366
7367		return this.translateOnAxis( _xAxis, distance );
7368
7369	}
7370
7371	translateY( distance ) {
7372
7373		return this.translateOnAxis( _yAxis, distance );
7374
7375	}
7376
7377	translateZ( distance ) {
7378
7379		return this.translateOnAxis( _zAxis, distance );
7380
7381	}
7382
7383	localToWorld( vector ) {
7384
7385		this.updateWorldMatrix( true, false );
7386
7387		return vector.applyMatrix4( this.matrixWorld );
7388
7389	}
7390
7391	worldToLocal( vector ) {
7392
7393		this.updateWorldMatrix( true, false );
7394
7395		return vector.applyMatrix4( _m1$3.copy( this.matrixWorld ).invert() );
7396
7397	}
7398
7399	lookAt( x, y, z ) {
7400
7401		// This method does not support objects having non-uniformly-scaled parent(s)
7402
7403		if ( x.isVector3 ) {
7404
7405			_target.copy( x );
7406
7407		} else {
7408
7409			_target.set( x, y, z );
7410
7411		}
7412
7413		const parent = this.parent;
7414
7415		this.updateWorldMatrix( true, false );
7416
7417		_position$3.setFromMatrixPosition( this.matrixWorld );
7418
7419		if ( this.isCamera || this.isLight ) {
7420
7421			_m1$3.lookAt( _position$3, _target, this.up );
7422
7423		} else {
7424
7425			_m1$3.lookAt( _target, _position$3, this.up );
7426
7427		}
7428
7429		this.quaternion.setFromRotationMatrix( _m1$3 );
7430
7431		if ( parent ) {
7432
7433			_m1$3.extractRotation( parent.matrixWorld );
7434			_q1.setFromRotationMatrix( _m1$3 );
7435			this.quaternion.premultiply( _q1.invert() );
7436
7437		}
7438
7439	}
7440
7441	add( object ) {
7442
7443		if ( arguments.length > 1 ) {
7444
7445			for ( let i = 0; i < arguments.length; i ++ ) {
7446
7447				this.add( arguments[ i ] );
7448
7449			}
7450
7451			return this;
7452
7453		}
7454
7455		if ( object === this ) {
7456
7457			console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object );
7458			return this;
7459
7460		}
7461
7462		if ( object && object.isObject3D ) {
7463
7464			object.removeFromParent();
7465			object.parent = this;
7466			this.children.push( object );
7467
7468			object.dispatchEvent( _addedEvent );
7469
7470			_childaddedEvent.child = object;
7471			this.dispatchEvent( _childaddedEvent );
7472			_childaddedEvent.child = null;
7473
7474		} else {
7475
7476			console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object );
7477
7478		}
7479
7480		return this;
7481
7482	}
7483
7484	remove( object ) {
7485
7486		if ( arguments.length > 1 ) {
7487
7488			for ( let i = 0; i < arguments.length; i ++ ) {
7489
7490				this.remove( arguments[ i ] );
7491
7492			}
7493
7494			return this;
7495
7496		}
7497
7498		const index = this.children.indexOf( object );
7499
7500		if ( index !== - 1 ) {
7501
7502			object.parent = null;
7503			this.children.splice( index, 1 );
7504
7505			object.dispatchEvent( _removedEvent );
7506
7507			_childremovedEvent.child = object;
7508			this.dispatchEvent( _childremovedEvent );
7509			_childremovedEvent.child = null;
7510
7511		}
7512
7513		return this;
7514
7515	}
7516
7517	removeFromParent() {
7518
7519		const parent = this.parent;
7520
7521		if ( parent !== null ) {
7522
7523			parent.remove( this );
7524
7525		}
7526
7527		return this;
7528
7529	}
7530
7531	clear() {
7532
7533		return this.remove( ... this.children );
7534
7535	}
7536
7537	attach( object ) {
7538
7539		// adds object as a child of this, while maintaining the object's world transform
7540
7541		// Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
7542
7543		this.updateWorldMatrix( true, false );
7544
7545		_m1$3.copy( this.matrixWorld ).invert();
7546
7547		if ( object.parent !== null ) {
7548
7549			object.parent.updateWorldMatrix( true, false );
7550
7551			_m1$3.multiply( object.parent.matrixWorld );
7552
7553		}
7554
7555		object.applyMatrix4( _m1$3 );
7556
7557		object.removeFromParent();
7558		object.parent = this;
7559		this.children.push( object );
7560
7561		object.updateWorldMatrix( false, true );
7562
7563		object.dispatchEvent( _addedEvent );
7564
7565		_childaddedEvent.child = object;
7566		this.dispatchEvent( _childaddedEvent );
7567		_childaddedEvent.child = null;
7568
7569		return this;
7570
7571	}
7572
7573	getObjectById( id ) {
7574
7575		return this.getObjectByProperty( 'id', id );
7576
7577	}
7578
7579	getObjectByName( name ) {
7580
7581		return this.getObjectByProperty( 'name', name );
7582
7583	}
7584
7585	getObjectByProperty( name, value ) {
7586
7587		if ( this[ name ] === value ) return this;
7588
7589		for ( let i = 0, l = this.children.length; i < l; i ++ ) {
7590
7591			const child = this.children[ i ];
7592			const object = child.getObjectByProperty( name, value );
7593
7594			if ( object !== undefined ) {
7595
7596				return object;
7597
7598			}
7599
7600		}
7601
7602		return undefined;
7603
7604	}
7605
7606	getObjectsByProperty( name, value, result = [] ) {
7607
7608		if ( this[ name ] === value ) result.push( this );
7609
7610		const children = this.children;
7611
7612		for ( let i = 0, l = children.length; i < l; i ++ ) {
7613
7614			children[ i ].getObjectsByProperty( name, value, result );
7615
7616		}
7617
7618		return result;
7619
7620	}
7621
7622	getWorldPosition( target ) {
7623
7624		this.updateWorldMatrix( true, false );
7625
7626		return target.setFromMatrixPosition( this.matrixWorld );
7627
7628	}
7629
7630	getWorldQuaternion( target ) {
7631
7632		this.updateWorldMatrix( true, false );
7633
7634		this.matrixWorld.decompose( _position$3, target, _scale$2 );
7635
7636		return target;
7637
7638	}
7639
7640	getWorldScale( target ) {
7641
7642		this.updateWorldMatrix( true, false );
7643
7644		this.matrixWorld.decompose( _position$3, _quaternion$2, target );
7645
7646		return target;
7647
7648	}
7649
7650	getWorldDirection( target ) {
7651
7652		this.updateWorldMatrix( true, false );
7653
7654		const e = this.matrixWorld.elements;
7655
7656		return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
7657
7658	}
7659
7660	raycast( /* raycaster, intersects */ ) {}
7661
7662	traverse( callback ) {
7663
7664		callback( this );
7665
7666		const children = this.children;
7667
7668		for ( let i = 0, l = children.length; i < l; i ++ ) {
7669
7670			children[ i ].traverse( callback );
7671
7672		}
7673
7674	}
7675
7676	traverseVisible( callback ) {
7677
7678		if ( this.visible === false ) return;
7679
7680		callback( this );
7681
7682		const children = this.children;
7683
7684		for ( let i = 0, l = children.length; i < l; i ++ ) {
7685
7686			children[ i ].traverseVisible( callback );
7687
7688		}
7689
7690	}
7691
7692	traverseAncestors( callback ) {
7693
7694		const parent = this.parent;
7695
7696		if ( parent !== null ) {
7697
7698			callback( parent );
7699
7700			parent.traverseAncestors( callback );
7701
7702		}
7703
7704	}
7705
7706	updateMatrix() {
7707
7708		this.matrix.compose( this.position, this.quaternion, this.scale );
7709
7710		this.matrixWorldNeedsUpdate = true;
7711
7712	}
7713
7714	updateMatrixWorld( force ) {
7715
7716		if ( this.matrixAutoUpdate ) this.updateMatrix();
7717
7718		if ( this.matrixWorldNeedsUpdate || force ) {
7719
7720			if ( this.parent === null ) {
7721
7722				this.matrixWorld.copy( this.matrix );
7723
7724			} else {
7725
7726				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
7727
7728			}
7729
7730			this.matrixWorldNeedsUpdate = false;
vendor: 3,767 bytes, lines 7731-7892
7731
7732			force = true;
7733
7734		}
7735
7736		// update children
7737
7738		const children = this.children;
7739
7740		for ( let i = 0, l = children.length; i < l; i ++ ) {
7741
7742			const child = children[ i ];
7743
7744			if ( child.matrixWorldAutoUpdate === true || force === true ) {
7745
7746				child.updateMatrixWorld( force );
7747
7748			}
7749
7750		}
7751
7752	}
7753
7754	updateWorldMatrix( updateParents, updateChildren ) {
7755
7756		const parent = this.parent;
7757
7758		if ( updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true ) {
7759
7760			parent.updateWorldMatrix( true, false );
7761
7762		}
7763
7764		if ( this.matrixAutoUpdate ) this.updateMatrix();
7765
7766		if ( this.parent === null ) {
7767
7768			this.matrixWorld.copy( this.matrix );
7769
7770		} else {
7771
7772			this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
7773
7774		}
7775
7776		// update children
7777
7778		if ( updateChildren === true ) {
7779
7780			const children = this.children;
7781
7782			for ( let i = 0, l = children.length; i < l; i ++ ) {
7783
7784				const child = children[ i ];
7785
7786				if ( child.matrixWorldAutoUpdate === true ) {
7787
7788					child.updateWorldMatrix( false, true );
7789
7790				}
7791
7792			}
7793
7794		}
7795
7796	}
7797
7798	toJSON( meta ) {
7799
7800		// meta is a string when called from JSON.stringify
7801		const isRootObject = ( meta === undefined || typeof meta === 'string' );
7802
7803		const output = {};
7804
7805		// meta is a hash used to collect geometries, materials.
7806		// not providing it implies that this is the root object
7807		// being serialized.
7808		if ( isRootObject ) {
7809
7810			// initialize meta obj
7811			meta = {
7812				geometries: {},
7813				materials: {},
7814				textures: {},
7815				images: {},
7816				shapes: {},
7817				skeletons: {},
7818				animations: {},
7819				nodes: {}
7820			};
7821
7822			output.metadata = {
7823				version: 4.6,
7824				type: 'Object',
7825				generator: 'Object3D.toJSON'
7826			};
7827
7828		}
7829
7830		// standard Object3D serialization
7831
7832		const object = {};
7833
7834		object.uuid = this.uuid;
7835		object.type = this.type;
7836
7837		if ( this.name !== '' ) object.name = this.name;
7838		if ( this.castShadow === true ) object.castShadow = true;
7839		if ( this.receiveShadow === true ) object.receiveShadow = true;
7840		if ( this.visible === false ) object.visible = false;
7841		if ( this.frustumCulled === false ) object.frustumCulled = false;
7842		if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;
7843		if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
7844
7845		object.layers = this.layers.mask;
7846		object.matrix = this.matrix.toArray();
7847		object.up = this.up.toArray();
7848
7849		if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
7850
7851		// object specific properties
7852
7853		if ( this.isInstancedMesh ) {
7854
7855			object.type = 'InstancedMesh';
7856			object.count = this.count;
7857			object.instanceMatrix = this.instanceMatrix.toJSON();
7858			if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
7859
7860		}
7861
7862		if ( this.isBatchedMesh ) {
7863
7864			object.type = 'BatchedMesh';
7865			object.perObjectFrustumCulled = this.perObjectFrustumCulled;
7866			object.sortObjects = this.sortObjects;
7867
7868			object.drawRanges = this._drawRanges;
7869			object.reservedRanges = this._reservedRanges;
7870
7871			object.visibility = this._visibility;
7872			object.active = this._active;
7873			object.bounds = this._bounds.map( bound => ( {
7874				boxInitialized: bound.boxInitialized,
7875				boxMin: bound.box.min.toArray(),
7876				boxMax: bound.box.max.toArray(),
7877
7878				sphereInitialized: bound.sphereInitialized,
7879				sphereRadius: bound.sphere.radius,
7880				sphereCenter: bound.sphere.center.toArray()
7881			} ) );
7882
7883			object.maxGeometryCount = this._maxGeometryCount;
7884			object.maxVertexCount = this._maxVertexCount;
7885			object.maxIndexCount = this._maxIndexCount;
7886
7887			object.geometryInitialized = this._geometryInitialized;
7888			object.geometryCount = this._geometryCount;
7889
7890			object.matricesTexture = this._matricesTexture.toJSON( meta );
7891
7892			if ( this._colorsTexture !== null ) object.colorsTexture = this._color
vendor: 16,800 bytes, lines 7892-8585
7892sTexture.toJSON( meta );
7893
7894			if ( this.boundingSphere !== null ) {
7895
7896				object.boundingSphere = {
7897					center: object.boundingSphere.center.toArray(),
7898					radius: object.boundingSphere.radius
7899				};
7900
7901			}
7902
7903			if ( this.boundingBox !== null ) {
7904
7905				object.boundingBox = {
7906					min: object.boundingBox.min.toArray(),
7907					max: object.boundingBox.max.toArray()
7908				};
7909
7910			}
7911
7912		}
7913
7914		//
7915
7916		function serialize( library, element ) {
7917
7918			if ( library[ element.uuid ] === undefined ) {
7919
7920				library[ element.uuid ] = element.toJSON( meta );
7921
7922			}
7923
7924			return element.uuid;
7925
7926		}
7927
7928		if ( this.isScene ) {
7929
7930			if ( this.background ) {
7931
7932				if ( this.background.isColor ) {
7933
7934					object.background = this.background.toJSON();
7935
7936				} else if ( this.background.isTexture ) {
7937
7938					object.background = this.background.toJSON( meta ).uuid;
7939
7940				}
7941
7942			}
7943
7944			if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
7945
7946				object.environment = this.environment.toJSON( meta ).uuid;
7947
7948			}
7949
7950		} else if ( this.isMesh || this.isLine || this.isPoints ) {
7951
7952			object.geometry = serialize( meta.geometries, this.geometry );
7953
7954			const parameters = this.geometry.parameters;
7955
7956			if ( parameters !== undefined && parameters.shapes !== undefined ) {
7957
7958				const shapes = parameters.shapes;
7959
7960				if ( Array.isArray( shapes ) ) {
7961
7962					for ( let i = 0, l = shapes.length; i < l; i ++ ) {
7963
7964						const shape = shapes[ i ];
7965
7966						serialize( meta.shapes, shape );
7967
7968					}
7969
7970				} else {
7971
7972					serialize( meta.shapes, shapes );
7973
7974				}
7975
7976			}
7977
7978		}
7979
7980		if ( this.isSkinnedMesh ) {
7981
7982			object.bindMode = this.bindMode;
7983			object.bindMatrix = this.bindMatrix.toArray();
7984
7985			if ( this.skeleton !== undefined ) {
7986
7987				serialize( meta.skeletons, this.skeleton );
7988
7989				object.skeleton = this.skeleton.uuid;
7990
7991			}
7992
7993		}
7994
7995		if ( this.material !== undefined ) {
7996
7997			if ( Array.isArray( this.material ) ) {
7998
7999				const uuids = [];
8000
8001				for ( let i = 0, l = this.material.length; i < l; i ++ ) {
8002
8003					uuids.push( serialize( meta.materials, this.material[ i ] ) );
8004
8005				}
8006
8007				object.material = uuids;
8008
8009			} else {
8010
8011				object.material = serialize( meta.materials, this.material );
8012
8013			}
8014
8015		}
8016
8017		//
8018
8019		if ( this.children.length > 0 ) {
8020
8021			object.children = [];
8022
8023			for ( let i = 0; i < this.children.length; i ++ ) {
8024
8025				object.children.push( this.children[ i ].toJSON( meta ).object );
8026
8027			}
8028
8029		}
8030
8031		//
8032
8033		if ( this.animations.length > 0 ) {
8034
8035			object.animations = [];
8036
8037			for ( let i = 0; i < this.animations.length; i ++ ) {
8038
8039				const animation = this.animations[ i ];
8040
8041				object.animations.push( serialize( meta.animations, animation ) );
8042
8043			}
8044
8045		}
8046
8047		if ( isRootObject ) {
8048
8049			const geometries = extractFromCache( meta.geometries );
8050			const materials = extractFromCache( meta.materials );
8051			const textures = extractFromCache( meta.textures );
8052			const images = extractFromCache( meta.images );
8053			const shapes = extractFromCache( meta.shapes );
8054			const skeletons = extractFromCache( meta.skeletons );
8055			const animations = extractFromCache( meta.animations );
8056			const nodes = extractFromCache( meta.nodes );
8057
8058			if ( geometries.length > 0 ) output.geometries = geometries;
8059			if ( materials.length > 0 ) output.materials = materials;
8060			if ( textures.length > 0 ) output.textures = textures;
8061			if ( images.length > 0 ) output.images = images;
8062			if ( shapes.length > 0 ) output.shapes = shapes;
8063			if ( skeletons.length > 0 ) output.skeletons = skeletons;
8064			if ( animations.length > 0 ) output.animations = animations;
8065			if ( nodes.length > 0 ) output.nodes = nodes;
8066
8067		}
8068
8069		output.object = object;
8070
8071		return output;
8072
8073		// extract data from the cache hash
8074		// remove metadata on each item
8075		// and return as array
8076		function extractFromCache( cache ) {
8077
8078			const values = [];
8079			for ( const key in cache ) {
8080
8081				const data = cache[ key ];
8082				delete data.metadata;
8083				values.push( data );
8084
8085			}
8086
8087			return values;
8088
8089		}
8090
8091	}
8092
8093	clone( recursive ) {
8094
8095		return new this.constructor().copy( this, recursive );
8096
8097	}
8098
8099	copy( source, recursive = true ) {
8100
8101		this.name = source.name;
8102
8103		this.up.copy( source.up );
8104
8105		this.position.copy( source.position );
8106		this.rotation.order = source.rotation.order;
8107		this.quaternion.copy( source.quaternion );
8108		this.scale.copy( source.scale );
8109
8110		this.matrix.copy( source.matrix );
8111		this.matrixWorld.copy( source.matrixWorld );
8112
8113		this.matrixAutoUpdate = source.matrixAutoUpdate;
8114
8115		this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
8116		this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
8117
8118		this.layers.mask = source.layers.mask;
8119		this.visible = source.visible;
8120
8121		this.castShadow = source.castShadow;
8122		this.receiveShadow = source.receiveShadow;
8123
8124		this.frustumCulled = source.frustumCulled;
8125		this.renderOrder = source.renderOrder;
8126
8127		this.animations = source.animations.slice();
8128
8129		this.userData = JSON.parse( JSON.stringify( source.userData ) );
8130
8131		if ( recursive === true ) {
8132
8133			for ( let i = 0; i < source.children.length; i ++ ) {
8134
8135				const child = source.children[ i ];
8136				this.add( child.clone() );
8137
8138			}
8139
8140		}
8141
8142		return this;
8143
8144	}
8145
8146}
8147
8148Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
8149Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
8150Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
8151
8152const _v0$1 = /*@__PURE__*/ new Vector3();
8153const _v1$3 = /*@__PURE__*/ new Vector3();
8154const _v2$2 = /*@__PURE__*/ new Vector3();
8155const _v3$2 = /*@__PURE__*/ new Vector3();
8156
8157const _vab = /*@__PURE__*/ new Vector3();
8158const _vac = /*@__PURE__*/ new Vector3();
8159const _vbc = /*@__PURE__*/ new Vector3();
8160const _vap = /*@__PURE__*/ new Vector3();
8161const _vbp = /*@__PURE__*/ new Vector3();
8162const _vcp = /*@__PURE__*/ new Vector3();
8163
8164class Triangle {
8165
8166	constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) {
8167
8168		this.a = a;
8169		this.b = b;
8170		this.c = c;
8171
8172	}
8173
8174	static getNormal( a, b, c, target ) {
8175
8176		target.subVectors( c, b );
8177		_v0$1.subVectors( a, b );
8178		target.cross( _v0$1 );
8179
8180		const targetLengthSq = target.lengthSq();
8181		if ( targetLengthSq > 0 ) {
8182
8183			return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
8184
8185		}
8186
8187		return target.set( 0, 0, 0 );
8188
8189	}
8190
8191	// static/instance method to calculate barycentric coordinates
8192	// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
8193	static getBarycoord( point, a, b, c, target ) {
8194
8195		_v0$1.subVectors( c, a );
8196		_v1$3.subVectors( b, a );
8197		_v2$2.subVectors( point, a );
8198
8199		const dot00 = _v0$1.dot( _v0$1 );
8200		const dot01 = _v0$1.dot( _v1$3 );
8201		const dot02 = _v0$1.dot( _v2$2 );
8202		const dot11 = _v1$3.dot( _v1$3 );
8203		const dot12 = _v1$3.dot( _v2$2 );
8204
8205		const denom = ( dot00 * dot11 - dot01 * dot01 );
8206
8207		// collinear or singular triangle
8208		if ( denom === 0 ) {
8209
8210			target.set( 0, 0, 0 );
8211			return null;
8212
8213		}
8214
8215		const invDenom = 1 / denom;
8216		const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
8217		const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
8218
8219		// barycentric coordinates must always sum to 1
8220		return target.set( 1 - u - v, v, u );
8221
8222	}
8223
8224	static containsPoint( point, a, b, c ) {
8225
8226		// if the triangle is degenerate then we can't contain a point
8227		if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) {
8228
8229			return false;
8230
8231		}
8232
8233		return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 );
8234
8235	}
8236
8237	static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) {
8238
8239		if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) {
8240
8241			target.x = 0;
8242			target.y = 0;
8243			if ( 'z' in target ) target.z = 0;
8244			if ( 'w' in target ) target.w = 0;
8245			return null;
8246
8247		}
8248
8249		target.setScalar( 0 );
8250		target.addScaledVector( v1, _v3$2.x );
8251		target.addScaledVector( v2, _v3$2.y );
8252		target.addScaledVector( v3, _v3$2.z );
8253
8254		return target;
8255
8256	}
8257
8258	static isFrontFacing( a, b, c, direction ) {
8259
8260		_v0$1.subVectors( c, b );
8261		_v1$3.subVectors( a, b );
8262
8263		// strictly front facing
8264		return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;
8265
8266	}
8267
8268	set( a, b, c ) {
8269
8270		this.a.copy( a );
8271		this.b.copy( b );
8272		this.c.copy( c );
8273
8274		return this;
8275
8276	}
8277
8278	setFromPointsAndIndices( points, i0, i1, i2 ) {
8279
8280		this.a.copy( points[ i0 ] );
8281		this.b.copy( points[ i1 ] );
8282		this.c.copy( points[ i2 ] );
8283
8284		return this;
8285
8286	}
8287
8288	setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
8289
8290		this.a.fromBufferAttribute( attribute, i0 );
8291		this.b.fromBufferAttribute( attribute, i1 );
8292		this.c.fromBufferAttribute( attribute, i2 );
8293
8294		return this;
8295
8296	}
8297
8298	clone() {
8299
8300		return new this.constructor().copy( this );
8301
8302	}
8303
8304	copy( triangle ) {
8305
8306		this.a.copy( triangle.a );
8307		this.b.copy( triangle.b );
8308		this.c.copy( triangle.c );
8309
8310		return this;
8311
8312	}
8313
8314	getArea() {
8315
8316		_v0$1.subVectors( this.c, this.b );
8317		_v1$3.subVectors( this.a, this.b );
8318
8319		return _v0$1.cross( _v1$3 ).length() * 0.5;
8320
8321	}
8322
8323	getMidpoint( target ) {
8324
8325		return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
8326
8327	}
8328
8329	getNormal( target ) {
8330
8331		return Triangle.getNormal( this.a, this.b, this.c, target );
8332
8333	}
8334
8335	getPlane( target ) {
8336
8337		return target.setFromCoplanarPoints( this.a, this.b, this.c );
8338
8339	}
8340
8341	getBarycoord( point, target ) {
8342
8343		return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
8344
8345	}
8346
8347	getInterpolation( point, v1, v2, v3, target ) {
8348
8349		return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target );
8350
8351	}
8352
8353	containsPoint( point ) {
8354
8355		return Triangle.containsPoint( point, this.a, this.b, this.c );
8356
8357	}
8358
8359	isFrontFacing( direction ) {
8360
8361		return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
8362
8363	}
8364
8365	intersectsBox( box ) {
8366
8367		return box.intersectsTriangle( this );
8368
8369	}
8370
8371	closestPointToPoint( p, target ) {
8372
8373		const a = this.a, b = this.b, c = this.c;
8374		let v, w;
8375
8376		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
8377		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
8378		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
8379		// basically, we're distinguishing which of the voronoi regions of the triangle
8380		// the point lies in with the minimum amount of redundant computation.
8381
8382		_vab.subVectors( b, a );
8383		_vac.subVectors( c, a );
8384		_vap.subVectors( p, a );
8385		const d1 = _vab.dot( _vap );
8386		const d2 = _vac.dot( _vap );
8387		if ( d1 <= 0 && d2 <= 0 ) {
8388
8389			// vertex region of A; barycentric coords (1, 0, 0)
8390			return target.copy( a );
8391
8392		}
8393
8394		_vbp.subVectors( p, b );
8395		const d3 = _vab.dot( _vbp );
8396		const d4 = _vac.dot( _vbp );
8397		if ( d3 >= 0 && d4 <= d3 ) {
8398
8399			// vertex region of B; barycentric coords (0, 1, 0)
8400			return target.copy( b );
8401
8402		}
8403
8404		const vc = d1 * d4 - d3 * d2;
8405		if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
8406
8407			v = d1 / ( d1 - d3 );
8408			// edge region of AB; barycentric coords (1-v, v, 0)
8409			return target.copy( a ).addScaledVector( _vab, v );
8410
8411		}
8412
8413		_vcp.subVectors( p, c );
8414		const d5 = _vab.dot( _vcp );
8415		const d6 = _vac.dot( _vcp );
8416		if ( d6 >= 0 && d5 <= d6 ) {
8417
8418			// vertex region of C; barycentric coords (0, 0, 1)
8419			return target.copy( c );
8420
8421		}
8422
8423		const vb = d5 * d2 - d1 * d6;
8424		if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
8425
8426			w = d2 / ( d2 - d6 );
8427			// edge region of AC; barycentric coords (1-w, 0, w)
8428			return target.copy( a ).addScaledVector( _vac, w );
8429
8430		}
8431
8432		const va = d3 * d6 - d5 * d4;
8433		if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
8434
8435			_vbc.subVectors( c, b );
8436			w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
8437			// edge region of BC; barycentric coords (0, 1-w, w)
8438			return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
8439
8440		}
8441
8442		// face region
8443		const denom = 1 / ( va + vb + vc );
8444		// u = va * denom
8445		v = vb * denom;
8446		w = vc * denom;
8447
8448		return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
8449
8450	}
8451
8452	equals( triangle ) {
8453
8454		return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
8455
8456	}
8457
8458}
8459
8460const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
8461	'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
8462	'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
8463	'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
8464	'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
8465	'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
8466	'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
8467	'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
8468	'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
8469	'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
8470	'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
8471	'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
8472	'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
8473	'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
8474	'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
8475	'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
8476	'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
8477	'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
8478	'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
8479	'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
8480	'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
8481	'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
8482	'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
8483	'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
8484
8485const _hslA = { h: 0, s: 0, l: 0 };
8486const _hslB = { h: 0, s: 0, l: 0 };
8487
8488function hue2rgb( p, q, t ) {
8489
8490	if ( t < 0 ) t += 1;
8491	if ( t > 1 ) t -= 1;
8492	if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
8493	if ( t < 1 / 2 ) return q;
8494	if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
8495	return p;
8496
8497}
8498
8499class Color {
8500
8501	constructor( r, g, b ) {
8502
8503		this.isColor = true;
8504
8505		this.r = 1;
8506		this.g = 1;
8507		this.b = 1;
8508
8509		return this.set( r, g, b );
8510
8511	}
8512
8513	set( r, g, b ) {
8514
8515		if ( g === undefined && b === undefined ) {
8516
8517			// r is THREE.Color, hex or string
8518
8519			const value = r;
8520
8521			if ( value && value.isColor ) {
8522
8523				this.copy( value );
8524
8525			} else if ( typeof value === 'number' ) {
8526
8527				this.setHex( value );
8528
8529			} else if ( typeof value === 'string' ) {
8530
8531				this.setStyle( value );
8532
8533			}
8534
8535		} else {
8536
8537			this.setRGB( r, g, b );
8538
8539		}
8540
8541		return this;
8542
8543	}
8544
8545	setScalar( scalar ) {
8546
8547		this.r = scalar;
8548		this.g = scalar;
8549		this.b = scalar;
8550
8551		return this;
8552
8553	}
8554
8555	setHex( hex, colorSpace = SRGBColorSpace ) {
8556
8557		hex = Math.floor( hex );
8558
8559		this.r = ( hex >> 16 & 255 ) / 255;
8560		this.g = ( hex >> 8 & 255 ) / 255;
8561		this.b = ( hex & 255 ) / 255;
8562
8563		ColorManagement.toWorkingColorSpace( this, colorSpace );
8564
8565		return this;
8566
8567	}
8568
8569	setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) {
8570
8571		this.r = r;
8572		this.g = g;
8573		this.b = b;
8574
8575		ColorManagement.toWorkingColorSpace( this, colorSpace );
8576
8577		return this;
8578
8579	}
8580
8581	setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) {
8582
8583		// h,s,l ranges are in 0.0 - 1.0
8584		h = euclideanModulo( h, 1 );
8585		s = clamp
vendor: 13,496 bytes, lines 8585-9293
8585( s, 0, 1 );
8586		l = clamp( l, 0, 1 );
8587
8588		if ( s === 0 ) {
8589
8590			this.r = this.g = this.b = l;
8591
8592		} else {
8593
8594			const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
8595			const q = ( 2 * l ) - p;
8596
8597			this.r = hue2rgb( q, p, h + 1 / 3 );
8598			this.g = hue2rgb( q, p, h );
8599			this.b = hue2rgb( q, p, h - 1 / 3 );
8600
8601		}
8602
8603		ColorManagement.toWorkingColorSpace( this, colorSpace );
8604
8605		return this;
8606
8607	}
8608
8609	setStyle( style, colorSpace = SRGBColorSpace ) {
8610
8611		function handleAlpha( string ) {
8612
8613			if ( string === undefined ) return;
8614
8615			if ( parseFloat( string ) < 1 ) {
8616
8617				console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );
8618
8619			}
8620
8621		}
8622
8623
8624		let m;
8625
8626		if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) {
8627
8628			// rgb / hsl
8629
8630			let color;
8631			const name = m[ 1 ];
8632			const components = m[ 2 ];
8633
8634			switch ( name ) {
8635
8636				case 'rgb':
8637				case 'rgba':
8638
8639					if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8640
8641						// rgb(255,0,0) rgba(255,0,0,0.5)
8642
8643						handleAlpha( color[ 4 ] );
8644
8645						return this.setRGB(
8646							Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255,
8647							Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255,
8648							Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255,
8649							colorSpace
8650						);
8651
8652					}
8653
8654					if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8655
8656						// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
8657
8658						handleAlpha( color[ 4 ] );
8659
8660						return this.setRGB(
8661							Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100,
8662							Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100,
8663							Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100,
8664							colorSpace
8665						);
8666
8667					}
8668
8669					break;
8670
8671				case 'hsl':
8672				case 'hsla':
8673
8674					if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
8675
8676						// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
8677
8678						handleAlpha( color[ 4 ] );
8679
8680						return this.setHSL(
8681							parseFloat( color[ 1 ] ) / 360,
8682							parseFloat( color[ 2 ] ) / 100,
8683							parseFloat( color[ 3 ] ) / 100,
8684							colorSpace
8685						);
8686
8687					}
8688
8689					break;
8690
8691				default:
8692
8693					console.warn( 'THREE.Color: Unknown color model ' + style );
8694
8695			}
8696
8697		} else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
8698
8699			// hex color
8700
8701			const hex = m[ 1 ];
8702			const size = hex.length;
8703
8704			if ( size === 3 ) {
8705
8706				// #ff0
8707				return this.setRGB(
8708					parseInt( hex.charAt( 0 ), 16 ) / 15,
8709					parseInt( hex.charAt( 1 ), 16 ) / 15,
8710					parseInt( hex.charAt( 2 ), 16 ) / 15,
8711					colorSpace
8712				);
8713
8714			} else if ( size === 6 ) {
8715
8716				// #ff0000
8717				return this.setHex( parseInt( hex, 16 ), colorSpace );
8718
8719			} else {
8720
8721				console.warn( 'THREE.Color: Invalid hex color ' + style );
8722
8723			}
8724
8725		} else if ( style && style.length > 0 ) {
8726
8727			return this.setColorName( style, colorSpace );
8728
8729		}
8730
8731		return this;
8732
8733	}
8734
8735	setColorName( style, colorSpace = SRGBColorSpace ) {
8736
8737		// color keywords
8738		const hex = _colorKeywords[ style.toLowerCase() ];
8739
8740		if ( hex !== undefined ) {
8741
8742			// red
8743			this.setHex( hex, colorSpace );
8744
8745		} else {
8746
8747			// unknown color
8748			console.warn( 'THREE.Color: Unknown color ' + style );
8749
8750		}
8751
8752		return this;
8753
8754	}
8755
8756	clone() {
8757
8758		return new this.constructor( this.r, this.g, this.b );
8759
8760	}
8761
8762	copy( color ) {
8763
8764		this.r = color.r;
8765		this.g = color.g;
8766		this.b = color.b;
8767
8768		return this;
8769
8770	}
8771
8772	copySRGBToLinear( color ) {
8773
8774		this.r = SRGBToLinear( color.r );
8775		this.g = SRGBToLinear( color.g );
8776		this.b = SRGBToLinear( color.b );
8777
8778		return this;
8779
8780	}
8781
8782	copyLinearToSRGB( color ) {
8783
8784		this.r = LinearToSRGB( color.r );
8785		this.g = LinearToSRGB( color.g );
8786		this.b = LinearToSRGB( color.b );
8787
8788		return this;
8789
8790	}
8791
8792	convertSRGBToLinear() {
8793
8794		this.copySRGBToLinear( this );
8795
8796		return this;
8797
8798	}
8799
8800	convertLinearToSRGB() {
8801
8802		this.copyLinearToSRGB( this );
8803
8804		return this;
8805
8806	}
8807
8808	getHex( colorSpace = SRGBColorSpace ) {
8809
8810		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8811
8812		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 ) );
8813
8814	}
8815
8816	getHexString( colorSpace = SRGBColorSpace ) {
8817
8818		return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 );
8819
8820	}
8821
8822	getHSL( target, colorSpace = ColorManagement.workingColorSpace ) {
8823
8824		// h,s,l ranges are in 0.0 - 1.0
8825
8826		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8827
8828		const r = _color.r, g = _color.g, b = _color.b;
8829
8830		const max = Math.max( r, g, b );
8831		const min = Math.min( r, g, b );
8832
8833		let hue, saturation;
8834		const lightness = ( min + max ) / 2.0;
8835
8836		if ( min === max ) {
8837
8838			hue = 0;
8839			saturation = 0;
8840
8841		} else {
8842
8843			const delta = max - min;
8844
8845			saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
8846
8847			switch ( max ) {
8848
8849				case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
8850				case g: hue = ( b - r ) / delta + 2; break;
8851				case b: hue = ( r - g ) / delta + 4; break;
8852
8853			}
8854
8855			hue /= 6;
8856
8857		}
8858
8859		target.h = hue;
8860		target.s = saturation;
8861		target.l = lightness;
8862
8863		return target;
8864
8865	}
8866
8867	getRGB( target, colorSpace = ColorManagement.workingColorSpace ) {
8868
8869		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8870
8871		target.r = _color.r;
8872		target.g = _color.g;
8873		target.b = _color.b;
8874
8875		return target;
8876
8877	}
8878
8879	getStyle( colorSpace = SRGBColorSpace ) {
8880
8881		ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace );
8882
8883		const r = _color.r, g = _color.g, b = _color.b;
8884
8885		if ( colorSpace !== SRGBColorSpace ) {
8886
8887			// Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
8888			return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`;
8889
8890		}
8891
8892		return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`;
8893
8894	}
8895
8896	offsetHSL( h, s, l ) {
8897
8898		this.getHSL( _hslA );
8899
8900		return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l );
8901
8902	}
8903
8904	add( color ) {
8905
8906		this.r += color.r;
8907		this.g += color.g;
8908		this.b += color.b;
8909
8910		return this;
8911
8912	}
8913
8914	addColors( color1, color2 ) {
8915
8916		this.r = color1.r + color2.r;
8917		this.g = color1.g + color2.g;
8918		this.b = color1.b + color2.b;
8919
8920		return this;
8921
8922	}
8923
8924	addScalar( s ) {
8925
8926		this.r += s;
8927		this.g += s;
8928		this.b += s;
8929
8930		return this;
8931
8932	}
8933
8934	sub( color ) {
8935
8936		this.r = Math.max( 0, this.r - color.r );
8937		this.g = Math.max( 0, this.g - color.g );
8938		this.b = Math.max( 0, this.b - color.b );
8939
8940		return this;
8941
8942	}
8943
8944	multiply( color ) {
8945
8946		this.r *= color.r;
8947		this.g *= color.g;
8948		this.b *= color.b;
8949
8950		return this;
8951
8952	}
8953
8954	multiplyScalar( s ) {
8955
8956		this.r *= s;
8957		this.g *= s;
8958		this.b *= s;
8959
8960		return this;
8961
8962	}
8963
8964	lerp( color, alpha ) {
8965
8966		this.r += ( color.r - this.r ) * alpha;
8967		this.g += ( color.g - this.g ) * alpha;
8968		this.b += ( color.b - this.b ) * alpha;
8969
8970		return this;
8971
8972	}
8973
8974	lerpColors( color1, color2, alpha ) {
8975
8976		this.r = color1.r + ( color2.r - color1.r ) * alpha;
8977		this.g = color1.g + ( color2.g - color1.g ) * alpha;
8978		this.b = color1.b + ( color2.b - color1.b ) * alpha;
8979
8980		return this;
8981
8982	}
8983
8984	lerpHSL( color, alpha ) {
8985
8986		this.getHSL( _hslA );
8987		color.getHSL( _hslB );
8988
8989		const h = lerp( _hslA.h, _hslB.h, alpha );
8990		const s = lerp( _hslA.s, _hslB.s, alpha );
8991		const l = lerp( _hslA.l, _hslB.l, alpha );
8992
8993		this.setHSL( h, s, l );
8994
8995		return this;
8996
8997	}
8998
8999	setFromVector3( v ) {
9000
9001		this.r = v.x;
9002		this.g = v.y;
9003		this.b = v.z;
9004
9005		return this;
9006
9007	}
9008
9009	applyMatrix3( m ) {
9010
9011		const r = this.r, g = this.g, b = this.b;
9012		const e = m.elements;
9013
9014		this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b;
9015		this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b;
9016		this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b;
9017
9018		return this;
9019
9020	}
9021
9022	equals( c ) {
9023
9024		return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
9025
9026	}
9027
9028	fromArray( array, offset = 0 ) {
9029
9030		this.r = array[ offset ];
9031		this.g = array[ offset + 1 ];
9032		this.b = array[ offset + 2 ];
9033
9034		return this;
9035
9036	}
9037
9038	toArray( array = [], offset = 0 ) {
9039
9040		array[ offset ] = this.r;
9041		array[ offset + 1 ] = this.g;
9042		array[ offset + 2 ] = this.b;
9043
9044		return array;
9045
9046	}
9047
9048	fromBufferAttribute( attribute, index ) {
9049
9050		this.r = attribute.getX( index );
9051		this.g = attribute.getY( index );
9052		this.b = attribute.getZ( index );
9053
9054		return this;
9055
9056	}
9057
9058	toJSON() {
9059
9060		return this.getHex();
9061
9062	}
9063
9064	*[ Symbol.iterator ]() {
9065
9066		yield this.r;
9067		yield this.g;
9068		yield this.b;
9069
9070	}
9071
9072}
9073
9074const _color = /*@__PURE__*/ new Color();
9075
9076Color.NAMES = _colorKeywords;
9077
9078let _materialId = 0;
9079
9080class Material extends EventDispatcher {
9081
9082	constructor() {
9083
9084		super();
9085
9086		this.isMaterial = true;
9087
9088		Object.defineProperty( this, 'id', { value: _materialId ++ } );
9089
9090		this.uuid = generateUUID();
9091
9092		this.name = '';
9093		this.type = 'Material';
9094
9095		this.blending = NormalBlending;
9096		this.side = FrontSide;
9097		this.vertexColors = false;
9098
9099		this.opacity = 1;
9100		this.transparent = false;
9101		this.alphaHash = false;
9102
9103		this.blendSrc = SrcAlphaFactor;
9104		this.blendDst = OneMinusSrcAlphaFactor;
9105		this.blendEquation = AddEquation;
9106		this.blendSrcAlpha = null;
9107		this.blendDstAlpha = null;
9108		this.blendEquationAlpha = null;
9109		this.blendColor = new Color( 0, 0, 0 );
9110		this.blendAlpha = 0;
9111
9112		this.depthFunc = LessEqualDepth;
9113		this.depthTest = true;
9114		this.depthWrite = true;
9115
9116		this.stencilWriteMask = 0xff;
9117		this.stencilFunc = AlwaysStencilFunc;
9118		this.stencilRef = 0;
9119		this.stencilFuncMask = 0xff;
9120		this.stencilFail = KeepStencilOp;
9121		this.stencilZFail = KeepStencilOp;
9122		this.stencilZPass = KeepStencilOp;
9123		this.stencilWrite = false;
9124
9125		this.clippingPlanes = null;
9126		this.clipIntersection = false;
9127		this.clipShadows = false;
9128
9129		this.shadowSide = null;
9130
9131		this.colorWrite = true;
9132
9133		this.precision = null; // override the renderer's default precision for this material
9134
9135		this.polygonOffset = false;
9136		this.polygonOffsetFactor = 0;
9137		this.polygonOffsetUnits = 0;
9138
9139		this.dithering = false;
9140
9141		this.alphaToCoverage = false;
9142		this.premultipliedAlpha = false;
9143		this.forceSinglePass = false;
9144
9145		this.visible = true;
9146
9147		this.toneMapped = true;
9148
9149		this.userData = {};
9150
9151		this.version = 0;
9152
9153		this._alphaTest = 0;
9154
9155	}
9156
9157	get alphaTest() {
9158
9159		return this._alphaTest;
9160
9161	}
9162
9163	set alphaTest( value ) {
9164
9165		if ( this._alphaTest > 0 !== value > 0 ) {
9166
9167			this.version ++;
9168
9169		}
9170
9171		this._alphaTest = value;
9172
9173	}
9174
9175	onBuild( /* shaderobject, renderer */ ) {}
9176
9177	onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {}
9178
9179	onBeforeCompile( /* shaderobject, renderer */ ) {}
9180
9181	customProgramCacheKey() {
9182
9183		return this.onBeforeCompile.toString();
9184
9185	}
9186
9187	setValues( values ) {
9188
9189		if ( values === undefined ) return;
9190
9191		for ( const key in values ) {
9192
9193			const newValue = values[ key ];
9194
9195			if ( newValue === undefined ) {
9196
9197				console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` );
9198				continue;
9199
9200			}
9201
9202			const currentValue = this[ key ];
9203
9204			if ( currentValue === undefined ) {
9205
9206				console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` );
9207				continue;
9208
9209			}
9210
9211			if ( currentValue && currentValue.isColor ) {
9212
9213				currentValue.set( newValue );
9214
9215			} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
9216
9217				currentValue.copy( newValue );
9218
9219			} else {
9220
9221				this[ key ] = newValue;
9222
9223			}
9224
9225		}
9226
9227	}
9228
9229	toJSON( meta ) {
9230
9231		const isRootObject = ( meta === undefined || typeof meta === 'string' );
9232
9233		if ( isRootObject ) {
9234
9235			meta = {
9236				textures: {},
9237				images: {}
9238			};
9239
9240		}
9241
9242		const data = {
9243			metadata: {
9244				version: 4.6,
9245				type: 'Material',
9246				generator: 'Material.toJSON'
9247			}
9248		};
9249
9250		// standard Material serialization
9251		data.uuid = this.uuid;
9252		data.type = this.type;
9253
9254		if ( this.name !== '' ) data.name = this.name;
9255
9256		if ( this.color && this.color.isColor ) data.color = this.color.getHex();
9257
9258		if ( this.roughness !== undefined ) data.roughness = this.roughness;
9259		if ( this.metalness !== undefined ) data.metalness = this.metalness;
9260
9261		if ( this.sheen !== undefined ) data.sheen = this.sheen;
9262		if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
9263		if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness;
9264		if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
9265		if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
9266
9267		if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
9268		if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity;
9269		if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
9270		if ( this.shininess !== undefined ) data.shininess = this.shininess;
9271		if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
9272		if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
9273
9274		if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
9275
9276			data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
9277
9278		}
9279
9280		if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
9281
9282			data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
9283
9284		}
9285
9286		if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
9287
9288			data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
9289			data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
9290
9291		}
9292
9293		if ( this.dispersion !== undefined ) data.dispersion = this.dispersion;
vendor: 12,287 bytes, lines 9293-9674
9293
9294
9295		if ( this.iridescence !== undefined ) data.iridescence = this.iridescence;
9296		if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR;
9297		if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
9298
9299		if ( this.iridescenceMap && this.iridescenceMap.isTexture ) {
9300
9301			data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid;
9302
9303		}
9304
9305		if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) {
9306
9307			data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid;
9308
9309		}
9310
9311		if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy;
9312		if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation;
9313
9314		if ( this.anisotropyMap && this.anisotropyMap.isTexture ) {
9315
9316			data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid;
9317
9318		}
9319
9320		if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
9321		if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
9322		if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
9323
9324		if ( this.lightMap && this.lightMap.isTexture ) {
9325
9326			data.lightMap = this.lightMap.toJSON( meta ).uuid;
9327			data.lightMapIntensity = this.lightMapIntensity;
9328
9329		}
9330
9331		if ( this.aoMap && this.aoMap.isTexture ) {
9332
9333			data.aoMap = this.aoMap.toJSON( meta ).uuid;
9334			data.aoMapIntensity = this.aoMapIntensity;
9335
9336		}
9337
9338		if ( this.bumpMap && this.bumpMap.isTexture ) {
9339
9340			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
9341			data.bumpScale = this.bumpScale;
9342
9343		}
9344
9345		if ( this.normalMap && this.normalMap.isTexture ) {
9346
9347			data.normalMap = this.normalMap.toJSON( meta ).uuid;
9348			data.normalMapType = this.normalMapType;
9349			data.normalScale = this.normalScale.toArray();
9350
9351		}
9352
9353		if ( this.displacementMap && this.displacementMap.isTexture ) {
9354
9355			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
9356			data.displacementScale = this.displacementScale;
9357			data.displacementBias = this.displacementBias;
9358
9359		}
9360
9361		if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
9362		if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
9363
9364		if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
9365		if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
9366		if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
9367		if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
9368
9369		if ( this.envMap && this.envMap.isTexture ) {
9370
9371			data.envMap = this.envMap.toJSON( meta ).uuid;
9372
9373			if ( this.combine !== undefined ) data.combine = this.combine;
9374
9375		}
9376
9377		if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray();
9378		if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
9379		if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity;
9380		if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio;
9381
9382		if ( this.gradientMap && this.gradientMap.isTexture ) {
9383
9384			data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
9385
9386		}
9387
9388		if ( this.transmission !== undefined ) data.transmission = this.transmission;
9389		if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
9390		if ( this.thickness !== undefined ) data.thickness = this.thickness;
9391		if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
9392		if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance;
9393		if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
9394
9395		if ( this.size !== undefined ) data.size = this.size;
9396		if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide;
9397		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
9398
9399		if ( this.blending !== NormalBlending ) data.blending = this.blending;
9400		if ( this.side !== FrontSide ) data.side = this.side;
9401		if ( this.vertexColors === true ) data.vertexColors = true;
9402
9403		if ( this.opacity < 1 ) data.opacity = this.opacity;
9404		if ( this.transparent === true ) data.transparent = true;
9405
9406		if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc;
9407		if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst;
9408		if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation;
9409		if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha;
9410		if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha;
9411		if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha;
9412		if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex();
9413		if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha;
9414
9415		if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc;
9416		if ( this.depthTest === false ) data.depthTest = this.depthTest;
9417		if ( this.depthWrite === false ) data.depthWrite = this.depthWrite;
9418		if ( this.colorWrite === false ) data.colorWrite = this.colorWrite;
9419
9420		if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask;
9421		if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc;
9422		if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef;
9423		if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask;
9424		if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail;
9425		if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail;
9426		if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass;
9427		if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite;
9428
9429		// rotation (SpriteMaterial)
9430		if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation;
9431
9432		if ( this.polygonOffset === true ) data.polygonOffset = true;
9433		if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
9434		if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
9435
9436		if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth;
9437		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
9438		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
9439		if ( this.scale !== undefined ) data.scale = this.scale;
9440
9441		if ( this.dithering === true ) data.dithering = true;
9442
9443		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
9444		if ( this.alphaHash === true ) data.alphaHash = true;
9445		if ( this.alphaToCoverage === true ) data.alphaToCoverage = true;
9446		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true;
9447		if ( this.forceSinglePass === true ) data.forceSinglePass = true;
9448
9449		if ( this.wireframe === true ) data.wireframe = true;
9450		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
9451		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
9452		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
9453
9454		if ( this.flatShading === true ) data.flatShading = true;
9455
9456		if ( this.visible === false ) data.visible = false;
9457
9458		if ( this.toneMapped === false ) data.toneMapped = false;
9459
9460		if ( this.fog === false ) data.fog = false;
9461
9462		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
9463
9464		// TODO: Copied from Object3D.toJSON
9465
9466		function extractFromCache( cache ) {
9467
9468			const values = [];
9469
9470			for ( const key in cache ) {
9471
9472				const data = cache[ key ];
9473				delete data.metadata;
9474				values.push( data );
9475
9476			}
9477
9478			return values;
9479
9480		}
9481
9482		if ( isRootObject ) {
9483
9484			const textures = extractFromCache( meta.textures );
9485			const images = extractFromCache( meta.images );
9486
9487			if ( textures.length > 0 ) data.textures = textures;
9488			if ( images.length > 0 ) data.images = images;
9489
9490		}
9491
9492		return data;
9493
9494	}
9495
9496	clone() {
9497
9498		return new this.constructor().copy( this );
9499
9500	}
9501
9502	copy( source ) {
9503
9504		this.name = source.name;
9505
9506		this.blending = source.blending;
9507		this.side = source.side;
9508		this.vertexColors = source.vertexColors;
9509
9510		this.opacity = source.opacity;
9511		this.transparent = source.transparent;
9512
9513		this.blendSrc = source.blendSrc;
9514		this.blendDst = source.blendDst;
9515		this.blendEquation = source.blendEquation;
9516		this.blendSrcAlpha = source.blendSrcAlpha;
9517		this.blendDstAlpha = source.blendDstAlpha;
9518		this.blendEquationAlpha = source.blendEquationAlpha;
9519		this.blendColor.copy( source.blendColor );
9520		this.blendAlpha = source.blendAlpha;
9521
9522		this.depthFunc = source.depthFunc;
9523		this.depthTest = source.depthTest;
9524		this.depthWrite = source.depthWrite;
9525
9526		this.stencilWriteMask = source.stencilWriteMask;
9527		this.stencilFunc = source.stencilFunc;
9528		this.stencilRef = source.stencilRef;
9529		this.stencilFuncMask = source.stencilFuncMask;
9530		this.stencilFail = source.stencilFail;
9531		this.stencilZFail = source.stencilZFail;
9532		this.stencilZPass = source.stencilZPass;
9533		this.stencilWrite = source.stencilWrite;
9534
9535		const srcPlanes = source.clippingPlanes;
9536		let dstPlanes = null;
9537
9538		if ( srcPlanes !== null ) {
9539
9540			const n = srcPlanes.length;
9541			dstPlanes = new Array( n );
9542
9543			for ( let i = 0; i !== n; ++ i ) {
9544
9545				dstPlanes[ i ] = srcPlanes[ i ].clone();
9546
9547			}
9548
9549		}
9550
9551		this.clippingPlanes = dstPlanes;
9552		this.clipIntersection = source.clipIntersection;
9553		this.clipShadows = source.clipShadows;
9554
9555		this.shadowSide = source.shadowSide;
9556
9557		this.colorWrite = source.colorWrite;
9558
9559		this.precision = source.precision;
9560
9561		this.polygonOffset = source.polygonOffset;
9562		this.polygonOffsetFactor = source.polygonOffsetFactor;
9563		this.polygonOffsetUnits = source.polygonOffsetUnits;
9564
9565		this.dithering = source.dithering;
9566
9567		this.alphaTest = source.alphaTest;
9568		this.alphaHash = source.alphaHash;
9569		this.alphaToCoverage = source.alphaToCoverage;
9570		this.premultipliedAlpha = source.premultipliedAlpha;
9571		this.forceSinglePass = source.forceSinglePass;
9572
9573		this.visible = source.visible;
9574
9575		this.toneMapped = source.toneMapped;
9576
9577		this.userData = JSON.parse( JSON.stringify( source.userData ) );
9578
9579		return this;
9580
9581	}
9582
9583	dispose() {
9584
9585		this.dispatchEvent( { type: 'dispose' } );
9586
9587	}
9588
9589	set needsUpdate( value ) {
9590
9591		if ( value === true ) this.version ++;
9592
9593	}
9594
9595}
9596
9597class MeshBasicMaterial extends Material {
9598
9599	constructor( parameters ) {
9600
9601		super();
9602
9603		this.isMeshBasicMaterial = true;
9604
9605		this.type = 'MeshBasicMaterial';
9606
9607		this.color = new Color( 0xffffff ); // emissive
9608
9609		this.map = null;
9610
9611		this.lightMap = null;
9612		this.lightMapIntensity = 1.0;
9613
9614		this.aoMap = null;
9615		this.aoMapIntensity = 1.0;
9616
9617		this.specularMap = null;
9618
9619		this.alphaMap = null;
9620
9621		this.envMap = null;
9622		this.envMapRotation = new Euler();
9623		this.combine = MultiplyOperation;
9624		this.reflectivity = 1;
9625		this.refractionRatio = 0.98;
9626
9627		this.wireframe = false;
9628		this.wireframeLinewidth = 1;
9629		this.wireframeLinecap = 'round';
9630		this.wireframeLinejoin = 'round';
9631
9632		this.fog = true;
9633
9634		this.setValues( parameters );
9635
9636	}
9637
9638	copy( source ) {
9639
9640		super.copy( source );
9641
9642		this.color.copy( source.color );
9643
9644		this.map = source.map;
9645
9646		this.lightMap = source.lightMap;
9647		this.lightMapIntensity = source.lightMapIntensity;
9648
9649		this.aoMap = source.aoMap;
9650		this.aoMapIntensity = source.aoMapIntensity;
9651
9652		this.specularMap = source.specularMap;
9653
9654		this.alphaMap = source.alphaMap;
9655
9656		this.envMap = source.envMap;
9657		this.envMapRotation.copy( source.envMapRotation );
9658		this.combine = source.combine;
9659		this.reflectivity = source.reflectivity;
9660		this.refractionRatio = source.refractionRatio;
9661
9662		this.wireframe = source.wireframe;
9663		this.wireframeLinewidth = source.wireframeLinewidth;
9664		this.wireframeLinecap = source.wireframeLinecap;
9665		this.wireframeLinejoin = source.wireframeLinejoin;
9666
9667		this.fog = source.fog;
9668
9669		return this;
9670
9671	}
9672
9673}
9674
vendor: 4,666 bytes, lines 9675-9913
9675// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
9676
9677const _tables = /*@__PURE__*/ _generateTables();
9678
9679function _generateTables() {
9680
9681	// float32 to float16 helpers
9682
9683	const buffer = new ArrayBuffer( 4 );
9684	const floatView = new Float32Array( buffer );
9685	const uint32View = new Uint32Array( buffer );
9686
9687	const baseTable = new Uint32Array( 512 );
9688	const shiftTable = new Uint32Array( 512 );
9689
9690	for ( let i = 0; i < 256; ++ i ) {
9691
9692		const e = i - 127;
9693
9694		// very small number (0, -0)
9695
9696		if ( e < - 27 ) {
9697
9698			baseTable[ i ] = 0x0000;
9699			baseTable[ i | 0x100 ] = 0x8000;
9700			shiftTable[ i ] = 24;
9701			shiftTable[ i | 0x100 ] = 24;
9702
9703			// small number (denorm)
9704
9705		} else if ( e < - 14 ) {
9706
9707			baseTable[ i ] = 0x0400 >> ( - e - 14 );
9708			baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000;
9709			shiftTable[ i ] = - e - 1;
9710			shiftTable[ i | 0x100 ] = - e - 1;
9711
9712			// normal number
9713
9714		} else if ( e <= 15 ) {
9715
9716			baseTable[ i ] = ( e + 15 ) << 10;
9717			baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000;
9718			shiftTable[ i ] = 13;
9719			shiftTable[ i | 0x100 ] = 13;
9720
9721			// large number (Infinity, -Infinity)
9722
9723		} else if ( e < 128 ) {
9724
9725			baseTable[ i ] = 0x7c00;
9726			baseTable[ i | 0x100 ] = 0xfc00;
9727			shiftTable[ i ] = 24;
9728			shiftTable[ i | 0x100 ] = 24;
9729
9730			// stay (NaN, Infinity, -Infinity)
9731
9732		} else {
9733
9734			baseTable[ i ] = 0x7c00;
9735			baseTable[ i | 0x100 ] = 0xfc00;
9736			shiftTable[ i ] = 13;
9737			shiftTable[ i | 0x100 ] = 13;
9738
9739		}
9740
9741	}
9742
9743	// float16 to float32 helpers
9744
9745	const mantissaTable = new Uint32Array( 2048 );
9746	const exponentTable = new Uint32Array( 64 );
9747	const offsetTable = new Uint32Array( 64 );
9748
9749	for ( let i = 1; i < 1024; ++ i ) {
9750
9751		let m = i << 13; // zero pad mantissa bits
9752		let e = 0; // zero exponent
9753
9754		// normalized
9755		while ( ( m & 0x00800000 ) === 0 ) {
9756
9757			m <<= 1;
9758			e -= 0x00800000; // decrement exponent
9759
9760		}
9761
9762		m &= ~ 0x00800000; // clear leading 1 bit
9763		e += 0x38800000; // adjust bias
9764
9765		mantissaTable[ i ] = m | e;
9766
9767	}
9768
9769	for ( let i = 1024; i < 2048; ++ i ) {
9770
9771		mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 );
9772
9773	}
9774
9775	for ( let i = 1; i < 31; ++ i ) {
9776
9777		exponentTable[ i ] = i << 23;
9778
9779	}
9780
9781	exponentTable[ 31 ] = 0x47800000;
9782	exponentTable[ 32 ] = 0x80000000;
9783
9784	for ( let i = 33; i < 63; ++ i ) {
9785
9786		exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 );
9787
9788	}
9789
9790	exponentTable[ 63 ] = 0xc7800000;
9791
9792	for ( let i = 1; i < 64; ++ i ) {
9793
9794		if ( i !== 32 ) {
9795
9796			offsetTable[ i ] = 1024;
9797
9798		}
9799
9800	}
9801
9802	return {
9803		floatView: floatView,
9804		uint32View: uint32View,
9805		baseTable: baseTable,
9806		shiftTable: shiftTable,
9807		mantissaTable: mantissaTable,
9808		exponentTable: exponentTable,
9809		offsetTable: offsetTable
9810	};
9811
9812}
9813
9814// float32 to float16
9815
9816function toHalfFloat( val ) {
9817
9818	if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' );
9819
9820	val = clamp( val, - 65504, 65504 );
9821
9822	_tables.floatView[ 0 ] = val;
9823	const f = _tables.uint32View[ 0 ];
9824	const e = ( f >> 23 ) & 0x1ff;
9825	return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] );
9826
9827}
9828
9829// float16 to float32
9830
9831function fromHalfFloat( val ) {
9832
9833	const m = val >> 10;
9834	_tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ];
9835	return _tables.floatView[ 0 ];
9836
9837}
9838
9839const DataUtils = {
9840	toHalfFloat: toHalfFloat,
9841	fromHalfFloat: fromHalfFloat,
9842};
9843
9844const _vector$9 = /*@__PURE__*/ new Vector3();
9845const _vector2$1 = /*@__PURE__*/ new Vector2();
9846
9847class BufferAttribute {
9848
9849	constructor( array, itemSize, normalized = false ) {
9850
9851		if ( Array.isArray( array ) ) {
9852
9853			throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
9854
9855		}
9856
9857		this.isBufferAttribute = true;
9858
9859		this.name = '';
9860
9861		this.array = array;
9862		this.itemSize = itemSize;
9863		this.count = array !== undefined ? array.length / itemSize : 0;
9864		this.normalized = normalized;
9865
9866		this.usage = StaticDrawUsage;
9867		this._updateRange = { offset: 0, count: - 1 };
9868		this.updateRanges = [];
9869		this.gpuType = FloatType;
9870
9871		this.version = 0;
9872
9873	}
9874
9875	onUploadCallback() {}
9876
9877	set needsUpdate( value ) {
9878
9879		if ( value === true ) this.version ++;
9880
9881	}
9882
9883	get updateRange() {
9884
9885		warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159
9886		return this._updateRange;
9887
9888	}
9889
9890	setUsage( value ) {
9891
9892		this.usage = value;
9893
9894		return this;
9895
9896	}
9897
9898	addUpdateRange( start, count ) {
9899
9900		this.updateRanges.push( { start, count } );
9901
9902	}
9903
9904	clearUpdateRanges() {
9905
9906		this.updateRanges.length = 0;
9907
9908	}
9909
9910	copy( source ) {
9911
9912		this.name = source.name;
9913		this.array = new source.array.constructor( source.array );
vendor: 8,607 bytes, lines 9914-10445
9914		this.itemSize = source.itemSize;
9915		this.count = source.count;
9916		this.normalized = source.normalized;
9917
9918		this.usage = source.usage;
9919		this.gpuType = source.gpuType;
9920
9921		return this;
9922
9923	}
9924
9925	copyAt( index1, attribute, index2 ) {
9926
9927		index1 *= this.itemSize;
9928		index2 *= attribute.itemSize;
9929
9930		for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
9931
9932			this.array[ index1 + i ] = attribute.array[ index2 + i ];
9933
9934		}
9935
9936		return this;
9937
9938	}
9939
9940	copyArray( array ) {
9941
9942		this.array.set( array );
9943
9944		return this;
9945
9946	}
9947
9948	applyMatrix3( m ) {
9949
9950		if ( this.itemSize === 2 ) {
9951
9952			for ( let i = 0, l = this.count; i < l; i ++ ) {
9953
9954				_vector2$1.fromBufferAttribute( this, i );
9955				_vector2$1.applyMatrix3( m );
9956
9957				this.setXY( i, _vector2$1.x, _vector2$1.y );
9958
9959			}
9960
9961		} else if ( this.itemSize === 3 ) {
9962
9963			for ( let i = 0, l = this.count; i < l; i ++ ) {
9964
9965				_vector$9.fromBufferAttribute( this, i );
9966				_vector$9.applyMatrix3( m );
9967
9968				this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9969
9970			}
9971
9972		}
9973
9974		return this;
9975
9976	}
9977
9978	applyMatrix4( m ) {
9979
9980		for ( let i = 0, l = this.count; i < l; i ++ ) {
9981
9982			_vector$9.fromBufferAttribute( this, i );
9983
9984			_vector$9.applyMatrix4( m );
9985
9986			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
9987
9988		}
9989
9990		return this;
9991
9992	}
9993
9994	applyNormalMatrix( m ) {
9995
9996		for ( let i = 0, l = this.count; i < l; i ++ ) {
9997
9998			_vector$9.fromBufferAttribute( this, i );
9999
10000			_vector$9.applyNormalMatrix( m );
10001
10002			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
10003
10004		}
10005
10006		return this;
10007
10008	}
10009
10010	transformDirection( m ) {
10011
10012		for ( let i = 0, l = this.count; i < l; i ++ ) {
10013
10014			_vector$9.fromBufferAttribute( this, i );
10015
10016			_vector$9.transformDirection( m );
10017
10018			this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
10019
10020		}
10021
10022		return this;
10023
10024	}
10025
10026	set( value, offset = 0 ) {
10027
10028		// Matching BufferAttribute constructor, do not normalize the array.
10029		this.array.set( value, offset );
10030
10031		return this;
10032
10033	}
10034
10035	getComponent( index, component ) {
10036
10037		let value = this.array[ index * this.itemSize + component ];
10038
10039		if ( this.normalized ) value = denormalize( value, this.array );
10040
10041		return value;
10042
10043	}
10044
10045	setComponent( index, component, value ) {
10046
10047		if ( this.normalized ) value = normalize( value, this.array );
10048
10049		this.array[ index * this.itemSize + component ] = value;
10050
10051		return this;
10052
10053	}
10054
10055	getX( index ) {
10056
10057		let x = this.array[ index * this.itemSize ];
10058
10059		if ( this.normalized ) x = denormalize( x, this.array );
10060
10061		return x;
10062
10063	}
10064
10065	setX( index, x ) {
10066
10067		if ( this.normalized ) x = normalize( x, this.array );
10068
10069		this.array[ index * this.itemSize ] = x;
10070
10071		return this;
10072
10073	}
10074
10075	getY( index ) {
10076
10077		let y = this.array[ index * this.itemSize + 1 ];
10078
10079		if ( this.normalized ) y = denormalize( y, this.array );
10080
10081		return y;
10082
10083	}
10084
10085	setY( index, y ) {
10086
10087		if ( this.normalized ) y = normalize( y, this.array );
10088
10089		this.array[ index * this.itemSize + 1 ] = y;
10090
10091		return this;
10092
10093	}
10094
10095	getZ( index ) {
10096
10097		let z = this.array[ index * this.itemSize + 2 ];
10098
10099		if ( this.normalized ) z = denormalize( z, this.array );
10100
10101		return z;
10102
10103	}
10104
10105	setZ( index, z ) {
10106
10107		if ( this.normalized ) z = normalize( z, this.array );
10108
10109		this.array[ index * this.itemSize + 2 ] = z;
10110
10111		return this;
10112
10113	}
10114
10115	getW( index ) {
10116
10117		let w = this.array[ index * this.itemSize + 3 ];
10118
10119		if ( this.normalized ) w = denormalize( w, this.array );
10120
10121		return w;
10122
10123	}
10124
10125	setW( index, w ) {
10126
10127		if ( this.normalized ) w = normalize( w, this.array );
10128
10129		this.array[ index * this.itemSize + 3 ] = w;
10130
10131		return this;
10132
10133	}
10134
10135	setXY( index, x, y ) {
10136
10137		index *= this.itemSize;
10138
10139		if ( this.normalized ) {
10140
10141			x = normalize( x, this.array );
10142			y = normalize( y, this.array );
10143
10144		}
10145
10146		this.array[ index + 0 ] = x;
10147		this.array[ index + 1 ] = y;
10148
10149		return this;
10150
10151	}
10152
10153	setXYZ( index, x, y, z ) {
10154
10155		index *= this.itemSize;
10156
10157		if ( this.normalized ) {
10158
10159			x = normalize( x, this.array );
10160			y = normalize( y, this.array );
10161			z = normalize( z, this.array );
10162
10163		}
10164
10165		this.array[ index + 0 ] = x;
10166		this.array[ index + 1 ] = y;
10167		this.array[ index + 2 ] = z;
10168
10169		return this;
10170
10171	}
10172
10173	setXYZW( index, x, y, z, w ) {
10174
10175		index *= this.itemSize;
10176
10177		if ( this.normalized ) {
10178
10179			x = normalize( x, this.array );
10180			y = normalize( y, this.array );
10181			z = normalize( z, this.array );
10182			w = normalize( w, this.array );
10183
10184		}
10185
10186		this.array[ index + 0 ] = x;
10187		this.array[ index + 1 ] = y;
10188		this.array[ index + 2 ] = z;
10189		this.array[ index + 3 ] = w;
10190
10191		return this;
10192
10193	}
10194
10195	onUpload( callback ) {
10196
10197		this.onUploadCallback = callback;
10198
10199		return this;
10200
10201	}
10202
10203	clone() {
10204
10205		return new this.constructor( this.array, this.itemSize ).copy( this );
10206
10207	}
10208
10209	toJSON() {
10210
10211		const data = {
10212			itemSize: this.itemSize,
10213			type: this.array.constructor.name,
10214			array: Array.from( this.array ),
10215			normalized: this.normalized
10216		};
10217
10218		if ( this.name !== '' ) data.name = this.name;
10219		if ( this.usage !== StaticDrawUsage ) data.usage = this.usage;
10220
10221		return data;
10222
10223	}
10224
10225}
10226
10227//
10228
10229class Int8BufferAttribute extends BufferAttribute {
10230
10231	constructor( array, itemSize, normalized ) {
10232
10233		super( new Int8Array( array ), itemSize, normalized );
10234
10235	}
10236
10237}
10238
10239class Uint8BufferAttribute extends BufferAttribute {
10240
10241	constructor( array, itemSize, normalized ) {
10242
10243		super( new Uint8Array( array ), itemSize, normalized );
10244
10245	}
10246
10247}
10248
10249class Uint8ClampedBufferAttribute extends BufferAttribute {
10250
10251	constructor( array, itemSize, normalized ) {
10252
10253		super( new Uint8ClampedArray( array ), itemSize, normalized );
10254
10255	}
10256
10257}
10258
10259class Int16BufferAttribute extends BufferAttribute {
10260
10261	constructor( array, itemSize, normalized ) {
10262
10263		super( new Int16Array( array ), itemSize, normalized );
10264
10265	}
10266
10267}
10268
10269class Uint16BufferAttribute extends BufferAttribute {
10270
10271	constructor( array, itemSize, normalized ) {
10272
10273		super( new Uint16Array( array ), itemSize, normalized );
10274
10275	}
10276
10277}
10278
10279class Int32BufferAttribute extends BufferAttribute {
10280
10281	constructor( array, itemSize, normalized ) {
10282
10283		super( new Int32Array( array ), itemSize, normalized );
10284
10285	}
10286
10287}
10288
10289class Uint32BufferAttribute extends BufferAttribute {
10290
10291	constructor( array, itemSize, normalized ) {
10292
10293		super( new Uint32Array( array ), itemSize, normalized );
10294
10295	}
10296
10297}
10298
10299class Float16BufferAttribute extends BufferAttribute {
10300
10301	constructor( array, itemSize, normalized ) {
10302
10303		super( new Uint16Array( array ), itemSize, normalized );
10304
10305		this.isFloat16BufferAttribute = true;
10306
10307	}
10308
10309	getX( index ) {
10310
10311		let x = fromHalfFloat( this.array[ index * this.itemSize ] );
10312
10313		if ( this.normalized ) x = denormalize( x, this.array );
10314
10315		return x;
10316
10317	}
10318
10319	setX( index, x ) {
10320
10321		if ( this.normalized ) x = normalize( x, this.array );
10322
10323		this.array[ index * this.itemSize ] = toHalfFloat( x );
10324
10325		return this;
10326
10327	}
10328
10329	getY( index ) {
10330
10331		let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] );
10332
10333		if ( this.normalized ) y = denormalize( y, this.array );
10334
10335		return y;
10336
10337	}
10338
10339	setY( index, y ) {
10340
10341		if ( this.normalized ) y = normalize( y, this.array );
10342
10343		this.array[ index * this.itemSize + 1 ] = toHalfFloat( y );
10344
10345		return this;
10346
10347	}
10348
10349	getZ( index ) {
10350
10351		let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] );
10352
10353		if ( this.normalized ) z = denormalize( z, this.array );
10354
10355		return z;
10356
10357	}
10358
10359	setZ( index, z ) {
10360
10361		if ( this.normalized ) z = normalize( z, this.array );
10362
10363		this.array[ index * this.itemSize + 2 ] = toHalfFloat( z );
10364
10365		return this;
10366
10367	}
10368
10369	getW( index ) {
10370
10371		let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] );
10372
10373		if ( this.normalized ) w = denormalize( w, this.array );
10374
10375		return w;
10376
10377	}
10378
10379	setW( index, w ) {
10380
10381		if ( this.normalized ) w = normalize( w, this.array );
10382
10383		this.array[ index * this.itemSize + 3 ] = toHalfFloat( w );
10384
10385		return this;
10386
10387	}
10388
10389	setXY( index, x, y ) {
10390
10391		index *= this.itemSize;
10392
10393		if ( this.normalized ) {
10394
10395			x = normalize( x, this.array );
10396			y = normalize( y, this.array );
10397
10398		}
10399
10400		this.array[ index + 0 ] = toHalfFloat( x );
10401		this.array[ index + 1 ] = toHalfFloat( y );
10402
10403		return this;
10404
10405	}
10406
10407	setXYZ( index, x, y, z ) {
10408
10409		index *= this.itemSize;
10410
10411		if ( this.normalized ) {
10412
10413			x = normalize( x, this.array );
10414			y = normalize( y, this.array );
10415			z = normalize( z, this.array );
10416
10417		}
10418
10419		this.array[ index + 0 ] = toHalfFloat( x );
10420		this.array[ index + 1 ] = toHalfFloat( y );
10421		this.array[ index + 2 ] = toHalfFloat( z );
10422
10423		return this;
10424
10425	}
10426
10427	setXYZW( index, x, y, z, w ) {
10428
10429		index *= this.itemSize;
10430
10431		if ( this.normalized ) {
10432
10433			x = normalize( x, this.array );
10434			y = normalize( y, this.array );
10435			z = normalize( z, this.array );
10436			w = normalize( w, this.array );
10437
10438		}
10439
10440		this.array[ index + 0 ] = toHalfFloat( x );
10441		this.array[ index + 1 ] = toHalfFloat( y );
10442		this.array[ index + 2 ] = toHalfFloat( z );
10443		this.array[ index + 3 ] = toHalfFloat( w );
10444
10445		return this
vendor: 11,366 bytes, lines 10445-11055
10445;
10446
10447	}
10448
10449}
10450
10451
10452class Float32BufferAttribute extends BufferAttribute {
10453
10454	constructor( array, itemSize, normalized ) {
10455
10456		super( new Float32Array( array ), itemSize, normalized );
10457
10458	}
10459
10460}
10461
10462let _id$2 = 0;
10463
10464const _m1$2 = /*@__PURE__*/ new Matrix4();
10465const _obj = /*@__PURE__*/ new Object3D();
10466const _offset = /*@__PURE__*/ new Vector3();
10467const _box$2 = /*@__PURE__*/ new Box3();
10468const _boxMorphTargets = /*@__PURE__*/ new Box3();
10469const _vector$8 = /*@__PURE__*/ new Vector3();
10470
10471class BufferGeometry extends EventDispatcher {
10472
10473	constructor() {
10474
10475		super();
10476
10477		this.isBufferGeometry = true;
10478
10479		Object.defineProperty( this, 'id', { value: _id$2 ++ } );
10480
10481		this.uuid = generateUUID();
10482
10483		this.name = '';
10484		this.type = 'BufferGeometry';
10485
10486		this.index = null;
10487		this.attributes = {};
10488
10489		this.morphAttributes = {};
10490		this.morphTargetsRelative = false;
10491
10492		this.groups = [];
10493
10494		this.boundingBox = null;
10495		this.boundingSphere = null;
10496
10497		this.drawRange = { start: 0, count: Infinity };
10498
10499		this.userData = {};
10500
10501	}
10502
10503	getIndex() {
10504
10505		return this.index;
10506
10507	}
10508
10509	setIndex( index ) {
10510
10511		if ( Array.isArray( index ) ) {
10512
10513			this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
10514
10515		} else {
10516
10517			this.index = index;
10518
10519		}
10520
10521		return this;
10522
10523	}
10524
10525	getAttribute( name ) {
10526
10527		return this.attributes[ name ];
10528
10529	}
10530
10531	setAttribute( name, attribute ) {
10532
10533		this.attributes[ name ] = attribute;
10534
10535		return this;
10536
10537	}
10538
10539	deleteAttribute( name ) {
10540
10541		delete this.attributes[ name ];
10542
10543		return this;
10544
10545	}
10546
10547	hasAttribute( name ) {
10548
10549		return this.attributes[ name ] !== undefined;
10550
10551	}
10552
10553	addGroup( start, count, materialIndex = 0 ) {
10554
10555		this.groups.push( {
10556
10557			start: start,
10558			count: count,
10559			materialIndex: materialIndex
10560
10561		} );
10562
10563	}
10564
10565	clearGroups() {
10566
10567		this.groups = [];
10568
10569	}
10570
10571	setDrawRange( start, count ) {
10572
10573		this.drawRange.start = start;
10574		this.drawRange.count = count;
10575
10576	}
10577
10578	applyMatrix4( matrix ) {
10579
10580		const position = this.attributes.position;
10581
10582		if ( position !== undefined ) {
10583
10584			position.applyMatrix4( matrix );
10585
10586			position.needsUpdate = true;
10587
10588		}
10589
10590		const normal = this.attributes.normal;
10591
10592		if ( normal !== undefined ) {
10593
10594			const normalMatrix = new Matrix3().getNormalMatrix( matrix );
10595
10596			normal.applyNormalMatrix( normalMatrix );
10597
10598			normal.needsUpdate = true;
10599
10600		}
10601
10602		const tangent = this.attributes.tangent;
10603
10604		if ( tangent !== undefined ) {
10605
10606			tangent.transformDirection( matrix );
10607
10608			tangent.needsUpdate = true;
10609
10610		}
10611
10612		if ( this.boundingBox !== null ) {
10613
10614			this.computeBoundingBox();
10615
10616		}
10617
10618		if ( this.boundingSphere !== null ) {
10619
10620			this.computeBoundingSphere();
10621
10622		}
10623
10624		return this;
10625
10626	}
10627
10628	applyQuaternion( q ) {
10629
10630		_m1$2.makeRotationFromQuaternion( q );
10631
10632		this.applyMatrix4( _m1$2 );
10633
10634		return this;
10635
10636	}
10637
10638	rotateX( angle ) {
10639
10640		// rotate geometry around world x-axis
10641
10642		_m1$2.makeRotationX( angle );
10643
10644		this.applyMatrix4( _m1$2 );
10645
10646		return this;
10647
10648	}
10649
10650	rotateY( angle ) {
10651
10652		// rotate geometry around world y-axis
10653
10654		_m1$2.makeRotationY( angle );
10655
10656		this.applyMatrix4( _m1$2 );
10657
10658		return this;
10659
10660	}
10661
10662	rotateZ( angle ) {
10663
10664		// rotate geometry around world z-axis
10665
10666		_m1$2.makeRotationZ( angle );
10667
10668		this.applyMatrix4( _m1$2 );
10669
10670		return this;
10671
10672	}
10673
10674	translate( x, y, z ) {
10675
10676		// translate geometry
10677
10678		_m1$2.makeTranslation( x, y, z );
10679
10680		this.applyMatrix4( _m1$2 );
10681
10682		return this;
10683
10684	}
10685
10686	scale( x, y, z ) {
10687
10688		// scale geometry
10689
10690		_m1$2.makeScale( x, y, z );
10691
10692		this.applyMatrix4( _m1$2 );
10693
10694		return this;
10695
10696	}
10697
10698	lookAt( vector ) {
10699
10700		_obj.lookAt( vector );
10701
10702		_obj.updateMatrix();
10703
10704		this.applyMatrix4( _obj.matrix );
10705
10706		return this;
10707
10708	}
10709
10710	center() {
10711
10712		this.computeBoundingBox();
10713
10714		this.boundingBox.getCenter( _offset ).negate();
10715
10716		this.translate( _offset.x, _offset.y, _offset.z );
10717
10718		return this;
10719
10720	}
10721
10722	setFromPoints( points ) {
10723
10724		const position = [];
10725
10726		for ( let i = 0, l = points.length; i < l; i ++ ) {
10727
10728			const point = points[ i ];
10729			position.push( point.x, point.y, point.z || 0 );
10730
10731		}
10732
10733		this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
10734
10735		return this;
10736
10737	}
10738
10739	computeBoundingBox() {
10740
10741		if ( this.boundingBox === null ) {
10742
10743			this.boundingBox = new Box3();
10744
10745		}
10746
10747		const position = this.attributes.position;
10748		const morphAttributesPosition = this.morphAttributes.position;
10749
10750		if ( position && position.isGLBufferAttribute ) {
10751
10752			console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this );
10753
10754			this.boundingBox.set(
10755				new Vector3( - Infinity, - Infinity, - Infinity ),
10756				new Vector3( + Infinity, + Infinity, + Infinity )
10757			);
10758
10759			return;
10760
10761		}
10762
10763		if ( position !== undefined ) {
10764
10765			this.boundingBox.setFromBufferAttribute( position );
10766
10767			// process morph attributes if present
10768
10769			if ( morphAttributesPosition ) {
10770
10771				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10772
10773					const morphAttribute = morphAttributesPosition[ i ];
10774					_box$2.setFromBufferAttribute( morphAttribute );
10775
10776					if ( this.morphTargetsRelative ) {
10777
10778						_vector$8.addVectors( this.boundingBox.min, _box$2.min );
10779						this.boundingBox.expandByPoint( _vector$8 );
10780
10781						_vector$8.addVectors( this.boundingBox.max, _box$2.max );
10782						this.boundingBox.expandByPoint( _vector$8 );
10783
10784					} else {
10785
10786						this.boundingBox.expandByPoint( _box$2.min );
10787						this.boundingBox.expandByPoint( _box$2.max );
10788
10789					}
10790
10791				}
10792
10793			}
10794
10795		} else {
10796
10797			this.boundingBox.makeEmpty();
10798
10799		}
10800
10801		if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
10802
10803			console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
10804
10805		}
10806
10807	}
10808
10809	computeBoundingSphere() {
10810
10811		if ( this.boundingSphere === null ) {
10812
10813			this.boundingSphere = new Sphere();
10814
10815		}
10816
10817		const position = this.attributes.position;
10818		const morphAttributesPosition = this.morphAttributes.position;
10819
10820		if ( position && position.isGLBufferAttribute ) {
10821
10822			console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this );
10823
10824			this.boundingSphere.set( new Vector3(), Infinity );
10825
10826			return;
10827
10828		}
10829
10830		if ( position ) {
10831
10832			// first, find the center of the bounding sphere
10833
10834			const center = this.boundingSphere.center;
10835
10836			_box$2.setFromBufferAttribute( position );
10837
10838			// process morph attributes if present
10839
10840			if ( morphAttributesPosition ) {
10841
10842				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10843
10844					const morphAttribute = morphAttributesPosition[ i ];
10845					_boxMorphTargets.setFromBufferAttribute( morphAttribute );
10846
10847					if ( this.morphTargetsRelative ) {
10848
10849						_vector$8.addVectors( _box$2.min, _boxMorphTargets.min );
10850						_box$2.expandByPoint( _vector$8 );
10851
10852						_vector$8.addVectors( _box$2.max, _boxMorphTargets.max );
10853						_box$2.expandByPoint( _vector$8 );
10854
10855					} else {
10856
10857						_box$2.expandByPoint( _boxMorphTargets.min );
10858						_box$2.expandByPoint( _boxMorphTargets.max );
10859
10860					}
10861
10862				}
10863
10864			}
10865
10866			_box$2.getCenter( center );
10867
10868			// second, try to find a boundingSphere with a radius smaller than the
10869			// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
10870
10871			let maxRadiusSq = 0;
10872
10873			for ( let i = 0, il = position.count; i < il; i ++ ) {
10874
10875				_vector$8.fromBufferAttribute( position, i );
10876
10877				maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10878
10879			}
10880
10881			// process morph attributes if present
10882
10883			if ( morphAttributesPosition ) {
10884
10885				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
10886
10887					const morphAttribute = morphAttributesPosition[ i ];
10888					const morphTargetsRelative = this.morphTargetsRelative;
10889
10890					for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
10891
10892						_vector$8.fromBufferAttribute( morphAttribute, j );
10893
10894						if ( morphTargetsRelative ) {
10895
10896							_offset.fromBufferAttribute( position, j );
10897							_vector$8.add( _offset );
10898
10899						}
10900
10901						maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10902
10903					}
10904
10905				}
10906
10907			}
10908
10909			this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
10910
10911			if ( isNaN( this.boundingSphere.radius ) ) {
10912
10913				console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
10914
10915			}
10916
10917		}
10918
10919	}
10920
10921	computeTangents() {
10922
10923		const index = this.index;
10924		const attributes = this.attributes;
10925
10926		// based on http://www.terathon.com/code/tangent.html
10927		// (per vertex tangents)
10928
10929		if ( index === null ||
10930			 attributes.position === undefined ||
10931			 attributes.normal === undefined ||
10932			 attributes.uv === undefined ) {
10933
10934			console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
10935			return;
10936
10937		}
10938
10939		const positionAttribute = attributes.position;
10940		const normalAttribute = attributes.normal;
10941		const uvAttribute = attributes.uv;
10942
10943		if ( this.hasAttribute( 'tangent' ) === false ) {
10944
10945			this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) );
10946
10947		}
10948
10949		const tangentAttribute = this.getAttribute( 'tangent' );
10950
10951		const tan1 = [], tan2 = [];
10952
10953		for ( let i = 0; i < positionAttribute.count; i ++ ) {
10954
10955			tan1[ i ] = new Vector3();
10956			tan2[ i ] = new Vector3();
10957
10958		}
10959
10960		const vA = new Vector3(),
10961			vB = new Vector3(),
10962			vC = new Vector3(),
10963
10964			uvA = new Vector2(),
10965			uvB = new Vector2(),
10966			uvC = new Vector2(),
10967
10968			sdir = new Vector3(),
10969			tdir = new Vector3();
10970
10971		function handleTriangle( a, b, c ) {
10972
10973			vA.fromBufferAttribute( positionAttribute, a );
10974			vB.fromBufferAttribute( positionAttribute, b );
10975			vC.fromBufferAttribute( positionAttribute, c );
10976
10977			uvA.fromBufferAttribute( uvAttribute, a );
10978			uvB.fromBufferAttribute( uvAttribute, b );
10979			uvC.fromBufferAttribute( uvAttribute, c );
10980
10981			vB.sub( vA );
10982			vC.sub( vA );
10983
10984			uvB.sub( uvA );
10985			uvC.sub( uvA );
10986
10987			const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
10988
10989			// silently ignore degenerate uv triangles having coincident or colinear vertices
10990
10991			if ( ! isFinite( r ) ) return;
10992
10993			sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
10994			tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
10995
10996			tan1[ a ].add( sdir );
10997			tan1[ b ].add( sdir );
10998			tan1[ c ].add( sdir );
10999
11000			tan2[ a ].add( tdir );
11001			tan2[ b ].add( tdir );
11002			tan2[ c ].add( tdir );
11003
11004		}
11005
11006		let groups = this.groups;
11007
11008		if ( groups.length === 0 ) {
11009
11010			groups = [ {
11011				start: 0,
11012				count: index.count
11013			} ];
11014
11015		}
11016
11017		for ( let i = 0, il = groups.length; i < il; ++ i ) {
11018
11019			const group = groups[ i ];
11020
11021			const start = group.start;
11022			const count = group.count;
11023
11024			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
11025
11026				handleTriangle(
11027					index.getX( j + 0 ),
11028					index.getX( j + 1 ),
11029					index.getX( j + 2 )
11030				);
11031
11032			}
11033
11034		}
11035
11036		const tmp = new Vector3(), tmp2 = new Vector3();
11037		const n = new Vector3(), n2 = new Vector3();
11038
11039		function handleVertex( v ) {
11040
11041			n.fromBufferAttribute( normalAttribute, v );
11042			n2.copy( n );
11043
11044			const t = tan1[ v ];
11045
11046			// Gram-Schmidt orthogonalize
11047
11048			tmp.copy( t );
11049			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
11050
11051			// Calculate handedness
11052
11053			tmp2.crossVectors( n2, t );
11054			const test = tmp2.dot( tan2[ v ] );
11055			const w = ( test < 0.0 ) ? -
11055 1.0
vendor: 16,831 bytes, lines 11055-11843
11055 : 1.0;
11056
11057			tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w );
11058
11059		}
11060
11061		for ( let i = 0, il = groups.length; i < il; ++ i ) {
11062
11063			const group = groups[ i ];
11064
11065			const start = group.start;
11066			const count = group.count;
11067
11068			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
11069
11070				handleVertex( index.getX( j + 0 ) );
11071				handleVertex( index.getX( j + 1 ) );
11072				handleVertex( index.getX( j + 2 ) );
11073
11074			}
11075
11076		}
11077
11078	}
11079
11080	computeVertexNormals() {
11081
11082		const index = this.index;
11083		const positionAttribute = this.getAttribute( 'position' );
11084
11085		if ( positionAttribute !== undefined ) {
11086
11087			let normalAttribute = this.getAttribute( 'normal' );
11088
11089			if ( normalAttribute === undefined ) {
11090
11091				normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
11092				this.setAttribute( 'normal', normalAttribute );
11093
11094			} else {
11095
11096				// reset existing normals to zero
11097
11098				for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
11099
11100					normalAttribute.setXYZ( i, 0, 0, 0 );
11101
11102				}
11103
11104			}
11105
11106			const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
11107			const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
11108			const cb = new Vector3(), ab = new Vector3();
11109
11110			// indexed elements
11111
11112			if ( index ) {
11113
11114				for ( let i = 0, il = index.count; i < il; i += 3 ) {
11115
11116					const vA = index.getX( i + 0 );
11117					const vB = index.getX( i + 1 );
11118					const vC = index.getX( i + 2 );
11119
11120					pA.fromBufferAttribute( positionAttribute, vA );
11121					pB.fromBufferAttribute( positionAttribute, vB );
11122					pC.fromBufferAttribute( positionAttribute, vC );
11123
11124					cb.subVectors( pC, pB );
11125					ab.subVectors( pA, pB );
11126					cb.cross( ab );
11127
11128					nA.fromBufferAttribute( normalAttribute, vA );
11129					nB.fromBufferAttribute( normalAttribute, vB );
11130					nC.fromBufferAttribute( normalAttribute, vC );
11131
11132					nA.add( cb );
11133					nB.add( cb );
11134					nC.add( cb );
11135
11136					normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
11137					normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
11138					normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
11139
11140				}
11141
11142			} else {
11143
11144				// non-indexed elements (unconnected triangle soup)
11145
11146				for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
11147
11148					pA.fromBufferAttribute( positionAttribute, i + 0 );
11149					pB.fromBufferAttribute( positionAttribute, i + 1 );
11150					pC.fromBufferAttribute( positionAttribute, i + 2 );
11151
11152					cb.subVectors( pC, pB );
11153					ab.subVectors( pA, pB );
11154					cb.cross( ab );
11155
11156					normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
11157					normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
11158					normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
11159
11160				}
11161
11162			}
11163
11164			this.normalizeNormals();
11165
11166			normalAttribute.needsUpdate = true;
11167
11168		}
11169
11170	}
11171
11172	normalizeNormals() {
11173
11174		const normals = this.attributes.normal;
11175
11176		for ( let i = 0, il = normals.count; i < il; i ++ ) {
11177
11178			_vector$8.fromBufferAttribute( normals, i );
11179
11180			_vector$8.normalize();
11181
11182			normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
11183
11184		}
11185
11186	}
11187
11188	toNonIndexed() {
11189
11190		function convertBufferAttribute( attribute, indices ) {
11191
11192			const array = attribute.array;
11193			const itemSize = attribute.itemSize;
11194			const normalized = attribute.normalized;
11195
11196			const array2 = new array.constructor( indices.length * itemSize );
11197
11198			let index = 0, index2 = 0;
11199
11200			for ( let i = 0, l = indices.length; i < l; i ++ ) {
11201
11202				if ( attribute.isInterleavedBufferAttribute ) {
11203
11204					index = indices[ i ] * attribute.data.stride + attribute.offset;
11205
11206				} else {
11207
11208					index = indices[ i ] * itemSize;
11209
11210				}
11211
11212				for ( let j = 0; j < itemSize; j ++ ) {
11213
11214					array2[ index2 ++ ] = array[ index ++ ];
11215
11216				}
11217
11218			}
11219
11220			return new BufferAttribute( array2, itemSize, normalized );
11221
11222		}
11223
11224		//
11225
11226		if ( this.index === null ) {
11227
11228			console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
11229			return this;
11230
11231		}
11232
11233		const geometry2 = new BufferGeometry();
11234
11235		const indices = this.index.array;
11236		const attributes = this.attributes;
11237
11238		// attributes
11239
11240		for ( const name in attributes ) {
11241
11242			const attribute = attributes[ name ];
11243
11244			const newAttribute = convertBufferAttribute( attribute, indices );
11245
11246			geometry2.setAttribute( name, newAttribute );
11247
11248		}
11249
11250		// morph attributes
11251
11252		const morphAttributes = this.morphAttributes;
11253
11254		for ( const name in morphAttributes ) {
11255
11256			const morphArray = [];
11257			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
11258
11259			for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
11260
11261				const attribute = morphAttribute[ i ];
11262
11263				const newAttribute = convertBufferAttribute( attribute, indices );
11264
11265				morphArray.push( newAttribute );
11266
11267			}
11268
11269			geometry2.morphAttributes[ name ] = morphArray;
11270
11271		}
11272
11273		geometry2.morphTargetsRelative = this.morphTargetsRelative;
11274
11275		// groups
11276
11277		const groups = this.groups;
11278
11279		for ( let i = 0, l = groups.length; i < l; i ++ ) {
11280
11281			const group = groups[ i ];
11282			geometry2.addGroup( group.start, group.count, group.materialIndex );
11283
11284		}
11285
11286		return geometry2;
11287
11288	}
11289
11290	toJSON() {
11291
11292		const data = {
11293			metadata: {
11294				version: 4.6,
11295				type: 'BufferGeometry',
11296				generator: 'BufferGeometry.toJSON'
11297			}
11298		};
11299
11300		// standard BufferGeometry serialization
11301
11302		data.uuid = this.uuid;
11303		data.type = this.type;
11304		if ( this.name !== '' ) data.name = this.name;
11305		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
11306
11307		if ( this.parameters !== undefined ) {
11308
11309			const parameters = this.parameters;
11310
11311			for ( const key in parameters ) {
11312
11313				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
11314
11315			}
11316
11317			return data;
11318
11319		}
11320
11321		// for simplicity the code assumes attributes are not shared across geometries, see #15811
11322
11323		data.data = { attributes: {} };
11324
11325		const index = this.index;
11326
11327		if ( index !== null ) {
11328
11329			data.data.index = {
11330				type: index.array.constructor.name,
11331				array: Array.prototype.slice.call( index.array )
11332			};
11333
11334		}
11335
11336		const attributes = this.attributes;
11337
11338		for ( const key in attributes ) {
11339
11340			const attribute = attributes[ key ];
11341
11342			data.data.attributes[ key ] = attribute.toJSON( data.data );
11343
11344		}
11345
11346		const morphAttributes = {};
11347		let hasMorphAttributes = false;
11348
11349		for ( const key in this.morphAttributes ) {
11350
11351			const attributeArray = this.morphAttributes[ key ];
11352
11353			const array = [];
11354
11355			for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
11356
11357				const attribute = attributeArray[ i ];
11358
11359				array.push( attribute.toJSON( data.data ) );
11360
11361			}
11362
11363			if ( array.length > 0 ) {
11364
11365				morphAttributes[ key ] = array;
11366
11367				hasMorphAttributes = true;
11368
11369			}
11370
11371		}
11372
11373		if ( hasMorphAttributes ) {
11374
11375			data.data.morphAttributes = morphAttributes;
11376			data.data.morphTargetsRelative = this.morphTargetsRelative;
11377
11378		}
11379
11380		const groups = this.groups;
11381
11382		if ( groups.length > 0 ) {
11383
11384			data.data.groups = JSON.parse( JSON.stringify( groups ) );
11385
11386		}
11387
11388		const boundingSphere = this.boundingSphere;
11389
11390		if ( boundingSphere !== null ) {
11391
11392			data.data.boundingSphere = {
11393				center: boundingSphere.center.toArray(),
11394				radius: boundingSphere.radius
11395			};
11396
11397		}
11398
11399		return data;
11400
11401	}
11402
11403	clone() {
11404
11405		return new this.constructor().copy( this );
11406
11407	}
11408
11409	copy( source ) {
11410
11411		// reset
11412
11413		this.index = null;
11414		this.attributes = {};
11415		this.morphAttributes = {};
11416		this.groups = [];
11417		this.boundingBox = null;
11418		this.boundingSphere = null;
11419
11420		// used for storing cloned, shared data
11421
11422		const data = {};
11423
11424		// name
11425
11426		this.name = source.name;
11427
11428		// index
11429
11430		const index = source.index;
11431
11432		if ( index !== null ) {
11433
11434			this.setIndex( index.clone( data ) );
11435
11436		}
11437
11438		// attributes
11439
11440		const attributes = source.attributes;
11441
11442		for ( const name in attributes ) {
11443
11444			const attribute = attributes[ name ];
11445			this.setAttribute( name, attribute.clone( data ) );
11446
11447		}
11448
11449		// morph attributes
11450
11451		const morphAttributes = source.morphAttributes;
11452
11453		for ( const name in morphAttributes ) {
11454
11455			const array = [];
11456			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
11457
11458			for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
11459
11460				array.push( morphAttribute[ i ].clone( data ) );
11461
11462			}
11463
11464			this.morphAttributes[ name ] = array;
11465
11466		}
11467
11468		this.morphTargetsRelative = source.morphTargetsRelative;
11469
11470		// groups
11471
11472		const groups = source.groups;
11473
11474		for ( let i = 0, l = groups.length; i < l; i ++ ) {
11475
11476			const group = groups[ i ];
11477			this.addGroup( group.start, group.count, group.materialIndex );
11478
11479		}
11480
11481		// bounding box
11482
11483		const boundingBox = source.boundingBox;
11484
11485		if ( boundingBox !== null ) {
11486
11487			this.boundingBox = boundingBox.clone();
11488
11489		}
11490
11491		// bounding sphere
11492
11493		const boundingSphere = source.boundingSphere;
11494
11495		if ( boundingSphere !== null ) {
11496
11497			this.boundingSphere = boundingSphere.clone();
11498
11499		}
11500
11501		// draw range
11502
11503		this.drawRange.start = source.drawRange.start;
11504		this.drawRange.count = source.drawRange.count;
11505
11506		// user data
11507
11508		this.userData = source.userData;
11509
11510		return this;
11511
11512	}
11513
11514	dispose() {
11515
11516		this.dispatchEvent( { type: 'dispose' } );
11517
11518	}
11519
11520}
11521
11522const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4();
11523const _ray$3 = /*@__PURE__*/ new Ray();
11524const _sphere$6 = /*@__PURE__*/ new Sphere();
11525const _sphereHitAt = /*@__PURE__*/ new Vector3();
11526
11527const _vA$1 = /*@__PURE__*/ new Vector3();
11528const _vB$1 = /*@__PURE__*/ new Vector3();
11529const _vC$1 = /*@__PURE__*/ new Vector3();
11530
11531const _tempA = /*@__PURE__*/ new Vector3();
11532const _morphA = /*@__PURE__*/ new Vector3();
11533
11534const _uvA$1 = /*@__PURE__*/ new Vector2();
11535const _uvB$1 = /*@__PURE__*/ new Vector2();
11536const _uvC$1 = /*@__PURE__*/ new Vector2();
11537
11538const _normalA = /*@__PURE__*/ new Vector3();
11539const _normalB = /*@__PURE__*/ new Vector3();
11540const _normalC = /*@__PURE__*/ new Vector3();
11541
11542const _intersectionPoint = /*@__PURE__*/ new Vector3();
11543const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
11544
11545class Mesh extends Object3D {
11546
11547	constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
11548
11549		super();
11550
11551		this.isMesh = true;
11552
11553		this.type = 'Mesh';
11554
11555		this.geometry = geometry;
11556		this.material = material;
11557
11558		this.updateMorphTargets();
11559
11560	}
11561
11562	copy( source, recursive ) {
11563
11564		super.copy( source, recursive );
11565
11566		if ( source.morphTargetInfluences !== undefined ) {
11567
11568			this.morphTargetInfluences = source.morphTargetInfluences.slice();
11569
11570		}
11571
11572		if ( source.morphTargetDictionary !== undefined ) {
11573
11574			this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
11575
11576		}
11577
11578		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
11579		this.geometry = source.geometry;
11580
11581		return this;
11582
11583	}
11584
11585	updateMorphTargets() {
11586
11587		const geometry = this.geometry;
11588
11589		const morphAttributes = geometry.morphAttributes;
11590		const keys = Object.keys( morphAttributes );
11591
11592		if ( keys.length > 0 ) {
11593
11594			const morphAttribute = morphAttributes[ keys[ 0 ] ];
11595
11596			if ( morphAttribute !== undefined ) {
11597
11598				this.morphTargetInfluences = [];
11599				this.morphTargetDictionary = {};
11600
11601				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
11602
11603					const name = morphAttribute[ m ].name || String( m );
11604
11605					this.morphTargetInfluences.push( 0 );
11606					this.morphTargetDictionary[ name ] = m;
11607
11608				}
11609
11610			}
11611
11612		}
11613
11614	}
11615
11616	getVertexPosition( index, target ) {
11617
11618		const geometry = this.geometry;
11619		const position = geometry.attributes.position;
11620		const morphPosition = geometry.morphAttributes.position;
11621		const morphTargetsRelative = geometry.morphTargetsRelative;
11622
11623		target.fromBufferAttribute( position, index );
11624
11625		const morphInfluences = this.morphTargetInfluences;
11626
11627		if ( morphPosition && morphInfluences ) {
11628
11629			_morphA.set( 0, 0, 0 );
11630
11631			for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
11632
11633				const influence = morphInfluences[ i ];
11634				const morphAttribute = morphPosition[ i ];
11635
11636				if ( influence === 0 ) continue;
11637
11638				_tempA.fromBufferAttribute( morphAttribute, index );
11639
11640				if ( morphTargetsRelative ) {
11641
11642					_morphA.addScaledVector( _tempA, influence );
11643
11644				} else {
11645
11646					_morphA.addScaledVector( _tempA.sub( target ), influence );
11647
11648				}
11649
11650			}
11651
11652			target.add( _morphA );
11653
11654		}
11655
11656		return target;
11657
11658	}
11659
11660	raycast( raycaster, intersects ) {
11661
11662		const geometry = this.geometry;
11663		const material = this.material;
11664		const matrixWorld = this.matrixWorld;
11665
11666		if ( material === undefined ) return;
11667
11668		// test with bounding sphere in world space
11669
11670		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
11671
11672		_sphere$6.copy( geometry.boundingSphere );
11673		_sphere$6.applyMatrix4( matrixWorld );
11674
11675		// check distance from ray origin to bounding sphere
11676
11677		_ray$3.copy( raycaster.ray ).recast( raycaster.near );
11678
11679		if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) {
11680
11681			if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return;
11682
11683			if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return;
11684
11685		}
11686
11687		// convert ray to local space of mesh
11688
11689		_inverseMatrix$3.copy( matrixWorld ).invert();
11690		_ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 );
11691
11692		// test with bounding box in local space
11693
11694		if ( geometry.boundingBox !== null ) {
11695
11696			if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return;
11697
11698		}
11699
11700		// test for intersections with geometry
11701
11702		this._computeIntersections( raycaster, intersects, _ray$3 );
11703
11704	}
11705
11706	_computeIntersections( raycaster, intersects, rayLocalSpace ) {
11707
11708		let intersection;
11709
11710		const geometry = this.geometry;
11711		const material = this.material;
11712
11713		const index = geometry.index;
11714		const position = geometry.attributes.position;
11715		const uv = geometry.attributes.uv;
11716		const uv1 = geometry.attributes.uv1;
11717		const normal = geometry.attributes.normal;
11718		const groups = geometry.groups;
11719		const drawRange = geometry.drawRange;
11720
11721		if ( index !== null ) {
11722
11723			// indexed buffer geometry
11724
11725			if ( Array.isArray( material ) ) {
11726
11727				for ( let i = 0, il = groups.length; i < il; i ++ ) {
11728
11729					const group = groups[ i ];
11730					const groupMaterial = material[ group.materialIndex ];
11731
11732					const start = Math.max( group.start, drawRange.start );
11733					const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11734
11735					for ( let j = start, jl = end; j < jl; j += 3 ) {
11736
11737						const a = index.getX( j );
11738						const b = index.getX( j + 1 );
11739						const c = index.getX( j + 2 );
11740
11741						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11742
11743						if ( intersection ) {
11744
11745							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
11746							intersection.face.materialIndex = group.materialIndex;
11747							intersects.push( intersection );
11748
11749						}
11750
11751					}
11752
11753				}
11754
11755			} else {
11756
11757				const start = Math.max( 0, drawRange.start );
11758				const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
11759
11760				for ( let i = start, il = end; i < il; i += 3 ) {
11761
11762					const a = index.getX( i );
11763					const b = index.getX( i + 1 );
11764					const c = index.getX( i + 2 );
11765
11766					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11767
11768					if ( intersection ) {
11769
11770						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
11771						intersects.push( intersection );
11772
11773					}
11774
11775				}
11776
11777			}
11778
11779		} else if ( position !== undefined ) {
11780
11781			// non-indexed buffer geometry
11782
11783			if ( Array.isArray( material ) ) {
11784
11785				for ( let i = 0, il = groups.length; i < il; i ++ ) {
11786
11787					const group = groups[ i ];
11788					const groupMaterial = material[ group.materialIndex ];
11789
11790					const start = Math.max( group.start, drawRange.start );
11791					const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11792
11793					for ( let j = start, jl = end; j < jl; j += 3 ) {
11794
11795						const a = j;
11796						const b = j + 1;
11797						const c = j + 2;
11798
11799						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11800
11801						if ( intersection ) {
11802
11803							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
11804							intersection.face.materialIndex = group.materialIndex;
11805							intersects.push( intersection );
11806
11807						}
11808
11809					}
11810
11811				}
11812
11813			} else {
11814
11815				const start = Math.max( 0, drawRange.start );
11816				const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
11817
11818				for ( let i = start, il = end; i < il; i += 3 ) {
11819
11820					const a = i;
11821					const b = i + 1;
11822					const c = i + 2;
11823
11824					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
11825
11826					if ( intersection ) {
11827
11828						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
11829						intersects.push( intersection );
11830
11831					}
11832
11833				}
11834
11835			}
11836
11837		}
11838
11839	}
11840
11841}
11842
11843function checkIntersection
11843$1( object, material, raycaster, ray, pA, pB, pC, point ) {
11844
11845	let intersect;
11846
11847	if ( material.side === BackSide ) {
11848
11849		intersect = ray.intersectTriangle( pC, pB, pA, true, point );
11850
11851	} else {
11852
11853		intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point );
11854
11855	}
11856
11857	if ( intersect === null ) return null;
11858
11859	_intersectionPointWorld.copy( point );
11860	_intersectionPointWorld.applyMatrix4( object.matrixWorld );
11861
11862	const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
11863
11864	if ( distance < raycaster.near || distance > raycaster.far ) return null;
11865
11866	return {
11867		distance: distance,
11868		point: _intersectionPointWorld.clone(),
11869		object: object
11870	};
11871
11872}
11873
11874function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) {
11875
11876	object.getVertexPosition( a, _vA$1 );
11877	object.getVertexPosition( b, _vB$1 );
11878	object.getVertexPosition( c, _vC$1 );
11879
11880	const intersection = checkIntersection$1( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint );
11881
11882	if ( intersection ) {
11883
11884		if ( uv ) {
11885
11886			_uvA$1.fromBufferAttribute( uv, a );
11887			_uvB$1.fromBufferAttribute( uv, b );
11888			_uvC$1.fromBufferAttribute( uv, c );
11889
11890			intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
11891
11892		}
11893
11894		if ( uv1 ) {
11895
11896			_uvA$1.fromBufferAttribute( uv1, a );
11897			_uvB$1.fromBufferAttribute( uv1, b );
11898			_uvC$1.fromBufferAttribute( uv1, c );
11899
11900			intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() );
11901
11902		}
11903
11904		if ( normal ) {
11905
11906			_normalA.fromBufferAttribute( normal, a );
11907			_normalB.fromBufferAttribute( normal, b );
11908			_normalC.fromBufferAttribute( normal, c );
11909
vendor: 6,950 bytes, lines 11910-12246
11910			intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() );
11911
11912			if ( intersection.normal.dot( ray.direction ) > 0 ) {
11913
11914				intersection.normal.multiplyScalar( - 1 );
11915
11916			}
11917
11918		}
11919
11920		const face = {
11921			a: a,
11922			b: b,
11923			c: c,
11924			normal: new Vector3(),
11925			materialIndex: 0
11926		};
11927
11928		Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal );
11929
11930		intersection.face = face;
11931
11932	}
11933
11934	return intersection;
11935
11936}
11937
11938class BoxGeometry extends BufferGeometry {
11939
11940	constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
11941
11942		super();
11943
11944		this.type = 'BoxGeometry';
11945
11946		this.parameters = {
11947			width: width,
11948			height: height,
11949			depth: depth,
11950			widthSegments: widthSegments,
11951			heightSegments: heightSegments,
11952			depthSegments: depthSegments
11953		};
11954
11955		const scope = this;
11956
11957		// segments
11958
11959		widthSegments = Math.floor( widthSegments );
11960		heightSegments = Math.floor( heightSegments );
11961		depthSegments = Math.floor( depthSegments );
11962
11963		// buffers
11964
11965		const indices = [];
11966		const vertices = [];
11967		const normals = [];
11968		const uvs = [];
11969
11970		// helper variables
11971
11972		let numberOfVertices = 0;
11973		let groupStart = 0;
11974
11975		// build each side of the box geometry
11976
11977		buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
11978		buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
11979		buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
11980		buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
11981		buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
11982		buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
11983
11984		// build geometry
11985
11986		this.setIndex( indices );
11987		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
11988		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
11989		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
11990
11991		function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
11992
11993			const segmentWidth = width / gridX;
11994			const segmentHeight = height / gridY;
11995
11996			const widthHalf = width / 2;
11997			const heightHalf = height / 2;
11998			const depthHalf = depth / 2;
11999
12000			const gridX1 = gridX + 1;
12001			const gridY1 = gridY + 1;
12002
12003			let vertexCounter = 0;
12004			let groupCount = 0;
12005
12006			const vector = new Vector3();
12007
12008			// generate vertices, normals and uvs
12009
12010			for ( let iy = 0; iy < gridY1; iy ++ ) {
12011
12012				const y = iy * segmentHeight - heightHalf;
12013
12014				for ( let ix = 0; ix < gridX1; ix ++ ) {
12015
12016					const x = ix * segmentWidth - widthHalf;
12017
12018					// set values to correct vector component
12019
12020					vector[ u ] = x * udir;
12021					vector[ v ] = y * vdir;
12022					vector[ w ] = depthHalf;
12023
12024					// now apply vector to vertex buffer
12025
12026					vertices.push( vector.x, vector.y, vector.z );
12027
12028					// set values to correct vector component
12029
12030					vector[ u ] = 0;
12031					vector[ v ] = 0;
12032					vector[ w ] = depth > 0 ? 1 : - 1;
12033
12034					// now apply vector to normal buffer
12035
12036					normals.push( vector.x, vector.y, vector.z );
12037
12038					// uvs
12039
12040					uvs.push( ix / gridX );
12041					uvs.push( 1 - ( iy / gridY ) );
12042
12043					// counters
12044
12045					vertexCounter += 1;
12046
12047				}
12048
12049			}
12050
12051			// indices
12052
12053			// 1. you need three indices to draw a single face
12054			// 2. a single segment consists of two faces
12055			// 3. so we need to generate six (2*3) indices per segment
12056
12057			for ( let iy = 0; iy < gridY; iy ++ ) {
12058
12059				for ( let ix = 0; ix < gridX; ix ++ ) {
12060
12061					const a = numberOfVertices + ix + gridX1 * iy;
12062					const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
12063					const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
12064					const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
12065
12066					// faces
12067
12068					indices.push( a, b, d );
12069					indices.push( b, c, d );
12070
12071					// increase counter
12072
12073					groupCount += 6;
12074
12075				}
12076
12077			}
12078
12079			// add a group to the geometry. this will ensure multi material support
12080
12081			scope.addGroup( groupStart, groupCount, materialIndex );
12082
12083			// calculate new start value for groups
12084
12085			groupStart += groupCount;
12086
12087			// update total number of vertices
12088
12089			numberOfVertices += vertexCounter;
12090
12091		}
12092
12093	}
12094
12095	copy( source ) {
12096
12097		super.copy( source );
12098
12099		this.parameters = Object.assign( {}, source.parameters );
12100
12101		return this;
12102
12103	}
12104
12105	static fromJSON( data ) {
12106
12107		return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
12108
12109	}
12110
12111}
12112
12113/**
12114 * Uniform Utilities
12115 */
12116
12117function cloneUniforms( src ) {
12118
12119	const dst = {};
12120
12121	for ( const u in src ) {
12122
12123		dst[ u ] = {};
12124
12125		for ( const p in src[ u ] ) {
12126
12127			const property = src[ u ][ p ];
12128
12129			if ( property && ( property.isColor ||
12130				property.isMatrix3 || property.isMatrix4 ||
12131				property.isVector2 || property.isVector3 || property.isVector4 ||
12132				property.isTexture || property.isQuaternion ) ) {
12133
12134				if ( property.isRenderTargetTexture ) {
12135
12136					console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' );
12137					dst[ u ][ p ] = null;
12138
12139				} else {
12140
12141					dst[ u ][ p ] = property.clone();
12142
12143				}
12144
12145			} else if ( Array.isArray( property ) ) {
12146
12147				dst[ u ][ p ] = property.slice();
12148
12149			} else {
12150
12151				dst[ u ][ p ] = property;
12152
12153			}
12154
12155		}
12156
12157	}
12158
12159	return dst;
12160
12161}
12162
12163function mergeUniforms( uniforms ) {
12164
12165	const merged = {};
12166
12167	for ( let u = 0; u < uniforms.length; u ++ ) {
12168
12169		const tmp = cloneUniforms( uniforms[ u ] );
12170
12171		for ( const p in tmp ) {
12172
12173			merged[ p ] = tmp[ p ];
12174
12175		}
12176
12177	}
12178
12179	return merged;
12180
12181}
12182
12183function cloneUniformsGroups( src ) {
12184
12185	const dst = [];
12186
12187	for ( let u = 0; u < src.length; u ++ ) {
12188
12189		dst.push( src[ u ].clone() );
12190
12191	}
12192
12193	return dst;
12194
12195}
12196
12197function getUnlitUniformColorSpace( renderer ) {
12198
12199	const currentRenderTarget = renderer.getRenderTarget();
12200
12201	if ( currentRenderTarget === null ) {
12202
12203		// https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398
12204		return renderer.outputColorSpace;
12205
12206	}
12207
12208	// https://github.com/mrdoob/three.js/issues/27868
12209	if ( currentRenderTarget.isXRRenderTarget === true ) {
12210
12211		return currentRenderTarget.texture.colorSpace;
12212
12213	}
12214
12215	return ColorManagement.workingColorSpace;
12216
12217}
12218
12219// Legacy
12220
12221const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
12222
12223var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
12224
12225var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
12226
12227class ShaderMaterial extends Material {
12228
12229	constructor( parameters ) {
12230
12231		super();
12232
12233		this.isShaderMaterial = true;
12234
12235		this.type = 'ShaderMaterial';
12236
12237		this.defines = {};
12238		this.uniforms = {};
12239		this.uniformsGroups = [];
12240
12241		this.vertexShader = default_vertex;
12242		this.fragmentShader = default_fragment;
12243
12244		this.linewidth = 1;
12245
12246		this.wireframe = false;
vendor: 5,162 bytes, lines 12247-12509
12247		this.wireframeLinewidth = 1;
12248
12249		this.fog = false; // set to use scene fog
12250		this.lights = false; // set to use scene lights
12251		this.clipping = false; // set to use user-defined clipping planes
12252
12253		this.forceSinglePass = true;
12254
12255		this.extensions = {
12256			clipCullDistance: false, // set to use vertex shader clipping
12257			multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID
12258		};
12259
12260		// When rendered geometry doesn't include these attributes but the material does,
12261		// use these default values in WebGL. This avoids errors when buffer data is missing.
12262		this.defaultAttributeValues = {
12263			'color': [ 1, 1, 1 ],
12264			'uv': [ 0, 0 ],
12265			'uv1': [ 0, 0 ]
12266		};
12267
12268		this.index0AttributeName = undefined;
12269		this.uniformsNeedUpdate = false;
12270
12271		this.glslVersion = null;
12272
12273		if ( parameters !== undefined ) {
12274
12275			this.setValues( parameters );
12276
12277		}
12278
12279	}
12280
12281	copy( source ) {
12282
12283		super.copy( source );
12284
12285		this.fragmentShader = source.fragmentShader;
12286		this.vertexShader = source.vertexShader;
12287
12288		this.uniforms = cloneUniforms( source.uniforms );
12289		this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups );
12290
12291		this.defines = Object.assign( {}, source.defines );
12292
12293		this.wireframe = source.wireframe;
12294		this.wireframeLinewidth = source.wireframeLinewidth;
12295
12296		this.fog = source.fog;
12297		this.lights = source.lights;
12298		this.clipping = source.clipping;
12299
12300		this.extensions = Object.assign( {}, source.extensions );
12301
12302		this.glslVersion = source.glslVersion;
12303
12304		return this;
12305
12306	}
12307
12308	toJSON( meta ) {
12309
12310		const data = super.toJSON( meta );
12311
12312		data.glslVersion = this.glslVersion;
12313		data.uniforms = {};
12314
12315		for ( const name in this.uniforms ) {
12316
12317			const uniform = this.uniforms[ name ];
12318			const value = uniform.value;
12319
12320			if ( value && value.isTexture ) {
12321
12322				data.uniforms[ name ] = {
12323					type: 't',
12324					value: value.toJSON( meta ).uuid
12325				};
12326
12327			} else if ( value && value.isColor ) {
12328
12329				data.uniforms[ name ] = {
12330					type: 'c',
12331					value: value.getHex()
12332				};
12333
12334			} else if ( value && value.isVector2 ) {
12335
12336				data.uniforms[ name ] = {
12337					type: 'v2',
12338					value: value.toArray()
12339				};
12340
12341			} else if ( value && value.isVector3 ) {
12342
12343				data.uniforms[ name ] = {
12344					type: 'v3',
12345					value: value.toArray()
12346				};
12347
12348			} else if ( value && value.isVector4 ) {
12349
12350				data.uniforms[ name ] = {
12351					type: 'v4',
12352					value: value.toArray()
12353				};
12354
12355			} else if ( value && value.isMatrix3 ) {
12356
12357				data.uniforms[ name ] = {
12358					type: 'm3',
12359					value: value.toArray()
12360				};
12361
12362			} else if ( value && value.isMatrix4 ) {
12363
12364				data.uniforms[ name ] = {
12365					type: 'm4',
12366					value: value.toArray()
12367				};
12368
12369			} else {
12370
12371				data.uniforms[ name ] = {
12372					value: value
12373				};
12374
12375				// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
12376
12377			}
12378
12379		}
12380
12381		if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
12382
12383		data.vertexShader = this.vertexShader;
12384		data.fragmentShader = this.fragmentShader;
12385
12386		data.lights = this.lights;
12387		data.clipping = this.clipping;
12388
12389		const extensions = {};
12390
12391		for ( const key in this.extensions ) {
12392
12393			if ( this.extensions[ key ] === true ) extensions[ key ] = true;
12394
12395		}
12396
12397		if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
12398
12399		return data;
12400
12401	}
12402
12403}
12404
12405class Camera extends Object3D {
12406
12407	constructor() {
12408
12409		super();
12410
12411		this.isCamera = true;
12412
12413		this.type = 'Camera';
12414
12415		this.matrixWorldInverse = new Matrix4();
12416
12417		this.projectionMatrix = new Matrix4();
12418		this.projectionMatrixInverse = new Matrix4();
12419
12420		this.coordinateSystem = WebGLCoordinateSystem;
12421
12422	}
12423
12424	copy( source, recursive ) {
12425
12426		super.copy( source, recursive );
12427
12428		this.matrixWorldInverse.copy( source.matrixWorldInverse );
12429
12430		this.projectionMatrix.copy( source.projectionMatrix );
12431		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
12432
12433		this.coordinateSystem = source.coordinateSystem;
12434
12435		return this;
12436
12437	}
12438
12439	getWorldDirection( target ) {
12440
12441		return super.getWorldDirection( target ).negate();
12442
12443	}
12444
12445	updateMatrixWorld( force ) {
12446
12447		super.updateMatrixWorld( force );
12448
12449		this.matrixWorldInverse.copy( this.matrixWorld ).invert();
12450
12451	}
12452
12453	updateWorldMatrix( updateParents, updateChildren ) {
12454
12455		super.updateWorldMatrix( updateParents, updateChildren );
12456
12457		this.matrixWorldInverse.copy( this.matrixWorld ).invert();
12458
12459	}
12460
12461	clone() {
12462
12463		return new this.constructor().copy( this );
12464
12465	}
12466
12467}
12468
12469const _v3$1 = /*@__PURE__*/ new Vector3();
12470const _minTarget = /*@__PURE__*/ new Vector2();
12471const _maxTarget = /*@__PURE__*/ new Vector2();
12472
12473
12474class PerspectiveCamera extends Camera {
12475
12476	constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
12477
12478		super();
12479
12480		this.isPerspectiveCamera = true;
12481
12482		this.type = 'PerspectiveCamera';
12483
12484		this.fov = fov;
12485		this.zoom = 1;
12486
12487		this.near = near;
12488		this.far = far;
12489		this.focus = 10;
12490
12491		this.aspect = aspect;
12492		this.view = null;
12493
12494		this.filmGauge = 35;	// width of the film (default in millimeters)
12495		this.filmOffset = 0;	// horizontal film offset (same unit as gauge)
12496
12497		this.updateProjectionMatrix();
12498
12499	}
12500
12501	copy( source, recursive ) {
12502
12503		super.copy( source, recursive );
12504
12505		this.fov = source.fov;
12506		this.zoom = source.zoom;
12507
12508		this.near = source.near;
12509		this.far = source.far;
vendor: 4,346 bytes, lines 12510-12683
12510		this.focus = source.focus;
12511
12512		this.aspect = source.aspect;
12513		this.view = source.view === null ? null : Object.assign( {}, source.view );
12514
12515		this.filmGauge = source.filmGauge;
12516		this.filmOffset = source.filmOffset;
12517
12518		return this;
12519
12520	}
12521
12522	/**
12523	 * Sets the FOV by focal length in respect to the current .filmGauge.
12524	 *
12525	 * The default film gauge is 35, so that the focal length can be specified for
12526	 * a 35mm (full frame) camera.
12527	 *
12528	 * Values for focal length and film gauge must have the same unit.
12529	 */
12530	setFocalLength( focalLength ) {
12531
12532		/** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
12533		const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
12534
12535		this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
12536		this.updateProjectionMatrix();
12537
12538	}
12539
12540	/**
12541	 * Calculates the focal length from the current .fov and .filmGauge.
12542	 */
12543	getFocalLength() {
12544
12545		const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
12546
12547		return 0.5 * this.getFilmHeight() / vExtentSlope;
12548
12549	}
12550
12551	getEffectiveFOV() {
12552
12553		return RAD2DEG * 2 * Math.atan(
12554			Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
12555
12556	}
12557
12558	getFilmWidth() {
12559
12560		// film not completely covered in portrait format (aspect < 1)
12561		return this.filmGauge * Math.min( this.aspect, 1 );
12562
12563	}
12564
12565	getFilmHeight() {
12566
12567		// film not completely covered in landscape format (aspect > 1)
12568		return this.filmGauge / Math.max( this.aspect, 1 );
12569
12570	}
12571
12572	/**
12573	 * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction.
12574	 * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle.
12575	 */
12576	getViewBounds( distance, minTarget, maxTarget ) {
12577
12578		_v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
12579
12580		minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
12581
12582		_v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
12583
12584		maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
12585
12586	}
12587
12588	/**
12589	 * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction.
12590	 * Copies the result into the target Vector2, where x is width and y is height.
12591	 */
12592	getViewSize( distance, target ) {
12593
12594		this.getViewBounds( distance, _minTarget, _maxTarget );
12595
12596		return target.subVectors( _maxTarget, _minTarget );
12597
12598	}
12599
12600	/**
12601	 * Sets an offset in a larger frustum. This is useful for multi-window or
12602	 * multi-monitor/multi-machine setups.
12603	 *
12604	 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
12605	 * the monitors are in grid like this
12606	 *
12607	 *   +---+---+---+
12608	 *   | A | B | C |
12609	 *   +---+---+---+
12610	 *   | D | E | F |
12611	 *   +---+---+---+
12612	 *
12613	 * then for each monitor you would call it like this
12614	 *
12615	 *   const w = 1920;
12616	 *   const h = 1080;
12617	 *   const fullWidth = w * 3;
12618	 *   const fullHeight = h * 2;
12619	 *
12620	 *   --A--
12621	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
12622	 *   --B--
12623	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
12624	 *   --C--
12625	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
12626	 *   --D--
12627	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
12628	 *   --E--
12629	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
12630	 *   --F--
12631	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
12632	 *
12633	 *   Note there is no reason monitors have to be the same size or in a grid.
12634	 */
12635	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
12636
12637		this.aspect = fullWidth / fullHeight;
12638
12639		if ( this.view === null ) {
12640
12641			this.view = {
12642				enabled: true,
12643				fullWidth: 1,
12644				fullHeight: 1,
12645				offsetX: 0,
12646				offsetY: 0,
12647				width: 1,
12648				height: 1
12649			};
12650
12651		}
12652
12653		this.view.enabled = true;
12654		this.view.fullWidth = fullWidth;
12655		this.view.fullHeight = fullHeight;
12656		this.view.offsetX = x;
12657		this.view.offsetY = y;
12658		this.view.width = width;
12659		this.view.height = height;
12660
12661		this.updateProjectionMatrix();
12662
12663	}
12664
12665	clearViewOffset() {
12666
12667		if ( this.view !== null ) {
12668
12669			this.view.enabled = false;
12670
12671		}
12672
12673		this.updateProjectionMatrix();
12674
12675	}
12676
12677	updateProjectionMatrix() {
12678
12679		const near = this.near;
12680		let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
12681		let height = 2 * top;
12682		let width = this.aspect * height;
12683		let left = - 0.5 * width;
vendor: 3,266 bytes, lines 12684-12820
12684		const view = this.view;
12685
12686		if ( this.view !== null && this.view.enabled ) {
12687
12688			const fullWidth = view.fullWidth,
12689				fullHeight = view.fullHeight;
12690
12691			left += view.offsetX * width / fullWidth;
12692			top -= view.offsetY * height / fullHeight;
12693			width *= view.width / fullWidth;
12694			height *= view.height / fullHeight;
12695
12696		}
12697
12698		const skew = this.filmOffset;
12699		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
12700
12701		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem );
12702
12703		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
12704
12705	}
12706
12707	toJSON( meta ) {
12708
12709		const data = super.toJSON( meta );
12710
12711		data.object.fov = this.fov;
12712		data.object.zoom = this.zoom;
12713
12714		data.object.near = this.near;
12715		data.object.far = this.far;
12716		data.object.focus = this.focus;
12717
12718		data.object.aspect = this.aspect;
12719
12720		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
12721
12722		data.object.filmGauge = this.filmGauge;
12723		data.object.filmOffset = this.filmOffset;
12724
12725		return data;
12726
12727	}
12728
12729}
12730
12731const fov = - 90; // negative fov is not an error
12732const aspect = 1;
12733
12734class CubeCamera extends Object3D {
12735
12736	constructor( near, far, renderTarget ) {
12737
12738		super();
12739
12740		this.type = 'CubeCamera';
12741
12742		this.renderTarget = renderTarget;
12743		this.coordinateSystem = null;
12744		this.activeMipmapLevel = 0;
12745
12746		const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
12747		cameraPX.layers = this.layers;
12748		this.add( cameraPX );
12749
12750		const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
12751		cameraNX.layers = this.layers;
12752		this.add( cameraNX );
12753
12754		const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
12755		cameraPY.layers = this.layers;
12756		this.add( cameraPY );
12757
12758		const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
12759		cameraNY.layers = this.layers;
12760		this.add( cameraNY );
12761
12762		const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
12763		cameraPZ.layers = this.layers;
12764		this.add( cameraPZ );
12765
12766		const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
12767		cameraNZ.layers = this.layers;
12768		this.add( cameraNZ );
12769
12770	}
12771
12772	updateCoordinateSystem() {
12773
12774		const coordinateSystem = this.coordinateSystem;
12775
12776		const cameras = this.children.concat();
12777
12778		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
12779
12780		for ( const camera of cameras ) this.remove( camera );
12781
12782		if ( coordinateSystem === WebGLCoordinateSystem ) {
12783
12784			cameraPX.up.set( 0, 1, 0 );
12785			cameraPX.lookAt( 1, 0, 0 );
12786
12787			cameraNX.up.set( 0, 1, 0 );
12788			cameraNX.lookAt( - 1, 0, 0 );
12789
12790			cameraPY.up.set( 0, 0, - 1 );
12791			cameraPY.lookAt( 0, 1, 0 );
12792
12793			cameraNY.up.set( 0, 0, 1 );
12794			cameraNY.lookAt( 0, - 1, 0 );
12795
12796			cameraPZ.up.set( 0, 1, 0 );
12797			cameraPZ.lookAt( 0, 0, 1 );
12798
12799			cameraNZ.up.set( 0, 1, 0 );
12800			cameraNZ.lookAt( 0, 0, - 1 );
12801
12802		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
12803
12804			cameraPX.up.set( 0, - 1, 0 );
12805			cameraPX.lookAt( - 1, 0, 0 );
12806
12807			cameraNX.up.set( 0, - 1, 0 );
12808			cameraNX.lookAt( 1, 0, 0 );
12809
12810			cameraPY.up.set( 0, 0, 1 );
12811			cameraPY.lookAt( 0, 1, 0 );
12812
12813			cameraNY.up.set( 0, 0, - 1 );
12814			cameraNY.lookAt( 0, - 1, 0 );
12815
12816			cameraPZ.up.set( 0, - 1, 0 );
12817			cameraPZ.lookAt( 0, 0, 1 );
12818
12819			cameraNZ.up.set( 0, - 1, 0 );
12820			cameraNZ.lookAt( 0, 0, - 
vendor: 7,494 bytes, lines 12820-13143
128201 );
12821
12822		} else {
12823
12824			throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
12825
12826		}
12827
12828		for ( const camera of cameras ) {
12829
12830			this.add( camera );
12831
12832			camera.updateMatrixWorld();
12833
12834		}
12835
12836	}
12837
12838	update( renderer, scene ) {
12839
12840		if ( this.parent === null ) this.updateMatrixWorld();
12841
12842		const { renderTarget, activeMipmapLevel } = this;
12843
12844		if ( this.coordinateSystem !== renderer.coordinateSystem ) {
12845
12846			this.coordinateSystem = renderer.coordinateSystem;
12847
12848			this.updateCoordinateSystem();
12849
12850		}
12851
12852		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
12853
12854		const currentRenderTarget = renderer.getRenderTarget();
12855		const currentActiveCubeFace = renderer.getActiveCubeFace();
12856		const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
12857
12858		const currentXrEnabled = renderer.xr.enabled;
12859
12860		renderer.xr.enabled = false;
12861
12862		const generateMipmaps = renderTarget.texture.generateMipmaps;
12863
12864		renderTarget.texture.generateMipmaps = false;
12865
12866		renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
12867		renderer.render( scene, cameraPX );
12868
12869		renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
12870		renderer.render( scene, cameraNX );
12871
12872		renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
12873		renderer.render( scene, cameraPY );
12874
12875		renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
12876		renderer.render( scene, cameraNY );
12877
12878		renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
12879		renderer.render( scene, cameraPZ );
12880
12881		// mipmaps are generated during the last call of render()
12882		// at this point, all sides of the cube render target are defined
12883
12884		renderTarget.texture.generateMipmaps = generateMipmaps;
12885
12886		renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
12887		renderer.render( scene, cameraNZ );
12888
12889		renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
12890
12891		renderer.xr.enabled = currentXrEnabled;
12892
12893		renderTarget.texture.needsPMREMUpdate = true;
12894
12895	}
12896
12897}
12898
12899class CubeTexture extends Texture {
12900
12901	constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
12902
12903		images = images !== undefined ? images : [];
12904		mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
12905
12906		super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
12907
12908		this.isCubeTexture = true;
12909
12910		this.flipY = false;
12911
12912	}
12913
12914	get images() {
12915
12916		return this.image;
12917
12918	}
12919
12920	set images( value ) {
12921
12922		this.image = value;
12923
12924	}
12925
12926}
12927
12928class WebGLCubeRenderTarget extends WebGLRenderTarget {
12929
12930	constructor( size = 1, options = {} ) {
12931
12932		super( size, size, options );
12933
12934		this.isWebGLCubeRenderTarget = true;
12935
12936		const image = { width: size, height: size, depth: 1 };
12937		const images = [ image, image, image, image, image, image ];
12938
12939		this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
12940
12941		// By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
12942		// in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
12943		// in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
12944
12945		// three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
12946		// and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
12947		// as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
12948
12949		this.texture.isRenderTargetTexture = true;
12950
12951		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
12952		this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
12953
12954	}
12955
12956	fromEquirectangularTexture( renderer, texture ) {
12957
12958		this.texture.type = texture.type;
12959		this.texture.colorSpace = texture.colorSpace;
12960
12961		this.texture.generateMipmaps = texture.generateMipmaps;
12962		this.texture.minFilter = texture.minFilter;
12963		this.texture.magFilter = texture.magFilter;
12964
12965		const shader = {
12966
12967			uniforms: {
12968				tEquirect: { value: null },
12969			},
12970
12971			vertexShader: /* glsl */`
12972
12973				varying vec3 vWorldDirection;
12974
12975				vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
12976
12977					return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
12978
12979				}
12980
12981				void main() {
12982
12983					vWorldDirection = transformDirection( position, modelMatrix );
12984
12985					#include <begin_vertex>
12986					#include <project_vertex>
12987
12988				}
12989			`,
12990
12991			fragmentShader: /* glsl */`
12992
12993				uniform sampler2D tEquirect;
12994
12995				varying vec3 vWorldDirection;
12996
12997				#include <common>
12998
12999				void main() {
13000
13001					vec3 direction = normalize( vWorldDirection );
13002
13003					vec2 sampleUV = equirectUv( direction );
13004
13005					gl_FragColor = texture2D( tEquirect, sampleUV );
13006
13007				}
13008			`
13009		};
13010
13011		const geometry = new BoxGeometry( 5, 5, 5 );
13012
13013		const material = new ShaderMaterial( {
13014
13015			name: 'CubemapFromEquirect',
13016
13017			uniforms: cloneUniforms( shader.uniforms ),
13018			vertexShader: shader.vertexShader,
13019			fragmentShader: shader.fragmentShader,
13020			side: BackSide,
13021			blending: NoBlending
13022
13023		} );
13024
13025		material.uniforms.tEquirect.value = texture;
13026
13027		const mesh = new Mesh( geometry, material );
13028
13029		const currentMinFilter = texture.minFilter;
13030
13031		// Avoid blurred poles
13032		if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter;
13033
13034		const camera = new CubeCamera( 1, 10, this );
13035		camera.update( renderer, mesh );
13036
13037		texture.minFilter = currentMinFilter;
13038
13039		mesh.geometry.dispose();
13040		mesh.material.dispose();
13041
13042		return this;
13043
13044	}
13045
13046	clear( renderer, color, depth, stencil ) {
13047
13048		const currentRenderTarget = renderer.getRenderTarget();
13049
13050		for ( let i = 0; i < 6; i ++ ) {
13051
13052			renderer.setRenderTarget( this, i );
13053
13054			renderer.clear( color, depth, stencil );
13055
13056		}
13057
13058		renderer.setRenderTarget( currentRenderTarget );
13059
13060	}
13061
13062}
13063
13064const _vector1 = /*@__PURE__*/ new Vector3();
13065const _vector2 = /*@__PURE__*/ new Vector3();
13066const _normalMatrix = /*@__PURE__*/ new Matrix3();
13067
13068class Plane {
13069
13070	constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) {
13071
13072		this.isPlane = true;
13073
13074		// normal is assumed to be normalized
13075
13076		this.normal = normal;
13077		this.constant = constant;
13078
13079	}
13080
13081	set( normal, constant ) {
13082
13083		this.normal.copy( normal );
13084		this.constant = constant;
13085
13086		return this;
13087
13088	}
13089
13090	setComponents( x, y, z, w ) {
13091
13092		this.normal.set( x, y, z );
13093		this.constant = w;
13094
13095		return this;
13096
13097	}
13098
13099	setFromNormalAndCoplanarPoint( normal, point ) {
13100
13101		this.normal.copy( normal );
13102		this.constant = - point.dot( this.normal );
13103
13104		return this;
13105
13106	}
13107
13108	setFromCoplanarPoints( a, b, c ) {
13109
13110		const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
13111
13112		// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
13113
13114		this.setFromNormalAndCoplanarPoint( normal, a );
13115
13116		return this;
13117
13118	}
13119
13120	copy( plane ) {
13121
13122		this.normal.copy( plane.normal );
13123		this.constant = plane.constant;
13124
13125		return this;
13126
13127	}
13128
13129	normalize() {
13130
13131		// Note: will lead to a divide by zero if the plane is invalid.
13132
13133		const inverseNormalLength = 1.0 / this.normal.length();
13134		this.normal.multiplyScalar( inverseNormalLength );
13135		this.constant *= inverseNormalLength;
13136
13137		return this;
13138
13139	}
13140
13141	negate() {
13142
13143		this.constant *= -
vendor: 15,925 bytes, lines 13143-13806
13143 1;
13144		this.normal.negate();
13145
13146		return this;
13147
13148	}
13149
13150	distanceToPoint( point ) {
13151
13152		return this.normal.dot( point ) + this.constant;
13153
13154	}
13155
13156	distanceToSphere( sphere ) {
13157
13158		return this.distanceToPoint( sphere.center ) - sphere.radius;
13159
13160	}
13161
13162	projectPoint( point, target ) {
13163
13164		return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) );
13165
13166	}
13167
13168	intersectLine( line, target ) {
13169
13170		const direction = line.delta( _vector1 );
13171
13172		const denominator = this.normal.dot( direction );
13173
13174		if ( denominator === 0 ) {
13175
13176			// line is coplanar, return origin
13177			if ( this.distanceToPoint( line.start ) === 0 ) {
13178
13179				return target.copy( line.start );
13180
13181			}
13182
13183			// Unsure if this is the correct method to handle this case.
13184			return null;
13185
13186		}
13187
13188		const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
13189
13190		if ( t < 0 || t > 1 ) {
13191
13192			return null;
13193
13194		}
13195
13196		return target.copy( line.start ).addScaledVector( direction, t );
13197
13198	}
13199
13200	intersectsLine( line ) {
13201
13202		// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
13203
13204		const startSign = this.distanceToPoint( line.start );
13205		const endSign = this.distanceToPoint( line.end );
13206
13207		return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
13208
13209	}
13210
13211	intersectsBox( box ) {
13212
13213		return box.intersectsPlane( this );
13214
13215	}
13216
13217	intersectsSphere( sphere ) {
13218
13219		return sphere.intersectsPlane( this );
13220
13221	}
13222
13223	coplanarPoint( target ) {
13224
13225		return target.copy( this.normal ).multiplyScalar( - this.constant );
13226
13227	}
13228
13229	applyMatrix4( matrix, optionalNormalMatrix ) {
13230
13231		const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
13232
13233		const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
13234
13235		const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
13236
13237		this.constant = - referencePoint.dot( normal );
13238
13239		return this;
13240
13241	}
13242
13243	translate( offset ) {
13244
13245		this.constant -= offset.dot( this.normal );
13246
13247		return this;
13248
13249	}
13250
13251	equals( plane ) {
13252
13253		return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
13254
13255	}
13256
13257	clone() {
13258
13259		return new this.constructor().copy( this );
13260
13261	}
13262
13263}
13264
13265const _sphere$5 = /*@__PURE__*/ new Sphere();
13266const _vector$7 = /*@__PURE__*/ new Vector3();
13267
13268class Frustum {
13269
13270	constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
13271
13272		this.planes = [ p0, p1, p2, p3, p4, p5 ];
13273
13274	}
13275
13276	set( p0, p1, p2, p3, p4, p5 ) {
13277
13278		const planes = this.planes;
13279
13280		planes[ 0 ].copy( p0 );
13281		planes[ 1 ].copy( p1 );
13282		planes[ 2 ].copy( p2 );
13283		planes[ 3 ].copy( p3 );
13284		planes[ 4 ].copy( p4 );
13285		planes[ 5 ].copy( p5 );
13286
13287		return this;
13288
13289	}
13290
13291	copy( frustum ) {
13292
13293		const planes = this.planes;
13294
13295		for ( let i = 0; i < 6; i ++ ) {
13296
13297			planes[ i ].copy( frustum.planes[ i ] );
13298
13299		}
13300
13301		return this;
13302
13303	}
13304
13305	setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) {
13306
13307		const planes = this.planes;
13308		const me = m.elements;
13309		const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
13310		const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
13311		const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
13312		const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
13313
13314		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
13315		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
13316		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
13317		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
13318		planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
13319
13320		if ( coordinateSystem === WebGLCoordinateSystem ) {
13321
13322			planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
13323
13324		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
13325
13326			planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
13327
13328		} else {
13329
13330			throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
13331
13332		}
13333
13334		return this;
13335
13336	}
13337
13338	intersectsObject( object ) {
13339
13340		if ( object.boundingSphere !== undefined ) {
13341
13342			if ( object.boundingSphere === null ) object.computeBoundingSphere();
13343
13344			_sphere$5.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld );
13345
13346		} else {
13347
13348			const geometry = object.geometry;
13349
13350			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
13351
13352			_sphere$5.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
13353
13354		}
13355
13356		return this.intersectsSphere( _sphere$5 );
13357
13358	}
13359
13360	intersectsSprite( sprite ) {
13361
13362		_sphere$5.center.set( 0, 0, 0 );
13363		_sphere$5.radius = 0.7071067811865476;
13364		_sphere$5.applyMatrix4( sprite.matrixWorld );
13365
13366		return this.intersectsSphere( _sphere$5 );
13367
13368	}
13369
13370	intersectsSphere( sphere ) {
13371
13372		const planes = this.planes;
13373		const center = sphere.center;
13374		const negRadius = - sphere.radius;
13375
13376		for ( let i = 0; i < 6; i ++ ) {
13377
13378			const distance = planes[ i ].distanceToPoint( center );
13379
13380			if ( distance < negRadius ) {
13381
13382				return false;
13383
13384			}
13385
13386		}
13387
13388		return true;
13389
13390	}
13391
13392	intersectsBox( box ) {
13393
13394		const planes = this.planes;
13395
13396		for ( let i = 0; i < 6; i ++ ) {
13397
13398			const plane = planes[ i ];
13399
13400			// corner at max distance
13401
13402			_vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x;
13403			_vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y;
13404			_vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z;
13405
13406			if ( plane.distanceToPoint( _vector$7 ) < 0 ) {
13407
13408				return false;
13409
13410			}
13411
13412		}
13413
13414		return true;
13415
13416	}
13417
13418	containsPoint( point ) {
13419
13420		const planes = this.planes;
13421
13422		for ( let i = 0; i < 6; i ++ ) {
13423
13424			if ( planes[ i ].distanceToPoint( point ) < 0 ) {
13425
13426				return false;
13427
13428			}
13429
13430		}
13431
13432		return true;
13433
13434	}
13435
13436	clone() {
13437
13438		return new this.constructor().copy( this );
13439
13440	}
13441
13442}
13443
13444function WebGLAnimation() {
13445
13446	let context = null;
13447	let isAnimating = false;
13448	let animationLoop = null;
13449	let requestId = null;
13450
13451	function onAnimationFrame( time, frame ) {
13452
13453		animationLoop( time, frame );
13454
13455		requestId = context.requestAnimationFrame( onAnimationFrame );
13456
13457	}
13458
13459	return {
13460
13461		start: function () {
13462
13463			if ( isAnimating === true ) return;
13464			if ( animationLoop === null ) return;
13465
13466			requestId = context.requestAnimationFrame( onAnimationFrame );
13467
13468			isAnimating = true;
13469
13470		},
13471
13472		stop: function () {
13473
13474			context.cancelAnimationFrame( requestId );
13475
13476			isAnimating = false;
13477
13478		},
13479
13480		setAnimationLoop: function ( callback ) {
13481
13482			animationLoop = callback;
13483
13484		},
13485
13486		setContext: function ( value ) {
13487
13488			context = value;
13489
13490		}
13491
13492	};
13493
13494}
13495
13496function WebGLAttributes( gl ) {
13497
13498	const buffers = new WeakMap();
13499
13500	function createBuffer( attribute, bufferType ) {
13501
13502		const array = attribute.array;
13503		const usage = attribute.usage;
13504		const size = array.byteLength;
13505
13506		const buffer = gl.createBuffer();
13507
13508		gl.bindBuffer( bufferType, buffer );
13509		gl.bufferData( bufferType, array, usage );
13510
13511		attribute.onUploadCallback();
13512
13513		let type;
13514
13515		if ( array instanceof Float32Array ) {
13516
13517			type = gl.FLOAT;
13518
13519		} else if ( array instanceof Uint16Array ) {
13520
13521			if ( attribute.isFloat16BufferAttribute ) {
13522
13523				type = gl.HALF_FLOAT;
13524
13525			} else {
13526
13527				type = gl.UNSIGNED_SHORT;
13528
13529			}
13530
13531		} else if ( array instanceof Int16Array ) {
13532
13533			type = gl.SHORT;
13534
13535		} else if ( array instanceof Uint32Array ) {
13536
13537			type = gl.UNSIGNED_INT;
13538
13539		} else if ( array instanceof Int32Array ) {
13540
13541			type = gl.INT;
13542
13543		} else if ( array instanceof Int8Array ) {
13544
13545			type = gl.BYTE;
13546
13547		} else if ( array instanceof Uint8Array ) {
13548
13549			type = gl.UNSIGNED_BYTE;
13550
13551		} else if ( array instanceof Uint8ClampedArray ) {
13552
13553			type = gl.UNSIGNED_BYTE;
13554
13555		} else {
13556
13557			throw new Error( 'THREE.WebGLAttributes: Unsupported buffer data format: ' + array );
13558
13559		}
13560
13561		return {
13562			buffer: buffer,
13563			type: type,
13564			bytesPerElement: array.BYTES_PER_ELEMENT,
13565			version: attribute.version,
13566			size: size
13567		};
13568
13569	}
13570
13571	function updateBuffer( buffer, attribute, bufferType ) {
13572
13573		const array = attribute.array;
13574		const updateRange = attribute._updateRange; // @deprecated, r159
13575		const updateRanges = attribute.updateRanges;
13576
13577		gl.bindBuffer( bufferType, buffer );
13578
13579		if ( updateRange.count === - 1 && updateRanges.length === 0 ) {
13580
13581			// Not using update ranges
13582			gl.bufferSubData( bufferType, 0, array );
13583
13584		}
13585
13586		if ( updateRanges.length !== 0 ) {
13587
13588			for ( let i = 0, l = updateRanges.length; i < l; i ++ ) {
13589
13590				const range = updateRanges[ i ];
13591
13592				gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
13593					array, range.start, range.count );
13594
13595			}
13596
13597			attribute.clearUpdateRanges();
13598
13599		}
13600
13601		// @deprecated, r159
13602		if ( updateRange.count !== - 1 ) {
13603
13604			gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
13605				array, updateRange.offset, updateRange.count );
13606
13607			updateRange.count = - 1; // reset range
13608
13609		}
13610
13611		attribute.onUploadCallback();
13612
13613	}
13614
13615	//
13616
13617	function get( attribute ) {
13618
13619		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13620
13621		return buffers.get( attribute );
13622
13623	}
13624
13625	function remove( attribute ) {
13626
13627		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13628
13629		const data = buffers.get( attribute );
13630
13631		if ( data ) {
13632
13633			gl.deleteBuffer( data.buffer );
13634
13635			buffers.delete( attribute );
13636
13637		}
13638
13639	}
13640
13641	function update( attribute, bufferType ) {
13642
13643		if ( attribute.isGLBufferAttribute ) {
13644
13645			const cached = buffers.get( attribute );
13646
13647			if ( ! cached || cached.version < attribute.version ) {
13648
13649				buffers.set( attribute, {
13650					buffer: attribute.buffer,
13651					type: attribute.type,
13652					bytesPerElement: attribute.elementSize,
13653					version: attribute.version
13654				} );
13655
13656			}
13657
13658			return;
13659
13660		}
13661
13662		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13663
13664		const data = buffers.get( attribute );
13665
13666		if ( data === undefined ) {
13667
13668			buffers.set( attribute, createBuffer( attribute, bufferType ) );
13669
13670		} else if ( data.version < attribute.version ) {
13671
13672			if ( data.size !== attribute.array.byteLength ) {
13673
13674				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.' );
13675
13676			}
13677
13678			updateBuffer( data.buffer, attribute, bufferType );
13679
13680			data.version = attribute.version;
13681
13682		}
13683
13684	}
13685
13686	return {
13687
13688		get: get,
13689		remove: remove,
13690		update: update
13691
13692	};
13693
13694}
13695
13696class PlaneGeometry extends BufferGeometry {
13697
13698	constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
13699
13700		super();
13701
13702		this.type = 'PlaneGeometry';
13703
13704		this.parameters = {
13705			width: width,
13706			height: height,
13707			widthSegments: widthSegments,
13708			heightSegments: heightSegments
13709		};
13710
13711		const width_half = width / 2;
13712		const height_half = height / 2;
13713
13714		const gridX = Math.floor( widthSegments );
13715		const gridY = Math.floor( heightSegments );
13716
13717		const gridX1 = gridX + 1;
13718		const gridY1 = gridY + 1;
13719
13720		const segment_width = width / gridX;
13721		const segment_height = height / gridY;
13722
13723		//
13724
13725		const indices = [];
13726		const vertices = [];
13727		const normals = [];
13728		const uvs = [];
13729
13730		for ( let iy = 0; iy < gridY1; iy ++ ) {
13731
13732			const y = iy * segment_height - height_half;
13733
13734			for ( let ix = 0; ix < gridX1; ix ++ ) {
13735
13736				const x = ix * segment_width - width_half;
13737
13738				vertices.push( x, - y, 0 );
13739
13740				normals.push( 0, 0, 1 );
13741
13742				uvs.push( ix / gridX );
13743				uvs.push( 1 - ( iy / gridY ) );
13744
13745			}
13746
13747		}
13748
13749		for ( let iy = 0; iy < gridY; iy ++ ) {
13750
13751			for ( let ix = 0; ix < gridX; ix ++ ) {
13752
13753				const a = ix + gridX1 * iy;
13754				const b = ix + gridX1 * ( iy + 1 );
13755				const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
13756				const d = ( ix + 1 ) + gridX1 * iy;
13757
13758				indices.push( a, b, d );
13759				indices.push( b, c, d );
13760
13761			}
13762
13763		}
13764
13765		this.setIndex( indices );
13766		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
13767		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
13768		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
13769
13770	}
13771
13772	copy( source ) {
13773
13774		super.copy( source );
13775
13776		this.parameters = Object.assign( {}, source.parameters );
13777
13778		return this;
13779
13780	}
13781
13782	static fromJSON( data ) {
13783
13784		return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
13785
13786	}
13787
13788}
13789
13790var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif";
13791
13792var 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";
13793
13794var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif";
13795
13796var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
13797
13798var 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";
13799
13800var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif";
13801
13802var 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";
13803
13804var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
13805
13806var 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\n#ifdef USE_BATCHING_COLOR\n\tuniform sampler2D batchingColorTexture;\n\tvec3 getBatchingColor( const in float i ) {\n\t\tint size = textureSize( batchingColorTexture, 0 ).x;\n\t\tint j = int( i );\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\treturn texelFetch( batchingColorTexture, ivec2( x, y ), 0 ).rgb
vendor: 7,693 bytes, lines 13806-13832
13806;\n\t}\n#endif";
13807
13808var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif";
13809
13810var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif";
13811
13812var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
13813
13814var 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";
13815
13816var 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";
13817
13818var 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";
13819
13820var 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";
13821
13822var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
13823
13824var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
13825
13826var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
13827
13828var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif";
13829
13830var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif";
13831
13832var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )
13832 || defined( USE_BATCHING_COLOR )\n\tvarying vec3 vColor;\n#endif";
13833
13834var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR ) || defined( USE_BATCHING_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\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( batchId );\n\tvColor.xyz *= batching
vendor: 11,862 bytes, lines 13834-13862
13834Color.xyz;\n#endif";
13835
13836var 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";
13837
13838var 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";
13839
13840var 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";
13841
13842var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
13843
13844var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif";
13845
13846var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
13847
13848var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
13849
13850var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
13851
13852var 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}";
13853
13854var 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";
13855
13856var 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";
13857
13858var 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";
13859
13860var 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";
13861
13862var 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}
vendor: 5,745 bytes, lines 13862-13880
13862 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";
13863
13864var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif";
13865
13866var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif";
13867
13868var 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";
13869
13870var 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";
13871
13872var 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}";
13873
13874var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
13875
13876var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;";
13877
13878var 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";
13879
13880var 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\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n}\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}
vendor: 8,222 bytes, lines 13880-13892
13880\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";
13881
13882var 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";
13883
13884var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
13885
13886var 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";
13887
13888var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
13889
13890var 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";
13891
13892var 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_
13892DISPERSION\n\tmaterial.dispersion = dispersion;\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";
13893
13894var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion
vendor: 22,309 bytes, lines 13894-13902
13894;\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}";
13895
13896var 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";
13897
13898var 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";
13899
13900var 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";
13901
13902var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF )
13902\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
13903
13904var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
13905
13906var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
13907
13908var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif";
13909
13910var 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";
13911
13912var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
13913
13914var 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";
13915
13916var 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";
13917
13918var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
13919
13920var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
13921
13922var 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";
13923
13924var morphcolor_vertex = "#if defined( USE_MORPHCOLORS )\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";
13925
13926var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif";
13927
13928var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif";
13929
13930var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}
vendor: 15,324 bytes, lines 13930-13968
13930\n#endif";
13931
13932var 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;";
13933
13934var 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";
13935
13936var 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";
13937
13938var 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";
13939
13940var 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";
13941
13942var 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";
13943
13944var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif";
13945
13946var 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";
13947
13948var 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";
13949
13950var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif";
13951
13952var 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 );";
13953
13954var 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}";
13955
13956var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
13957
13958var 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;";
13959
13960var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
13961
13962var 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";
13963
13964var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
13965
13966var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
13967
13968var 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
13968float 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: 9,652 bytes, lines 13968-13990
13968\n\t}\n#endif";
13969
13970var 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";
13971
13972var 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";
13973
13974var 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}";
13975
13976var 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";
13977
13978var 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";
13979
13980var 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";
13981
13982var 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";
13983
13984var 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";
13985
13986var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
13987
13988var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
13989
13990var 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\t
13990const float StartCompression = 0.8 - 0.04;\n\tconst float 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, vec3( newPeak ), g );\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
13991
13992var 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.dispersion, 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";
13993
13994var 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 dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t
vendor: 6,265 bytes, lines 13994-14000
13994\n\t\t#endif\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";
13995
13996var 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";
13997
13998var 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";
13999
14000var 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: 25,481 bytes, lines 14000-14054
14000\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";
14001
14002var 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";
14003
14004const 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}";
14005
14006const 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}";
14007
14008const 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}";
14009
14010const 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}";
14011
14012const 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}";
14013
14014const 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}";
14015
14016const 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}";
14017
14018const 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}";
14019
14020const 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}";
14021
14022const 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}";
14023
14024const 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}";
14025
14026const 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}";
14027
14028const 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}";
14029
14030const 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}";
14031
14032const 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}";
14033
14034const 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}";
14035
14036const 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}";
14037
14038const 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}";
14039
14040const 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}";
14041
14042const 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}";
14043
14044const 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}";
14045
14046const 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}";
14047
14048const 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}";
14049
14050const 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}";
14051
14052const 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}";
14053
14054const 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;
vendor: 3,685 bytes, line 14054
14054\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\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}"
vendor: 20,991 bytes, lines 14054-14570
14054;
14055
14056const 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}";
14057
14058const 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}";
14059
14060const 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}";
14061
14062const 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}";
14063
14064const 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}";
14065
14066const 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}";
14067
14068const 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}";
14069
14070const 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}";
14071
14072const ShaderChunk = {
14073	alphahash_fragment: alphahash_fragment,
14074	alphahash_pars_fragment: alphahash_pars_fragment,
14075	alphamap_fragment: alphamap_fragment,
14076	alphamap_pars_fragment: alphamap_pars_fragment,
14077	alphatest_fragment: alphatest_fragment,
14078	alphatest_pars_fragment: alphatest_pars_fragment,
14079	aomap_fragment: aomap_fragment,
14080	aomap_pars_fragment: aomap_pars_fragment,
14081	batching_pars_vertex: batching_pars_vertex,
14082	batching_vertex: batching_vertex,
14083	begin_vertex: begin_vertex,
14084	beginnormal_vertex: beginnormal_vertex,
14085	bsdfs: bsdfs,
14086	iridescence_fragment: iridescence_fragment,
14087	bumpmap_pars_fragment: bumpmap_pars_fragment,
14088	clipping_planes_fragment: clipping_planes_fragment,
14089	clipping_planes_pars_fragment: clipping_planes_pars_fragment,
14090	clipping_planes_pars_vertex: clipping_planes_pars_vertex,
14091	clipping_planes_vertex: clipping_planes_vertex,
14092	color_fragment: color_fragment,
14093	color_pars_fragment: color_pars_fragment,
14094	color_pars_vertex: color_pars_vertex,
14095	color_vertex: color_vertex,
14096	common: common,
14097	cube_uv_reflection_fragment: cube_uv_reflection_fragment,
14098	defaultnormal_vertex: defaultnormal_vertex,
14099	displacementmap_pars_vertex: displacementmap_pars_vertex,
14100	displacementmap_vertex: displacementmap_vertex,
14101	emissivemap_fragment: emissivemap_fragment,
14102	emissivemap_pars_fragment: emissivemap_pars_fragment,
14103	colorspace_fragment: colorspace_fragment,
14104	colorspace_pars_fragment: colorspace_pars_fragment,
14105	envmap_fragment: envmap_fragment,
14106	envmap_common_pars_fragment: envmap_common_pars_fragment,
14107	envmap_pars_fragment: envmap_pars_fragment,
14108	envmap_pars_vertex: envmap_pars_vertex,
14109	envmap_physical_pars_fragment: envmap_physical_pars_fragment,
14110	envmap_vertex: envmap_vertex,
14111	fog_vertex: fog_vertex,
14112	fog_pars_vertex: fog_pars_vertex,
14113	fog_fragment: fog_fragment,
14114	fog_pars_fragment: fog_pars_fragment,
14115	gradientmap_pars_fragment: gradientmap_pars_fragment,
14116	lightmap_pars_fragment: lightmap_pars_fragment,
14117	lights_lambert_fragment: lights_lambert_fragment,
14118	lights_lambert_pars_fragment: lights_lambert_pars_fragment,
14119	lights_pars_begin: lights_pars_begin,
14120	lights_toon_fragment: lights_toon_fragment,
14121	lights_toon_pars_fragment: lights_toon_pars_fragment,
14122	lights_phong_fragment: lights_phong_fragment,
14123	lights_phong_pars_fragment: lights_phong_pars_fragment,
14124	lights_physical_fragment: lights_physical_fragment,
14125	lights_physical_pars_fragment: lights_physical_pars_fragment,
14126	lights_fragment_begin: lights_fragment_begin,
14127	lights_fragment_maps: lights_fragment_maps,
14128	lights_fragment_end: lights_fragment_end,
14129	logdepthbuf_fragment: logdepthbuf_fragment,
14130	logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
14131	logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
14132	logdepthbuf_vertex: logdepthbuf_vertex,
14133	map_fragment: map_fragment,
14134	map_pars_fragment: map_pars_fragment,
14135	map_particle_fragment: map_particle_fragment,
14136	map_particle_pars_fragment: map_particle_pars_fragment,
14137	metalnessmap_fragment: metalnessmap_fragment,
14138	metalnessmap_pars_fragment: metalnessmap_pars_fragment,
14139	morphinstance_vertex: morphinstance_vertex,
14140	morphcolor_vertex: morphcolor_vertex,
14141	morphnormal_vertex: morphnormal_vertex,
14142	morphtarget_pars_vertex: morphtarget_pars_vertex,
14143	morphtarget_vertex: morphtarget_vertex,
14144	normal_fragment_begin: normal_fragment_begin,
14145	normal_fragment_maps: normal_fragment_maps,
14146	normal_pars_fragment: normal_pars_fragment,
14147	normal_pars_vertex: normal_pars_vertex,
14148	normal_vertex: normal_vertex,
14149	normalmap_pars_fragment: normalmap_pars_fragment,
14150	clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
14151	clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
14152	clearcoat_pars_fragment: clearcoat_pars_fragment,
14153	iridescence_pars_fragment: iridescence_pars_fragment,
14154	opaque_fragment: opaque_fragment,
14155	packing: packing,
14156	premultiplied_alpha_fragment: premultiplied_alpha_fragment,
14157	project_vertex: project_vertex,
14158	dithering_fragment: dithering_fragment,
14159	dithering_pars_fragment: dithering_pars_fragment,
14160	roughnessmap_fragment: roughnessmap_fragment,
14161	roughnessmap_pars_fragment: roughnessmap_pars_fragment,
14162	shadowmap_pars_fragment: shadowmap_pars_fragment,
14163	shadowmap_pars_vertex: shadowmap_pars_vertex,
14164	shadowmap_vertex: shadowmap_vertex,
14165	shadowmask_pars_fragment: shadowmask_pars_fragment,
14166	skinbase_vertex: skinbase_vertex,
14167	skinning_pars_vertex: skinning_pars_vertex,
14168	skinning_vertex: skinning_vertex,
14169	skinnormal_vertex: skinnormal_vertex,
14170	specularmap_fragment: specularmap_fragment,
14171	specularmap_pars_fragment: specularmap_pars_fragment,
14172	tonemapping_fragment: tonemapping_fragment,
14173	tonemapping_pars_fragment: tonemapping_pars_fragment,
14174	transmission_fragment: transmission_fragment,
14175	transmission_pars_fragment: transmission_pars_fragment,
14176	uv_pars_fragment: uv_pars_fragment,
14177	uv_pars_vertex: uv_pars_vertex,
14178	uv_vertex: uv_vertex,
14179	worldpos_vertex: worldpos_vertex,
14180
14181	background_vert: vertex$h,
14182	background_frag: fragment$h,
14183	backgroundCube_vert: vertex$g,
14184	backgroundCube_frag: fragment$g,
14185	cube_vert: vertex$f,
14186	cube_frag: fragment$f,
14187	depth_vert: vertex$e,
14188	depth_frag: fragment$e,
14189	distanceRGBA_vert: vertex$d,
14190	distanceRGBA_frag: fragment$d,
14191	equirect_vert: vertex$c,
14192	equirect_frag: fragment$c,
14193	linedashed_vert: vertex$b,
14194	linedashed_frag: fragment$b,
14195	meshbasic_vert: vertex$a,
14196	meshbasic_frag: fragment$a,
14197	meshlambert_vert: vertex$9,
14198	meshlambert_frag: fragment$9,
14199	meshmatcap_vert: vertex$8,
14200	meshmatcap_frag: fragment$8,
14201	meshnormal_vert: vertex$7,
14202	meshnormal_frag: fragment$7,
14203	meshphong_vert: vertex$6,
14204	meshphong_frag: fragment$6,
14205	meshphysical_vert: vertex$5,
14206	meshphysical_frag: fragment$5,
14207	meshtoon_vert: vertex$4,
14208	meshtoon_frag: fragment$4,
14209	points_vert: vertex$3,
14210	points_frag: fragment$3,
14211	shadow_vert: vertex$2,
14212	shadow_frag: fragment$2,
14213	sprite_vert: vertex$1,
14214	sprite_frag: fragment$1
14215};
14216
14217/**
14218 * Uniforms library for shared webgl shaders
14219 */
14220
14221const UniformsLib = {
14222
14223	common: {
14224
14225		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
14226		opacity: { value: 1.0 },
14227
14228		map: { value: null },
14229		mapTransform: { value: /*@__PURE__*/ new Matrix3() },
14230
14231		alphaMap: { value: null },
14232		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14233
14234		alphaTest: { value: 0 }
14235
14236	},
14237
14238	specularmap: {
14239
14240		specularMap: { value: null },
14241		specularMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14242
14243	},
14244
14245	envmap: {
14246
14247		envMap: { value: null },
14248		envMapRotation: { value: /*@__PURE__*/ new Matrix3() },
14249		flipEnvMap: { value: - 1 },
14250		reflectivity: { value: 1.0 }, // basic, lambert, phong
14251		ior: { value: 1.5 }, // physical
14252		refractionRatio: { value: 0.98 }, // basic, lambert, phong
14253
14254	},
14255
14256	aomap: {
14257
14258		aoMap: { value: null },
14259		aoMapIntensity: { value: 1 },
14260		aoMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14261
14262	},
14263
14264	lightmap: {
14265
14266		lightMap: { value: null },
14267		lightMapIntensity: { value: 1 },
14268		lightMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14269
14270	},
14271
14272	bumpmap: {
14273
14274		bumpMap: { value: null },
14275		bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14276		bumpScale: { value: 1 }
14277
14278	},
14279
14280	normalmap: {
14281
14282		normalMap: { value: null },
14283		normalMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14284		normalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) }
14285
14286	},
14287
14288	displacementmap: {
14289
14290		displacementMap: { value: null },
14291		displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14292		displacementScale: { value: 1 },
14293		displacementBias: { value: 0 }
14294
14295	},
14296
14297	emissivemap: {
14298
14299		emissiveMap: { value: null },
14300		emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14301
14302	},
14303
14304	metalnessmap: {
14305
14306		metalnessMap: { value: null },
14307		metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14308
14309	},
14310
14311	roughnessmap: {
14312
14313		roughnessMap: { value: null },
14314		roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14315
14316	},
14317
14318	gradientmap: {
14319
14320		gradientMap: { value: null }
14321
14322	},
14323
14324	fog: {
14325
14326		fogDensity: { value: 0.00025 },
14327		fogNear: { value: 1 },
14328		fogFar: { value: 2000 },
14329		fogColor: { value: /*@__PURE__*/ new Color( 0xffffff ) }
14330
14331	},
14332
14333	lights: {
14334
14335		ambientLightColor: { value: [] },
14336
14337		lightProbe: { value: [] },
14338
14339		directionalLights: { value: [], properties: {
14340			direction: {},
14341			color: {}
14342		} },
14343
14344		directionalLightShadows: { value: [], properties: {
14345			shadowBias: {},
14346			shadowNormalBias: {},
14347			shadowRadius: {},
14348			shadowMapSize: {}
14349		} },
14350
14351		directionalShadowMap: { value: [] },
14352		directionalShadowMatrix: { value: [] },
14353
14354		spotLights: { value: [], properties: {
14355			color: {},
14356			position: {},
14357			direction: {},
14358			distance: {},
14359			coneCos: {},
14360			penumbraCos: {},
14361			decay: {}
14362		} },
14363
14364		spotLightShadows: { value: [], properties: {
14365			shadowBias: {},
14366			shadowNormalBias: {},
14367			shadowRadius: {},
14368			shadowMapSize: {}
14369		} },
14370
14371		spotLightMap: { value: [] },
14372		spotShadowMap: { value: [] },
14373		spotLightMatrix: { value: [] },
14374
14375		pointLights: { value: [], properties: {
14376			color: {},
14377			position: {},
14378			decay: {},
14379			distance: {}
14380		} },
14381
14382		pointLightShadows: { value: [], properties: {
14383			shadowBias: {},
14384			shadowNormalBias: {},
14385			shadowRadius: {},
14386			shadowMapSize: {},
14387			shadowCameraNear: {},
14388			shadowCameraFar: {}
14389		} },
14390
14391		pointShadowMap: { value: [] },
14392		pointShadowMatrix: { value: [] },
14393
14394		hemisphereLights: { value: [], properties: {
14395			direction: {},
14396			skyColor: {},
14397			groundColor: {}
14398		} },
14399
14400		// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
14401		rectAreaLights: { value: [], properties: {
14402			color: {},
14403			position: {},
14404			width: {},
14405			height: {}
14406		} },
14407
14408		ltc_1: { value: null },
14409		ltc_2: { value: null }
14410
14411	},
14412
14413	points: {
14414
14415		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
14416		opacity: { value: 1.0 },
14417		size: { value: 1.0 },
14418		scale: { value: 1.0 },
14419		map: { value: null },
14420		alphaMap: { value: null },
14421		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14422		alphaTest: { value: 0 },
14423		uvTransform: { value: /*@__PURE__*/ new Matrix3() }
14424
14425	},
14426
14427	sprite: {
14428
14429		diffuse: { value: /*@__PURE__*/ new Color( 0xffffff ) },
14430		opacity: { value: 1.0 },
14431		center: { value: /*@__PURE__*/ new Vector2( 0.5, 0.5 ) },
14432		rotation: { value: 0.0 },
14433		map: { value: null },
14434		mapTransform: { value: /*@__PURE__*/ new Matrix3() },
14435		alphaMap: { value: null },
14436		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14437		alphaTest: { value: 0 }
14438
14439	}
14440
14441};
14442
14443const ShaderLib = {
14444
14445	basic: {
14446
14447		uniforms: /*@__PURE__*/ mergeUniforms( [
14448			UniformsLib.common,
14449			UniformsLib.specularmap,
14450			UniformsLib.envmap,
14451			UniformsLib.aomap,
14452			UniformsLib.lightmap,
14453			UniformsLib.fog
14454		] ),
14455
14456		vertexShader: ShaderChunk.meshbasic_vert,
14457		fragmentShader: ShaderChunk.meshbasic_frag
14458
14459	},
14460
14461	lambert: {
14462
14463		uniforms: /*@__PURE__*/ mergeUniforms( [
14464			UniformsLib.common,
14465			UniformsLib.specularmap,
14466			UniformsLib.envmap,
14467			UniformsLib.aomap,
14468			UniformsLib.lightmap,
14469			UniformsLib.emissivemap,
14470			UniformsLib.bumpmap,
14471			UniformsLib.normalmap,
14472			UniformsLib.displacementmap,
14473			UniformsLib.fog,
14474			UniformsLib.lights,
14475			{
14476				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }
14477			}
14478		] ),
14479
14480		vertexShader: ShaderChunk.meshlambert_vert,
14481		fragmentShader: ShaderChunk.meshlambert_frag
14482
14483	},
14484
14485	phong: {
14486
14487		uniforms: /*@__PURE__*/ mergeUniforms( [
14488			UniformsLib.common,
14489			UniformsLib.specularmap,
14490			UniformsLib.envmap,
14491			UniformsLib.aomap,
14492			UniformsLib.lightmap,
14493			UniformsLib.emissivemap,
14494			UniformsLib.bumpmap,
14495			UniformsLib.normalmap,
14496			UniformsLib.displacementmap,
14497			UniformsLib.fog,
14498			UniformsLib.lights,
14499			{
14500				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14501				specular: { value: /*@__PURE__*/ new Color( 0x111111 ) },
14502				shininess: { value: 30 }
14503			}
14504		] ),
14505
14506		vertexShader: ShaderChunk.meshphong_vert,
14507		fragmentShader: ShaderChunk.meshphong_frag
14508
14509	},
14510
14511	standard: {
14512
14513		uniforms: /*@__PURE__*/ mergeUniforms( [
14514			UniformsLib.common,
14515			UniformsLib.envmap,
14516			UniformsLib.aomap,
14517			UniformsLib.lightmap,
14518			UniformsLib.emissivemap,
14519			UniformsLib.bumpmap,
14520			UniformsLib.normalmap,
14521			UniformsLib.displacementmap,
14522			UniformsLib.roughnessmap,
14523			UniformsLib.metalnessmap,
14524			UniformsLib.fog,
14525			UniformsLib.lights,
14526			{
14527				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14528				roughness: { value: 1.0 },
14529				metalness: { value: 0.0 },
14530				envMapIntensity: { value: 1 }
14531			}
14532		] ),
14533
14534		vertexShader: ShaderChunk.meshphysical_vert,
14535		fragmentShader: ShaderChunk.meshphysical_frag
14536
14537	},
14538
14539	toon: {
14540
14541		uniforms: /*@__PURE__*/ mergeUniforms( [
14542			UniformsLib.common,
14543			UniformsLib.aomap,
14544			UniformsLib.lightmap,
14545			UniformsLib.emissivemap,
14546			UniformsLib.bumpmap,
14547			UniformsLib.normalmap,
14548			UniformsLib.displacementmap,
14549			UniformsLib.gradientmap,
14550			UniformsLib.fog,
14551			UniformsLib.lights,
14552			{
14553				emissive: { value: /*@__PURE__*/ new Color( 0x000000 ) }
14554			}
14555		] ),
14556
14557		vertexShader: ShaderChunk.meshtoon_vert,
14558		fragmentShader: ShaderChunk.meshtoon_frag
14559
14560	},
14561
14562	matcap: {
14563
14564		uniforms: /*@__PURE__*/ mergeUniforms( [
14565			UniformsLib.common,
14566			UniformsLib.bumpmap,
14567			UniformsLib.normalmap,
14568			UniformsLib.displacementmap,
14569			UniformsLib.fog,
14570			{
vendor: 5,447 bytes, lines 14571-14797
14571				matcap: { value: null }
14572			}
14573		] ),
14574
14575		vertexShader: ShaderChunk.meshmatcap_vert,
14576		fragmentShader: ShaderChunk.meshmatcap_frag
14577
14578	},
14579
14580	points: {
14581
14582		uniforms: /*@__PURE__*/ mergeUniforms( [
14583			UniformsLib.points,
14584			UniformsLib.fog
14585		] ),
14586
14587		vertexShader: ShaderChunk.points_vert,
14588		fragmentShader: ShaderChunk.points_frag
14589
14590	},
14591
14592	dashed: {
14593
14594		uniforms: /*@__PURE__*/ mergeUniforms( [
14595			UniformsLib.common,
14596			UniformsLib.fog,
14597			{
14598				scale: { value: 1 },
14599				dashSize: { value: 1 },
14600				totalSize: { value: 2 }
14601			}
14602		] ),
14603
14604		vertexShader: ShaderChunk.linedashed_vert,
14605		fragmentShader: ShaderChunk.linedashed_frag
14606
14607	},
14608
14609	depth: {
14610
14611		uniforms: /*@__PURE__*/ mergeUniforms( [
14612			UniformsLib.common,
14613			UniformsLib.displacementmap
14614		] ),
14615
14616		vertexShader: ShaderChunk.depth_vert,
14617		fragmentShader: ShaderChunk.depth_frag
14618
14619	},
14620
14621	normal: {
14622
14623		uniforms: /*@__PURE__*/ mergeUniforms( [
14624			UniformsLib.common,
14625			UniformsLib.bumpmap,
14626			UniformsLib.normalmap,
14627			UniformsLib.displacementmap,
14628			{
14629				opacity: { value: 1.0 }
14630			}
14631		] ),
14632
14633		vertexShader: ShaderChunk.meshnormal_vert,
14634		fragmentShader: ShaderChunk.meshnormal_frag
14635
14636	},
14637
14638	sprite: {
14639
14640		uniforms: /*@__PURE__*/ mergeUniforms( [
14641			UniformsLib.sprite,
14642			UniformsLib.fog
14643		] ),
14644
14645		vertexShader: ShaderChunk.sprite_vert,
14646		fragmentShader: ShaderChunk.sprite_frag
14647
14648	},
14649
14650	background: {
14651
14652		uniforms: {
14653			uvTransform: { value: /*@__PURE__*/ new Matrix3() },
14654			t2D: { value: null },
14655			backgroundIntensity: { value: 1 }
14656		},
14657
14658		vertexShader: ShaderChunk.background_vert,
14659		fragmentShader: ShaderChunk.background_frag
14660
14661	},
14662
14663	backgroundCube: {
14664
14665		uniforms: {
14666			envMap: { value: null },
14667			flipEnvMap: { value: - 1 },
14668			backgroundBlurriness: { value: 0 },
14669			backgroundIntensity: { value: 1 },
14670			backgroundRotation: { value: /*@__PURE__*/ new Matrix3() }
14671		},
14672
14673		vertexShader: ShaderChunk.backgroundCube_vert,
14674		fragmentShader: ShaderChunk.backgroundCube_frag
14675
14676	},
14677
14678	cube: {
14679
14680		uniforms: {
14681			tCube: { value: null },
14682			tFlip: { value: - 1 },
14683			opacity: { value: 1.0 }
14684		},
14685
14686		vertexShader: ShaderChunk.cube_vert,
14687		fragmentShader: ShaderChunk.cube_frag
14688
14689	},
14690
14691	equirect: {
14692
14693		uniforms: {
14694			tEquirect: { value: null },
14695		},
14696
14697		vertexShader: ShaderChunk.equirect_vert,
14698		fragmentShader: ShaderChunk.equirect_frag
14699
14700	},
14701
14702	distanceRGBA: {
14703
14704		uniforms: /*@__PURE__*/ mergeUniforms( [
14705			UniformsLib.common,
14706			UniformsLib.displacementmap,
14707			{
14708				referencePosition: { value: /*@__PURE__*/ new Vector3() },
14709				nearDistance: { value: 1 },
14710				farDistance: { value: 1000 }
14711			}
14712		] ),
14713
14714		vertexShader: ShaderChunk.distanceRGBA_vert,
14715		fragmentShader: ShaderChunk.distanceRGBA_frag
14716
14717	},
14718
14719	shadow: {
14720
14721		uniforms: /*@__PURE__*/ mergeUniforms( [
14722			UniformsLib.lights,
14723			UniformsLib.fog,
14724			{
14725				color: { value: /*@__PURE__*/ new Color( 0x00000 ) },
14726				opacity: { value: 1.0 }
14727			},
14728		] ),
14729
14730		vertexShader: ShaderChunk.shadow_vert,
14731		fragmentShader: ShaderChunk.shadow_frag
14732
14733	}
14734
14735};
14736
14737ShaderLib.physical = {
14738
14739	uniforms: /*@__PURE__*/ mergeUniforms( [
14740		ShaderLib.standard.uniforms,
14741		{
14742			clearcoat: { value: 0 },
14743			clearcoatMap: { value: null },
14744			clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14745			clearcoatNormalMap: { value: null },
14746			clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14747			clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2( 1, 1 ) },
14748			clearcoatRoughness: { value: 0 },
14749			clearcoatRoughnessMap: { value: null },
14750			clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14751			dispersion: { value: 0 },
14752			iridescence: { value: 0 },
14753			iridescenceMap: { value: null },
14754			iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14755			iridescenceIOR: { value: 1.3 },
14756			iridescenceThicknessMinimum: { value: 100 },
14757			iridescenceThicknessMaximum: { value: 400 },
14758			iridescenceThicknessMap: { value: null },
14759			iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14760			sheen: { value: 0 },
14761			sheenColor: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14762			sheenColorMap: { value: null },
14763			sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14764			sheenRoughness: { value: 1 },
14765			sheenRoughnessMap: { value: null },
14766			sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14767			transmission: { value: 0 },
14768			transmissionMap: { value: null },
14769			transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14770			transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() },
14771			transmissionSamplerMap: { value: null },
14772			thickness: { value: 0 },
14773			thicknessMap: { value: null },
14774			thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14775			attenuationDistance: { value: 0 },
14776			attenuationColor: { value: /*@__PURE__*/ new Color( 0x000000 ) },
14777			specularColor: { value: /*@__PURE__*/ new Color( 1, 1, 1 ) },
14778			specularColorMap: { value: null },
14779			specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14780			specularIntensity: { value: 1 },
14781			specularIntensityMap: { value: null },
14782			specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14783			anisotropyVector: { value: /*@__PURE__*/ new Vector2() },
14784			anisotropyMap: { value: null },
14785			anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14786		}
14787	] ),
14788
14789	vertexShader: ShaderChunk.meshphysical_vert,
14790	fragmentShader: ShaderChunk.meshphysical_frag
14791
14792};
14793
14794const _rgb = { r: 0, b: 0, g: 0 };
14795const _e1$1 = /*@__PURE__*/ new Euler();
14796const _m1$1 = /*@__PURE__*/ new Matrix4();
14797
vendor: 4,415 bytes, lines 14798-14956
14798function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) {
14799
14800	const clearColor = new Color( 0x000000 );
14801	let clearAlpha = alpha === true ? 0 : 1;
14802
14803	let planeMesh;
14804	let boxMesh;
14805
14806	let currentBackground = null;
14807	let currentBackgroundVersion = 0;
14808	let currentTonemapping = null;
14809
14810	function getBackground( scene ) {
14811
14812		let background = scene.isScene === true ? scene.background : null;
14813
14814		if ( background && background.isTexture ) {
14815
14816			const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background
14817			background = ( usePMREM ? cubeuvmaps : cubemaps ).get( background );
14818
14819		}
14820
14821		return background;
14822
14823	}
14824
14825	function render( scene ) {
14826
14827		let forceClear = false;
14828		const background = getBackground( scene );
14829
14830		if ( background === null ) {
14831
14832			setClear( clearColor, clearAlpha );
14833
14834		} else if ( background && background.isColor ) {
14835
14836			setClear( background, 1 );
14837			forceClear = true;
14838
14839		}
14840
14841		const environmentBlendMode = renderer.xr.getEnvironmentBlendMode();
14842
14843		if ( environmentBlendMode === 'additive' ) {
14844
14845			state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha );
14846
14847		} else if ( environmentBlendMode === 'alpha-blend' ) {
14848
14849			state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha );
14850
14851		}
14852
14853		if ( renderer.autoClear || forceClear ) {
14854
14855			// buffers might not be writable which is required to ensure a correct clear
14856
14857			state.buffers.depth.setTest( true );
14858			state.buffers.depth.setMask( true );
14859			state.buffers.color.setMask( true );
14860
14861			renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
14862
14863		}
14864
14865	}
14866
14867	function addToRenderList( renderList, scene ) {
14868
14869		const background = getBackground( scene );
14870
14871		if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
14872
14873			if ( boxMesh === undefined ) {
14874
14875				boxMesh = new Mesh(
14876					new BoxGeometry( 1, 1, 1 ),
14877					new ShaderMaterial( {
14878						name: 'BackgroundCubeMaterial',
14879						uniforms: cloneUniforms( ShaderLib.backgroundCube.uniforms ),
14880						vertexShader: ShaderLib.backgroundCube.vertexShader,
14881						fragmentShader: ShaderLib.backgroundCube.fragmentShader,
14882						side: BackSide,
14883						depthTest: false,
14884						depthWrite: false,
14885						fog: false
14886					} )
14887				);
14888
14889				boxMesh.geometry.deleteAttribute( 'normal' );
14890				boxMesh.geometry.deleteAttribute( 'uv' );
14891
14892				boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
14893
14894					this.matrixWorld.copyPosition( camera.matrixWorld );
14895
14896				};
14897
14898				// add "envMap" material property so the renderer can evaluate it like for built-in materials
14899				Object.defineProperty( boxMesh.material, 'envMap', {
14900
14901					get: function () {
14902
14903						return this.uniforms.envMap.value;
14904
14905					}
14906
14907				} );
14908
14909				objects.update( boxMesh );
14910
14911			}
14912
14913			_e1$1.copy( scene.backgroundRotation );
14914
14915			// accommodate left-handed frame
14916			_e1$1.x *= - 1; _e1$1.y *= - 1; _e1$1.z *= - 1;
14917
14918			if ( background.isCubeTexture && background.isRenderTargetTexture === false ) {
14919
14920				// environment maps which are not cube render targets or PMREMs follow a different convention
14921				_e1$1.y *= - 1;
14922				_e1$1.z *= - 1;
14923
14924			}
14925
14926			boxMesh.material.uniforms.envMap.value = background;
14927			boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
14928			boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
14929			boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14930			boxMesh.material.uniforms.backgroundRotation.value.setFromMatrix4( _m1$1.makeRotationFromEuler( _e1$1 ) );
14931			boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
14932
14933			if ( currentBackground !== background ||
14934				currentBackgroundVersion !== background.version ||
14935				currentTonemapping !== renderer.toneMapping ) {
14936
14937				boxMesh.material.needsUpdate = true;
14938
14939				currentBackground = background;
14940				currentBackgroundVersion = background.version;
14941				currentTonemapping = renderer.toneMapping;
14942
14943			}
14944
14945			boxMesh.layers.enableAll();
14946
14947			// push to the pre-sorted opaque render list
14948			renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
14949
14950		} else if ( background && background.isTexture ) {
14951
14952			if ( planeMesh === undefined ) {
14953
14954				planeMesh = new Mesh(
14955					new PlaneGeometry( 2, 2 ),
14956					new ShaderMaterial( {
vendor: 14,224 bytes, lines 14957-15627
14957						name: 'BackgroundMaterial',
14958						uniforms: cloneUniforms( ShaderLib.background.uniforms ),
14959						vertexShader: ShaderLib.background.vertexShader,
14960						fragmentShader: ShaderLib.background.fragmentShader,
14961						side: FrontSide,
14962						depthTest: false,
14963						depthWrite: false,
14964						fog: false
14965					} )
14966				);
14967
14968				planeMesh.geometry.deleteAttribute( 'normal' );
14969
14970				// add "map" material property so the renderer can evaluate it like for built-in materials
14971				Object.defineProperty( planeMesh.material, 'map', {
14972
14973					get: function () {
14974
14975						return this.uniforms.t2D.value;
14976
14977					}
14978
14979				} );
14980
14981				objects.update( planeMesh );
14982
14983			}
14984
14985			planeMesh.material.uniforms.t2D.value = background;
14986			planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14987			planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
14988
14989			if ( background.matrixAutoUpdate === true ) {
14990
14991				background.updateMatrix();
14992
14993			}
14994
14995			planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
14996
14997			if ( currentBackground !== background ||
14998				currentBackgroundVersion !== background.version ||
14999				currentTonemapping !== renderer.toneMapping ) {
15000
15001				planeMesh.material.needsUpdate = true;
15002
15003				currentBackground = background;
15004				currentBackgroundVersion = background.version;
15005				currentTonemapping = renderer.toneMapping;
15006
15007			}
15008
15009			planeMesh.layers.enableAll();
15010
15011			// push to the pre-sorted opaque render list
15012			renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );
15013
15014		}
15015
15016	}
15017
15018	function setClear( color, alpha ) {
15019
15020		color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) );
15021
15022		state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha );
15023
15024	}
15025
15026	return {
15027
15028		getClearColor: function () {
15029
15030			return clearColor;
15031
15032		},
15033		setClearColor: function ( color, alpha = 1 ) {
15034
15035			clearColor.set( color );
15036			clearAlpha = alpha;
15037			setClear( clearColor, clearAlpha );
15038
15039		},
15040		getClearAlpha: function () {
15041
15042			return clearAlpha;
15043
15044		},
15045		setClearAlpha: function ( alpha ) {
15046
15047			clearAlpha = alpha;
15048			setClear( clearColor, clearAlpha );
15049
15050		},
15051		render: render,
15052		addToRenderList: addToRenderList
15053
15054	};
15055
15056}
15057
15058function WebGLBindingStates( gl, attributes ) {
15059
15060	const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
15061
15062	const bindingStates = {};
15063
15064	const defaultState = createBindingState( null );
15065	let currentState = defaultState;
15066	let forceUpdate = false;
15067
15068	function setup( object, material, program, geometry, index ) {
15069
15070		let updateBuffers = false;
15071
15072		const state = getBindingState( geometry, program, material );
15073
15074		if ( currentState !== state ) {
15075
15076			currentState = state;
15077			bindVertexArrayObject( currentState.object );
15078
15079		}
15080
15081		updateBuffers = needsUpdate( object, geometry, program, index );
15082
15083		if ( updateBuffers ) saveCache( object, geometry, program, index );
15084
15085		if ( index !== null ) {
15086
15087			attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
15088
15089		}
15090
15091		if ( updateBuffers || forceUpdate ) {
15092
15093			forceUpdate = false;
15094
15095			setupVertexAttributes( object, material, program, geometry );
15096
15097			if ( index !== null ) {
15098
15099				gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer );
15100
15101			}
15102
15103		}
15104
15105	}
15106
15107	function createVertexArrayObject() {
15108
15109		return gl.createVertexArray();
15110
15111	}
15112
15113	function bindVertexArrayObject( vao ) {
15114
15115		return gl.bindVertexArray( vao );
15116
15117	}
15118
15119	function deleteVertexArrayObject( vao ) {
15120
15121		return gl.deleteVertexArray( vao );
15122
15123	}
15124
15125	function getBindingState( geometry, program, material ) {
15126
15127		const wireframe = ( material.wireframe === true );
15128
15129		let programMap = bindingStates[ geometry.id ];
15130
15131		if ( programMap === undefined ) {
15132
15133			programMap = {};
15134			bindingStates[ geometry.id ] = programMap;
15135
15136		}
15137
15138		let stateMap = programMap[ program.id ];
15139
15140		if ( stateMap === undefined ) {
15141
15142			stateMap = {};
15143			programMap[ program.id ] = stateMap;
15144
15145		}
15146
15147		let state = stateMap[ wireframe ];
15148
15149		if ( state === undefined ) {
15150
15151			state = createBindingState( createVertexArrayObject() );
15152			stateMap[ wireframe ] = state;
15153
15154		}
15155
15156		return state;
15157
15158	}
15159
15160	function createBindingState( vao ) {
15161
15162		const newAttributes = [];
15163		const enabledAttributes = [];
15164		const attributeDivisors = [];
15165
15166		for ( let i = 0; i < maxVertexAttributes; i ++ ) {
15167
15168			newAttributes[ i ] = 0;
15169			enabledAttributes[ i ] = 0;
15170			attributeDivisors[ i ] = 0;
15171
15172		}
15173
15174		return {
15175
15176			// for backward compatibility on non-VAO support browser
15177			geometry: null,
15178			program: null,
15179			wireframe: false,
15180
15181			newAttributes: newAttributes,
15182			enabledAttributes: enabledAttributes,
15183			attributeDivisors: attributeDivisors,
15184			object: vao,
15185			attributes: {},
15186			index: null
15187
15188		};
15189
15190	}
15191
15192	function needsUpdate( object, geometry, program, index ) {
15193
15194		const cachedAttributes = currentState.attributes;
15195		const geometryAttributes = geometry.attributes;
15196
15197		let attributesNum = 0;
15198
15199		const programAttributes = program.getAttributes();
15200
15201		for ( const name in programAttributes ) {
15202
15203			const programAttribute = programAttributes[ name ];
15204
15205			if ( programAttribute.location >= 0 ) {
15206
15207				const cachedAttribute = cachedAttributes[ name ];
15208				let geometryAttribute = geometryAttributes[ name ];
15209
15210				if ( geometryAttribute === undefined ) {
15211
15212					if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
15213					if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
15214
15215				}
15216
15217				if ( cachedAttribute === undefined ) return true;
15218
15219				if ( cachedAttribute.attribute !== geometryAttribute ) return true;
15220
15221				if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true;
15222
15223				attributesNum ++;
15224
15225			}
15226
15227		}
15228
15229		if ( currentState.attributesNum !== attributesNum ) return true;
15230
15231		if ( currentState.index !== index ) return true;
15232
15233		return false;
15234
15235	}
15236
15237	function saveCache( object, geometry, program, index ) {
15238
15239		const cache = {};
15240		const attributes = geometry.attributes;
15241		let attributesNum = 0;
15242
15243		const programAttributes = program.getAttributes();
15244
15245		for ( const name in programAttributes ) {
15246
15247			const programAttribute = programAttributes[ name ];
15248
15249			if ( programAttribute.location >= 0 ) {
15250
15251				let attribute = attributes[ name ];
15252
15253				if ( attribute === undefined ) {
15254
15255					if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix;
15256					if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor;
15257
15258				}
15259
15260				const data = {};
15261				data.attribute = attribute;
15262
15263				if ( attribute && attribute.data ) {
15264
15265					data.data = attribute.data;
15266
15267				}
15268
15269				cache[ name ] = data;
15270
15271				attributesNum ++;
15272
15273			}
15274
15275		}
15276
15277		currentState.attributes = cache;
15278		currentState.attributesNum = attributesNum;
15279
15280		currentState.index = index;
15281
15282	}
15283
15284	function initAttributes() {
15285
15286		const newAttributes = currentState.newAttributes;
15287
15288		for ( let i = 0, il = newAttributes.length; i < il; i ++ ) {
15289
15290			newAttributes[ i ] = 0;
15291
15292		}
15293
15294	}
15295
15296	function enableAttribute( attribute ) {
15297
15298		enableAttributeAndDivisor( attribute, 0 );
15299
15300	}
15301
15302	function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
15303
15304		const newAttributes = currentState.newAttributes;
15305		const enabledAttributes = currentState.enabledAttributes;
15306		const attributeDivisors = currentState.attributeDivisors;
15307
15308		newAttributes[ attribute ] = 1;
15309
15310		if ( enabledAttributes[ attribute ] === 0 ) {
15311
15312			gl.enableVertexAttribArray( attribute );
15313			enabledAttributes[ attribute ] = 1;
15314
15315		}
15316
15317		if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
15318
15319			gl.vertexAttribDivisor( attribute, meshPerAttribute );
15320			attributeDivisors[ attribute ] = meshPerAttribute;
15321
15322		}
15323
15324	}
15325
15326	function disableUnusedAttributes() {
15327
15328		const newAttributes = currentState.newAttributes;
15329		const enabledAttributes = currentState.enabledAttributes;
15330
15331		for ( let i = 0, il = enabledAttributes.length; i < il; i ++ ) {
15332
15333			if ( enabledAttributes[ i ] !== newAttributes[ i ] ) {
15334
15335				gl.disableVertexAttribArray( i );
15336				enabledAttributes[ i ] = 0;
15337
15338			}
15339
15340		}
15341
15342	}
15343
15344	function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) {
15345
15346		if ( integer === true ) {
15347
15348			gl.vertexAttribIPointer( index, size, type, stride, offset );
15349
15350		} else {
15351
15352			gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
15353
15354		}
15355
15356	}
15357
15358	function setupVertexAttributes( object, material, program, geometry ) {
15359
15360		initAttributes();
15361
15362		const geometryAttributes = geometry.attributes;
15363
15364		const programAttributes = program.getAttributes();
15365
15366		const materialDefaultAttributeValues = material.defaultAttributeValues;
15367
15368		for ( const name in programAttributes ) {
15369
15370			const programAttribute = programAttributes[ name ];
15371
15372			if ( programAttribute.location >= 0 ) {
15373
15374				let geometryAttribute = geometryAttributes[ name ];
15375
15376				if ( geometryAttribute === undefined ) {
15377
15378					if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix;
15379					if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor;
15380
15381				}
15382
15383				if ( geometryAttribute !== undefined ) {
15384
15385					const normalized = geometryAttribute.normalized;
15386					const size = geometryAttribute.itemSize;
15387
15388					const attribute = attributes.get( geometryAttribute );
15389
15390					// TODO Attribute may not be available on context restore
15391
15392					if ( attribute === undefined ) continue;
15393
15394					const buffer = attribute.buffer;
15395					const type = attribute.type;
15396					const bytesPerElement = attribute.bytesPerElement;
15397
15398					// check for integer attributes
15399
15400					const integer = ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType );
15401
15402					if ( geometryAttribute.isInterleavedBufferAttribute ) {
15403
15404						const data = geometryAttribute.data;
15405						const stride = data.stride;
15406						const offset = geometryAttribute.offset;
15407
15408						if ( data.isInstancedInterleavedBuffer ) {
15409
15410							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15411
15412								enableAttributeAndDivisor( programAttribute.location + i, data.meshPerAttribute );
15413
15414							}
15415
15416							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
15417
15418								geometry._maxInstanceCount = data.meshPerAttribute * data.count;
15419
15420							}
15421
15422						} else {
15423
15424							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15425
15426								enableAttribute( programAttribute.location + i );
15427
15428							}
15429
15430						}
15431
15432						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
15433
15434						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15435
15436							vertexAttribPointer(
15437								programAttribute.location + i,
15438								size / programAttribute.locationSize,
15439								type,
15440								normalized,
15441								stride * bytesPerElement,
15442								( offset + ( size / programAttribute.locationSize ) * i ) * bytesPerElement,
15443								integer
15444							);
15445
15446						}
15447
15448					} else {
15449
15450						if ( geometryAttribute.isInstancedBufferAttribute ) {
15451
15452							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15453
15454								enableAttributeAndDivisor( programAttribute.location + i, geometryAttribute.meshPerAttribute );
15455
15456							}
15457
15458							if ( object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined ) {
15459
15460								geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
15461
15462							}
15463
15464						} else {
15465
15466							for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15467
15468								enableAttribute( programAttribute.location + i );
15469
15470							}
15471
15472						}
15473
15474						gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
15475
15476						for ( let i = 0; i < programAttribute.locationSize; i ++ ) {
15477
15478							vertexAttribPointer(
15479								programAttribute.location + i,
15480								size / programAttribute.locationSize,
15481								type,
15482								normalized,
15483								size * bytesPerElement,
15484								( size / programAttribute.locationSize ) * i * bytesPerElement,
15485								integer
15486							);
15487
15488						}
15489
15490					}
15491
15492				} else if ( materialDefaultAttributeValues !== undefined ) {
15493
15494					const value = materialDefaultAttributeValues[ name ];
15495
15496					if ( value !== undefined ) {
15497
15498						switch ( value.length ) {
15499
15500							case 2:
15501								gl.vertexAttrib2fv( programAttribute.location, value );
15502								break;
15503
15504							case 3:
15505								gl.vertexAttrib3fv( programAttribute.location, value );
15506								break;
15507
15508							case 4:
15509								gl.vertexAttrib4fv( programAttribute.location, value );
15510								break;
15511
15512							default:
15513								gl.vertexAttrib1fv( programAttribute.location, value );
15514
15515						}
15516
15517					}
15518
15519				}
15520
15521			}
15522
15523		}
15524
15525		disableUnusedAttributes();
15526
15527	}
15528
15529	function dispose() {
15530
15531		reset();
15532
15533		for ( const geometryId in bindingStates ) {
15534
15535			const programMap = bindingStates[ geometryId ];
15536
15537			for ( const programId in programMap ) {
15538
15539				const stateMap = programMap[ programId ];
15540
15541				for ( const wireframe in stateMap ) {
15542
15543					deleteVertexArrayObject( stateMap[ wireframe ].object );
15544
15545					delete stateMap[ wireframe ];
15546
15547				}
15548
15549				delete programMap[ programId ];
15550
15551			}
15552
15553			delete bindingStates[ geometryId ];
15554
15555		}
15556
15557	}
15558
15559	function releaseStatesOfGeometry( geometry ) {
15560
15561		if ( bindingStates[ geometry.id ] === undefined ) return;
15562
15563		const programMap = bindingStates[ geometry.id ];
15564
15565		for ( const programId in programMap ) {
15566
15567			const stateMap = programMap[ programId ];
15568
15569			for ( const wireframe in stateMap ) {
15570
15571				deleteVertexArrayObject( stateMap[ wireframe ].object );
15572
15573				delete stateMap[ wireframe ];
15574
15575			}
15576
15577			delete programMap[ programId ];
15578
15579		}
15580
15581		delete bindingStates[ geometry.id ];
15582
15583	}
15584
15585	function releaseStatesOfProgram( program ) {
15586
15587		for ( const geometryId in bindingStates ) {
15588
15589			const programMap = bindingStates[ geometryId ];
15590
15591			if ( programMap[ program.id ] === undefined ) continue;
15592
15593			const stateMap = programMap[ program.id ];
15594
15595			for ( const wireframe in stateMap ) {
15596
15597				deleteVertexArrayObject( stateMap[ wireframe ].object );
15598
15599				delete stateMap[ wireframe ];
15600
15601			}
15602
15603			delete programMap[ program.id ];
15604
15605		}
15606
15607	}
15608
15609	function reset() {
15610
15611		resetDefaultState();
15612		forceUpdate = true;
15613
15614		if ( currentState === defaultState ) return;
15615
15616		currentState = defaultState;
15617		bindVertexArrayObject( currentState.object );
15618
15619	}
15620
15621	// for backward-compatibility
15622
15623	function resetDefaultState() {
15624
15625		defaultState.geometry = null;
15626		defaultState.program = null;
15627		defaultState.wireframe = false;
vendor: 1,634 bytes, lines 15628-15722
15628
15629	}
15630
15631	return {
15632
15633		setup: setup,
15634		reset: reset,
15635		resetDefaultState: resetDefaultState,
15636		dispose: dispose,
15637		releaseStatesOfGeometry: releaseStatesOfGeometry,
15638		releaseStatesOfProgram: releaseStatesOfProgram,
15639
15640		initAttributes: initAttributes,
15641		enableAttribute: enableAttribute,
15642		disableUnusedAttributes: disableUnusedAttributes
15643
15644	};
15645
15646}
15647
15648function WebGLBufferRenderer( gl, extensions, info ) {
15649
15650	let mode;
15651
15652	function setMode( value ) {
15653
15654		mode = value;
15655
15656	}
15657
15658	function render( start, count ) {
15659
15660		gl.drawArrays( mode, start, count );
15661
15662		info.update( count, mode, 1 );
15663
15664	}
15665
15666	function renderInstances( start, count, primcount ) {
15667
15668		if ( primcount === 0 ) return;
15669
15670		gl.drawArraysInstanced( mode, start, count, primcount );
15671
15672		info.update( count, mode, primcount );
15673
15674	}
15675
15676	function renderMultiDraw( starts, counts, drawCount ) {
15677
15678		if ( drawCount === 0 ) return;
15679
15680		const extension = extensions.get( 'WEBGL_multi_draw' );
15681
15682		if ( extension === null ) {
15683
15684			for ( let i = 0; i < drawCount; i ++ ) {
15685
15686				this.render( starts[ i ], counts[ i ] );
15687
15688			}
15689
15690		} else {
15691
15692			extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount );
15693
15694			let elementCount = 0;
15695			for ( let i = 0; i < drawCount; i ++ ) {
15696
15697				elementCount += counts[ i ];
15698
15699			}
15700
15701			info.update( elementCount, mode, 1 );
15702
15703		}
15704
15705	}
15706
15707	function renderMultiDrawInstances( starts, counts, drawCount, primcount ) {
15708
15709		if ( drawCount === 0 ) return;
15710
15711		const extension = extensions.get( 'WEBGL_multi_draw' );
15712
15713		if ( extension === null ) {
15714
15715			for ( let i = 0; i < starts.length; i ++ ) {
15716
15717				renderInstances( starts[ i ], counts[ i ], primcount[ i ] );
15718
15719			}
15720
15721		} else {
15722
vendor: 3,529 bytes, lines 15723-15864
15723			extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount );
15724
15725			let elementCount = 0;
15726			for ( let i = 0; i < drawCount; i ++ ) {
15727
15728				elementCount += counts[ i ];
15729
15730			}
15731
15732			for ( let i = 0; i < primcount.length; i ++ ) {
15733
15734				info.update( elementCount, mode, primcount[ i ] );
15735
15736			}
15737
15738		}
15739
15740	}
15741
15742	//
15743
15744	this.setMode = setMode;
15745	this.render = render;
15746	this.renderInstances = renderInstances;
15747	this.renderMultiDraw = renderMultiDraw;
15748	this.renderMultiDrawInstances = renderMultiDrawInstances;
15749
15750}
15751
15752function WebGLCapabilities( gl, extensions, parameters, utils ) {
15753
15754	let maxAnisotropy;
15755
15756	function getMaxAnisotropy() {
15757
15758		if ( maxAnisotropy !== undefined ) return maxAnisotropy;
15759
15760		if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
15761
15762			const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
15763
15764			maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
15765
15766		} else {
15767
15768			maxAnisotropy = 0;
15769
15770		}
15771
15772		return maxAnisotropy;
15773
15774	}
15775
15776	function textureFormatReadable( textureFormat ) {
15777
15778		if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
15779
15780			return false;
15781
15782		}
15783
15784		return true;
15785
15786	}
15787
15788	function textureTypeReadable( textureType ) {
15789
15790		const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) );
15791
15792		if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513)
15793			textureType !== FloatType && ! halfFloatSupportedByExt ) {
15794
15795			return false;
15796
15797		}
15798
15799		return true;
15800
15801	}
15802
15803	function getMaxPrecision( precision ) {
15804
15805		if ( precision === 'highp' ) {
15806
15807			if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
15808				gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
15809
15810				return 'highp';
15811
15812			}
15813
15814			precision = 'mediump';
15815
15816		}
15817
15818		if ( precision === 'mediump' ) {
15819
15820			if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
15821				gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
15822
15823				return 'mediump';
15824
15825			}
15826
15827		}
15828
15829		return 'lowp';
15830
15831	}
15832
15833	let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
15834	const maxPrecision = getMaxPrecision( precision );
15835
15836	if ( maxPrecision !== precision ) {
15837
15838		console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );
15839		precision = maxPrecision;
15840
15841	}
15842
15843	const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
15844
15845	const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
15846	const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
15847	const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
15848	const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
15849
15850	const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
15851	const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
15852	const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
15853	const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
15854
15855	const vertexTextures = maxVertexTextures > 0;
15856
15857	const maxSamples = gl.getParameter( gl.MAX_SAMPLES );
15858
15859	return {
15860
15861		isWebGL2: true, // keeping this for backwards compatibility
15862
15863		getMaxAnisotropy: getMaxAnisotropy,
15864		getMaxPrecision: getMaxPrecision,
vendor: 1,710 bytes, lines 15865-15948
15865
15866		textureFormatReadable: textureFormatReadable,
15867		textureTypeReadable: textureTypeReadable,
15868
15869		precision: precision,
15870		logarithmicDepthBuffer: logarithmicDepthBuffer,
15871
15872		maxTextures: maxTextures,
15873		maxVertexTextures: maxVertexTextures,
15874		maxTextureSize: maxTextureSize,
15875		maxCubemapSize: maxCubemapSize,
15876
15877		maxAttributes: maxAttributes,
15878		maxVertexUniforms: maxVertexUniforms,
15879		maxVaryings: maxVaryings,
15880		maxFragmentUniforms: maxFragmentUniforms,
15881
15882		vertexTextures: vertexTextures,
15883
15884		maxSamples: maxSamples
15885
15886	};
15887
15888}
15889
15890function WebGLClipping( properties ) {
15891
15892	const scope = this;
15893
15894	let globalState = null,
15895		numGlobalPlanes = 0,
15896		localClippingEnabled = false,
15897		renderingShadows = false;
15898
15899	const plane = new Plane(),
15900		viewNormalMatrix = new Matrix3(),
15901
15902		uniform = { value: null, needsUpdate: false };
15903
15904	this.uniform = uniform;
15905	this.numPlanes = 0;
15906	this.numIntersection = 0;
15907
15908	this.init = function ( planes, enableLocalClipping ) {
15909
15910		const enabled =
15911			planes.length !== 0 ||
15912			enableLocalClipping ||
15913			// enable state of previous frame - the clipping code has to
15914			// run another frame in order to reset the state:
15915			numGlobalPlanes !== 0 ||
15916			localClippingEnabled;
15917
15918		localClippingEnabled = enableLocalClipping;
15919
15920		numGlobalPlanes = planes.length;
15921
15922		return enabled;
15923
15924	};
15925
15926	this.beginShadows = function () {
15927
15928		renderingShadows = true;
15929		projectPlanes( null );
15930
15931	};
15932
15933	this.endShadows = function () {
15934
15935		renderingShadows = false;
15936
15937	};
15938
15939	this.setGlobalState = function ( planes, camera ) {
15940
15941		globalState = projectPlanes( planes, camera, 0 );
15942
15943	};
15944
15945	this.setState = function ( material, camera, useCache ) {
15946
15947		const planes = material.clippingPlanes,
15948			clipIntersection = material.clipIntersection,
vendor: 9,736 bytes, lines 15949-16371
15949			clipShadows = material.clipShadows;
15950
15951		const materialProperties = properties.get( material );
15952
15953		if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {
15954
15955			// there's no local clipping
15956
15957			if ( renderingShadows ) {
15958
15959				// there's no global clipping
15960
15961				projectPlanes( null );
15962
15963			} else {
15964
15965				resetGlobalState();
15966
15967			}
15968
15969		} else {
15970
15971			const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
15972				lGlobal = nGlobal * 4;
15973
15974			let dstArray = materialProperties.clippingState || null;
15975
15976			uniform.value = dstArray; // ensure unique state
15977
15978			dstArray = projectPlanes( planes, camera, lGlobal, useCache );
15979
15980			for ( let i = 0; i !== lGlobal; ++ i ) {
15981
15982				dstArray[ i ] = globalState[ i ];
15983
15984			}
15985
15986			materialProperties.clippingState = dstArray;
15987			this.numIntersection = clipIntersection ? this.numPlanes : 0;
15988			this.numPlanes += nGlobal;
15989
15990		}
15991
15992
15993	};
15994
15995	function resetGlobalState() {
15996
15997		if ( uniform.value !== globalState ) {
15998
15999			uniform.value = globalState;
16000			uniform.needsUpdate = numGlobalPlanes > 0;
16001
16002		}
16003
16004		scope.numPlanes = numGlobalPlanes;
16005		scope.numIntersection = 0;
16006
16007	}
16008
16009	function projectPlanes( planes, camera, dstOffset, skipTransform ) {
16010
16011		const nPlanes = planes !== null ? planes.length : 0;
16012		let dstArray = null;
16013
16014		if ( nPlanes !== 0 ) {
16015
16016			dstArray = uniform.value;
16017
16018			if ( skipTransform !== true || dstArray === null ) {
16019
16020				const flatSize = dstOffset + nPlanes * 4,
16021					viewMatrix = camera.matrixWorldInverse;
16022
16023				viewNormalMatrix.getNormalMatrix( viewMatrix );
16024
16025				if ( dstArray === null || dstArray.length < flatSize ) {
16026
16027					dstArray = new Float32Array( flatSize );
16028
16029				}
16030
16031				for ( let i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {
16032
16033					plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
16034
16035					plane.normal.toArray( dstArray, i4 );
16036					dstArray[ i4 + 3 ] = plane.constant;
16037
16038				}
16039
16040			}
16041
16042			uniform.value = dstArray;
16043			uniform.needsUpdate = true;
16044
16045		}
16046
16047		scope.numPlanes = nPlanes;
16048		scope.numIntersection = 0;
16049
16050		return dstArray;
16051
16052	}
16053
16054}
16055
16056function WebGLCubeMaps( renderer ) {
16057
16058	let cubemaps = new WeakMap();
16059
16060	function mapTextureMapping( texture, mapping ) {
16061
16062		if ( mapping === EquirectangularReflectionMapping ) {
16063
16064			texture.mapping = CubeReflectionMapping;
16065
16066		} else if ( mapping === EquirectangularRefractionMapping ) {
16067
16068			texture.mapping = CubeRefractionMapping;
16069
16070		}
16071
16072		return texture;
16073
16074	}
16075
16076	function get( texture ) {
16077
16078		if ( texture && texture.isTexture ) {
16079
16080			const mapping = texture.mapping;
16081
16082			if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
16083
16084				if ( cubemaps.has( texture ) ) {
16085
16086					const cubemap = cubemaps.get( texture ).texture;
16087					return mapTextureMapping( cubemap, texture.mapping );
16088
16089				} else {
16090
16091					const image = texture.image;
16092
16093					if ( image && image.height > 0 ) {
16094
16095						const renderTarget = new WebGLCubeRenderTarget( image.height );
16096						renderTarget.fromEquirectangularTexture( renderer, texture );
16097						cubemaps.set( texture, renderTarget );
16098
16099						texture.addEventListener( 'dispose', onTextureDispose );
16100
16101						return mapTextureMapping( renderTarget.texture, texture.mapping );
16102
16103					} else {
16104
16105						// image not yet ready. try the conversion next frame
16106
16107						return null;
16108
16109					}
16110
16111				}
16112
16113			}
16114
16115		}
16116
16117		return texture;
16118
16119	}
16120
16121	function onTextureDispose( event ) {
16122
16123		const texture = event.target;
16124
16125		texture.removeEventListener( 'dispose', onTextureDispose );
16126
16127		const cubemap = cubemaps.get( texture );
16128
16129		if ( cubemap !== undefined ) {
16130
16131			cubemaps.delete( texture );
16132			cubemap.dispose();
16133
16134		}
16135
16136	}
16137
16138	function dispose() {
16139
16140		cubemaps = new WeakMap();
16141
16142	}
16143
16144	return {
16145		get: get,
16146		dispose: dispose
16147	};
16148
16149}
16150
16151class OrthographicCamera extends Camera {
16152
16153	constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
16154
16155		super();
16156
16157		this.isOrthographicCamera = true;
16158
16159		this.type = 'OrthographicCamera';
16160
16161		this.zoom = 1;
16162		this.view = null;
16163
16164		this.left = left;
16165		this.right = right;
16166		this.top = top;
16167		this.bottom = bottom;
16168
16169		this.near = near;
16170		this.far = far;
16171
16172		this.updateProjectionMatrix();
16173
16174	}
16175
16176	copy( source, recursive ) {
16177
16178		super.copy( source, recursive );
16179
16180		this.left = source.left;
16181		this.right = source.right;
16182		this.top = source.top;
16183		this.bottom = source.bottom;
16184		this.near = source.near;
16185		this.far = source.far;
16186
16187		this.zoom = source.zoom;
16188		this.view = source.view === null ? null : Object.assign( {}, source.view );
16189
16190		return this;
16191
16192	}
16193
16194	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
16195
16196		if ( this.view === null ) {
16197
16198			this.view = {
16199				enabled: true,
16200				fullWidth: 1,
16201				fullHeight: 1,
16202				offsetX: 0,
16203				offsetY: 0,
16204				width: 1,
16205				height: 1
16206			};
16207
16208		}
16209
16210		this.view.enabled = true;
16211		this.view.fullWidth = fullWidth;
16212		this.view.fullHeight = fullHeight;
16213		this.view.offsetX = x;
16214		this.view.offsetY = y;
16215		this.view.width = width;
16216		this.view.height = height;
16217
16218		this.updateProjectionMatrix();
16219
16220	}
16221
16222	clearViewOffset() {
16223
16224		if ( this.view !== null ) {
16225
16226			this.view.enabled = false;
16227
16228		}
16229
16230		this.updateProjectionMatrix();
16231
16232	}
16233
16234	updateProjectionMatrix() {
16235
16236		const dx = ( this.right - this.left ) / ( 2 * this.zoom );
16237		const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
16238		const cx = ( this.right + this.left ) / 2;
16239		const cy = ( this.top + this.bottom ) / 2;
16240
16241		let left = cx - dx;
16242		let right = cx + dx;
16243		let top = cy + dy;
16244		let bottom = cy - dy;
16245
16246		if ( this.view !== null && this.view.enabled ) {
16247
16248			const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
16249			const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
16250
16251			left += scaleW * this.view.offsetX;
16252			right = left + scaleW * this.view.width;
16253			top -= scaleH * this.view.offsetY;
16254			bottom = top - scaleH * this.view.height;
16255
16256		}
16257
16258		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem );
16259
16260		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
16261
16262	}
16263
16264	toJSON( meta ) {
16265
16266		const data = super.toJSON( meta );
16267
16268		data.object.zoom = this.zoom;
16269		data.object.left = this.left;
16270		data.object.right = this.right;
16271		data.object.top = this.top;
16272		data.object.bottom = this.bottom;
16273		data.object.near = this.near;
16274		data.object.far = this.far;
16275
16276		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
16277
16278		return data;
16279
16280	}
16281
16282}
16283
16284const LOD_MIN = 4;
16285
16286// The standard deviations (radians) associated with the extra mips. These are
16287// chosen to approximate a Trowbridge-Reitz distribution function times the
16288// geometric shadowing function. These sigma values squared must match the
16289// variance #defines in cube_uv_reflection_fragment.glsl.js.
16290const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
16291
16292// The maximum length of the blur for loop. Smaller sigmas will use fewer
16293// samples and exit early, but not recompile the shader.
16294const MAX_SAMPLES = 20;
16295
16296const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
16297const _clearColor = /*@__PURE__*/ new Color();
16298let _oldTarget = null;
16299let _oldActiveCubeFace = 0;
16300let _oldActiveMipmapLevel = 0;
16301let _oldXrEnabled = false;
16302
16303// Golden Ratio
16304const PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
16305const INV_PHI = 1 / PHI;
16306
16307// Vertices of a dodecahedron (except the opposites, which represent the
16308// same axis), used as axis directions evenly spread on a sphere.
16309const _axisDirections = [
16310	/*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ),
16311	/*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ),
16312	/*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ),
16313	/*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ),
16314	/*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ),
16315	/*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ),
16316	/*@__PURE__*/ new Vector3( - 1, 1, - 1 ),
16317	/*@__PURE__*/ new Vector3( 1, 1, - 1 ),
16318	/*@__PURE__*/ new Vector3( - 1, 1, 1 ),
16319	/*@__PURE__*/ new Vector3( 1, 1, 1 ) ];
16320
16321/**
16322 * This class generates a Prefiltered, Mipmapped Radiance Environment Map
16323 * (PMREM) from a cubeMap environment texture. This allows different levels of
16324 * blur to be quickly accessed based on material roughness. It is packed into a
16325 * special CubeUV format that allows us to perform custom interpolation so that
16326 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
16327 * chain, it only goes down to the LOD_MIN level (above), and then creates extra
16328 * even more filtered 'mips' at the same LOD_MIN resolution, associated with
16329 * higher roughness levels. In this way we maintain resolution to smoothly
16330 * interpolate diffuse lighting while limiting sampling computation.
16331 *
16332 * Paper: Fast, Accurate Image-Based Lighting
16333 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view
16334*/
16335
16336class PMREMGenerator {
16337
16338	constructor( renderer ) {
16339
16340		this._renderer = renderer;
16341		this._pingPongRenderTarget = null;
16342
16343		this._lodMax = 0;
16344		this._cubeSize = 0;
16345		this._lodPlanes = [];
16346		this._sizeLods = [];
16347		this._sigmas = [];
16348
16349		this._blurMaterial = null;
16350		this._cubemapMaterial = null;
16351		this._equirectMaterial = null;
16352
16353		this._compileMaterial( this._blurMaterial );
16354
16355	}
16356
16357	/**
16358	 * Generates a PMREM from a supplied Scene, which can be faster than using an
16359	 * image if networking bandwidth is low. Optional sigma specifies a blur radius
16360	 * in radians to be applied to the scene before PMREM generation. Optional near
16361	 * and far planes ensure the scene is rendered in its entirety (the cubeCamera
16362	 * is placed at the origin).
16363	 */
16364	fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
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;
vendor: 5,454 bytes, lines 16372-16581
16372
16373		this._setSize( 256 );
16374
16375		const cubeUVRenderTarget = this._allocateTargets();
16376		cubeUVRenderTarget.depthBuffer = true;
16377
16378		this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
16379
16380		if ( sigma > 0 ) {
16381
16382			this._blur( cubeUVRenderTarget, 0, 0, sigma );
16383
16384		}
16385
16386		this._applyPMREM( cubeUVRenderTarget );
16387		this._cleanup( cubeUVRenderTarget );
16388
16389		return cubeUVRenderTarget;
16390
16391	}
16392
16393	/**
16394	 * Generates a PMREM from an equirectangular texture, which can be either LDR
16395	 * or HDR. The ideal input image size is 1k (1024 x 512),
16396	 * as this matches best with the 256 x 256 cubemap output.
16397	 * The smallest supported equirectangular image size is 64 x 32.
16398	 */
16399	fromEquirectangular( equirectangular, renderTarget = null ) {
16400
16401		return this._fromTexture( equirectangular, renderTarget );
16402
16403	}
16404
16405	/**
16406	 * Generates a PMREM from an cubemap texture, which can be either LDR
16407	 * or HDR. The ideal input cube size is 256 x 256,
16408	 * as this matches best with the 256 x 256 cubemap output.
16409	 * The smallest supported cube size is 16 x 16.
16410	 */
16411	fromCubemap( cubemap, renderTarget = null ) {
16412
16413		return this._fromTexture( cubemap, renderTarget );
16414
16415	}
16416
16417	/**
16418	 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
16419	 * your texture's network fetch for increased concurrency.
16420	 */
16421	compileCubemapShader() {
16422
16423		if ( this._cubemapMaterial === null ) {
16424
16425			this._cubemapMaterial = _getCubemapMaterial();
16426			this._compileMaterial( this._cubemapMaterial );
16427
16428		}
16429
16430	}
16431
16432	/**
16433	 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
16434	 * your texture's network fetch for increased concurrency.
16435	 */
16436	compileEquirectangularShader() {
16437
16438		if ( this._equirectMaterial === null ) {
16439
16440			this._equirectMaterial = _getEquirectMaterial();
16441			this._compileMaterial( this._equirectMaterial );
16442
16443		}
16444
16445	}
16446
16447	/**
16448	 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
16449	 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
16450	 * one of them will cause any others to also become unusable.
16451	 */
16452	dispose() {
16453
16454		this._dispose();
16455
16456		if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose();
16457		if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose();
16458
16459	}
16460
16461	// private interface
16462
16463	_setSize( cubeSize ) {
16464
16465		this._lodMax = Math.floor( Math.log2( cubeSize ) );
16466		this._cubeSize = Math.pow( 2, this._lodMax );
16467
16468	}
16469
16470	_dispose() {
16471
16472		if ( this._blurMaterial !== null ) this._blurMaterial.dispose();
16473
16474		if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose();
16475
16476		for ( let i = 0; i < this._lodPlanes.length; i ++ ) {
16477
16478			this._lodPlanes[ i ].dispose();
16479
16480		}
16481
16482	}
16483
16484	_cleanup( outputTarget ) {
16485
16486		this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel );
16487		this._renderer.xr.enabled = _oldXrEnabled;
16488
16489		outputTarget.scissorTest = false;
16490		_setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
16491
16492	}
16493
16494	_fromTexture( texture, renderTarget ) {
16495
16496		if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) {
16497
16498			this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
16499
16500		} else { // Equirectangular
16501
16502			this._setSize( texture.image.width / 4 );
16503
16504		}
16505
16506		_oldTarget = this._renderer.getRenderTarget();
16507		_oldActiveCubeFace = this._renderer.getActiveCubeFace();
16508		_oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
16509		_oldXrEnabled = this._renderer.xr.enabled;
16510
16511		this._renderer.xr.enabled = false;
16512
16513		const cubeUVRenderTarget = renderTarget || this._allocateTargets();
16514		this._textureToCubeUV( texture, cubeUVRenderTarget );
16515		this._applyPMREM( cubeUVRenderTarget );
16516		this._cleanup( cubeUVRenderTarget );
16517
16518		return cubeUVRenderTarget;
16519
16520	}
16521
16522	_allocateTargets() {
16523
16524		const width = 3 * Math.max( this._cubeSize, 16 * 7 );
16525		const height = 4 * this._cubeSize;
16526
16527		const params = {
16528			magFilter: LinearFilter,
16529			minFilter: LinearFilter,
16530			generateMipmaps: false,
16531			type: HalfFloatType,
16532			format: RGBAFormat,
16533			colorSpace: LinearSRGBColorSpace,
16534			depthBuffer: false
16535		};
16536
16537		const cubeUVRenderTarget = _createRenderTarget( width, height, params );
16538
16539		if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) {
16540
16541			if ( this._pingPongRenderTarget !== null ) {
16542
16543				this._dispose();
16544
16545			}
16546
16547			this._pingPongRenderTarget = _createRenderTarget( width, height, params );
16548
16549			const { _lodMax } = this;
16550			( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) );
16551
16552			this._blurMaterial = _getBlurShader( _lodMax, width, height );
16553
16554		}
16555
16556		return cubeUVRenderTarget;
16557
16558	}
16559
16560	_compileMaterial( material ) {
16561
16562		const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material );
16563		this._renderer.compile( tmpMesh, _flatCamera );
16564
16565	}
16566
16567	_sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
16568
16569		const fov = 90;
16570		const aspect = 1;
16571		const cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
16572		const upSign = [ 1, - 1, 1, 1, 1, 1 ];
16573		const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
16574		const renderer = this._renderer;
16575
16576		const originalAutoClear = renderer.autoClear;
16577		const toneMapping = renderer.toneMapping;
16578		renderer.getClearColor( _clearColor );
16579
16580		renderer.toneMapping = NoToneMapping;
16581		renderer.autoClear = false;
vendor: 8,464 bytes, lines 16582-16938
16582
16583		const backgroundMaterial = new MeshBasicMaterial( {
16584			name: 'PMREM.Background',
16585			side: BackSide,
16586			depthWrite: false,
16587			depthTest: false,
16588		} );
16589
16590		const backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial );
16591
16592		let useSolidColor = false;
16593		const background = scene.background;
16594
16595		if ( background ) {
16596
16597			if ( background.isColor ) {
16598
16599				backgroundMaterial.color.copy( background );
16600				scene.background = null;
16601				useSolidColor = true;
16602
16603			}
16604
16605		} else {
16606
16607			backgroundMaterial.color.copy( _clearColor );
16608			useSolidColor = true;
16609
16610		}
16611
16612		for ( let i = 0; i < 6; i ++ ) {
16613
16614			const col = i % 3;
16615
16616			if ( col === 0 ) {
16617
16618				cubeCamera.up.set( 0, upSign[ i ], 0 );
16619				cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
16620
16621			} else if ( col === 1 ) {
16622
16623				cubeCamera.up.set( 0, 0, upSign[ i ] );
16624				cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
16625
16626			} else {
16627
16628				cubeCamera.up.set( 0, upSign[ i ], 0 );
16629				cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
16630
16631			}
16632
16633			const size = this._cubeSize;
16634
16635			_setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size );
16636
16637			renderer.setRenderTarget( cubeUVRenderTarget );
16638
16639			if ( useSolidColor ) {
16640
16641				renderer.render( backgroundBox, cubeCamera );
16642
16643			}
16644
16645			renderer.render( scene, cubeCamera );
16646
16647		}
16648
16649		backgroundBox.geometry.dispose();
16650		backgroundBox.material.dispose();
16651
16652		renderer.toneMapping = toneMapping;
16653		renderer.autoClear = originalAutoClear;
16654		scene.background = background;
16655
16656	}
16657
16658	_textureToCubeUV( texture, cubeUVRenderTarget ) {
16659
16660		const renderer = this._renderer;
16661
16662		const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping );
16663
16664		if ( isCubeTexture ) {
16665
16666			if ( this._cubemapMaterial === null ) {
16667
16668				this._cubemapMaterial = _getCubemapMaterial();
16669
16670			}
16671
16672			this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1;
16673
16674		} else {
16675
16676			if ( this._equirectMaterial === null ) {
16677
16678				this._equirectMaterial = _getEquirectMaterial();
16679
16680			}
16681
16682		}
16683
16684		const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
16685		const mesh = new Mesh( this._lodPlanes[ 0 ], material );
16686
16687		const uniforms = material.uniforms;
16688
16689		uniforms[ 'envMap' ].value = texture;
16690
16691		const size = this._cubeSize;
16692
16693		_setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size );
16694
16695		renderer.setRenderTarget( cubeUVRenderTarget );
16696		renderer.render( mesh, _flatCamera );
16697
16698	}
16699
16700	_applyPMREM( cubeUVRenderTarget ) {
16701
16702		const renderer = this._renderer;
16703		const autoClear = renderer.autoClear;
16704		renderer.autoClear = false;
16705		const n = this._lodPlanes.length;
16706
16707		for ( let i = 1; i < n; i ++ ) {
16708
16709			const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] );
16710
16711			const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ];
16712
16713			this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
16714
16715		}
16716
16717		renderer.autoClear = autoClear;
16718
16719	}
16720
16721	/**
16722	 * This is a two-pass Gaussian blur for a cubemap. Normally this is done
16723	 * vertically and horizontally, but this breaks down on a cube. Here we apply
16724	 * the blur latitudinally (around the poles), and then longitudinally (towards
16725	 * the poles) to approximate the orthogonally-separable blur. It is least
16726	 * accurate at the poles, but still does a decent job.
16727	 */
16728	_blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
16729
16730		const pingPongRenderTarget = this._pingPongRenderTarget;
16731
16732		this._halfBlur(
16733			cubeUVRenderTarget,
16734			pingPongRenderTarget,
16735			lodIn,
16736			lodOut,
16737			sigma,
16738			'latitudinal',
16739			poleAxis );
16740
16741		this._halfBlur(
16742			pingPongRenderTarget,
16743			cubeUVRenderTarget,
16744			lodOut,
16745			lodOut,
16746			sigma,
16747			'longitudinal',
16748			poleAxis );
16749
16750	}
16751
16752	_halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
16753
16754		const renderer = this._renderer;
16755		const blurMaterial = this._blurMaterial;
16756
16757		if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
16758
16759			console.error(
16760				'blur direction must be either latitudinal or longitudinal!' );
16761
16762		}
16763
16764		// Number of standard deviations at which to cut off the discrete approximation.
16765		const STANDARD_DEVIATIONS = 3;
16766
16767		const blurMesh = new Mesh( this._lodPlanes[ lodOut ], blurMaterial );
16768		const blurUniforms = blurMaterial.uniforms;
16769
16770		const pixels = this._sizeLods[ lodIn ] - 1;
16771		const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
16772		const sigmaPixels = sigmaRadians / radiansPerPixel;
16773		const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
16774
16775		if ( samples > MAX_SAMPLES ) {
16776
16777			console.warn( `sigmaRadians, ${
16778				sigmaRadians}, is too large and will clip, as it requested ${
16779				samples} samples when the maximum is set to ${MAX_SAMPLES}` );
16780
16781		}
16782
16783		const weights = [];
16784		let sum = 0;
16785
16786		for ( let i = 0; i < MAX_SAMPLES; ++ i ) {
16787
16788			const x = i / sigmaPixels;
16789			const weight = Math.exp( - x * x / 2 );
16790			weights.push( weight );
16791
16792			if ( i === 0 ) {
16793
16794				sum += weight;
16795
16796			} else if ( i < samples ) {
16797
16798				sum += 2 * weight;
16799
16800			}
16801
16802		}
16803
16804		for ( let i = 0; i < weights.length; i ++ ) {
16805
16806			weights[ i ] = weights[ i ] / sum;
16807
16808		}
16809
16810		blurUniforms[ 'envMap' ].value = targetIn.texture;
16811		blurUniforms[ 'samples' ].value = samples;
16812		blurUniforms[ 'weights' ].value = weights;
16813		blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
16814
16815		if ( poleAxis ) {
16816
16817			blurUniforms[ 'poleAxis' ].value = poleAxis;
16818
16819		}
16820
16821		const { _lodMax } = this;
16822		blurUniforms[ 'dTheta' ].value = radiansPerPixel;
16823		blurUniforms[ 'mipInt' ].value = _lodMax - lodIn;
16824
16825		const outputSize = this._sizeLods[ lodOut ];
16826		const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 );
16827		const y = 4 * ( this._cubeSize - outputSize );
16828
16829		_setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
16830		renderer.setRenderTarget( targetOut );
16831		renderer.render( blurMesh, _flatCamera );
16832
16833	}
16834
16835}
16836
16837
16838
16839function _createPlanes( lodMax ) {
16840
16841	const lodPlanes = [];
16842	const sizeLods = [];
16843	const sigmas = [];
16844
16845	let lod = lodMax;
16846
16847	const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
16848
16849	for ( let i = 0; i < totalLods; i ++ ) {
16850
16851		const sizeLod = Math.pow( 2, lod );
16852		sizeLods.push( sizeLod );
16853		let sigma = 1.0 / sizeLod;
16854
16855		if ( i > lodMax - LOD_MIN ) {
16856
16857			sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ];
16858
16859		} else if ( i === 0 ) {
16860
16861			sigma = 0;
16862
16863		}
16864
16865		sigmas.push( sigma );
16866
16867		const texelSize = 1.0 / ( sizeLod - 2 );
16868		const min = - texelSize;
16869		const max = 1 + texelSize;
16870		const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
16871
16872		const cubeFaces = 6;
16873		const vertices = 6;
16874		const positionSize = 3;
16875		const uvSize = 2;
16876		const faceIndexSize = 1;
16877
16878		const position = new Float32Array( positionSize * vertices * cubeFaces );
16879		const uv = new Float32Array( uvSize * vertices * cubeFaces );
16880		const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
16881
16882		for ( let face = 0; face < cubeFaces; face ++ ) {
16883
16884			const x = ( face % 3 ) * 2 / 3 - 1;
16885			const y = face > 2 ? 0 : - 1;
16886			const coordinates = [
16887				x, y, 0,
16888				x + 2 / 3, y, 0,
16889				x + 2 / 3, y + 1, 0,
16890				x, y, 0,
16891				x + 2 / 3, y + 1, 0,
16892				x, y + 1, 0
16893			];
16894			position.set( coordinates, positionSize * vertices * face );
16895			uv.set( uv1, uvSize * vertices * face );
16896			const fill = [ face, face, face, face, face, face ];
16897			faceIndex.set( fill, faceIndexSize * vertices * face );
16898
16899		}
16900
16901		const planes = new BufferGeometry();
16902		planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
16903		planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
16904		planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
16905		lodPlanes.push( planes );
16906
16907		if ( lod > LOD_MIN ) {
16908
16909			lod --;
16910
16911		}
16912
16913	}
16914
16915	return { lodPlanes, sizeLods, sigmas };
16916
16917}
16918
16919function _createRenderTarget( width, height, params ) {
16920
16921	const cubeUVRenderTarget = new WebGLRenderTarget( width, height, params );
16922	cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
16923	cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
16924	cubeUVRenderTarget.scissorTest = true;
16925	return cubeUVRenderTarget;
16926
16927}
16928
16929function _setViewport( target, x, y, width, height ) {
16930
16931	target.viewport.set( x, y, width, height );
16932	target.scissor.set( x, y, width, height );
16933
16934}
16935
16936function _getBlurShader( lodMax, width, height ) {
16937
16938	const weights = new Float32Array( MAX_SAMPLES );
vendor: 4,417 bytes, lines 16939-17177
16939	const poleAxis = new Vector3( 0, 1, 0 );
16940	const shaderMaterial = new ShaderMaterial( {
16941
16942		name: 'SphericalGaussianBlur',
16943
16944		defines: {
16945			'n': MAX_SAMPLES,
16946			'CUBEUV_TEXEL_WIDTH': 1.0 / width,
16947			'CUBEUV_TEXEL_HEIGHT': 1.0 / height,
16948			'CUBEUV_MAX_MIP': `${lodMax}.0`,
16949		},
16950
16951		uniforms: {
16952			'envMap': { value: null },
16953			'samples': { value: 1 },
16954			'weights': { value: weights },
16955			'latitudinal': { value: false },
16956			'dTheta': { value: 0 },
16957			'mipInt': { value: 0 },
16958			'poleAxis': { value: poleAxis }
16959		},
16960
16961		vertexShader: _getCommonVertexShader(),
16962
16963		fragmentShader: /* glsl */`
16964
16965			precision mediump float;
16966			precision mediump int;
16967
16968			varying vec3 vOutputDirection;
16969
16970			uniform sampler2D envMap;
16971			uniform int samples;
16972			uniform float weights[ n ];
16973			uniform bool latitudinal;
16974			uniform float dTheta;
16975			uniform float mipInt;
16976			uniform vec3 poleAxis;
16977
16978			#define ENVMAP_TYPE_CUBE_UV
16979			#include <cube_uv_reflection_fragment>
16980
16981			vec3 getSample( float theta, vec3 axis ) {
16982
16983				float cosTheta = cos( theta );
16984				// Rodrigues' axis-angle rotation
16985				vec3 sampleDirection = vOutputDirection * cosTheta
16986					+ cross( axis, vOutputDirection ) * sin( theta )
16987					+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
16988
16989				return bilinearCubeUV( envMap, sampleDirection, mipInt );
16990
16991			}
16992
16993			void main() {
16994
16995				vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
16996
16997				if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
16998
16999					axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
17000
17001				}
17002
17003				axis = normalize( axis );
17004
17005				gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
17006				gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
17007
17008				for ( int i = 1; i < n; i++ ) {
17009
17010					if ( i >= samples ) {
17011
17012						break;
17013
17014					}
17015
17016					float theta = dTheta * float( i );
17017					gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
17018					gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
17019
17020				}
17021
17022			}
17023		`,
17024
17025		blending: NoBlending,
17026		depthTest: false,
17027		depthWrite: false
17028
17029	} );
17030
17031	return shaderMaterial;
17032
17033}
17034
17035function _getEquirectMaterial() {
17036
17037	return new ShaderMaterial( {
17038
17039		name: 'EquirectangularToCubeUV',
17040
17041		uniforms: {
17042			'envMap': { value: null }
17043		},
17044
17045		vertexShader: _getCommonVertexShader(),
17046
17047		fragmentShader: /* glsl */`
17048
17049			precision mediump float;
17050			precision mediump int;
17051
17052			varying vec3 vOutputDirection;
17053
17054			uniform sampler2D envMap;
17055
17056			#include <common>
17057
17058			void main() {
17059
17060				vec3 outputDirection = normalize( vOutputDirection );
17061				vec2 uv = equirectUv( outputDirection );
17062
17063				gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );
17064
17065			}
17066		`,
17067
17068		blending: NoBlending,
17069		depthTest: false,
17070		depthWrite: false
17071
17072	} );
17073
17074}
17075
17076function _getCubemapMaterial() {
17077
17078	return new ShaderMaterial( {
17079
17080		name: 'CubemapToCubeUV',
17081
17082		uniforms: {
17083			'envMap': { value: null },
17084			'flipEnvMap': { value: - 1 }
17085		},
17086
17087		vertexShader: _getCommonVertexShader(),
17088
17089		fragmentShader: /* glsl */`
17090
17091			precision mediump float;
17092			precision mediump int;
17093
17094			uniform float flipEnvMap;
17095
17096			varying vec3 vOutputDirection;
17097
17098			uniform samplerCube envMap;
17099
17100			void main() {
17101
17102				gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
17103
17104			}
17105		`,
17106
17107		blending: NoBlending,
17108		depthTest: false,
17109		depthWrite: false
17110
17111	} );
17112
17113}
17114
17115function _getCommonVertexShader() {
17116
17117	return /* glsl */`
17118
17119		precision mediump float;
17120		precision mediump int;
17121
17122		attribute float faceIndex;
17123
17124		varying vec3 vOutputDirection;
17125
17126		// RH coordinate system; PMREM face-indexing convention
17127		vec3 getDirection( vec2 uv, float face ) {
17128
17129			uv = 2.0 * uv - 1.0;
17130
17131			vec3 direction = vec3( uv, 1.0 );
17132
17133			if ( face == 0.0 ) {
17134
17135				direction = direction.zyx; // ( 1, v, u ) pos x
17136
17137			} else if ( face == 1.0 ) {
17138
17139				direction = direction.xzy;
17140				direction.xz *= -1.0; // ( -u, 1, -v ) pos y
17141
17142			} else if ( face == 2.0 ) {
17143
17144				direction.x *= -1.0; // ( -u, v, 1 ) pos z
17145
17146			} else if ( face == 3.0 ) {
17147
17148				direction = direction.zyx;
17149				direction.xz *= -1.0; // ( -1, v, -u ) neg x
17150
17151			} else if ( face == 4.0 ) {
17152
17153				direction = direction.xzy;
17154				direction.xy *= -1.0; // ( -u, -1, v ) neg y
17155
17156			} else if ( face == 5.0 ) {
17157
17158				direction.z *= -1.0; // ( u, v, -1 ) neg z
17159
17160			}
17161
17162			return direction;
17163
17164		}
17165
17166		void main() {
17167
17168			vOutputDirection = getDirection( uv, faceIndex );
17169			gl_Position = vec4( position, 1.0 );
17170
17171		}
17172	`;
17173
17174}
17175
17176function WebGLCubeUVMaps( renderer ) {
17177
vendor: 9,737 bytes, lines 17178-17675
17178	let cubeUVmaps = new WeakMap();
17179
17180	let pmremGenerator = null;
17181
17182	function get( texture ) {
17183
17184		if ( texture && texture.isTexture ) {
17185
17186			const mapping = texture.mapping;
17187
17188			const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
17189			const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
17190
17191			// equirect/cube map to cubeUV conversion
17192
17193			if ( isEquirectMap || isCubeMap ) {
17194
17195				let renderTarget = cubeUVmaps.get( texture );
17196
17197				const currentPMREMVersion = renderTarget !== undefined ? renderTarget.texture.pmremVersion : 0;
17198
17199				if ( texture.isRenderTargetTexture && texture.pmremVersion !== currentPMREMVersion ) {
17200
17201					if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
17202
17203					renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget );
17204					renderTarget.texture.pmremVersion = texture.pmremVersion;
17205
17206					cubeUVmaps.set( texture, renderTarget );
17207
17208					return renderTarget.texture;
17209
17210				} else {
17211
17212					if ( renderTarget !== undefined ) {
17213
17214						return renderTarget.texture;
17215
17216					} else {
17217
17218						const image = texture.image;
17219
17220						if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) {
17221
17222							if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
17223
17224							renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture );
17225							renderTarget.texture.pmremVersion = texture.pmremVersion;
17226
17227							cubeUVmaps.set( texture, renderTarget );
17228
17229							texture.addEventListener( 'dispose', onTextureDispose );
17230
17231							return renderTarget.texture;
17232
17233						} else {
17234
17235							// image not yet ready. try the conversion next frame
17236
17237							return null;
17238
17239						}
17240
17241					}
17242
17243				}
17244
17245			}
17246
17247		}
17248
17249		return texture;
17250
17251	}
17252
17253	function isCubeTextureComplete( image ) {
17254
17255		let count = 0;
17256		const length = 6;
17257
17258		for ( let i = 0; i < length; i ++ ) {
17259
17260			if ( image[ i ] !== undefined ) count ++;
17261
17262		}
17263
17264		return count === length;
17265
17266
17267	}
17268
17269	function onTextureDispose( event ) {
17270
17271		const texture = event.target;
17272
17273		texture.removeEventListener( 'dispose', onTextureDispose );
17274
17275		const cubemapUV = cubeUVmaps.get( texture );
17276
17277		if ( cubemapUV !== undefined ) {
17278
17279			cubeUVmaps.delete( texture );
17280			cubemapUV.dispose();
17281
17282		}
17283
17284	}
17285
17286	function dispose() {
17287
17288		cubeUVmaps = new WeakMap();
17289
17290		if ( pmremGenerator !== null ) {
17291
17292			pmremGenerator.dispose();
17293			pmremGenerator = null;
17294
17295		}
17296
17297	}
17298
17299	return {
17300		get: get,
17301		dispose: dispose
17302	};
17303
17304}
17305
17306function WebGLExtensions( gl ) {
17307
17308	const extensions = {};
17309
17310	function getExtension( name ) {
17311
17312		if ( extensions[ name ] !== undefined ) {
17313
17314			return extensions[ name ];
17315
17316		}
17317
17318		let extension;
17319
17320		switch ( name ) {
17321
17322			case 'WEBGL_depth_texture':
17323				extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );
17324				break;
17325
17326			case 'EXT_texture_filter_anisotropic':
17327				extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
17328				break;
17329
17330			case 'WEBGL_compressed_texture_s3tc':
17331				extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
17332				break;
17333
17334			case 'WEBGL_compressed_texture_pvrtc':
17335				extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );
17336				break;
17337
17338			default:
17339				extension = gl.getExtension( name );
17340
17341		}
17342
17343		extensions[ name ] = extension;
17344
17345		return extension;
17346
17347	}
17348
17349	return {
17350
17351		has: function ( name ) {
17352
17353			return getExtension( name ) !== null;
17354
17355		},
17356
17357		init: function () {
17358
17359			getExtension( 'EXT_color_buffer_float' );
17360			getExtension( 'WEBGL_clip_cull_distance' );
17361			getExtension( 'OES_texture_float_linear' );
17362			getExtension( 'EXT_color_buffer_half_float' );
17363			getExtension( 'WEBGL_multisampled_render_to_texture' );
17364			getExtension( 'WEBGL_render_shared_exponent' );
17365
17366		},
17367
17368		get: function ( name ) {
17369
17370			const extension = getExtension( name );
17371
17372			if ( extension === null ) {
17373
17374				warnOnce( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );
17375
17376			}
17377
17378			return extension;
17379
17380		}
17381
17382	};
17383
17384}
17385
17386function WebGLGeometries( gl, attributes, info, bindingStates ) {
17387
17388	const geometries = {};
17389	const wireframeAttributes = new WeakMap();
17390
17391	function onGeometryDispose( event ) {
17392
17393		const geometry = event.target;
17394
17395		if ( geometry.index !== null ) {
17396
17397			attributes.remove( geometry.index );
17398
17399		}
17400
17401		for ( const name in geometry.attributes ) {
17402
17403			attributes.remove( geometry.attributes[ name ] );
17404
17405		}
17406
17407		for ( const name in geometry.morphAttributes ) {
17408
17409			const array = geometry.morphAttributes[ name ];
17410
17411			for ( let i = 0, l = array.length; i < l; i ++ ) {
17412
17413				attributes.remove( array[ i ] );
17414
17415			}
17416
17417		}
17418
17419		geometry.removeEventListener( 'dispose', onGeometryDispose );
17420
17421		delete geometries[ geometry.id ];
17422
17423		const attribute = wireframeAttributes.get( geometry );
17424
17425		if ( attribute ) {
17426
17427			attributes.remove( attribute );
17428			wireframeAttributes.delete( geometry );
17429
17430		}
17431
17432		bindingStates.releaseStatesOfGeometry( geometry );
17433
17434		if ( geometry.isInstancedBufferGeometry === true ) {
17435
17436			delete geometry._maxInstanceCount;
17437
17438		}
17439
17440		//
17441
17442		info.memory.geometries --;
17443
17444	}
17445
17446	function get( object, geometry ) {
17447
17448		if ( geometries[ geometry.id ] === true ) return geometry;
17449
17450		geometry.addEventListener( 'dispose', onGeometryDispose );
17451
17452		geometries[ geometry.id ] = true;
17453
17454		info.memory.geometries ++;
17455
17456		return geometry;
17457
17458	}
17459
17460	function update( geometry ) {
17461
17462		const geometryAttributes = geometry.attributes;
17463
17464		// Updating index buffer in VAO now. See WebGLBindingStates.
17465
17466		for ( const name in geometryAttributes ) {
17467
17468			attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
17469
17470		}
17471
17472		// morph targets
17473
17474		const morphAttributes = geometry.morphAttributes;
17475
17476		for ( const name in morphAttributes ) {
17477
17478			const array = morphAttributes[ name ];
17479
17480			for ( let i = 0, l = array.length; i < l; i ++ ) {
17481
17482				attributes.update( array[ i ], gl.ARRAY_BUFFER );
17483
17484			}
17485
17486		}
17487
17488	}
17489
17490	function updateWireframeAttribute( geometry ) {
17491
17492		const indices = [];
17493
17494		const geometryIndex = geometry.index;
17495		const geometryPosition = geometry.attributes.position;
17496		let version = 0;
17497
17498		if ( geometryIndex !== null ) {
17499
17500			const array = geometryIndex.array;
17501			version = geometryIndex.version;
17502
17503			for ( let i = 0, l = array.length; i < l; i += 3 ) {
17504
17505				const a = array[ i + 0 ];
17506				const b = array[ i + 1 ];
17507				const c = array[ i + 2 ];
17508
17509				indices.push( a, b, b, c, c, a );
17510
17511			}
17512
17513		} else if ( geometryPosition !== undefined ) {
17514
17515			const array = geometryPosition.array;
17516			version = geometryPosition.version;
17517
17518			for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
17519
17520				const a = i + 0;
17521				const b = i + 1;
17522				const c = i + 2;
17523
17524				indices.push( a, b, b, c, c, a );
17525
17526			}
17527
17528		} else {
17529
17530			return;
17531
17532		}
17533
17534		const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
17535		attribute.version = version;
17536
17537		// Updating index buffer in VAO now. See WebGLBindingStates
17538
17539		//
17540
17541		const previousAttribute = wireframeAttributes.get( geometry );
17542
17543		if ( previousAttribute ) attributes.remove( previousAttribute );
17544
17545		//
17546
17547		wireframeAttributes.set( geometry, attribute );
17548
17549	}
17550
17551	function getWireframeAttribute( geometry ) {
17552
17553		const currentAttribute = wireframeAttributes.get( geometry );
17554
17555		if ( currentAttribute ) {
17556
17557			const geometryIndex = geometry.index;
17558
17559			if ( geometryIndex !== null ) {
17560
17561				// if the attribute is obsolete, create a new one
17562
17563				if ( currentAttribute.version < geometryIndex.version ) {
17564
17565					updateWireframeAttribute( geometry );
17566
17567				}
17568
17569			}
17570
17571		} else {
17572
17573			updateWireframeAttribute( geometry );
17574
17575		}
17576
17577		return wireframeAttributes.get( geometry );
17578
17579	}
17580
17581	return {
17582
17583		get: get,
17584		update: update,
17585
17586		getWireframeAttribute: getWireframeAttribute
17587
17588	};
17589
17590}
17591
17592function WebGLIndexedBufferRenderer( gl, extensions, info ) {
17593
17594	let mode;
17595
17596	function setMode( value ) {
17597
17598		mode = value;
17599
17600	}
17601
17602	let type, bytesPerElement;
17603
17604	function setIndex( value ) {
17605
17606		type = value.type;
17607		bytesPerElement = value.bytesPerElement;
17608
17609	}
17610
17611	function render( start, count ) {
17612
17613		gl.drawElements( mode, count, type, start * bytesPerElement );
17614
17615		info.update( count, mode, 1 );
17616
17617	}
17618
17619	function renderInstances( start, count, primcount ) {
17620
17621		if ( primcount === 0 ) return;
17622
17623		gl.drawElementsInstanced( mode, count, type, start * bytesPerElement, primcount );
17624
17625		info.update( count, mode, primcount );
17626
17627	}
17628
17629	function renderMultiDraw( starts, counts, drawCount ) {
17630
17631		if ( drawCount === 0 ) return;
17632
17633		const extension = extensions.get( 'WEBGL_multi_draw' );
17634
17635		if ( extension === null ) {
17636
17637			for ( let i = 0; i < drawCount; i ++ ) {
17638
17639				this.render( starts[ i ] / bytesPerElement, counts[ i ] );
17640
17641			}
17642
17643		} else {
17644
17645			extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount );
17646
17647			let elementCount = 0;
17648			for ( let i = 0; i < drawCount; i ++ ) {
17649
17650				elementCount += counts[ i ];
17651
17652			}
17653
17654			info.update( elementCount, mode, 1 );
17655
17656		}
17657
17658	}
17659
17660	function renderMultiDrawInstances( starts, counts, drawCount, primcount ) {
17661
17662		if ( drawCount === 0 ) return;
17663
17664		const extension = extensions.get( 'WEBGL_multi_draw' );
17665
17666		if ( extension === null ) {
17667
17668			for ( let i = 0; i < starts.length; i ++ ) {
17669
17670				renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] );
17671
17672			}
17673
17674		} else {
17675
vendor: 7,412 bytes, lines 17676-18019
17676			extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount );
17677
17678			let elementCount = 0;
17679			for ( let i = 0; i < drawCount; i ++ ) {
17680
17681				elementCount += counts[ i ];
17682
17683			}
17684
17685			for ( let i = 0; i < primcount.length; i ++ ) {
17686
17687				info.update( elementCount, mode, primcount[ i ] );
17688
17689			}
17690
17691		}
17692
17693	}
17694
17695	//
17696
17697	this.setMode = setMode;
17698	this.setIndex = setIndex;
17699	this.render = render;
17700	this.renderInstances = renderInstances;
17701	this.renderMultiDraw = renderMultiDraw;
17702	this.renderMultiDrawInstances = renderMultiDrawInstances;
17703
17704}
17705
17706function WebGLInfo( gl ) {
17707
17708	const memory = {
17709		geometries: 0,
17710		textures: 0
17711	};
17712
17713	const render = {
17714		frame: 0,
17715		calls: 0,
17716		triangles: 0,
17717		points: 0,
17718		lines: 0
17719	};
17720
17721	function update( count, mode, instanceCount ) {
17722
17723		render.calls ++;
17724
17725		switch ( mode ) {
17726
17727			case gl.TRIANGLES:
17728				render.triangles += instanceCount * ( count / 3 );
17729				break;
17730
17731			case gl.LINES:
17732				render.lines += instanceCount * ( count / 2 );
17733				break;
17734
17735			case gl.LINE_STRIP:
17736				render.lines += instanceCount * ( count - 1 );
17737				break;
17738
17739			case gl.LINE_LOOP:
17740				render.lines += instanceCount * count;
17741				break;
17742
17743			case gl.POINTS:
17744				render.points += instanceCount * count;
17745				break;
17746
17747			default:
17748				console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );
17749				break;
17750
17751		}
17752
17753	}
17754
17755	function reset() {
17756
17757		render.calls = 0;
17758		render.triangles = 0;
17759		render.points = 0;
17760		render.lines = 0;
17761
17762	}
17763
17764	return {
17765		memory: memory,
17766		render: render,
17767		programs: null,
17768		autoReset: true,
17769		reset: reset,
17770		update: update
17771	};
17772
17773}
17774
17775function WebGLMorphtargets( gl, capabilities, textures ) {
17776
17777	const morphTextures = new WeakMap();
17778	const morph = new Vector4();
17779
17780	function update( object, geometry, program ) {
17781
17782		const objectInfluences = object.morphTargetInfluences;
17783
17784		// the following encodes morph targets into an array of data textures. Each layer represents a single morph target.
17785
17786		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
17787		const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
17788
17789		let entry = morphTextures.get( geometry );
17790
17791		if ( entry === undefined || entry.count !== morphTargetsCount ) {
17792
17793			if ( entry !== undefined ) entry.texture.dispose();
17794
17795			const hasMorphPosition = geometry.morphAttributes.position !== undefined;
17796			const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
17797			const hasMorphColors = geometry.morphAttributes.color !== undefined;
17798
17799			const morphTargets = geometry.morphAttributes.position || [];
17800			const morphNormals = geometry.morphAttributes.normal || [];
17801			const morphColors = geometry.morphAttributes.color || [];
17802
17803			let vertexDataCount = 0;
17804
17805			if ( hasMorphPosition === true ) vertexDataCount = 1;
17806			if ( hasMorphNormals === true ) vertexDataCount = 2;
17807			if ( hasMorphColors === true ) vertexDataCount = 3;
17808
17809			let width = geometry.attributes.position.count * vertexDataCount;
17810			let height = 1;
17811
17812			if ( width > capabilities.maxTextureSize ) {
17813
17814				height = Math.ceil( width / capabilities.maxTextureSize );
17815				width = capabilities.maxTextureSize;
17816
17817			}
17818
17819			const buffer = new Float32Array( width * height * 4 * morphTargetsCount );
17820
17821			const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount );
17822			texture.type = FloatType;
17823			texture.needsUpdate = true;
17824
17825			// fill buffer
17826
17827			const vertexDataStride = vertexDataCount * 4;
17828
17829			for ( let i = 0; i < morphTargetsCount; i ++ ) {
17830
17831				const morphTarget = morphTargets[ i ];
17832				const morphNormal = morphNormals[ i ];
17833				const morphColor = morphColors[ i ];
17834
17835				const offset = width * height * 4 * i;
17836
17837				for ( let j = 0; j < morphTarget.count; j ++ ) {
17838
17839					const stride = j * vertexDataStride;
17840
17841					if ( hasMorphPosition === true ) {
17842
17843						morph.fromBufferAttribute( morphTarget, j );
17844
17845						buffer[ offset + stride + 0 ] = morph.x;
17846						buffer[ offset + stride + 1 ] = morph.y;
17847						buffer[ offset + stride + 2 ] = morph.z;
17848						buffer[ offset + stride + 3 ] = 0;
17849
17850					}
17851
17852					if ( hasMorphNormals === true ) {
17853
17854						morph.fromBufferAttribute( morphNormal, j );
17855
17856						buffer[ offset + stride + 4 ] = morph.x;
17857						buffer[ offset + stride + 5 ] = morph.y;
17858						buffer[ offset + stride + 6 ] = morph.z;
17859						buffer[ offset + stride + 7 ] = 0;
17860
17861					}
17862
17863					if ( hasMorphColors === true ) {
17864
17865						morph.fromBufferAttribute( morphColor, j );
17866
17867						buffer[ offset + stride + 8 ] = morph.x;
17868						buffer[ offset + stride + 9 ] = morph.y;
17869						buffer[ offset + stride + 10 ] = morph.z;
17870						buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1;
17871
17872					}
17873
17874				}
17875
17876			}
17877
17878			entry = {
17879				count: morphTargetsCount,
17880				texture: texture,
17881				size: new Vector2( width, height )
17882			};
17883
17884			morphTextures.set( geometry, entry );
17885
17886			function disposeTexture() {
17887
17888				texture.dispose();
17889
17890				morphTextures.delete( geometry );
17891
17892				geometry.removeEventListener( 'dispose', disposeTexture );
17893
17894			}
17895
17896			geometry.addEventListener( 'dispose', disposeTexture );
17897
17898		}
17899
17900		//
17901		if ( object.isInstancedMesh === true && object.morphTexture !== null ) {
17902
17903			program.getUniforms().setValue( gl, 'morphTexture', object.morphTexture, textures );
17904
17905		} else {
17906
17907			let morphInfluencesSum = 0;
17908
17909			for ( let i = 0; i < objectInfluences.length; i ++ ) {
17910
17911				morphInfluencesSum += objectInfluences[ i ];
17912
17913			}
17914
17915			const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
17916
17917
17918			program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
17919			program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences );
17920
17921		}
17922
17923		program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures );
17924		program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
17925
17926	}
17927
17928	return {
17929
17930		update: update
17931
17932	};
17933
17934}
17935
17936function WebGLObjects( gl, geometries, attributes, info ) {
17937
17938	let updateMap = new WeakMap();
17939
17940	function update( object ) {
17941
17942		const frame = info.render.frame;
17943
17944		const geometry = object.geometry;
17945		const buffergeometry = geometries.get( object, geometry );
17946
17947		// Update once per frame
17948
17949		if ( updateMap.get( buffergeometry ) !== frame ) {
17950
17951			geometries.update( buffergeometry );
17952
17953			updateMap.set( buffergeometry, frame );
17954
17955		}
17956
17957		if ( object.isInstancedMesh ) {
17958
17959			if ( object.hasEventListener( 'dispose', onInstancedMeshDispose ) === false ) {
17960
17961				object.addEventListener( 'dispose', onInstancedMeshDispose );
17962
17963			}
17964
17965			if ( updateMap.get( object ) !== frame ) {
17966
17967				attributes.update( object.instanceMatrix, gl.ARRAY_BUFFER );
17968
17969				if ( object.instanceColor !== null ) {
17970
17971					attributes.update( object.instanceColor, gl.ARRAY_BUFFER );
17972
17973				}
17974
17975				updateMap.set( object, frame );
17976
17977			}
17978
17979		}
17980
17981		if ( object.isSkinnedMesh ) {
17982
17983			const skeleton = object.skeleton;
17984
17985			if ( updateMap.get( skeleton ) !== frame ) {
17986
17987				skeleton.update();
17988
17989				updateMap.set( skeleton, frame );
17990
17991			}
17992
17993		}
17994
17995		return buffergeometry;
17996
17997	}
17998
17999	function dispose() {
18000
18001		updateMap = new WeakMap();
18002
18003	}
18004
18005	function onInstancedMeshDispose( event ) {
18006
18007		const instancedMesh = event.target;
18008
18009		instancedMesh.removeEventListener( 'dispose', onInstancedMeshDispose );
18010
18011		attributes.remove( instancedMesh.instanceMatrix );
18012
18013		if ( instancedMesh.instanceColor !== null ) attributes.remove( instancedMesh.instanceColor );
18014
18015	}
18016
18017	return {
18018
18019		update: update,
18020		dispose: dispose
18021
18022	};
18023
18024}
18025
18026class DepthTexture extends Texture {
18027
18028	constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format = DepthFormat ) {
vendor: 24,805 bytes, lines 18028-19376
18028
18029
18030		if ( format !== DepthFormat && format !== DepthStencilFormat ) {
18031
18032			throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
18033
18034		}
18035
18036		if ( type === undefined && format === DepthFormat ) type = UnsignedIntType;
18037		if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
18038
18039		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18040
18041		this.isDepthTexture = true;
18042
18043		this.image = { width: width, height: height };
18044
18045		this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
18046		this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
18047
18048		this.flipY = false;
18049		this.generateMipmaps = false;
18050
18051		this.compareFunction = null;
18052
18053	}
18054
18055
18056	copy( source ) {
18057
18058		super.copy( source );
18059
18060		this.compareFunction = source.compareFunction;
18061
18062		return this;
18063
18064	}
18065
18066	toJSON( meta ) {
18067
18068		const data = super.toJSON( meta );
18069
18070		if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction;
18071
18072		return data;
18073
18074	}
18075
18076}
18077
18078/**
18079 * Uniforms of a program.
18080 * Those form a tree structure with a special top-level container for the root,
18081 * which you get by calling 'new WebGLUniforms( gl, program )'.
18082 *
18083 *
18084 * Properties of inner nodes including the top-level container:
18085 *
18086 * .seq - array of nested uniforms
18087 * .map - nested uniforms by name
18088 *
18089 *
18090 * Methods of all nodes except the top-level container:
18091 *
18092 * .setValue( gl, value, [textures] )
18093 *
18094 * 		uploads a uniform value(s)
18095 *  	the 'textures' parameter is needed for sampler uniforms
18096 *
18097 *
18098 * Static methods of the top-level container (textures factorizations):
18099 *
18100 * .upload( gl, seq, values, textures )
18101 *
18102 * 		sets uniforms in 'seq' to 'values[id].value'
18103 *
18104 * .seqWithValue( seq, values ) : filteredSeq
18105 *
18106 * 		filters 'seq' entries with corresponding entry in values
18107 *
18108 *
18109 * Methods of the top-level container (textures factorizations):
18110 *
18111 * .setValue( gl, name, value, textures )
18112 *
18113 * 		sets uniform with  name 'name' to 'value'
18114 *
18115 * .setOptional( gl, obj, prop )
18116 *
18117 * 		like .set for an optional property of the object
18118 *
18119 */
18120
18121
18122const emptyTexture = /*@__PURE__*/ new Texture();
18123
18124const emptyShadowTexture = /*@__PURE__*/ new DepthTexture( 1, 1 );
18125emptyShadowTexture.compareFunction = LessEqualCompare;
18126
18127const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture();
18128const empty3dTexture = /*@__PURE__*/ new Data3DTexture();
18129const emptyCubeTexture = /*@__PURE__*/ new CubeTexture();
18130
18131// --- Utilities ---
18132
18133// Array Caches (provide typed arrays for temporary by size)
18134
18135const arrayCacheF32 = [];
18136const arrayCacheI32 = [];
18137
18138// Float32Array caches used for uploading Matrix uniforms
18139
18140const mat4array = new Float32Array( 16 );
18141const mat3array = new Float32Array( 9 );
18142const mat2array = new Float32Array( 4 );
18143
18144// Flattening for arrays of vectors and matrices
18145
18146function flatten( array, nBlocks, blockSize ) {
18147
18148	const firstElem = array[ 0 ];
18149
18150	if ( firstElem <= 0 || firstElem > 0 ) return array;
18151	// unoptimized: ! isNaN( firstElem )
18152	// see http://jacksondunstan.com/articles/983
18153
18154	const n = nBlocks * blockSize;
18155	let r = arrayCacheF32[ n ];
18156
18157	if ( r === undefined ) {
18158
18159		r = new Float32Array( n );
18160		arrayCacheF32[ n ] = r;
18161
18162	}
18163
18164	if ( nBlocks !== 0 ) {
18165
18166		firstElem.toArray( r, 0 );
18167
18168		for ( let i = 1, offset = 0; i !== nBlocks; ++ i ) {
18169
18170			offset += blockSize;
18171			array[ i ].toArray( r, offset );
18172
18173		}
18174
18175	}
18176
18177	return r;
18178
18179}
18180
18181function arraysEqual( a, b ) {
18182
18183	if ( a.length !== b.length ) return false;
18184
18185	for ( let i = 0, l = a.length; i < l; i ++ ) {
18186
18187		if ( a[ i ] !== b[ i ] ) return false;
18188
18189	}
18190
18191	return true;
18192
18193}
18194
18195function copyArray( a, b ) {
18196
18197	for ( let i = 0, l = b.length; i < l; i ++ ) {
18198
18199		a[ i ] = b[ i ];
18200
18201	}
18202
18203}
18204
18205// Texture unit allocation
18206
18207function allocTexUnits( textures, n ) {
18208
18209	let r = arrayCacheI32[ n ];
18210
18211	if ( r === undefined ) {
18212
18213		r = new Int32Array( n );
18214		arrayCacheI32[ n ] = r;
18215
18216	}
18217
18218	for ( let i = 0; i !== n; ++ i ) {
18219
18220		r[ i ] = textures.allocateTextureUnit();
18221
18222	}
18223
18224	return r;
18225
18226}
18227
18228// --- Setters ---
18229
18230// Note: Defining these methods externally, because they come in a bunch
18231// and this way their names minify.
18232
18233// Single scalar
18234
18235function setValueV1f( gl, v ) {
18236
18237	const cache = this.cache;
18238
18239	if ( cache[ 0 ] === v ) return;
18240
18241	gl.uniform1f( this.addr, v );
18242
18243	cache[ 0 ] = v;
18244
18245}
18246
18247// Single float vector (from flat array or THREE.VectorN)
18248
18249function setValueV2f( gl, v ) {
18250
18251	const cache = this.cache;
18252
18253	if ( v.x !== undefined ) {
18254
18255		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
18256
18257			gl.uniform2f( this.addr, v.x, v.y );
18258
18259			cache[ 0 ] = v.x;
18260			cache[ 1 ] = v.y;
18261
18262		}
18263
18264	} else {
18265
18266		if ( arraysEqual( cache, v ) ) return;
18267
18268		gl.uniform2fv( this.addr, v );
18269
18270		copyArray( cache, v );
18271
18272	}
18273
18274}
18275
18276function setValueV3f( gl, v ) {
18277
18278	const cache = this.cache;
18279
18280	if ( v.x !== undefined ) {
18281
18282		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
18283
18284			gl.uniform3f( this.addr, v.x, v.y, v.z );
18285
18286			cache[ 0 ] = v.x;
18287			cache[ 1 ] = v.y;
18288			cache[ 2 ] = v.z;
18289
18290		}
18291
18292	} else if ( v.r !== undefined ) {
18293
18294		if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {
18295
18296			gl.uniform3f( this.addr, v.r, v.g, v.b );
18297
18298			cache[ 0 ] = v.r;
18299			cache[ 1 ] = v.g;
18300			cache[ 2 ] = v.b;
18301
18302		}
18303
18304	} else {
18305
18306		if ( arraysEqual( cache, v ) ) return;
18307
18308		gl.uniform3fv( this.addr, v );
18309
18310		copyArray( cache, v );
18311
18312	}
18313
18314}
18315
18316function setValueV4f( gl, v ) {
18317
18318	const cache = this.cache;
18319
18320	if ( v.x !== undefined ) {
18321
18322		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
18323
18324			gl.uniform4f( this.addr, v.x, v.y, v.z, v.w );
18325
18326			cache[ 0 ] = v.x;
18327			cache[ 1 ] = v.y;
18328			cache[ 2 ] = v.z;
18329			cache[ 3 ] = v.w;
18330
18331		}
18332
18333	} else {
18334
18335		if ( arraysEqual( cache, v ) ) return;
18336
18337		gl.uniform4fv( this.addr, v );
18338
18339		copyArray( cache, v );
18340
18341	}
18342
18343}
18344
18345// Single matrix (from flat array or THREE.MatrixN)
18346
18347function setValueM2( gl, v ) {
18348
18349	const cache = this.cache;
18350	const elements = v.elements;
18351
18352	if ( elements === undefined ) {
18353
18354		if ( arraysEqual( cache, v ) ) return;
18355
18356		gl.uniformMatrix2fv( this.addr, false, v );
18357
18358		copyArray( cache, v );
18359
18360	} else {
18361
18362		if ( arraysEqual( cache, elements ) ) return;
18363
18364		mat2array.set( elements );
18365
18366		gl.uniformMatrix2fv( this.addr, false, mat2array );
18367
18368		copyArray( cache, elements );
18369
18370	}
18371
18372}
18373
18374function setValueM3( gl, v ) {
18375
18376	const cache = this.cache;
18377	const elements = v.elements;
18378
18379	if ( elements === undefined ) {
18380
18381		if ( arraysEqual( cache, v ) ) return;
18382
18383		gl.uniformMatrix3fv( this.addr, false, v );
18384
18385		copyArray( cache, v );
18386
18387	} else {
18388
18389		if ( arraysEqual( cache, elements ) ) return;
18390
18391		mat3array.set( elements );
18392
18393		gl.uniformMatrix3fv( this.addr, false, mat3array );
18394
18395		copyArray( cache, elements );
18396
18397	}
18398
18399}
18400
18401function setValueM4( gl, v ) {
18402
18403	const cache = this.cache;
18404	const elements = v.elements;
18405
18406	if ( elements === undefined ) {
18407
18408		if ( arraysEqual( cache, v ) ) return;
18409
18410		gl.uniformMatrix4fv( this.addr, false, v );
18411
18412		copyArray( cache, v );
18413
18414	} else {
18415
18416		if ( arraysEqual( cache, elements ) ) return;
18417
18418		mat4array.set( elements );
18419
18420		gl.uniformMatrix4fv( this.addr, false, mat4array );
18421
18422		copyArray( cache, elements );
18423
18424	}
18425
18426}
18427
18428// Single integer / boolean
18429
18430function setValueV1i( gl, v ) {
18431
18432	const cache = this.cache;
18433
18434	if ( cache[ 0 ] === v ) return;
18435
18436	gl.uniform1i( this.addr, v );
18437
18438	cache[ 0 ] = v;
18439
18440}
18441
18442// Single integer / boolean vector (from flat array or THREE.VectorN)
18443
18444function setValueV2i( gl, v ) {
18445
18446	const cache = this.cache;
18447
18448	if ( v.x !== undefined ) {
18449
18450		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
18451
18452			gl.uniform2i( this.addr, v.x, v.y );
18453
18454			cache[ 0 ] = v.x;
18455			cache[ 1 ] = v.y;
18456
18457		}
18458
18459	} else {
18460
18461		if ( arraysEqual( cache, v ) ) return;
18462
18463		gl.uniform2iv( this.addr, v );
18464
18465		copyArray( cache, v );
18466
18467	}
18468
18469}
18470
18471function setValueV3i( gl, v ) {
18472
18473	const cache = this.cache;
18474
18475	if ( v.x !== undefined ) {
18476
18477		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
18478
18479			gl.uniform3i( this.addr, v.x, v.y, v.z );
18480
18481			cache[ 0 ] = v.x;
18482			cache[ 1 ] = v.y;
18483			cache[ 2 ] = v.z;
18484
18485		}
18486
18487	} else {
18488
18489		if ( arraysEqual( cache, v ) ) return;
18490
18491		gl.uniform3iv( this.addr, v );
18492
18493		copyArray( cache, v );
18494
18495	}
18496
18497}
18498
18499function setValueV4i( gl, v ) {
18500
18501	const cache = this.cache;
18502
18503	if ( v.x !== undefined ) {
18504
18505		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
18506
18507			gl.uniform4i( this.addr, v.x, v.y, v.z, v.w );
18508
18509			cache[ 0 ] = v.x;
18510			cache[ 1 ] = v.y;
18511			cache[ 2 ] = v.z;
18512			cache[ 3 ] = v.w;
18513
18514		}
18515
18516	} else {
18517
18518		if ( arraysEqual( cache, v ) ) return;
18519
18520		gl.uniform4iv( this.addr, v );
18521
18522		copyArray( cache, v );
18523
18524	}
18525
18526}
18527
18528// Single unsigned integer
18529
18530function setValueV1ui( gl, v ) {
18531
18532	const cache = this.cache;
18533
18534	if ( cache[ 0 ] === v ) return;
18535
18536	gl.uniform1ui( this.addr, v );
18537
18538	cache[ 0 ] = v;
18539
18540}
18541
18542// Single unsigned integer vector (from flat array or THREE.VectorN)
18543
18544function setValueV2ui( gl, v ) {
18545
18546	const cache = this.cache;
18547
18548	if ( v.x !== undefined ) {
18549
18550		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {
18551
18552			gl.uniform2ui( this.addr, v.x, v.y );
18553
18554			cache[ 0 ] = v.x;
18555			cache[ 1 ] = v.y;
18556
18557		}
18558
18559	} else {
18560
18561		if ( arraysEqual( cache, v ) ) return;
18562
18563		gl.uniform2uiv( this.addr, v );
18564
18565		copyArray( cache, v );
18566
18567	}
18568
18569}
18570
18571function setValueV3ui( gl, v ) {
18572
18573	const cache = this.cache;
18574
18575	if ( v.x !== undefined ) {
18576
18577		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {
18578
18579			gl.uniform3ui( this.addr, v.x, v.y, v.z );
18580
18581			cache[ 0 ] = v.x;
18582			cache[ 1 ] = v.y;
18583			cache[ 2 ] = v.z;
18584
18585		}
18586
18587	} else {
18588
18589		if ( arraysEqual( cache, v ) ) return;
18590
18591		gl.uniform3uiv( this.addr, v );
18592
18593		copyArray( cache, v );
18594
18595	}
18596
18597}
18598
18599function setValueV4ui( gl, v ) {
18600
18601	const cache = this.cache;
18602
18603	if ( v.x !== undefined ) {
18604
18605		if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {
18606
18607			gl.uniform4ui( this.addr, v.x, v.y, v.z, v.w );
18608
18609			cache[ 0 ] = v.x;
18610			cache[ 1 ] = v.y;
18611			cache[ 2 ] = v.z;
18612			cache[ 3 ] = v.w;
18613
18614		}
18615
18616	} else {
18617
18618		if ( arraysEqual( cache, v ) ) return;
18619
18620		gl.uniform4uiv( this.addr, v );
18621
18622		copyArray( cache, v );
18623
18624	}
18625
18626}
18627
18628
18629// Single texture (2D / Cube)
18630
18631function setValueT1( gl, v, textures ) {
18632
18633	const cache = this.cache;
18634	const unit = textures.allocateTextureUnit();
18635
18636	if ( cache[ 0 ] !== unit ) {
18637
18638		gl.uniform1i( this.addr, unit );
18639		cache[ 0 ] = unit;
18640
18641	}
18642
18643	const emptyTexture2D = ( this.type === gl.SAMPLER_2D_SHADOW ) ? emptyShadowTexture : emptyTexture;
18644
18645	textures.setTexture2D( v || emptyTexture2D, unit );
18646
18647}
18648
18649function setValueT3D1( gl, v, textures ) {
18650
18651	const cache = this.cache;
18652	const unit = textures.allocateTextureUnit();
18653
18654	if ( cache[ 0 ] !== unit ) {
18655
18656		gl.uniform1i( this.addr, unit );
18657		cache[ 0 ] = unit;
18658
18659	}
18660
18661	textures.setTexture3D( v || empty3dTexture, unit );
18662
18663}
18664
18665function setValueT6( gl, v, textures ) {
18666
18667	const cache = this.cache;
18668	const unit = textures.allocateTextureUnit();
18669
18670	if ( cache[ 0 ] !== unit ) {
18671
18672		gl.uniform1i( this.addr, unit );
18673		cache[ 0 ] = unit;
18674
18675	}
18676
18677	textures.setTextureCube( v || emptyCubeTexture, unit );
18678
18679}
18680
18681function setValueT2DArray1( gl, v, textures ) {
18682
18683	const cache = this.cache;
18684	const unit = textures.allocateTextureUnit();
18685
18686	if ( cache[ 0 ] !== unit ) {
18687
18688		gl.uniform1i( this.addr, unit );
18689		cache[ 0 ] = unit;
18690
18691	}
18692
18693	textures.setTexture2DArray( v || emptyArrayTexture, unit );
18694
18695}
18696
18697// Helper to pick the right setter for the singular case
18698
18699function getSingularSetter( type ) {
18700
18701	switch ( type ) {
18702
18703		case 0x1406: return setValueV1f; // FLOAT
18704		case 0x8b50: return setValueV2f; // _VEC2
18705		case 0x8b51: return setValueV3f; // _VEC3
18706		case 0x8b52: return setValueV4f; // _VEC4
18707
18708		case 0x8b5a: return setValueM2; // _MAT2
18709		case 0x8b5b: return setValueM3; // _MAT3
18710		case 0x8b5c: return setValueM4; // _MAT4
18711
18712		case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
18713		case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
18714		case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
18715		case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
18716
18717		case 0x1405: return setValueV1ui; // UINT
18718		case 0x8dc6: return setValueV2ui; // _VEC2
18719		case 0x8dc7: return setValueV3ui; // _VEC3
18720		case 0x8dc8: return setValueV4ui; // _VEC4
18721
18722		case 0x8b5e: // SAMPLER_2D
18723		case 0x8d66: // SAMPLER_EXTERNAL_OES
18724		case 0x8dca: // INT_SAMPLER_2D
18725		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
18726		case 0x8b62: // SAMPLER_2D_SHADOW
18727			return setValueT1;
18728
18729		case 0x8b5f: // SAMPLER_3D
18730		case 0x8dcb: // INT_SAMPLER_3D
18731		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
18732			return setValueT3D1;
18733
18734		case 0x8b60: // SAMPLER_CUBE
18735		case 0x8dcc: // INT_SAMPLER_CUBE
18736		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
18737		case 0x8dc5: // SAMPLER_CUBE_SHADOW
18738			return setValueT6;
18739
18740		case 0x8dc1: // SAMPLER_2D_ARRAY
18741		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
18742		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
18743		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
18744			return setValueT2DArray1;
18745
18746	}
18747
18748}
18749
18750
18751// Array of scalars
18752
18753function setValueV1fArray( gl, v ) {
18754
18755	gl.uniform1fv( this.addr, v );
18756
18757}
18758
18759// Array of vectors (from flat array or array of THREE.VectorN)
18760
18761function setValueV2fArray( gl, v ) {
18762
18763	const data = flatten( v, this.size, 2 );
18764
18765	gl.uniform2fv( this.addr, data );
18766
18767}
18768
18769function setValueV3fArray( gl, v ) {
18770
18771	const data = flatten( v, this.size, 3 );
18772
18773	gl.uniform3fv( this.addr, data );
18774
18775}
18776
18777function setValueV4fArray( gl, v ) {
18778
18779	const data = flatten( v, this.size, 4 );
18780
18781	gl.uniform4fv( this.addr, data );
18782
18783}
18784
18785// Array of matrices (from flat array or array of THREE.MatrixN)
18786
18787function setValueM2Array( gl, v ) {
18788
18789	const data = flatten( v, this.size, 4 );
18790
18791	gl.uniformMatrix2fv( this.addr, false, data );
18792
18793}
18794
18795function setValueM3Array( gl, v ) {
18796
18797	const data = flatten( v, this.size, 9 );
18798
18799	gl.uniformMatrix3fv( this.addr, false, data );
18800
18801}
18802
18803function setValueM4Array( gl, v ) {
18804
18805	const data = flatten( v, this.size, 16 );
18806
18807	gl.uniformMatrix4fv( this.addr, false, data );
18808
18809}
18810
18811// Array of integer / boolean
18812
18813function setValueV1iArray( gl, v ) {
18814
18815	gl.uniform1iv( this.addr, v );
18816
18817}
18818
18819// Array of integer / boolean vectors (from flat array)
18820
18821function setValueV2iArray( gl, v ) {
18822
18823	gl.uniform2iv( this.addr, v );
18824
18825}
18826
18827function setValueV3iArray( gl, v ) {
18828
18829	gl.uniform3iv( this.addr, v );
18830
18831}
18832
18833function setValueV4iArray( gl, v ) {
18834
18835	gl.uniform4iv( this.addr, v );
18836
18837}
18838
18839// Array of unsigned integer
18840
18841function setValueV1uiArray( gl, v ) {
18842
18843	gl.uniform1uiv( this.addr, v );
18844
18845}
18846
18847// Array of unsigned integer vectors (from flat array)
18848
18849function setValueV2uiArray( gl, v ) {
18850
18851	gl.uniform2uiv( this.addr, v );
18852
18853}
18854
18855function setValueV3uiArray( gl, v ) {
18856
18857	gl.uniform3uiv( this.addr, v );
18858
18859}
18860
18861function setValueV4uiArray( gl, v ) {
18862
18863	gl.uniform4uiv( this.addr, v );
18864
18865}
18866
18867
18868// Array of textures (2D / 3D / Cube / 2DArray)
18869
18870function setValueT1Array( gl, v, textures ) {
18871
18872	const cache = this.cache;
18873
18874	const n = v.length;
18875
18876	const units = allocTexUnits( textures, n );
18877
18878	if ( ! arraysEqual( cache, units ) ) {
18879
18880		gl.uniform1iv( this.addr, units );
18881
18882		copyArray( cache, units );
18883
18884	}
18885
18886	for ( let i = 0; i !== n; ++ i ) {
18887
18888		textures.setTexture2D( v[ i ] || emptyTexture, units[ i ] );
18889
18890	}
18891
18892}
18893
18894function setValueT3DArray( gl, v, textures ) {
18895
18896	const cache = this.cache;
18897
18898	const n = v.length;
18899
18900	const units = allocTexUnits( textures, n );
18901
18902	if ( ! arraysEqual( cache, units ) ) {
18903
18904		gl.uniform1iv( this.addr, units );
18905
18906		copyArray( cache, units );
18907
18908	}
18909
18910	for ( let i = 0; i !== n; ++ i ) {
18911
18912		textures.setTexture3D( v[ i ] || empty3dTexture, units[ i ] );
18913
18914	}
18915
18916}
18917
18918function setValueT6Array( gl, v, textures ) {
18919
18920	const cache = this.cache;
18921
18922	const n = v.length;
18923
18924	const units = allocTexUnits( textures, n );
18925
18926	if ( ! arraysEqual( cache, units ) ) {
18927
18928		gl.uniform1iv( this.addr, units );
18929
18930		copyArray( cache, units );
18931
18932	}
18933
18934	for ( let i = 0; i !== n; ++ i ) {
18935
18936		textures.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );
18937
18938	}
18939
18940}
18941
18942function setValueT2DArrayArray( gl, v, textures ) {
18943
18944	const cache = this.cache;
18945
18946	const n = v.length;
18947
18948	const units = allocTexUnits( textures, n );
18949
18950	if ( ! arraysEqual( cache, units ) ) {
18951
18952		gl.uniform1iv( this.addr, units );
18953
18954		copyArray( cache, units );
18955
18956	}
18957
18958	for ( let i = 0; i !== n; ++ i ) {
18959
18960		textures.setTexture2DArray( v[ i ] || emptyArrayTexture, units[ i ] );
18961
18962	}
18963
18964}
18965
18966
18967// Helper to pick the right setter for a pure (bottom-level) array
18968
18969function getPureArraySetter( type ) {
18970
18971	switch ( type ) {
18972
18973		case 0x1406: return setValueV1fArray; // FLOAT
18974		case 0x8b50: return setValueV2fArray; // _VEC2
18975		case 0x8b51: return setValueV3fArray; // _VEC3
18976		case 0x8b52: return setValueV4fArray; // _VEC4
18977
18978		case 0x8b5a: return setValueM2Array; // _MAT2
18979		case 0x8b5b: return setValueM3Array; // _MAT3
18980		case 0x8b5c: return setValueM4Array; // _MAT4
18981
18982		case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
18983		case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
18984		case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
18985		case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
18986
18987		case 0x1405: return setValueV1uiArray; // UINT
18988		case 0x8dc6: return setValueV2uiArray; // _VEC2
18989		case 0x8dc7: return setValueV3uiArray; // _VEC3
18990		case 0x8dc8: return setValueV4uiArray; // _VEC4
18991
18992		case 0x8b5e: // SAMPLER_2D
18993		case 0x8d66: // SAMPLER_EXTERNAL_OES
18994		case 0x8dca: // INT_SAMPLER_2D
18995		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
18996		case 0x8b62: // SAMPLER_2D_SHADOW
18997			return setValueT1Array;
18998
18999		case 0x8b5f: // SAMPLER_3D
19000		case 0x8dcb: // INT_SAMPLER_3D
19001		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
19002			return setValueT3DArray;
19003
19004		case 0x8b60: // SAMPLER_CUBE
19005		case 0x8dcc: // INT_SAMPLER_CUBE
19006		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
19007		case 0x8dc5: // SAMPLER_CUBE_SHADOW
19008			return setValueT6Array;
19009
19010		case 0x8dc1: // SAMPLER_2D_ARRAY
19011		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
19012		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
19013		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
19014			return setValueT2DArrayArray;
19015
19016	}
19017
19018}
19019
19020// --- Uniform Classes ---
19021
19022class SingleUniform {
19023
19024	constructor( id, activeInfo, addr ) {
19025
19026		this.id = id;
19027		this.addr = addr;
19028		this.cache = [];
19029		this.type = activeInfo.type;
19030		this.setValue = getSingularSetter( activeInfo.type );
19031
19032		// this.path = activeInfo.name; // DEBUG
19033
19034	}
19035
19036}
19037
19038class PureArrayUniform {
19039
19040	constructor( id, activeInfo, addr ) {
19041
19042		this.id = id;
19043		this.addr = addr;
19044		this.cache = [];
19045		this.type = activeInfo.type;
19046		this.size = activeInfo.size;
19047		this.setValue = getPureArraySetter( activeInfo.type );
19048
19049		// this.path = activeInfo.name; // DEBUG
19050
19051	}
19052
19053}
19054
19055class StructuredUniform {
19056
19057	constructor( id ) {
19058
19059		this.id = id;
19060
19061		this.seq = [];
19062		this.map = {};
19063
19064	}
19065
19066	setValue( gl, value, textures ) {
19067
19068		const seq = this.seq;
19069
19070		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
19071
19072			const u = seq[ i ];
19073			u.setValue( gl, value[ u.id ], textures );
19074
19075		}
19076
19077	}
19078
19079}
19080
19081// --- Top-level ---
19082
19083// Parser - builds up the property tree from the path strings
19084
19085const RePathPart = /(\w+)(\])?(\[|\.)?/g;
19086
19087// extracts
19088// 	- the identifier (member name or array index)
19089//  - followed by an optional right bracket (found when array index)
19090//  - followed by an optional left bracket or dot (type of subscript)
19091//
19092// Note: These portions can be read in a non-overlapping fashion and
19093// allow straightforward parsing of the hierarchy that WebGL encodes
19094// in the uniform names.
19095
19096function addUniform( container, uniformObject ) {
19097
19098	container.seq.push( uniformObject );
19099	container.map[ uniformObject.id ] = uniformObject;
19100
19101}
19102
19103function parseUniform( activeInfo, addr, container ) {
19104
19105	const path = activeInfo.name,
19106		pathLength = path.length;
19107
19108	// reset RegExp object, because of the early exit of a previous run
19109	RePathPart.lastIndex = 0;
19110
19111	while ( true ) {
19112
19113		const match = RePathPart.exec( path ),
19114			matchEnd = RePathPart.lastIndex;
19115
19116		let id = match[ 1 ];
19117		const idIsIndex = match[ 2 ] === ']',
19118			subscript = match[ 3 ];
19119
19120		if ( idIsIndex ) id = id | 0; // convert to integer
19121
19122		if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {
19123
19124			// bare name or "pure" bottom-level array "[0]" suffix
19125
19126			addUniform( container, subscript === undefined ?
19127				new SingleUniform( id, activeInfo, addr ) :
19128				new PureArrayUniform( id, activeInfo, addr ) );
19129
19130			break;
19131
19132		} else {
19133
19134			// step into inner node / create it in case it doesn't exist
19135
19136			const map = container.map;
19137			let next = map[ id ];
19138
19139			if ( next === undefined ) {
19140
19141				next = new StructuredUniform( id );
19142				addUniform( container, next );
19143
19144			}
19145
19146			container = next;
19147
19148		}
19149
19150	}
19151
19152}
19153
19154// Root Container
19155
19156class WebGLUniforms {
19157
19158	constructor( gl, program ) {
19159
19160		this.seq = [];
19161		this.map = {};
19162
19163		const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
19164
19165		for ( let i = 0; i < n; ++ i ) {
19166
19167			const info = gl.getActiveUniform( program, i ),
19168				addr = gl.getUniformLocation( program, info.name );
19169
19170			parseUniform( info, addr, this );
19171
19172		}
19173
19174	}
19175
19176	setValue( gl, name, value, textures ) {
19177
19178		const u = this.map[ name ];
19179
19180		if ( u !== undefined ) u.setValue( gl, value, textures );
19181
19182	}
19183
19184	setOptional( gl, object, name ) {
19185
19186		const v = object[ name ];
19187
19188		if ( v !== undefined ) this.setValue( gl, name, v );
19189
19190	}
19191
19192	static upload( gl, seq, values, textures ) {
19193
19194		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
19195
19196			const u = seq[ i ],
19197				v = values[ u.id ];
19198
19199			if ( v.needsUpdate !== false ) {
19200
19201				// note: always updating when .needsUpdate is undefined
19202				u.setValue( gl, v.value, textures );
19203
19204			}
19205
19206		}
19207
19208	}
19209
19210	static seqWithValue( seq, values ) {
19211
19212		const r = [];
19213
19214		for ( let i = 0, n = seq.length; i !== n; ++ i ) {
19215
19216			const u = seq[ i ];
19217			if ( u.id in values ) r.push( u );
19218
19219		}
19220
19221		return r;
19222
19223	}
19224
19225}
19226
19227function WebGLShader( gl, type, string ) {
19228
19229	const shader = gl.createShader( type );
19230
19231	gl.shaderSource( shader, string );
19232	gl.compileShader( shader );
19233
19234	return shader;
19235
19236}
19237
19238// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/
19239const COMPLETION_STATUS_KHR = 0x91B1;
19240
19241let programIdCount = 0;
19242
19243function handleSource( string, errorLine ) {
19244
19245	const lines = string.split( '\n' );
19246	const lines2 = [];
19247
19248	const from = Math.max( errorLine - 6, 0 );
19249	const to = Math.min( errorLine + 6, lines.length );
19250
19251	for ( let i = from; i < to; i ++ ) {
19252
19253		const line = i + 1;
19254		lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` );
19255
19256	}
19257
19258	return lines2.join( '\n' );
19259
19260}
19261
19262function getEncodingComponents( colorSpace ) {
19263
19264	const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
19265	const encodingPrimaries = ColorManagement.getPrimaries( colorSpace );
19266
19267	let gamutMapping;
19268
19269	if ( workingPrimaries === encodingPrimaries ) {
19270
19271		gamutMapping = '';
19272
19273	} else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) {
19274
19275		gamutMapping = 'LinearDisplayP3ToLinearSRGB';
19276
19277	} else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) {
19278
19279		gamutMapping = 'LinearSRGBToLinearDisplayP3';
19280
19281	}
19282
19283	switch ( colorSpace ) {
19284
19285		case LinearSRGBColorSpace:
19286		case LinearDisplayP3ColorSpace:
19287			return [ gamutMapping, 'LinearTransferOETF' ];
19288
19289		case SRGBColorSpace:
19290		case DisplayP3ColorSpace:
19291			return [ gamutMapping, 'sRGBTransferOETF' ];
19292
19293		default:
19294			console.warn( 'THREE.WebGLProgram: Unsupported color space:', colorSpace );
19295			return [ gamutMapping, 'LinearTransferOETF' ];
19296
19297	}
19298
19299}
19300
19301function getShaderErrors( gl, shader, type ) {
19302
19303	const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS );
19304	const errors = gl.getShaderInfoLog( shader ).trim();
19305
19306	if ( status && errors === '' ) return '';
19307
19308	const errorMatches = /ERROR: 0:(\d+)/.exec( errors );
19309	if ( errorMatches ) {
19310
19311		// --enable-privileged-webgl-extension
19312		// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
19313
19314		const errorLine = parseInt( errorMatches[ 1 ] );
19315		return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine );
19316
19317	} else {
19318
19319		return errors;
19320
19321	}
19322
19323}
19324
19325function getTexelEncodingFunction( functionName, colorSpace ) {
19326
19327	const components = getEncodingComponents( colorSpace );
19328	return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}( ${components[ 1 ]}( value ) ); }`;
19329
19330}
19331
19332function getToneMappingFunction( functionName, toneMapping ) {
19333
19334	let toneMappingName;
19335
19336	switch ( toneMapping ) {
19337
19338		case LinearToneMapping:
19339			toneMappingName = 'Linear';
19340			break;
19341
19342		case ReinhardToneMapping:
19343			toneMappingName = 'Reinhard';
19344			break;
19345
19346		case CineonToneMapping:
19347			toneMappingName = 'OptimizedCineon';
19348			break;
19349
19350		case ACESFilmicToneMapping:
19351			toneMappingName = 'ACESFilmic';
19352			break;
19353
19354		case AgXToneMapping:
19355			toneMappingName = 'AgX';
19356			break;
19357
19358		case NeutralToneMapping:
19359			toneMappingName = 'Neutral';
19360			break;
19361
19362		case CustomToneMapping:
19363			toneMappingName = 'Custom';
19364			break;
19365
19366		default:
19367			console.warn( 'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
19368			toneMappingName = 'Linear';
19369
19370	}
19371
19372	return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
19373
19374}
19375
19376function generate
19376VertexExtensions( parameters ) {
19377
19378	const chunks = [
vendor: 7,072 bytes, lines 19379-19686
19379		parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : '',
19380		parameters.extensionMultiDraw ? '#extension GL_ANGLE_multi_draw : require' : '',
19381	];
19382
19383	return chunks.filter( filterEmptyLine ).join( '\n' );
19384
19385}
19386
19387function generateDefines( defines ) {
19388
19389	const chunks = [];
19390
19391	for ( const name in defines ) {
19392
19393		const value = defines[ name ];
19394
19395		if ( value === false ) continue;
19396
19397		chunks.push( '#define ' + name + ' ' + value );
19398
19399	}
19400
19401	return chunks.join( '\n' );
19402
19403}
19404
19405function fetchAttributeLocations( gl, program ) {
19406
19407	const attributes = {};
19408
19409	const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
19410
19411	for ( let i = 0; i < n; i ++ ) {
19412
19413		const info = gl.getActiveAttrib( program, i );
19414		const name = info.name;
19415
19416		let locationSize = 1;
19417		if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2;
19418		if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3;
19419		if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4;
19420
19421		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
19422
19423		attributes[ name ] = {
19424			type: info.type,
19425			location: gl.getAttribLocation( program, name ),
19426			locationSize: locationSize
19427		};
19428
19429	}
19430
19431	return attributes;
19432
19433}
19434
19435function filterEmptyLine( string ) {
19436
19437	return string !== '';
19438
19439}
19440
19441function replaceLightNums( string, parameters ) {
19442
19443	const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps;
19444
19445	return string
19446		.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
19447		.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )
19448		.replace( /NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps )
19449		.replace( /NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords )
19450		.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )
19451		.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )
19452		.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )
19453		.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )
19454		.replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps )
19455		.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )
19456		.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );
19457
19458}
19459
19460function replaceClippingPlaneNums( string, parameters ) {
19461
19462	return string
19463		.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )
19464		.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
19465
19466}
19467
19468// Resolve Includes
19469
19470const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
19471
19472function resolveIncludes( string ) {
19473
19474	return string.replace( includePattern, includeReplacer );
19475
19476}
19477
19478const shaderChunkMap = new Map();
19479
19480function includeReplacer( match, include ) {
19481
19482	let string = ShaderChunk[ include ];
19483
19484	if ( string === undefined ) {
19485
19486		const newInclude = shaderChunkMap.get( include );
19487
19488		if ( newInclude !== undefined ) {
19489
19490			string = ShaderChunk[ newInclude ];
19491			console.warn( 'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude );
19492
19493		} else {
19494
19495			throw new Error( 'Can not resolve #include <' + include + '>' );
19496
19497		}
19498
19499	}
19500
19501	return resolveIncludes( string );
19502
19503}
19504
19505// Unroll Loops
19506
19507const 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;
19508
19509function unrollLoops( string ) {
19510
19511	return string.replace( unrollLoopPattern, loopReplacer );
19512
19513}
19514
19515function loopReplacer( match, start, end, snippet ) {
19516
19517	let string = '';
19518
19519	for ( let i = parseInt( start ); i < parseInt( end ); i ++ ) {
19520
19521		string += snippet
19522			.replace( /\[\s*i\s*\]/g, '[ ' + i + ' ]' )
19523			.replace( /UNROLLED_LOOP_INDEX/g, i );
19524
19525	}
19526
19527	return string;
19528
19529}
19530
19531//
19532
19533function generatePrecision( parameters ) {
19534
19535	let precisionstring = `precision ${parameters.precision} float;
19536	precision ${parameters.precision} int;
19537	precision ${parameters.precision} sampler2D;
19538	precision ${parameters.precision} samplerCube;
19539	precision ${parameters.precision} sampler3D;
19540	precision ${parameters.precision} sampler2DArray;
19541	precision ${parameters.precision} sampler2DShadow;
19542	precision ${parameters.precision} samplerCubeShadow;
19543	precision ${parameters.precision} sampler2DArrayShadow;
19544	precision ${parameters.precision} isampler2D;
19545	precision ${parameters.precision} isampler3D;
19546	precision ${parameters.precision} isamplerCube;
19547	precision ${parameters.precision} isampler2DArray;
19548	precision ${parameters.precision} usampler2D;
19549	precision ${parameters.precision} usampler3D;
19550	precision ${parameters.precision} usamplerCube;
19551	precision ${parameters.precision} usampler2DArray;
19552	`;
19553
19554	if ( parameters.precision === 'highp' ) {
19555
19556		precisionstring += '\n#define HIGH_PRECISION';
19557
19558	} else if ( parameters.precision === 'mediump' ) {
19559
19560		precisionstring += '\n#define MEDIUM_PRECISION';
19561
19562	} else if ( parameters.precision === 'lowp' ) {
19563
19564		precisionstring += '\n#define LOW_PRECISION';
19565
19566	}
19567
19568	return precisionstring;
19569
19570}
19571
19572function generateShadowMapTypeDefine( parameters ) {
19573
19574	let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
19575
19576	if ( parameters.shadowMapType === PCFShadowMap ) {
19577
19578		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
19579
19580	} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {
19581
19582		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
19583
19584	} else if ( parameters.shadowMapType === VSMShadowMap ) {
19585
19586		shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
19587
19588	}
19589
19590	return shadowMapTypeDefine;
19591
19592}
19593
19594function generateEnvMapTypeDefine( parameters ) {
19595
19596	let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
19597
19598	if ( parameters.envMap ) {
19599
19600		switch ( parameters.envMapMode ) {
19601
19602			case CubeReflectionMapping:
19603			case CubeRefractionMapping:
19604				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
19605				break;
19606
19607			case CubeUVReflectionMapping:
19608				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
19609				break;
19610
19611		}
19612
19613	}
19614
19615	return envMapTypeDefine;
19616
19617}
19618
19619function generateEnvMapModeDefine( parameters ) {
19620
19621	let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
19622
19623	if ( parameters.envMap ) {
19624
19625		switch ( parameters.envMapMode ) {
19626
19627			case CubeRefractionMapping:
19628
19629				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
19630				break;
19631
19632		}
19633
19634	}
19635
19636	return envMapModeDefine;
19637
19638}
19639
19640function generateEnvMapBlendingDefine( parameters ) {
19641
19642	let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
19643
19644	if ( parameters.envMap ) {
19645
19646		switch ( parameters.combine ) {
19647
19648			case MultiplyOperation:
19649				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
19650				break;
19651
19652			case MixOperation:
19653				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
19654				break;
19655
19656			case AddOperation:
19657				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
19658				break;
19659
19660		}
19661
19662	}
19663
19664	return envMapBlendingDefine;
19665
19666}
19667
19668function generateCubeUVSize( parameters ) {
19669
19670	const imageHeight = parameters.envMapCubeUVHeight;
19671
19672	if ( imageHeight === null ) return null;
19673
19674	const maxMip = Math.log2( imageHeight ) - 2;
19675
19676	const texelHeight = 1.0 / imageHeight;
19677
19678	const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) );
19679
19680	return { texelWidth, texelHeight, maxMip };
19681
19682}
19683
19684function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
19685
19686	// TODO Send this event to Three.js DevTools
vendor: 14,731 bytes, lines 19687-20078
19687	// console.log( 'WebGLProgram', cacheKey );
19688
19689	const gl = renderer.getContext();
19690
19691	const defines = parameters.defines;
19692
19693	let vertexShader = parameters.vertexShader;
19694	let fragmentShader = parameters.fragmentShader;
19695
19696	const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
19697	const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
19698	const envMapModeDefine = generateEnvMapModeDefine( parameters );
19699	const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
19700	const envMapCubeUVSize = generateCubeUVSize( parameters );
19701
19702	const customVertexExtensions = generateVertexExtensions( parameters );
19703
19704	const customDefines = generateDefines( defines );
19705
19706	const program = gl.createProgram();
19707
19708	let prefixVertex, prefixFragment;
19709	let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
19710
19711	if ( parameters.isRawShaderMaterial ) {
19712
19713		prefixVertex = [
19714
19715			'#define SHADER_TYPE ' + parameters.shaderType,
19716			'#define SHADER_NAME ' + parameters.shaderName,
19717
19718			customDefines
19719
19720		].filter( filterEmptyLine ).join( '\n' );
19721
19722		if ( prefixVertex.length > 0 ) {
19723
19724			prefixVertex += '\n';
19725
19726		}
19727
19728		prefixFragment = [
19729
19730			'#define SHADER_TYPE ' + parameters.shaderType,
19731			'#define SHADER_NAME ' + parameters.shaderName,
19732
19733			customDefines
19734
19735		].filter( filterEmptyLine ).join( '\n' );
19736
19737		if ( prefixFragment.length > 0 ) {
19738
19739			prefixFragment += '\n';
19740
19741		}
19742
19743	} else {
19744
19745		prefixVertex = [
19746
19747			generatePrecision( parameters ),
19748
19749			'#define SHADER_TYPE ' + parameters.shaderType,
19750			'#define SHADER_NAME ' + parameters.shaderName,
19751
19752			customDefines,
19753
19754			parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '',
19755			parameters.batching ? '#define USE_BATCHING' : '',
19756			parameters.batchingColor ? '#define USE_BATCHING_COLOR' : '',
19757			parameters.instancing ? '#define USE_INSTANCING' : '',
19758			parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
19759			parameters.instancingMorph ? '#define USE_INSTANCING_MORPH' : '',
19760
19761			parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
19762			parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
19763
19764			parameters.map ? '#define USE_MAP' : '',
19765			parameters.envMap ? '#define USE_ENVMAP' : '',
19766			parameters.envMap ? '#define ' + envMapModeDefine : '',
19767			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
19768			parameters.aoMap ? '#define USE_AOMAP' : '',
19769			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
19770			parameters.normalMap ? '#define USE_NORMALMAP' : '',
19771			parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '',
19772			parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '',
19773			parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '',
19774			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
19775
19776			parameters.anisotropy ? '#define USE_ANISOTROPY' : '',
19777			parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '',
19778
19779			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
19780			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
19781			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
19782
19783			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
19784			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
19785
19786			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
19787			parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '',
19788			parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '',
19789
19790			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
19791			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
19792			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
19793			parameters.alphaHash ? '#define USE_ALPHAHASH' : '',
19794
19795			parameters.transmission ? '#define USE_TRANSMISSION' : '',
19796			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
19797			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
19798
19799			parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '',
19800			parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '',
19801
19802			//
19803
19804			parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '',
19805			parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '',
19806			parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '',
19807			parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '',
19808			parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '',
19809			parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '',
19810			parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '',
19811			parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '',
19812
19813			parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '',
19814			parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '',
19815
19816			parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '',
19817
19818			parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '',
19819			parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '',
19820			parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '',
19821
19822			parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '',
19823			parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '',
19824
19825			parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '',
19826			parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '',
19827
19828			parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '',
19829			parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '',
19830			parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '',
19831
19832			parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '',
19833			parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '',
19834
19835			//
19836
19837			parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
19838			parameters.vertexColors ? '#define USE_COLOR' : '',
19839			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
19840			parameters.vertexUv1s ? '#define USE_UV1' : '',
19841			parameters.vertexUv2s ? '#define USE_UV2' : '',
19842			parameters.vertexUv3s ? '#define USE_UV3' : '',
19843
19844			parameters.pointsUvs ? '#define USE_POINTS_UV' : '',
19845
19846			parameters.flatShading ? '#define FLAT_SHADED' : '',
19847
19848			parameters.skinning ? '#define USE_SKINNING' : '',
19849
19850			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
19851			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
19852			( parameters.morphColors ) ? '#define USE_MORPHCOLORS' : '',
19853			( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '',
19854			( parameters.morphTargetsCount > 0 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '',
19855			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
19856			parameters.flipSided ? '#define FLIP_SIDED' : '',
19857
19858			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
19859			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
19860
19861			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
19862
19863			parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
19864
19865			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
19866
19867			'uniform mat4 modelMatrix;',
19868			'uniform mat4 modelViewMatrix;',
19869			'uniform mat4 projectionMatrix;',
19870			'uniform mat4 viewMatrix;',
19871			'uniform mat3 normalMatrix;',
19872			'uniform vec3 cameraPosition;',
19873			'uniform bool isOrthographic;',
19874
19875			'#ifdef USE_INSTANCING',
19876
19877			'	attribute mat4 instanceMatrix;',
19878
19879			'#endif',
19880
19881			'#ifdef USE_INSTANCING_COLOR',
19882
19883			'	attribute vec3 instanceColor;',
19884
19885			'#endif',
19886
19887			'#ifdef USE_INSTANCING_MORPH',
19888
19889			'	uniform sampler2D morphTexture;',
19890
19891			'#endif',
19892
19893			'attribute vec3 position;',
19894			'attribute vec3 normal;',
19895			'attribute vec2 uv;',
19896
19897			'#ifdef USE_UV1',
19898
19899			'	attribute vec2 uv1;',
19900
19901			'#endif',
19902
19903			'#ifdef USE_UV2',
19904
19905			'	attribute vec2 uv2;',
19906
19907			'#endif',
19908
19909			'#ifdef USE_UV3',
19910
19911			'	attribute vec2 uv3;',
19912
19913			'#endif',
19914
19915			'#ifdef USE_TANGENT',
19916
19917			'	attribute vec4 tangent;',
19918
19919			'#endif',
19920
19921			'#if defined( USE_COLOR_ALPHA )',
19922
19923			'	attribute vec4 color;',
19924
19925			'#elif defined( USE_COLOR )',
19926
19927			'	attribute vec3 color;',
19928
19929			'#endif',
19930
19931			'#ifdef USE_SKINNING',
19932
19933			'	attribute vec4 skinIndex;',
19934			'	attribute vec4 skinWeight;',
19935
19936			'#endif',
19937
19938			'\n'
19939
19940		].filter( filterEmptyLine ).join( '\n' );
19941
19942		prefixFragment = [
19943
19944			generatePrecision( parameters ),
19945
19946			'#define SHADER_TYPE ' + parameters.shaderType,
19947			'#define SHADER_NAME ' + parameters.shaderName,
19948
19949			customDefines,
19950
19951			parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
19952			parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
19953
19954			parameters.alphaToCoverage ? '#define ALPHA_TO_COVERAGE' : '',
19955			parameters.map ? '#define USE_MAP' : '',
19956			parameters.matcap ? '#define USE_MATCAP' : '',
19957			parameters.envMap ? '#define USE_ENVMAP' : '',
19958			parameters.envMap ? '#define ' + envMapTypeDefine : '',
19959			parameters.envMap ? '#define ' + envMapModeDefine : '',
19960			parameters.envMap ? '#define ' + envMapBlendingDefine : '',
19961			envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '',
19962			envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '',
19963			envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '',
19964			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
19965			parameters.aoMap ? '#define USE_AOMAP' : '',
19966			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
19967			parameters.normalMap ? '#define USE_NORMALMAP' : '',
19968			parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '',
19969			parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '',
19970			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
19971
19972			parameters.anisotropy ? '#define USE_ANISOTROPY' : '',
19973			parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '',
19974
19975			parameters.clearcoat ? '#define USE_CLEARCOAT' : '',
19976			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
19977			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
19978			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
19979
19980			parameters.dispersion ? '#define USE_DISPERSION' : '',
19981
19982			parameters.iridescence ? '#define USE_IRIDESCENCE' : '',
19983			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
19984			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
19985
19986			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
19987			parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '',
19988			parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '',
19989
19990			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
19991			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
19992
19993			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
19994			parameters.alphaTest ? '#define USE_ALPHATEST' : '',
19995			parameters.alphaHash ? '#define USE_ALPHAHASH' : '',
19996
19997			parameters.sheen ? '#define USE_SHEEN' : '',
19998			parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '',
19999			parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '',
20000
20001			parameters.transmission ? '#define USE_TRANSMISSION' : '',
20002			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
20003			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
20004
20005			parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
20006			parameters.vertexColors || parameters.instancingColor || parameters.batchingColor ? '#define USE_COLOR' : '',
20007			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
20008			parameters.vertexUv1s ? '#define USE_UV1' : '',
20009			parameters.vertexUv2s ? '#define USE_UV2' : '',
20010			parameters.vertexUv3s ? '#define USE_UV3' : '',
20011
20012			parameters.pointsUvs ? '#define USE_POINTS_UV' : '',
20013
20014			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
20015
20016			parameters.flatShading ? '#define FLAT_SHADED' : '',
20017
20018			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
20019			parameters.flipSided ? '#define FLIP_SIDED' : '',
20020
20021			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
20022			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
20023
20024			parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
20025
20026			parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
20027
20028			parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '',
20029
20030			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
20031
20032			'uniform mat4 viewMatrix;',
20033			'uniform vec3 cameraPosition;',
20034			'uniform bool isOrthographic;',
20035
20036			( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
20037			( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
20038			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
20039
20040			parameters.dithering ? '#define DITHERING' : '',
20041			parameters.opaque ? '#define OPAQUE' : '',
20042
20043			ShaderChunk[ 'colorspace_pars_fragment' ], // this code is required here because it is used by the various encoding/decoding function defined below
20044			getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputColorSpace ),
20045
20046			parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
20047
20048			'\n'
20049
20050		].filter( filterEmptyLine ).join( '\n' );
20051
20052	}
20053
20054	vertexShader = resolveIncludes( vertexShader );
20055	vertexShader = replaceLightNums( vertexShader, parameters );
20056	vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
20057
20058	fragmentShader = resolveIncludes( fragmentShader );
20059	fragmentShader = replaceLightNums( fragmentShader, parameters );
20060	fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
20061
20062	vertexShader = unrollLoops( vertexShader );
20063	fragmentShader = unrollLoops( fragmentShader );
20064
20065	if ( parameters.isRawShaderMaterial !== true ) {
20066
20067		// GLSL 3.0 conversion for built-in materials and ShaderMaterial
20068
20069		versionString = '#version 300 es\n';
20070
20071		prefixVertex = [
20072			customVertexExtensions,
20073			'#define attribute in',
20074			'#define varying out',
20075			'#define texture2D texture'
20076		].join( '\n' ) + '\n' + prefixVertex;
20077
20078		prefixFragment = [
vendor: 7,213 bytes, lines 20078-20421
20078
20079			'#define varying in',
20080			( parameters.glslVersion === GLSL3 ) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;',
20081			( parameters.glslVersion === GLSL3 ) ? '' : '#define gl_FragColor pc_fragColor',
20082			'#define gl_FragDepthEXT gl_FragDepth',
20083			'#define texture2D texture',
20084			'#define textureCube texture',
20085			'#define texture2DProj textureProj',
20086			'#define texture2DLodEXT textureLod',
20087			'#define texture2DProjLodEXT textureProjLod',
20088			'#define textureCubeLodEXT textureLod',
20089			'#define texture2DGradEXT textureGrad',
20090			'#define texture2DProjGradEXT textureProjGrad',
20091			'#define textureCubeGradEXT textureGrad'
20092		].join( '\n' ) + '\n' + prefixFragment;
20093
20094	}
20095
20096	const vertexGlsl = versionString + prefixVertex + vertexShader;
20097	const fragmentGlsl = versionString + prefixFragment + fragmentShader;
20098
20099	// console.log( '*VERTEX*', vertexGlsl );
20100	// console.log( '*FRAGMENT*', fragmentGlsl );
20101
20102	const glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
20103	const glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
20104
20105	gl.attachShader( program, glVertexShader );
20106	gl.attachShader( program, glFragmentShader );
20107
20108	// Force a particular attribute to index 0.
20109
20110	if ( parameters.index0AttributeName !== undefined ) {
20111
20112		gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
20113
20114	} else if ( parameters.morphTargets === true ) {
20115
20116		// programs with morphTargets displace position out of attribute 0
20117		gl.bindAttribLocation( program, 0, 'position' );
20118
20119	}
20120
20121	gl.linkProgram( program );
20122
20123	function onFirstUse( self ) {
20124
20125		// check for link errors
20126		if ( renderer.debug.checkShaderErrors ) {
20127
20128			const programLog = gl.getProgramInfoLog( program ).trim();
20129			const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
20130			const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
20131
20132			let runnable = true;
20133			let haveDiagnostics = true;
20134
20135			if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {
20136
20137				runnable = false;
20138
20139				if ( typeof renderer.debug.onShaderError === 'function' ) {
20140
20141					renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
20142
20143				} else {
20144
20145					// default error reporting
20146
20147					const vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );
20148					const fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );
20149
20150					console.error(
20151						'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
20152						'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) + '\n\n' +
20153						'Material Name: ' + self.name + '\n' +
20154						'Material Type: ' + self.type + '\n\n' +
20155						'Program Info Log: ' + programLog + '\n' +
20156						vertexErrors + '\n' +
20157						fragmentErrors
20158					);
20159
20160				}
20161
20162			} else if ( programLog !== '' ) {
20163
20164				console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog );
20165
20166			} else if ( vertexLog === '' || fragmentLog === '' ) {
20167
20168				haveDiagnostics = false;
20169
20170			}
20171
20172			if ( haveDiagnostics ) {
20173
20174				self.diagnostics = {
20175
20176					runnable: runnable,
20177
20178					programLog: programLog,
20179
20180					vertexShader: {
20181
20182						log: vertexLog,
20183						prefix: prefixVertex
20184
20185					},
20186
20187					fragmentShader: {
20188
20189						log: fragmentLog,
20190						prefix: prefixFragment
20191
20192					}
20193
20194				};
20195
20196			}
20197
20198		}
20199
20200		// Clean up
20201
20202		// Crashes in iOS9 and iOS10. #18402
20203		// gl.detachShader( program, glVertexShader );
20204		// gl.detachShader( program, glFragmentShader );
20205
20206		gl.deleteShader( glVertexShader );
20207		gl.deleteShader( glFragmentShader );
20208
20209		cachedUniforms = new WebGLUniforms( gl, program );
20210		cachedAttributes = fetchAttributeLocations( gl, program );
20211
20212	}
20213
20214	// set up caching for uniform locations
20215
20216	let cachedUniforms;
20217
20218	this.getUniforms = function () {
20219
20220		if ( cachedUniforms === undefined ) {
20221
20222			// Populates cachedUniforms and cachedAttributes
20223			onFirstUse( this );
20224
20225		}
20226
20227		return cachedUniforms;
20228
20229	};
20230
20231	// set up caching for attribute locations
20232
20233	let cachedAttributes;
20234
20235	this.getAttributes = function () {
20236
20237		if ( cachedAttributes === undefined ) {
20238
20239			// Populates cachedAttributes and cachedUniforms
20240			onFirstUse( this );
20241
20242		}
20243
20244		return cachedAttributes;
20245
20246	};
20247
20248	// indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported,
20249	// flag the program as ready immediately. It may cause a stall when it's first used.
20250
20251	let programReady = ( parameters.rendererExtensionParallelShaderCompile === false );
20252
20253	this.isReady = function () {
20254
20255		if ( programReady === false ) {
20256
20257			programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR );
20258
20259		}
20260
20261		return programReady;
20262
20263	};
20264
20265	// free resource
20266
20267	this.destroy = function () {
20268
20269		bindingStates.releaseStatesOfProgram( this );
20270
20271		gl.deleteProgram( program );
20272		this.program = undefined;
20273
20274	};
20275
20276	//
20277
20278	this.type = parameters.shaderType;
20279	this.name = parameters.shaderName;
20280	this.id = programIdCount ++;
20281	this.cacheKey = cacheKey;
20282	this.usedTimes = 1;
20283	this.program = program;
20284	this.vertexShader = glVertexShader;
20285	this.fragmentShader = glFragmentShader;
20286
20287	return this;
20288
20289}
20290
20291let _id$1 = 0;
20292
20293class WebGLShaderCache {
20294
20295	constructor() {
20296
20297		this.shaderCache = new Map();
20298		this.materialCache = new Map();
20299
20300	}
20301
20302	update( material ) {
20303
20304		const vertexShader = material.vertexShader;
20305		const fragmentShader = material.fragmentShader;
20306
20307		const vertexShaderStage = this._getShaderStage( vertexShader );
20308		const fragmentShaderStage = this._getShaderStage( fragmentShader );
20309
20310		const materialShaders = this._getShaderCacheForMaterial( material );
20311
20312		if ( materialShaders.has( vertexShaderStage ) === false ) {
20313
20314			materialShaders.add( vertexShaderStage );
20315			vertexShaderStage.usedTimes ++;
20316
20317		}
20318
20319		if ( materialShaders.has( fragmentShaderStage ) === false ) {
20320
20321			materialShaders.add( fragmentShaderStage );
20322			fragmentShaderStage.usedTimes ++;
20323
20324		}
20325
20326		return this;
20327
20328	}
20329
20330	remove( material ) {
20331
20332		const materialShaders = this.materialCache.get( material );
20333
20334		for ( const shaderStage of materialShaders ) {
20335
20336			shaderStage.usedTimes --;
20337
20338			if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code );
20339
20340		}
20341
20342		this.materialCache.delete( material );
20343
20344		return this;
20345
20346	}
20347
20348	getVertexShaderID( material ) {
20349
20350		return this._getShaderStage( material.vertexShader ).id;
20351
20352	}
20353
20354	getFragmentShaderID( material ) {
20355
20356		return this._getShaderStage( material.fragmentShader ).id;
20357
20358	}
20359
20360	dispose() {
20361
20362		this.shaderCache.clear();
20363		this.materialCache.clear();
20364
20365	}
20366
20367	_getShaderCacheForMaterial( material ) {
20368
20369		const cache = this.materialCache;
20370		let set = cache.get( material );
20371
20372		if ( set === undefined ) {
20373
20374			set = new Set();
20375			cache.set( material, set );
20376
20377		}
20378
20379		return set;
20380
20381	}
20382
20383	_getShaderStage( code ) {
20384
20385		const cache = this.shaderCache;
20386		let stage = cache.get( code );
20387
20388		if ( stage === undefined ) {
20389
20390			stage = new WebGLShaderStage( code );
20391			cache.set( code, stage );
20392
20393		}
20394
20395		return stage;
20396
20397	}
20398
20399}
20400
20401class WebGLShaderStage {
20402
20403	constructor( code ) {
20404
20405		this.id = _id$1 ++;
20406
20407		this.code = code;
20408		this.usedTimes = 0;
20409
20410	}
20411
20412}
20413
20414function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) {
20415
20416	const _programLayers = new Layers();
20417	const _customShaders = new WebGLShaderCache();
20418	const _activeChannels = new Set();
20419	const programs = [];
20420
20421	const 
vendor: 20,058 bytes, lines 20421-21056
20421logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
20422	const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures;
20423
20424	let precision = capabilities.precision;
20425
20426	const shaderIDs = {
20427		MeshDepthMaterial: 'depth',
20428		MeshDistanceMaterial: 'distanceRGBA',
20429		MeshNormalMaterial: 'normal',
20430		MeshBasicMaterial: 'basic',
20431		MeshLambertMaterial: 'lambert',
20432		MeshPhongMaterial: 'phong',
20433		MeshToonMaterial: 'toon',
20434		MeshStandardMaterial: 'physical',
20435		MeshPhysicalMaterial: 'physical',
20436		MeshMatcapMaterial: 'matcap',
20437		LineBasicMaterial: 'basic',
20438		LineDashedMaterial: 'dashed',
20439		PointsMaterial: 'points',
20440		ShadowMaterial: 'shadow',
20441		SpriteMaterial: 'sprite'
20442	};
20443
20444	function getChannel( value ) {
20445
20446		_activeChannels.add( value );
20447
20448		if ( value === 0 ) return 'uv';
20449
20450		return `uv${ value }`;
20451
20452	}
20453
20454	function getParameters( material, lights, shadows, scene, object ) {
20455
20456		const fog = scene.fog;
20457		const geometry = object.geometry;
20458		const environment = material.isMeshStandardMaterial ? scene.environment : null;
20459
20460		const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
20461		const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height : null;
20462
20463		const shaderID = shaderIDs[ material.type ];
20464
20465		// heuristics to create shader parameters according to lights in the scene
20466		// (not to blow over maxLights budget)
20467
20468		if ( material.precision !== null ) {
20469
20470			precision = capabilities.getMaxPrecision( material.precision );
20471
20472			if ( precision !== material.precision ) {
20473
20474				console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );
20475
20476			}
20477
20478		}
20479
20480		//
20481
20482		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
20483		const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
20484
20485		let morphTextureStride = 0;
20486
20487		if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1;
20488		if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2;
20489		if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3;
20490
20491		//
20492
20493		let vertexShader, fragmentShader;
20494		let customVertexShaderID, customFragmentShaderID;
20495
20496		if ( shaderID ) {
20497
20498			const shader = ShaderLib[ shaderID ];
20499
20500			vertexShader = shader.vertexShader;
20501			fragmentShader = shader.fragmentShader;
20502
20503		} else {
20504
20505			vertexShader = material.vertexShader;
20506			fragmentShader = material.fragmentShader;
20507
20508			_customShaders.update( material );
20509
20510			customVertexShaderID = _customShaders.getVertexShaderID( material );
20511			customFragmentShaderID = _customShaders.getFragmentShaderID( material );
20512
20513		}
20514
20515		const currentRenderTarget = renderer.getRenderTarget();
20516
20517		const IS_INSTANCEDMESH = object.isInstancedMesh === true;
20518		const IS_BATCHEDMESH = object.isBatchedMesh === true;
20519
20520		const HAS_MAP = !! material.map;
20521		const HAS_MATCAP = !! material.matcap;
20522		const HAS_ENVMAP = !! envMap;
20523		const HAS_AOMAP = !! material.aoMap;
20524		const HAS_LIGHTMAP = !! material.lightMap;
20525		const HAS_BUMPMAP = !! material.bumpMap;
20526		const HAS_NORMALMAP = !! material.normalMap;
20527		const HAS_DISPLACEMENTMAP = !! material.displacementMap;
20528		const HAS_EMISSIVEMAP = !! material.emissiveMap;
20529
20530		const HAS_METALNESSMAP = !! material.metalnessMap;
20531		const HAS_ROUGHNESSMAP = !! material.roughnessMap;
20532
20533		const HAS_ANISOTROPY = material.anisotropy > 0;
20534		const HAS_CLEARCOAT = material.clearcoat > 0;
20535		const HAS_DISPERSION = material.dispersion > 0;
20536		const HAS_IRIDESCENCE = material.iridescence > 0;
20537		const HAS_SHEEN = material.sheen > 0;
20538		const HAS_TRANSMISSION = material.transmission > 0;
20539
20540		const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap;
20541
20542		const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap;
20543		const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap;
20544		const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap;
20545
20546		const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap;
20547		const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap;
20548
20549		const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap;
20550		const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap;
20551
20552		const HAS_SPECULARMAP = !! material.specularMap;
20553		const HAS_SPECULAR_COLORMAP = !! material.specularColorMap;
20554		const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap;
20555
20556		const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap;
20557		const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap;
20558
20559		const HAS_GRADIENTMAP = !! material.gradientMap;
20560
20561		const HAS_ALPHAMAP = !! material.alphaMap;
20562
20563		const HAS_ALPHATEST = material.alphaTest > 0;
20564
20565		const HAS_ALPHAHASH = !! material.alphaHash;
20566
20567		const HAS_EXTENSIONS = !! material.extensions;
20568
20569		let toneMapping = NoToneMapping;
20570
20571		if ( material.toneMapped ) {
20572
20573			if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) {
20574
20575				toneMapping = renderer.toneMapping;
20576
20577			}
20578
20579		}
20580
20581		const parameters = {
20582
20583			shaderID: shaderID,
20584			shaderType: material.type,
20585			shaderName: material.name,
20586
20587			vertexShader: vertexShader,
20588			fragmentShader: fragmentShader,
20589			defines: material.defines,
20590
20591			customVertexShaderID: customVertexShaderID,
20592			customFragmentShaderID: customFragmentShaderID,
20593
20594			isRawShaderMaterial: material.isRawShaderMaterial === true,
20595			glslVersion: material.glslVersion,
20596
20597			precision: precision,
20598
20599			batching: IS_BATCHEDMESH,
20600			batchingColor: IS_BATCHEDMESH && object._colorsTexture !== null,
20601			instancing: IS_INSTANCEDMESH,
20602			instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null,
20603			instancingMorph: IS_INSTANCEDMESH && object.morphTexture !== null,
20604
20605			supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES,
20606			outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ),
20607			alphaToCoverage: !! material.alphaToCoverage,
20608
20609			map: HAS_MAP,
20610			matcap: HAS_MATCAP,
20611			envMap: HAS_ENVMAP,
20612			envMapMode: HAS_ENVMAP && envMap.mapping,
20613			envMapCubeUVHeight: envMapCubeUVHeight,
20614			aoMap: HAS_AOMAP,
20615			lightMap: HAS_LIGHTMAP,
20616			bumpMap: HAS_BUMPMAP,
20617			normalMap: HAS_NORMALMAP,
20618			displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP,
20619			emissiveMap: HAS_EMISSIVEMAP,
20620
20621			normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap,
20622			normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap,
20623
20624			metalnessMap: HAS_METALNESSMAP,
20625			roughnessMap: HAS_ROUGHNESSMAP,
20626
20627			anisotropy: HAS_ANISOTROPY,
20628			anisotropyMap: HAS_ANISOTROPYMAP,
20629
20630			clearcoat: HAS_CLEARCOAT,
20631			clearcoatMap: HAS_CLEARCOATMAP,
20632			clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP,
20633			clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP,
20634
20635			dispersion: HAS_DISPERSION,
20636
20637			iridescence: HAS_IRIDESCENCE,
20638			iridescenceMap: HAS_IRIDESCENCEMAP,
20639			iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP,
20640
20641			sheen: HAS_SHEEN,
20642			sheenColorMap: HAS_SHEEN_COLORMAP,
20643			sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP,
20644
20645			specularMap: HAS_SPECULARMAP,
20646			specularColorMap: HAS_SPECULAR_COLORMAP,
20647			specularIntensityMap: HAS_SPECULAR_INTENSITYMAP,
20648
20649			transmission: HAS_TRANSMISSION,
20650			transmissionMap: HAS_TRANSMISSIONMAP,
20651			thicknessMap: HAS_THICKNESSMAP,
20652
20653			gradientMap: HAS_GRADIENTMAP,
20654
20655			opaque: material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false,
20656
20657			alphaMap: HAS_ALPHAMAP,
20658			alphaTest: HAS_ALPHATEST,
20659			alphaHash: HAS_ALPHAHASH,
20660
20661			combine: material.combine,
20662
20663			//
20664
20665			mapUv: HAS_MAP && getChannel( material.map.channel ),
20666			aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ),
20667			lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ),
20668			bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ),
20669			normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ),
20670			displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ),
20671			emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ),
20672
20673			metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ),
20674			roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ),
20675
20676			anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ),
20677
20678			clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ),
20679			clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ),
20680			clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ),
20681
20682			iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ),
20683			iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ),
20684
20685			sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ),
20686			sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ),
20687
20688			specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ),
20689			specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ),
20690			specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ),
20691
20692			transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ),
20693			thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ),
20694
20695			alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ),
20696
20697			//
20698
20699			vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ),
20700			vertexColors: material.vertexColors,
20701			vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4,
20702
20703			pointsUvs: object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ),
20704
20705			fog: !! fog,
20706			useFog: material.fog === true,
20707			fogExp2: ( !! fog && fog.isFogExp2 ),
20708
20709			flatShading: material.flatShading === true,
20710
20711			sizeAttenuation: material.sizeAttenuation === true,
20712			logarithmicDepthBuffer: logarithmicDepthBuffer,
20713
20714			skinning: object.isSkinnedMesh === true,
20715
20716			morphTargets: geometry.morphAttributes.position !== undefined,
20717			morphNormals: geometry.morphAttributes.normal !== undefined,
20718			morphColors: geometry.morphAttributes.color !== undefined,
20719			morphTargetsCount: morphTargetsCount,
20720			morphTextureStride: morphTextureStride,
20721
20722			numDirLights: lights.directional.length,
20723			numPointLights: lights.point.length,
20724			numSpotLights: lights.spot.length,
20725			numSpotLightMaps: lights.spotLightMap.length,
20726			numRectAreaLights: lights.rectArea.length,
20727			numHemiLights: lights.hemi.length,
20728
20729			numDirLightShadows: lights.directionalShadowMap.length,
20730			numPointLightShadows: lights.pointShadowMap.length,
20731			numSpotLightShadows: lights.spotShadowMap.length,
20732			numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps,
20733
20734			numLightProbes: lights.numLightProbes,
20735
20736			numClippingPlanes: clipping.numPlanes,
20737			numClipIntersection: clipping.numIntersection,
20738
20739			dithering: material.dithering,
20740
20741			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
20742			shadowMapType: renderer.shadowMap.type,
20743
20744			toneMapping: toneMapping,
20745
20746			decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ),
20747
20748			premultipliedAlpha: material.premultipliedAlpha,
20749
20750			doubleSided: material.side === DoubleSide,
20751			flipSided: material.side === BackSide,
20752
20753			useDepthPacking: material.depthPacking >= 0,
20754			depthPacking: material.depthPacking || 0,
20755
20756			index0AttributeName: material.index0AttributeName,
20757
20758			extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance === true && extensions.has( 'WEBGL_clip_cull_distance' ),
20759			extensionMultiDraw: HAS_EXTENSIONS && material.extensions.multiDraw === true && extensions.has( 'WEBGL_multi_draw' ),
20760
20761			rendererExtensionParallelShaderCompile: extensions.has( 'KHR_parallel_shader_compile' ),
20762
20763			customProgramCacheKey: material.customProgramCacheKey()
20764
20765		};
20766
20767		// the usage of getChannel() determines the active texture channels for this shader
20768
20769		parameters.vertexUv1s = _activeChannels.has( 1 );
20770		parameters.vertexUv2s = _activeChannels.has( 2 );
20771		parameters.vertexUv3s = _activeChannels.has( 3 );
20772
20773		_activeChannels.clear();
20774
20775		return parameters;
20776
20777	}
20778
20779	function getProgramCacheKey( parameters ) {
20780
20781		const array = [];
20782
20783		if ( parameters.shaderID ) {
20784
20785			array.push( parameters.shaderID );
20786
20787		} else {
20788
20789			array.push( parameters.customVertexShaderID );
20790			array.push( parameters.customFragmentShaderID );
20791
20792		}
20793
20794		if ( parameters.defines !== undefined ) {
20795
20796			for ( const name in parameters.defines ) {
20797
20798				array.push( name );
20799				array.push( parameters.defines[ name ] );
20800
20801			}
20802
20803		}
20804
20805		if ( parameters.isRawShaderMaterial === false ) {
20806
20807			getProgramCacheKeyParameters( array, parameters );
20808			getProgramCacheKeyBooleans( array, parameters );
20809			array.push( renderer.outputColorSpace );
20810
20811		}
20812
20813		array.push( parameters.customProgramCacheKey );
20814
20815		return array.join();
20816
20817	}
20818
20819	function getProgramCacheKeyParameters( array, parameters ) {
20820
20821		array.push( parameters.precision );
20822		array.push( parameters.outputColorSpace );
20823		array.push( parameters.envMapMode );
20824		array.push( parameters.envMapCubeUVHeight );
20825		array.push( parameters.mapUv );
20826		array.push( parameters.alphaMapUv );
20827		array.push( parameters.lightMapUv );
20828		array.push( parameters.aoMapUv );
20829		array.push( parameters.bumpMapUv );
20830		array.push( parameters.normalMapUv );
20831		array.push( parameters.displacementMapUv );
20832		array.push( parameters.emissiveMapUv );
20833		array.push( parameters.metalnessMapUv );
20834		array.push( parameters.roughnessMapUv );
20835		array.push( parameters.anisotropyMapUv );
20836		array.push( parameters.clearcoatMapUv );
20837		array.push( parameters.clearcoatNormalMapUv );
20838		array.push( parameters.clearcoatRoughnessMapUv );
20839		array.push( parameters.iridescenceMapUv );
20840		array.push( parameters.iridescenceThicknessMapUv );
20841		array.push( parameters.sheenColorMapUv );
20842		array.push( parameters.sheenRoughnessMapUv );
20843		array.push( parameters.specularMapUv );
20844		array.push( parameters.specularColorMapUv );
20845		array.push( parameters.specularIntensityMapUv );
20846		array.push( parameters.transmissionMapUv );
20847		array.push( parameters.thicknessMapUv );
20848		array.push( parameters.combine );
20849		array.push( parameters.fogExp2 );
20850		array.push( parameters.sizeAttenuation );
20851		array.push( parameters.morphTargetsCount );
20852		array.push( parameters.morphAttributeCount );
20853		array.push( parameters.numDirLights );
20854		array.push( parameters.numPointLights );
20855		array.push( parameters.numSpotLights );
20856		array.push( parameters.numSpotLightMaps );
20857		array.push( parameters.numHemiLights );
20858		array.push( parameters.numRectAreaLights );
20859		array.push( parameters.numDirLightShadows );
20860		array.push( parameters.numPointLightShadows );
20861		array.push( parameters.numSpotLightShadows );
20862		array.push( parameters.numSpotLightShadowsWithMaps );
20863		array.push( parameters.numLightProbes );
20864		array.push( parameters.shadowMapType );
20865		array.push( parameters.toneMapping );
20866		array.push( parameters.numClippingPlanes );
20867		array.push( parameters.numClipIntersection );
20868		array.push( parameters.depthPacking );
20869
20870	}
20871
20872	function getProgramCacheKeyBooleans( array, parameters ) {
20873
20874		_programLayers.disableAll();
20875
20876		if ( parameters.supportsVertexTextures )
20877			_programLayers.enable( 0 );
20878		if ( parameters.instancing )
20879			_programLayers.enable( 1 );
20880		if ( parameters.instancingColor )
20881			_programLayers.enable( 2 );
20882		if ( parameters.instancingMorph )
20883			_programLayers.enable( 3 );
20884		if ( parameters.matcap )
20885			_programLayers.enable( 4 );
20886		if ( parameters.envMap )
20887			_programLayers.enable( 5 );
20888		if ( parameters.normalMapObjectSpace )
20889			_programLayers.enable( 6 );
20890		if ( parameters.normalMapTangentSpace )
20891			_programLayers.enable( 7 );
20892		if ( parameters.clearcoat )
20893			_programLayers.enable( 8 );
20894		if ( parameters.iridescence )
20895			_programLayers.enable( 9 );
20896		if ( parameters.alphaTest )
20897			_programLayers.enable( 10 );
20898		if ( parameters.vertexColors )
20899			_programLayers.enable( 11 );
20900		if ( parameters.vertexAlphas )
20901			_programLayers.enable( 12 );
20902		if ( parameters.vertexUv1s )
20903			_programLayers.enable( 13 );
20904		if ( parameters.vertexUv2s )
20905			_programLayers.enable( 14 );
20906		if ( parameters.vertexUv3s )
20907			_programLayers.enable( 15 );
20908		if ( parameters.vertexTangents )
20909			_programLayers.enable( 16 );
20910		if ( parameters.anisotropy )
20911			_programLayers.enable( 17 );
20912		if ( parameters.alphaHash )
20913			_programLayers.enable( 18 );
20914		if ( parameters.batching )
20915			_programLayers.enable( 19 );
20916		if ( parameters.dispersion )
20917			_programLayers.enable( 20 );
20918		if ( parameters.batchingColor )
20919			_programLayers.enable( 21 );
20920
20921		array.push( _programLayers.mask );
20922		_programLayers.disableAll();
20923
20924		if ( parameters.fog )
20925			_programLayers.enable( 0 );
20926		if ( parameters.useFog )
20927			_programLayers.enable( 1 );
20928		if ( parameters.flatShading )
20929			_programLayers.enable( 2 );
20930		if ( parameters.logarithmicDepthBuffer )
20931			_programLayers.enable( 3 );
20932		if ( parameters.skinning )
20933			_programLayers.enable( 4 );
20934		if ( parameters.morphTargets )
20935			_programLayers.enable( 5 );
20936		if ( parameters.morphNormals )
20937			_programLayers.enable( 6 );
20938		if ( parameters.morphColors )
20939			_programLayers.enable( 7 );
20940		if ( parameters.premultipliedAlpha )
20941			_programLayers.enable( 8 );
20942		if ( parameters.shadowMapEnabled )
20943			_programLayers.enable( 9 );
20944		if ( parameters.doubleSided )
20945			_programLayers.enable( 10 );
20946		if ( parameters.flipSided )
20947			_programLayers.enable( 11 );
20948		if ( parameters.useDepthPacking )
20949			_programLayers.enable( 12 );
20950		if ( parameters.dithering )
20951			_programLayers.enable( 13 );
20952		if ( parameters.transmission )
20953			_programLayers.enable( 14 );
20954		if ( parameters.sheen )
20955			_programLayers.enable( 15 );
20956		if ( parameters.opaque )
20957			_programLayers.enable( 16 );
20958		if ( parameters.pointsUvs )
20959			_programLayers.enable( 17 );
20960		if ( parameters.decodeVideoTexture )
20961			_programLayers.enable( 18 );
20962		if ( parameters.alphaToCoverage )
20963			_programLayers.enable( 19 );
20964
20965		array.push( _programLayers.mask );
20966
20967	}
20968
20969	function getUniforms( material ) {
20970
20971		const shaderID = shaderIDs[ material.type ];
20972		let uniforms;
20973
20974		if ( shaderID ) {
20975
20976			const shader = ShaderLib[ shaderID ];
20977			uniforms = UniformsUtils.clone( shader.uniforms );
20978
20979		} else {
20980
20981			uniforms = material.uniforms;
20982
20983		}
20984
20985		return uniforms;
20986
20987	}
20988
20989	function acquireProgram( parameters, cacheKey ) {
20990
20991		let program;
20992
20993		// Check if code has been already compiled
20994		for ( let p = 0, pl = programs.length; p < pl; p ++ ) {
20995
20996			const preexistingProgram = programs[ p ];
20997
20998			if ( preexistingProgram.cacheKey === cacheKey ) {
20999
21000				program = preexistingProgram;
21001				++ program.usedTimes;
21002
21003				break;
21004
21005			}
21006
21007		}
21008
21009		if ( program === undefined ) {
21010
21011			program = new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
21012			programs.push( program );
21013
21014		}
21015
21016		return program;
21017
21018	}
21019
21020	function releaseProgram( program ) {
21021
21022		if ( -- program.usedTimes === 0 ) {
21023
21024			// Remove from unordered set
21025			const i = programs.indexOf( program );
21026			programs[ i ] = programs[ programs.length - 1 ];
21027			programs.pop();
21028
21029			// Free WebGL resources
21030			program.destroy();
21031
21032		}
21033
21034	}
21035
21036	function releaseShaderCache( material ) {
21037
21038		_customShaders.remove( material );
21039
21040	}
21041
21042	function dispose() {
21043
21044		_customShaders.dispose();
21045
21046	}
21047
21048	return {
21049		getParameters: getParameters,
21050		getProgramCacheKey: getProgramCacheKey,
21051		getUniforms: getUniforms,
21052		acquireProgram: acquireProgram,
21053		releaseProgram: releaseProgram,
21054		releaseShaderCache: releaseShaderCache,
21055		// Exposed for resource monitoring & error feedback via renderer.info:
21056		programs: programs,
vendor: 4,538 bytes, lines 21057-21338
21057		dispose: dispose
21058	};
21059
21060}
21061
21062function WebGLProperties() {
21063
21064	let properties = new WeakMap();
21065
21066	function get( object ) {
21067
21068		let map = properties.get( object );
21069
21070		if ( map === undefined ) {
21071
21072			map = {};
21073			properties.set( object, map );
21074
21075		}
21076
21077		return map;
21078
21079	}
21080
21081	function remove( object ) {
21082
21083		properties.delete( object );
21084
21085	}
21086
21087	function update( object, key, value ) {
21088
21089		properties.get( object )[ key ] = value;
21090
21091	}
21092
21093	function dispose() {
21094
21095		properties = new WeakMap();
21096
21097	}
21098
21099	return {
21100		get: get,
21101		remove: remove,
21102		update: update,
21103		dispose: dispose
21104	};
21105
21106}
21107
21108function painterSortStable( a, b ) {
21109
21110	if ( a.groupOrder !== b.groupOrder ) {
21111
21112		return a.groupOrder - b.groupOrder;
21113
21114	} else if ( a.renderOrder !== b.renderOrder ) {
21115
21116		return a.renderOrder - b.renderOrder;
21117
21118	} else if ( a.material.id !== b.material.id ) {
21119
21120		return a.material.id - b.material.id;
21121
21122	} else if ( a.z !== b.z ) {
21123
21124		return a.z - b.z;
21125
21126	} else {
21127
21128		return a.id - b.id;
21129
21130	}
21131
21132}
21133
21134function reversePainterSortStable( a, b ) {
21135
21136	if ( a.groupOrder !== b.groupOrder ) {
21137
21138		return a.groupOrder - b.groupOrder;
21139
21140	} else if ( a.renderOrder !== b.renderOrder ) {
21141
21142		return a.renderOrder - b.renderOrder;
21143
21144	} else if ( a.z !== b.z ) {
21145
21146		return b.z - a.z;
21147
21148	} else {
21149
21150		return a.id - b.id;
21151
21152	}
21153
21154}
21155
21156
21157function WebGLRenderList() {
21158
21159	const renderItems = [];
21160	let renderItemsIndex = 0;
21161
21162	const opaque = [];
21163	const transmissive = [];
21164	const transparent = [];
21165
21166	function init() {
21167
21168		renderItemsIndex = 0;
21169
21170		opaque.length = 0;
21171		transmissive.length = 0;
21172		transparent.length = 0;
21173
21174	}
21175
21176	function getNextRenderItem( object, geometry, material, groupOrder, z, group ) {
21177
21178		let renderItem = renderItems[ renderItemsIndex ];
21179
21180		if ( renderItem === undefined ) {
21181
21182			renderItem = {
21183				id: object.id,
21184				object: object,
21185				geometry: geometry,
21186				material: material,
21187				groupOrder: groupOrder,
21188				renderOrder: object.renderOrder,
21189				z: z,
21190				group: group
21191			};
21192
21193			renderItems[ renderItemsIndex ] = renderItem;
21194
21195		} else {
21196
21197			renderItem.id = object.id;
21198			renderItem.object = object;
21199			renderItem.geometry = geometry;
21200			renderItem.material = material;
21201			renderItem.groupOrder = groupOrder;
21202			renderItem.renderOrder = object.renderOrder;
21203			renderItem.z = z;
21204			renderItem.group = group;
21205
21206		}
21207
21208		renderItemsIndex ++;
21209
21210		return renderItem;
21211
21212	}
21213
21214	function push( object, geometry, material, groupOrder, z, group ) {
21215
21216		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
21217
21218		if ( material.transmission > 0.0 ) {
21219
21220			transmissive.push( renderItem );
21221
21222		} else if ( material.transparent === true ) {
21223
21224			transparent.push( renderItem );
21225
21226		} else {
21227
21228			opaque.push( renderItem );
21229
21230		}
21231
21232	}
21233
21234	function unshift( object, geometry, material, groupOrder, z, group ) {
21235
21236		const renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );
21237
21238		if ( material.transmission > 0.0 ) {
21239
21240			transmissive.unshift( renderItem );
21241
21242		} else if ( material.transparent === true ) {
21243
21244			transparent.unshift( renderItem );
21245
21246		} else {
21247
21248			opaque.unshift( renderItem );
21249
21250		}
21251
21252	}
21253
21254	function sort( customOpaqueSort, customTransparentSort ) {
21255
21256		if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
21257		if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
21258		if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
21259
21260	}
21261
21262	function finish() {
21263
21264		// Clear references from inactive renderItems in the list
21265
21266		for ( let i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {
21267
21268			const renderItem = renderItems[ i ];
21269
21270			if ( renderItem.id === null ) break;
21271
21272			renderItem.id = null;
21273			renderItem.object = null;
21274			renderItem.geometry = null;
21275			renderItem.material = null;
21276			renderItem.group = null;
21277
21278		}
21279
21280	}
21281
21282	return {
21283
21284		opaque: opaque,
21285		transmissive: transmissive,
21286		transparent: transparent,
21287
21288		init: init,
21289		push: push,
21290		unshift: unshift,
21291		finish: finish,
21292
21293		sort: sort
21294	};
21295
21296}
21297
21298function WebGLRenderLists() {
21299
21300	let lists = new WeakMap();
21301
21302	function get( scene, renderCallDepth ) {
21303
21304		const listArray = lists.get( scene );
21305		let list;
21306
21307		if ( listArray === undefined ) {
21308
21309			list = new WebGLRenderList();
21310			lists.set( scene, [ list ] );
21311
21312		} else {
21313
21314			if ( renderCallDepth >= listArray.length ) {
21315
21316				list = new WebGLRenderList();
21317				listArray.push( list );
21318
21319			} else {
21320
21321				list = listArray[ renderCallDepth ];
21322
21323			}
21324
21325		}
21326
21327		return list;
21328
21329	}
21330
21331	function dispose() {
21332
21333		lists = new WeakMap();
21334
21335	}
21336
21337	return {
21338		get: get,
vendor: 10,347 bytes, lines 21339-21798
21339		dispose: dispose
21340	};
21341
21342}
21343
21344function UniformsCache() {
21345
21346	const lights = {};
21347
21348	return {
21349
21350		get: function ( light ) {
21351
21352			if ( lights[ light.id ] !== undefined ) {
21353
21354				return lights[ light.id ];
21355
21356			}
21357
21358			let uniforms;
21359
21360			switch ( light.type ) {
21361
21362				case 'DirectionalLight':
21363					uniforms = {
21364						direction: new Vector3(),
21365						color: new Color()
21366					};
21367					break;
21368
21369				case 'SpotLight':
21370					uniforms = {
21371						position: new Vector3(),
21372						direction: new Vector3(),
21373						color: new Color(),
21374						distance: 0,
21375						coneCos: 0,
21376						penumbraCos: 0,
21377						decay: 0
21378					};
21379					break;
21380
21381				case 'PointLight':
21382					uniforms = {
21383						position: new Vector3(),
21384						color: new Color(),
21385						distance: 0,
21386						decay: 0
21387					};
21388					break;
21389
21390				case 'HemisphereLight':
21391					uniforms = {
21392						direction: new Vector3(),
21393						skyColor: new Color(),
21394						groundColor: new Color()
21395					};
21396					break;
21397
21398				case 'RectAreaLight':
21399					uniforms = {
21400						color: new Color(),
21401						position: new Vector3(),
21402						halfWidth: new Vector3(),
21403						halfHeight: new Vector3()
21404					};
21405					break;
21406
21407			}
21408
21409			lights[ light.id ] = uniforms;
21410
21411			return uniforms;
21412
21413		}
21414
21415	};
21416
21417}
21418
21419function ShadowUniformsCache() {
21420
21421	const lights = {};
21422
21423	return {
21424
21425		get: function ( light ) {
21426
21427			if ( lights[ light.id ] !== undefined ) {
21428
21429				return lights[ light.id ];
21430
21431			}
21432
21433			let uniforms;
21434
21435			switch ( light.type ) {
21436
21437				case 'DirectionalLight':
21438					uniforms = {
21439						shadowBias: 0,
21440						shadowNormalBias: 0,
21441						shadowRadius: 1,
21442						shadowMapSize: new Vector2()
21443					};
21444					break;
21445
21446				case 'SpotLight':
21447					uniforms = {
21448						shadowBias: 0,
21449						shadowNormalBias: 0,
21450						shadowRadius: 1,
21451						shadowMapSize: new Vector2()
21452					};
21453					break;
21454
21455				case 'PointLight':
21456					uniforms = {
21457						shadowBias: 0,
21458						shadowNormalBias: 0,
21459						shadowRadius: 1,
21460						shadowMapSize: new Vector2(),
21461						shadowCameraNear: 1,
21462						shadowCameraFar: 1000
21463					};
21464					break;
21465
21466				// TODO (abelnation): set RectAreaLight shadow uniforms
21467
21468			}
21469
21470			lights[ light.id ] = uniforms;
21471
21472			return uniforms;
21473
21474		}
21475
21476	};
21477
21478}
21479
21480
21481
21482let nextVersion = 0;
21483
21484function shadowCastingAndTexturingLightsFirst( lightA, lightB ) {
21485
21486	return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 );
21487
21488}
21489
21490function WebGLLights( extensions ) {
21491
21492	const cache = new UniformsCache();
21493
21494	const shadowCache = ShadowUniformsCache();
21495
21496	const state = {
21497
21498		version: 0,
21499
21500		hash: {
21501			directionalLength: - 1,
21502			pointLength: - 1,
21503			spotLength: - 1,
21504			rectAreaLength: - 1,
21505			hemiLength: - 1,
21506
21507			numDirectionalShadows: - 1,
21508			numPointShadows: - 1,
21509			numSpotShadows: - 1,
21510			numSpotMaps: - 1,
21511
21512			numLightProbes: - 1
21513		},
21514
21515		ambient: [ 0, 0, 0 ],
21516		probe: [],
21517		directional: [],
21518		directionalShadow: [],
21519		directionalShadowMap: [],
21520		directionalShadowMatrix: [],
21521		spot: [],
21522		spotLightMap: [],
21523		spotShadow: [],
21524		spotShadowMap: [],
21525		spotLightMatrix: [],
21526		rectArea: [],
21527		rectAreaLTC1: null,
21528		rectAreaLTC2: null,
21529		point: [],
21530		pointShadow: [],
21531		pointShadowMap: [],
21532		pointShadowMatrix: [],
21533		hemi: [],
21534		numSpotLightShadowsWithMaps: 0,
21535		numLightProbes: 0
21536
21537	};
21538
21539	for ( let i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );
21540
21541	const vector3 = new Vector3();
21542	const matrix4 = new Matrix4();
21543	const matrix42 = new Matrix4();
21544
21545	function setup( lights ) {
21546
21547		let r = 0, g = 0, b = 0;
21548
21549		for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );
21550
21551		let directionalLength = 0;
21552		let pointLength = 0;
21553		let spotLength = 0;
21554		let rectAreaLength = 0;
21555		let hemiLength = 0;
21556
21557		let numDirectionalShadows = 0;
21558		let numPointShadows = 0;
21559		let numSpotShadows = 0;
21560		let numSpotMaps = 0;
21561		let numSpotShadowsWithMaps = 0;
21562
21563		let numLightProbes = 0;
21564
21565		// ordering : [shadow casting + map texturing, map texturing, shadow casting, none ]
21566		lights.sort( shadowCastingAndTexturingLightsFirst );
21567
21568		for ( let i = 0, l = lights.length; i < l; i ++ ) {
21569
21570			const light = lights[ i ];
21571
21572			const color = light.color;
21573			const intensity = light.intensity;
21574			const distance = light.distance;
21575
21576			const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
21577
21578			if ( light.isAmbientLight ) {
21579
21580				r += color.r * intensity;
21581				g += color.g * intensity;
21582				b += color.b * intensity;
21583
21584			} else if ( light.isLightProbe ) {
21585
21586				for ( let j = 0; j < 9; j ++ ) {
21587
21588					state.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );
21589
21590				}
21591
21592				numLightProbes ++;
21593
21594			} else if ( light.isDirectionalLight ) {
21595
21596				const uniforms = cache.get( light );
21597
21598				uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
21599
21600				if ( light.castShadow ) {
21601
21602					const shadow = light.shadow;
21603
21604					const shadowUniforms = shadowCache.get( light );
21605
21606					shadowUniforms.shadowBias = shadow.bias;
21607					shadowUniforms.shadowNormalBias = shadow.normalBias;
21608					shadowUniforms.shadowRadius = shadow.radius;
21609					shadowUniforms.shadowMapSize = shadow.mapSize;
21610
21611					state.directionalShadow[ directionalLength ] = shadowUniforms;
21612					state.directionalShadowMap[ directionalLength ] = shadowMap;
21613					state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
21614
21615					numDirectionalShadows ++;
21616
21617				}
21618
21619				state.directional[ directionalLength ] = uniforms;
21620
21621				directionalLength ++;
21622
21623			} else if ( light.isSpotLight ) {
21624
21625				const uniforms = cache.get( light );
21626
21627				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21628
21629				uniforms.color.copy( color ).multiplyScalar( intensity );
21630				uniforms.distance = distance;
21631
21632				uniforms.coneCos = Math.cos( light.angle );
21633				uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
21634				uniforms.decay = light.decay;
21635
21636				state.spot[ spotLength ] = uniforms;
21637
21638				const shadow = light.shadow;
21639
21640				if ( light.map ) {
21641
21642					state.spotLightMap[ numSpotMaps ] = light.map;
21643					numSpotMaps ++;
21644
21645					// make sure the lightMatrix is up to date
21646					// TODO : do it if required only
21647					shadow.updateMatrices( light );
21648
21649					if ( light.castShadow ) numSpotShadowsWithMaps ++;
21650
21651				}
21652
21653				state.spotLightMatrix[ spotLength ] = shadow.matrix;
21654
21655				if ( light.castShadow ) {
21656
21657					const shadowUniforms = shadowCache.get( light );
21658
21659					shadowUniforms.shadowBias = shadow.bias;
21660					shadowUniforms.shadowNormalBias = shadow.normalBias;
21661					shadowUniforms.shadowRadius = shadow.radius;
21662					shadowUniforms.shadowMapSize = shadow.mapSize;
21663
21664					state.spotShadow[ spotLength ] = shadowUniforms;
21665					state.spotShadowMap[ spotLength ] = shadowMap;
21666
21667					numSpotShadows ++;
21668
21669				}
21670
21671				spotLength ++;
21672
21673			} else if ( light.isRectAreaLight ) {
21674
21675				const uniforms = cache.get( light );
21676
21677				uniforms.color.copy( color ).multiplyScalar( intensity );
21678
21679				uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
21680				uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
21681
21682				state.rectArea[ rectAreaLength ] = uniforms;
21683
21684				rectAreaLength ++;
21685
21686			} else if ( light.isPointLight ) {
21687
21688				const uniforms = cache.get( light );
21689
21690				uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
21691				uniforms.distance = light.distance;
21692				uniforms.decay = light.decay;
21693
21694				if ( light.castShadow ) {
21695
21696					const shadow = light.shadow;
21697
21698					const shadowUniforms = shadowCache.get( light );
21699
21700					shadowUniforms.shadowBias = shadow.bias;
21701					shadowUniforms.shadowNormalBias = shadow.normalBias;
21702					shadowUniforms.shadowRadius = shadow.radius;
21703					shadowUniforms.shadowMapSize = shadow.mapSize;
21704					shadowUniforms.shadowCameraNear = shadow.camera.near;
21705					shadowUniforms.shadowCameraFar = shadow.camera.far;
21706
21707					state.pointShadow[ pointLength ] = shadowUniforms;
21708					state.pointShadowMap[ pointLength ] = shadowMap;
21709					state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
21710
21711					numPointShadows ++;
21712
21713				}
21714
21715				state.point[ pointLength ] = uniforms;
21716
21717				pointLength ++;
21718
21719			} else if ( light.isHemisphereLight ) {
21720
21721				const uniforms = cache.get( light );
21722
21723				uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
21724				uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
21725
21726				state.hemi[ hemiLength ] = uniforms;
21727
21728				hemiLength ++;
21729
21730			}
21731
21732		}
21733
21734		if ( rectAreaLength > 0 ) {
21735
21736			if ( extensions.has( 'OES_texture_float_linear' ) === true ) {
21737
21738				state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
21739				state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
21740
21741			} else {
21742
21743				state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
21744				state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
21745
21746			}
21747
21748		}
21749
21750		state.ambient[ 0 ] = r;
21751		state.ambient[ 1 ] = g;
21752		state.ambient[ 2 ] = b;
21753
21754		const hash = state.hash;
21755
21756		if ( hash.directionalLength !== directionalLength ||
21757			hash.pointLength !== pointLength ||
21758			hash.spotLength !== spotLength ||
21759			hash.rectAreaLength !== rectAreaLength ||
21760			hash.hemiLength !== hemiLength ||
21761			hash.numDirectionalShadows !== numDirectionalShadows ||
21762			hash.numPointShadows !== numPointShadows ||
21763			hash.numSpotShadows !== numSpotShadows ||
21764			hash.numSpotMaps !== numSpotMaps ||
21765			hash.numLightProbes !== numLightProbes ) {
21766
21767			state.directional.length = directionalLength;
21768			state.spot.length = spotLength;
21769			state.rectArea.length = rectAreaLength;
21770			state.point.length = pointLength;
21771			state.hemi.length = hemiLength;
21772
21773			state.directionalShadow.length = numDirectionalShadows;
21774			state.directionalShadowMap.length = numDirectionalShadows;
21775			state.pointShadow.length = numPointShadows;
21776			state.pointShadowMap.length = numPointShadows;
21777			state.spotShadow.length = numSpotShadows;
21778			state.spotShadowMap.length = numSpotShadows;
21779			state.directionalShadowMatrix.length = numDirectionalShadows;
21780			state.pointShadowMatrix.length = numPointShadows;
21781			state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps;
21782			state.spotLightMap.length = numSpotMaps;
21783			state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps;
21784			state.numLightProbes = numLightProbes;
21785
21786			hash.directionalLength = directionalLength;
21787			hash.pointLength = pointLength;
21788			hash.spotLength = spotLength;
21789			hash.rectAreaLength = rectAreaLength;
21790			hash.hemiLength = hemiLength;
21791
21792			hash.numDirectionalShadows = numDirectionalShadows;
21793			hash.numPointShadows = numPointShadows;
21794			hash.numSpotShadows = numSpotShadows;
21795			hash.numSpotMaps = numSpotMaps;
21796
21797			hash.numLightProbes = numLightProbes;
21798
vendor: 4,329 bytes, lines 21799-22026
21799			state.version = nextVersion ++;
21800
21801		}
21802
21803	}
21804
21805	function setupView( lights, camera ) {
21806
21807		let directionalLength = 0;
21808		let pointLength = 0;
21809		let spotLength = 0;
21810		let rectAreaLength = 0;
21811		let hemiLength = 0;
21812
21813		const viewMatrix = camera.matrixWorldInverse;
21814
21815		for ( let i = 0, l = lights.length; i < l; i ++ ) {
21816
21817			const light = lights[ i ];
21818
21819			if ( light.isDirectionalLight ) {
21820
21821				const uniforms = state.directional[ directionalLength ];
21822
21823				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
21824				vector3.setFromMatrixPosition( light.target.matrixWorld );
21825				uniforms.direction.sub( vector3 );
21826				uniforms.direction.transformDirection( viewMatrix );
21827
21828				directionalLength ++;
21829
21830			} else if ( light.isSpotLight ) {
21831
21832				const uniforms = state.spot[ spotLength ];
21833
21834				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21835				uniforms.position.applyMatrix4( viewMatrix );
21836
21837				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
21838				vector3.setFromMatrixPosition( light.target.matrixWorld );
21839				uniforms.direction.sub( vector3 );
21840				uniforms.direction.transformDirection( viewMatrix );
21841
21842				spotLength ++;
21843
21844			} else if ( light.isRectAreaLight ) {
21845
21846				const uniforms = state.rectArea[ rectAreaLength ];
21847
21848				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21849				uniforms.position.applyMatrix4( viewMatrix );
21850
21851				// extract local rotation of light to derive width/height half vectors
21852				matrix42.identity();
21853				matrix4.copy( light.matrixWorld );
21854				matrix4.premultiply( viewMatrix );
21855				matrix42.extractRotation( matrix4 );
21856
21857				uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
21858				uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
21859
21860				uniforms.halfWidth.applyMatrix4( matrix42 );
21861				uniforms.halfHeight.applyMatrix4( matrix42 );
21862
21863				rectAreaLength ++;
21864
21865			} else if ( light.isPointLight ) {
21866
21867				const uniforms = state.point[ pointLength ];
21868
21869				uniforms.position.setFromMatrixPosition( light.matrixWorld );
21870				uniforms.position.applyMatrix4( viewMatrix );
21871
21872				pointLength ++;
21873
21874			} else if ( light.isHemisphereLight ) {
21875
21876				const uniforms = state.hemi[ hemiLength ];
21877
21878				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
21879				uniforms.direction.transformDirection( viewMatrix );
21880
21881				hemiLength ++;
21882
21883			}
21884
21885		}
21886
21887	}
21888
21889	return {
21890		setup: setup,
21891		setupView: setupView,
21892		state: state
21893	};
21894
21895}
21896
21897function WebGLRenderState( extensions ) {
21898
21899	const lights = new WebGLLights( extensions );
21900
21901	const lightsArray = [];
21902	const shadowsArray = [];
21903
21904	function init( camera ) {
21905
21906		state.camera = camera;
21907
21908		lightsArray.length = 0;
21909		shadowsArray.length = 0;
21910
21911	}
21912
21913	function pushLight( light ) {
21914
21915		lightsArray.push( light );
21916
21917	}
21918
21919	function pushShadow( shadowLight ) {
21920
21921		shadowsArray.push( shadowLight );
21922
21923	}
21924
21925	function setupLights() {
21926
21927		lights.setup( lightsArray );
21928
21929	}
21930
21931	function setupLightsView( camera ) {
21932
21933		lights.setupView( lightsArray, camera );
21934
21935	}
21936
21937	const state = {
21938		lightsArray: lightsArray,
21939		shadowsArray: shadowsArray,
21940
21941		camera: null,
21942
21943		lights: lights,
21944
21945		transmissionRenderTarget: {}
21946	};
21947
21948	return {
21949		init: init,
21950		state: state,
21951		setupLights: setupLights,
21952		setupLightsView: setupLightsView,
21953
21954		pushLight: pushLight,
21955		pushShadow: pushShadow
21956	};
21957
21958}
21959
21960function WebGLRenderStates( extensions ) {
21961
21962	let renderStates = new WeakMap();
21963
21964	function get( scene, renderCallDepth = 0 ) {
21965
21966		const renderStateArray = renderStates.get( scene );
21967		let renderState;
21968
21969		if ( renderStateArray === undefined ) {
21970
21971			renderState = new WebGLRenderState( extensions );
21972			renderStates.set( scene, [ renderState ] );
21973
21974		} else {
21975
21976			if ( renderCallDepth >= renderStateArray.length ) {
21977
21978				renderState = new WebGLRenderState( extensions );
21979				renderStateArray.push( renderState );
21980
21981			} else {
21982
21983				renderState = renderStateArray[ renderCallDepth ];
21984
21985			}
21986
21987		}
21988
21989		return renderState;
21990
21991	}
21992
21993	function dispose() {
21994
21995		renderStates = new WeakMap();
21996
21997	}
21998
21999	return {
22000		get: get,
22001		dispose: dispose
22002	};
22003
22004}
22005
22006class MeshDepthMaterial extends Material {
22007
22008	constructor( parameters ) {
22009
22010		super();
22011
22012		this.isMeshDepthMaterial = true;
22013
22014		this.type = 'MeshDepthMaterial';
22015
22016		this.depthPacking = BasicDepthPacking;
22017
22018		this.map = null;
22019
22020		this.alphaMap = null;
22021
22022		this.displacementMap = null;
22023		this.displacementScale = 1;
22024		this.displacementBias = 0;
22025
22026		this.wireframe = false;
vendor: 10,058 bytes, lines 22027-22393
22027		this.wireframeLinewidth = 1;
22028
22029		this.setValues( parameters );
22030
22031	}
22032
22033	copy( source ) {
22034
22035		super.copy( source );
22036
22037		this.depthPacking = source.depthPacking;
22038
22039		this.map = source.map;
22040
22041		this.alphaMap = source.alphaMap;
22042
22043		this.displacementMap = source.displacementMap;
22044		this.displacementScale = source.displacementScale;
22045		this.displacementBias = source.displacementBias;
22046
22047		this.wireframe = source.wireframe;
22048		this.wireframeLinewidth = source.wireframeLinewidth;
22049
22050		return this;
22051
22052	}
22053
22054}
22055
22056class MeshDistanceMaterial extends Material {
22057
22058	constructor( parameters ) {
22059
22060		super();
22061
22062		this.isMeshDistanceMaterial = true;
22063
22064		this.type = 'MeshDistanceMaterial';
22065
22066		this.map = null;
22067
22068		this.alphaMap = null;
22069
22070		this.displacementMap = null;
22071		this.displacementScale = 1;
22072		this.displacementBias = 0;
22073
22074		this.setValues( parameters );
22075
22076	}
22077
22078	copy( source ) {
22079
22080		super.copy( source );
22081
22082		this.map = source.map;
22083
22084		this.alphaMap = source.alphaMap;
22085
22086		this.displacementMap = source.displacementMap;
22087		this.displacementScale = source.displacementScale;
22088		this.displacementBias = source.displacementBias;
22089
22090		return this;
22091
22092	}
22093
22094}
22095
22096const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
22097
22098const 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}";
22099
22100function WebGLShadowMap( renderer, objects, capabilities ) {
22101
22102	let _frustum = new Frustum();
22103
22104	const _shadowMapSize = new Vector2(),
22105		_viewportSize = new Vector2(),
22106
22107		_viewport = new Vector4(),
22108
22109		_depthMaterial = new MeshDepthMaterial( { depthPacking: RGBADepthPacking } ),
22110		_distanceMaterial = new MeshDistanceMaterial(),
22111
22112		_materialCache = {},
22113
22114		_maxTextureSize = capabilities.maxTextureSize;
22115
22116	const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide };
22117
22118	const shadowMaterialVertical = new ShaderMaterial( {
22119		defines: {
22120			VSM_SAMPLES: 8
22121		},
22122		uniforms: {
22123			shadow_pass: { value: null },
22124			resolution: { value: new Vector2() },
22125			radius: { value: 4.0 }
22126		},
22127
22128		vertexShader: vertex,
22129		fragmentShader: fragment
22130
22131	} );
22132
22133	const shadowMaterialHorizontal = shadowMaterialVertical.clone();
22134	shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
22135
22136	const fullScreenTri = new BufferGeometry();
22137	fullScreenTri.setAttribute(
22138		'position',
22139		new BufferAttribute(
22140			new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
22141			3
22142		)
22143	);
22144
22145	const fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );
22146
22147	const scope = this;
22148
22149	this.enabled = false;
22150
22151	this.autoUpdate = true;
22152	this.needsUpdate = false;
22153
22154	this.type = PCFShadowMap;
22155	let _previousType = this.type;
22156
22157	this.render = function ( lights, scene, camera ) {
22158
22159		if ( scope.enabled === false ) return;
22160		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
22161
22162		if ( lights.length === 0 ) return;
22163
22164		const currentRenderTarget = renderer.getRenderTarget();
22165		const activeCubeFace = renderer.getActiveCubeFace();
22166		const activeMipmapLevel = renderer.getActiveMipmapLevel();
22167
22168		const _state = renderer.state;
22169
22170		// Set GL state for depth map.
22171		_state.setBlending( NoBlending );
22172		_state.buffers.color.setClear( 1, 1, 1, 1 );
22173		_state.buffers.depth.setTest( true );
22174		_state.setScissorTest( false );
22175
22176		// check for shadow map type changes
22177
22178		const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap );
22179		const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap );
22180
22181		// render depth map
22182
22183		for ( let i = 0, il = lights.length; i < il; i ++ ) {
22184
22185			const light = lights[ i ];
22186			const shadow = light.shadow;
22187
22188			if ( shadow === undefined ) {
22189
22190				console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
22191				continue;
22192
22193			}
22194
22195			if ( shadow.autoUpdate === false && shadow.needsUpdate === false ) continue;
22196
22197			_shadowMapSize.copy( shadow.mapSize );
22198
22199			const shadowFrameExtents = shadow.getFrameExtents();
22200
22201			_shadowMapSize.multiply( shadowFrameExtents );
22202
22203			_viewportSize.copy( shadow.mapSize );
22204
22205			if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) {
22206
22207				if ( _shadowMapSize.x > _maxTextureSize ) {
22208
22209					_viewportSize.x = Math.floor( _maxTextureSize / shadowFrameExtents.x );
22210					_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
22211					shadow.mapSize.x = _viewportSize.x;
22212
22213				}
22214
22215				if ( _shadowMapSize.y > _maxTextureSize ) {
22216
22217					_viewportSize.y = Math.floor( _maxTextureSize / shadowFrameExtents.y );
22218					_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
22219					shadow.mapSize.y = _viewportSize.y;
22220
22221				}
22222
22223			}
22224
22225			if ( shadow.map === null || toVSM === true || fromVSM === true ) {
22226
22227				const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {};
22228
22229				if ( shadow.map !== null ) {
22230
22231					shadow.map.dispose();
22232
22233				}
22234
22235				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
22236				shadow.map.texture.name = light.name + '.shadowMap';
22237
22238				shadow.camera.updateProjectionMatrix();
22239
22240			}
22241
22242			renderer.setRenderTarget( shadow.map );
22243			renderer.clear();
22244
22245			const viewportCount = shadow.getViewportCount();
22246
22247			for ( let vp = 0; vp < viewportCount; vp ++ ) {
22248
22249				const viewport = shadow.getViewport( vp );
22250
22251				_viewport.set(
22252					_viewportSize.x * viewport.x,
22253					_viewportSize.y * viewport.y,
22254					_viewportSize.x * viewport.z,
22255					_viewportSize.y * viewport.w
22256				);
22257
22258				_state.viewport( _viewport );
22259
22260				shadow.updateMatrices( light, vp );
22261
22262				_frustum = shadow.getFrustum();
22263
22264				renderObject( scene, camera, shadow.camera, light, this.type );
22265
22266			}
22267
22268			// do blur pass for VSM
22269
22270			if ( shadow.isPointLightShadow !== true && this.type === VSMShadowMap ) {
22271
22272				VSMPass( shadow, camera );
22273
22274			}
22275
22276			shadow.needsUpdate = false;
22277
22278		}
22279
22280		_previousType = this.type;
22281
22282		scope.needsUpdate = false;
22283
22284		renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
22285
22286	};
22287
22288	function VSMPass( shadow, camera ) {
22289
22290		const geometry = objects.update( fullScreenMesh );
22291
22292		if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) {
22293
22294			shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
22295			shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
22296
22297			shadowMaterialVertical.needsUpdate = true;
22298			shadowMaterialHorizontal.needsUpdate = true;
22299
22300		}
22301
22302		if ( shadow.mapPass === null ) {
22303
22304			shadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y );
22305
22306		}
22307
22308		// vertical pass
22309
22310		shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
22311		shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
22312		shadowMaterialVertical.uniforms.radius.value = shadow.radius;
22313		renderer.setRenderTarget( shadow.mapPass );
22314		renderer.clear();
22315		renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );
22316
22317		// horizontal pass
22318
22319		shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
22320		shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
22321		shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
22322		renderer.setRenderTarget( shadow.map );
22323		renderer.clear();
22324		renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null );
22325
22326	}
22327
22328	function getDepthMaterial( object, material, light, type ) {
22329
22330		let result = null;
22331
22332		const customMaterial = ( light.isPointLight === true ) ? object.customDistanceMaterial : object.customDepthMaterial;
22333
22334		if ( customMaterial !== undefined ) {
22335
22336			result = customMaterial;
22337
22338		} else {
22339
22340			result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial;
22341
22342			if ( ( renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) ||
22343				( material.displacementMap && material.displacementScale !== 0 ) ||
22344				( material.alphaMap && material.alphaTest > 0 ) ||
22345				( material.map && material.alphaTest > 0 ) ) {
22346
22347				// in this case we need a unique material instance reflecting the
22348				// appropriate state
22349
22350				const keyA = result.uuid, keyB = material.uuid;
22351
22352				let materialsForVariant = _materialCache[ keyA ];
22353
22354				if ( materialsForVariant === undefined ) {
22355
22356					materialsForVariant = {};
22357					_materialCache[ keyA ] = materialsForVariant;
22358
22359				}
22360
22361				let cachedMaterial = materialsForVariant[ keyB ];
22362
22363				if ( cachedMaterial === undefined ) {
22364
22365					cachedMaterial = result.clone();
22366					materialsForVariant[ keyB ] = cachedMaterial;
22367					material.addEventListener( 'dispose', onMaterialDispose );
22368
22369				}
22370
22371				result = cachedMaterial;
22372
22373			}
22374
22375		}
22376
22377		result.visible = material.visible;
22378		result.wireframe = material.wireframe;
22379
22380		if ( type === VSMShadowMap ) {
22381
22382			result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
22383
22384		} else {
22385
22386			result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
22387
22388		}
22389
22390		result.alphaMap = material.alphaMap;
22391		result.alphaTest = material.alphaTest;
22392		result.map = material.map;
22393
vendor: 12,973 bytes, lines 22394-23047
22394		result.clipShadows = material.clipShadows;
22395		result.clippingPlanes = material.clippingPlanes;
22396		result.clipIntersection = material.clipIntersection;
22397
22398		result.displacementMap = material.displacementMap;
22399		result.displacementScale = material.displacementScale;
22400		result.displacementBias = material.displacementBias;
22401
22402		result.wireframeLinewidth = material.wireframeLinewidth;
22403		result.linewidth = material.linewidth;
22404
22405		if ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {
22406
22407			const materialProperties = renderer.properties.get( result );
22408			materialProperties.light = light;
22409
22410		}
22411
22412		return result;
22413
22414	}
22415
22416	function renderObject( object, camera, shadowCamera, light, type ) {
22417
22418		if ( object.visible === false ) return;
22419
22420		const visible = object.layers.test( camera.layers );
22421
22422		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
22423
22424			if ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
22425
22426				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
22427
22428				const geometry = objects.update( object );
22429				const material = object.material;
22430
22431				if ( Array.isArray( material ) ) {
22432
22433					const groups = geometry.groups;
22434
22435					for ( let k = 0, kl = groups.length; k < kl; k ++ ) {
22436
22437						const group = groups[ k ];
22438						const groupMaterial = material[ group.materialIndex ];
22439
22440						if ( groupMaterial && groupMaterial.visible ) {
22441
22442							const depthMaterial = getDepthMaterial( object, groupMaterial, light, type );
22443
22444							object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group );
22445
22446							renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
22447
22448							object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group );
22449
22450						}
22451
22452					}
22453
22454				} else if ( material.visible ) {
22455
22456					const depthMaterial = getDepthMaterial( object, material, light, type );
22457
22458					object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null );
22459
22460					renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
22461
22462					object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null );
22463
22464				}
22465
22466			}
22467
22468		}
22469
22470		const children = object.children;
22471
22472		for ( let i = 0, l = children.length; i < l; i ++ ) {
22473
22474			renderObject( children[ i ], camera, shadowCamera, light, type );
22475
22476		}
22477
22478	}
22479
22480	function onMaterialDispose( event ) {
22481
22482		const material = event.target;
22483
22484		material.removeEventListener( 'dispose', onMaterialDispose );
22485
22486		// make sure to remove the unique distance/depth materials used for shadow map rendering
22487
22488		for ( const id in _materialCache ) {
22489
22490			const cache = _materialCache[ id ];
22491
22492			const uuid = event.target.uuid;
22493
22494			if ( uuid in cache ) {
22495
22496				const shadowMaterial = cache[ uuid ];
22497				shadowMaterial.dispose();
22498				delete cache[ uuid ];
22499
22500			}
22501
22502		}
22503
22504	}
22505
22506}
22507
22508function WebGLState( gl ) {
22509
22510	function ColorBuffer() {
22511
22512		let locked = false;
22513
22514		const color = new Vector4();
22515		let currentColorMask = null;
22516		const currentColorClear = new Vector4( 0, 0, 0, 0 );
22517
22518		return {
22519
22520			setMask: function ( colorMask ) {
22521
22522				if ( currentColorMask !== colorMask && ! locked ) {
22523
22524					gl.colorMask( colorMask, colorMask, colorMask, colorMask );
22525					currentColorMask = colorMask;
22526
22527				}
22528
22529			},
22530
22531			setLocked: function ( lock ) {
22532
22533				locked = lock;
22534
22535			},
22536
22537			setClear: function ( r, g, b, a, premultipliedAlpha ) {
22538
22539				if ( premultipliedAlpha === true ) {
22540
22541					r *= a; g *= a; b *= a;
22542
22543				}
22544
22545				color.set( r, g, b, a );
22546
22547				if ( currentColorClear.equals( color ) === false ) {
22548
22549					gl.clearColor( r, g, b, a );
22550					currentColorClear.copy( color );
22551
22552				}
22553
22554			},
22555
22556			reset: function () {
22557
22558				locked = false;
22559
22560				currentColorMask = null;
22561				currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state
22562
22563			}
22564
22565		};
22566
22567	}
22568
22569	function DepthBuffer() {
22570
22571		let locked = false;
22572
22573		let currentDepthMask = null;
22574		let currentDepthFunc = null;
22575		let currentDepthClear = null;
22576
22577		return {
22578
22579			setTest: function ( depthTest ) {
22580
22581				if ( depthTest ) {
22582
22583					enable( gl.DEPTH_TEST );
22584
22585				} else {
22586
22587					disable( gl.DEPTH_TEST );
22588
22589				}
22590
22591			},
22592
22593			setMask: function ( depthMask ) {
22594
22595				if ( currentDepthMask !== depthMask && ! locked ) {
22596
22597					gl.depthMask( depthMask );
22598					currentDepthMask = depthMask;
22599
22600				}
22601
22602			},
22603
22604			setFunc: function ( depthFunc ) {
22605
22606				if ( currentDepthFunc !== depthFunc ) {
22607
22608					switch ( depthFunc ) {
22609
22610						case NeverDepth:
22611
22612							gl.depthFunc( gl.NEVER );
22613							break;
22614
22615						case AlwaysDepth:
22616
22617							gl.depthFunc( gl.ALWAYS );
22618							break;
22619
22620						case LessDepth:
22621
22622							gl.depthFunc( gl.LESS );
22623							break;
22624
22625						case LessEqualDepth:
22626
22627							gl.depthFunc( gl.LEQUAL );
22628							break;
22629
22630						case EqualDepth:
22631
22632							gl.depthFunc( gl.EQUAL );
22633							break;
22634
22635						case GreaterEqualDepth:
22636
22637							gl.depthFunc( gl.GEQUAL );
22638							break;
22639
22640						case GreaterDepth:
22641
22642							gl.depthFunc( gl.GREATER );
22643							break;
22644
22645						case NotEqualDepth:
22646
22647							gl.depthFunc( gl.NOTEQUAL );
22648							break;
22649
22650						default:
22651
22652							gl.depthFunc( gl.LEQUAL );
22653
22654					}
22655
22656					currentDepthFunc = depthFunc;
22657
22658				}
22659
22660			},
22661
22662			setLocked: function ( lock ) {
22663
22664				locked = lock;
22665
22666			},
22667
22668			setClear: function ( depth ) {
22669
22670				if ( currentDepthClear !== depth ) {
22671
22672					gl.clearDepth( depth );
22673					currentDepthClear = depth;
22674
22675				}
22676
22677			},
22678
22679			reset: function () {
22680
22681				locked = false;
22682
22683				currentDepthMask = null;
22684				currentDepthFunc = null;
22685				currentDepthClear = null;
22686
22687			}
22688
22689		};
22690
22691	}
22692
22693	function StencilBuffer() {
22694
22695		let locked = false;
22696
22697		let currentStencilMask = null;
22698		let currentStencilFunc = null;
22699		let currentStencilRef = null;
22700		let currentStencilFuncMask = null;
22701		let currentStencilFail = null;
22702		let currentStencilZFail = null;
22703		let currentStencilZPass = null;
22704		let currentStencilClear = null;
22705
22706		return {
22707
22708			setTest: function ( stencilTest ) {
22709
22710				if ( ! locked ) {
22711
22712					if ( stencilTest ) {
22713
22714						enable( gl.STENCIL_TEST );
22715
22716					} else {
22717
22718						disable( gl.STENCIL_TEST );
22719
22720					}
22721
22722				}
22723
22724			},
22725
22726			setMask: function ( stencilMask ) {
22727
22728				if ( currentStencilMask !== stencilMask && ! locked ) {
22729
22730					gl.stencilMask( stencilMask );
22731					currentStencilMask = stencilMask;
22732
22733				}
22734
22735			},
22736
22737			setFunc: function ( stencilFunc, stencilRef, stencilMask ) {
22738
22739				if ( currentStencilFunc !== stencilFunc ||
22740				     currentStencilRef !== stencilRef ||
22741				     currentStencilFuncMask !== stencilMask ) {
22742
22743					gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
22744
22745					currentStencilFunc = stencilFunc;
22746					currentStencilRef = stencilRef;
22747					currentStencilFuncMask = stencilMask;
22748
22749				}
22750
22751			},
22752
22753			setOp: function ( stencilFail, stencilZFail, stencilZPass ) {
22754
22755				if ( currentStencilFail !== stencilFail ||
22756				     currentStencilZFail !== stencilZFail ||
22757				     currentStencilZPass !== stencilZPass ) {
22758
22759					gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
22760
22761					currentStencilFail = stencilFail;
22762					currentStencilZFail = stencilZFail;
22763					currentStencilZPass = stencilZPass;
22764
22765				}
22766
22767			},
22768
22769			setLocked: function ( lock ) {
22770
22771				locked = lock;
22772
22773			},
22774
22775			setClear: function ( stencil ) {
22776
22777				if ( currentStencilClear !== stencil ) {
22778
22779					gl.clearStencil( stencil );
22780					currentStencilClear = stencil;
22781
22782				}
22783
22784			},
22785
22786			reset: function () {
22787
22788				locked = false;
22789
22790				currentStencilMask = null;
22791				currentStencilFunc = null;
22792				currentStencilRef = null;
22793				currentStencilFuncMask = null;
22794				currentStencilFail = null;
22795				currentStencilZFail = null;
22796				currentStencilZPass = null;
22797				currentStencilClear = null;
22798
22799			}
22800
22801		};
22802
22803	}
22804
22805	//
22806
22807	const colorBuffer = new ColorBuffer();
22808	const depthBuffer = new DepthBuffer();
22809	const stencilBuffer = new StencilBuffer();
22810
22811	const uboBindings = new WeakMap();
22812	const uboProgramMap = new WeakMap();
22813
22814	let enabledCapabilities = {};
22815
22816	let currentBoundFramebuffers = {};
22817	let currentDrawbuffers = new WeakMap();
22818	let defaultDrawbuffers = [];
22819
22820	let currentProgram = null;
22821
22822	let currentBlendingEnabled = false;
22823	let currentBlending = null;
22824	let currentBlendEquation = null;
22825	let currentBlendSrc = null;
22826	let currentBlendDst = null;
22827	let currentBlendEquationAlpha = null;
22828	let currentBlendSrcAlpha = null;
22829	let currentBlendDstAlpha = null;
22830	let currentBlendColor = new Color( 0, 0, 0 );
22831	let currentBlendAlpha = 0;
22832	let currentPremultipledAlpha = false;
22833
22834	let currentFlipSided = null;
22835	let currentCullFace = null;
22836
22837	let currentLineWidth = null;
22838
22839	let currentPolygonOffsetFactor = null;
22840	let currentPolygonOffsetUnits = null;
22841
22842	const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );
22843
22844	let lineWidthAvailable = false;
22845	let version = 0;
22846	const glVersion = gl.getParameter( gl.VERSION );
22847
22848	if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {
22849
22850		version = parseFloat( /^WebGL (\d)/.exec( glVersion )[ 1 ] );
22851		lineWidthAvailable = ( version >= 1.0 );
22852
22853	} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {
22854
22855		version = parseFloat( /^OpenGL ES (\d)/.exec( glVersion )[ 1 ] );
22856		lineWidthAvailable = ( version >= 2.0 );
22857
22858	}
22859
22860	let currentTextureSlot = null;
22861	let currentBoundTextures = {};
22862
22863	const scissorParam = gl.getParameter( gl.SCISSOR_BOX );
22864	const viewportParam = gl.getParameter( gl.VIEWPORT );
22865
22866	const currentScissor = new Vector4().fromArray( scissorParam );
22867	const currentViewport = new Vector4().fromArray( viewportParam );
22868
22869	function createTexture( type, target, count, dimensions ) {
22870
22871		const data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.
22872		const texture = gl.createTexture();
22873
22874		gl.bindTexture( type, texture );
22875		gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
22876		gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
22877
22878		for ( let i = 0; i < count; i ++ ) {
22879
22880			if ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) {
22881
22882				gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
22883
22884			} else {
22885
22886				gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
22887
22888			}
22889
22890		}
22891
22892		return texture;
22893
22894	}
22895
22896	const emptyTextures = {};
22897	emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );
22898	emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );
22899	emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 );
22900	emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 );
22901
22902	// init
22903
22904	colorBuffer.setClear( 0, 0, 0, 1 );
22905	depthBuffer.setClear( 1 );
22906	stencilBuffer.setClear( 0 );
22907
22908	enable( gl.DEPTH_TEST );
22909	depthBuffer.setFunc( LessEqualDepth );
22910
22911	setFlipSided( false );
22912	setCullFace( CullFaceBack );
22913	enable( gl.CULL_FACE );
22914
22915	setBlending( NoBlending );
22916
22917	//
22918
22919	function enable( id ) {
22920
22921		if ( enabledCapabilities[ id ] !== true ) {
22922
22923			gl.enable( id );
22924			enabledCapabilities[ id ] = true;
22925
22926		}
22927
22928	}
22929
22930	function disable( id ) {
22931
22932		if ( enabledCapabilities[ id ] !== false ) {
22933
22934			gl.disable( id );
22935			enabledCapabilities[ id ] = false;
22936
22937		}
22938
22939	}
22940
22941	function bindFramebuffer( target, framebuffer ) {
22942
22943		if ( currentBoundFramebuffers[ target ] !== framebuffer ) {
22944
22945			gl.bindFramebuffer( target, framebuffer );
22946
22947			currentBoundFramebuffers[ target ] = framebuffer;
22948
22949			// gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER
22950
22951			if ( target === gl.DRAW_FRAMEBUFFER ) {
22952
22953				currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer;
22954
22955			}
22956
22957			if ( target === gl.FRAMEBUFFER ) {
22958
22959				currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer;
22960
22961			}
22962
22963			return true;
22964
22965		}
22966
22967		return false;
22968
22969	}
22970
22971	function drawBuffers( renderTarget, framebuffer ) {
22972
22973		let drawBuffers = defaultDrawbuffers;
22974
22975		let needsUpdate = false;
22976
22977		if ( renderTarget ) {
22978
22979			drawBuffers = currentDrawbuffers.get( framebuffer );
22980
22981			if ( drawBuffers === undefined ) {
22982
22983				drawBuffers = [];
22984				currentDrawbuffers.set( framebuffer, drawBuffers );
22985
22986			}
22987
22988			const textures = renderTarget.textures;
22989
22990			if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) {
22991
22992				for ( let i = 0, il = textures.length; i < il; i ++ ) {
22993
22994					drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i;
22995
22996				}
22997
22998				drawBuffers.length = textures.length;
22999
23000				needsUpdate = true;
23001
23002			}
23003
23004		} else {
23005
23006			if ( drawBuffers[ 0 ] !== gl.BACK ) {
23007
23008				drawBuffers[ 0 ] = gl.BACK;
23009
23010				needsUpdate = true;
23011
23012			}
23013
23014		}
23015
23016		if ( needsUpdate ) {
23017
23018			gl.drawBuffers( drawBuffers );
23019
23020		}
23021
23022	}
23023
23024	function useProgram( program ) {
23025
23026		if ( currentProgram !== program ) {
23027
23028			gl.useProgram( program );
23029
23030			currentProgram = program;
23031
23032			return true;
23033
23034		}
23035
23036		return false;
23037
23038	}
23039
23040	const equationToGL = {
23041		[ AddEquation ]: gl.FUNC_ADD,
23042		[ SubtractEquation ]: gl.FUNC_SUBTRACT,
23043		[ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT
23044	};
23045
23046	equationToGL[ MinEquation ] = gl.MIN;
23047	equationToGL[ MaxEquation ] = gl.MAX;
vendor: 12,328 bytes, lines 23047-23670
23047
23048
23049	const factorToGL = {
23050		[ ZeroFactor ]: gl.ZERO,
23051		[ OneFactor ]: gl.ONE,
23052		[ SrcColorFactor ]: gl.SRC_COLOR,
23053		[ SrcAlphaFactor ]: gl.SRC_ALPHA,
23054		[ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE,
23055		[ DstColorFactor ]: gl.DST_COLOR,
23056		[ DstAlphaFactor ]: gl.DST_ALPHA,
23057		[ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR,
23058		[ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA,
23059		[ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR,
23060		[ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA,
23061		[ ConstantColorFactor ]: gl.CONSTANT_COLOR,
23062		[ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR,
23063		[ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA,
23064		[ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA
23065	};
23066
23067	function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) {
23068
23069		if ( blending === NoBlending ) {
23070
23071			if ( currentBlendingEnabled === true ) {
23072
23073				disable( gl.BLEND );
23074				currentBlendingEnabled = false;
23075
23076			}
23077
23078			return;
23079
23080		}
23081
23082		if ( currentBlendingEnabled === false ) {
23083
23084			enable( gl.BLEND );
23085			currentBlendingEnabled = true;
23086
23087		}
23088
23089		if ( blending !== CustomBlending ) {
23090
23091			if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
23092
23093				if ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {
23094
23095					gl.blendEquation( gl.FUNC_ADD );
23096
23097					currentBlendEquation = AddEquation;
23098					currentBlendEquationAlpha = AddEquation;
23099
23100				}
23101
23102				if ( premultipliedAlpha ) {
23103
23104					switch ( blending ) {
23105
23106						case NormalBlending:
23107							gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
23108							break;
23109
23110						case AdditiveBlending:
23111							gl.blendFunc( gl.ONE, gl.ONE );
23112							break;
23113
23114						case SubtractiveBlending:
23115							gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
23116							break;
23117
23118						case MultiplyBlending:
23119							gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
23120							break;
23121
23122						default:
23123							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
23124							break;
23125
23126					}
23127
23128				} else {
23129
23130					switch ( blending ) {
23131
23132						case NormalBlending:
23133							gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
23134							break;
23135
23136						case AdditiveBlending:
23137							gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
23138							break;
23139
23140						case SubtractiveBlending:
23141							gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
23142							break;
23143
23144						case MultiplyBlending:
23145							gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
23146							break;
23147
23148						default:
23149							console.error( 'THREE.WebGLState: Invalid blending: ', blending );
23150							break;
23151
23152					}
23153
23154				}
23155
23156				currentBlendSrc = null;
23157				currentBlendDst = null;
23158				currentBlendSrcAlpha = null;
23159				currentBlendDstAlpha = null;
23160				currentBlendColor.set( 0, 0, 0 );
23161				currentBlendAlpha = 0;
23162
23163				currentBlending = blending;
23164				currentPremultipledAlpha = premultipliedAlpha;
23165
23166			}
23167
23168			return;
23169
23170		}
23171
23172		// custom blending
23173
23174		blendEquationAlpha = blendEquationAlpha || blendEquation;
23175		blendSrcAlpha = blendSrcAlpha || blendSrc;
23176		blendDstAlpha = blendDstAlpha || blendDst;
23177
23178		if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
23179
23180			gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
23181
23182			currentBlendEquation = blendEquation;
23183			currentBlendEquationAlpha = blendEquationAlpha;
23184
23185		}
23186
23187		if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
23188
23189			gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
23190
23191			currentBlendSrc = blendSrc;
23192			currentBlendDst = blendDst;
23193			currentBlendSrcAlpha = blendSrcAlpha;
23194			currentBlendDstAlpha = blendDstAlpha;
23195
23196		}
23197
23198		if ( blendColor.equals( currentBlendColor ) === false || blendAlpha !== currentBlendAlpha ) {
23199
23200			gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha );
23201
23202			currentBlendColor.copy( blendColor );
23203			currentBlendAlpha = blendAlpha;
23204
23205		}
23206
23207		currentBlending = blending;
23208		currentPremultipledAlpha = false;
23209
23210	}
23211
23212	function setMaterial( material, frontFaceCW ) {
23213
23214		material.side === DoubleSide
23215			? disable( gl.CULL_FACE )
23216			: enable( gl.CULL_FACE );
23217
23218		let flipSided = ( material.side === BackSide );
23219		if ( frontFaceCW ) flipSided = ! flipSided;
23220
23221		setFlipSided( flipSided );
23222
23223		( material.blending === NormalBlending && material.transparent === false )
23224			? setBlending( NoBlending )
23225			: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha );
23226
23227		depthBuffer.setFunc( material.depthFunc );
23228		depthBuffer.setTest( material.depthTest );
23229		depthBuffer.setMask( material.depthWrite );
23230		colorBuffer.setMask( material.colorWrite );
23231
23232		const stencilWrite = material.stencilWrite;
23233		stencilBuffer.setTest( stencilWrite );
23234		if ( stencilWrite ) {
23235
23236			stencilBuffer.setMask( material.stencilWriteMask );
23237			stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
23238			stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
23239
23240		}
23241
23242		setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
23243
23244		material.alphaToCoverage === true
23245			? enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
23246			: disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
23247
23248	}
23249
23250	//
23251
23252	function setFlipSided( flipSided ) {
23253
23254		if ( currentFlipSided !== flipSided ) {
23255
23256			if ( flipSided ) {
23257
23258				gl.frontFace( gl.CW );
23259
23260			} else {
23261
23262				gl.frontFace( gl.CCW );
23263
23264			}
23265
23266			currentFlipSided = flipSided;
23267
23268		}
23269
23270	}
23271
23272	function setCullFace( cullFace ) {
23273
23274		if ( cullFace !== CullFaceNone ) {
23275
23276			enable( gl.CULL_FACE );
23277
23278			if ( cullFace !== currentCullFace ) {
23279
23280				if ( cullFace === CullFaceBack ) {
23281
23282					gl.cullFace( gl.BACK );
23283
23284				} else if ( cullFace === CullFaceFront ) {
23285
23286					gl.cullFace( gl.FRONT );
23287
23288				} else {
23289
23290					gl.cullFace( gl.FRONT_AND_BACK );
23291
23292				}
23293
23294			}
23295
23296		} else {
23297
23298			disable( gl.CULL_FACE );
23299
23300		}
23301
23302		currentCullFace = cullFace;
23303
23304	}
23305
23306	function setLineWidth( width ) {
23307
23308		if ( width !== currentLineWidth ) {
23309
23310			if ( lineWidthAvailable ) gl.lineWidth( width );
23311
23312			currentLineWidth = width;
23313
23314		}
23315
23316	}
23317
23318	function setPolygonOffset( polygonOffset, factor, units ) {
23319
23320		if ( polygonOffset ) {
23321
23322			enable( gl.POLYGON_OFFSET_FILL );
23323
23324			if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
23325
23326				gl.polygonOffset( factor, units );
23327
23328				currentPolygonOffsetFactor = factor;
23329				currentPolygonOffsetUnits = units;
23330
23331			}
23332
23333		} else {
23334
23335			disable( gl.POLYGON_OFFSET_FILL );
23336
23337		}
23338
23339	}
23340
23341	function setScissorTest( scissorTest ) {
23342
23343		if ( scissorTest ) {
23344
23345			enable( gl.SCISSOR_TEST );
23346
23347		} else {
23348
23349			disable( gl.SCISSOR_TEST );
23350
23351		}
23352
23353	}
23354
23355	// texture
23356
23357	function activeTexture( webglSlot ) {
23358
23359		if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
23360
23361		if ( currentTextureSlot !== webglSlot ) {
23362
23363			gl.activeTexture( webglSlot );
23364			currentTextureSlot = webglSlot;
23365
23366		}
23367
23368	}
23369
23370	function bindTexture( webglType, webglTexture, webglSlot ) {
23371
23372		if ( webglSlot === undefined ) {
23373
23374			if ( currentTextureSlot === null ) {
23375
23376				webglSlot = gl.TEXTURE0 + maxTextures - 1;
23377
23378			} else {
23379
23380				webglSlot = currentTextureSlot;
23381
23382			}
23383
23384		}
23385
23386		let boundTexture = currentBoundTextures[ webglSlot ];
23387
23388		if ( boundTexture === undefined ) {
23389
23390			boundTexture = { type: undefined, texture: undefined };
23391			currentBoundTextures[ webglSlot ] = boundTexture;
23392
23393		}
23394
23395		if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
23396
23397			if ( currentTextureSlot !== webglSlot ) {
23398
23399				gl.activeTexture( webglSlot );
23400				currentTextureSlot = webglSlot;
23401
23402			}
23403
23404			gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
23405
23406			boundTexture.type = webglType;
23407			boundTexture.texture = webglTexture;
23408
23409		}
23410
23411	}
23412
23413	function unbindTexture() {
23414
23415		const boundTexture = currentBoundTextures[ currentTextureSlot ];
23416
23417		if ( boundTexture !== undefined && boundTexture.type !== undefined ) {
23418
23419			gl.bindTexture( boundTexture.type, null );
23420
23421			boundTexture.type = undefined;
23422			boundTexture.texture = undefined;
23423
23424		}
23425
23426	}
23427
23428	function compressedTexImage2D() {
23429
23430		try {
23431
23432			gl.compressedTexImage2D.apply( gl, arguments );
23433
23434		} catch ( error ) {
23435
23436			console.error( 'THREE.WebGLState:', error );
23437
23438		}
23439
23440	}
23441
23442	function compressedTexImage3D() {
23443
23444		try {
23445
23446			gl.compressedTexImage3D.apply( gl, arguments );
23447
23448		} catch ( error ) {
23449
23450			console.error( 'THREE.WebGLState:', error );
23451
23452		}
23453
23454	}
23455
23456	function texSubImage2D() {
23457
23458		try {
23459
23460			gl.texSubImage2D.apply( gl, arguments );
23461
23462		} catch ( error ) {
23463
23464			console.error( 'THREE.WebGLState:', error );
23465
23466		}
23467
23468	}
23469
23470	function texSubImage3D() {
23471
23472		try {
23473
23474			gl.texSubImage3D.apply( gl, arguments );
23475
23476		} catch ( error ) {
23477
23478			console.error( 'THREE.WebGLState:', error );
23479
23480		}
23481
23482	}
23483
23484	function compressedTexSubImage2D() {
23485
23486		try {
23487
23488			gl.compressedTexSubImage2D.apply( gl, arguments );
23489
23490		} catch ( error ) {
23491
23492			console.error( 'THREE.WebGLState:', error );
23493
23494		}
23495
23496	}
23497
23498	function compressedTexSubImage3D() {
23499
23500		try {
23501
23502			gl.compressedTexSubImage3D.apply( gl, arguments );
23503
23504		} catch ( error ) {
23505
23506			console.error( 'THREE.WebGLState:', error );
23507
23508		}
23509
23510	}
23511
23512	function texStorage2D() {
23513
23514		try {
23515
23516			gl.texStorage2D.apply( gl, arguments );
23517
23518		} catch ( error ) {
23519
23520			console.error( 'THREE.WebGLState:', error );
23521
23522		}
23523
23524	}
23525
23526	function texStorage3D() {
23527
23528		try {
23529
23530			gl.texStorage3D.apply( gl, arguments );
23531
23532		} catch ( error ) {
23533
23534			console.error( 'THREE.WebGLState:', error );
23535
23536		}
23537
23538	}
23539
23540	function texImage2D() {
23541
23542		try {
23543
23544			gl.texImage2D.apply( gl, arguments );
23545
23546		} catch ( error ) {
23547
23548			console.error( 'THREE.WebGLState:', error );
23549
23550		}
23551
23552	}
23553
23554	function texImage3D() {
23555
23556		try {
23557
23558			gl.texImage3D.apply( gl, arguments );
23559
23560		} catch ( error ) {
23561
23562			console.error( 'THREE.WebGLState:', error );
23563
23564		}
23565
23566	}
23567
23568	//
23569
23570	function scissor( scissor ) {
23571
23572		if ( currentScissor.equals( scissor ) === false ) {
23573
23574			gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
23575			currentScissor.copy( scissor );
23576
23577		}
23578
23579	}
23580
23581	function viewport( viewport ) {
23582
23583		if ( currentViewport.equals( viewport ) === false ) {
23584
23585			gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
23586			currentViewport.copy( viewport );
23587
23588		}
23589
23590	}
23591
23592	function updateUBOMapping( uniformsGroup, program ) {
23593
23594		let mapping = uboProgramMap.get( program );
23595
23596		if ( mapping === undefined ) {
23597
23598			mapping = new WeakMap();
23599
23600			uboProgramMap.set( program, mapping );
23601
23602		}
23603
23604		let blockIndex = mapping.get( uniformsGroup );
23605
23606		if ( blockIndex === undefined ) {
23607
23608			blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name );
23609
23610			mapping.set( uniformsGroup, blockIndex );
23611
23612		}
23613
23614	}
23615
23616	function uniformBlockBinding( uniformsGroup, program ) {
23617
23618		const mapping = uboProgramMap.get( program );
23619		const blockIndex = mapping.get( uniformsGroup );
23620
23621		if ( uboBindings.get( program ) !== blockIndex ) {
23622
23623			// bind shader specific block index to global block point
23624			gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex );
23625
23626			uboBindings.set( program, blockIndex );
23627
23628		}
23629
23630	}
23631
23632	//
23633
23634	function reset() {
23635
23636		// reset state
23637
23638		gl.disable( gl.BLEND );
23639		gl.disable( gl.CULL_FACE );
23640		gl.disable( gl.DEPTH_TEST );
23641		gl.disable( gl.POLYGON_OFFSET_FILL );
23642		gl.disable( gl.SCISSOR_TEST );
23643		gl.disable( gl.STENCIL_TEST );
23644		gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
23645
23646		gl.blendEquation( gl.FUNC_ADD );
23647		gl.blendFunc( gl.ONE, gl.ZERO );
23648		gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO );
23649		gl.blendColor( 0, 0, 0, 0 );
23650
23651		gl.colorMask( true, true, true, true );
23652		gl.clearColor( 0, 0, 0, 0 );
23653
23654		gl.depthMask( true );
23655		gl.depthFunc( gl.LESS );
23656		gl.clearDepth( 1 );
23657
23658		gl.stencilMask( 0xffffffff );
23659		gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff );
23660		gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP );
23661		gl.clearStencil( 0 );
23662
23663		gl.cullFace( gl.BACK );
23664		gl.frontFace( gl.CCW );
23665
23666		gl.polygonOffset( 0, 0 );
23667
23668		gl.activeTexture( gl.TEXTURE0 );
23669
23670		gl.bindFramebuffer( gl.FRAMEBUFFER, null );
vendor: 9,248 bytes, lines 23671-24014
23671		gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER, null );
23672		gl.bindFramebuffer( gl.READ_FRAMEBUFFER, null );
23673
23674		gl.useProgram( null );
23675
23676		gl.lineWidth( 1 );
23677
23678		gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height );
23679		gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height );
23680
23681		// reset internals
23682
23683		enabledCapabilities = {};
23684
23685		currentTextureSlot = null;
23686		currentBoundTextures = {};
23687
23688		currentBoundFramebuffers = {};
23689		currentDrawbuffers = new WeakMap();
23690		defaultDrawbuffers = [];
23691
23692		currentProgram = null;
23693
23694		currentBlendingEnabled = false;
23695		currentBlending = null;
23696		currentBlendEquation = null;
23697		currentBlendSrc = null;
23698		currentBlendDst = null;
23699		currentBlendEquationAlpha = null;
23700		currentBlendSrcAlpha = null;
23701		currentBlendDstAlpha = null;
23702		currentBlendColor = new Color( 0, 0, 0 );
23703		currentBlendAlpha = 0;
23704		currentPremultipledAlpha = false;
23705
23706		currentFlipSided = null;
23707		currentCullFace = null;
23708
23709		currentLineWidth = null;
23710
23711		currentPolygonOffsetFactor = null;
23712		currentPolygonOffsetUnits = null;
23713
23714		currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height );
23715		currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height );
23716
23717		colorBuffer.reset();
23718		depthBuffer.reset();
23719		stencilBuffer.reset();
23720
23721	}
23722
23723	return {
23724
23725		buffers: {
23726			color: colorBuffer,
23727			depth: depthBuffer,
23728			stencil: stencilBuffer
23729		},
23730
23731		enable: enable,
23732		disable: disable,
23733
23734		bindFramebuffer: bindFramebuffer,
23735		drawBuffers: drawBuffers,
23736
23737		useProgram: useProgram,
23738
23739		setBlending: setBlending,
23740		setMaterial: setMaterial,
23741
23742		setFlipSided: setFlipSided,
23743		setCullFace: setCullFace,
23744
23745		setLineWidth: setLineWidth,
23746		setPolygonOffset: setPolygonOffset,
23747
23748		setScissorTest: setScissorTest,
23749
23750		activeTexture: activeTexture,
23751		bindTexture: bindTexture,
23752		unbindTexture: unbindTexture,
23753		compressedTexImage2D: compressedTexImage2D,
23754		compressedTexImage3D: compressedTexImage3D,
23755		texImage2D: texImage2D,
23756		texImage3D: texImage3D,
23757
23758		updateUBOMapping: updateUBOMapping,
23759		uniformBlockBinding: uniformBlockBinding,
23760
23761		texStorage2D: texStorage2D,
23762		texStorage3D: texStorage3D,
23763		texSubImage2D: texSubImage2D,
23764		texSubImage3D: texSubImage3D,
23765		compressedTexSubImage2D: compressedTexSubImage2D,
23766		compressedTexSubImage3D: compressedTexSubImage3D,
23767
23768		scissor: scissor,
23769		viewport: viewport,
23770
23771		reset: reset
23772
23773	};
23774
23775}
23776
23777function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
23778
23779	const multisampledRTTExt = extensions.has( 'WEBGL_multisampled_render_to_texture' ) ? extensions.get( 'WEBGL_multisampled_render_to_texture' ) : null;
23780	const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test( navigator.userAgent );
23781
23782	const _imageDimensions = new Vector2();
23783	const _videoTextures = new WeakMap();
23784	let _canvas;
23785
23786	const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source
23787
23788	// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
23789	// also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
23790	// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
23791
23792	let useOffscreenCanvas = false;
23793
23794	try {
23795
23796		useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
23797			// eslint-disable-next-line compat/compat
23798			&& ( new OffscreenCanvas( 1, 1 ).getContext( '2d' ) ) !== null;
23799
23800	} catch ( err ) {
23801
23802		// Ignore any errors
23803
23804	}
23805
23806	function createCanvas( width, height ) {
23807
23808		// Use OffscreenCanvas when available. Specially needed in web workers
23809
23810		return useOffscreenCanvas ?
23811			// eslint-disable-next-line compat/compat
23812			new OffscreenCanvas( width, height ) : createElementNS( 'canvas' );
23813
23814	}
23815
23816	function resizeImage( image, needsNewCanvas, maxSize ) {
23817
23818		let scale = 1;
23819
23820		const dimensions = getDimensions( image );
23821
23822		// handle case if texture exceeds max size
23823
23824		if ( dimensions.width > maxSize || dimensions.height > maxSize ) {
23825
23826			scale = maxSize / Math.max( dimensions.width, dimensions.height );
23827
23828		}
23829
23830		// only perform resize if necessary
23831
23832		if ( scale < 1 ) {
23833
23834			// only perform resize for certain image types
23835
23836			if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
23837				( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
23838				( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ||
23839				( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) ) {
23840
23841				const width = Math.floor( scale * dimensions.width );
23842				const height = Math.floor( scale * dimensions.height );
23843
23844				if ( _canvas === undefined ) _canvas = createCanvas( width, height );
23845
23846				// cube textures can't reuse the same canvas
23847
23848				const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
23849
23850				canvas.width = width;
23851				canvas.height = height;
23852
23853				const context = canvas.getContext( '2d' );
23854				context.drawImage( image, 0, 0, width, height );
23855
23856				console.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + dimensions.width + 'x' + dimensions.height + ') to (' + width + 'x' + height + ').' );
23857
23858				return canvas;
23859
23860			} else {
23861
23862				if ( 'data' in image ) {
23863
23864					console.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + dimensions.width + 'x' + dimensions.height + ').' );
23865
23866				}
23867
23868				return image;
23869
23870			}
23871
23872		}
23873
23874		return image;
23875
23876	}
23877
23878	function textureNeedsGenerateMipmaps( texture ) {
23879
23880		return texture.generateMipmaps && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
23881
23882	}
23883
23884	function generateMipmap( target ) {
23885
23886		_gl.generateMipmap( target );
23887
23888	}
23889
23890	function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) {
23891
23892		if ( internalFormatName !== null ) {
23893
23894			if ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];
23895
23896			console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' );
23897
23898		}
23899
23900		let internalFormat = glFormat;
23901
23902		if ( glFormat === _gl.RED ) {
23903
23904			if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F;
23905			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F;
23906			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8;
23907
23908		}
23909
23910		if ( glFormat === _gl.RED_INTEGER ) {
23911
23912			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI;
23913			if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI;
23914			if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI;
23915			if ( glType === _gl.BYTE ) internalFormat = _gl.R8I;
23916			if ( glType === _gl.SHORT ) internalFormat = _gl.R16I;
23917			if ( glType === _gl.INT ) internalFormat = _gl.R32I;
23918
23919		}
23920
23921		if ( glFormat === _gl.RG ) {
23922
23923			if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F;
23924			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F;
23925			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8;
23926
23927		}
23928
23929		if ( glFormat === _gl.RG_INTEGER ) {
23930
23931			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8UI;
23932			if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RG16UI;
23933			if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RG32UI;
23934			if ( glType === _gl.BYTE ) internalFormat = _gl.RG8I;
23935			if ( glType === _gl.SHORT ) internalFormat = _gl.RG16I;
23936			if ( glType === _gl.INT ) internalFormat = _gl.RG32I;
23937
23938		}
23939
23940		if ( glFormat === _gl.RGB ) {
23941
23942			if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5;
23943
23944		}
23945
23946		if ( glFormat === _gl.RGBA ) {
23947
23948			const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace );
23949
23950			if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F;
23951			if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F;
23952			if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8;
23953			if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4;
23954			if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1;
23955
23956		}
23957
23958		if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F ||
23959			internalFormat === _gl.RG16F || internalFormat === _gl.RG32F ||
23960			internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) {
23961
23962			extensions.get( 'EXT_color_buffer_float' );
23963
23964		}
23965
23966		return internalFormat;
23967
23968	}
23969
23970	function getInternalDepthFormat( useStencil, depthType ) {
23971
23972		let glInternalFormat;
23973		if ( useStencil ) {
23974
23975			if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) {
23976
23977				glInternalFormat = _gl.DEPTH24_STENCIL8;
23978
23979			} else if ( depthType === FloatType ) {
23980
23981				glInternalFormat = _gl.DEPTH32F_STENCIL8;
23982
23983			} else if ( depthType === UnsignedShortType ) {
23984
23985				glInternalFormat = _gl.DEPTH24_STENCIL8;
23986				console.warn( 'DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.' );
23987
23988			}
23989
23990		} else {
23991
23992			if ( depthType === null || depthType === UnsignedIntType || depthType === UnsignedInt248Type ) {
23993
23994				glInternalFormat = _gl.DEPTH_COMPONENT24;
23995
23996			} else if ( depthType === FloatType ) {
23997
23998				glInternalFormat = _gl.DEPTH_COMPONENT32F;
23999
24000			} else if ( depthType === UnsignedShortType ) {
24001
24002				glInternalFormat = _gl.DEPTH_COMPONENT16;
24003
24004			}
24005
24006		}
24007
24008		return glInternalFormat;
24009
24010	}
24011
24012	function getMipLevels( texture, image ) {
24013
24014		if ( textureNeedsGenerateMipmaps( texture ) === true || ( texture.is
vendor: 10,305 bytes, lines 24014-24401
24014FramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) ) {
24015
24016			return Math.log2( Math.max( image.width, image.height ) ) + 1;
24017
24018		} else if ( texture.mipmaps !== undefined && texture.mipmaps.length > 0 ) {
24019
24020			// user-defined mipmaps
24021
24022			return texture.mipmaps.length;
24023
24024		} else if ( texture.isCompressedTexture && Array.isArray( texture.image ) ) {
24025
24026			return image.mipmaps.length;
24027
24028		} else {
24029
24030			// texture without mipmaps (only base level)
24031
24032			return 1;
24033
24034		}
24035
24036	}
24037
24038	//
24039
24040	function onTextureDispose( event ) {
24041
24042		const texture = event.target;
24043
24044		texture.removeEventListener( 'dispose', onTextureDispose );
24045
24046		deallocateTexture( texture );
24047
24048		if ( texture.isVideoTexture ) {
24049
24050			_videoTextures.delete( texture );
24051
24052		}
24053
24054	}
24055
24056	function onRenderTargetDispose( event ) {
24057
24058		const renderTarget = event.target;
24059
24060		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
24061
24062		deallocateRenderTarget( renderTarget );
24063
24064	}
24065
24066	//
24067
24068	function deallocateTexture( texture ) {
24069
24070		const textureProperties = properties.get( texture );
24071
24072		if ( textureProperties.__webglInit === undefined ) return;
24073
24074		// check if it's necessary to remove the WebGLTexture object
24075
24076		const source = texture.source;
24077		const webglTextures = _sources.get( source );
24078
24079		if ( webglTextures ) {
24080
24081			const webglTexture = webglTextures[ textureProperties.__cacheKey ];
24082			webglTexture.usedTimes --;
24083
24084			// the WebGLTexture object is not used anymore, remove it
24085
24086			if ( webglTexture.usedTimes === 0 ) {
24087
24088				deleteTexture( texture );
24089
24090			}
24091
24092			// remove the weak map entry if no WebGLTexture uses the source anymore
24093
24094			if ( Object.keys( webglTextures ).length === 0 ) {
24095
24096				_sources.delete( source );
24097
24098			}
24099
24100		}
24101
24102		properties.remove( texture );
24103
24104	}
24105
24106	function deleteTexture( texture ) {
24107
24108		const textureProperties = properties.get( texture );
24109		_gl.deleteTexture( textureProperties.__webglTexture );
24110
24111		const source = texture.source;
24112		const webglTextures = _sources.get( source );
24113		delete webglTextures[ textureProperties.__cacheKey ];
24114
24115		info.memory.textures --;
24116
24117	}
24118
24119	function deallocateRenderTarget( renderTarget ) {
24120
24121		const renderTargetProperties = properties.get( renderTarget );
24122
24123		if ( renderTarget.depthTexture ) {
24124
24125			renderTarget.depthTexture.dispose();
24126
24127		}
24128
24129		if ( renderTarget.isWebGLCubeRenderTarget ) {
24130
24131			for ( let i = 0; i < 6; i ++ ) {
24132
24133				if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) {
24134
24135					for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] );
24136
24137				} else {
24138
24139					_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
24140
24141				}
24142
24143				if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
24144
24145			}
24146
24147		} else {
24148
24149			if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) {
24150
24151				for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] );
24152
24153			} else {
24154
24155				_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
24156
24157			}
24158
24159			if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
24160			if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
24161
24162			if ( renderTargetProperties.__webglColorRenderbuffer ) {
24163
24164				for ( let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i ++ ) {
24165
24166					if ( renderTargetProperties.__webglColorRenderbuffer[ i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[ i ] );
24167
24168				}
24169
24170			}
24171
24172			if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
24173
24174		}
24175
24176		const textures = renderTarget.textures;
24177
24178		for ( let i = 0, il = textures.length; i < il; i ++ ) {
24179
24180			const attachmentProperties = properties.get( textures[ i ] );
24181
24182			if ( attachmentProperties.__webglTexture ) {
24183
24184				_gl.deleteTexture( attachmentProperties.__webglTexture );
24185
24186				info.memory.textures --;
24187
24188			}
24189
24190			properties.remove( textures[ i ] );
24191
24192		}
24193
24194		properties.remove( renderTarget );
24195
24196	}
24197
24198	//
24199
24200	let textureUnits = 0;
24201
24202	function resetTextureUnits() {
24203
24204		textureUnits = 0;
24205
24206	}
24207
24208	function allocateTextureUnit() {
24209
24210		const textureUnit = textureUnits;
24211
24212		if ( textureUnit >= capabilities.maxTextures ) {
24213
24214			console.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
24215
24216		}
24217
24218		textureUnits += 1;
24219
24220		return textureUnit;
24221
24222	}
24223
24224	function getTextureCacheKey( texture ) {
24225
24226		const array = [];
24227
24228		array.push( texture.wrapS );
24229		array.push( texture.wrapT );
24230		array.push( texture.wrapR || 0 );
24231		array.push( texture.magFilter );
24232		array.push( texture.minFilter );
24233		array.push( texture.anisotropy );
24234		array.push( texture.internalFormat );
24235		array.push( texture.format );
24236		array.push( texture.type );
24237		array.push( texture.generateMipmaps );
24238		array.push( texture.premultiplyAlpha );
24239		array.push( texture.flipY );
24240		array.push( texture.unpackAlignment );
24241		array.push( texture.colorSpace );
24242
24243		return array.join();
24244
24245	}
24246
24247	//
24248
24249	function setTexture2D( texture, slot ) {
24250
24251		const textureProperties = properties.get( texture );
24252
24253		if ( texture.isVideoTexture ) updateVideoTexture( texture );
24254
24255		if ( texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version ) {
24256
24257			const image = texture.image;
24258
24259			if ( image === null ) {
24260
24261				console.warn( 'THREE.WebGLRenderer: Texture marked for update but no image data found.' );
24262
24263			} else if ( image.complete === false ) {
24264
24265				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
24266
24267			} else {
24268
24269				uploadTexture( textureProperties, texture, slot );
24270				return;
24271
24272			}
24273
24274		}
24275
24276		state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24277
24278	}
24279
24280	function setTexture2DArray( texture, slot ) {
24281
24282		const textureProperties = properties.get( texture );
24283
24284		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24285
24286			uploadTexture( textureProperties, texture, slot );
24287			return;
24288
24289		}
24290
24291		state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24292
24293	}
24294
24295	function setTexture3D( texture, slot ) {
24296
24297		const textureProperties = properties.get( texture );
24298
24299		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24300
24301			uploadTexture( textureProperties, texture, slot );
24302			return;
24303
24304		}
24305
24306		state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24307
24308	}
24309
24310	function setTextureCube( texture, slot ) {
24311
24312		const textureProperties = properties.get( texture );
24313
24314		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24315
24316			uploadCubeTexture( textureProperties, texture, slot );
24317			return;
24318
24319		}
24320
24321		state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24322
24323	}
24324
24325	const wrappingToGL = {
24326		[ RepeatWrapping ]: _gl.REPEAT,
24327		[ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE,
24328		[ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT
24329	};
24330
24331	const filterToGL = {
24332		[ NearestFilter ]: _gl.NEAREST,
24333		[ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST,
24334		[ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR,
24335
24336		[ LinearFilter ]: _gl.LINEAR,
24337		[ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST,
24338		[ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR
24339	};
24340
24341	const compareToGL = {
24342		[ NeverCompare ]: _gl.NEVER,
24343		[ AlwaysCompare ]: _gl.ALWAYS,
24344		[ LessCompare ]: _gl.LESS,
24345		[ LessEqualCompare ]: _gl.LEQUAL,
24346		[ EqualCompare ]: _gl.EQUAL,
24347		[ GreaterEqualCompare ]: _gl.GEQUAL,
24348		[ GreaterCompare ]: _gl.GREATER,
24349		[ NotEqualCompare ]: _gl.NOTEQUAL
24350	};
24351
24352	function setTextureParameters( textureType, texture ) {
24353
24354		if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false &&
24355			( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter ||
24356			texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ) ) {
24357
24358			console.warn( 'THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device.' );
24359
24360		}
24361
24362		_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] );
24363		_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] );
24364
24365		if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {
24366
24367			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] );
24368
24369		}
24370
24371		_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] );
24372		_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] );
24373
24374		if ( texture.compareFunction ) {
24375
24376			_gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE );
24377			_gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] );
24378
24379		}
24380
24381		if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) {
24382
24383			if ( texture.magFilter === NearestFilter ) return;
24384			if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return;
24385			if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension
24386
24387			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
24388
24389				const extension = extensions.get( 'EXT_texture_filter_anisotropic' );
24390				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
24391				properties.get( texture ).__currentAnisotropy = texture.anisotropy;
24392
24393			}
24394
24395		}
24396
24397	}
24398
24399	function initTexture( textureProperties, texture ) {
24400
24401		let forceUpload = false;
vendor: 5,128 bytes, lines 24402-24578
24402
24403		if ( textureProperties.__webglInit === undefined ) {
24404
24405			textureProperties.__webglInit = true;
24406
24407			texture.addEventListener( 'dispose', onTextureDispose );
24408
24409		}
24410
24411		// create Source <-> WebGLTextures mapping if necessary
24412
24413		const source = texture.source;
24414		let webglTextures = _sources.get( source );
24415
24416		if ( webglTextures === undefined ) {
24417
24418			webglTextures = {};
24419			_sources.set( source, webglTextures );
24420
24421		}
24422
24423		// check if there is already a WebGLTexture object for the given texture parameters
24424
24425		const textureCacheKey = getTextureCacheKey( texture );
24426
24427		if ( textureCacheKey !== textureProperties.__cacheKey ) {
24428
24429			// if not, create a new instance of WebGLTexture
24430
24431			if ( webglTextures[ textureCacheKey ] === undefined ) {
24432
24433				// create new entry
24434
24435				webglTextures[ textureCacheKey ] = {
24436					texture: _gl.createTexture(),
24437					usedTimes: 0
24438				};
24439
24440				info.memory.textures ++;
24441
24442				// when a new instance of WebGLTexture was created, a texture upload is required
24443				// even if the image contents are identical
24444
24445				forceUpload = true;
24446
24447			}
24448
24449			webglTextures[ textureCacheKey ].usedTimes ++;
24450
24451			// every time the texture cache key changes, it's necessary to check if an instance of
24452			// WebGLTexture can be deleted in order to avoid a memory leak.
24453
24454			const webglTexture = webglTextures[ textureProperties.__cacheKey ];
24455
24456			if ( webglTexture !== undefined ) {
24457
24458				webglTextures[ textureProperties.__cacheKey ].usedTimes --;
24459
24460				if ( webglTexture.usedTimes === 0 ) {
24461
24462					deleteTexture( texture );
24463
24464				}
24465
24466			}
24467
24468			// store references to cache key and WebGLTexture object
24469
24470			textureProperties.__cacheKey = textureCacheKey;
24471			textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture;
24472
24473		}
24474
24475		return forceUpload;
24476
24477	}
24478
24479	function uploadTexture( textureProperties, texture, slot ) {
24480
24481		let textureType = _gl.TEXTURE_2D;
24482
24483		if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY;
24484		if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D;
24485
24486		const forceUpload = initTexture( textureProperties, texture );
24487		const source = texture.source;
24488
24489		state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24490
24491		const sourceProperties = properties.get( source );
24492
24493		if ( source.version !== sourceProperties.__version || forceUpload === true ) {
24494
24495			state.activeTexture( _gl.TEXTURE0 + slot );
24496
24497			const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
24498			const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
24499			const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
24500
24501			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
24502			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
24503			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
24504			_gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
24505
24506			let image = resizeImage( texture.image, false, capabilities.maxTextureSize );
24507			image = verifyColorSpace( texture, image );
24508
24509			const glFormat = utils.convert( texture.format, texture.colorSpace );
24510
24511			const glType = utils.convert( texture.type );
24512			let glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture );
24513
24514			setTextureParameters( textureType, texture );
24515
24516			let mipmap;
24517			const mipmaps = texture.mipmaps;
24518
24519			const useTexStorage = ( texture.isVideoTexture !== true );
24520			const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
24521			const dataReady = source.dataReady;
24522			const levels = getMipLevels( texture, image );
24523
24524			if ( texture.isDepthTexture ) {
24525
24526				glInternalFormat = getInternalDepthFormat( texture.format === DepthStencilFormat, texture.type );
24527
24528				//
24529
24530				if ( allocateMemory ) {
24531
24532					if ( useTexStorage ) {
24533
24534						state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height );
24535
24536					} else {
24537
24538						state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
24539
24540					}
24541
24542				}
24543
24544			} else if ( texture.isDataTexture ) {
24545
24546				// use manually created mipmaps if available
24547				// if there are no manual mipmaps
24548				// set 0 level mipmap and then use GL to generate other mipmap levels
24549
24550				if ( mipmaps.length > 0 ) {
24551
24552					if ( useTexStorage && allocateMemory ) {
24553
24554						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
24555
24556					}
24557
24558					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24559
24560						mipmap = mipmaps[ i ];
24561
24562						if ( useTexStorage ) {
24563
24564							if ( dataReady ) {
24565
24566								state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
24567
24568							}
24569
24570						} else {
24571
24572							state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24573
24574						}
24575
24576					}
24577
24578					texture.generateMipmaps = false;
24579
24580				} else {
24581
24582					if ( useTexStorage ) {
24583
24584						if ( allocateMemory ) {
24585
24586							state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
24587
24588						}
24589
24590						if ( dataReady ) {
24591
24592							state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
24593
24594						}
24595
24596					} else {
24597
24598						state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
24599
24600					}
24601
24602				}
24603
24604			} else if ( texture.isCompressedTexture ) {
24605
24606				if ( texture.isCompressedArrayTexture ) {
24607
24608					if ( useTexStorage && allocateMemory ) {
24609
24610						state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth );
24611
24612					}
24613
24614					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24615
24616						mipmap = mipmaps[ i ];
24617
24618						if ( texture.format !== RGBAFormat ) {
24619
24620							if ( glFormat !== null ) {
24621
24622								if ( useTexStorage ) {
24623
24624									if ( dataReady ) {
24625
24626										if ( texture.layerUpdates.size > 0 ) {
24627
24628											for ( const layerIndex of texture.layerUpdates ) {
24629
24630												const layerSize = mipmap.width * mipmap.height;
24631												state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, mipmap.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ), 0, 0 );
24632
24633											}
24634
24635											texture.clearLayerUpdates();
24636
24637										} else {
24638
24639											state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 );
24640
24641										}
24642
24643									}
24644
24645								} else {
24646
24647									state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 );
24648
24649								}
24650
24651							} else {
24652
24653								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
24654
24655							}
24656
24657						} else {
24658
24659							if ( useTexStorage ) {
24660
24661								if ( dataReady ) {
24662
24663									state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data );
24664
24665								}
24666
24667							} else {
24668
24669								state.texImage3D( _gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data );
24670
24671							}
24672
24673						}
24674
24675					}
24676
24677				} else {
24678
24679					if ( useTexStorage && allocateMemory ) {
24680
24681						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
24682
24683					}
24684
24685					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24686
24687						mipmap = mipmaps[ i ];
24688
24689						if ( texture.format !== RGBAFormat ) {
24690
24691							if ( glFormat !== null ) {
24692
24693								if ( useTexStorage ) {
24694
24695									if ( dataReady ) {
24696
24697										state.compressedTexSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
24698
24699									}
24700
24701								} else {
24702
24703									state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24704
24705								}
24706
24707							} else {
24708
24709								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
24710
24711							}
24712
24713						} else {
24714
24715							if ( useTexStorage ) {
24716
24717								if ( dataReady ) {
24718
24719									state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
24720
24721								}
24722
24723							} else {
24724
24725								state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24726
24727							}
24728
24729						}
24730
24731					}
24732
24733				}
24734
24735			} else if ( texture.isDataArrayTexture ) {
24736
24737				if ( useTexStorage ) {
24738
24739					if ( allocateMemory ) {
24740
24741						state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth );
24742
24743					}
24744
24745					if ( dataReady ) {
24746
24747						if ( texture.layerUpdates.size > 0 ) {
24748
24749							// When type is GL_UNSIGNED_BYTE, each of these bytes is
24750							// interpreted as one color component, depending on format. When
24751							// type is one of GL_UNSIGNED_SHORT_5_6_5,
24752							// GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, each
24753							// unsigned value is interpreted as containing all the components
24754							// for a single pixel, with the color components arranged
24755							// according to format.
24756							//
24757							// See https://registry.khronos.org/OpenGL-Refpages/es1.1/xhtml/glTexImage2D.xml
24758							let texelSize;
24759							switch ( glType ) {
24760
24761								case _gl.UNSIGNED_BYTE:
24762									switch ( glFormat ) {
24763
24764										case _gl.ALPHA:
24765											texelSize = 1;
24766											break;
24767										case _gl.LUMINANCE:
24768											texelSize = 1;
24769											break;
24770										case _gl.LUMINANCE_ALPHA:
24771											texelSize = 2;
24772											break;
24773										case _gl.RGB:
24774											texelSize = 3;
24775											break;
24776										case _gl.RGBA:
24777											texelSize = 4;
24778											break;
24779
24780										default:
24781											throw new Error( `Unknown texel size for format ${glFormat}.` );
24782
24783									}
24784
24785									break;
24786
24787								case _gl.UNSIGNED_SHORT_4_4_4_4:
24788								case _gl.UNSIGNED_SHORT_5_5_5_1:
24789								case _gl.UNSIGNED_SHORT_5_6_5:
24790									texelSize = 1;
24791									break;
24792
24793								default:
24794									throw new Error( `Unknown texel size for type ${glType}.` );
24795
24796							}
24797
24798							const layerSize = image.width * image.height * texelSize;
24799
24800							for ( const layerIndex of texture.layerUpdates ) {
24801
24802								state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, image.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ) );
24803
24804							}
24805
24806							texture.clearLayerUpdates();
24807
24808						} else {
24809
24810							state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
24811
24812						}
24813
24814					}
24815
24816				} else {
24817
24818					state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
24819
24820				}
24821
24822			} else if ( texture.isData3DTexture ) {
24823
24824				if ( useTexStorage ) {
24825
24826					if ( allocateMemory ) {
24827
24828						state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth );
24829
24830					}
24831
24832					if ( dataReady ) {
24833
24834						state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
24835
24836					}
24837
24838				} else {
24839
24840					state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
24841
24842				}
24843
24844			}
vendor: 8,580 bytes, lines 24844-25191
24844 else if ( texture.isFramebufferTexture ) {
24845
24846				if ( allocateMemory ) {
24847
24848					if ( useTexStorage ) {
24849
24850						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
24851
24852					} else {
24853
24854						let width = image.width, height = image.height;
24855
24856						for ( let i = 0; i < levels; i ++ ) {
24857
24858							state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null );
24859
24860							width >>= 1;
24861							height >>= 1;
24862
24863						}
24864
24865					}
24866
24867				}
24868
24869			} else {
24870
24871				// regular Texture (image, video, canvas)
24872
24873				// use manually created mipmaps if available
24874				// if there are no manual mipmaps
24875				// set 0 level mipmap and then use GL to generate other mipmap levels
24876
24877				if ( mipmaps.length > 0 ) {
24878
24879					if ( useTexStorage && allocateMemory ) {
24880
24881						const dimensions = getDimensions( mipmaps[ 0 ] );
24882
24883						state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height );
24884
24885					}
24886
24887					for ( let i = 0, il = mipmaps.length; i < il; i ++ ) {
24888
24889						mipmap = mipmaps[ i ];
24890
24891						if ( useTexStorage ) {
24892
24893							if ( dataReady ) {
24894
24895								state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap );
24896
24897							}
24898
24899						} else {
24900
24901							state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
24902
24903						}
24904
24905					}
24906
24907					texture.generateMipmaps = false;
24908
24909				} else {
24910
24911					if ( useTexStorage ) {
24912
24913						if ( allocateMemory ) {
24914
24915							const dimensions = getDimensions( image );
24916
24917							state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, dimensions.width, dimensions.height );
24918
24919						}
24920
24921						if ( dataReady ) {
24922
24923							state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image );
24924
24925						}
24926
24927					} else {
24928
24929						state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
24930
24931					}
24932
24933				}
24934
24935			}
24936
24937			if ( textureNeedsGenerateMipmaps( texture ) ) {
24938
24939				generateMipmap( textureType );
24940
24941			}
24942
24943			sourceProperties.__version = source.version;
24944
24945			if ( texture.onUpdate ) texture.onUpdate( texture );
24946
24947		}
24948
24949		textureProperties.__version = texture.version;
24950
24951	}
24952
24953	function uploadCubeTexture( textureProperties, texture, slot ) {
24954
24955		if ( texture.image.length !== 6 ) return;
24956
24957		const forceUpload = initTexture( textureProperties, texture );
24958		const source = texture.source;
24959
24960		state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24961
24962		const sourceProperties = properties.get( source );
24963
24964		if ( source.version !== sourceProperties.__version || forceUpload === true ) {
24965
24966			state.activeTexture( _gl.TEXTURE0 + slot );
24967
24968			const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
24969			const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
24970			const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
24971
24972			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
24973			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
24974			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
24975			_gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
24976
24977			const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture );
24978			const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
24979
24980			const cubeImage = [];
24981
24982			for ( let i = 0; i < 6; i ++ ) {
24983
24984				if ( ! isCompressed && ! isDataTexture ) {
24985
24986					cubeImage[ i ] = resizeImage( texture.image[ i ], true, capabilities.maxCubemapSize );
24987
24988				} else {
24989
24990					cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
24991
24992				}
24993
24994				cubeImage[ i ] = verifyColorSpace( texture, cubeImage[ i ] );
24995
24996			}
24997
24998			const image = cubeImage[ 0 ],
24999				glFormat = utils.convert( texture.format, texture.colorSpace ),
25000				glType = utils.convert( texture.type ),
25001				glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
25002
25003			const useTexStorage = ( texture.isVideoTexture !== true );
25004			const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true );
25005			const dataReady = source.dataReady;
25006			let levels = getMipLevels( texture, image );
25007
25008			setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture );
25009
25010			let mipmaps;
25011
25012			if ( isCompressed ) {
25013
25014				if ( useTexStorage && allocateMemory ) {
25015
25016					state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height );
25017
25018				}
25019
25020				for ( let i = 0; i < 6; i ++ ) {
25021
25022					mipmaps = cubeImage[ i ].mipmaps;
25023
25024					for ( let j = 0; j < mipmaps.length; j ++ ) {
25025
25026						const mipmap = mipmaps[ j ];
25027
25028						if ( texture.format !== RGBAFormat ) {
25029
25030							if ( glFormat !== null ) {
25031
25032								if ( useTexStorage ) {
25033
25034									if ( dataReady ) {
25035
25036										state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
25037
25038									}
25039
25040								} else {
25041
25042									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
25043
25044								}
25045
25046							} else {
25047
25048								console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
25049
25050							}
25051
25052						} else {
25053
25054							if ( useTexStorage ) {
25055
25056								if ( dataReady ) {
25057
25058									state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
25059
25060								}
25061
25062							} else {
25063
25064								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
25065
25066							}
25067
25068						}
25069
25070					}
25071
25072				}
25073
25074			} else {
25075
25076				mipmaps = texture.mipmaps;
25077
25078				if ( useTexStorage && allocateMemory ) {
25079
25080					// TODO: Uniformly handle mipmap definitions
25081					// Normal textures and compressed cube textures define base level + mips with their mipmap array
25082					// Uncompressed cube textures use their mipmap array only for mips (no base level)
25083
25084					if ( mipmaps.length > 0 ) levels ++;
25085
25086					const dimensions = getDimensions( cubeImage[ 0 ] );
25087
25088					state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, dimensions.width, dimensions.height );
25089
25090				}
25091
25092				for ( let i = 0; i < 6; i ++ ) {
25093
25094					if ( isDataTexture ) {
25095
25096						if ( useTexStorage ) {
25097
25098							if ( dataReady ) {
25099
25100								state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[ i ].width, cubeImage[ i ].height, glFormat, glType, cubeImage[ i ].data );
25101
25102							}
25103
25104						} else {
25105
25106							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
25107
25108						}
25109
25110						for ( let j = 0; j < mipmaps.length; j ++ ) {
25111
25112							const mipmap = mipmaps[ j ];
25113							const mipmapImage = mipmap.image[ i ].image;
25114
25115							if ( useTexStorage ) {
25116
25117								if ( dataReady ) {
25118
25119									state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data );
25120
25121								}
25122
25123							} else {
25124
25125								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
25126
25127							}
25128
25129						}
25130
25131					} else {
25132
25133						if ( useTexStorage ) {
25134
25135							if ( dataReady ) {
25136
25137								state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[ i ] );
25138
25139							}
25140
25141						} else {
25142
25143							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
25144
25145						}
25146
25147						for ( let j = 0; j < mipmaps.length; j ++ ) {
25148
25149							const mipmap = mipmaps[ j ];
25150
25151							if ( useTexStorage ) {
25152
25153								if ( dataReady ) {
25154
25155									state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[ i ] );
25156
25157								}
25158
25159							} else {
25160
25161								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );
25162
25163							}
25164
25165						}
25166
25167					}
25168
25169				}
25170
25171			}
25172
25173			if ( textureNeedsGenerateMipmaps( texture ) ) {
25174
25175				// We assume images for cube map have the same size.
25176				generateMipmap( _gl.TEXTURE_CUBE_MAP );
25177
25178			}
25179
25180			sourceProperties.__version = source.version;
25181
25182			if ( texture.onUpdate ) texture.onUpdate( texture );
25183
25184		}
25185
25186		textureProperties.__version = texture.version;
25187
25188	}
25189
25190	// Render targets
25191
vendor: 10,068 bytes, lines 25192-25513
25192	// Setup storage for target texture and bind it to correct framebuffer
25193	function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) {
25194
25195		const glFormat = utils.convert( texture.format, texture.colorSpace );
25196		const glType = utils.convert( texture.type );
25197		const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
25198		const renderTargetProperties = properties.get( renderTarget );
25199
25200		if ( ! renderTargetProperties.__hasExternalTextures ) {
25201
25202			const width = Math.max( 1, renderTarget.width >> level );
25203			const height = Math.max( 1, renderTarget.height >> level );
25204
25205			if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) {
25206
25207				state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null );
25208
25209			} else {
25210
25211				state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null );
25212
25213			}
25214
25215		}
25216
25217		state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
25218
25219		if ( useMultisampledRTT( renderTarget ) ) {
25220
25221			multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) );
25222
25223		} else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) { // see #24753
25224
25225			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level );
25226
25227		}
25228
25229		state.bindFramebuffer( _gl.FRAMEBUFFER, null );
25230
25231	}
25232
25233	// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
25234	function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
25235
25236		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
25237
25238		if ( renderTarget.depthBuffer ) {
25239
25240			// retrieve the depth attachment types
25241			const depthTexture = renderTarget.depthTexture;
25242			const depthType = depthTexture && depthTexture.isDepthTexture ? depthTexture.type : null;
25243			const glInternalFormat = getInternalDepthFormat( renderTarget.stencilBuffer, depthType );
25244			const glAttachmentType = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT;
25245
25246			// set up the attachment
25247			const samples = getRenderTargetSamples( renderTarget );
25248			const isUseMultisampledRTT = useMultisampledRTT( renderTarget );
25249			if ( isUseMultisampledRTT ) {
25250
25251				multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25252
25253			} else if ( isMultisample ) {
25254
25255				_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25256
25257			} else {
25258
25259				_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
25260
25261			}
25262
25263			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, glAttachmentType, _gl.RENDERBUFFER, renderbuffer );
25264
25265		} else {
25266
25267			const textures = renderTarget.textures;
25268
25269			for ( let i = 0; i < textures.length; i ++ ) {
25270
25271				const texture = textures[ i ];
25272
25273				const glFormat = utils.convert( texture.format, texture.colorSpace );
25274				const glType = utils.convert( texture.type );
25275				const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
25276				const samples = getRenderTargetSamples( renderTarget );
25277
25278				if ( isMultisample && useMultisampledRTT( renderTarget ) === false ) {
25279
25280					_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25281
25282				} else if ( useMultisampledRTT( renderTarget ) ) {
25283
25284					multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25285
25286				} else {
25287
25288					_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
25289
25290				}
25291
25292			}
25293
25294		}
25295
25296		_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
25297
25298	}
25299
25300	// Setup resources for a Depth Texture for a FBO (needs an extension)
25301	function setupDepthTexture( framebuffer, renderTarget ) {
25302
25303		const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
25304		if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );
25305
25306		state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
25307
25308		if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
25309
25310			throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
25311
25312		}
25313
25314		// upload an empty depth texture with framebuffer size
25315		if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
25316				renderTarget.depthTexture.image.width !== renderTarget.width ||
25317				renderTarget.depthTexture.image.height !== renderTarget.height ) {
25318
25319			renderTarget.depthTexture.image.width = renderTarget.width;
25320			renderTarget.depthTexture.image.height = renderTarget.height;
25321			renderTarget.depthTexture.needsUpdate = true;
25322
25323		}
25324
25325		setTexture2D( renderTarget.depthTexture, 0 );
25326
25327		const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
25328		const samples = getRenderTargetSamples( renderTarget );
25329
25330		if ( renderTarget.depthTexture.format === DepthFormat ) {
25331
25332			if ( useMultisampledRTT( renderTarget ) ) {
25333
25334				multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
25335
25336			} else {
25337
25338				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
25339
25340			}
25341
25342		} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
25343
25344			if ( useMultisampledRTT( renderTarget ) ) {
25345
25346				multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
25347
25348			} else {
25349
25350				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
25351
25352			}
25353
25354		} else {
25355
25356			throw new Error( 'Unknown depthTexture format' );
25357
25358		}
25359
25360	}
25361
25362	// Setup GL resources for a non-texture depth buffer
25363	function setupDepthRenderbuffer( renderTarget ) {
25364
25365		const renderTargetProperties = properties.get( renderTarget );
25366		const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25367
25368		if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) {
25369
25370			if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );
25371
25372			setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
25373
25374		} else {
25375
25376			if ( isCube ) {
25377
25378				renderTargetProperties.__webglDepthbuffer = [];
25379
25380				for ( let i = 0; i < 6; i ++ ) {
25381
25382					state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
25383					renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
25384					setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );
25385
25386				}
25387
25388			} else {
25389
25390				state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25391				renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
25392				setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );
25393
25394			}
25395
25396		}
25397
25398		state.bindFramebuffer( _gl.FRAMEBUFFER, null );
25399
25400	}
25401
25402	// rebind framebuffer with external textures
25403	function rebindTextures( renderTarget, colorTexture, depthTexture ) {
25404
25405		const renderTargetProperties = properties.get( renderTarget );
25406
25407		if ( colorTexture !== undefined ) {
25408
25409			setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 );
25410
25411		}
25412
25413		if ( depthTexture !== undefined ) {
25414
25415			setupDepthRenderbuffer( renderTarget );
25416
25417		}
25418
25419	}
25420
25421	// Set up GL resources for the render target
25422	function setupRenderTarget( renderTarget ) {
25423
25424		const texture = renderTarget.texture;
25425
25426		const renderTargetProperties = properties.get( renderTarget );
25427		const textureProperties = properties.get( texture );
25428
25429		renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
25430
25431		const textures = renderTarget.textures;
25432
25433		const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25434		const isMultipleRenderTargets = ( textures.length > 1 );
25435
25436		if ( ! isMultipleRenderTargets ) {
25437
25438			if ( textureProperties.__webglTexture === undefined ) {
25439
25440				textureProperties.__webglTexture = _gl.createTexture();
25441
25442			}
25443
25444			textureProperties.__version = texture.version;
25445			info.memory.textures ++;
25446
25447		}
25448
25449		// Setup framebuffer
25450
25451		if ( isCube ) {
25452
25453			renderTargetProperties.__webglFramebuffer = [];
25454
25455			for ( let i = 0; i < 6; i ++ ) {
25456
25457				if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25458
25459					renderTargetProperties.__webglFramebuffer[ i ] = [];
25460
25461					for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25462
25463						renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer();
25464
25465					}
25466
25467				} else {
25468
25469					renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
25470
25471				}
25472
25473			}
25474
25475		} else {
25476
25477			if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25478
25479				renderTargetProperties.__webglFramebuffer = [];
25480
25481				for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25482
25483					renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer();
25484
25485				}
25486
25487			} else {
25488
25489				renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
25490
25491			}
25492
25493			if ( isMultipleRenderTargets ) {
25494
25495				for ( let i = 0, il = textures.length; i < il; i ++ ) {
25496
25497					const attachmentProperties = properties.get( textures[ i ] );
25498
25499					if ( attachmentProperties.__webglTexture === undefined ) {
25500
25501						attachmentProperties.__webglTexture = _gl.createTexture();
25502
25503						info.memory.textures ++;
25504
25505					}
25506
25507				}
25508
25509			}
25510
25511			if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) {
25512
25513				renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
vendor: 4,218 bytes, lines 25514-25660
25514				renderTargetProperties.__webglColorRenderbuffer = [];
25515
25516				state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25517
25518				for ( let i = 0; i < textures.length; i ++ ) {
25519
25520					const texture = textures[ i ];
25521					renderTargetProperties.__webglColorRenderbuffer[ i ] = _gl.createRenderbuffer();
25522
25523					_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25524
25525					const glFormat = utils.convert( texture.format, texture.colorSpace );
25526					const glType = utils.convert( texture.type );
25527					const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true );
25528					const samples = getRenderTargetSamples( renderTarget );
25529					_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25530
25531					_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25532
25533				}
25534
25535				_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
25536
25537				if ( renderTarget.depthBuffer ) {
25538
25539					renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
25540					setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );
25541
25542				}
25543
25544				state.bindFramebuffer( _gl.FRAMEBUFFER, null );
25545
25546			}
25547
25548		}
25549
25550		// Setup color buffer
25551
25552		if ( isCube ) {
25553
25554			state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
25555			setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture );
25556
25557			for ( let i = 0; i < 6; i ++ ) {
25558
25559				if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25560
25561					for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25562
25563						setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level );
25564
25565					}
25566
25567				} else {
25568
25569					setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 );
25570
25571				}
25572
25573			}
25574
25575			if ( textureNeedsGenerateMipmaps( texture ) ) {
25576
25577				generateMipmap( _gl.TEXTURE_CUBE_MAP );
25578
25579			}
25580
25581			state.unbindTexture();
25582
25583		} else if ( isMultipleRenderTargets ) {
25584
25585			for ( let i = 0, il = textures.length; i < il; i ++ ) {
25586
25587				const attachment = textures[ i ];
25588				const attachmentProperties = properties.get( attachment );
25589
25590				state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture );
25591				setTextureParameters( _gl.TEXTURE_2D, attachment );
25592				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 );
25593
25594				if ( textureNeedsGenerateMipmaps( attachment ) ) {
25595
25596					generateMipmap( _gl.TEXTURE_2D );
25597
25598				}
25599
25600			}
25601
25602			state.unbindTexture();
25603
25604		} else {
25605
25606			let glTextureType = _gl.TEXTURE_2D;
25607
25608			if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) {
25609
25610				glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY;
25611
25612			}
25613
25614			state.bindTexture( glTextureType, textureProperties.__webglTexture );
25615			setTextureParameters( glTextureType, texture );
25616
25617			if ( texture.mipmaps && texture.mipmaps.length > 0 ) {
25618
25619				for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25620
25621					setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level );
25622
25623				}
25624
25625			} else {
25626
25627				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 );
25628
25629			}
25630
25631			if ( textureNeedsGenerateMipmaps( texture ) ) {
25632
25633				generateMipmap( glTextureType );
25634
25635			}
25636
25637			state.unbindTexture();
25638
25639		}
25640
25641		// Setup depth and stencil buffers
25642
25643		if ( renderTarget.depthBuffer ) {
25644
25645			setupDepthRenderbuffer( renderTarget );
25646
25647		}
25648
25649	}
25650
25651	function updateRenderTargetMipmap( renderTarget ) {
25652
25653		const textures = renderTarget.textures;
25654
25655		for ( let i = 0, il = textures.length; i < il; i ++ ) {
25656
25657			const texture = textures[ i ];
25658
25659			if ( textureNeedsGenerateMipmaps( texture ) ) {
25660
vendor: 4,313 bytes, lines 25661-25781
25661				const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
25662				const webglTexture = properties.get( texture ).__webglTexture;
25663
25664				state.bindTexture( target, webglTexture );
25665				generateMipmap( target );
25666				state.unbindTexture();
25667
25668			}
25669
25670		}
25671
25672	}
25673
25674	const invalidationArrayRead = [];
25675	const invalidationArrayDraw = [];
25676
25677	function updateMultisampleRenderTarget( renderTarget ) {
25678
25679		if ( renderTarget.samples > 0 ) {
25680
25681			if ( useMultisampledRTT( renderTarget ) === false ) {
25682
25683				const textures = renderTarget.textures;
25684				const width = renderTarget.width;
25685				const height = renderTarget.height;
25686				let mask = _gl.COLOR_BUFFER_BIT;
25687				const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT;
25688				const renderTargetProperties = properties.get( renderTarget );
25689				const isMultipleRenderTargets = ( textures.length > 1 );
25690
25691				// If MRT we need to remove FBO attachments
25692				if ( isMultipleRenderTargets ) {
25693
25694					for ( let i = 0; i < textures.length; i ++ ) {
25695
25696						state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25697						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null );
25698
25699						state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25700						_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 );
25701
25702					}
25703
25704				}
25705
25706				state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25707				state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25708
25709				for ( let i = 0; i < textures.length; i ++ ) {
25710
25711					if ( renderTarget.resolveDepthBuffer ) {
25712
25713						if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT;
25714
25715						// resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799)
25716
25717						if ( renderTarget.stencilBuffer && renderTarget.resolveStencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT;
25718
25719					}
25720
25721					if ( isMultipleRenderTargets ) {
25722
25723						_gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25724
25725						const webglTexture = properties.get( textures[ i ] ).__webglTexture;
25726						_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 );
25727
25728					}
25729
25730					_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST );
25731
25732					if ( supportsInvalidateFramebuffer === true ) {
25733
25734						invalidationArrayRead.length = 0;
25735						invalidationArrayDraw.length = 0;
25736
25737						invalidationArrayRead.push( _gl.COLOR_ATTACHMENT0 + i );
25738
25739						if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false ) {
25740
25741							invalidationArrayRead.push( depthStyle );
25742							invalidationArrayDraw.push( depthStyle );
25743
25744							_gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, invalidationArrayDraw );
25745
25746						}
25747
25748						_gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArrayRead );
25749
25750					}
25751
25752				}
25753
25754				state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null );
25755				state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null );
25756
25757				// If MRT since pre-blit we removed the FBO we need to reconstruct the attachments
25758				if ( isMultipleRenderTargets ) {
25759
25760					for ( let i = 0; i < textures.length; i ++ ) {
25761
25762						state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25763						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] );
25764
25765						const webglTexture = properties.get( textures[ i ] ).__webglTexture;
25766
25767						state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25768						_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 );
25769
25770					}
25771
25772				}
25773
25774				state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25775
25776			} else {
25777
25778				if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false && supportsInvalidateFramebuffer ) {
25779
25780					const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT;
25781
vendor: 15,061 bytes, lines 25782-26325
25782					_gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] );
25783
25784				}
25785
25786			}
25787
25788		}
25789
25790	}
25791
25792	function getRenderTargetSamples( renderTarget ) {
25793
25794		return Math.min( capabilities.maxSamples, renderTarget.samples );
25795
25796	}
25797
25798	function useMultisampledRTT( renderTarget ) {
25799
25800		const renderTargetProperties = properties.get( renderTarget );
25801
25802		return renderTarget.samples > 0 && extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true && renderTargetProperties.__useRenderToTexture !== false;
25803
25804	}
25805
25806	function updateVideoTexture( texture ) {
25807
25808		const frame = info.render.frame;
25809
25810		// Check the last frame we updated the VideoTexture
25811
25812		if ( _videoTextures.get( texture ) !== frame ) {
25813
25814			_videoTextures.set( texture, frame );
25815			texture.update();
25816
25817		}
25818
25819	}
25820
25821	function verifyColorSpace( texture, image ) {
25822
25823		const colorSpace = texture.colorSpace;
25824		const format = texture.format;
25825		const type = texture.type;
25826
25827		if ( texture.isCompressedTexture === true || texture.isVideoTexture === true ) return image;
25828
25829		if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) {
25830
25831			// sRGB
25832
25833			if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) {
25834
25835				// in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format
25836
25837				if ( format !== RGBAFormat || type !== UnsignedByteType ) {
25838
25839					console.warn( 'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' );
25840
25841				}
25842
25843			} else {
25844
25845				console.error( 'THREE.WebGLTextures: Unsupported texture color space:', colorSpace );
25846
25847			}
25848
25849		}
25850
25851		return image;
25852
25853	}
25854
25855	function getDimensions( image ) {
25856
25857		if ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) {
25858
25859			// if intrinsic data are not available, fallback to width/height
25860
25861			_imageDimensions.width = image.naturalWidth || image.width;
25862			_imageDimensions.height = image.naturalHeight || image.height;
25863
25864		} else if ( typeof VideoFrame !== 'undefined' && image instanceof VideoFrame ) {
25865
25866			_imageDimensions.width = image.displayWidth;
25867			_imageDimensions.height = image.displayHeight;
25868
25869		} else {
25870
25871			_imageDimensions.width = image.width;
25872			_imageDimensions.height = image.height;
25873
25874		}
25875
25876		return _imageDimensions;
25877
25878	}
25879
25880	//
25881
25882	this.allocateTextureUnit = allocateTextureUnit;
25883	this.resetTextureUnits = resetTextureUnits;
25884
25885	this.setTexture2D = setTexture2D;
25886	this.setTexture2DArray = setTexture2DArray;
25887	this.setTexture3D = setTexture3D;
25888	this.setTextureCube = setTextureCube;
25889	this.rebindTextures = rebindTextures;
25890	this.setupRenderTarget = setupRenderTarget;
25891	this.updateRenderTargetMipmap = updateRenderTargetMipmap;
25892	this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
25893	this.setupDepthRenderbuffer = setupDepthRenderbuffer;
25894	this.setupFrameBufferTexture = setupFrameBufferTexture;
25895	this.useMultisampledRTT = useMultisampledRTT;
25896
25897}
25898
25899function WebGLUtils( gl, extensions ) {
25900
25901	function convert( p, colorSpace = NoColorSpace ) {
25902
25903		let extension;
25904
25905		const transfer = ColorManagement.getTransfer( colorSpace );
25906
25907		if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;
25908		if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;
25909		if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;
25910		if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV;
25911
25912		if ( p === ByteType ) return gl.BYTE;
25913		if ( p === ShortType ) return gl.SHORT;
25914		if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;
25915		if ( p === IntType ) return gl.INT;
25916		if ( p === UnsignedIntType ) return gl.UNSIGNED_INT;
25917		if ( p === FloatType ) return gl.FLOAT;
25918		if ( p === HalfFloatType ) return gl.HALF_FLOAT;
25919
25920		if ( p === AlphaFormat ) return gl.ALPHA;
25921		if ( p === RGBFormat ) return gl.RGB;
25922		if ( p === RGBAFormat ) return gl.RGBA;
25923		if ( p === LuminanceFormat ) return gl.LUMINANCE;
25924		if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;
25925		if ( p === DepthFormat ) return gl.DEPTH_COMPONENT;
25926		if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;
25927
25928		// WebGL2 formats.
25929
25930		if ( p === RedFormat ) return gl.RED;
25931		if ( p === RedIntegerFormat ) return gl.RED_INTEGER;
25932		if ( p === RGFormat ) return gl.RG;
25933		if ( p === RGIntegerFormat ) return gl.RG_INTEGER;
25934		if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER;
25935
25936		// S3TC
25937
25938		if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {
25939
25940			if ( transfer === SRGBTransfer ) {
25941
25942				extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' );
25943
25944				if ( extension !== null ) {
25945
25946					if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT;
25947					if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
25948					if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
25949					if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
25950
25951				} else {
25952
25953					return null;
25954
25955				}
25956
25957			} else {
25958
25959				extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
25960
25961				if ( extension !== null ) {
25962
25963					if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
25964					if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
25965					if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
25966					if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
25967
25968				} else {
25969
25970					return null;
25971
25972				}
25973
25974			}
25975
25976		}
25977
25978		// PVRTC
25979
25980		if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {
25981
25982			extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );
25983
25984			if ( extension !== null ) {
25985
25986				if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
25987				if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
25988				if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
25989				if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
25990
25991			} else {
25992
25993				return null;
25994
25995			}
25996
25997		}
25998
25999		// ETC
26000
26001		if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {
26002
26003			extension = extensions.get( 'WEBGL_compressed_texture_etc' );
26004
26005			if ( extension !== null ) {
26006
26007				if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
26008				if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
26009
26010			} else {
26011
26012				return null;
26013
26014			}
26015
26016		}
26017
26018		// ASTC
26019
26020		if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
26021			p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
26022			p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
26023			p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
26024			p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {
26025
26026			extension = extensions.get( 'WEBGL_compressed_texture_astc' );
26027
26028			if ( extension !== null ) {
26029
26030				if ( p === RGBA_ASTC_4x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
26031				if ( p === RGBA_ASTC_5x4_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
26032				if ( p === RGBA_ASTC_5x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR;
26033				if ( p === RGBA_ASTC_6x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR;
26034				if ( p === RGBA_ASTC_6x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR;
26035				if ( p === RGBA_ASTC_8x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR;
26036				if ( p === RGBA_ASTC_8x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR;
26037				if ( p === RGBA_ASTC_8x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR;
26038				if ( p === RGBA_ASTC_10x5_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR;
26039				if ( p === RGBA_ASTC_10x6_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR;
26040				if ( p === RGBA_ASTC_10x8_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR;
26041				if ( p === RGBA_ASTC_10x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR;
26042				if ( p === RGBA_ASTC_12x10_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR;
26043				if ( p === RGBA_ASTC_12x12_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR;
26044
26045			} else {
26046
26047				return null;
26048
26049			}
26050
26051		}
26052
26053		// BPTC
26054
26055		if ( p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format ) {
26056
26057			extension = extensions.get( 'EXT_texture_compression_bptc' );
26058
26059			if ( extension !== null ) {
26060
26061				if ( p === RGBA_BPTC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
26062				if ( p === RGB_BPTC_SIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;
26063				if ( p === RGB_BPTC_UNSIGNED_Format ) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
26064
26065			} else {
26066
26067				return null;
26068
26069			}
26070
26071		}
26072
26073		// RGTC
26074
26075		if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) {
26076
26077			extension = extensions.get( 'EXT_texture_compression_rgtc' );
26078
26079			if ( extension !== null ) {
26080
26081				if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT;
26082				if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT;
26083				if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT;
26084				if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
26085
26086			} else {
26087
26088				return null;
26089
26090			}
26091
26092		}
26093
26094		//
26095
26096		if ( p === UnsignedInt248Type ) return gl.UNSIGNED_INT_24_8;
26097
26098		// if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats)
26099
26100		return ( gl[ p ] !== undefined ) ? gl[ p ] : null;
26101
26102	}
26103
26104	return { convert: convert };
26105
26106}
26107
26108class ArrayCamera extends PerspectiveCamera {
26109
26110	constructor( array = [] ) {
26111
26112		super();
26113
26114		this.isArrayCamera = true;
26115
26116		this.cameras = array;
26117
26118	}
26119
26120}
26121
26122class Group extends Object3D {
26123
26124	constructor() {
26125
26126		super();
26127
26128		this.isGroup = true;
26129
26130		this.type = 'Group';
26131
26132	}
26133
26134}
26135
26136const _moveEvent = { type: 'move' };
26137
26138class WebXRController {
26139
26140	constructor() {
26141
26142		this._targetRay = null;
26143		this._grip = null;
26144		this._hand = null;
26145
26146	}
26147
26148	getHandSpace() {
26149
26150		if ( this._hand === null ) {
26151
26152			this._hand = new Group();
26153			this._hand.matrixAutoUpdate = false;
26154			this._hand.visible = false;
26155
26156			this._hand.joints = {};
26157			this._hand.inputState = { pinching: false };
26158
26159		}
26160
26161		return this._hand;
26162
26163	}
26164
26165	getTargetRaySpace() {
26166
26167		if ( this._targetRay === null ) {
26168
26169			this._targetRay = new Group();
26170			this._targetRay.matrixAutoUpdate = false;
26171			this._targetRay.visible = false;
26172			this._targetRay.hasLinearVelocity = false;
26173			this._targetRay.linearVelocity = new Vector3();
26174			this._targetRay.hasAngularVelocity = false;
26175			this._targetRay.angularVelocity = new Vector3();
26176
26177		}
26178
26179		return this._targetRay;
26180
26181	}
26182
26183	getGripSpace() {
26184
26185		if ( this._grip === null ) {
26186
26187			this._grip = new Group();
26188			this._grip.matrixAutoUpdate = false;
26189			this._grip.visible = false;
26190			this._grip.hasLinearVelocity = false;
26191			this._grip.linearVelocity = new Vector3();
26192			this._grip.hasAngularVelocity = false;
26193			this._grip.angularVelocity = new Vector3();
26194
26195		}
26196
26197		return this._grip;
26198
26199	}
26200
26201	dispatchEvent( event ) {
26202
26203		if ( this._targetRay !== null ) {
26204
26205			this._targetRay.dispatchEvent( event );
26206
26207		}
26208
26209		if ( this._grip !== null ) {
26210
26211			this._grip.dispatchEvent( event );
26212
26213		}
26214
26215		if ( this._hand !== null ) {
26216
26217			this._hand.dispatchEvent( event );
26218
26219		}
26220
26221		return this;
26222
26223	}
26224
26225	connect( inputSource ) {
26226
26227		if ( inputSource && inputSource.hand ) {
26228
26229			const hand = this._hand;
26230
26231			if ( hand ) {
26232
26233				for ( const inputjoint of inputSource.hand.values() ) {
26234
26235					// Initialize hand with joints when connected
26236					this._getHandJoint( hand, inputjoint );
26237
26238				}
26239
26240			}
26241
26242		}
26243
26244		this.dispatchEvent( { type: 'connected', data: inputSource } );
26245
26246		return this;
26247
26248	}
26249
26250	disconnect( inputSource ) {
26251
26252		this.dispatchEvent( { type: 'disconnected', data: inputSource } );
26253
26254		if ( this._targetRay !== null ) {
26255
26256			this._targetRay.visible = false;
26257
26258		}
26259
26260		if ( this._grip !== null ) {
26261
26262			this._grip.visible = false;
26263
26264		}
26265
26266		if ( this._hand !== null ) {
26267
26268			this._hand.visible = false;
26269
26270		}
26271
26272		return this;
26273
26274	}
26275
26276	update( inputSource, frame, referenceSpace ) {
26277
26278		let inputPose = null;
26279		let gripPose = null;
26280		let handPose = null;
26281
26282		const targetRay = this._targetRay;
26283		const grip = this._grip;
26284		const hand = this._hand;
26285
26286		if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
26287
26288			if ( hand && inputSource.hand ) {
26289
26290				handPose = true;
26291
26292				for ( const inputjoint of inputSource.hand.values() ) {
26293
26294					// Update the joints groups with the XRJoint poses
26295					const jointPose = frame.getJointPose( inputjoint, referenceSpace );
26296
26297					// The transform of this joint will be updated with the joint pose on each frame
26298					const joint = this._getHandJoint( hand, inputjoint );
26299
26300					if ( jointPose !== null ) {
26301
26302						joint.matrix.fromArray( jointPose.transform.matrix );
26303						joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
26304						joint.matrixWorldNeedsUpdate = true;
26305						joint.jointRadius = jointPose.radius;
26306
26307					}
26308
26309					joint.visible = jointPose !== null;
26310
26311				}
26312
26313				// Custom events
26314
26315				// Check pinchz
26316				const indexTip = hand.joints[ 'index-finger-tip' ];
26317				const thumbTip = hand.joints[ 'thumb-tip' ];
26318				const distance = indexTip.position.distanceTo( thumbTip.position );
26319
26320				const distanceToPinch = 0.02;
26321				const threshold = 0.005;
26322
26323				if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
26324
26325					hand.inputState.pinching = false;
vendor: 24,774 bytes, lines 26326-27448
26326					this.dispatchEvent( {
26327						type: 'pinchend',
26328						handedness: inputSource.handedness,
26329						target: this
26330					} );
26331
26332				} else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
26333
26334					hand.inputState.pinching = true;
26335					this.dispatchEvent( {
26336						type: 'pinchstart',
26337						handedness: inputSource.handedness,
26338						target: this
26339					} );
26340
26341				}
26342
26343			} else {
26344
26345				if ( grip !== null && inputSource.gripSpace ) {
26346
26347					gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
26348
26349					if ( gripPose !== null ) {
26350
26351						grip.matrix.fromArray( gripPose.transform.matrix );
26352						grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
26353						grip.matrixWorldNeedsUpdate = true;
26354
26355						if ( gripPose.linearVelocity ) {
26356
26357							grip.hasLinearVelocity = true;
26358							grip.linearVelocity.copy( gripPose.linearVelocity );
26359
26360						} else {
26361
26362							grip.hasLinearVelocity = false;
26363
26364						}
26365
26366						if ( gripPose.angularVelocity ) {
26367
26368							grip.hasAngularVelocity = true;
26369							grip.angularVelocity.copy( gripPose.angularVelocity );
26370
26371						} else {
26372
26373							grip.hasAngularVelocity = false;
26374
26375						}
26376
26377					}
26378
26379				}
26380
26381			}
26382
26383			if ( targetRay !== null ) {
26384
26385				inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
26386
26387				// Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it
26388				if ( inputPose === null && gripPose !== null ) {
26389
26390					inputPose = gripPose;
26391
26392				}
26393
26394				if ( inputPose !== null ) {
26395
26396					targetRay.matrix.fromArray( inputPose.transform.matrix );
26397					targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
26398					targetRay.matrixWorldNeedsUpdate = true;
26399
26400					if ( inputPose.linearVelocity ) {
26401
26402						targetRay.hasLinearVelocity = true;
26403						targetRay.linearVelocity.copy( inputPose.linearVelocity );
26404
26405					} else {
26406
26407						targetRay.hasLinearVelocity = false;
26408
26409					}
26410
26411					if ( inputPose.angularVelocity ) {
26412
26413						targetRay.hasAngularVelocity = true;
26414						targetRay.angularVelocity.copy( inputPose.angularVelocity );
26415
26416					} else {
26417
26418						targetRay.hasAngularVelocity = false;
26419
26420					}
26421
26422					this.dispatchEvent( _moveEvent );
26423
26424				}
26425
26426			}
26427
26428
26429		}
26430
26431		if ( targetRay !== null ) {
26432
26433			targetRay.visible = ( inputPose !== null );
26434
26435		}
26436
26437		if ( grip !== null ) {
26438
26439			grip.visible = ( gripPose !== null );
26440
26441		}
26442
26443		if ( hand !== null ) {
26444
26445			hand.visible = ( handPose !== null );
26446
26447		}
26448
26449		return this;
26450
26451	}
26452
26453	// private method
26454
26455	_getHandJoint( hand, inputjoint ) {
26456
26457		if ( hand.joints[ inputjoint.jointName ] === undefined ) {
26458
26459			const joint = new Group();
26460			joint.matrixAutoUpdate = false;
26461			joint.visible = false;
26462			hand.joints[ inputjoint.jointName ] = joint;
26463
26464			hand.add( joint );
26465
26466		}
26467
26468		return hand.joints[ inputjoint.jointName ];
26469
26470	}
26471
26472}
26473
26474const _occlusion_vertex = `
26475void main() {
26476
26477	gl_Position = vec4( position, 1.0 );
26478
26479}`;
26480
26481const _occlusion_fragment = `
26482uniform sampler2DArray depthColor;
26483uniform float depthWidth;
26484uniform float depthHeight;
26485
26486void main() {
26487
26488	vec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );
26489
26490	if ( coord.x >= 1.0 ) {
26491
26492		gl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;
26493
26494	} else {
26495
26496		gl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;
26497
26498	}
26499
26500}`;
26501
26502class WebXRDepthSensing {
26503
26504	constructor() {
26505
26506		this.texture = null;
26507		this.mesh = null;
26508
26509		this.depthNear = 0;
26510		this.depthFar = 0;
26511
26512	}
26513
26514	init( renderer, depthData, renderState ) {
26515
26516		if ( this.texture === null ) {
26517
26518			const texture = new Texture();
26519
26520			const texProps = renderer.properties.get( texture );
26521			texProps.__webglTexture = depthData.texture;
26522
26523			if ( ( depthData.depthNear != renderState.depthNear ) || ( depthData.depthFar != renderState.depthFar ) ) {
26524
26525				this.depthNear = depthData.depthNear;
26526				this.depthFar = depthData.depthFar;
26527
26528			}
26529
26530			this.texture = texture;
26531
26532		}
26533
26534	}
26535
26536	getMesh( cameraXR ) {
26537
26538		if ( this.texture !== null ) {
26539
26540			if ( this.mesh === null ) {
26541
26542				const viewport = cameraXR.cameras[ 0 ].viewport;
26543				const material = new ShaderMaterial( {
26544					vertexShader: _occlusion_vertex,
26545					fragmentShader: _occlusion_fragment,
26546					uniforms: {
26547						depthColor: { value: this.texture },
26548						depthWidth: { value: viewport.z },
26549						depthHeight: { value: viewport.w }
26550					}
26551				} );
26552
26553				this.mesh = new Mesh( new PlaneGeometry( 20, 20 ), material );
26554
26555			}
26556
26557		}
26558
26559		return this.mesh;
26560
26561	}
26562
26563	reset() {
26564
26565		this.texture = null;
26566		this.mesh = null;
26567
26568	}
26569
26570}
26571
26572class WebXRManager extends EventDispatcher {
26573
26574	constructor( renderer, gl ) {
26575
26576		super();
26577
26578		const scope = this;
26579
26580		let session = null;
26581
26582		let framebufferScaleFactor = 1.0;
26583
26584		let referenceSpace = null;
26585		let referenceSpaceType = 'local-floor';
26586		// Set default foveation to maximum.
26587		let foveation = 1.0;
26588		let customReferenceSpace = null;
26589
26590		let pose = null;
26591		let glBinding = null;
26592		let glProjLayer = null;
26593		let glBaseLayer = null;
26594		let xrFrame = null;
26595
26596		const depthSensing = new WebXRDepthSensing();
26597		const attributes = gl.getContextAttributes();
26598
26599		let initialRenderTarget = null;
26600		let newRenderTarget = null;
26601
26602		const controllers = [];
26603		const controllerInputSources = [];
26604
26605		const currentSize = new Vector2();
26606		let currentPixelRatio = null;
26607
26608		//
26609
26610		const cameraL = new PerspectiveCamera();
26611		cameraL.layers.enable( 1 );
26612		cameraL.viewport = new Vector4();
26613
26614		const cameraR = new PerspectiveCamera();
26615		cameraR.layers.enable( 2 );
26616		cameraR.viewport = new Vector4();
26617
26618		const cameras = [ cameraL, cameraR ];
26619
26620		const cameraXR = new ArrayCamera();
26621		cameraXR.layers.enable( 1 );
26622		cameraXR.layers.enable( 2 );
26623
26624		let _currentDepthNear = null;
26625		let _currentDepthFar = null;
26626
26627		//
26628
26629		this.cameraAutoUpdate = true;
26630		this.enabled = false;
26631
26632		this.isPresenting = false;
26633
26634		this.getController = function ( index ) {
26635
26636			let controller = controllers[ index ];
26637
26638			if ( controller === undefined ) {
26639
26640				controller = new WebXRController();
26641				controllers[ index ] = controller;
26642
26643			}
26644
26645			return controller.getTargetRaySpace();
26646
26647		};
26648
26649		this.getControllerGrip = function ( index ) {
26650
26651			let controller = controllers[ index ];
26652
26653			if ( controller === undefined ) {
26654
26655				controller = new WebXRController();
26656				controllers[ index ] = controller;
26657
26658			}
26659
26660			return controller.getGripSpace();
26661
26662		};
26663
26664		this.getHand = function ( index ) {
26665
26666			let controller = controllers[ index ];
26667
26668			if ( controller === undefined ) {
26669
26670				controller = new WebXRController();
26671				controllers[ index ] = controller;
26672
26673			}
26674
26675			return controller.getHandSpace();
26676
26677		};
26678
26679		//
26680
26681		function onSessionEvent( event ) {
26682
26683			const controllerIndex = controllerInputSources.indexOf( event.inputSource );
26684
26685			if ( controllerIndex === - 1 ) {
26686
26687				return;
26688
26689			}
26690
26691			const controller = controllers[ controllerIndex ];
26692
26693			if ( controller !== undefined ) {
26694
26695				controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace );
26696				controller.dispatchEvent( { type: event.type, data: event.inputSource } );
26697
26698			}
26699
26700		}
26701
26702		function onSessionEnd() {
26703
26704			session.removeEventListener( 'select', onSessionEvent );
26705			session.removeEventListener( 'selectstart', onSessionEvent );
26706			session.removeEventListener( 'selectend', onSessionEvent );
26707			session.removeEventListener( 'squeeze', onSessionEvent );
26708			session.removeEventListener( 'squeezestart', onSessionEvent );
26709			session.removeEventListener( 'squeezeend', onSessionEvent );
26710			session.removeEventListener( 'end', onSessionEnd );
26711			session.removeEventListener( 'inputsourceschange', onInputSourcesChange );
26712
26713			for ( let i = 0; i < controllers.length; i ++ ) {
26714
26715				const inputSource = controllerInputSources[ i ];
26716
26717				if ( inputSource === null ) continue;
26718
26719				controllerInputSources[ i ] = null;
26720
26721				controllers[ i ].disconnect( inputSource );
26722
26723			}
26724
26725			_currentDepthNear = null;
26726			_currentDepthFar = null;
26727
26728			depthSensing.reset();
26729
26730			// restore framebuffer/rendering state
26731
26732			renderer.setRenderTarget( initialRenderTarget );
26733
26734			glBaseLayer = null;
26735			glProjLayer = null;
26736			glBinding = null;
26737			session = null;
26738			newRenderTarget = null;
26739
26740			//
26741
26742			animation.stop();
26743
26744			scope.isPresenting = false;
26745
26746			renderer.setPixelRatio( currentPixelRatio );
26747			renderer.setSize( currentSize.width, currentSize.height, false );
26748
26749			scope.dispatchEvent( { type: 'sessionend' } );
26750
26751		}
26752
26753		this.setFramebufferScaleFactor = function ( value ) {
26754
26755			framebufferScaleFactor = value;
26756
26757			if ( scope.isPresenting === true ) {
26758
26759				console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
26760
26761			}
26762
26763		};
26764
26765		this.setReferenceSpaceType = function ( value ) {
26766
26767			referenceSpaceType = value;
26768
26769			if ( scope.isPresenting === true ) {
26770
26771				console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
26772
26773			}
26774
26775		};
26776
26777		this.getReferenceSpace = function () {
26778
26779			return customReferenceSpace || referenceSpace;
26780
26781		};
26782
26783		this.setReferenceSpace = function ( space ) {
26784
26785			customReferenceSpace = space;
26786
26787		};
26788
26789		this.getBaseLayer = function () {
26790
26791			return glProjLayer !== null ? glProjLayer : glBaseLayer;
26792
26793		};
26794
26795		this.getBinding = function () {
26796
26797			return glBinding;
26798
26799		};
26800
26801		this.getFrame = function () {
26802
26803			return xrFrame;
26804
26805		};
26806
26807		this.getSession = function () {
26808
26809			return session;
26810
26811		};
26812
26813		this.setSession = async function ( value ) {
26814
26815			session = value;
26816
26817			if ( session !== null ) {
26818
26819				initialRenderTarget = renderer.getRenderTarget();
26820
26821				session.addEventListener( 'select', onSessionEvent );
26822				session.addEventListener( 'selectstart', onSessionEvent );
26823				session.addEventListener( 'selectend', onSessionEvent );
26824				session.addEventListener( 'squeeze', onSessionEvent );
26825				session.addEventListener( 'squeezestart', onSessionEvent );
26826				session.addEventListener( 'squeezeend', onSessionEvent );
26827				session.addEventListener( 'end', onSessionEnd );
26828				session.addEventListener( 'inputsourceschange', onInputSourcesChange );
26829
26830				if ( attributes.xrCompatible !== true ) {
26831
26832					await gl.makeXRCompatible();
26833
26834				}
26835
26836				currentPixelRatio = renderer.getPixelRatio();
26837				renderer.getSize( currentSize );
26838
26839				if ( session.renderState.layers === undefined ) {
26840
26841					const layerInit = {
26842						antialias: attributes.antialias,
26843						alpha: true,
26844						depth: attributes.depth,
26845						stencil: attributes.stencil,
26846						framebufferScaleFactor: framebufferScaleFactor
26847					};
26848
26849					glBaseLayer = new XRWebGLLayer( session, gl, layerInit );
26850
26851					session.updateRenderState( { baseLayer: glBaseLayer } );
26852
26853					renderer.setPixelRatio( 1 );
26854					renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false );
26855
26856					newRenderTarget = new WebGLRenderTarget(
26857						glBaseLayer.framebufferWidth,
26858						glBaseLayer.framebufferHeight,
26859						{
26860							format: RGBAFormat,
26861							type: UnsignedByteType,
26862							colorSpace: renderer.outputColorSpace,
26863							stencilBuffer: attributes.stencil
26864						}
26865					);
26866
26867				} else {
26868
26869					let depthFormat = null;
26870					let depthType = null;
26871					let glDepthFormat = null;
26872
26873					if ( attributes.depth ) {
26874
26875						glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
26876						depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat;
26877						depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType;
26878
26879					}
26880
26881					const projectionlayerInit = {
26882						colorFormat: gl.RGBA8,
26883						depthFormat: glDepthFormat,
26884						scaleFactor: framebufferScaleFactor
26885					};
26886
26887					glBinding = new XRWebGLBinding( session, gl );
26888
26889					glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
26890
26891					session.updateRenderState( { layers: [ glProjLayer ] } );
26892
26893					renderer.setPixelRatio( 1 );
26894					renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight, false );
26895
26896					newRenderTarget = new WebGLRenderTarget(
26897						glProjLayer.textureWidth,
26898						glProjLayer.textureHeight,
26899						{
26900							format: RGBAFormat,
26901							type: UnsignedByteType,
26902							depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ),
26903							stencilBuffer: attributes.stencil,
26904							colorSpace: renderer.outputColorSpace,
26905							samples: attributes.antialias ? 4 : 0,
26906							resolveDepthBuffer: ( glProjLayer.ignoreDepthValues === false )
26907						} );
26908
26909				}
26910
26911				newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278
26912
26913				this.setFoveation( foveation );
26914
26915				customReferenceSpace = null;
26916				referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
26917
26918				animation.setContext( session );
26919				animation.start();
26920
26921				scope.isPresenting = true;
26922
26923				scope.dispatchEvent( { type: 'sessionstart' } );
26924
26925			}
26926
26927		};
26928
26929		this.getEnvironmentBlendMode = function () {
26930
26931			if ( session !== null ) {
26932
26933				return session.environmentBlendMode;
26934
26935			}
26936
26937		};
26938
26939		function onInputSourcesChange( event ) {
26940
26941			// Notify disconnected
26942
26943			for ( let i = 0; i < event.removed.length; i ++ ) {
26944
26945				const inputSource = event.removed[ i ];
26946				const index = controllerInputSources.indexOf( inputSource );
26947
26948				if ( index >= 0 ) {
26949
26950					controllerInputSources[ index ] = null;
26951					controllers[ index ].disconnect( inputSource );
26952
26953				}
26954
26955			}
26956
26957			// Notify connected
26958
26959			for ( let i = 0; i < event.added.length; i ++ ) {
26960
26961				const inputSource = event.added[ i ];
26962
26963				let controllerIndex = controllerInputSources.indexOf( inputSource );
26964
26965				if ( controllerIndex === - 1 ) {
26966
26967					// Assign input source a controller that currently has no input source
26968
26969					for ( let i = 0; i < controllers.length; i ++ ) {
26970
26971						if ( i >= controllerInputSources.length ) {
26972
26973							controllerInputSources.push( inputSource );
26974							controllerIndex = i;
26975							break;
26976
26977						} else if ( controllerInputSources[ i ] === null ) {
26978
26979							controllerInputSources[ i ] = inputSource;
26980							controllerIndex = i;
26981							break;
26982
26983						}
26984
26985					}
26986
26987					// If all controllers do currently receive input we ignore new ones
26988
26989					if ( controllerIndex === - 1 ) break;
26990
26991				}
26992
26993				const controller = controllers[ controllerIndex ];
26994
26995				if ( controller ) {
26996
26997					controller.connect( inputSource );
26998
26999				}
27000
27001			}
27002
27003		}
27004
27005		//
27006
27007		const cameraLPos = new Vector3();
27008		const cameraRPos = new Vector3();
27009
27010		/**
27011		 * Assumes 2 cameras that are parallel and share an X-axis, and that
27012		 * the cameras' projection and world matrices have already been set.
27013		 * And that near and far planes are identical for both cameras.
27014		 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
27015		 */
27016		function setProjectionFromUnion( camera, cameraL, cameraR ) {
27017
27018			cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
27019			cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
27020
27021			const ipd = cameraLPos.distanceTo( cameraRPos );
27022
27023			const projL = cameraL.projectionMatrix.elements;
27024			const projR = cameraR.projectionMatrix.elements;
27025
27026			// VR systems will have identical far and near planes, and
27027			// most likely identical top and bottom frustum extents.
27028			// Use the left camera for these values.
27029			const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
27030			const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
27031			const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
27032			const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
27033
27034			const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
27035			const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
27036			const left = near * leftFov;
27037			const right = near * rightFov;
27038
27039			// Calculate the new camera's position offset from the
27040			// left camera. xOffset should be roughly half `ipd`.
27041			const zOffset = ipd / ( - leftFov + rightFov );
27042			const xOffset = zOffset * - leftFov;
27043
27044			// TODO: Better way to apply this offset?
27045			cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
27046			camera.translateX( xOffset );
27047			camera.translateZ( zOffset );
27048			camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
27049			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
27050
27051			// Find the union of the frustum values of the cameras and scale
27052			// the values so that the near plane's position does not change in world space,
27053			// although must now be relative to the new union camera.
27054			const near2 = near + zOffset;
27055			const far2 = far + zOffset;
27056			const left2 = left - xOffset;
27057			const right2 = right + ( ipd - xOffset );
27058			const top2 = topFov * far / far2 * near2;
27059			const bottom2 = bottomFov * far / far2 * near2;
27060
27061			camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
27062			camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
27063
27064		}
27065
27066		function updateCamera( camera, parent ) {
27067
27068			if ( parent === null ) {
27069
27070				camera.matrixWorld.copy( camera.matrix );
27071
27072			} else {
27073
27074				camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
27075
27076			}
27077
27078			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
27079
27080		}
27081
27082		this.updateCamera = function ( camera ) {
27083
27084			if ( session === null ) return;
27085
27086			if ( depthSensing.texture !== null ) {
27087
27088				camera.near = depthSensing.depthNear;
27089				camera.far = depthSensing.depthFar;
27090
27091			}
27092
27093			cameraXR.near = cameraR.near = cameraL.near = camera.near;
27094			cameraXR.far = cameraR.far = cameraL.far = camera.far;
27095
27096			if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) {
27097
27098				// Note that the new renderState won't apply until the next frame. See #18320
27099
27100				session.updateRenderState( {
27101					depthNear: cameraXR.near,
27102					depthFar: cameraXR.far
27103				} );
27104
27105				_currentDepthNear = cameraXR.near;
27106				_currentDepthFar = cameraXR.far;
27107
27108				cameraL.near = _currentDepthNear;
27109				cameraL.far = _currentDepthFar;
27110				cameraR.near = _currentDepthNear;
27111				cameraR.far = _currentDepthFar;
27112
27113				cameraL.updateProjectionMatrix();
27114				cameraR.updateProjectionMatrix();
27115				camera.updateProjectionMatrix();
27116
27117			}
27118
27119			const parent = camera.parent;
27120			const cameras = cameraXR.cameras;
27121
27122			updateCamera( cameraXR, parent );
27123
27124			for ( let i = 0; i < cameras.length; i ++ ) {
27125
27126				updateCamera( cameras[ i ], parent );
27127
27128			}
27129
27130			// update projection matrix for proper view frustum culling
27131
27132			if ( cameras.length === 2 ) {
27133
27134				setProjectionFromUnion( cameraXR, cameraL, cameraR );
27135
27136			} else {
27137
27138				// assume single camera setup (AR)
27139
27140				cameraXR.projectionMatrix.copy( cameraL.projectionMatrix );
27141
27142			}
27143
27144			// update user camera and its children
27145
27146			updateUserCamera( camera, cameraXR, parent );
27147
27148		};
27149
27150		function updateUserCamera( camera, cameraXR, parent ) {
27151
27152			if ( parent === null ) {
27153
27154				camera.matrix.copy( cameraXR.matrixWorld );
27155
27156			} else {
27157
27158				camera.matrix.copy( parent.matrixWorld );
27159				camera.matrix.invert();
27160				camera.matrix.multiply( cameraXR.matrixWorld );
27161
27162			}
27163
27164			camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
27165			camera.updateMatrixWorld( true );
27166
27167			camera.projectionMatrix.copy( cameraXR.projectionMatrix );
27168			camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse );
27169
27170			if ( camera.isPerspectiveCamera ) {
27171
27172				camera.fov = RAD2DEG * 2 * Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] );
27173				camera.zoom = 1;
27174
27175			}
27176
27177		}
27178
27179		this.getCamera = function () {
27180
27181			return cameraXR;
27182
27183		};
27184
27185		this.getFoveation = function () {
27186
27187			if ( glProjLayer === null && glBaseLayer === null ) {
27188
27189				return undefined;
27190
27191			}
27192
27193			return foveation;
27194
27195		};
27196
27197		this.setFoveation = function ( value ) {
27198
27199			// 0 = no foveation = full resolution
27200			// 1 = maximum foveation = the edges render at lower resolution
27201
27202			foveation = value;
27203
27204			if ( glProjLayer !== null ) {
27205
27206				glProjLayer.fixedFoveation = value;
27207
27208			}
27209
27210			if ( glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined ) {
27211
27212				glBaseLayer.fixedFoveation = value;
27213
27214			}
27215
27216		};
27217
27218		this.hasDepthSensing = function () {
27219
27220			return depthSensing.texture !== null;
27221
27222		};
27223
27224		this.getDepthSensingMesh = function () {
27225
27226			return depthSensing.getMesh( cameraXR );
27227
27228		};
27229
27230		// Animation Loop
27231
27232		let onAnimationFrameCallback = null;
27233
27234		function onAnimationFrame( time, frame ) {
27235
27236			pose = frame.getViewerPose( customReferenceSpace || referenceSpace );
27237			xrFrame = frame;
27238
27239			if ( pose !== null ) {
27240
27241				const views = pose.views;
27242
27243				if ( glBaseLayer !== null ) {
27244
27245					renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer );
27246					renderer.setRenderTarget( newRenderTarget );
27247
27248				}
27249
27250				let cameraXRNeedsUpdate = false;
27251
27252				// check if it's necessary to rebuild cameraXR's camera list
27253
27254				if ( views.length !== cameraXR.cameras.length ) {
27255
27256					cameraXR.cameras.length = 0;
27257					cameraXRNeedsUpdate = true;
27258
27259				}
27260
27261				for ( let i = 0; i < views.length; i ++ ) {
27262
27263					const view = views[ i ];
27264
27265					let viewport = null;
27266
27267					if ( glBaseLayer !== null ) {
27268
27269						viewport = glBaseLayer.getViewport( view );
27270
27271					} else {
27272
27273						const glSubImage = glBinding.getViewSubImage( glProjLayer, view );
27274						viewport = glSubImage.viewport;
27275
27276						// For side-by-side projection, we only produce a single texture for both eyes.
27277						if ( i === 0 ) {
27278
27279							renderer.setRenderTargetTextures(
27280								newRenderTarget,
27281								glSubImage.colorTexture,
27282								glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture );
27283
27284							renderer.setRenderTarget( newRenderTarget );
27285
27286						}
27287
27288					}
27289
27290					let camera = cameras[ i ];
27291
27292					if ( camera === undefined ) {
27293
27294						camera = new PerspectiveCamera();
27295						camera.layers.enable( i );
27296						camera.viewport = new Vector4();
27297						cameras[ i ] = camera;
27298
27299					}
27300
27301					camera.matrix.fromArray( view.transform.matrix );
27302					camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
27303					camera.projectionMatrix.fromArray( view.projectionMatrix );
27304					camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
27305					camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
27306
27307					if ( i === 0 ) {
27308
27309						cameraXR.matrix.copy( camera.matrix );
27310						cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale );
27311
27312					}
27313
27314					if ( cameraXRNeedsUpdate === true ) {
27315
27316						cameraXR.cameras.push( camera );
27317
27318					}
27319
27320				}
27321
27322				//
27323
27324				const enabledFeatures = session.enabledFeatures;
27325
27326				if ( enabledFeatures && enabledFeatures.includes( 'depth-sensing' ) ) {
27327
27328					const depthData = glBinding.getDepthInformation( views[ 0 ] );
27329
27330					if ( depthData && depthData.isValid && depthData.texture ) {
27331
27332						depthSensing.init( renderer, depthData, session.renderState );
27333
27334					}
27335
27336				}
27337
27338			}
27339
27340			//
27341
27342			for ( let i = 0; i < controllers.length; i ++ ) {
27343
27344				const inputSource = controllerInputSources[ i ];
27345				const controller = controllers[ i ];
27346
27347				if ( inputSource !== null && controller !== undefined ) {
27348
27349					controller.update( inputSource, frame, customReferenceSpace || referenceSpace );
27350
27351				}
27352
27353			}
27354
27355			if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
27356
27357			if ( frame.detectedPlanes ) {
27358
27359				scope.dispatchEvent( { type: 'planesdetected', data: frame } );
27360
27361			}
27362
27363			xrFrame = null;
27364
27365		}
27366
27367		const animation = new WebGLAnimation();
27368
27369		animation.setAnimationLoop( onAnimationFrame );
27370
27371		this.setAnimationLoop = function ( callback ) {
27372
27373			onAnimationFrameCallback = callback;
27374
27375		};
27376
27377		this.dispose = function () {};
27378
27379	}
27380
27381}
27382
27383const _e1 = /*@__PURE__*/ new Euler();
27384const _m1 = /*@__PURE__*/ new Matrix4();
27385
27386function WebGLMaterials( renderer, properties ) {
27387
27388	function refreshTransformUniform( map, uniform ) {
27389
27390		if ( map.matrixAutoUpdate === true ) {
27391
27392			map.updateMatrix();
27393
27394		}
27395
27396		uniform.value.copy( map.matrix );
27397
27398	}
27399
27400	function refreshFogUniforms( uniforms, fog ) {
27401
27402		fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) );
27403
27404		if ( fog.isFog ) {
27405
27406			uniforms.fogNear.value = fog.near;
27407			uniforms.fogFar.value = fog.far;
27408
27409		} else if ( fog.isFogExp2 ) {
27410
27411			uniforms.fogDensity.value = fog.density;
27412
27413		}
27414
27415	}
27416
27417	function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
27418
27419		if ( material.isMeshBasicMaterial ) {
27420
27421			refreshUniformsCommon( uniforms, material );
27422
27423		} else if ( material.isMeshLambertMaterial ) {
27424
27425			refreshUniformsCommon( uniforms, material );
27426
27427		} else if ( material.isMeshToonMaterial ) {
27428
27429			refreshUniformsCommon( uniforms, material );
27430			refreshUniformsToon( uniforms, material );
27431
27432		} else if ( material.isMeshPhongMaterial ) {
27433
27434			refreshUniformsCommon( uniforms, material );
27435			refreshUniformsPhong( uniforms, material );
27436
27437		} else if ( material.isMeshStandardMaterial ) {
27438
27439			refreshUniformsCommon( uniforms, material );
27440			refreshUniformsStandard( uniforms, material );
27441
27442			if ( material.isMeshPhysicalMaterial ) {
27443
27444				refreshUniformsPhysical( uniforms, material, transmissionRenderTarget );
27445
27446			}
27447
27448		}
vendor: 14,159 bytes, lines 27448-28041
27448 else if ( material.isMeshMatcapMaterial ) {
27449
27450			refreshUniformsCommon( uniforms, material );
27451			refreshUniformsMatcap( uniforms, material );
27452
27453		} else if ( material.isMeshDepthMaterial ) {
27454
27455			refreshUniformsCommon( uniforms, material );
27456
27457		} else if ( material.isMeshDistanceMaterial ) {
27458
27459			refreshUniformsCommon( uniforms, material );
27460			refreshUniformsDistance( uniforms, material );
27461
27462		} else if ( material.isMeshNormalMaterial ) {
27463
27464			refreshUniformsCommon( uniforms, material );
27465
27466		} else if ( material.isLineBasicMaterial ) {
27467
27468			refreshUniformsLine( uniforms, material );
27469
27470			if ( material.isLineDashedMaterial ) {
27471
27472				refreshUniformsDash( uniforms, material );
27473
27474			}
27475
27476		} else if ( material.isPointsMaterial ) {
27477
27478			refreshUniformsPoints( uniforms, material, pixelRatio, height );
27479
27480		} else if ( material.isSpriteMaterial ) {
27481
27482			refreshUniformsSprites( uniforms, material );
27483
27484		} else if ( material.isShadowMaterial ) {
27485
27486			uniforms.color.value.copy( material.color );
27487			uniforms.opacity.value = material.opacity;
27488
27489		} else if ( material.isShaderMaterial ) {
27490
27491			material.uniformsNeedUpdate = false; // #15581
27492
27493		}
27494
27495	}
27496
27497	function refreshUniformsCommon( uniforms, material ) {
27498
27499		uniforms.opacity.value = material.opacity;
27500
27501		if ( material.color ) {
27502
27503			uniforms.diffuse.value.copy( material.color );
27504
27505		}
27506
27507		if ( material.emissive ) {
27508
27509			uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
27510
27511		}
27512
27513		if ( material.map ) {
27514
27515			uniforms.map.value = material.map;
27516
27517			refreshTransformUniform( material.map, uniforms.mapTransform );
27518
27519		}
27520
27521		if ( material.alphaMap ) {
27522
27523			uniforms.alphaMap.value = material.alphaMap;
27524
27525			refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27526
27527		}
27528
27529		if ( material.bumpMap ) {
27530
27531			uniforms.bumpMap.value = material.bumpMap;
27532
27533			refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform );
27534
27535			uniforms.bumpScale.value = material.bumpScale;
27536
27537			if ( material.side === BackSide ) {
27538
27539				uniforms.bumpScale.value *= - 1;
27540
27541			}
27542
27543		}
27544
27545		if ( material.normalMap ) {
27546
27547			uniforms.normalMap.value = material.normalMap;
27548
27549			refreshTransformUniform( material.normalMap, uniforms.normalMapTransform );
27550
27551			uniforms.normalScale.value.copy( material.normalScale );
27552
27553			if ( material.side === BackSide ) {
27554
27555				uniforms.normalScale.value.negate();
27556
27557			}
27558
27559		}
27560
27561		if ( material.displacementMap ) {
27562
27563			uniforms.displacementMap.value = material.displacementMap;
27564
27565			refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform );
27566
27567			uniforms.displacementScale.value = material.displacementScale;
27568			uniforms.displacementBias.value = material.displacementBias;
27569
27570		}
27571
27572		if ( material.emissiveMap ) {
27573
27574			uniforms.emissiveMap.value = material.emissiveMap;
27575
27576			refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform );
27577
27578		}
27579
27580		if ( material.specularMap ) {
27581
27582			uniforms.specularMap.value = material.specularMap;
27583
27584			refreshTransformUniform( material.specularMap, uniforms.specularMapTransform );
27585
27586		}
27587
27588		if ( material.alphaTest > 0 ) {
27589
27590			uniforms.alphaTest.value = material.alphaTest;
27591
27592		}
27593
27594		const materialProperties = properties.get( material );
27595
27596		const envMap = materialProperties.envMap;
27597		const envMapRotation = materialProperties.envMapRotation;
27598
27599		if ( envMap ) {
27600
27601			uniforms.envMap.value = envMap;
27602
27603			_e1.copy( envMapRotation );
27604
27605			// accommodate left-handed frame
27606			_e1.x *= - 1; _e1.y *= - 1; _e1.z *= - 1;
27607
27608			if ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) {
27609
27610				// environment maps which are not cube render targets or PMREMs follow a different convention
27611				_e1.y *= - 1;
27612				_e1.z *= - 1;
27613
27614			}
27615
27616			uniforms.envMapRotation.value.setFromMatrix4( _m1.makeRotationFromEuler( _e1 ) );
27617
27618			uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
27619
27620			uniforms.reflectivity.value = material.reflectivity;
27621			uniforms.ior.value = material.ior;
27622			uniforms.refractionRatio.value = material.refractionRatio;
27623
27624		}
27625
27626		if ( material.lightMap ) {
27627
27628			uniforms.lightMap.value = material.lightMap;
27629			uniforms.lightMapIntensity.value = material.lightMapIntensity;
27630
27631			refreshTransformUniform( material.lightMap, uniforms.lightMapTransform );
27632
27633		}
27634
27635		if ( material.aoMap ) {
27636
27637			uniforms.aoMap.value = material.aoMap;
27638			uniforms.aoMapIntensity.value = material.aoMapIntensity;
27639
27640			refreshTransformUniform( material.aoMap, uniforms.aoMapTransform );
27641
27642		}
27643
27644	}
27645
27646	function refreshUniformsLine( uniforms, material ) {
27647
27648		uniforms.diffuse.value.copy( material.color );
27649		uniforms.opacity.value = material.opacity;
27650
27651		if ( material.map ) {
27652
27653			uniforms.map.value = material.map;
27654
27655			refreshTransformUniform( material.map, uniforms.mapTransform );
27656
27657		}
27658
27659	}
27660
27661	function refreshUniformsDash( uniforms, material ) {
27662
27663		uniforms.dashSize.value = material.dashSize;
27664		uniforms.totalSize.value = material.dashSize + material.gapSize;
27665		uniforms.scale.value = material.scale;
27666
27667	}
27668
27669	function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
27670
27671		uniforms.diffuse.value.copy( material.color );
27672		uniforms.opacity.value = material.opacity;
27673		uniforms.size.value = material.size * pixelRatio;
27674		uniforms.scale.value = height * 0.5;
27675
27676		if ( material.map ) {
27677
27678			uniforms.map.value = material.map;
27679
27680			refreshTransformUniform( material.map, uniforms.uvTransform );
27681
27682		}
27683
27684		if ( material.alphaMap ) {
27685
27686			uniforms.alphaMap.value = material.alphaMap;
27687
27688			refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27689
27690		}
27691
27692		if ( material.alphaTest > 0 ) {
27693
27694			uniforms.alphaTest.value = material.alphaTest;
27695
27696		}
27697
27698	}
27699
27700	function refreshUniformsSprites( uniforms, material ) {
27701
27702		uniforms.diffuse.value.copy( material.color );
27703		uniforms.opacity.value = material.opacity;
27704		uniforms.rotation.value = material.rotation;
27705
27706		if ( material.map ) {
27707
27708			uniforms.map.value = material.map;
27709
27710			refreshTransformUniform( material.map, uniforms.mapTransform );
27711
27712		}
27713
27714		if ( material.alphaMap ) {
27715
27716			uniforms.alphaMap.value = material.alphaMap;
27717
27718			refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27719
27720		}
27721
27722		if ( material.alphaTest > 0 ) {
27723
27724			uniforms.alphaTest.value = material.alphaTest;
27725
27726		}
27727
27728	}
27729
27730	function refreshUniformsPhong( uniforms, material ) {
27731
27732		uniforms.specular.value.copy( material.specular );
27733		uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
27734
27735	}
27736
27737	function refreshUniformsToon( uniforms, material ) {
27738
27739		if ( material.gradientMap ) {
27740
27741			uniforms.gradientMap.value = material.gradientMap;
27742
27743		}
27744
27745	}
27746
27747	function refreshUniformsStandard( uniforms, material ) {
27748
27749		uniforms.metalness.value = material.metalness;
27750
27751		if ( material.metalnessMap ) {
27752
27753			uniforms.metalnessMap.value = material.metalnessMap;
27754
27755			refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform );
27756
27757		}
27758
27759		uniforms.roughness.value = material.roughness;
27760
27761		if ( material.roughnessMap ) {
27762
27763			uniforms.roughnessMap.value = material.roughnessMap;
27764
27765			refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform );
27766
27767		}
27768
27769		if ( material.envMap ) {
27770
27771			//uniforms.envMap.value = material.envMap; // part of uniforms common
27772
27773			uniforms.envMapIntensity.value = material.envMapIntensity;
27774
27775		}
27776
27777	}
27778
27779	function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) {
27780
27781		uniforms.ior.value = material.ior; // also part of uniforms common
27782
27783		if ( material.sheen > 0 ) {
27784
27785			uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen );
27786
27787			uniforms.sheenRoughness.value = material.sheenRoughness;
27788
27789			if ( material.sheenColorMap ) {
27790
27791				uniforms.sheenColorMap.value = material.sheenColorMap;
27792
27793				refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform );
27794
27795			}
27796
27797			if ( material.sheenRoughnessMap ) {
27798
27799				uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap;
27800
27801				refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform );
27802
27803			}
27804
27805		}
27806
27807		if ( material.clearcoat > 0 ) {
27808
27809			uniforms.clearcoat.value = material.clearcoat;
27810			uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
27811
27812			if ( material.clearcoatMap ) {
27813
27814				uniforms.clearcoatMap.value = material.clearcoatMap;
27815
27816				refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform );
27817
27818			}
27819
27820			if ( material.clearcoatRoughnessMap ) {
27821
27822				uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
27823
27824				refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform );
27825
27826			}
27827
27828			if ( material.clearcoatNormalMap ) {
27829
27830				uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
27831
27832				refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform );
27833
27834				uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
27835
27836				if ( material.side === BackSide ) {
27837
27838					uniforms.clearcoatNormalScale.value.negate();
27839
27840				}
27841
27842			}
27843
27844		}
27845
27846		if ( material.dispersion > 0 ) {
27847
27848			uniforms.dispersion.value = material.dispersion;
27849
27850		}
27851
27852		if ( material.iridescence > 0 ) {
27853
27854			uniforms.iridescence.value = material.iridescence;
27855			uniforms.iridescenceIOR.value = material.iridescenceIOR;
27856			uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ];
27857			uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ];
27858
27859			if ( material.iridescenceMap ) {
27860
27861				uniforms.iridescenceMap.value = material.iridescenceMap;
27862
27863				refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform );
27864
27865			}
27866
27867			if ( material.iridescenceThicknessMap ) {
27868
27869				uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap;
27870
27871				refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform );
27872
27873			}
27874
27875		}
27876
27877		if ( material.transmission > 0 ) {
27878
27879			uniforms.transmission.value = material.transmission;
27880			uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
27881			uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
27882
27883			if ( material.transmissionMap ) {
27884
27885				uniforms.transmissionMap.value = material.transmissionMap;
27886
27887				refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform );
27888
27889			}
27890
27891			uniforms.thickness.value = material.thickness;
27892
27893			if ( material.thicknessMap ) {
27894
27895				uniforms.thicknessMap.value = material.thicknessMap;
27896
27897				refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform );
27898
27899			}
27900
27901			uniforms.attenuationDistance.value = material.attenuationDistance;
27902			uniforms.attenuationColor.value.copy( material.attenuationColor );
27903
27904		}
27905
27906		if ( material.anisotropy > 0 ) {
27907
27908			uniforms.anisotropyVector.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) );
27909
27910			if ( material.anisotropyMap ) {
27911
27912				uniforms.anisotropyMap.value = material.anisotropyMap;
27913
27914				refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform );
27915
27916			}
27917
27918		}
27919
27920		uniforms.specularIntensity.value = material.specularIntensity;
27921		uniforms.specularColor.value.copy( material.specularColor );
27922
27923		if ( material.specularColorMap ) {
27924
27925			uniforms.specularColorMap.value = material.specularColorMap;
27926
27927			refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform );
27928
27929		}
27930
27931		if ( material.specularIntensityMap ) {
27932
27933			uniforms.specularIntensityMap.value = material.specularIntensityMap;
27934
27935			refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform );
27936
27937		}
27938
27939	}
27940
27941	function refreshUniformsMatcap( uniforms, material ) {
27942
27943		if ( material.matcap ) {
27944
27945			uniforms.matcap.value = material.matcap;
27946
27947		}
27948
27949	}
27950
27951	function refreshUniformsDistance( uniforms, material ) {
27952
27953		const light = properties.get( material ).light;
27954
27955		uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld );
27956		uniforms.nearDistance.value = light.shadow.camera.near;
27957		uniforms.farDistance.value = light.shadow.camera.far;
27958
27959	}
27960
27961	return {
27962		refreshFogUniforms: refreshFogUniforms,
27963		refreshMaterialUniforms: refreshMaterialUniforms
27964	};
27965
27966}
27967
27968function WebGLUniformsGroups( gl, info, capabilities, state ) {
27969
27970	let buffers = {};
27971	let updateList = {};
27972	let allocatedBindingPoints = [];
27973
27974	const maxBindingPoints = gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ); // binding points are global whereas block indices are per shader program
27975
27976	function bind( uniformsGroup, program ) {
27977
27978		const webglProgram = program.program;
27979		state.uniformBlockBinding( uniformsGroup, webglProgram );
27980
27981	}
27982
27983	function update( uniformsGroup, program ) {
27984
27985		let buffer = buffers[ uniformsGroup.id ];
27986
27987		if ( buffer === undefined ) {
27988
27989			prepareUniformsGroup( uniformsGroup );
27990
27991			buffer = createBuffer( uniformsGroup );
27992			buffers[ uniformsGroup.id ] = buffer;
27993
27994			uniformsGroup.addEventListener( 'dispose', onUniformsGroupsDispose );
27995
27996		}
27997
27998		// ensure to update the binding points/block indices mapping for this program
27999
28000		const webglProgram = program.program;
28001		state.updateUBOMapping( uniformsGroup, webglProgram );
28002
28003		// update UBO once per frame
28004
28005		const frame = info.render.frame;
28006
28007		if ( updateList[ uniformsGroup.id ] !== frame ) {
28008
28009			updateBufferData( uniformsGroup );
28010
28011			updateList[ uniformsGroup.id ] = frame;
28012
28013		}
28014
28015	}
28016
28017	function createBuffer( uniformsGroup ) {
28018
28019		// the setup of an UBO is independent of a particular shader program but global
28020
28021		const bindingPointIndex = allocateBindingPointIndex();
28022		uniformsGroup.__bindingPointIndex = bindingPointIndex;
28023
28024		const buffer = gl.createBuffer();
28025		const size = uniformsGroup.__size;
28026		const usage = uniformsGroup.usage;
28027
28028		gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
28029		gl.bufferData( gl.UNIFORM_BUFFER, size, usage );
28030		gl.bindBuffer( gl.UNIFORM_BUFFER, null );
28031		gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer );
28032
28033		return buffer;
28034
28035	}
28036
28037	function allocateBindingPointIndex() {
28038
28039		for ( let i = 0; i < maxBindingPoints; i ++ ) {
28040
28041			if ( allocatedBindingPoints.indexOf( i ) === - 
vendor: 6,630 bytes, lines 28041-28366
280411 ) {
28042
28043				allocatedBindingPoints.push( i );
28044				return i;
28045
28046			}
28047
28048		}
28049
28050		console.error( 'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' );
28051
28052		return 0;
28053
28054	}
28055
28056	function updateBufferData( uniformsGroup ) {
28057
28058		const buffer = buffers[ uniformsGroup.id ];
28059		const uniforms = uniformsGroup.uniforms;
28060		const cache = uniformsGroup.__cache;
28061
28062		gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
28063
28064		for ( let i = 0, il = uniforms.length; i < il; i ++ ) {
28065
28066			const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ];
28067
28068			for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) {
28069
28070				const uniform = uniformArray[ j ];
28071
28072				if ( hasUniformChanged( uniform, i, j, cache ) === true ) {
28073
28074					const offset = uniform.__offset;
28075
28076					const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
28077
28078					let arrayOffset = 0;
28079
28080					for ( let k = 0; k < values.length; k ++ ) {
28081
28082						const value = values[ k ];
28083
28084						const info = getUniformSize( value );
28085
28086						// TODO add integer and struct support
28087						if ( typeof value === 'number' || typeof value === 'boolean' ) {
28088
28089							uniform.__data[ 0 ] = value;
28090							gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data );
28091
28092						} else if ( value.isMatrix3 ) {
28093
28094							// manually converting 3x3 to 3x4
28095
28096							uniform.__data[ 0 ] = value.elements[ 0 ];
28097							uniform.__data[ 1 ] = value.elements[ 1 ];
28098							uniform.__data[ 2 ] = value.elements[ 2 ];
28099							uniform.__data[ 3 ] = 0;
28100							uniform.__data[ 4 ] = value.elements[ 3 ];
28101							uniform.__data[ 5 ] = value.elements[ 4 ];
28102							uniform.__data[ 6 ] = value.elements[ 5 ];
28103							uniform.__data[ 7 ] = 0;
28104							uniform.__data[ 8 ] = value.elements[ 6 ];
28105							uniform.__data[ 9 ] = value.elements[ 7 ];
28106							uniform.__data[ 10 ] = value.elements[ 8 ];
28107							uniform.__data[ 11 ] = 0;
28108
28109						} else {
28110
28111							value.toArray( uniform.__data, arrayOffset );
28112
28113							arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
28114
28115						}
28116
28117					}
28118
28119					gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data );
28120
28121				}
28122
28123			}
28124
28125		}
28126
28127		gl.bindBuffer( gl.UNIFORM_BUFFER, null );
28128
28129	}
28130
28131	function hasUniformChanged( uniform, index, indexArray, cache ) {
28132
28133		const value = uniform.value;
28134		const indexString = index + '_' + indexArray;
28135
28136		if ( cache[ indexString ] === undefined ) {
28137
28138			// cache entry does not exist so far
28139
28140			if ( typeof value === 'number' || typeof value === 'boolean' ) {
28141
28142				cache[ indexString ] = value;
28143
28144			} else {
28145
28146				cache[ indexString ] = value.clone();
28147
28148			}
28149
28150			return true;
28151
28152		} else {
28153
28154			const cachedObject = cache[ indexString ];
28155
28156			// compare current value with cached entry
28157
28158			if ( typeof value === 'number' || typeof value === 'boolean' ) {
28159
28160				if ( cachedObject !== value ) {
28161
28162					cache[ indexString ] = value;
28163					return true;
28164
28165				}
28166
28167			} else {
28168
28169				if ( cachedObject.equals( value ) === false ) {
28170
28171					cachedObject.copy( value );
28172					return true;
28173
28174				}
28175
28176			}
28177
28178		}
28179
28180		return false;
28181
28182	}
28183
28184	function prepareUniformsGroup( uniformsGroup ) {
28185
28186		// determine total buffer size according to the STD140 layout
28187		// Hint: STD140 is the only supported layout in WebGL 2
28188
28189		const uniforms = uniformsGroup.uniforms;
28190
28191		let offset = 0; // global buffer offset in bytes
28192		const chunkSize = 16; // size of a chunk in bytes
28193
28194		for ( let i = 0, l = uniforms.length; i < l; i ++ ) {
28195
28196			const uniformArray = Array.isArray( uniforms[ i ] ) ? uniforms[ i ] : [ uniforms[ i ] ];
28197
28198			for ( let j = 0, jl = uniformArray.length; j < jl; j ++ ) {
28199
28200				const uniform = uniformArray[ j ];
28201
28202				const values = Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
28203
28204				for ( let k = 0, kl = values.length; k < kl; k ++ ) {
28205
28206					const value = values[ k ];
28207
28208					const info = getUniformSize( value );
28209
28210					// Calculate the chunk offset
28211					const chunkOffsetUniform = offset % chunkSize;
28212
28213					// Check for chunk overflow
28214					if ( chunkOffsetUniform !== 0 && ( chunkSize - chunkOffsetUniform ) < info.boundary ) {
28215
28216						// Add padding and adjust offset
28217						offset += ( chunkSize - chunkOffsetUniform );
28218
28219					}
28220
28221					// the following two properties will be used for partial buffer updates
28222
28223					uniform.__data = new Float32Array( info.storage / Float32Array.BYTES_PER_ELEMENT );
28224					uniform.__offset = offset;
28225
28226
28227					// Update the global offset
28228					offset += info.storage;
28229
28230
28231				}
28232
28233			}
28234
28235		}
28236
28237		// ensure correct final padding
28238
28239		const chunkOffset = offset % chunkSize;
28240
28241		if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset );
28242
28243		//
28244
28245		uniformsGroup.__size = offset;
28246		uniformsGroup.__cache = {};
28247
28248		return this;
28249
28250	}
28251
28252	function getUniformSize( value ) {
28253
28254		const info = {
28255			boundary: 0, // bytes
28256			storage: 0 // bytes
28257		};
28258
28259		// determine sizes according to STD140
28260
28261		if ( typeof value === 'number' || typeof value === 'boolean' ) {
28262
28263			// float/int/bool
28264
28265			info.boundary = 4;
28266			info.storage = 4;
28267
28268		} else if ( value.isVector2 ) {
28269
28270			// vec2
28271
28272			info.boundary = 8;
28273			info.storage = 8;
28274
28275		} else if ( value.isVector3 || value.isColor ) {
28276
28277			// vec3
28278
28279			info.boundary = 16;
28280			info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes
28281
28282		} else if ( value.isVector4 ) {
28283
28284			// vec4
28285
28286			info.boundary = 16;
28287			info.storage = 16;
28288
28289		} else if ( value.isMatrix3 ) {
28290
28291			// mat3 (in STD140 a 3x3 matrix is represented as 3x4)
28292
28293			info.boundary = 48;
28294			info.storage = 48;
28295
28296		} else if ( value.isMatrix4 ) {
28297
28298			// mat4
28299
28300			info.boundary = 64;
28301			info.storage = 64;
28302
28303		} else if ( value.isTexture ) {
28304
28305			console.warn( 'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' );
28306
28307		} else {
28308
28309			console.warn( 'THREE.WebGLRenderer: Unsupported uniform value type.', value );
28310
28311		}
28312
28313		return info;
28314
28315	}
28316
28317	function onUniformsGroupsDispose( event ) {
28318
28319		const uniformsGroup = event.target;
28320
28321		uniformsGroup.removeEventListener( 'dispose', onUniformsGroupsDispose );
28322
28323		const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex );
28324		allocatedBindingPoints.splice( index, 1 );
28325
28326		gl.deleteBuffer( buffers[ uniformsGroup.id ] );
28327
28328		delete buffers[ uniformsGroup.id ];
28329		delete updateList[ uniformsGroup.id ];
28330
28331	}
28332
28333	function dispose() {
28334
28335		for ( const id in buffers ) {
28336
28337			gl.deleteBuffer( buffers[ id ] );
28338
28339		}
28340
28341		allocatedBindingPoints = [];
28342		buffers = {};
28343		updateList = {};
28344
28345	}
28346
28347	return {
28348
28349		bind: bind,
28350		update: update,
28351
28352		dispose: dispose
28353
28354	};
28355
28356}
28357
28358class WebGLRenderer {
28359
28360	constructor( parameters = {} ) {
28361
28362		const {
28363			canvas = createCanvasElement(),
28364			context = null,
28365			depth = true,
28366			stencil = 
vendor: 5,855 bytes, lines 28366-28604
28366false,
28367			alpha = false,
28368			antialias = false,
28369			premultipliedAlpha = true,
28370			preserveDrawingBuffer = false,
28371			powerPreference = 'default',
28372			failIfMajorPerformanceCaveat = false,
28373		} = parameters;
28374
28375		this.isWebGLRenderer = true;
28376
28377		let _alpha;
28378
28379		if ( context !== null ) {
28380
28381			if ( typeof WebGLRenderingContext !== 'undefined' && context instanceof WebGLRenderingContext ) {
28382
28383				throw new Error( 'THREE.WebGLRenderer: WebGL 1 is not supported since r163.' );
28384
28385			}
28386
28387			_alpha = context.getContextAttributes().alpha;
28388
28389		} else {
28390
28391			_alpha = alpha;
28392
28393		}
28394
28395		const uintClearColor = new Uint32Array( 4 );
28396		const intClearColor = new Int32Array( 4 );
28397
28398		let currentRenderList = null;
28399		let currentRenderState = null;
28400
28401		// render() can be called from within a callback triggered by another render.
28402		// We track this so that the nested render call gets its list and state isolated from the parent render call.
28403
28404		const renderListStack = [];
28405		const renderStateStack = [];
28406
28407		// public properties
28408
28409		this.domElement = canvas;
28410
28411		// Debug configuration container
28412		this.debug = {
28413
28414			/**
28415			 * Enables error checking and reporting when shader programs are being compiled
28416			 * @type {boolean}
28417			 */
28418			checkShaderErrors: true,
28419			/**
28420			 * Callback for custom error reporting.
28421			 * @type {?Function}
28422			 */
28423			onShaderError: null
28424		};
28425
28426		// clearing
28427
28428		this.autoClear = true;
28429		this.autoClearColor = true;
28430		this.autoClearDepth = true;
28431		this.autoClearStencil = true;
28432
28433		// scene graph
28434
28435		this.sortObjects = true;
28436
28437		// user-defined clipping
28438
28439		this.clippingPlanes = [];
28440		this.localClippingEnabled = false;
28441
28442		// physically based shading
28443
28444		this._outputColorSpace = SRGBColorSpace;
28445
28446		// tone mapping
28447
28448		this.toneMapping = NoToneMapping;
28449		this.toneMappingExposure = 1.0;
28450
28451		// internal properties
28452
28453		const _this = this;
28454
28455		let _isContextLost = false;
28456
28457		// internal state cache
28458
28459		let _currentActiveCubeFace = 0;
28460		let _currentActiveMipmapLevel = 0;
28461		let _currentRenderTarget = null;
28462		let _currentMaterialId = - 1;
28463
28464		let _currentCamera = null;
28465
28466		const _currentViewport = new Vector4();
28467		const _currentScissor = new Vector4();
28468		let _currentScissorTest = null;
28469
28470		const _currentClearColor = new Color( 0x000000 );
28471		let _currentClearAlpha = 0;
28472
28473		//
28474
28475		let _width = canvas.width;
28476		let _height = canvas.height;
28477
28478		let _pixelRatio = 1;
28479		let _opaqueSort = null;
28480		let _transparentSort = null;
28481
28482		const _viewport = new Vector4( 0, 0, _width, _height );
28483		const _scissor = new Vector4( 0, 0, _width, _height );
28484		let _scissorTest = false;
28485
28486		// frustum
28487
28488		const _frustum = new Frustum();
28489
28490		// clipping
28491
28492		let _clippingEnabled = false;
28493		let _localClippingEnabled = false;
28494
28495		// camera matrices cache
28496
28497		const _projScreenMatrix = new Matrix4();
28498
28499		const _vector3 = new Vector3();
28500
28501		const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
28502
28503		let _renderBackground = false;
28504
28505		function getTargetPixelRatio() {
28506
28507			return _currentRenderTarget === null ? _pixelRatio : 1;
28508
28509		}
28510
28511		// initialize
28512
28513		let _gl = context;
28514
28515		function getContext( contextName, contextAttributes ) {
28516
28517			return canvas.getContext( contextName, contextAttributes );
28518
28519		}
28520
28521		try {
28522
28523			const contextAttributes = {
28524				alpha: true,
28525				depth,
28526				stencil,
28527				antialias,
28528				premultipliedAlpha,
28529				preserveDrawingBuffer,
28530				powerPreference,
28531				failIfMajorPerformanceCaveat,
28532			};
28533
28534			// OffscreenCanvas does not have setAttribute, see #22811
28535			if ( 'setAttribute' in canvas ) canvas.setAttribute( 'data-engine', `three.js r${REVISION}` );
28536
28537			// event listeners must be registered before WebGL context is created, see #12753
28538			canvas.addEventListener( 'webglcontextlost', onContextLost, false );
28539			canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );
28540			canvas.addEventListener( 'webglcontextcreationerror', onContextCreationError, false );
28541
28542			if ( _gl === null ) {
28543
28544				const contextName = 'webgl2';
28545
28546				_gl = getContext( contextName, contextAttributes );
28547
28548				if ( _gl === null ) {
28549
28550					if ( getContext( contextName ) ) {
28551
28552						throw new Error( 'Error creating WebGL context with your selected attributes.' );
28553
28554					} else {
28555
28556						throw new Error( 'Error creating WebGL context.' );
28557
28558					}
28559
28560				}
28561
28562			}
28563
28564		} catch ( error ) {
28565
28566			console.error( 'THREE.WebGLRenderer: ' + error.message );
28567			throw error;
28568
28569		}
28570
28571		let extensions, capabilities, state, info;
28572		let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
28573		let programCache, materials, renderLists, renderStates, clipping, shadowMap;
28574
28575		let background, morphtargets, bufferRenderer, indexedBufferRenderer;
28576
28577		let utils, bindingStates, uniformsGroups;
28578
28579		function initGLContext() {
28580
28581			extensions = new WebGLExtensions( _gl );
28582			extensions.init();
28583
28584			utils = new WebGLUtils( _gl, extensions );
28585
28586			capabilities = new WebGLCapabilities( _gl, extensions, parameters, utils );
28587
28588			state = new WebGLState( _gl );
28589
28590			info = new WebGLInfo( _gl );
28591			properties = new WebGLProperties();
28592			textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
28593			cubemaps = new WebGLCubeMaps( _this );
28594			cubeuvmaps = new WebGLCubeUVMaps( _this );
28595			attributes = new WebGLAttributes( _gl );
28596			bindingStates = new WebGLBindingStates( _gl, attributes );
28597			geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
28598			objects = new WebGLObjects( _gl, geometries, attributes, info );
28599			morphtargets = new WebGLMorphtargets( _gl, capabilities, textures );
28600			clipping = new WebGLClipping( properties );
28601			programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );
28602			materials = new WebGLMaterials( _this, properties );
28603			renderLists = new WebGLRenderLists();
28604			renderStates = new WebGLRenderStates( extensions );
vendor: 16,914 bytes, lines 28605-29418
28605			background = new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha );
28606			shadowMap = new WebGLShadowMap( _this, objects, capabilities );
28607			uniformsGroups = new WebGLUniformsGroups( _gl, info, capabilities, state );
28608
28609			bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
28610			indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
28611
28612			info.programs = programCache.programs;
28613
28614			_this.capabilities = capabilities;
28615			_this.extensions = extensions;
28616			_this.properties = properties;
28617			_this.renderLists = renderLists;
28618			_this.shadowMap = shadowMap;
28619			_this.state = state;
28620			_this.info = info;
28621
28622		}
28623
28624		initGLContext();
28625
28626		// xr
28627
28628		const xr = new WebXRManager( _this, _gl );
28629
28630		this.xr = xr;
28631
28632		// API
28633
28634		this.getContext = function () {
28635
28636			return _gl;
28637
28638		};
28639
28640		this.getContextAttributes = function () {
28641
28642			return _gl.getContextAttributes();
28643
28644		};
28645
28646		this.forceContextLoss = function () {
28647
28648			const extension = extensions.get( 'WEBGL_lose_context' );
28649			if ( extension ) extension.loseContext();
28650
28651		};
28652
28653		this.forceContextRestore = function () {
28654
28655			const extension = extensions.get( 'WEBGL_lose_context' );
28656			if ( extension ) extension.restoreContext();
28657
28658		};
28659
28660		this.getPixelRatio = function () {
28661
28662			return _pixelRatio;
28663
28664		};
28665
28666		this.setPixelRatio = function ( value ) {
28667
28668			if ( value === undefined ) return;
28669
28670			_pixelRatio = value;
28671
28672			this.setSize( _width, _height, false );
28673
28674		};
28675
28676		this.getSize = function ( target ) {
28677
28678			return target.set( _width, _height );
28679
28680		};
28681
28682		this.setSize = function ( width, height, updateStyle = true ) {
28683
28684			if ( xr.isPresenting ) {
28685
28686				console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
28687				return;
28688
28689			}
28690
28691			_width = width;
28692			_height = height;
28693
28694			canvas.width = Math.floor( width * _pixelRatio );
28695			canvas.height = Math.floor( height * _pixelRatio );
28696
28697			if ( updateStyle === true ) {
28698
28699				canvas.style.width = width + 'px';
28700				canvas.style.height = height + 'px';
28701
28702			}
28703
28704			this.setViewport( 0, 0, width, height );
28705
28706		};
28707
28708		this.getDrawingBufferSize = function ( target ) {
28709
28710			return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
28711
28712		};
28713
28714		this.setDrawingBufferSize = function ( width, height, pixelRatio ) {
28715
28716			_width = width;
28717			_height = height;
28718
28719			_pixelRatio = pixelRatio;
28720
28721			canvas.width = Math.floor( width * pixelRatio );
28722			canvas.height = Math.floor( height * pixelRatio );
28723
28724			this.setViewport( 0, 0, width, height );
28725
28726		};
28727
28728		this.getCurrentViewport = function ( target ) {
28729
28730			return target.copy( _currentViewport );
28731
28732		};
28733
28734		this.getViewport = function ( target ) {
28735
28736			return target.copy( _viewport );
28737
28738		};
28739
28740		this.setViewport = function ( x, y, width, height ) {
28741
28742			if ( x.isVector4 ) {
28743
28744				_viewport.set( x.x, x.y, x.z, x.w );
28745
28746			} else {
28747
28748				_viewport.set( x, y, width, height );
28749
28750			}
28751
28752			state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).round() );
28753
28754		};
28755
28756		this.getScissor = function ( target ) {
28757
28758			return target.copy( _scissor );
28759
28760		};
28761
28762		this.setScissor = function ( x, y, width, height ) {
28763
28764			if ( x.isVector4 ) {
28765
28766				_scissor.set( x.x, x.y, x.z, x.w );
28767
28768			} else {
28769
28770				_scissor.set( x, y, width, height );
28771
28772			}
28773
28774			state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).round() );
28775
28776		};
28777
28778		this.getScissorTest = function () {
28779
28780			return _scissorTest;
28781
28782		};
28783
28784		this.setScissorTest = function ( boolean ) {
28785
28786			state.setScissorTest( _scissorTest = boolean );
28787
28788		};
28789
28790		this.setOpaqueSort = function ( method ) {
28791
28792			_opaqueSort = method;
28793
28794		};
28795
28796		this.setTransparentSort = function ( method ) {
28797
28798			_transparentSort = method;
28799
28800		};
28801
28802		// Clearing
28803
28804		this.getClearColor = function ( target ) {
28805
28806			return target.copy( background.getClearColor() );
28807
28808		};
28809
28810		this.setClearColor = function () {
28811
28812			background.setClearColor.apply( background, arguments );
28813
28814		};
28815
28816		this.getClearAlpha = function () {
28817
28818			return background.getClearAlpha();
28819
28820		};
28821
28822		this.setClearAlpha = function () {
28823
28824			background.setClearAlpha.apply( background, arguments );
28825
28826		};
28827
28828		this.clear = function ( color = true, depth = true, stencil = true ) {
28829
28830			let bits = 0;
28831
28832			if ( color ) {
28833
28834				// check if we're trying to clear an integer target
28835				let isIntegerFormat = false;
28836				if ( _currentRenderTarget !== null ) {
28837
28838					const targetFormat = _currentRenderTarget.texture.format;
28839					isIntegerFormat = targetFormat === RGBAIntegerFormat ||
28840						targetFormat === RGIntegerFormat ||
28841						targetFormat === RedIntegerFormat;
28842
28843				}
28844
28845				// use the appropriate clear functions to clear the target if it's a signed
28846				// or unsigned integer target
28847				if ( isIntegerFormat ) {
28848
28849					const targetType = _currentRenderTarget.texture.type;
28850					const isUnsignedType = targetType === UnsignedByteType ||
28851						targetType === UnsignedIntType ||
28852						targetType === UnsignedShortType ||
28853						targetType === UnsignedInt248Type ||
28854						targetType === UnsignedShort4444Type ||
28855						targetType === UnsignedShort5551Type;
28856
28857					const clearColor = background.getClearColor();
28858					const a = background.getClearAlpha();
28859					const r = clearColor.r;
28860					const g = clearColor.g;
28861					const b = clearColor.b;
28862
28863					if ( isUnsignedType ) {
28864
28865						uintClearColor[ 0 ] = r;
28866						uintClearColor[ 1 ] = g;
28867						uintClearColor[ 2 ] = b;
28868						uintClearColor[ 3 ] = a;
28869						_gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor );
28870
28871					} else {
28872
28873						intClearColor[ 0 ] = r;
28874						intClearColor[ 1 ] = g;
28875						intClearColor[ 2 ] = b;
28876						intClearColor[ 3 ] = a;
28877						_gl.clearBufferiv( _gl.COLOR, 0, intClearColor );
28878
28879					}
28880
28881				} else {
28882
28883					bits |= _gl.COLOR_BUFFER_BIT;
28884
28885				}
28886
28887			}
28888
28889			if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT;
28890			if ( stencil ) {
28891
28892				bits |= _gl.STENCIL_BUFFER_BIT;
28893				this.state.buffers.stencil.setMask( 0xffffffff );
28894
28895			}
28896
28897			_gl.clear( bits );
28898
28899		};
28900
28901		this.clearColor = function () {
28902
28903			this.clear( true, false, false );
28904
28905		};
28906
28907		this.clearDepth = function () {
28908
28909			this.clear( false, true, false );
28910
28911		};
28912
28913		this.clearStencil = function () {
28914
28915			this.clear( false, false, true );
28916
28917		};
28918
28919		//
28920
28921		this.dispose = function () {
28922
28923			canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
28924			canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );
28925			canvas.removeEventListener( 'webglcontextcreationerror', onContextCreationError, false );
28926
28927			renderLists.dispose();
28928			renderStates.dispose();
28929			properties.dispose();
28930			cubemaps.dispose();
28931			cubeuvmaps.dispose();
28932			objects.dispose();
28933			bindingStates.dispose();
28934			uniformsGroups.dispose();
28935			programCache.dispose();
28936
28937			xr.dispose();
28938
28939			xr.removeEventListener( 'sessionstart', onXRSessionStart );
28940			xr.removeEventListener( 'sessionend', onXRSessionEnd );
28941
28942			animation.stop();
28943
28944		};
28945
28946		// Events
28947
28948		function onContextLost( event ) {
28949
28950			event.preventDefault();
28951
28952			console.log( 'THREE.WebGLRenderer: Context Lost.' );
28953
28954			_isContextLost = true;
28955
28956		}
28957
28958		function onContextRestore( /* event */ ) {
28959
28960			console.log( 'THREE.WebGLRenderer: Context Restored.' );
28961
28962			_isContextLost = false;
28963
28964			const infoAutoReset = info.autoReset;
28965			const shadowMapEnabled = shadowMap.enabled;
28966			const shadowMapAutoUpdate = shadowMap.autoUpdate;
28967			const shadowMapNeedsUpdate = shadowMap.needsUpdate;
28968			const shadowMapType = shadowMap.type;
28969
28970			initGLContext();
28971
28972			info.autoReset = infoAutoReset;
28973			shadowMap.enabled = shadowMapEnabled;
28974			shadowMap.autoUpdate = shadowMapAutoUpdate;
28975			shadowMap.needsUpdate = shadowMapNeedsUpdate;
28976			shadowMap.type = shadowMapType;
28977
28978		}
28979
28980		function onContextCreationError( event ) {
28981
28982			console.error( 'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage );
28983
28984		}
28985
28986		function onMaterialDispose( event ) {
28987
28988			const material = event.target;
28989
28990			material.removeEventListener( 'dispose', onMaterialDispose );
28991
28992			deallocateMaterial( material );
28993
28994		}
28995
28996		// Buffer deallocation
28997
28998		function deallocateMaterial( material ) {
28999
29000			releaseMaterialProgramReferences( material );
29001
29002			properties.remove( material );
29003
29004		}
29005
29006
29007		function releaseMaterialProgramReferences( material ) {
29008
29009			const programs = properties.get( material ).programs;
29010
29011			if ( programs !== undefined ) {
29012
29013				programs.forEach( function ( program ) {
29014
29015					programCache.releaseProgram( program );
29016
29017				} );
29018
29019				if ( material.isShaderMaterial ) {
29020
29021					programCache.releaseShaderCache( material );
29022
29023				}
29024
29025			}
29026
29027		}
29028
29029		// Buffer rendering
29030
29031		this.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {
29032
29033			if ( scene === null ) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
29034
29035			const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );
29036
29037			const program = setProgram( camera, scene, geometry, material, object );
29038
29039			state.setMaterial( material, frontFaceCW );
29040
29041			//
29042
29043			let index = geometry.index;
29044			let rangeFactor = 1;
29045
29046			if ( material.wireframe === true ) {
29047
29048				index = geometries.getWireframeAttribute( geometry );
29049
29050				if ( index === undefined ) return;
29051
29052				rangeFactor = 2;
29053
29054			}
29055
29056			//
29057
29058			const drawRange = geometry.drawRange;
29059			const position = geometry.attributes.position;
29060
29061			let drawStart = drawRange.start * rangeFactor;
29062			let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor;
29063
29064			if ( group !== null ) {
29065
29066				drawStart = Math.max( drawStart, group.start * rangeFactor );
29067				drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor );
29068
29069			}
29070
29071			if ( index !== null ) {
29072
29073				drawStart = Math.max( drawStart, 0 );
29074				drawEnd = Math.min( drawEnd, index.count );
29075
29076			} else if ( position !== undefined && position !== null ) {
29077
29078				drawStart = Math.max( drawStart, 0 );
29079				drawEnd = Math.min( drawEnd, position.count );
29080
29081			}
29082
29083			const drawCount = drawEnd - drawStart;
29084
29085			if ( drawCount < 0 || drawCount === Infinity ) return;
29086
29087			//
29088
29089			bindingStates.setup( object, material, program, geometry, index );
29090
29091			let attribute;
29092			let renderer = bufferRenderer;
29093
29094			if ( index !== null ) {
29095
29096				attribute = attributes.get( index );
29097
29098				renderer = indexedBufferRenderer;
29099				renderer.setIndex( attribute );
29100
29101			}
29102
29103			//
29104
29105			if ( object.isMesh ) {
29106
29107				if ( material.wireframe === true ) {
29108
29109					state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
29110					renderer.setMode( _gl.LINES );
29111
29112				} else {
29113
29114					renderer.setMode( _gl.TRIANGLES );
29115
29116				}
29117
29118			} else if ( object.isLine ) {
29119
29120				let lineWidth = material.linewidth;
29121
29122				if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
29123
29124				state.setLineWidth( lineWidth * getTargetPixelRatio() );
29125
29126				if ( object.isLineSegments ) {
29127
29128					renderer.setMode( _gl.LINES );
29129
29130				} else if ( object.isLineLoop ) {
29131
29132					renderer.setMode( _gl.LINE_LOOP );
29133
29134				} else {
29135
29136					renderer.setMode( _gl.LINE_STRIP );
29137
29138				}
29139
29140			} else if ( object.isPoints ) {
29141
29142				renderer.setMode( _gl.POINTS );
29143
29144			} else if ( object.isSprite ) {
29145
29146				renderer.setMode( _gl.TRIANGLES );
29147
29148			}
29149
29150			if ( object.isBatchedMesh ) {
29151
29152				if ( object._multiDrawInstances !== null ) {
29153
29154					renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances );
29155
29156				} else {
29157
29158					renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount );
29159
29160				}
29161
29162			} else if ( object.isInstancedMesh ) {
29163
29164				renderer.renderInstances( drawStart, drawCount, object.count );
29165
29166			} else if ( geometry.isInstancedBufferGeometry ) {
29167
29168				const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity;
29169				const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount );
29170
29171				renderer.renderInstances( drawStart, drawCount, instanceCount );
29172
29173			} else {
29174
29175				renderer.render( drawStart, drawCount );
29176
29177			}
29178
29179		};
29180
29181		// Compile
29182
29183		function prepareMaterial( material, scene, object ) {
29184
29185			if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
29186
29187				material.side = BackSide;
29188				material.needsUpdate = true;
29189				getProgram( material, scene, object );
29190
29191				material.side = FrontSide;
29192				material.needsUpdate = true;
29193				getProgram( material, scene, object );
29194
29195				material.side = DoubleSide;
29196
29197			} else {
29198
29199				getProgram( material, scene, object );
29200
29201			}
29202
29203		}
29204
29205		this.compile = function ( scene, camera, targetScene = null ) {
29206
29207			if ( targetScene === null ) targetScene = scene;
29208
29209			currentRenderState = renderStates.get( targetScene );
29210			currentRenderState.init( camera );
29211
29212			renderStateStack.push( currentRenderState );
29213
29214			// gather lights from both the target scene and the new object that will be added to the scene.
29215
29216			targetScene.traverseVisible( function ( object ) {
29217
29218				if ( object.isLight && object.layers.test( camera.layers ) ) {
29219
29220					currentRenderState.pushLight( object );
29221
29222					if ( object.castShadow ) {
29223
29224						currentRenderState.pushShadow( object );
29225
29226					}
29227
29228				}
29229
29230			} );
29231
29232			if ( scene !== targetScene ) {
29233
29234				scene.traverseVisible( function ( object ) {
29235
29236					if ( object.isLight && object.layers.test( camera.layers ) ) {
29237
29238						currentRenderState.pushLight( object );
29239
29240						if ( object.castShadow ) {
29241
29242							currentRenderState.pushShadow( object );
29243
29244						}
29245
29246					}
29247
29248				} );
29249
29250			}
29251
29252			currentRenderState.setupLights();
29253
29254			// Only initialize materials in the new scene, not the targetScene.
29255
29256			const materials = new Set();
29257
29258			scene.traverse( function ( object ) {
29259
29260				const material = object.material;
29261
29262				if ( material ) {
29263
29264					if ( Array.isArray( material ) ) {
29265
29266						for ( let i = 0; i < material.length; i ++ ) {
29267
29268							const material2 = material[ i ];
29269
29270							prepareMaterial( material2, targetScene, object );
29271							materials.add( material2 );
29272
29273						}
29274
29275					} else {
29276
29277						prepareMaterial( material, targetScene, object );
29278						materials.add( material );
29279
29280					}
29281
29282				}
29283
29284			} );
29285
29286			renderStateStack.pop();
29287			currentRenderState = null;
29288
29289			return materials;
29290
29291		};
29292
29293		// compileAsync
29294
29295		this.compileAsync = function ( scene, camera, targetScene = null ) {
29296
29297			const materials = this.compile( scene, camera, targetScene );
29298
29299			// Wait for all the materials in the new object to indicate that they're
29300			// ready to be used before resolving the promise.
29301
29302			return new Promise( ( resolve ) => {
29303
29304				function checkMaterialsReady() {
29305
29306					materials.forEach( function ( material ) {
29307
29308						const materialProperties = properties.get( material );
29309						const program = materialProperties.currentProgram;
29310
29311						if ( program.isReady() ) {
29312
29313							// remove any programs that report they're ready to use from the list
29314							materials.delete( material );
29315
29316						}
29317
29318					} );
29319
29320					// once the list of compiling materials is empty, call the callback
29321
29322					if ( materials.size === 0 ) {
29323
29324						resolve( scene );
29325						return;
29326
29327					}
29328
29329					// if some materials are still not ready, wait a bit and check again
29330
29331					setTimeout( checkMaterialsReady, 10 );
29332
29333				}
29334
29335				if ( extensions.get( 'KHR_parallel_shader_compile' ) !== null ) {
29336
29337					// If we can check the compilation status of the materials without
29338					// blocking then do so right away.
29339
29340					checkMaterialsReady();
29341
29342				} else {
29343
29344					// Otherwise start by waiting a bit to give the materials we just
29345					// initialized a chance to finish.
29346
29347					setTimeout( checkMaterialsReady, 10 );
29348
29349				}
29350
29351			} );
29352
29353		};
29354
29355		// Animation Loop
29356
29357		let onAnimationFrameCallback = null;
29358
29359		function onAnimationFrame( time ) {
29360
29361			if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
29362
29363		}
29364
29365		function onXRSessionStart() {
29366
29367			animation.stop();
29368
29369		}
29370
29371		function onXRSessionEnd() {
29372
29373			animation.start();
29374
29375		}
29376
29377		const animation = new WebGLAnimation();
29378		animation.setAnimationLoop( onAnimationFrame );
29379
29380		if ( typeof self !== 'undefined' ) animation.setContext( self );
29381
29382		this.setAnimationLoop = function ( callback ) {
29383
29384			onAnimationFrameCallback = callback;
29385			xr.setAnimationLoop( callback );
29386
29387			( callback === null ) ? animation.stop() : animation.start();
29388
29389		};
29390
29391		xr.addEventListener( 'sessionstart', onXRSessionStart );
29392		xr.addEventListener( 'sessionend', onXRSessionEnd );
29393
29394		// Rendering
29395
29396		this.render = function ( scene, camera ) {
29397
29398			if ( camera !== undefined && camera.isCamera !== true ) {
29399
29400				console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
29401				return;
29402
29403			}
29404
29405			if ( _isContextLost === true ) return;
29406
29407			// update scene graph
29408
29409			if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld();
29410
29411			// update camera matrices and frustum
29412
29413			if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
29414
29415			if ( xr.enabled === true && xr.isPresenting === true ) {
29416
29417				if ( xr.cameraAutoUpdate === true ) xr.updateCamera( camera );
29418
vendor: 13,080 bytes, lines 29419-29912
29419				camera = xr.getCamera(); // use XR camera for rendering
29420
29421			}
29422
29423			//
29424			if ( scene.isScene === true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget );
29425
29426			currentRenderState = renderStates.get( scene, renderStateStack.length );
29427			currentRenderState.init( camera );
29428
29429			renderStateStack.push( currentRenderState );
29430
29431			_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
29432			_frustum.setFromProjectionMatrix( _projScreenMatrix );
29433
29434			_localClippingEnabled = this.localClippingEnabled;
29435			_clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled );
29436
29437			currentRenderList = renderLists.get( scene, renderListStack.length );
29438			currentRenderList.init();
29439
29440			renderListStack.push( currentRenderList );
29441
29442			if ( xr.enabled === true && xr.isPresenting === true ) {
29443
29444				const depthSensingMesh = _this.xr.getDepthSensingMesh();
29445
29446				if ( depthSensingMesh !== null ) {
29447
29448					projectObject( depthSensingMesh, camera, - Infinity, _this.sortObjects );
29449
29450				}
29451
29452			}
29453
29454			projectObject( scene, camera, 0, _this.sortObjects );
29455
29456			currentRenderList.finish();
29457
29458			if ( _this.sortObjects === true ) {
29459
29460				currentRenderList.sort( _opaqueSort, _transparentSort );
29461
29462			}
29463
29464			_renderBackground = xr.enabled === false || xr.isPresenting === false || xr.hasDepthSensing() === false;
29465			if ( _renderBackground ) {
29466
29467				background.addToRenderList( currentRenderList, scene );
29468
29469			}
29470
29471			//
29472
29473			this.info.render.frame ++;
29474
29475			if ( _clippingEnabled === true ) clipping.beginShadows();
29476
29477			const shadowsArray = currentRenderState.state.shadowsArray;
29478
29479			shadowMap.render( shadowsArray, scene, camera );
29480
29481			if ( _clippingEnabled === true ) clipping.endShadows();
29482
29483			//
29484
29485			if ( this.info.autoReset === true ) this.info.reset();
29486
29487			// render scene
29488
29489			const opaqueObjects = currentRenderList.opaque;
29490			const transmissiveObjects = currentRenderList.transmissive;
29491
29492			currentRenderState.setupLights();
29493
29494			if ( camera.isArrayCamera ) {
29495
29496				const cameras = camera.cameras;
29497
29498				if ( transmissiveObjects.length > 0 ) {
29499
29500					for ( let i = 0, l = cameras.length; i < l; i ++ ) {
29501
29502						const camera2 = cameras[ i ];
29503
29504						renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera2 );
29505
29506					}
29507
29508				}
29509
29510				if ( _renderBackground ) background.render( scene );
29511
29512				for ( let i = 0, l = cameras.length; i < l; i ++ ) {
29513
29514					const camera2 = cameras[ i ];
29515
29516					renderScene( currentRenderList, scene, camera2, camera2.viewport );
29517
29518				}
29519
29520			} else {
29521
29522				if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera );
29523
29524				if ( _renderBackground ) background.render( scene );
29525
29526				renderScene( currentRenderList, scene, camera );
29527
29528			}
29529
29530			//
29531
29532			if ( _currentRenderTarget !== null ) {
29533
29534				// resolve multisample renderbuffers to a single-sample texture if necessary
29535
29536				textures.updateMultisampleRenderTarget( _currentRenderTarget );
29537
29538				// Generate mipmap if we're using any kind of mipmap filtering
29539
29540				textures.updateRenderTargetMipmap( _currentRenderTarget );
29541
29542			}
29543
29544			//
29545
29546			if ( scene.isScene === true ) scene.onAfterRender( _this, scene, camera );
29547
29548			// _gl.finish();
29549
29550			bindingStates.resetDefaultState();
29551			_currentMaterialId = - 1;
29552			_currentCamera = null;
29553
29554			renderStateStack.pop();
29555
29556			if ( renderStateStack.length > 0 ) {
29557
29558				currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
29559
29560				if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, currentRenderState.state.camera );
29561
29562			} else {
29563
29564				currentRenderState = null;
29565
29566			}
29567
29568			renderListStack.pop();
29569
29570			if ( renderListStack.length > 0 ) {
29571
29572				currentRenderList = renderListStack[ renderListStack.length - 1 ];
29573
29574			} else {
29575
29576				currentRenderList = null;
29577
29578			}
29579
29580		};
29581
29582		function projectObject( object, camera, groupOrder, sortObjects ) {
29583
29584			if ( object.visible === false ) return;
29585
29586			const visible = object.layers.test( camera.layers );
29587
29588			if ( visible ) {
29589
29590				if ( object.isGroup ) {
29591
29592					groupOrder = object.renderOrder;
29593
29594				} else if ( object.isLOD ) {
29595
29596					if ( object.autoUpdate === true ) object.update( camera );
29597
29598				} else if ( object.isLight ) {
29599
29600					currentRenderState.pushLight( object );
29601
29602					if ( object.castShadow ) {
29603
29604						currentRenderState.pushShadow( object );
29605
29606					}
29607
29608				} else if ( object.isSprite ) {
29609
29610					if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
29611
29612						if ( sortObjects ) {
29613
29614							_vector3.setFromMatrixPosition( object.matrixWorld )
29615								.applyMatrix4( _projScreenMatrix );
29616
29617						}
29618
29619						const geometry = objects.update( object );
29620						const material = object.material;
29621
29622						if ( material.visible ) {
29623
29624							currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
29625
29626						}
29627
29628					}
29629
29630				} else if ( object.isMesh || object.isLine || object.isPoints ) {
29631
29632					if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
29633
29634						const geometry = objects.update( object );
29635						const material = object.material;
29636
29637						if ( sortObjects ) {
29638
29639							if ( object.boundingSphere !== undefined ) {
29640
29641								if ( object.boundingSphere === null ) object.computeBoundingSphere();
29642								_vector3.copy( object.boundingSphere.center );
29643
29644							} else {
29645
29646								if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
29647								_vector3.copy( geometry.boundingSphere.center );
29648
29649							}
29650
29651							_vector3
29652								.applyMatrix4( object.matrixWorld )
29653								.applyMatrix4( _projScreenMatrix );
29654
29655						}
29656
29657						if ( Array.isArray( material ) ) {
29658
29659							const groups = geometry.groups;
29660
29661							for ( let i = 0, l = groups.length; i < l; i ++ ) {
29662
29663								const group = groups[ i ];
29664								const groupMaterial = material[ group.materialIndex ];
29665
29666								if ( groupMaterial && groupMaterial.visible ) {
29667
29668									currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );
29669
29670								}
29671
29672							}
29673
29674						} else if ( material.visible ) {
29675
29676							currentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );
29677
29678						}
29679
29680					}
29681
29682				}
29683
29684			}
29685
29686			const children = object.children;
29687
29688			for ( let i = 0, l = children.length; i < l; i ++ ) {
29689
29690				projectObject( children[ i ], camera, groupOrder, sortObjects );
29691
29692			}
29693
29694		}
29695
29696		function renderScene( currentRenderList, scene, camera, viewport ) {
29697
29698			const opaqueObjects = currentRenderList.opaque;
29699			const transmissiveObjects = currentRenderList.transmissive;
29700			const transparentObjects = currentRenderList.transparent;
29701
29702			currentRenderState.setupLightsView( camera );
29703
29704			if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera );
29705
29706			if ( viewport ) state.viewport( _currentViewport.copy( viewport ) );
29707
29708			if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
29709			if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera );
29710			if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
29711
29712			// Ensure depth buffer writing is enabled so it can be cleared on next render
29713
29714			state.buffers.depth.setTest( true );
29715			state.buffers.depth.setMask( true );
29716			state.buffers.color.setMask( true );
29717
29718			state.setPolygonOffset( false );
29719
29720		}
29721
29722		function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) {
29723
29724			const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
29725
29726			if ( overrideMaterial !== null ) {
29727
29728				return;
29729
29730			}
29731
29732			if ( currentRenderState.state.transmissionRenderTarget[ camera.id ] === undefined ) {
29733
29734				currentRenderState.state.transmissionRenderTarget[ camera.id ] = new WebGLRenderTarget( 1, 1, {
29735					generateMipmaps: true,
29736					type: ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ) ? HalfFloatType : UnsignedByteType,
29737					minFilter: LinearMipmapLinearFilter,
29738					samples: 4,
29739					stencilBuffer: stencil,
29740					resolveDepthBuffer: false,
29741					resolveStencilBuffer: false,
29742					colorSpace: ColorManagement.workingColorSpace,
29743				} );
29744
29745				// debug
29746
29747				/*
29748				const geometry = new PlaneGeometry();
29749				const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } );
29750
29751				const mesh = new Mesh( geometry, material );
29752				scene.add( mesh );
29753				*/
29754
29755			}
29756
29757			const transmissionRenderTarget = currentRenderState.state.transmissionRenderTarget[ camera.id ];
29758
29759			const activeViewport = camera.viewport || _currentViewport;
29760			transmissionRenderTarget.setSize( activeViewport.z, activeViewport.w );
29761
29762			//
29763
29764			const currentRenderTarget = _this.getRenderTarget();
29765			_this.setRenderTarget( transmissionRenderTarget );
29766
29767			_this.getClearColor( _currentClearColor );
29768			_currentClearAlpha = _this.getClearAlpha();
29769			if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 );
29770
29771			if ( _renderBackground ) {
29772
29773				background.render( scene );
29774
29775			} else {
29776
29777				_this.clear();
29778
29779			}
29780
29781			// Turn off the features which can affect the frag color for opaque objects pass.
29782			// Otherwise they are applied twice in opaque objects pass and transmission objects pass.
29783			const currentToneMapping = _this.toneMapping;
29784			_this.toneMapping = NoToneMapping;
29785
29786			// Remove viewport from camera to avoid nested render calls resetting viewport to it (e.g Reflector).
29787			// Transmission render pass requires viewport to match the transmissionRenderTarget.
29788			const currentCameraViewport = camera.viewport;
29789			if ( camera.viewport !== undefined ) camera.viewport = undefined;
29790
29791			currentRenderState.setupLightsView( camera );
29792
29793			if ( _clippingEnabled === true ) clipping.setGlobalState( _this.clippingPlanes, camera );
29794
29795			renderObjects( opaqueObjects, scene, camera );
29796
29797			textures.updateMultisampleRenderTarget( transmissionRenderTarget );
29798			textures.updateRenderTargetMipmap( transmissionRenderTarget );
29799
29800			if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === false ) { // see #28131
29801
29802				let renderTargetNeedsUpdate = false;
29803
29804				for ( let i = 0, l = transmissiveObjects.length; i < l; i ++ ) {
29805
29806					const renderItem = transmissiveObjects[ i ];
29807
29808					const object = renderItem.object;
29809					const geometry = renderItem.geometry;
29810					const material = renderItem.material;
29811					const group = renderItem.group;
29812
29813					if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) {
29814
29815						const currentSide = material.side;
29816
29817						material.side = BackSide;
29818						material.needsUpdate = true;
29819
29820						renderObject( object, scene, camera, geometry, material, group );
29821
29822						material.side = currentSide;
29823						material.needsUpdate = true;
29824
29825						renderTargetNeedsUpdate = true;
29826
29827					}
29828
29829				}
29830
29831				if ( renderTargetNeedsUpdate === true ) {
29832
29833					textures.updateMultisampleRenderTarget( transmissionRenderTarget );
29834					textures.updateRenderTargetMipmap( transmissionRenderTarget );
29835
29836				}
29837
29838			}
29839
29840			_this.setRenderTarget( currentRenderTarget );
29841
29842			_this.setClearColor( _currentClearColor, _currentClearAlpha );
29843
29844			if ( currentCameraViewport !== undefined ) camera.viewport = currentCameraViewport;
29845
29846			_this.toneMapping = currentToneMapping;
29847
29848		}
29849
29850		function renderObjects( renderList, scene, camera ) {
29851
29852			const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
29853
29854			for ( let i = 0, l = renderList.length; i < l; i ++ ) {
29855
29856				const renderItem = renderList[ i ];
29857
29858				const object = renderItem.object;
29859				const geometry = renderItem.geometry;
29860				const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
29861				const group = renderItem.group;
29862
29863				if ( object.layers.test( camera.layers ) ) {
29864
29865					renderObject( object, scene, camera, geometry, material, group );
29866
29867				}
29868
29869			}
29870
29871		}
29872
29873		function renderObject( object, scene, camera, geometry, material, group ) {
29874
29875			object.onBeforeRender( _this, scene, camera, geometry, material, group );
29876
29877			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
29878			object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
29879
29880			material.onBeforeRender( _this, scene, camera, geometry, object, group );
29881
29882			if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) {
29883
29884				material.side = BackSide;
29885				material.needsUpdate = true;
29886				_this.renderBufferDirect( camera, scene, geometry, material, object, group );
29887
29888				material.side = FrontSide;
29889				material.needsUpdate = true;
29890				_this.renderBufferDirect( camera, scene, geometry, material, object, group );
29891
29892				material.side = DoubleSide;
29893
29894			} else {
29895
29896				_this.renderBufferDirect( camera, scene, geometry, material, object, group );
29897
29898			}
29899
29900			object.onAfterRender( _this, scene, camera, geometry, material, group );
29901
29902		}
29903
29904		function getProgram( material, scene, object ) {
29905
29906			if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
29907
29908			const materialProperties = properties.get( material );
29909
29910			const lights = currentRenderState.state.lights;
29911			const shadowsArray = currentRenderState.state.shadowsArray;
29912
vendor: 5,874 bytes, lines 29913-30062
29913			const lightsStateVersion = lights.state.version;
29914
29915			const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, object );
29916			const programCacheKey = programCache.getProgramCacheKey( parameters );
29917
29918			let programs = materialProperties.programs;
29919
29920			// always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change
29921
29922			materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
29923			materialProperties.fog = scene.fog;
29924			materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment );
29925			materialProperties.envMapRotation = ( materialProperties.environment !== null && material.envMap === null ) ? scene.environmentRotation : material.envMapRotation;
29926
29927			if ( programs === undefined ) {
29928
29929				// new material
29930
29931				material.addEventListener( 'dispose', onMaterialDispose );
29932
29933				programs = new Map();
29934				materialProperties.programs = programs;
29935
29936			}
29937
29938			let program = programs.get( programCacheKey );
29939
29940			if ( program !== undefined ) {
29941
29942				// early out if program and light state is identical
29943
29944				if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) {
29945
29946					updateCommonMaterialProperties( material, parameters );
29947
29948					return program;
29949
29950				}
29951
29952			} else {
29953
29954				parameters.uniforms = programCache.getUniforms( material );
29955
29956				material.onBuild( object, parameters, _this );
29957
29958				material.onBeforeCompile( parameters, _this );
29959
29960				program = programCache.acquireProgram( parameters, programCacheKey );
29961				programs.set( programCacheKey, program );
29962
29963				materialProperties.uniforms = parameters.uniforms;
29964
29965			}
29966
29967			const uniforms = materialProperties.uniforms;
29968
29969			if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping === true ) {
29970
29971				uniforms.clippingPlanes = clipping.uniform;
29972
29973			}
29974
29975			updateCommonMaterialProperties( material, parameters );
29976
29977			// store the light setup it was created for
29978
29979			materialProperties.needsLights = materialNeedsLights( material );
29980			materialProperties.lightsStateVersion = lightsStateVersion;
29981
29982			if ( materialProperties.needsLights ) {
29983
29984				// wire up the material to this renderer's lighting state
29985
29986				uniforms.ambientLightColor.value = lights.state.ambient;
29987				uniforms.lightProbe.value = lights.state.probe;
29988				uniforms.directionalLights.value = lights.state.directional;
29989				uniforms.directionalLightShadows.value = lights.state.directionalShadow;
29990				uniforms.spotLights.value = lights.state.spot;
29991				uniforms.spotLightShadows.value = lights.state.spotShadow;
29992				uniforms.rectAreaLights.value = lights.state.rectArea;
29993				uniforms.ltc_1.value = lights.state.rectAreaLTC1;
29994				uniforms.ltc_2.value = lights.state.rectAreaLTC2;
29995				uniforms.pointLights.value = lights.state.point;
29996				uniforms.pointLightShadows.value = lights.state.pointShadow;
29997				uniforms.hemisphereLights.value = lights.state.hemi;
29998
29999				uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
30000				uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
30001				uniforms.spotShadowMap.value = lights.state.spotShadowMap;
30002				uniforms.spotLightMatrix.value = lights.state.spotLightMatrix;
30003				uniforms.spotLightMap.value = lights.state.spotLightMap;
30004				uniforms.pointShadowMap.value = lights.state.pointShadowMap;
30005				uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
30006				// TODO (abelnation): add area lights shadow info to uniforms
30007
30008			}
30009
30010			materialProperties.currentProgram = program;
30011			materialProperties.uniformsList = null;
30012
30013			return program;
30014
30015		}
30016
30017		function getUniformList( materialProperties ) {
30018
30019			if ( materialProperties.uniformsList === null ) {
30020
30021				const progUniforms = materialProperties.currentProgram.getUniforms();
30022				materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms );
30023
30024			}
30025
30026			return materialProperties.uniformsList;
30027
30028		}
30029
30030		function updateCommonMaterialProperties( material, parameters ) {
30031
30032			const materialProperties = properties.get( material );
30033
30034			materialProperties.outputColorSpace = parameters.outputColorSpace;
30035			materialProperties.batching = parameters.batching;
30036			materialProperties.batchingColor = parameters.batchingColor;
30037			materialProperties.instancing = parameters.instancing;
30038			materialProperties.instancingColor = parameters.instancingColor;
30039			materialProperties.instancingMorph = parameters.instancingMorph;
30040			materialProperties.skinning = parameters.skinning;
30041			materialProperties.morphTargets = parameters.morphTargets;
30042			materialProperties.morphNormals = parameters.morphNormals;
30043			materialProperties.morphColors = parameters.morphColors;
30044			materialProperties.morphTargetsCount = parameters.morphTargetsCount;
30045			materialProperties.numClippingPlanes = parameters.numClippingPlanes;
30046			materialProperties.numIntersection = parameters.numClipIntersection;
30047			materialProperties.vertexAlphas = parameters.vertexAlphas;
30048			materialProperties.vertexTangents = parameters.vertexTangents;
30049			materialProperties.toneMapping = parameters.toneMapping;
30050
30051		}
30052
30053		function setProgram( camera, scene, geometry, material, object ) {
30054
30055			if ( scene.isScene !== true ) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
30056
30057			textures.resetTextureUnits();
30058
30059			const fog = scene.fog;
30060			const environment = material.isMeshStandardMaterial ? scene.environment : null;
30061			const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace );
30062			const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment
vendor: 5,405 bytes, lines 30062-30254
30062 );
30063			const vertexAlphas = material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4;
30064			const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 );
30065			const morphTargets = !! geometry.morphAttributes.position;
30066			const morphNormals = !! geometry.morphAttributes.normal;
30067			const morphColors = !! geometry.morphAttributes.color;
30068
30069			let toneMapping = NoToneMapping;
30070
30071			if ( material.toneMapped ) {
30072
30073				if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) {
30074
30075					toneMapping = _this.toneMapping;
30076
30077				}
30078
30079			}
30080
30081			const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
30082			const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0;
30083
30084			const materialProperties = properties.get( material );
30085			const lights = currentRenderState.state.lights;
30086
30087			if ( _clippingEnabled === true ) {
30088
30089				if ( _localClippingEnabled === true || camera !== _currentCamera ) {
30090
30091					const useCache =
30092						camera === _currentCamera &&
30093						material.id === _currentMaterialId;
30094
30095					// we might want to call this function with some ClippingGroup
30096					// object instead of the material, once it becomes feasible
30097					// (#8465, #8379)
30098					clipping.setState( material, camera, useCache );
30099
30100				}
30101
30102			}
30103
30104			//
30105
30106			let needsProgramChange = false;
30107
30108			if ( material.version === materialProperties.__version ) {
30109
30110				if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
30111
30112					needsProgramChange = true;
30113
30114				} else if ( materialProperties.outputColorSpace !== colorSpace ) {
30115
30116					needsProgramChange = true;
30117
30118				} else if ( object.isBatchedMesh && materialProperties.batching === false ) {
30119
30120					needsProgramChange = true;
30121
30122				} else if ( ! object.isBatchedMesh && materialProperties.batching === true ) {
30123
30124					needsProgramChange = true;
30125
30126				} else if ( object.isBatchedMesh && materialProperties.batchingColor === true && object.colorTexture === null ) {
30127
30128					needsProgramChange = true;
30129
30130				} else if ( object.isBatchedMesh && materialProperties.batchingColor === false && object.colorTexture !== null ) {
30131
30132					needsProgramChange = true;
30133
30134				} else if ( object.isInstancedMesh && materialProperties.instancing === false ) {
30135
30136					needsProgramChange = true;
30137
30138				} else if ( ! object.isInstancedMesh && materialProperties.instancing === true ) {
30139
30140					needsProgramChange = true;
30141
30142				} else if ( object.isSkinnedMesh && materialProperties.skinning === false ) {
30143
30144					needsProgramChange = true;
30145
30146				} else if ( ! object.isSkinnedMesh && materialProperties.skinning === true ) {
30147
30148					needsProgramChange = true;
30149
30150				} else if ( object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null ) {
30151
30152					needsProgramChange = true;
30153
30154				} else if ( object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null ) {
30155
30156					needsProgramChange = true;
30157
30158				} else if ( object.isInstancedMesh && materialProperties.instancingMorph === true && object.morphTexture === null ) {
30159
30160					needsProgramChange = true;
30161
30162				} else if ( object.isInstancedMesh && materialProperties.instancingMorph === false && object.morphTexture !== null ) {
30163
30164					needsProgramChange = true;
30165
30166				} else if ( materialProperties.envMap !== envMap ) {
30167
30168					needsProgramChange = true;
30169
30170				} else if ( material.fog === true && materialProperties.fog !== fog ) {
30171
30172					needsProgramChange = true;
30173
30174				} else if ( materialProperties.numClippingPlanes !== undefined &&
30175					( materialProperties.numClippingPlanes !== clipping.numPlanes ||
30176					materialProperties.numIntersection !== clipping.numIntersection ) ) {
30177
30178					needsProgramChange = true;
30179
30180				} else if ( materialProperties.vertexAlphas !== vertexAlphas ) {
30181
30182					needsProgramChange = true;
30183
30184				} else if ( materialProperties.vertexTangents !== vertexTangents ) {
30185
30186					needsProgramChange = true;
30187
30188				} else if ( materialProperties.morphTargets !== morphTargets ) {
30189
30190					needsProgramChange = true;
30191
30192				} else if ( materialProperties.morphNormals !== morphNormals ) {
30193
30194					needsProgramChange = true;
30195
30196				} else if ( materialProperties.morphColors !== morphColors ) {
30197
30198					needsProgramChange = true;
30199
30200				} else if ( materialProperties.toneMapping !== toneMapping ) {
30201
30202					needsProgramChange = true;
30203
30204				} else if ( materialProperties.morphTargetsCount !== morphTargetsCount ) {
30205
30206					needsProgramChange = true;
30207
30208				}
30209
30210			} else {
30211
30212				needsProgramChange = true;
30213				materialProperties.__version = material.version;
30214
30215			}
30216
30217			//
30218
30219			let program = materialProperties.currentProgram;
30220
30221			if ( needsProgramChange === true ) {
30222
30223				program = getProgram( material, scene, object );
30224
30225			}
30226
30227			let refreshProgram = false;
30228			let refreshMaterial = false;
30229			let refreshLights = false;
30230
30231			const p_uniforms = program.getUniforms(),
30232				m_uniforms = materialProperties.uniforms;
30233
30234			if ( state.useProgram( program.program ) ) {
30235
30236				refreshProgram = true;
30237				refreshMaterial = true;
30238				refreshLights = true;
30239
30240			}
30241
30242			if ( material.id !== _currentMaterialId ) {
30243
30244				_currentMaterialId = material.id;
30245
30246				refreshMaterial = true;
30247
30248			}
30249
30250			if ( refreshProgram || _currentCamera !== camera ) {
30251
30252				// common camera uniforms
30253
30254				
vendor: 4,556 bytes, lines 30254-30402
30254p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
30255				p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
30256
30257				const uCamPos = p_uniforms.map.cameraPosition;
30258
30259				if ( uCamPos !== undefined ) {
30260
30261					uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) );
30262
30263				}
30264
30265				if ( capabilities.logarithmicDepthBuffer ) {
30266
30267					p_uniforms.setValue( _gl, 'logDepthBufFC',
30268						2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
30269
30270				}
30271
30272				// consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067
30273
30274				if ( material.isMeshPhongMaterial ||
30275					material.isMeshToonMaterial ||
30276					material.isMeshLambertMaterial ||
30277					material.isMeshBasicMaterial ||
30278					material.isMeshStandardMaterial ||
30279					material.isShaderMaterial ) {
30280
30281					p_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );
30282
30283				}
30284
30285				if ( _currentCamera !== camera ) {
30286
30287					_currentCamera = camera;
30288
30289					// lighting uniforms depend on the camera so enforce an update
30290					// now, in case this material supports lights - or later, when
30291					// the next material that does gets activated:
30292
30293					refreshMaterial = true;		// set to true on material change
30294					refreshLights = true;		// remains set until update done
30295
30296				}
30297
30298			}
30299
30300			// skinning and morph target uniforms must be set even if material didn't change
30301			// auto-setting of texture unit for bone and morph texture must go before other textures
30302			// otherwise textures used for skinning and morphing can take over texture units reserved for other material textures
30303
30304			if ( object.isSkinnedMesh ) {
30305
30306				p_uniforms.setOptional( _gl, object, 'bindMatrix' );
30307				p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );
30308
30309				const skeleton = object.skeleton;
30310
30311				if ( skeleton ) {
30312
30313					if ( skeleton.boneTexture === null ) skeleton.computeBoneTexture();
30314
30315					p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );
30316
30317				}
30318
30319			}
30320
30321			if ( object.isBatchedMesh ) {
30322
30323				p_uniforms.setOptional( _gl, object, 'batchingTexture' );
30324				p_uniforms.setValue( _gl, 'batchingTexture', object._matricesTexture, textures );
30325
30326				p_uniforms.setOptional( _gl, object, 'batchingColorTexture' );
30327				if ( object._colorsTexture !== null ) {
30328
30329					p_uniforms.setValue( _gl, 'batchingColorTexture', object._colorsTexture, textures );
30330
30331				}
30332
30333			}
30334
30335			const morphAttributes = geometry.morphAttributes;
30336
30337			if ( morphAttributes.position !== undefined || morphAttributes.normal !== undefined || ( morphAttributes.color !== undefined ) ) {
30338
30339				morphtargets.update( object, geometry, program );
30340
30341			}
30342
30343			if ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {
30344
30345				materialProperties.receiveShadow = object.receiveShadow;
30346				p_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );
30347
30348			}
30349
30350			// https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512
30351
30352			if ( material.isMeshGouraudMaterial && material.envMap !== null ) {
30353
30354				m_uniforms.envMap.value = envMap;
30355
30356				m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
30357
30358			}
30359
30360			if ( material.isMeshStandardMaterial && material.envMap === null && scene.environment !== null ) {
30361
30362				m_uniforms.envMapIntensity.value = scene.environmentIntensity;
30363
30364			}
30365
30366			if ( refreshMaterial ) {
30367
30368				p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );
30369
30370				if ( materialProperties.needsLights ) {
30371
30372					// the current material requires lighting info
30373
30374					// note: all lighting uniforms are always set correctly
30375					// they simply reference the renderer's state for their
30376					// values
30377					//
30378					// use the current material's .needsUpdate flags to set
30379					// the GL state when required
30380
30381					markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
30382
30383				}
30384
30385				// refresh uniforms common to several materials
30386
30387				if ( fog && material.fog === true ) {
30388
30389					materials.refreshFogUniforms( m_uniforms, fog );
30390
30391				}
30392
30393				materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, currentRenderState.state.transmissionRenderTarget[ camera.id ] );
30394
30395				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
30396
30397			}
30398
30399			if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {
30400
30401				WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
30402				material.uniformsNeedUpdate = false;
vendor: 4,533 bytes, lines 30403-30557
30403
30404			}
30405
30406			if ( material.isSpriteMaterial ) {
30407
30408				p_uniforms.setValue( _gl, 'center', object.center );
30409
30410			}
30411
30412			// common matrices
30413
30414			p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
30415			p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
30416			p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
30417
30418			// UBOs
30419
30420			if ( material.isShaderMaterial || material.isRawShaderMaterial ) {
30421
30422				const groups = material.uniformsGroups;
30423
30424				for ( let i = 0, l = groups.length; i < l; i ++ ) {
30425
30426					const group = groups[ i ];
30427
30428					uniformsGroups.update( group, program );
30429					uniformsGroups.bind( group, program );
30430
30431				}
30432
30433			}
30434
30435			return program;
30436
30437		}
30438
30439		// If uniforms are marked as clean, they don't need to be loaded to the GPU.
30440
30441		function markUniformsLightsNeedsUpdate( uniforms, value ) {
30442
30443			uniforms.ambientLightColor.needsUpdate = value;
30444			uniforms.lightProbe.needsUpdate = value;
30445
30446			uniforms.directionalLights.needsUpdate = value;
30447			uniforms.directionalLightShadows.needsUpdate = value;
30448			uniforms.pointLights.needsUpdate = value;
30449			uniforms.pointLightShadows.needsUpdate = value;
30450			uniforms.spotLights.needsUpdate = value;
30451			uniforms.spotLightShadows.needsUpdate = value;
30452			uniforms.rectAreaLights.needsUpdate = value;
30453			uniforms.hemisphereLights.needsUpdate = value;
30454
30455		}
30456
30457		function materialNeedsLights( material ) {
30458
30459			return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
30460				material.isMeshStandardMaterial || material.isShadowMaterial ||
30461				( material.isShaderMaterial && material.lights === true );
30462
30463		}
30464
30465		this.getActiveCubeFace = function () {
30466
30467			return _currentActiveCubeFace;
30468
30469		};
30470
30471		this.getActiveMipmapLevel = function () {
30472
30473			return _currentActiveMipmapLevel;
30474
30475		};
30476
30477		this.getRenderTarget = function () {
30478
30479			return _currentRenderTarget;
30480
30481		};
30482
30483		this.setRenderTargetTextures = function ( renderTarget, colorTexture, depthTexture ) {
30484
30485			properties.get( renderTarget.texture ).__webglTexture = colorTexture;
30486			properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture;
30487
30488			const renderTargetProperties = properties.get( renderTarget );
30489			renderTargetProperties.__hasExternalTextures = true;
30490
30491			renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined;
30492
30493			if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) {
30494
30495				// The multisample_render_to_texture extension doesn't work properly if there
30496				// are midframe flushes and an external depth buffer. Disable use of the extension.
30497				if ( extensions.has( 'WEBGL_multisampled_render_to_texture' ) === true ) {
30498
30499					console.warn( 'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' );
30500					renderTargetProperties.__useRenderToTexture = false;
30501
30502				}
30503
30504			}
30505
30506		};
30507
30508		this.setRenderTargetFramebuffer = function ( renderTarget, defaultFramebuffer ) {
30509
30510			const renderTargetProperties = properties.get( renderTarget );
30511			renderTargetProperties.__webglFramebuffer = defaultFramebuffer;
30512			renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined;
30513
30514		};
30515
30516		this.setRenderTarget = function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
30517
30518			_currentRenderTarget = renderTarget;
30519			_currentActiveCubeFace = activeCubeFace;
30520			_currentActiveMipmapLevel = activeMipmapLevel;
30521
30522			let useDefaultFramebuffer = true;
30523			let framebuffer = null;
30524			let isCube = false;
30525			let isRenderTarget3D = false;
30526
30527			if ( renderTarget ) {
30528
30529				const renderTargetProperties = properties.get( renderTarget );
30530
30531				if ( renderTargetProperties.__useDefaultFramebuffer !== undefined ) {
30532
30533					// We need to make sure to rebind the framebuffer.
30534					state.bindFramebuffer( _gl.FRAMEBUFFER, null );
30535					useDefaultFramebuffer = false;
30536
30537				} else if ( renderTargetProperties.__webglFramebuffer === undefined ) {
30538
30539					textures.setupRenderTarget( renderTarget );
30540
30541				} else if ( renderTargetProperties.__hasExternalTextures ) {
30542
30543					// Color and depth texture must be rebound in order for the swapchain to update.
30544					textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture );
30545
30546				}
30547
30548				const texture = renderTarget.texture;
30549
30550				if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
30551
30552					isRenderTarget3D = true;
30553
30554				}
30555
30556				const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
30557
vendor: 4,267 bytes, lines 30558-30701
30558				if ( renderTarget.isWebGLCubeRenderTarget ) {
30559
30560					if ( Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) {
30561
30562						framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ];
30563
30564					} else {
30565
30566						framebuffer = __webglFramebuffer[ activeCubeFace ];
30567
30568					}
30569
30570					isCube = true;
30571
30572				} else if ( ( renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) === false ) {
30573
30574					framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
30575
30576				} else {
30577
30578					if ( Array.isArray( __webglFramebuffer ) ) {
30579
30580						framebuffer = __webglFramebuffer[ activeMipmapLevel ];
30581
30582					} else {
30583
30584						framebuffer = __webglFramebuffer;
30585
30586					}
30587
30588				}
30589
30590				_currentViewport.copy( renderTarget.viewport );
30591				_currentScissor.copy( renderTarget.scissor );
30592				_currentScissorTest = renderTarget.scissorTest;
30593
30594			} else {
30595
30596				_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
30597				_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
30598				_currentScissorTest = _scissorTest;
30599
30600			}
30601
30602			const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30603
30604			if ( framebufferBound && useDefaultFramebuffer ) {
30605
30606				state.drawBuffers( renderTarget, framebuffer );
30607
30608			}
30609
30610			state.viewport( _currentViewport );
30611			state.scissor( _currentScissor );
30612			state.setScissorTest( _currentScissorTest );
30613
30614			if ( isCube ) {
30615
30616				const textureProperties = properties.get( renderTarget.texture );
30617				_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
30618
30619			} else if ( isRenderTarget3D ) {
30620
30621				const textureProperties = properties.get( renderTarget.texture );
30622				const layer = activeCubeFace || 0;
30623				_gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer );
30624
30625			}
30626
30627			_currentMaterialId = - 1; // reset current material to ensure correct uniform bindings
30628
30629		};
30630
30631		this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
30632
30633			if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
30634
30635				console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
30636				return;
30637
30638			}
30639
30640			let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
30641
30642			if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
30643
30644				framebuffer = framebuffer[ activeCubeFaceIndex ];
30645
30646			}
30647
30648			if ( framebuffer ) {
30649
30650				state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30651
30652				try {
30653
30654					const texture = renderTarget.texture;
30655					const textureFormat = texture.format;
30656					const textureType = texture.type;
30657
30658					if ( ! capabilities.textureFormatReadable( textureFormat ) ) {
30659
30660						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
30661						return;
30662
30663					}
30664
30665					if ( ! capabilities.textureTypeReadable( textureType ) ) {
30666
30667						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
30668						return;
30669
30670					}
30671
30672					// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
30673
30674					if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
30675
30676						_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
30677
30678					}
30679
30680				} finally {
30681
30682					// restore framebuffer of current render target if necessary
30683
30684					const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null;
30685					state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30686
30687				}
30688
30689			}
30690
30691		};
30692
30693		this.readRenderTargetPixelsAsync = async function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {
30694
30695			if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
30696
30697				throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
30698
30699			}
30700
30701			let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
30702			if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {
30703
30704				framebuffer = framebuffer[ activeCubeFaceIndex ];
30705
30706			}
30707
30708			if ( framebuffer ) {
30709
30710				state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30711
30712				try {
30713
30714					const texture = renderTarget.texture;
30715					const textureFormat = texture.format;
30716					const textureType = texture.type;
30717
30718					if ( ! capabilities.textureFormatReadable( textureFormat ) ) {
30719
30720						throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' );
30721
30722					}
30723
30724					if ( ! capabilities.textureTypeReadable( textureType ) ) {
30725
30726						throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' );
30727
30728					}
30729
30730					// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
30731					if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {
30732
30733						const glBuffer = _gl.createBuffer();
30734						_gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer );
30735						_gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ );
30736						_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 );
30737						_gl.flush();
30738
30739						// check if the commands have finished every 8 ms
30740						const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 );
30741						await probeAsync( _gl, sync, 4 );
30742
30743						try {
30744
30745							_gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer );
30746							_gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer );
30747
30748						} finally {
30749
30750							_gl.deleteBuffer( glBuffer );
30751							_gl.deleteSync( sync );
30752
30753						}
30754
30755						return buffer;
30756
30757					}
30758
30759				} finally {
30760
30761					// restore framebuffer of current render target if necessary
30762
30763					const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null;
30764					state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30765
30766				}
30767
30768			}
30769
30770		};
30771
30772		this.copyFramebufferToTexture = function ( texture, position = null, level = 0 ) {
30773
30774			// support previous signature with position first
30775			if ( texture.isTexture !== true ) {
30776
30777				// @deprecated, r165
30778				console.warn( 'WebGLRenderer: copyFramebufferToTexture function signature has changed.' );
30779
30780				position = arguments[ 0 ] || null;
30781				texture = arguments[ 1 ];
30782
30783			}
30784
30785			const levelScale = Math.pow( 2, - level );
30786			const width = Math.floor( texture.image.width * levelScale );
30787			const height = Math.floor( texture.image.height * levelScale );
30788
30789			const x = position !== null ? position.x : 0;
30790			const y = position !== null ? position.y : 0;
30791
30792			textures.setTexture2D( texture, 0 );
30793
30794			_gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0, x, y, width, height );
30795
30796			state.unbindTexture();
30797
30798		};
30799
30800		this.copyTextureToTexture = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
30801
30802			// support previous signature with dstPosition first
30803			if ( srcTexture.isTexture !== true ) {
30804
30805				// @deprecated, r165
30806				console.warn( 'WebGLRenderer: copyTextureToTexture function signature has changed.' );
30807
30808				dstPosition = arguments[ 0 ] || null;
30809				srcTexture = arguments[ 1 ];
30810				dstTexture = arguments[ 2 ];
30811				level = arguments[ 3 ] || 0;
30812				srcRegion = null;
30813
30814			}
30815
30816			let width, height, minX, minY;
30817			let dstX, dstY;
30818			if ( srcRegion !== null ) {
30819
30820				width = srcRegion.max.x - srcRegion.min.x;
30821				height = srcRegion.max.y - srcRegion.min.y;
30822				minX = srcRegion.min.x;
30823				minY = srcRegion.min.y;
30824
30825			} else {
30826
30827				width = srcTexture.image.width;
30828				height = srcTexture.image.height;
30829				minX = 0;
30830				minY = 0;
30831
30832			}
30833
30834			if ( dstPosition !== null ) {
30835
30836				dstX = dstPosition.x;
30837				dstY = dstPosition.y;
30838
30839			} else {
30840
30841				dstX = 0;
30842				dstY = 0;
30843
30844			}
30845
30846			const glFormat = utils.convert( dstTexture.format );
30847			const glType = utils.convert( dstTexture.type );
30848
30849			textures.setTexture2D( dstTexture, 0 );
30850
30851			// As another texture upload may have changed pixelStorei
30852			// parameters, make sure they are correct for the dstTexture
30853			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
30854			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
30855			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
30856
30857			const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
30858			const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
30859			const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
30860			const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
30861			const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );
30862
30863			const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
30864
30865			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
30866			_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
30867			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
30868			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
30869
30870			if ( srcTexture.isDataTexture ) {
30871
30872				_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data );
30873
30874			} else {
30875
30876				if ( srcTexture.isCompressedTexture ) {
30877
30878					_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data );
30879
30880				} else {
30881
30882					_gl.texSubImage2D( _gl.TEXTURE_2D, level, dstX, dstY, glFormat, glType, image );
30883
30884				}
30885
30886			}
30887
30888			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
30889			_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
30890			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
30891			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
30892			_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
30893
30894			// Generate mipmaps only when copying level 0
30895			if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D );
30896
30897			state.unbindTexture();
30898
30899		};
30900
30901		this.copyTextureToTexture3D = function ( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) {
30902
30903			// support previous signature with source box first
30904			if ( srcTexture.isTexture !== true ) {
30905
30906				// @deprecated, r165
30907				console.warn( 'WebGLRenderer: copyTextureToTexture3D function signature has changed.' );
30908
30909				srcRegion = arguments[ 0 ] || null;
30910				dstPosition = arguments[ 1 ] || null;
30911				srcTexture = arguments[ 2 ];
30912				dstTexture = arguments[ 3 ];
30913				level = arguments[ 4 ] || 0;
30914
30915			}
30916
30917			let width, height, depth, minX, minY, minZ;
30918			let dstX, dstY, dstZ;
30919			const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
30920			if ( srcRegion !== null ) {
30921
30922				width = srcRegion.max.x - srcRegion.min.x;
30923				height = srcRegion.max.y - srcRegion.min.y;
30924				depth = srcRegion.max.z - srcRegion.min.z;
vendor: 4,292 bytes, lines 30925-31099
30925				minX = srcRegion.min.x;
30926				minY = srcRegion.min.y;
30927				minZ = srcRegion.min.z;
30928
30929			} else {
30930
30931				width = image.width;
30932				height = image.height;
30933				depth = image.depth;
30934				minX = 0;
30935				minY = 0;
30936				minZ = 0;
30937
30938			}
30939
30940			if ( dstPosition !== null ) {
30941
30942				dstX = dstPosition.x;
30943				dstY = dstPosition.y;
30944				dstZ = dstPosition.z;
30945
30946			} else {
30947
30948				dstX = 0;
30949				dstY = 0;
30950				dstZ = 0;
30951
30952			}
30953
30954			const glFormat = utils.convert( dstTexture.format );
30955			const glType = utils.convert( dstTexture.type );
30956			let glTarget;
30957
30958			if ( dstTexture.isData3DTexture ) {
30959
30960				textures.setTexture3D( dstTexture, 0 );
30961				glTarget = _gl.TEXTURE_3D;
30962
30963			} else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) {
30964
30965				textures.setTexture2DArray( dstTexture, 0 );
30966				glTarget = _gl.TEXTURE_2D_ARRAY;
30967
30968			} else {
30969
30970				console.warn( 'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' );
30971				return;
30972
30973			}
30974
30975			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
30976			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
30977			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
30978
30979			const currentUnpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
30980			const currentUnpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
30981			const currentUnpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
30982			const currentUnpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
30983			const currentUnpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );
30984
30985			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
30986			_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
30987			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, minX );
30988			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, minY );
30989			_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, minZ );
30990
30991			if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
30992
30993				_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image.data );
30994
30995			} else {
30996
30997				if ( dstTexture.isCompressedArrayTexture ) {
30998
30999					_gl.compressedTexSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, image.data );
31000
31001				} else {
31002
31003					_gl.texSubImage3D( glTarget, level, dstX, dstY, dstZ, width, height, depth, glFormat, glType, image );
31004
31005				}
31006
31007			}
31008
31009			_gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, currentUnpackRowLen );
31010			_gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight );
31011			_gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels );
31012			_gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows );
31013			_gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages );
31014
31015			// Generate mipmaps only when copying level 0
31016			if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget );
31017
31018			state.unbindTexture();
31019
31020		};
31021
31022		this.initRenderTarget = function ( target ) {
31023
31024			if ( properties.get( target ).__webglFramebuffer === undefined ) {
31025
31026				textures.setupRenderTarget( target );
31027
31028			}
31029
31030		};
31031
31032		this.initTexture = function ( texture ) {
31033
31034			if ( texture.isCubeTexture ) {
31035
31036				textures.setTextureCube( texture, 0 );
31037
31038			} else if ( texture.isData3DTexture ) {
31039
31040				textures.setTexture3D( texture, 0 );
31041
31042			} else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
31043
31044				textures.setTexture2DArray( texture, 0 );
31045
31046			} else {
31047
31048				textures.setTexture2D( texture, 0 );
31049
31050			}
31051
31052			state.unbindTexture();
31053
31054		};
31055
31056		this.resetState = function () {
31057
31058			_currentActiveCubeFace = 0;
31059			_currentActiveMipmapLevel = 0;
31060			_currentRenderTarget = null;
31061
31062			state.reset();
31063			bindingStates.reset();
31064
31065		};
31066
31067		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
31068
31069			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
31070
31071		}
31072
31073	}
31074
31075	get coordinateSystem() {
31076
31077		return WebGLCoordinateSystem;
31078
31079	}
31080
31081	get outputColorSpace() {
31082
31083		return this._outputColorSpace;
31084
31085	}
31086
31087	set outputColorSpace( colorSpace ) {
31088
31089		this._outputColorSpace = colorSpace;
31090
31091		const gl = this.getContext();
31092		gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb';
31093		gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb';
31094
31095	}
31096
31097}
31098
31099class FogExp2 {
vendor: 11,981 bytes, lines 31100-31786
31100
31101	constructor( color, density = 0.00025 ) {
31102
31103		this.isFogExp2 = true;
31104
31105		this.name = '';
31106
31107		this.color = new Color( color );
31108		this.density = density;
31109
31110	}
31111
31112	clone() {
31113
31114		return new FogExp2( this.color, this.density );
31115
31116	}
31117
31118	toJSON( /* meta */ ) {
31119
31120		return {
31121			type: 'FogExp2',
31122			name: this.name,
31123			color: this.color.getHex(),
31124			density: this.density
31125		};
31126
31127	}
31128
31129}
31130
31131class Fog {
31132
31133	constructor( color, near = 1, far = 1000 ) {
31134
31135		this.isFog = true;
31136
31137		this.name = '';
31138
31139		this.color = new Color( color );
31140
31141		this.near = near;
31142		this.far = far;
31143
31144	}
31145
31146	clone() {
31147
31148		return new Fog( this.color, this.near, this.far );
31149
31150	}
31151
31152	toJSON( /* meta */ ) {
31153
31154		return {
31155			type: 'Fog',
31156			name: this.name,
31157			color: this.color.getHex(),
31158			near: this.near,
31159			far: this.far
31160		};
31161
31162	}
31163
31164}
31165
31166class Scene extends Object3D {
31167
31168	constructor() {
31169
31170		super();
31171
31172		this.isScene = true;
31173
31174		this.type = 'Scene';
31175
31176		this.background = null;
31177		this.environment = null;
31178		this.fog = null;
31179
31180		this.backgroundBlurriness = 0;
31181		this.backgroundIntensity = 1;
31182		this.backgroundRotation = new Euler();
31183
31184		this.environmentIntensity = 1;
31185		this.environmentRotation = new Euler();
31186
31187		this.overrideMaterial = null;
31188
31189		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
31190
31191			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
31192
31193		}
31194
31195	}
31196
31197	copy( source, recursive ) {
31198
31199		super.copy( source, recursive );
31200
31201		if ( source.background !== null ) this.background = source.background.clone();
31202		if ( source.environment !== null ) this.environment = source.environment.clone();
31203		if ( source.fog !== null ) this.fog = source.fog.clone();
31204
31205		this.backgroundBlurriness = source.backgroundBlurriness;
31206		this.backgroundIntensity = source.backgroundIntensity;
31207		this.backgroundRotation.copy( source.backgroundRotation );
31208
31209		this.environmentIntensity = source.environmentIntensity;
31210		this.environmentRotation.copy( source.environmentRotation );
31211
31212		if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
31213
31214		this.matrixAutoUpdate = source.matrixAutoUpdate;
31215
31216		return this;
31217
31218	}
31219
31220	toJSON( meta ) {
31221
31222		const data = super.toJSON( meta );
31223
31224		if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
31225
31226		if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness;
31227		if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity;
31228		data.object.backgroundRotation = this.backgroundRotation.toArray();
31229
31230		if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity;
31231		data.object.environmentRotation = this.environmentRotation.toArray();
31232
31233		return data;
31234
31235	}
31236
31237}
31238
31239class InterleavedBuffer {
31240
31241	constructor( array, stride ) {
31242
31243		this.isInterleavedBuffer = true;
31244
31245		this.array = array;
31246		this.stride = stride;
31247		this.count = array !== undefined ? array.length / stride : 0;
31248
31249		this.usage = StaticDrawUsage;
31250		this._updateRange = { offset: 0, count: - 1 };
31251		this.updateRanges = [];
31252
31253		this.version = 0;
31254
31255		this.uuid = generateUUID();
31256
31257	}
31258
31259	onUploadCallback() {}
31260
31261	set needsUpdate( value ) {
31262
31263		if ( value === true ) this.version ++;
31264
31265	}
31266
31267	get updateRange() {
31268
31269		warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159
31270		return this._updateRange;
31271
31272	}
31273
31274	setUsage( value ) {
31275
31276		this.usage = value;
31277
31278		return this;
31279
31280	}
31281
31282	addUpdateRange( start, count ) {
31283
31284		this.updateRanges.push( { start, count } );
31285
31286	}
31287
31288	clearUpdateRanges() {
31289
31290		this.updateRanges.length = 0;
31291
31292	}
31293
31294	copy( source ) {
31295
31296		this.array = new source.array.constructor( source.array );
31297		this.count = source.count;
31298		this.stride = source.stride;
31299		this.usage = source.usage;
31300
31301		return this;
31302
31303	}
31304
31305	copyAt( index1, attribute, index2 ) {
31306
31307		index1 *= this.stride;
31308		index2 *= attribute.stride;
31309
31310		for ( let i = 0, l = this.stride; i < l; i ++ ) {
31311
31312			this.array[ index1 + i ] = attribute.array[ index2 + i ];
31313
31314		}
31315
31316		return this;
31317
31318	}
31319
31320	set( value, offset = 0 ) {
31321
31322		this.array.set( value, offset );
31323
31324		return this;
31325
31326	}
31327
31328	clone( data ) {
31329
31330		if ( data.arrayBuffers === undefined ) {
31331
31332			data.arrayBuffers = {};
31333
31334		}
31335
31336		if ( this.array.buffer._uuid === undefined ) {
31337
31338			this.array.buffer._uuid = generateUUID();
31339
31340		}
31341
31342		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
31343
31344			data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
31345
31346		}
31347
31348		const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
31349
31350		const ib = new this.constructor( array, this.stride );
31351		ib.setUsage( this.usage );
31352
31353		return ib;
31354
31355	}
31356
31357	onUpload( callback ) {
31358
31359		this.onUploadCallback = callback;
31360
31361		return this;
31362
31363	}
31364
31365	toJSON( data ) {
31366
31367		if ( data.arrayBuffers === undefined ) {
31368
31369			data.arrayBuffers = {};
31370
31371		}
31372
31373		// generate UUID for array buffer if necessary
31374
31375		if ( this.array.buffer._uuid === undefined ) {
31376
31377			this.array.buffer._uuid = generateUUID();
31378
31379		}
31380
31381		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
31382
31383			data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) );
31384
31385		}
31386
31387		//
31388
31389		return {
31390			uuid: this.uuid,
31391			buffer: this.array.buffer._uuid,
31392			type: this.array.constructor.name,
31393			stride: this.stride
31394		};
31395
31396	}
31397
31398}
31399
31400const _vector$6 = /*@__PURE__*/ new Vector3();
31401
31402class InterleavedBufferAttribute {
31403
31404	constructor( interleavedBuffer, itemSize, offset, normalized = false ) {
31405
31406		this.isInterleavedBufferAttribute = true;
31407
31408		this.name = '';
31409
31410		this.data = interleavedBuffer;
31411		this.itemSize = itemSize;
31412		this.offset = offset;
31413
31414		this.normalized = normalized;
31415
31416	}
31417
31418	get count() {
31419
31420		return this.data.count;
31421
31422	}
31423
31424	get array() {
31425
31426		return this.data.array;
31427
31428	}
31429
31430	set needsUpdate( value ) {
31431
31432		this.data.needsUpdate = value;
31433
31434	}
31435
31436	applyMatrix4( m ) {
31437
31438		for ( let i = 0, l = this.data.count; i < l; i ++ ) {
31439
31440			_vector$6.fromBufferAttribute( this, i );
31441
31442			_vector$6.applyMatrix4( m );
31443
31444			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
31445
31446		}
31447
31448		return this;
31449
31450	}
31451
31452	applyNormalMatrix( m ) {
31453
31454		for ( let i = 0, l = this.count; i < l; i ++ ) {
31455
31456			_vector$6.fromBufferAttribute( this, i );
31457
31458			_vector$6.applyNormalMatrix( m );
31459
31460			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
31461
31462		}
31463
31464		return this;
31465
31466	}
31467
31468	transformDirection( m ) {
31469
31470		for ( let i = 0, l = this.count; i < l; i ++ ) {
31471
31472			_vector$6.fromBufferAttribute( this, i );
31473
31474			_vector$6.transformDirection( m );
31475
31476			this.setXYZ( i, _vector$6.x, _vector$6.y, _vector$6.z );
31477
31478		}
31479
31480		return this;
31481
31482	}
31483
31484	getComponent( index, component ) {
31485
31486		let value = this.array[ index * this.data.stride + this.offset + component ];
31487
31488		if ( this.normalized ) value = denormalize( value, this.array );
31489
31490		return value;
31491
31492	}
31493
31494	setComponent( index, component, value ) {
31495
31496		if ( this.normalized ) value = normalize( value, this.array );
31497
31498		this.data.array[ index * this.data.stride + this.offset + component ] = value;
31499
31500		return this;
31501
31502	}
31503
31504	setX( index, x ) {
31505
31506		if ( this.normalized ) x = normalize( x, this.array );
31507
31508		this.data.array[ index * this.data.stride + this.offset ] = x;
31509
31510		return this;
31511
31512	}
31513
31514	setY( index, y ) {
31515
31516		if ( this.normalized ) y = normalize( y, this.array );
31517
31518		this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
31519
31520		return this;
31521
31522	}
31523
31524	setZ( index, z ) {
31525
31526		if ( this.normalized ) z = normalize( z, this.array );
31527
31528		this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
31529
31530		return this;
31531
31532	}
31533
31534	setW( index, w ) {
31535
31536		if ( this.normalized ) w = normalize( w, this.array );
31537
31538		this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
31539
31540		return this;
31541
31542	}
31543
31544	getX( index ) {
31545
31546		let x = this.data.array[ index * this.data.stride + this.offset ];
31547
31548		if ( this.normalized ) x = denormalize( x, this.array );
31549
31550		return x;
31551
31552	}
31553
31554	getY( index ) {
31555
31556		let y = this.data.array[ index * this.data.stride + this.offset + 1 ];
31557
31558		if ( this.normalized ) y = denormalize( y, this.array );
31559
31560		return y;
31561
31562	}
31563
31564	getZ( index ) {
31565
31566		let z = this.data.array[ index * this.data.stride + this.offset + 2 ];
31567
31568		if ( this.normalized ) z = denormalize( z, this.array );
31569
31570		return z;
31571
31572	}
31573
31574	getW( index ) {
31575
31576		let w = this.data.array[ index * this.data.stride + this.offset + 3 ];
31577
31578		if ( this.normalized ) w = denormalize( w, this.array );
31579
31580		return w;
31581
31582	}
31583
31584	setXY( index, x, y ) {
31585
31586		index = index * this.data.stride + this.offset;
31587
31588		if ( this.normalized ) {
31589
31590			x = normalize( x, this.array );
31591			y = normalize( y, this.array );
31592
31593		}
31594
31595		this.data.array[ index + 0 ] = x;
31596		this.data.array[ index + 1 ] = y;
31597
31598		return this;
31599
31600	}
31601
31602	setXYZ( index, x, y, z ) {
31603
31604		index = index * this.data.stride + this.offset;
31605
31606		if ( this.normalized ) {
31607
31608			x = normalize( x, this.array );
31609			y = normalize( y, this.array );
31610			z = normalize( z, this.array );
31611
31612		}
31613
31614		this.data.array[ index + 0 ] = x;
31615		this.data.array[ index + 1 ] = y;
31616		this.data.array[ index + 2 ] = z;
31617
31618		return this;
31619
31620	}
31621
31622	setXYZW( index, x, y, z, w ) {
31623
31624		index = index * this.data.stride + this.offset;
31625
31626		if ( this.normalized ) {
31627
31628			x = normalize( x, this.array );
31629			y = normalize( y, this.array );
31630			z = normalize( z, this.array );
31631			w = normalize( w, this.array );
31632
31633		}
31634
31635		this.data.array[ index + 0 ] = x;
31636		this.data.array[ index + 1 ] = y;
31637		this.data.array[ index + 2 ] = z;
31638		this.data.array[ index + 3 ] = w;
31639
31640		return this;
31641
31642	}
31643
31644	clone( data ) {
31645
31646		if ( data === undefined ) {
31647
31648			console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' );
31649
31650			const array = [];
31651
31652			for ( let i = 0; i < this.count; i ++ ) {
31653
31654				const index = i * this.data.stride + this.offset;
31655
31656				for ( let j = 0; j < this.itemSize; j ++ ) {
31657
31658					array.push( this.data.array[ index + j ] );
31659
31660				}
31661
31662			}
31663
31664			return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
31665
31666		} else {
31667
31668			if ( data.interleavedBuffers === undefined ) {
31669
31670				data.interleavedBuffers = {};
31671
31672			}
31673
31674			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
31675
31676				data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
31677
31678			}
31679
31680			return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
31681
31682		}
31683
31684	}
31685
31686	toJSON( data ) {
31687
31688		if ( data === undefined ) {
31689
31690			console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' );
31691
31692			const array = [];
31693
31694			for ( let i = 0; i < this.count; i ++ ) {
31695
31696				const index = i * this.data.stride + this.offset;
31697
31698				for ( let j = 0; j < this.itemSize; j ++ ) {
31699
31700					array.push( this.data.array[ index + j ] );
31701
31702				}
31703
31704			}
31705
31706			// de-interleave data and save it as an ordinary buffer attribute for now
31707
31708			return {
31709				itemSize: this.itemSize,
31710				type: this.array.constructor.name,
31711				array: array,
31712				normalized: this.normalized
31713			};
31714
31715		} else {
31716
31717			// save as true interleaved attribute
31718
31719			if ( data.interleavedBuffers === undefined ) {
31720
31721				data.interleavedBuffers = {};
31722
31723			}
31724
31725			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
31726
31727				data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
31728
31729			}
31730
31731			return {
31732				isInterleavedBufferAttribute: true,
31733				itemSize: this.itemSize,
31734				data: this.data.uuid,
31735				offset: this.offset,
31736				normalized: this.normalized
31737			};
31738
31739		}
31740
31741	}
31742
31743}
31744
31745class SpriteMaterial extends Material {
31746
31747	constructor( parameters ) {
31748
31749		super();
31750
31751		this.isSpriteMaterial = true;
31752
31753		this.type = 'SpriteMaterial';
31754
31755		this.color = new Color( 0xffffff );
31756
31757		this.map = null;
31758
31759		this.alphaMap = null;
31760
31761		this.rotation = 0;
31762
31763		this.sizeAttenuation = true;
31764
31765		this.transparent = true;
31766
31767		this.fog = true;
31768
31769		this.setValues( parameters );
31770
31771	}
31772
31773	copy( source ) {
31774
31775		super.copy( source );
31776
31777		this.color.copy( source.color );
31778
31779		this.map = source.map;
31780
31781		this.alphaMap = source.alphaMap;
31782
31783		this.rotation = source.rotation;
31784
31785		this.sizeAttenuation = source.sizeAttenuation;
31786
vendor: 6,736 bytes, lines 31787-32123
31787		this.fog = source.fog;
31788
31789		return this;
31790
31791	}
31792
31793}
31794
31795let _geometry;
31796
31797const _intersectPoint = /*@__PURE__*/ new Vector3();
31798const _worldScale = /*@__PURE__*/ new Vector3();
31799const _mvPosition = /*@__PURE__*/ new Vector3();
31800
31801const _alignedPosition = /*@__PURE__*/ new Vector2();
31802const _rotatedPosition = /*@__PURE__*/ new Vector2();
31803const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
31804
31805const _vA = /*@__PURE__*/ new Vector3();
31806const _vB = /*@__PURE__*/ new Vector3();
31807const _vC = /*@__PURE__*/ new Vector3();
31808
31809const _uvA = /*@__PURE__*/ new Vector2();
31810const _uvB = /*@__PURE__*/ new Vector2();
31811const _uvC = /*@__PURE__*/ new Vector2();
31812
31813class Sprite extends Object3D {
31814
31815	constructor( material = new SpriteMaterial() ) {
31816
31817		super();
31818
31819		this.isSprite = true;
31820
31821		this.type = 'Sprite';
31822
31823		if ( _geometry === undefined ) {
31824
31825			_geometry = new BufferGeometry();
31826
31827			const float32Array = new Float32Array( [
31828				- 0.5, - 0.5, 0, 0, 0,
31829				0.5, - 0.5, 0, 1, 0,
31830				0.5, 0.5, 0, 1, 1,
31831				- 0.5, 0.5, 0, 0, 1
31832			] );
31833
31834			const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
31835
31836			_geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
31837			_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
31838			_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
31839
31840		}
31841
31842		this.geometry = _geometry;
31843		this.material = material;
31844
31845		this.center = new Vector2( 0.5, 0.5 );
31846
31847	}
31848
31849	raycast( raycaster, intersects ) {
31850
31851		if ( raycaster.camera === null ) {
31852
31853			console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
31854
31855		}
31856
31857		_worldScale.setFromMatrixScale( this.matrixWorld );
31858
31859		_viewWorldMatrix.copy( raycaster.camera.matrixWorld );
31860		this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
31861
31862		_mvPosition.setFromMatrixPosition( this.modelViewMatrix );
31863
31864		if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
31865
31866			_worldScale.multiplyScalar( - _mvPosition.z );
31867
31868		}
31869
31870		const rotation = this.material.rotation;
31871		let sin, cos;
31872
31873		if ( rotation !== 0 ) {
31874
31875			cos = Math.cos( rotation );
31876			sin = Math.sin( rotation );
31877
31878		}
31879
31880		const center = this.center;
31881
31882		transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31883		transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31884		transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31885
31886		_uvA.set( 0, 0 );
31887		_uvB.set( 1, 0 );
31888		_uvC.set( 1, 1 );
31889
31890		// check first triangle
31891		let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint );
31892
31893		if ( intersect === null ) {
31894
31895			// check second triangle
31896			transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31897			_uvB.set( 0, 1 );
31898
31899			intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint );
31900			if ( intersect === null ) {
31901
31902				return;
31903
31904			}
31905
31906		}
31907
31908		const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
31909
31910		if ( distance < raycaster.near || distance > raycaster.far ) return;
31911
31912		intersects.push( {
31913
31914			distance: distance,
31915			point: _intersectPoint.clone(),
31916			uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ),
31917			face: null,
31918			object: this
31919
31920		} );
31921
31922	}
31923
31924	copy( source, recursive ) {
31925
31926		super.copy( source, recursive );
31927
31928		if ( source.center !== undefined ) this.center.copy( source.center );
31929
31930		this.material = source.material;
31931
31932		return this;
31933
31934	}
31935
31936}
31937
31938function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
31939
31940	// compute position in camera space
31941	_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
31942
31943	// to check if rotation is not zero
31944	if ( sin !== undefined ) {
31945
31946		_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
31947		_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
31948
31949	} else {
31950
31951		_rotatedPosition.copy( _alignedPosition );
31952
31953	}
31954
31955
31956	vertexPosition.copy( mvPosition );
31957	vertexPosition.x += _rotatedPosition.x;
31958	vertexPosition.y += _rotatedPosition.y;
31959
31960	// transform to world space
31961	vertexPosition.applyMatrix4( _viewWorldMatrix );
31962
31963}
31964
31965const _v1$2 = /*@__PURE__*/ new Vector3();
31966const _v2$1 = /*@__PURE__*/ new Vector3();
31967
31968class LOD extends Object3D {
31969
31970	constructor() {
31971
31972		super();
31973
31974		this._currentLevel = 0;
31975
31976		this.type = 'LOD';
31977
31978		Object.defineProperties( this, {
31979			levels: {
31980				enumerable: true,
31981				value: []
31982			},
31983			isLOD: {
31984				value: true,
31985			}
31986		} );
31987
31988		this.autoUpdate = true;
31989
31990	}
31991
31992	copy( source ) {
31993
31994		super.copy( source, false );
31995
31996		const levels = source.levels;
31997
31998		for ( let i = 0, l = levels.length; i < l; i ++ ) {
31999
32000			const level = levels[ i ];
32001
32002			this.addLevel( level.object.clone(), level.distance, level.hysteresis );
32003
32004		}
32005
32006		this.autoUpdate = source.autoUpdate;
32007
32008		return this;
32009
32010	}
32011
32012	addLevel( object, distance = 0, hysteresis = 0 ) {
32013
32014		distance = Math.abs( distance );
32015
32016		const levels = this.levels;
32017
32018		let l;
32019
32020		for ( l = 0; l < levels.length; l ++ ) {
32021
32022			if ( distance < levels[ l ].distance ) {
32023
32024				break;
32025
32026			}
32027
32028		}
32029
32030		levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } );
32031
32032		this.add( object );
32033
32034		return this;
32035
32036	}
32037
32038	getCurrentLevel() {
32039
32040		return this._currentLevel;
32041
32042	}
32043
32044
32045
32046	getObjectForDistance( distance ) {
32047
32048		const levels = this.levels;
32049
32050		if ( levels.length > 0 ) {
32051
32052			let i, l;
32053
32054			for ( i = 1, l = levels.length; i < l; i ++ ) {
32055
32056				let levelDistance = levels[ i ].distance;
32057
32058				if ( levels[ i ].object.visible ) {
32059
32060					levelDistance -= levelDistance * levels[ i ].hysteresis;
32061
32062				}
32063
32064				if ( distance < levelDistance ) {
32065
32066					break;
32067
32068				}
32069
32070			}
32071
32072			return levels[ i - 1 ].object;
32073
32074		}
32075
32076		return null;
32077
32078	}
32079
32080	raycast( raycaster, intersects ) {
32081
32082		const levels = this.levels;
32083
32084		if ( levels.length > 0 ) {
32085
32086			_v1$2.setFromMatrixPosition( this.matrixWorld );
32087
32088			const distance = raycaster.ray.origin.distanceTo( _v1$2 );
32089
32090			this.getObjectForDistance( distance ).raycast( raycaster, intersects );
32091
32092		}
32093
32094	}
32095
32096	update( camera ) {
32097
32098		const levels = this.levels;
32099
32100		if ( levels.length > 1 ) {
32101
32102			_v1$2.setFromMatrixPosition( camera.matrixWorld );
32103			_v2$1.setFromMatrixPosition( this.matrixWorld );
32104
32105			const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom;
32106
32107			levels[ 0 ].object.visible = true;
32108
32109			let i, l;
32110
32111			for ( i = 1, l = levels.length; i < l; i ++ ) {
32112
32113				let levelDistance = levels[ i ].distance;
32114
32115				if ( levels[ i ].object.visible ) {
32116
32117					levelDistance -= levelDistance * levels[ i ].hysteresis;
32118
32119				}
32120
32121				if ( distance >= levelDistance ) {
32122
32123					levels[ i - 1 ].object.visible = false;
vendor: 4,383 bytes, lines 32124-32357
32124					levels[ i ].object.visible = true;
32125
32126				} else {
32127
32128					break;
32129
32130				}
32131
32132			}
32133
32134			this._currentLevel = i - 1;
32135
32136			for ( ; i < l; i ++ ) {
32137
32138				levels[ i ].object.visible = false;
32139
32140			}
32141
32142		}
32143
32144	}
32145
32146	toJSON( meta ) {
32147
32148		const data = super.toJSON( meta );
32149
32150		if ( this.autoUpdate === false ) data.object.autoUpdate = false;
32151
32152		data.object.levels = [];
32153
32154		const levels = this.levels;
32155
32156		for ( let i = 0, l = levels.length; i < l; i ++ ) {
32157
32158			const level = levels[ i ];
32159
32160			data.object.levels.push( {
32161				object: level.object.uuid,
32162				distance: level.distance,
32163				hysteresis: level.hysteresis
32164			} );
32165
32166		}
32167
32168		return data;
32169
32170	}
32171
32172}
32173
32174const _basePosition = /*@__PURE__*/ new Vector3();
32175
32176const _skinIndex = /*@__PURE__*/ new Vector4();
32177const _skinWeight = /*@__PURE__*/ new Vector4();
32178
32179const _vector3 = /*@__PURE__*/ new Vector3();
32180const _matrix4 = /*@__PURE__*/ new Matrix4();
32181const _vertex = /*@__PURE__*/ new Vector3();
32182
32183const _sphere$4 = /*@__PURE__*/ new Sphere();
32184const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4();
32185const _ray$2 = /*@__PURE__*/ new Ray();
32186
32187class SkinnedMesh extends Mesh {
32188
32189	constructor( geometry, material ) {
32190
32191		super( geometry, material );
32192
32193		this.isSkinnedMesh = true;
32194
32195		this.type = 'SkinnedMesh';
32196
32197		this.bindMode = AttachedBindMode;
32198		this.bindMatrix = new Matrix4();
32199		this.bindMatrixInverse = new Matrix4();
32200
32201		this.boundingBox = null;
32202		this.boundingSphere = null;
32203
32204	}
32205
32206	computeBoundingBox() {
32207
32208		const geometry = this.geometry;
32209
32210		if ( this.boundingBox === null ) {
32211
32212			this.boundingBox = new Box3();
32213
32214		}
32215
32216		this.boundingBox.makeEmpty();
32217
32218		const positionAttribute = geometry.getAttribute( 'position' );
32219
32220		for ( let i = 0; i < positionAttribute.count; i ++ ) {
32221
32222			this.getVertexPosition( i, _vertex );
32223			this.boundingBox.expandByPoint( _vertex );
32224
32225		}
32226
32227	}
32228
32229	computeBoundingSphere() {
32230
32231		const geometry = this.geometry;
32232
32233		if ( this.boundingSphere === null ) {
32234
32235			this.boundingSphere = new Sphere();
32236
32237		}
32238
32239		this.boundingSphere.makeEmpty();
32240
32241		const positionAttribute = geometry.getAttribute( 'position' );
32242
32243		for ( let i = 0; i < positionAttribute.count; i ++ ) {
32244
32245			this.getVertexPosition( i, _vertex );
32246			this.boundingSphere.expandByPoint( _vertex );
32247
32248		}
32249
32250	}
32251
32252	copy( source, recursive ) {
32253
32254		super.copy( source, recursive );
32255
32256		this.bindMode = source.bindMode;
32257		this.bindMatrix.copy( source.bindMatrix );
32258		this.bindMatrixInverse.copy( source.bindMatrixInverse );
32259
32260		this.skeleton = source.skeleton;
32261
32262		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
32263		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
32264
32265		return this;
32266
32267	}
32268
32269	raycast( raycaster, intersects ) {
32270
32271		const material = this.material;
32272		const matrixWorld = this.matrixWorld;
32273
32274		if ( material === undefined ) return;
32275
32276		// test with bounding sphere in world space
32277
32278		if ( this.boundingSphere === null ) this.computeBoundingSphere();
32279
32280		_sphere$4.copy( this.boundingSphere );
32281		_sphere$4.applyMatrix4( matrixWorld );
32282
32283		if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return;
32284
32285		// convert ray to local space of skinned mesh
32286
32287		_inverseMatrix$2.copy( matrixWorld ).invert();
32288		_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
32289
32290		// test with bounding box in local space
32291
32292		if ( this.boundingBox !== null ) {
32293
32294			if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return;
32295
32296		}
32297
32298		// test for intersections with geometry
32299
32300		this._computeIntersections( raycaster, intersects, _ray$2 );
32301
32302	}
32303
32304	getVertexPosition( index, target ) {
32305
32306		super.getVertexPosition( index, target );
32307
32308		this.applyBoneTransform( index, target );
32309
32310		return target;
32311
32312	}
32313
32314	bind( skeleton, bindMatrix ) {
32315
32316		this.skeleton = skeleton;
32317
32318		if ( bindMatrix === undefined ) {
32319
32320			this.updateMatrixWorld( true );
32321
32322			this.skeleton.calculateInverses();
32323
32324			bindMatrix = this.matrixWorld;
32325
32326		}
32327
32328		this.bindMatrix.copy( bindMatrix );
32329		this.bindMatrixInverse.copy( bindMatrix ).invert();
32330
32331	}
32332
32333	pose() {
32334
32335		this.skeleton.pose();
32336
32337	}
32338
32339	normalizeSkinWeights() {
32340
32341		const vector = new Vector4();
32342
32343		const skinWeight = this.geometry.attributes.skinWeight;
32344
32345		for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
32346
32347			vector.fromBufferAttribute( skinWeight, i );
32348
32349			const scale = 1.0 / vector.manhattanLength();
32350
32351			if ( scale !== Infinity ) {
32352
32353				vector.multiplyScalar( scale );
32354
32355			} else {
32356
32357				vector.set( 1, 0, 0, 0 );
vendor: 12,910 bytes, lines 32357-33029
32357 // do something reasonable
32358
32359			}
32360
32361			skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
32362
32363		}
32364
32365	}
32366
32367	updateMatrixWorld( force ) {
32368
32369		super.updateMatrixWorld( force );
32370
32371		if ( this.bindMode === AttachedBindMode ) {
32372
32373			this.bindMatrixInverse.copy( this.matrixWorld ).invert();
32374
32375		} else if ( this.bindMode === DetachedBindMode ) {
32376
32377			this.bindMatrixInverse.copy( this.bindMatrix ).invert();
32378
32379		} else {
32380
32381			console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
32382
32383		}
32384
32385	}
32386
32387	applyBoneTransform( index, vector ) {
32388
32389		const skeleton = this.skeleton;
32390		const geometry = this.geometry;
32391
32392		_skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
32393		_skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
32394
32395		_basePosition.copy( vector ).applyMatrix4( this.bindMatrix );
32396
32397		vector.set( 0, 0, 0 );
32398
32399		for ( let i = 0; i < 4; i ++ ) {
32400
32401			const weight = _skinWeight.getComponent( i );
32402
32403			if ( weight !== 0 ) {
32404
32405				const boneIndex = _skinIndex.getComponent( i );
32406
32407				_matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
32408
32409				vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight );
32410
32411			}
32412
32413		}
32414
32415		return vector.applyMatrix4( this.bindMatrixInverse );
32416
32417	}
32418
32419}
32420
32421class Bone extends Object3D {
32422
32423	constructor() {
32424
32425		super();
32426
32427		this.isBone = true;
32428
32429		this.type = 'Bone';
32430
32431	}
32432
32433}
32434
32435class DataTexture extends Texture {
32436
32437	constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) {
32438
32439		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
32440
32441		this.isDataTexture = true;
32442
32443		this.image = { data: data, width: width, height: height };
32444
32445		this.generateMipmaps = false;
32446		this.flipY = false;
32447		this.unpackAlignment = 1;
32448
32449	}
32450
32451}
32452
32453const _offsetMatrix = /*@__PURE__*/ new Matrix4();
32454const _identityMatrix$1 = /*@__PURE__*/ new Matrix4();
32455
32456class Skeleton {
32457
32458	constructor( bones = [], boneInverses = [] ) {
32459
32460		this.uuid = generateUUID();
32461
32462		this.bones = bones.slice( 0 );
32463		this.boneInverses = boneInverses;
32464		this.boneMatrices = null;
32465
32466		this.boneTexture = null;
32467
32468		this.init();
32469
32470	}
32471
32472	init() {
32473
32474		const bones = this.bones;
32475		const boneInverses = this.boneInverses;
32476
32477		this.boneMatrices = new Float32Array( bones.length * 16 );
32478
32479		// calculate inverse bone matrices if necessary
32480
32481		if ( boneInverses.length === 0 ) {
32482
32483			this.calculateInverses();
32484
32485		} else {
32486
32487			// handle special case
32488
32489			if ( bones.length !== boneInverses.length ) {
32490
32491				console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
32492
32493				this.boneInverses = [];
32494
32495				for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32496
32497					this.boneInverses.push( new Matrix4() );
32498
32499				}
32500
32501			}
32502
32503		}
32504
32505	}
32506
32507	calculateInverses() {
32508
32509		this.boneInverses.length = 0;
32510
32511		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32512
32513			const inverse = new Matrix4();
32514
32515			if ( this.bones[ i ] ) {
32516
32517				inverse.copy( this.bones[ i ].matrixWorld ).invert();
32518
32519			}
32520
32521			this.boneInverses.push( inverse );
32522
32523		}
32524
32525	}
32526
32527	pose() {
32528
32529		// recover the bind-time world matrices
32530
32531		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32532
32533			const bone = this.bones[ i ];
32534
32535			if ( bone ) {
32536
32537				bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
32538
32539			}
32540
32541		}
32542
32543		// compute the local matrices, positions, rotations and scales
32544
32545		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32546
32547			const bone = this.bones[ i ];
32548
32549			if ( bone ) {
32550
32551				if ( bone.parent && bone.parent.isBone ) {
32552
32553					bone.matrix.copy( bone.parent.matrixWorld ).invert();
32554					bone.matrix.multiply( bone.matrixWorld );
32555
32556				} else {
32557
32558					bone.matrix.copy( bone.matrixWorld );
32559
32560				}
32561
32562				bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
32563
32564			}
32565
32566		}
32567
32568	}
32569
32570	update() {
32571
32572		const bones = this.bones;
32573		const boneInverses = this.boneInverses;
32574		const boneMatrices = this.boneMatrices;
32575		const boneTexture = this.boneTexture;
32576
32577		// flatten bone matrices to array
32578
32579		for ( let i = 0, il = bones.length; i < il; i ++ ) {
32580
32581			// compute the offset between the current and the original transform
32582
32583			const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1;
32584
32585			_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
32586			_offsetMatrix.toArray( boneMatrices, i * 16 );
32587
32588		}
32589
32590		if ( boneTexture !== null ) {
32591
32592			boneTexture.needsUpdate = true;
32593
32594		}
32595
32596	}
32597
32598	clone() {
32599
32600		return new Skeleton( this.bones, this.boneInverses );
32601
32602	}
32603
32604	computeBoneTexture() {
32605
32606		// layout (1 matrix = 4 pixels)
32607		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
32608		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
32609		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
32610		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
32611		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
32612
32613		let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
32614		size = Math.ceil( size / 4 ) * 4;
32615		size = Math.max( size, 4 );
32616
32617		const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
32618		boneMatrices.set( this.boneMatrices ); // copy current values
32619
32620		const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
32621		boneTexture.needsUpdate = true;
32622
32623		this.boneMatrices = boneMatrices;
32624		this.boneTexture = boneTexture;
32625
32626		return this;
32627
32628	}
32629
32630	getBoneByName( name ) {
32631
32632		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
32633
32634			const bone = this.bones[ i ];
32635
32636			if ( bone.name === name ) {
32637
32638				return bone;
32639
32640			}
32641
32642		}
32643
32644		return undefined;
32645
32646	}
32647
32648	dispose( ) {
32649
32650		if ( this.boneTexture !== null ) {
32651
32652			this.boneTexture.dispose();
32653
32654			this.boneTexture = null;
32655
32656		}
32657
32658	}
32659
32660	fromJSON( json, bones ) {
32661
32662		this.uuid = json.uuid;
32663
32664		for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
32665
32666			const uuid = json.bones[ i ];
32667			let bone = bones[ uuid ];
32668
32669			if ( bone === undefined ) {
32670
32671				console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid );
32672				bone = new Bone();
32673
32674			}
32675
32676			this.bones.push( bone );
32677			this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
32678
32679		}
32680
32681		this.init();
32682
32683		return this;
32684
32685	}
32686
32687	toJSON() {
32688
32689		const data = {
32690			metadata: {
32691				version: 4.6,
32692				type: 'Skeleton',
32693				generator: 'Skeleton.toJSON'
32694			},
32695			bones: [],
32696			boneInverses: []
32697		};
32698
32699		data.uuid = this.uuid;
32700
32701		const bones = this.bones;
32702		const boneInverses = this.boneInverses;
32703
32704		for ( let i = 0, l = bones.length; i < l; i ++ ) {
32705
32706			const bone = bones[ i ];
32707			data.bones.push( bone.uuid );
32708
32709			const boneInverse = boneInverses[ i ];
32710			data.boneInverses.push( boneInverse.toArray() );
32711
32712		}
32713
32714		return data;
32715
32716	}
32717
32718}
32719
32720class InstancedBufferAttribute extends BufferAttribute {
32721
32722	constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {
32723
32724		super( array, itemSize, normalized );
32725
32726		this.isInstancedBufferAttribute = true;
32727
32728		this.meshPerAttribute = meshPerAttribute;
32729
32730	}
32731
32732	copy( source ) {
32733
32734		super.copy( source );
32735
32736		this.meshPerAttribute = source.meshPerAttribute;
32737
32738		return this;
32739
32740	}
32741
32742	toJSON() {
32743
32744		const data = super.toJSON();
32745
32746		data.meshPerAttribute = this.meshPerAttribute;
32747
32748		data.isInstancedBufferAttribute = true;
32749
32750		return data;
32751
32752	}
32753
32754}
32755
32756const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
32757const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
32758
32759const _instanceIntersects = [];
32760
32761const _box3 = /*@__PURE__*/ new Box3();
32762const _identity = /*@__PURE__*/ new Matrix4();
32763const _mesh$1 = /*@__PURE__*/ new Mesh();
32764const _sphere$3 = /*@__PURE__*/ new Sphere();
32765
32766class InstancedMesh extends Mesh {
32767
32768	constructor( geometry, material, count ) {
32769
32770		super( geometry, material );
32771
32772		this.isInstancedMesh = true;
32773
32774		this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
32775		this.instanceColor = null;
32776		this.morphTexture = null;
32777
32778		this.count = count;
32779
32780		this.boundingBox = null;
32781		this.boundingSphere = null;
32782
32783		for ( let i = 0; i < count; i ++ ) {
32784
32785			this.setMatrixAt( i, _identity );
32786
32787		}
32788
32789	}
32790
32791	computeBoundingBox() {
32792
32793		const geometry = this.geometry;
32794		const count = this.count;
32795
32796		if ( this.boundingBox === null ) {
32797
32798			this.boundingBox = new Box3();
32799
32800		}
32801
32802		if ( geometry.boundingBox === null ) {
32803
32804			geometry.computeBoundingBox();
32805
32806		}
32807
32808		this.boundingBox.makeEmpty();
32809
32810		for ( let i = 0; i < count; i ++ ) {
32811
32812			this.getMatrixAt( i, _instanceLocalMatrix );
32813
32814			_box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix );
32815
32816			this.boundingBox.union( _box3 );
32817
32818		}
32819
32820	}
32821
32822	computeBoundingSphere() {
32823
32824		const geometry = this.geometry;
32825		const count = this.count;
32826
32827		if ( this.boundingSphere === null ) {
32828
32829			this.boundingSphere = new Sphere();
32830
32831		}
32832
32833		if ( geometry.boundingSphere === null ) {
32834
32835			geometry.computeBoundingSphere();
32836
32837		}
32838
32839		this.boundingSphere.makeEmpty();
32840
32841		for ( let i = 0; i < count; i ++ ) {
32842
32843			this.getMatrixAt( i, _instanceLocalMatrix );
32844
32845			_sphere$3.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix );
32846
32847			this.boundingSphere.union( _sphere$3 );
32848
32849		}
32850
32851	}
32852
32853	copy( source, recursive ) {
32854
32855		super.copy( source, recursive );
32856
32857		this.instanceMatrix.copy( source.instanceMatrix );
32858
32859		if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone();
32860		if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
32861
32862		this.count = source.count;
32863
32864		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
32865		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
32866
32867		return this;
32868
32869	}
32870
32871	getColorAt( index, color ) {
32872
32873		color.fromArray( this.instanceColor.array, index * 3 );
32874
32875	}
32876
32877	getMatrixAt( index, matrix ) {
32878
32879		matrix.fromArray( this.instanceMatrix.array, index * 16 );
32880
32881	}
32882
32883	getMorphAt( index, object ) {
32884
32885		const objectInfluences = object.morphTargetInfluences;
32886
32887		const array = this.morphTexture.source.data.data;
32888
32889		const len = objectInfluences.length + 1; // All influences + the baseInfluenceSum
32890
32891		const dataIndex = index * len + 1; // Skip the baseInfluenceSum at the beginning
32892
32893		for ( let i = 0; i < objectInfluences.length; i ++ ) {
32894
32895			objectInfluences[ i ] = array[ dataIndex + i ];
32896
32897		}
32898
32899	}
32900
32901	raycast( raycaster, intersects ) {
32902
32903		const matrixWorld = this.matrixWorld;
32904		const raycastTimes = this.count;
32905
32906		_mesh$1.geometry = this.geometry;
32907		_mesh$1.material = this.material;
32908
32909		if ( _mesh$1.material === undefined ) return;
32910
32911		// test with bounding sphere first
32912
32913		if ( this.boundingSphere === null ) this.computeBoundingSphere();
32914
32915		_sphere$3.copy( this.boundingSphere );
32916		_sphere$3.applyMatrix4( matrixWorld );
32917
32918		if ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) return;
32919
32920		// now test each instance
32921
32922		for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
32923
32924			// calculate the world matrix for each instance
32925
32926			this.getMatrixAt( instanceId, _instanceLocalMatrix );
32927
32928			_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
32929
32930			// the mesh represents this single instance
32931
32932			_mesh$1.matrixWorld = _instanceWorldMatrix;
32933
32934			_mesh$1.raycast( raycaster, _instanceIntersects );
32935
32936			// process the result of raycast
32937
32938			for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
32939
32940				const intersect = _instanceIntersects[ i ];
32941				intersect.instanceId = instanceId;
32942				intersect.object = this;
32943				intersects.push( intersect );
32944
32945			}
32946
32947			_instanceIntersects.length = 0;
32948
32949		}
32950
32951	}
32952
32953	setColorAt( index, color ) {
32954
32955		if ( this.instanceColor === null ) {
32956
32957			this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ), 3 );
32958
32959		}
32960
32961		color.toArray( this.instanceColor.array, index * 3 );
32962
32963	}
32964
32965	setMatrixAt( index, matrix ) {
32966
32967		matrix.toArray( this.instanceMatrix.array, index * 16 );
32968
32969	}
32970
32971	setMorphAt( index, object ) {
32972
32973		const objectInfluences = object.morphTargetInfluences;
32974
32975		const len = objectInfluences.length + 1; // morphBaseInfluence + all influences
32976
32977		if ( this.morphTexture === null ) {
32978
32979			this.morphTexture = new DataTexture( new Float32Array( len * this.count ), len, this.count, RedFormat, FloatType );
32980
32981		}
32982
32983		const array = this.morphTexture.source.data.data;
32984
32985		let morphInfluencesSum = 0;
32986
32987		for ( let i = 0; i < objectInfluences.length; i ++ ) {
32988
32989			morphInfluencesSum += objectInfluences[ i ];
32990
32991		}
32992
32993		const morphBaseInfluence = this.geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
32994
32995		const dataIndex = len * index;
32996
32997		array[ dataIndex ] = morphBaseInfluence;
32998
32999		array.set( objectInfluences, dataIndex + 1 );
33000
33001	}
33002
33003	updateMorphTargets() {
33004
33005	}
33006
33007	dispose() {
33008
33009		this.dispatchEvent( { type: 'dispose' } );
33010
33011		if ( this.morphTexture !== null ) {
33012
33013			this.morphTexture.dispose();
33014			this.morphTexture = null;
33015
33016		}
33017
33018		return this;
33019
33020	}
33021
33022}
33023
33024function sortOpaque( a, b ) {
33025
33026	return a.z - b.z;
33027
33028}
33029
vendor: 4,321 bytes, lines 33030-33204
33030function sortTransparent( a, b ) {
33031
33032	return b.z - a.z;
33033
33034}
33035
33036class MultiDrawRenderList {
33037
33038	constructor() {
33039
33040		this.index = 0;
33041		this.pool = [];
33042		this.list = [];
33043
33044	}
33045
33046	push( drawRange, z ) {
33047
33048		const pool = this.pool;
33049		const list = this.list;
33050		if ( this.index >= pool.length ) {
33051
33052			pool.push( {
33053
33054				start: - 1,
33055				count: - 1,
33056				z: - 1,
33057
33058			} );
33059
33060		}
33061
33062		const item = pool[ this.index ];
33063		list.push( item );
33064		this.index ++;
33065
33066		item.start = drawRange.start;
33067		item.count = drawRange.count;
33068		item.z = z;
33069
33070	}
33071
33072	reset() {
33073
33074		this.list.length = 0;
33075		this.index = 0;
33076
33077	}
33078
33079}
33080
33081const ID_ATTR_NAME = 'batchId';
33082const _matrix$1 = /*@__PURE__*/ new Matrix4();
33083const _invMatrixWorld = /*@__PURE__*/ new Matrix4();
33084const _identityMatrix = /*@__PURE__*/ new Matrix4();
33085const _whiteColor = /*@__PURE__*/ new Color( 1, 1, 1 );
33086const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4();
33087const _frustum = /*@__PURE__*/ new Frustum();
33088const _box$1 = /*@__PURE__*/ new Box3();
33089const _sphere$2 = /*@__PURE__*/ new Sphere();
33090const _vector$5 = /*@__PURE__*/ new Vector3();
33091const _forward = /*@__PURE__*/ new Vector3();
33092const _temp = /*@__PURE__*/ new Vector3();
33093const _renderList = /*@__PURE__*/ new MultiDrawRenderList();
33094const _mesh = /*@__PURE__*/ new Mesh();
33095const _batchIntersects = [];
33096
33097// @TODO: SkinnedMesh support?
33098// @TODO: geometry.groups support?
33099// @TODO: geometry.drawRange support?
33100// @TODO: geometry.morphAttributes support?
33101// @TODO: Support uniform parameter per geometry
33102// @TODO: Add an "optimize" function to pack geometry and remove data gaps
33103
33104// copies data from attribute "src" into "target" starting at "targetOffset"
33105function copyAttributeData( src, target, targetOffset = 0 ) {
33106
33107	const itemSize = target.itemSize;
33108	if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) {
33109
33110		// use the component getters and setters if the array data cannot
33111		// be copied directly
33112		const vertexCount = src.count;
33113		for ( let i = 0; i < vertexCount; i ++ ) {
33114
33115			for ( let c = 0; c < itemSize; c ++ ) {
33116
33117				target.setComponent( i + targetOffset, c, src.getComponent( i, c ) );
33118
33119			}
33120
33121		}
33122
33123	} else {
33124
33125		// faster copy approach using typed array set function
33126		target.array.set( src.array, targetOffset * itemSize );
33127
33128	}
33129
33130	target.needsUpdate = true;
33131
33132}
33133
33134class BatchedMesh extends Mesh {
33135
33136	get maxGeometryCount() {
33137
33138		return this._maxGeometryCount;
33139
33140	}
33141
33142	constructor( maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) {
33143
33144		super( new BufferGeometry(), material );
33145
33146		this.isBatchedMesh = true;
33147		this.perObjectFrustumCulled = true;
33148		this.sortObjects = true;
33149		this.boundingBox = null;
33150		this.boundingSphere = null;
33151		this.customSort = null;
33152
33153		this._drawRanges = [];
33154		this._reservedRanges = [];
33155
33156		this._visibility = [];
33157		this._active = [];
33158		this._bounds = [];
33159
33160		this._maxGeometryCount = maxGeometryCount;
33161		this._maxVertexCount = maxVertexCount;
33162		this._maxIndexCount = maxIndexCount;
33163
33164		this._geometryInitialized = false;
33165		this._geometryCount = 0;
33166		this._multiDrawCounts = new Int32Array( maxGeometryCount );
33167		this._multiDrawStarts = new Int32Array( maxGeometryCount );
33168		this._multiDrawCount = 0;
33169		this._multiDrawInstances = null;
33170		this._visibilityChanged = true;
33171
33172		// Local matrix per geometry by using data texture
33173		this._matricesTexture = null;
33174
33175		this._initMatricesTexture();
33176
33177		// Local color per geometry by using data texture
33178		this._colorsTexture = null;
33179
33180	}
33181
33182	_initMatricesTexture() {
33183
33184		// layout (1 matrix = 4 pixels)
33185		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
33186		//  with  8x8  pixel texture max   16 matrices * 4 pixels =  (8 * 8)
33187		//       16x16 pixel texture max   64 matrices * 4 pixels = (16 * 16)
33188		//       32x32 pixel texture max  256 matrices * 4 pixels = (32 * 32)
33189		//       64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64)
33190
33191		let size = Math.sqrt( this._maxGeometryCount * 4 ); // 4 pixels needed for 1 matrix
33192		size = Math.ceil( size / 4 ) * 4;
33193		size = Math.max( size, 4 );
33194
33195		const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
33196		const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType );
33197
33198		this._matricesTexture = matricesTexture;
33199
33200	}
33201
33202	_initColorsTexture() {
33203
33204		let size = Math.sqrt( this._maxGeometryCount );
33205		size = Math.ceil( size );
33206
33207		// 4 floats per RGBA pixel initialized to white
33208		const colorsArray = new Float32Array( size * size * 4 ).fill( 1 );
33209		const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType );
33210		colorsTexture.colorSpace = ColorManagement.workingColorSpace;
33211
33212		this._colorsTexture = colorsTexture;
33213
33214	}
33215
33216	_initializeGeometry( reference ) {
33217
33218		const geometry = this.geometry;
33219		const maxVertexCount = this._maxVertexCount;
33220		const maxGeometryCount = this._maxGeometryCount;
33221		const maxIndexCount = this._maxIndexCount;
33222		if ( this._geometryInitialized === false ) {
33223
33224			for ( const attributeName in reference.attributes ) {
33225
33226				const srcAttribute = reference.getAttribute( attributeName );
33227				const { array, itemSize, normalized } = srcAttribute;
33228
33229				const dstArray = new array.constructor( maxVertexCount * itemSize );
33230				const dstAttribute = new BufferAttribute( dstArray, itemSize, normalized );
33231
33232				geometry.setAttribute( attributeName, dstAttribute );
33233
33234			}
33235
33236			if ( reference.getIndex() !== null ) {
33237
33238				const indexArray = maxVertexCount > 65536
33239					? new Uint32Array( maxIndexCount )
33240					: new Uint16Array( maxIndexCount );
33241
33242				geometry.setIndex( new BufferAttribute( indexArray, 1 ) );
33243
33244			}
33245
33246			const idArray = maxGeometryCount > 65536
33247				? new Uint32Array( maxVertexCount )
33248				: new Uint16Array( maxVertexCount );
33249			geometry.setAttribute( ID_ATTR_NAME, new BufferAttribute( idArray, 1 ) );
33250
33251			this._geometryInitialized = true;
33252
33253		}
33254
33255	}
33256
33257	// Make sure the geometry is compatible with the existing combined geometry attributes
33258	_validateGeometry( geometry ) {
33259
33260		// check that the geometry doesn't have a version of our reserved id attribute
33261		if ( geometry.getAttribute( ID_ATTR_NAME ) ) {
33262
33263			throw new Error( `BatchedMesh: Geometry cannot use attribute "${ ID_ATTR_NAME }"` );
33264
33265		}
33266
33267		// check to ensure the geometries are using consistent attributes and indices
33268		const batchGeometry = this.geometry;
33269		if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
33270
33271			throw new Error( 'BatchedMesh: All geometries must consistently have "index".' );
33272
33273		}
33274
33275		for ( const attributeName in batchGeometry.attributes ) {
33276
33277			if ( attributeName === ID_ATTR_NAME ) {
33278
33279				continue;
33280
33281			}
33282
33283			if ( ! geometry.hasAttribute( attributeName ) ) {
33284
33285				throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
33286
33287			}
33288
33289			const srcAttribute = geometry.getAttribute( attributeName );
33290			const dstAttribute = batchGeometry.getAttribute( attributeName );
33291			if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
33292
33293				throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
33294
33295			}
33296
33297		}
33298
33299	}
33300
33301	setCustomSort( func ) {
33302
33303		this.customSort = func;
33304		return this;
33305
33306	}
33307
33308	computeBoundingBox() {
33309
33310		if ( this.boundingBox === null ) {
33311
33312			this.boundingBox = new Box3();
33313
33314		}
33315
33316		const geometryCount = this._geometryCount;
33317		const boundingBox = this.boundingBox;
33318		const active = this._active;
33319
33320		boundingBox.makeEmpty();
33321		for ( let i = 0; i < geometryCount; i ++ ) {
33322
33323			if ( active[ i ] === false ) continue;
33324
33325			this.getMatrixAt( i, _matrix$1 );
33326			this.getBoundingBoxAt( i, _box$1 ).applyMatrix4( _matrix$1 );
33327			boundingBox.union( _box$1 );
33328
33329		}
33330
33331	}
33332
33333	computeBoundingSphere() {
33334
33335		if ( this.boundingSphere === null ) {
33336
33337			this.boundingSphere = new Sphere();
33338
33339		}
33340
33341		const geometryCount = this._geometryCount;
33342		const boundingSphere = this.boundingSphere;
33343		const active = this._active;
33344
33345		boundingSphere.makeEmpty();
33346		for ( let i = 0; i < geometryCount; i ++ ) {
33347
33348			if ( active[ i ] === false ) continue;
33349
33350			this.getMatrixAt( i, _matrix$1 );
33351			this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 );
33352			boundingSphere.union( _sphere$2 );
33353
33354		}
33355
33356	}
33357
33358	addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) {
33359
33360		this._initializeGeometry( geometry );
33361
33362		this._validateGeometry( geometry );
33363
33364		// ensure we're not over geometry
33365		if ( this._geometryCount >= this._maxGeometryCount ) {
33366
33367			throw new Error( 'BatchedMesh: Maximum geometry count reached.' );
33368
33369		}
33370
33371		// get the necessary range fo the geometry
33372		const reservedRange = {
33373			vertexStart: - 1,
33374			vertexCount: - 1,
33375			indexStart: - 1,
33376			indexCount: - 1,
33377		};
33378
33379		let lastRange = null;
33380		const reservedRanges = this._reservedRanges;
33381		const drawRanges = this._drawRanges;
33382		const bounds = this._bounds;
33383		if ( this._geometryCount !== 0 ) {
33384
33385			lastRange = reservedRanges[ reservedRanges.length - 1 ];
33386
33387		}
33388
33389		if ( vertexCount === - 1 ) {
33390
33391			reservedRange.vertexCount = geometry.getAttribute( 'position' ).count;
33392
33393		} else {
33394
33395			reservedRange.vertexCount = vertexCount;
33396
33397		}
33398
33399		if ( lastRange === null ) {
33400
33401			reservedRange.vertexStart = 0;
33402
33403		} else {
33404
33405			reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount;
33406
33407		}
33408
33409		const index = geometry.getIndex();
33410		const hasIndex = index !== null;
33411		if ( hasIndex ) {
33412
33413			if ( indexCount	=== - 1 ) {
33414
33415				reservedRange.indexCount = index.count;
33416
33417			} else {
33418
33419				reservedRange.indexCount = indexCount;
33420
33421			}
33422
33423			if ( lastRange === null ) {
33424
33425				reservedRange.indexStart = 0;
33426
33427			} else {
33428
33429				reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount;
33430
33431			}
33432
33433		}
33434
33435		if (
33436			reservedRange.indexStart !== - 1 &&
33437			reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount ||
33438			reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount
33439		) {
33440
33441			throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
33442
33443		}
33444
33445		const visibility = this._visibility;
33446		const active = this._active;
33447		const matricesTexture = this._matricesTexture;
33448		const matricesArray = this._matricesTexture.image.data;
33449		const colorsTexture = this._colorsTexture;
33450
33451		// push new visibility states
33452		visibility.push( true );
33453		active.push( true );
33454
33455		// update id
33456		const geometryId = this._geometryCount;
33457		this._geometryCount ++;
33458
33459		// initialize matrix information
33460		_identityMatrix.toArray( matricesArray, geometryId * 16 );
33461		matricesTexture.needsUpdate = true;
33462
33463		// initialize the color to white
33464		if ( colorsTexture !== null ) {
33465
33466			_whiteColor.toArray( colorsTexture.image.data, geometryId * 4 );
33467			colorsTexture.needsUpdate = true;
33468
33469		}
33470
33471		// add the reserved range and draw range objects
33472		reservedRanges.push( reservedRange );
33473		drawRanges.push( {
33474			start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart,
33475			count: - 1
33476		} );
33477		bounds.push( {
33478			boxInitialized: false,
33479			box: new Box3(),
33480
33481			sphereInitialized: false,
33482			sphere: new Sphere()
33483		} );
33484
33485		// set the id for the geometry
33486		const idAttribute = this.geometry.getAttribute( ID_ATTR_NAME );
33487		for ( let i = 0; i < reservedRange.vertexCount; i ++ ) {
33488
33489			idAttribute.setX( reservedRange.vertexStart + i, geometryId );
33490
33491		}
33492
33493		idAttribute.needsUpdate = true;
33494
33495		// update the geometry
33496		this.setGeometryAt( geometryId, geometry );
33497
33498		return geometryId;
33499
33500	}
33501
33502	setGeometryAt( id, geometry ) {
33503
33504		if ( id >= this._geometryCount ) {
33505
33506			throw new Error( 'BatchedMesh: Maximum geometry count reached.' );
33507
33508		}
33509
33510		this._validateGeometry( geometry );
33511
33512		const batchGeometry = this.geometry;
33513		const hasIndex = batchGeometry.getIndex() !== null;
33514		const dstIndex = batchGeometry.getIndex();
33515		const srcIndex = geometry.getIndex();
33516		const reservedRange = this._reservedRanges[ id ];
33517		if (
33518			hasIndex &&
33519			srcIndex.count > reservedRange.indexCount ||
33520			geometry.attributes.position.count > reservedRange.vertexCount
33521		) {
33522
33523			throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' );
33524
33525		}
33526
33527		// copy geometry over
33528		const vertexStart = reservedRange.vertexStart;
33529		const vertexCount = reservedRange.vertexCount;
33530		for ( const attributeName in batchGeometry.attributes ) {
33531
33532			if ( attributeName === ID_ATTR_NAME ) {
33533
33534				continue;
33535
33536			}
33537
33538			// copy attribute data
33539			const srcAttribute = geometry.getAttribute( attributeName );
33540			const dstAttribute = batchGeometry.getAttribute( attributeName );
33541			copyAttributeData( srcAttribute, dstAttribute, vertexStart );
33542
33543			// fill the rest in with zeroes
33544			const itemSize = srcAttribute.itemSize;
33545			for ( let i = srcAttribute.count, l = vertexCount; i < l; i ++ ) {
33546
33547				const index = vertexStart + i;
33548				for ( let c = 0; c < itemSize; c ++ ) {
33549
33550					dstAttribute.setComponent( index, c, 0 );
33551
33552				}
33553
33554			}
33555
33556			dstAttribute.needsUpdate = true;
33557			dstAttribute.addUpdateRange( vertexStart * itemSize, vertexCount * itemSize );
33558
33559		}
33560
33561		// copy index
33562		if ( hasIndex ) {
33563
33564			const indexStart = reservedRange.indexStart;
33565
33566			// copy index data over
33567			for ( let i = 0; i < srcIndex.count; i ++ ) {
33568
33569				dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) );
33570
33571			}
33572
33573			// fill the rest in with zeroes
33574			for ( let i = srcIndex.count, l = reservedRange.indexCount; i < l; i ++ ) {
33575
33576				dstIndex.setX( indexStart + i, vertexStart );
33577
33578			}
33579
33580			dstIndex.needsUpdate = true;
33581			dstIndex.addUpdateRange( indexStart, reservedRange.indexCount );
33582
33583		}
33584
33585		// store the bounding boxes
33586		const bound = this._bounds[ id ];
33587		if ( geometry.boundingBox !== null ) {
33588
33589			bound.box.copy( geometry.boundingBox );
33590			bound.boxInitialized = true;
33591
33592		} else {
33593
33594			bound.boxInitialized = false;
33595
33596		}
33597
33598		if ( geometry.boundingSphere !== null ) {
33599
33600			bound.sphere.copy( geometry.boundingSphere );
33601			bound.sphereInitialized = true;
33602
33603		} else {
33604
33605			bound.sphereInitialized = false;
33606
33607		}
33608
33609		// set drawRange count
33610		const drawRange = this._drawRanges[ id ];
33611		const posAttr = geometry.getAttribute( 'position' );
33612		drawRange.count = hasIndex ? srcIndex.count : posAttr.count;
33613		this._visibilityChanged = true;
33614
33615		return id;
33616
33617	}
33618
33619	deleteGeometry( geometryId ) {
33620
33621		// Note: User needs to call optimize() afterward to pack the data.
33622
33623		const active = this._active;
33624		if ( geometryId >= active.length || active[ geometryId ] === false ) {
33625
33626			return this;
33627
33628		}
33629
33630		active[ geometryId ] = false;
33631		this._visibilityChanged = true;
33632
33633		return this;
33634
33635	}
33636
33637	getInstanceCountAt( id ) {
33638
33639		if ( this._multiDrawInstances === null ) return null;
33640
33641		return this._multiDrawInstances[ id ];
33642
33643	}
33644
33645	setInstanceCountAt( id, instanceCount ) {
33646
33647		if ( this._multiDrawInstances === null ) {
33648
33649			this._multiDrawInstances = new Int32Array( this._maxGeometryCount ).fill( 1 );
33650
33651		}
33652
33653		this._multiDrawInstances[ id ] = instanceCount;
33654
33655		return id;
33656
33657	}
33658
33659	// get bounding box and compute it if it doesn't exist
33660	getBoundingBoxAt( id, target ) {
33661
33662		const active = this._active;
33663		if ( active[ id ] === false ) {
33664
33665			return null;
33666
33667		}
33668
33669		// compute bounding box
33670		const bound = this._bounds[ id ];
33671		const box = bound.box;
33672		const geometry = this.geometry;
33673		if ( bound.boxInitialized === false ) {
33674
33675			box.makeEmpty();
33676
33677			const index = geometry.index;
33678			const position = geometry.attributes.position;
33679			const drawRange = this._drawRanges[ id ];
33680			for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) {
33681
33682				let iv = i;
33683				if ( index ) {
33684
33685					iv = index.getX( iv );
33686
33687				}
33688
33689				box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) );
33690
33691			}
33692
33693			bound.boxInitialized = true;
33694
33695		}
33696
33697		target.copy( box );
33698		return target;
33699
33700	}
33701
33702	// get bounding sphere and compute it if it doesn't exist
33703	getBoundingSphereAt( id, target ) {
33704
33705		const active = this._active;
33706		if ( active[ id ] === false ) {
33707
33708			return null;
33709
33710		}
33711
33712		// compute bounding sphere
33713		const bound = this._bounds[ id ];
33714		const sphere = bound.sphere;
33715		const geometry = this.geometry;
33716		if ( bound.sphereInitialized === false ) {
33717
33718			sphere.makeEmpty();
33719
33720			this.getBoundingBoxAt( id, _box$1 );
33721			_box$1.getCenter( sphere.center );
33722
33723			const index = geometry.index;
33724			const position = geometry.attributes.position;
33725			const drawRange = this._drawRanges[ id ];
33726
33727			let maxRadiusSq = 0;
33728			for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) {
33729
33730				let iv = i;
33731				if ( index ) {
33732
33733					iv = index.getX( iv );
33734
33735				}
33736
33737				_vector$5.fromBufferAttribute( position, iv );
33738				maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) );
33739
33740			}
33741
33742			sphere.radius = Math.sqrt( maxRadiusSq );
33743			bound.sphereInitialized = true;
33744
33745		}
33746
33747		target.copy( sphere );
33748		return target;
33749
33750	}
33751
33752	setMatrixAt( geometryId, matrix ) {
33753
33754		// @TODO: Map geometryId to index of the arrays because
33755		//        optimize() can make geometryId mismatch the index
33756
33757		const active = this._active;
33758		const matricesTexture = this._matricesTexture;
33759		const matricesArray = this._matricesTexture.image.data;
33760		const geometryCount = this._geometryCount;
33761		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33762
33763			return this;
33764
33765		}
33766
33767		matrix.toArray( matricesArray, geometryId * 16 );
33768		matricesTexture.needsUpdate = true;
33769
33770		return this;
33771
33772	}
33773
33774	getMatrixAt( geometryId, matrix ) {
33775
33776		const active = this._active;
33777		const matricesArray = this._matricesTexture.image.data;
33778		const geometryCount = this._geometryCount;
33779		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33780
33781			return null;
33782
33783		}
33784
33785		return matrix.fromArray( matricesArray, geometryId * 16 );
33786
33787	}
33788
33789	setColorAt( geometryId, color ) {
33790
33791		if ( this._colorsTexture === null ) {
33792
33793			this._initColorsTexture();
33794
33795		}
33796
33797		// @TODO: Map geometryId to index of the arrays because
33798		//        optimize() can make geometryId mismatch the index
33799
33800		const active = this._active;
33801		const colorsTexture = this._colorsTexture;
33802		const colorsArray = this._colorsTexture.image.data;
33803		const geometryCount = this._geometryCount;
33804		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33805
33806			return this;
33807
33808		}
33809
33810		color.toArray( colorsArray, geometryId * 4 );
33811		colorsTexture.needsUpdate = true;
33812
33813		return this;
33814
33815	}
33816
33817	getColorAt( geometryId, color ) {
33818
33819		const active = this._active;
33820		const colorsArray = this._colorsTexture.image.data;
33821		const geometryCount = this._geometryCount;
33822		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33823
33824			return null;
33825
33826		}
33827
33828		return color.fromArray( colorsArray, geometryId * 4 );
33829
33830	}
33831
33832	setVisibleAt( geometryId, value ) {
33833
33834		const visibility = this._visibility;
33835		const active = this._active;
33836		const geometryCount = this._geometryCount;
33837
33838		// if the geometry is out of range, not active, or visibility state
33839		// does not change then return early
33840		if (
33841			geometryId >= geometryCount ||
33842			active[ geometryId ] === false ||
33843			visibility[ geometryId ] === value
33844		) {
33845
33846			return this;
33847
33848		}
33849
33850		visibility[ geometryId ] = value;
33851		this._visibilityChanged = true;
33852
33853		return this;
33854
33855	}
33856
33857	getVisibleAt( geometryId ) {
33858
33859		const visibility = this._visibility;
33860		const active = this._active;
33861		const geometryCount = this._geometryCount;
33862
33863		// return early if the geometry is out of range or not active
33864		if ( geometryId >= geometryCount || active[ geometryId ] === false ) {
33865
33866			return false;
33867
33868		}
33869
33870		return visibility[ geometryId ];
33871
33872	}
33873
33874	raycast( raycaster, intersects ) {
33875
33876		const visibility = this._visibility;
33877		const active = this._active;
33878		const drawRanges = this._drawRanges;
33879		const geometryCount = this._geometryCount;
33880		const matrixWorld = this.matrixWorld;
33881		const batchGeometry = this.geometry;
33882
33883		// iterate over each geometry
33884		_mesh.material = this.material;
33885		_mesh.geometry.index = batchGeometry.index;
33886		_mesh.geometry.attributes = batchGeometry.attributes;
33887		if ( _mesh.geometry.boundingBox === null ) {
33888
33889			_mesh.geometry.boundingBox = new Box3();
33890
33891		}
33892
33893		if ( _mesh.geometry.boundingSphere === null ) {
33894
33895			_mesh.geometry.boundingSphere = new Sphere();
33896
33897		}
33898
33899		for ( let i = 0; i < geometryCount; i ++ ) {
33900
33901			if ( ! visibility[ i ] || ! active[ i ] ) {
33902
33903				continue;
33904
33905			}
33906
33907			const drawRange = drawRanges[ i ];
33908			_mesh.geometry.setDrawRange( drawRange.start, drawRange.count );
33909
33910			// ge the intersects
33911			this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld );
33912			this.getBoundingBoxAt( i, _mesh.geometry.boundingBox );
33913			this.getBoundingSphereAt( i, _mesh.geometry.boundingSphere );
33914			_mesh.raycast( raycaster, _batchIntersects );
33915
33916			// add batch id to the intersects
33917			for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) {
33918
33919				const intersect = _batchIntersects[ j ];
33920				intersect.object = this;
33921				intersect.batchId = i;
33922				intersects.push( intersect );
33923
33924			}
33925
33926			_batchIntersects.length = 0;
33927
33928		}
33929
33930		_mesh.material = null;
33931		_mesh.geometry.index = null;
33932		_mesh.geometry.attributes = {};
33933		_mesh.geometry.setDrawRange( 0, Infinity );
33934
33935	}
33936
33937	copy( source ) {
33938
33939		super.copy( source );
33940
33941		this.geometry = source.geometry.clone();
33942		this.perObjectFrustumCulled = source.perObjectFrustumCulled;
33943		this.sortObjects = source.sortObjects;
33944		this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
33945		this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
33946
33947		this._drawRanges = source._drawRanges.map( range => ( { ...range } ) );
33948		this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) );
33949
33950		this._visibility = source._visibility.slice();
33951		this._active = source._active.slice();
33952		this._bounds = source._bounds.map( bound => ( {
33953			boxInitialized: bound.boxInitialized,
33954			box: bound.box.clone(),
33955
33956			sphereInitialized: bound.sphereInitialized,
33957			sphere: bound.sphere.clone()
33958		} ) );
33959
33960		this._maxGeometryCount = source._maxGeometryCount;
33961		this._maxVertexCount = source._maxVertexCount;
33962		this._maxIndexCount = source._maxIndexCount;
33963
33964		this._geometryInitialized = source._geometryInitialized;
33965		this._geometryCount = source._geometryCount;
33966		this._multiDrawCounts = source._multiDrawCounts.slice();
33967		this._multiDrawStarts = source._multiDrawStarts.slice();
33968
33969		this._matricesTexture = source._matricesTexture.clone();
33970		this._matricesTexture.image.data = this._matricesTexture.image.slice();
33971
33972		if ( this._colorsTexture !== null ) {
33973
33974			this._colorsTexture = source._colorsTexture.clone();
33975			this._colorsTexture.image.data = this._colorsTexture.image.slice();
33976
33977		}
33978
33979		return this;
33980
33981	}
33982
33983	dispose() {
33984
33985		// Assuming the geometry is not shared with other meshes
33986		this.geometry.dispose();
33987
33988		this._matricesTexture.dispose();
33989		this._matricesTexture = null;
33990
33991		if ( this._colorsTexture !== null ) {
33992
33993			this._colorsTexture.dispose();
33994			this._colorsTexture = null;
33995
33996		}
33997
33998		return this;
33999
34000	}
34001
34002	onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) {
34003
34004		// if visibility has not changed and frustum culling and object sorting is not required
34005		// then skip iterating over all items
34006		if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) {
34007
34008			return;
34009
34010		}
34011
34012		// the indexed version of the multi draw function requires specifying the start
34013		// offset in bytes.
34014		const index = geometry.getIndex();
34015		const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
34016
34017		const active = this._active;
34018		const visibility = this._visibility;
34019		const multiDrawStarts = this._multiDrawStarts;
34020		const multiDrawCounts = this._multiDrawCounts;
34021		const drawRanges = this._drawRanges;
34022		const perObjectFrustumCulled = this.perObjectFrustumCulled;
34023
34024		// prepare the frustum in the local frame
34025		if ( perObjectFrustumCulled ) {
34026
34027			_projScreenMatrix$2
34028				.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse )
34029				.multiply( this.matrixWorld );
34030			_frustum.setFromProjectionMatrix(
34031				_projScreenMatrix$2,
34032				renderer.coordinateSystem
34033			);
34034
34035		}
34036
34037		let count = 0;
34038		if ( this.sortObjects ) {
34039
34040			// get the camera position in the local frame
34041			_invMatrixWorld.copy( this.matrixWorld ).invert();
34042			_vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _invMatrixWorld );
34043			_forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).transformDirection( _invMatrixWorld );
34044
34045			for ( let i = 0, l = visibility.length; i < l; i ++ ) {
34046
34047				if ( visibility[ i ] && active[ i ] ) {
34048
34049					// get the bounds in world space
34050					this.getMatrixAt( i, _matrix$1 );
34051					this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 );
34052
34053					// determine whether the batched geometry is within the frustum
34054					let culled = false;
34055					if ( perObjectFrustumCulled ) {
34056
34057						culled = ! _frustum.intersectsSphere( _sphere$2 );
34058
34059					}
34060
34061					if ( ! culled ) {
34062
34063						// get the distance from camera used for sorting
34064						const z = _temp.subVectors( _sphere$2.center, _vector$5 ).dot( _forward );
34065						_renderList.push( drawRanges[ i ], z );
34066
34067					}
34068
34069				}
34070
34071			}
34072
34073			// Sort the draw ranges and prep for rendering
34074			const list = _renderList.list;
34075			const customSort = this.customSort;
34076			if ( customSort === null ) {
34077
34078				list.sort( material.transparent ? sortTransparent : sortOpaque );
34079
34080			} else {
34081
34082				customSort.call( this, list, camera );
34083
34084			}
34085
34086			for ( let i = 0, l = list.length; i < l; i ++ ) {
34087
34088				const item = list[ i ];
34089				multiDrawStarts[ count ] = item.start * bytesPerElement;
34090				multiDrawCounts[ count ] = item.count;
34091				count ++;
34092
34093			}
34094
34095			_renderList.reset();
34096
34097		} else {
34098
34099			for ( let i = 0, l = visibility.length; i < l; i ++ ) {
34100
34101				if ( visibility[ i ] && active[ i ] ) {
34102
34103					// determine whether the batched geometry is within the frustum
34104					let culled = false;
34105					if ( perObjectFrustumCulled ) {
34106
34107						// get the bounds in world space
34108						this.getMatrixAt( i, _matrix$1 );
34109						this.getBoundingSphereAt( i, _sphere$2 ).applyMatrix4( _matrix$1 );
34110						culled = ! _frustum.intersectsSphere( _sphere$2 );
34111
34112					}
34113
34114					if ( ! culled ) {
34115
34116						const range = drawRanges[ i ];
34117						multiDrawStarts[ count ] = range.start * bytesPerElement;
34118						multiDrawCounts[ count ] = range.count;
34119						count ++;
34120
34121					}
34122
34123				}
34124
34125			}
34126
34127		}
34128
34129		this._multiDrawCount = count;
34130		this._visibilityChanged = false;
vendor: 19,160 bytes, lines 34131-35077
34131
34132	}
34133
34134	onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) {
34135
34136		this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial );
34137
34138	}
34139
34140}
34141
34142class LineBasicMaterial extends Material {
34143
34144	constructor( parameters ) {
34145
34146		super();
34147
34148		this.isLineBasicMaterial = true;
34149
34150		this.type = 'LineBasicMaterial';
34151
34152		this.color = new Color( 0xffffff );
34153
34154		this.map = null;
34155
34156		this.linewidth = 1;
34157		this.linecap = 'round';
34158		this.linejoin = 'round';
34159
34160		this.fog = true;
34161
34162		this.setValues( parameters );
34163
34164	}
34165
34166
34167	copy( source ) {
34168
34169		super.copy( source );
34170
34171		this.color.copy( source.color );
34172
34173		this.map = source.map;
34174
34175		this.linewidth = source.linewidth;
34176		this.linecap = source.linecap;
34177		this.linejoin = source.linejoin;
34178
34179		this.fog = source.fog;
34180
34181		return this;
34182
34183	}
34184
34185}
34186
34187const _vStart = /*@__PURE__*/ new Vector3();
34188const _vEnd = /*@__PURE__*/ new Vector3();
34189
34190const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4();
34191const _ray$1 = /*@__PURE__*/ new Ray();
34192const _sphere$1 = /*@__PURE__*/ new Sphere();
34193
34194const _intersectPointOnRay = /*@__PURE__*/ new Vector3();
34195const _intersectPointOnSegment = /*@__PURE__*/ new Vector3();
34196
34197class Line extends Object3D {
34198
34199	constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
34200
34201		super();
34202
34203		this.isLine = true;
34204
34205		this.type = 'Line';
34206
34207		this.geometry = geometry;
34208		this.material = material;
34209
34210		this.updateMorphTargets();
34211
34212	}
34213
34214	copy( source, recursive ) {
34215
34216		super.copy( source, recursive );
34217
34218		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
34219		this.geometry = source.geometry;
34220
34221		return this;
34222
34223	}
34224
34225	computeLineDistances() {
34226
34227		const geometry = this.geometry;
34228
34229		// we assume non-indexed geometry
34230
34231		if ( geometry.index === null ) {
34232
34233			const positionAttribute = geometry.attributes.position;
34234			const lineDistances = [ 0 ];
34235
34236			for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
34237
34238				_vStart.fromBufferAttribute( positionAttribute, i - 1 );
34239				_vEnd.fromBufferAttribute( positionAttribute, i );
34240
34241				lineDistances[ i ] = lineDistances[ i - 1 ];
34242				lineDistances[ i ] += _vStart.distanceTo( _vEnd );
34243
34244			}
34245
34246			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
34247
34248		} else {
34249
34250			console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
34251
34252		}
34253
34254		return this;
34255
34256	}
34257
34258	raycast( raycaster, intersects ) {
34259
34260		const geometry = this.geometry;
34261		const matrixWorld = this.matrixWorld;
34262		const threshold = raycaster.params.Line.threshold;
34263		const drawRange = geometry.drawRange;
34264
34265		// Checking boundingSphere distance to ray
34266
34267		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
34268
34269		_sphere$1.copy( geometry.boundingSphere );
34270		_sphere$1.applyMatrix4( matrixWorld );
34271		_sphere$1.radius += threshold;
34272
34273		if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return;
34274
34275		//
34276
34277		_inverseMatrix$1.copy( matrixWorld ).invert();
34278		_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
34279
34280		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
34281		const localThresholdSq = localThreshold * localThreshold;
34282
34283		const step = this.isLineSegments ? 2 : 1;
34284
34285		const index = geometry.index;
34286		const attributes = geometry.attributes;
34287		const positionAttribute = attributes.position;
34288
34289		if ( index !== null ) {
34290
34291			const start = Math.max( 0, drawRange.start );
34292			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
34293
34294			for ( let i = start, l = end - 1; i < l; i += step ) {
34295
34296				const a = index.getX( i );
34297				const b = index.getX( i + 1 );
34298
34299				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b );
34300
34301				if ( intersect ) {
34302
34303					intersects.push( intersect );
34304
34305				}
34306
34307			}
34308
34309			if ( this.isLineLoop ) {
34310
34311				const a = index.getX( end - 1 );
34312				const b = index.getX( start );
34313
34314				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b );
34315
34316				if ( intersect ) {
34317
34318					intersects.push( intersect );
34319
34320				}
34321
34322			}
34323
34324		} else {
34325
34326			const start = Math.max( 0, drawRange.start );
34327			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
34328
34329			for ( let i = start, l = end - 1; i < l; i += step ) {
34330
34331				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1 );
34332
34333				if ( intersect ) {
34334
34335					intersects.push( intersect );
34336
34337				}
34338
34339			}
34340
34341			if ( this.isLineLoop ) {
34342
34343				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start );
34344
34345				if ( intersect ) {
34346
34347					intersects.push( intersect );
34348
34349				}
34350
34351			}
34352
34353		}
34354
34355	}
34356
34357	updateMorphTargets() {
34358
34359		const geometry = this.geometry;
34360
34361		const morphAttributes = geometry.morphAttributes;
34362		const keys = Object.keys( morphAttributes );
34363
34364		if ( keys.length > 0 ) {
34365
34366			const morphAttribute = morphAttributes[ keys[ 0 ] ];
34367
34368			if ( morphAttribute !== undefined ) {
34369
34370				this.morphTargetInfluences = [];
34371				this.morphTargetDictionary = {};
34372
34373				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
34374
34375					const name = morphAttribute[ m ].name || String( m );
34376
34377					this.morphTargetInfluences.push( 0 );
34378					this.morphTargetDictionary[ name ] = m;
34379
34380				}
34381
34382			}
34383
34384		}
34385
34386	}
34387
34388}
34389
34390function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) {
34391
34392	const positionAttribute = object.geometry.attributes.position;
34393
34394	_vStart.fromBufferAttribute( positionAttribute, a );
34395	_vEnd.fromBufferAttribute( positionAttribute, b );
34396
34397	const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment );
34398
34399	if ( distSq > thresholdSq ) return;
34400
34401	_intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation
34402
34403	const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay );
34404
34405	if ( distance < raycaster.near || distance > raycaster.far ) return;
34406
34407	return {
34408
34409		distance: distance,
34410		// What do we want? intersection point on the ray or on the segment??
34411		// point: raycaster.ray.at( distance ),
34412		point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ),
34413		index: a,
34414		face: null,
34415		faceIndex: null,
34416		object: object
34417
34418	};
34419
34420}
34421
34422const _start = /*@__PURE__*/ new Vector3();
34423const _end = /*@__PURE__*/ new Vector3();
34424
34425class LineSegments extends Line {
34426
34427	constructor( geometry, material ) {
34428
34429		super( geometry, material );
34430
34431		this.isLineSegments = true;
34432
34433		this.type = 'LineSegments';
34434
34435	}
34436
34437	computeLineDistances() {
34438
34439		const geometry = this.geometry;
34440
34441		// we assume non-indexed geometry
34442
34443		if ( geometry.index === null ) {
34444
34445			const positionAttribute = geometry.attributes.position;
34446			const lineDistances = [];
34447
34448			for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
34449
34450				_start.fromBufferAttribute( positionAttribute, i );
34451				_end.fromBufferAttribute( positionAttribute, i + 1 );
34452
34453				lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
34454				lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
34455
34456			}
34457
34458			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
34459
34460		} else {
34461
34462			console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
34463
34464		}
34465
34466		return this;
34467
34468	}
34469
34470}
34471
34472class LineLoop extends Line {
34473
34474	constructor( geometry, material ) {
34475
34476		super( geometry, material );
34477
34478		this.isLineLoop = true;
34479
34480		this.type = 'LineLoop';
34481
34482	}
34483
34484}
34485
34486class PointsMaterial extends Material {
34487
34488	constructor( parameters ) {
34489
34490		super();
34491
34492		this.isPointsMaterial = true;
34493
34494		this.type = 'PointsMaterial';
34495
34496		this.color = new Color( 0xffffff );
34497
34498		this.map = null;
34499
34500		this.alphaMap = null;
34501
34502		this.size = 1;
34503		this.sizeAttenuation = true;
34504
34505		this.fog = true;
34506
34507		this.setValues( parameters );
34508
34509	}
34510
34511	copy( source ) {
34512
34513		super.copy( source );
34514
34515		this.color.copy( source.color );
34516
34517		this.map = source.map;
34518
34519		this.alphaMap = source.alphaMap;
34520
34521		this.size = source.size;
34522		this.sizeAttenuation = source.sizeAttenuation;
34523
34524		this.fog = source.fog;
34525
34526		return this;
34527
34528	}
34529
34530}
34531
34532const _inverseMatrix = /*@__PURE__*/ new Matrix4();
34533const _ray = /*@__PURE__*/ new Ray();
34534const _sphere = /*@__PURE__*/ new Sphere();
34535const _position$2 = /*@__PURE__*/ new Vector3();
34536
34537class Points extends Object3D {
34538
34539	constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
34540
34541		super();
34542
34543		this.isPoints = true;
34544
34545		this.type = 'Points';
34546
34547		this.geometry = geometry;
34548		this.material = material;
34549
34550		this.updateMorphTargets();
34551
34552	}
34553
34554	copy( source, recursive ) {
34555
34556		super.copy( source, recursive );
34557
34558		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
34559		this.geometry = source.geometry;
34560
34561		return this;
34562
34563	}
34564
34565	raycast( raycaster, intersects ) {
34566
34567		const geometry = this.geometry;
34568		const matrixWorld = this.matrixWorld;
34569		const threshold = raycaster.params.Points.threshold;
34570		const drawRange = geometry.drawRange;
34571
34572		// Checking boundingSphere distance to ray
34573
34574		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
34575
34576		_sphere.copy( geometry.boundingSphere );
34577		_sphere.applyMatrix4( matrixWorld );
34578		_sphere.radius += threshold;
34579
34580		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
34581
34582		//
34583
34584		_inverseMatrix.copy( matrixWorld ).invert();
34585		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
34586
34587		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
34588		const localThresholdSq = localThreshold * localThreshold;
34589
34590		const index = geometry.index;
34591		const attributes = geometry.attributes;
34592		const positionAttribute = attributes.position;
34593
34594		if ( index !== null ) {
34595
34596			const start = Math.max( 0, drawRange.start );
34597			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
34598
34599			for ( let i = start, il = end; i < il; i ++ ) {
34600
34601				const a = index.getX( i );
34602
34603				_position$2.fromBufferAttribute( positionAttribute, a );
34604
34605				testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
34606
34607			}
34608
34609		} else {
34610
34611			const start = Math.max( 0, drawRange.start );
34612			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
34613
34614			for ( let i = start, l = end; i < l; i ++ ) {
34615
34616				_position$2.fromBufferAttribute( positionAttribute, i );
34617
34618				testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
34619
34620			}
34621
34622		}
34623
34624	}
34625
34626	updateMorphTargets() {
34627
34628		const geometry = this.geometry;
34629
34630		const morphAttributes = geometry.morphAttributes;
34631		const keys = Object.keys( morphAttributes );
34632
34633		if ( keys.length > 0 ) {
34634
34635			const morphAttribute = morphAttributes[ keys[ 0 ] ];
34636
34637			if ( morphAttribute !== undefined ) {
34638
34639				this.morphTargetInfluences = [];
34640				this.morphTargetDictionary = {};
34641
34642				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
34643
34644					const name = morphAttribute[ m ].name || String( m );
34645
34646					this.morphTargetInfluences.push( 0 );
34647					this.morphTargetDictionary[ name ] = m;
34648
34649				}
34650
34651			}
34652
34653		}
34654
34655	}
34656
34657}
34658
34659function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
34660
34661	const rayPointDistanceSq = _ray.distanceSqToPoint( point );
34662
34663	if ( rayPointDistanceSq < localThresholdSq ) {
34664
34665		const intersectPoint = new Vector3();
34666
34667		_ray.closestPointToPoint( point, intersectPoint );
34668		intersectPoint.applyMatrix4( matrixWorld );
34669
34670		const distance = raycaster.ray.origin.distanceTo( intersectPoint );
34671
34672		if ( distance < raycaster.near || distance > raycaster.far ) return;
34673
34674		intersects.push( {
34675
34676			distance: distance,
34677			distanceToRay: Math.sqrt( rayPointDistanceSq ),
34678			point: intersectPoint,
34679			index: index,
34680			face: null,
34681			object: object
34682
34683		} );
34684
34685	}
34686
34687}
34688
34689class VideoTexture extends Texture {
34690
34691	constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
34692
34693		super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
34694
34695		this.isVideoTexture = true;
34696
34697		this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
34698		this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
34699
34700		this.generateMipmaps = false;
34701
34702		const scope = this;
34703
34704		function updateVideo() {
34705
34706			scope.needsUpdate = true;
34707			video.requestVideoFrameCallback( updateVideo );
34708
34709		}
34710
34711		if ( 'requestVideoFrameCallback' in video ) {
34712
34713			video.requestVideoFrameCallback( updateVideo );
34714
34715		}
34716
34717	}
34718
34719	clone() {
34720
34721		return new this.constructor( this.image ).copy( this );
34722
34723	}
34724
34725	update() {
34726
34727		const video = this.image;
34728		const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
34729
34730		if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
34731
34732			this.needsUpdate = true;
34733
34734		}
34735
34736	}
34737
34738}
34739
34740class FramebufferTexture extends Texture {
34741
34742	constructor( width, height ) {
34743
34744		super( { width, height } );
34745
34746		this.isFramebufferTexture = true;
34747
34748		this.magFilter = NearestFilter;
34749		this.minFilter = NearestFilter;
34750
34751		this.generateMipmaps = false;
34752
34753		this.needsUpdate = true;
34754
34755	}
34756
34757}
34758
34759class CompressedTexture extends Texture {
34760
34761	constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) {
34762
34763		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
34764
34765		this.isCompressedTexture = true;
34766
34767		this.image = { width: width, height: height };
34768		this.mipmaps = mipmaps;
34769
34770		// no flipping for cube textures
34771		// (also flipping doesn't work for compressed textures )
34772
34773		this.flipY = false;
34774
34775		// can't generate mipmaps for compressed textures
34776		// mips must be embedded in DDS files
34777
34778		this.generateMipmaps = false;
34779
34780	}
34781
34782}
34783
34784class CompressedArrayTexture extends CompressedTexture {
34785
34786	constructor( mipmaps, width, height, depth, format, type ) {
34787
34788		super( mipmaps, width, height, format, type );
34789
34790		this.isCompressedArrayTexture = true;
34791		this.image.depth = depth;
34792		this.wrapR = ClampToEdgeWrapping;
34793
34794		this.layerUpdates = new Set();
34795
34796	}
34797
34798	addLayerUpdates( layerIndex ) {
34799
34800		this.layerUpdates.add( layerIndex );
34801
34802	}
34803
34804	clearLayerUpdates() {
34805
34806		this.layerUpdates.clear();
34807
34808	}
34809
34810}
34811
34812class CompressedCubeTexture extends CompressedTexture {
34813
34814	constructor( images, format, type ) {
34815
34816		super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping );
34817
34818		this.isCompressedCubeTexture = true;
34819		this.isCubeTexture = true;
34820
34821		this.image = images;
34822
34823	}
34824
34825}
34826
34827class CanvasTexture extends Texture {
34828
34829	constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
34830
34831		super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
34832
34833		this.isCanvasTexture = true;
34834
34835		this.needsUpdate = true;
34836
34837	}
34838
34839}
34840
34841/**
34842 * Extensible curve object.
34843 *
34844 * Some common of curve methods:
34845 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
34846 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
34847 * .getPoints(), .getSpacedPoints()
34848 * .getLength()
34849 * .updateArcLengths()
34850 *
34851 * This following curves inherit from THREE.Curve:
34852 *
34853 * -- 2D curves --
34854 * THREE.ArcCurve
34855 * THREE.CubicBezierCurve
34856 * THREE.EllipseCurve
34857 * THREE.LineCurve
34858 * THREE.QuadraticBezierCurve
34859 * THREE.SplineCurve
34860 *
34861 * -- 3D curves --
34862 * THREE.CatmullRomCurve3
34863 * THREE.CubicBezierCurve3
34864 * THREE.LineCurve3
34865 * THREE.QuadraticBezierCurve3
34866 *
34867 * A series of curves can be represented as a THREE.CurvePath.
34868 *
34869 **/
34870
34871class Curve {
34872
34873	constructor() {
34874
34875		this.type = 'Curve';
34876
34877		this.arcLengthDivisions = 200;
34878
34879	}
34880
34881	// Virtual base class method to overwrite and implement in subclasses
34882	//	- t [0 .. 1]
34883
34884	getPoint( /* t, optionalTarget */ ) {
34885
34886		console.warn( 'THREE.Curve: .getPoint() not implemented.' );
34887		return null;
34888
34889	}
34890
34891	// Get point at relative position in curve according to arc length
34892	// - u [0 .. 1]
34893
34894	getPointAt( u, optionalTarget ) {
34895
34896		const t = this.getUtoTmapping( u );
34897		return this.getPoint( t, optionalTarget );
34898
34899	}
34900
34901	// Get sequence of points using getPoint( t )
34902
34903	getPoints( divisions = 5 ) {
34904
34905		const points = [];
34906
34907		for ( let d = 0; d <= divisions; d ++ ) {
34908
34909			points.push( this.getPoint( d / divisions ) );
34910
34911		}
34912
34913		return points;
34914
34915	}
34916
34917	// Get sequence of points using getPointAt( u )
34918
34919	getSpacedPoints( divisions = 5 ) {
34920
34921		const points = [];
34922
34923		for ( let d = 0; d <= divisions; d ++ ) {
34924
34925			points.push( this.getPointAt( d / divisions ) );
34926
34927		}
34928
34929		return points;
34930
34931	}
34932
34933	// Get total curve arc length
34934
34935	getLength() {
34936
34937		const lengths = this.getLengths();
34938		return lengths[ lengths.length - 1 ];
34939
34940	}
34941
34942	// Get list of cumulative segment lengths
34943
34944	getLengths( divisions = this.arcLengthDivisions ) {
34945
34946		if ( this.cacheArcLengths &&
34947			( this.cacheArcLengths.length === divisions + 1 ) &&
34948			! this.needsUpdate ) {
34949
34950			return this.cacheArcLengths;
34951
34952		}
34953
34954		this.needsUpdate = false;
34955
34956		const cache = [];
34957		let current, last = this.getPoint( 0 );
34958		let sum = 0;
34959
34960		cache.push( 0 );
34961
34962		for ( let p = 1; p <= divisions; p ++ ) {
34963
34964			current = this.getPoint( p / divisions );
34965			sum += current.distanceTo( last );
34966			cache.push( sum );
34967			last = current;
34968
34969		}
34970
34971		this.cacheArcLengths = cache;
34972
34973		return cache; // { sums: cache, sum: sum }; Sum is in the last element.
34974
34975	}
34976
34977	updateArcLengths() {
34978
34979		this.needsUpdate = true;
34980		this.getLengths();
34981
34982	}
34983
34984	// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
34985
34986	getUtoTmapping( u, distance ) {
34987
34988		const arcLengths = this.getLengths();
34989
34990		let i = 0;
34991		const il = arcLengths.length;
34992
34993		let targetArcLength; // The targeted u distance value to get
34994
34995		if ( distance ) {
34996
34997			targetArcLength = distance;
34998
34999		} else {
35000
35001			targetArcLength = u * arcLengths[ il - 1 ];
35002
35003		}
35004
35005		// binary search for the index with largest value smaller than target u distance
35006
35007		let low = 0, high = il - 1, comparison;
35008
35009		while ( low <= high ) {
35010
35011			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
35012
35013			comparison = arcLengths[ i ] - targetArcLength;
35014
35015			if ( comparison < 0 ) {
35016
35017				low = i + 1;
35018
35019			} else if ( comparison > 0 ) {
35020
35021				high = i - 1;
35022
35023			} else {
35024
35025				high = i;
35026				break;
35027
35028				// DONE
35029
35030			}
35031
35032		}
35033
35034		i = high;
35035
35036		if ( arcLengths[ i ] === targetArcLength ) {
35037
35038			return i / ( il - 1 );
35039
35040		}
35041
35042		// we could get finer grain at lengths, or use simple interpolation between two points
35043
35044		const lengthBefore = arcLengths[ i ];
35045		const lengthAfter = arcLengths[ i + 1 ];
35046
35047		const segmentLength = lengthAfter - lengthBefore;
35048
35049		// determine where we are between the 'before' and 'after' points
35050
35051		const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
35052
35053		// add that fractional amount to t
35054
35055		const t = ( i + segmentFraction ) / ( il - 1 );
35056
35057		return t;
35058
35059	}
35060
35061	// Returns a unit vector tangent at t
35062	// In case any sub curve does not implement its tangent derivation,
35063	// 2 points a small delta apart will be used to find its gradient
35064	// which seems to give a reasonable approximation
35065
35066	getTangent( t, optionalTarget ) {
35067
35068		const delta = 0.0001;
35069		let t1 = t - delta;
35070		let t2 = t + delta;
35071
35072		// Capping in case of danger
35073
35074		if ( t1 < 0 ) t1 = 0;
35075		if ( t2 > 1 ) t2 = 1;
35076
35077		const pt1 = this.getPoint( t1 );
vendor: 5,109 bytes, lines 35078-35346
35078		const pt2 = this.getPoint( t2 );
35079
35080		const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
35081
35082		tangent.copy( pt2 ).sub( pt1 ).normalize();
35083
35084		return tangent;
35085
35086	}
35087
35088	getTangentAt( u, optionalTarget ) {
35089
35090		const t = this.getUtoTmapping( u );
35091		return this.getTangent( t, optionalTarget );
35092
35093	}
35094
35095	computeFrenetFrames( segments, closed ) {
35096
35097		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
35098
35099		const normal = new Vector3();
35100
35101		const tangents = [];
35102		const normals = [];
35103		const binormals = [];
35104
35105		const vec = new Vector3();
35106		const mat = new Matrix4();
35107
35108		// compute the tangent vectors for each segment on the curve
35109
35110		for ( let i = 0; i <= segments; i ++ ) {
35111
35112			const u = i / segments;
35113
35114			tangents[ i ] = this.getTangentAt( u, new Vector3() );
35115
35116		}
35117
35118		// select an initial normal vector perpendicular to the first tangent vector,
35119		// and in the direction of the minimum tangent xyz component
35120
35121		normals[ 0 ] = new Vector3();
35122		binormals[ 0 ] = new Vector3();
35123		let min = Number.MAX_VALUE;
35124		const tx = Math.abs( tangents[ 0 ].x );
35125		const ty = Math.abs( tangents[ 0 ].y );
35126		const tz = Math.abs( tangents[ 0 ].z );
35127
35128		if ( tx <= min ) {
35129
35130			min = tx;
35131			normal.set( 1, 0, 0 );
35132
35133		}
35134
35135		if ( ty <= min ) {
35136
35137			min = ty;
35138			normal.set( 0, 1, 0 );
35139
35140		}
35141
35142		if ( tz <= min ) {
35143
35144			normal.set( 0, 0, 1 );
35145
35146		}
35147
35148		vec.crossVectors( tangents[ 0 ], normal ).normalize();
35149
35150		normals[ 0 ].crossVectors( tangents[ 0 ], vec );
35151		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
35152
35153
35154		// compute the slowly-varying normal and binormal vectors for each segment on the curve
35155
35156		for ( let i = 1; i <= segments; i ++ ) {
35157
35158			normals[ i ] = normals[ i - 1 ].clone();
35159
35160			binormals[ i ] = binormals[ i - 1 ].clone();
35161
35162			vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
35163
35164			if ( vec.length() > Number.EPSILON ) {
35165
35166				vec.normalize();
35167
35168				const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
35169
35170				normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
35171
35172			}
35173
35174			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35175
35176		}
35177
35178		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
35179
35180		if ( closed === true ) {
35181
35182			let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
35183			theta /= segments;
35184
35185			if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
35186
35187				theta = - theta;
35188
35189			}
35190
35191			for ( let i = 1; i <= segments; i ++ ) {
35192
35193				// twist a little...
35194				normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
35195				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
35196
35197			}
35198
35199		}
35200
35201		return {
35202			tangents: tangents,
35203			normals: normals,
35204			binormals: binormals
35205		};
35206
35207	}
35208
35209	clone() {
35210
35211		return new this.constructor().copy( this );
35212
35213	}
35214
35215	copy( source ) {
35216
35217		this.arcLengthDivisions = source.arcLengthDivisions;
35218
35219		return this;
35220
35221	}
35222
35223	toJSON() {
35224
35225		const data = {
35226			metadata: {
35227				version: 4.6,
35228				type: 'Curve',
35229				generator: 'Curve.toJSON'
35230			}
35231		};
35232
35233		data.arcLengthDivisions = this.arcLengthDivisions;
35234		data.type = this.type;
35235
35236		return data;
35237
35238	}
35239
35240	fromJSON( json ) {
35241
35242		this.arcLengthDivisions = json.arcLengthDivisions;
35243
35244		return this;
35245
35246	}
35247
35248}
35249
35250class EllipseCurve extends Curve {
35251
35252	constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) {
35253
35254		super();
35255
35256		this.isEllipseCurve = true;
35257
35258		this.type = 'EllipseCurve';
35259
35260		this.aX = aX;
35261		this.aY = aY;
35262
35263		this.xRadius = xRadius;
35264		this.yRadius = yRadius;
35265
35266		this.aStartAngle = aStartAngle;
35267		this.aEndAngle = aEndAngle;
35268
35269		this.aClockwise = aClockwise;
35270
35271		this.aRotation = aRotation;
35272
35273	}
35274
35275	getPoint( t, optionalTarget = new Vector2() ) {
35276
35277		const point = optionalTarget;
35278
35279		const twoPi = Math.PI * 2;
35280		let deltaAngle = this.aEndAngle - this.aStartAngle;
35281		const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
35282
35283		// ensures that deltaAngle is 0 .. 2 PI
35284		while ( deltaAngle < 0 ) deltaAngle += twoPi;
35285		while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
35286
35287		if ( deltaAngle < Number.EPSILON ) {
35288
35289			if ( samePoints ) {
35290
35291				deltaAngle = 0;
35292
35293			} else {
35294
35295				deltaAngle = twoPi;
35296
35297			}
35298
35299		}
35300
35301		if ( this.aClockwise === true && ! samePoints ) {
35302
35303			if ( deltaAngle === twoPi ) {
35304
35305				deltaAngle = - twoPi;
35306
35307			} else {
35308
35309				deltaAngle = deltaAngle - twoPi;
35310
35311			}
35312
35313		}
35314
35315		const angle = this.aStartAngle + t * deltaAngle;
35316		let x = this.aX + this.xRadius * Math.cos( angle );
35317		let y = this.aY + this.yRadius * Math.sin( angle );
35318
35319		if ( this.aRotation !== 0 ) {
35320
35321			const cos = Math.cos( this.aRotation );
35322			const sin = Math.sin( this.aRotation );
35323
35324			const tx = x - this.aX;
35325			const ty = y - this.aY;
35326
35327			// Rotate the point about the center of the ellipse.
35328			x = tx * cos - ty * sin + this.aX;
35329			y = tx * sin + ty * cos + this.aY;
35330
35331		}
35332
35333		return point.set( x, y );
35334
35335	}
35336
35337	copy( source ) {
35338
35339		super.copy( source );
35340
35341		this.aX = source.aX;
35342		this.aY = source.aY;
35343
35344		this.xRadius = source.xRadius;
35345		this.yRadius = source.yRadius;
35346
vendor: 29,619 bytes, lines 35347-37029
35347		this.aStartAngle = source.aStartAngle;
35348		this.aEndAngle = source.aEndAngle;
35349
35350		this.aClockwise = source.aClockwise;
35351
35352		this.aRotation = source.aRotation;
35353
35354		return this;
35355
35356	}
35357
35358	toJSON() {
35359
35360		const data = super.toJSON();
35361
35362		data.aX = this.aX;
35363		data.aY = this.aY;
35364
35365		data.xRadius = this.xRadius;
35366		data.yRadius = this.yRadius;
35367
35368		data.aStartAngle = this.aStartAngle;
35369		data.aEndAngle = this.aEndAngle;
35370
35371		data.aClockwise = this.aClockwise;
35372
35373		data.aRotation = this.aRotation;
35374
35375		return data;
35376
35377	}
35378
35379	fromJSON( json ) {
35380
35381		super.fromJSON( json );
35382
35383		this.aX = json.aX;
35384		this.aY = json.aY;
35385
35386		this.xRadius = json.xRadius;
35387		this.yRadius = json.yRadius;
35388
35389		this.aStartAngle = json.aStartAngle;
35390		this.aEndAngle = json.aEndAngle;
35391
35392		this.aClockwise = json.aClockwise;
35393
35394		this.aRotation = json.aRotation;
35395
35396		return this;
35397
35398	}
35399
35400}
35401
35402class ArcCurve extends EllipseCurve {
35403
35404	constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35405
35406		super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
35407
35408		this.isArcCurve = true;
35409
35410		this.type = 'ArcCurve';
35411
35412	}
35413
35414}
35415
35416/**
35417 * Centripetal CatmullRom Curve - which is useful for avoiding
35418 * cusps and self-intersections in non-uniform catmull rom curves.
35419 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
35420 *
35421 * curve.type accepts centripetal(default), chordal and catmullrom
35422 * curve.tension is used for catmullrom which defaults to 0.5
35423 */
35424
35425
35426/*
35427Based on an optimized c++ solution in
35428 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
35429 - http://ideone.com/NoEbVM
35430
35431This CubicPoly class could be used for reusing some variables and calculations,
35432but for three.js curve use, it could be possible inlined and flatten into a single function call
35433which can be placed in CurveUtils.
35434*/
35435
35436function CubicPoly() {
35437
35438	let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
35439
35440	/*
35441	 * Compute coefficients for a cubic polynomial
35442	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
35443	 * such that
35444	 *   p(0) = x0, p(1) = x1
35445	 *  and
35446	 *   p'(0) = t0, p'(1) = t1.
35447	 */
35448	function init( x0, x1, t0, t1 ) {
35449
35450		c0 = x0;
35451		c1 = t0;
35452		c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
35453		c3 = 2 * x0 - 2 * x1 + t0 + t1;
35454
35455	}
35456
35457	return {
35458
35459		initCatmullRom: function ( x0, x1, x2, x3, tension ) {
35460
35461			init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
35462
35463		},
35464
35465		initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
35466
35467			// compute tangents when parameterized in [t1,t2]
35468			let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
35469			let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
35470
35471			// rescale tangents for parametrization in [0,1]
35472			t1 *= dt1;
35473			t2 *= dt1;
35474
35475			init( x1, x2, t1, t2 );
35476
35477		},
35478
35479		calc: function ( t ) {
35480
35481			const t2 = t * t;
35482			const t3 = t2 * t;
35483			return c0 + c1 * t + c2 * t2 + c3 * t3;
35484
35485		}
35486
35487	};
35488
35489}
35490
35491//
35492
35493const tmp = /*@__PURE__*/ new Vector3();
35494const px = /*@__PURE__*/ new CubicPoly();
35495const py = /*@__PURE__*/ new CubicPoly();
35496const pz = /*@__PURE__*/ new CubicPoly();
35497
35498class CatmullRomCurve3 extends Curve {
35499
35500	constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
35501
35502		super();
35503
35504		this.isCatmullRomCurve3 = true;
35505
35506		this.type = 'CatmullRomCurve3';
35507
35508		this.points = points;
35509		this.closed = closed;
35510		this.curveType = curveType;
35511		this.tension = tension;
35512
35513	}
35514
35515	getPoint( t, optionalTarget = new Vector3() ) {
35516
35517		const point = optionalTarget;
35518
35519		const points = this.points;
35520		const l = points.length;
35521
35522		const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
35523		let intPoint = Math.floor( p );
35524		let weight = p - intPoint;
35525
35526		if ( this.closed ) {
35527
35528			intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
35529
35530		} else if ( weight === 0 && intPoint === l - 1 ) {
35531
35532			intPoint = l - 2;
35533			weight = 1;
35534
35535		}
35536
35537		let p0, p3; // 4 points (p1 & p2 defined below)
35538
35539		if ( this.closed || intPoint > 0 ) {
35540
35541			p0 = points[ ( intPoint - 1 ) % l ];
35542
35543		} else {
35544
35545			// extrapolate first point
35546			tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
35547			p0 = tmp;
35548
35549		}
35550
35551		const p1 = points[ intPoint % l ];
35552		const p2 = points[ ( intPoint + 1 ) % l ];
35553
35554		if ( this.closed || intPoint + 2 < l ) {
35555
35556			p3 = points[ ( intPoint + 2 ) % l ];
35557
35558		} else {
35559
35560			// extrapolate last point
35561			tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
35562			p3 = tmp;
35563
35564		}
35565
35566		if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
35567
35568			// init Centripetal / Chordal Catmull-Rom
35569			const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
35570			let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
35571			let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
35572			let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
35573
35574			// safety check for repeated points
35575			if ( dt1 < 1e-4 ) dt1 = 1.0;
35576			if ( dt0 < 1e-4 ) dt0 = dt1;
35577			if ( dt2 < 1e-4 ) dt2 = dt1;
35578
35579			px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
35580			py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
35581			pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
35582
35583		} else if ( this.curveType === 'catmullrom' ) {
35584
35585			px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
35586			py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
35587			pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
35588
35589		}
35590
35591		point.set(
35592			px.calc( weight ),
35593			py.calc( weight ),
35594			pz.calc( weight )
35595		);
35596
35597		return point;
35598
35599	}
35600
35601	copy( source ) {
35602
35603		super.copy( source );
35604
35605		this.points = [];
35606
35607		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
35608
35609			const point = source.points[ i ];
35610
35611			this.points.push( point.clone() );
35612
35613		}
35614
35615		this.closed = source.closed;
35616		this.curveType = source.curveType;
35617		this.tension = source.tension;
35618
35619		return this;
35620
35621	}
35622
35623	toJSON() {
35624
35625		const data = super.toJSON();
35626
35627		data.points = [];
35628
35629		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
35630
35631			const point = this.points[ i ];
35632			data.points.push( point.toArray() );
35633
35634		}
35635
35636		data.closed = this.closed;
35637		data.curveType = this.curveType;
35638		data.tension = this.tension;
35639
35640		return data;
35641
35642	}
35643
35644	fromJSON( json ) {
35645
35646		super.fromJSON( json );
35647
35648		this.points = [];
35649
35650		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
35651
35652			const point = json.points[ i ];
35653			this.points.push( new Vector3().fromArray( point ) );
35654
35655		}
35656
35657		this.closed = json.closed;
35658		this.curveType = json.curveType;
35659		this.tension = json.tension;
35660
35661		return this;
35662
35663	}
35664
35665}
35666
35667/**
35668 * Bezier Curves formulas obtained from
35669 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
35670 */
35671
35672function CatmullRom( t, p0, p1, p2, p3 ) {
35673
35674	const v0 = ( p2 - p0 ) * 0.5;
35675	const v1 = ( p3 - p1 ) * 0.5;
35676	const t2 = t * t;
35677	const t3 = t * t2;
35678	return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
35679
35680}
35681
35682//
35683
35684function QuadraticBezierP0( t, p ) {
35685
35686	const k = 1 - t;
35687	return k * k * p;
35688
35689}
35690
35691function QuadraticBezierP1( t, p ) {
35692
35693	return 2 * ( 1 - t ) * t * p;
35694
35695}
35696
35697function QuadraticBezierP2( t, p ) {
35698
35699	return t * t * p;
35700
35701}
35702
35703function QuadraticBezier( t, p0, p1, p2 ) {
35704
35705	return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
35706		QuadraticBezierP2( t, p2 );
35707
35708}
35709
35710//
35711
35712function CubicBezierP0( t, p ) {
35713
35714	const k = 1 - t;
35715	return k * k * k * p;
35716
35717}
35718
35719function CubicBezierP1( t, p ) {
35720
35721	const k = 1 - t;
35722	return 3 * k * k * t * p;
35723
35724}
35725
35726function CubicBezierP2( t, p ) {
35727
35728	return 3 * ( 1 - t ) * t * t * p;
35729
35730}
35731
35732function CubicBezierP3( t, p ) {
35733
35734	return t * t * t * p;
35735
35736}
35737
35738function CubicBezier( t, p0, p1, p2, p3 ) {
35739
35740	return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
35741		CubicBezierP3( t, p3 );
35742
35743}
35744
35745class CubicBezierCurve extends Curve {
35746
35747	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
35748
35749		super();
35750
35751		this.isCubicBezierCurve = true;
35752
35753		this.type = 'CubicBezierCurve';
35754
35755		this.v0 = v0;
35756		this.v1 = v1;
35757		this.v2 = v2;
35758		this.v3 = v3;
35759
35760	}
35761
35762	getPoint( t, optionalTarget = new Vector2() ) {
35763
35764		const point = optionalTarget;
35765
35766		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35767
35768		point.set(
35769			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
35770			CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
35771		);
35772
35773		return point;
35774
35775	}
35776
35777	copy( source ) {
35778
35779		super.copy( source );
35780
35781		this.v0.copy( source.v0 );
35782		this.v1.copy( source.v1 );
35783		this.v2.copy( source.v2 );
35784		this.v3.copy( source.v3 );
35785
35786		return this;
35787
35788	}
35789
35790	toJSON() {
35791
35792		const data = super.toJSON();
35793
35794		data.v0 = this.v0.toArray();
35795		data.v1 = this.v1.toArray();
35796		data.v2 = this.v2.toArray();
35797		data.v3 = this.v3.toArray();
35798
35799		return data;
35800
35801	}
35802
35803	fromJSON( json ) {
35804
35805		super.fromJSON( json );
35806
35807		this.v0.fromArray( json.v0 );
35808		this.v1.fromArray( json.v1 );
35809		this.v2.fromArray( json.v2 );
35810		this.v3.fromArray( json.v3 );
35811
35812		return this;
35813
35814	}
35815
35816}
35817
35818class CubicBezierCurve3 extends Curve {
35819
35820	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
35821
35822		super();
35823
35824		this.isCubicBezierCurve3 = true;
35825
35826		this.type = 'CubicBezierCurve3';
35827
35828		this.v0 = v0;
35829		this.v1 = v1;
35830		this.v2 = v2;
35831		this.v3 = v3;
35832
35833	}
35834
35835	getPoint( t, optionalTarget = new Vector3() ) {
35836
35837		const point = optionalTarget;
35838
35839		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35840
35841		point.set(
35842			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
35843			CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
35844			CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
35845		);
35846
35847		return point;
35848
35849	}
35850
35851	copy( source ) {
35852
35853		super.copy( source );
35854
35855		this.v0.copy( source.v0 );
35856		this.v1.copy( source.v1 );
35857		this.v2.copy( source.v2 );
35858		this.v3.copy( source.v3 );
35859
35860		return this;
35861
35862	}
35863
35864	toJSON() {
35865
35866		const data = super.toJSON();
35867
35868		data.v0 = this.v0.toArray();
35869		data.v1 = this.v1.toArray();
35870		data.v2 = this.v2.toArray();
35871		data.v3 = this.v3.toArray();
35872
35873		return data;
35874
35875	}
35876
35877	fromJSON( json ) {
35878
35879		super.fromJSON( json );
35880
35881		this.v0.fromArray( json.v0 );
35882		this.v1.fromArray( json.v1 );
35883		this.v2.fromArray( json.v2 );
35884		this.v3.fromArray( json.v3 );
35885
35886		return this;
35887
35888	}
35889
35890}
35891
35892class LineCurve extends Curve {
35893
35894	constructor( v1 = new Vector2(), v2 = new Vector2() ) {
35895
35896		super();
35897
35898		this.isLineCurve = true;
35899
35900		this.type = 'LineCurve';
35901
35902		this.v1 = v1;
35903		this.v2 = v2;
35904
35905	}
35906
35907	getPoint( t, optionalTarget = new Vector2() ) {
35908
35909		const point = optionalTarget;
35910
35911		if ( t === 1 ) {
35912
35913			point.copy( this.v2 );
35914
35915		} else {
35916
35917			point.copy( this.v2 ).sub( this.v1 );
35918			point.multiplyScalar( t ).add( this.v1 );
35919
35920		}
35921
35922		return point;
35923
35924	}
35925
35926	// Line curve is linear, so we can overwrite default getPointAt
35927	getPointAt( u, optionalTarget ) {
35928
35929		return this.getPoint( u, optionalTarget );
35930
35931	}
35932
35933	getTangent( t, optionalTarget = new Vector2() ) {
35934
35935		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
35936
35937	}
35938
35939	getTangentAt( u, optionalTarget ) {
35940
35941		return this.getTangent( u, optionalTarget );
35942
35943	}
35944
35945	copy( source ) {
35946
35947		super.copy( source );
35948
35949		this.v1.copy( source.v1 );
35950		this.v2.copy( source.v2 );
35951
35952		return this;
35953
35954	}
35955
35956	toJSON() {
35957
35958		const data = super.toJSON();
35959
35960		data.v1 = this.v1.toArray();
35961		data.v2 = this.v2.toArray();
35962
35963		return data;
35964
35965	}
35966
35967	fromJSON( json ) {
35968
35969		super.fromJSON( json );
35970
35971		this.v1.fromArray( json.v1 );
35972		this.v2.fromArray( json.v2 );
35973
35974		return this;
35975
35976	}
35977
35978}
35979
35980class LineCurve3 extends Curve {
35981
35982	constructor( v1 = new Vector3(), v2 = new Vector3() ) {
35983
35984		super();
35985
35986		this.isLineCurve3 = true;
35987
35988		this.type = 'LineCurve3';
35989
35990		this.v1 = v1;
35991		this.v2 = v2;
35992
35993	}
35994
35995	getPoint( t, optionalTarget = new Vector3() ) {
35996
35997		const point = optionalTarget;
35998
35999		if ( t === 1 ) {
36000
36001			point.copy( this.v2 );
36002
36003		} else {
36004
36005			point.copy( this.v2 ).sub( this.v1 );
36006			point.multiplyScalar( t ).add( this.v1 );
36007
36008		}
36009
36010		return point;
36011
36012	}
36013
36014	// Line curve is linear, so we can overwrite default getPointAt
36015	getPointAt( u, optionalTarget ) {
36016
36017		return this.getPoint( u, optionalTarget );
36018
36019	}
36020
36021	getTangent( t, optionalTarget = new Vector3() ) {
36022
36023		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
36024
36025	}
36026
36027	getTangentAt( u, optionalTarget ) {
36028
36029		return this.getTangent( u, optionalTarget );
36030
36031	}
36032
36033	copy( source ) {
36034
36035		super.copy( source );
36036
36037		this.v1.copy( source.v1 );
36038		this.v2.copy( source.v2 );
36039
36040		return this;
36041
36042	}
36043
36044	toJSON() {
36045
36046		const data = super.toJSON();
36047
36048		data.v1 = this.v1.toArray();
36049		data.v2 = this.v2.toArray();
36050
36051		return data;
36052
36053	}
36054
36055	fromJSON( json ) {
36056
36057		super.fromJSON( json );
36058
36059		this.v1.fromArray( json.v1 );
36060		this.v2.fromArray( json.v2 );
36061
36062		return this;
36063
36064	}
36065
36066}
36067
36068class QuadraticBezierCurve extends Curve {
36069
36070	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
36071
36072		super();
36073
36074		this.isQuadraticBezierCurve = true;
36075
36076		this.type = 'QuadraticBezierCurve';
36077
36078		this.v0 = v0;
36079		this.v1 = v1;
36080		this.v2 = v2;
36081
36082	}
36083
36084	getPoint( t, optionalTarget = new Vector2() ) {
36085
36086		const point = optionalTarget;
36087
36088		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
36089
36090		point.set(
36091			QuadraticBezier( t, v0.x, v1.x, v2.x ),
36092			QuadraticBezier( t, v0.y, v1.y, v2.y )
36093		);
36094
36095		return point;
36096
36097	}
36098
36099	copy( source ) {
36100
36101		super.copy( source );
36102
36103		this.v0.copy( source.v0 );
36104		this.v1.copy( source.v1 );
36105		this.v2.copy( source.v2 );
36106
36107		return this;
36108
36109	}
36110
36111	toJSON() {
36112
36113		const data = super.toJSON();
36114
36115		data.v0 = this.v0.toArray();
36116		data.v1 = this.v1.toArray();
36117		data.v2 = this.v2.toArray();
36118
36119		return data;
36120
36121	}
36122
36123	fromJSON( json ) {
36124
36125		super.fromJSON( json );
36126
36127		this.v0.fromArray( json.v0 );
36128		this.v1.fromArray( json.v1 );
36129		this.v2.fromArray( json.v2 );
36130
36131		return this;
36132
36133	}
36134
36135}
36136
36137class QuadraticBezierCurve3 extends Curve {
36138
36139	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
36140
36141		super();
36142
36143		this.isQuadraticBezierCurve3 = true;
36144
36145		this.type = 'QuadraticBezierCurve3';
36146
36147		this.v0 = v0;
36148		this.v1 = v1;
36149		this.v2 = v2;
36150
36151	}
36152
36153	getPoint( t, optionalTarget = new Vector3() ) {
36154
36155		const point = optionalTarget;
36156
36157		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
36158
36159		point.set(
36160			QuadraticBezier( t, v0.x, v1.x, v2.x ),
36161			QuadraticBezier( t, v0.y, v1.y, v2.y ),
36162			QuadraticBezier( t, v0.z, v1.z, v2.z )
36163		);
36164
36165		return point;
36166
36167	}
36168
36169	copy( source ) {
36170
36171		super.copy( source );
36172
36173		this.v0.copy( source.v0 );
36174		this.v1.copy( source.v1 );
36175		this.v2.copy( source.v2 );
36176
36177		return this;
36178
36179	}
36180
36181	toJSON() {
36182
36183		const data = super.toJSON();
36184
36185		data.v0 = this.v0.toArray();
36186		data.v1 = this.v1.toArray();
36187		data.v2 = this.v2.toArray();
36188
36189		return data;
36190
36191	}
36192
36193	fromJSON( json ) {
36194
36195		super.fromJSON( json );
36196
36197		this.v0.fromArray( json.v0 );
36198		this.v1.fromArray( json.v1 );
36199		this.v2.fromArray( json.v2 );
36200
36201		return this;
36202
36203	}
36204
36205}
36206
36207class SplineCurve extends Curve {
36208
36209	constructor( points = [] ) {
36210
36211		super();
36212
36213		this.isSplineCurve = true;
36214
36215		this.type = 'SplineCurve';
36216
36217		this.points = points;
36218
36219	}
36220
36221	getPoint( t, optionalTarget = new Vector2() ) {
36222
36223		const point = optionalTarget;
36224
36225		const points = this.points;
36226		const p = ( points.length - 1 ) * t;
36227
36228		const intPoint = Math.floor( p );
36229		const weight = p - intPoint;
36230
36231		const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
36232		const p1 = points[ intPoint ];
36233		const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
36234		const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
36235
36236		point.set(
36237			CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
36238			CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
36239		);
36240
36241		return point;
36242
36243	}
36244
36245	copy( source ) {
36246
36247		super.copy( source );
36248
36249		this.points = [];
36250
36251		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
36252
36253			const point = source.points[ i ];
36254
36255			this.points.push( point.clone() );
36256
36257		}
36258
36259		return this;
36260
36261	}
36262
36263	toJSON() {
36264
36265		const data = super.toJSON();
36266
36267		data.points = [];
36268
36269		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
36270
36271			const point = this.points[ i ];
36272			data.points.push( point.toArray() );
36273
36274		}
36275
36276		return data;
36277
36278	}
36279
36280	fromJSON( json ) {
36281
36282		super.fromJSON( json );
36283
36284		this.points = [];
36285
36286		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
36287
36288			const point = json.points[ i ];
36289			this.points.push( new Vector2().fromArray( point ) );
36290
36291		}
36292
36293		return this;
36294
36295	}
36296
36297}
36298
36299var Curves = /*#__PURE__*/Object.freeze({
36300	__proto__: null,
36301	ArcCurve: ArcCurve,
36302	CatmullRomCurve3: CatmullRomCurve3,
36303	CubicBezierCurve: CubicBezierCurve,
36304	CubicBezierCurve3: CubicBezierCurve3,
36305	EllipseCurve: EllipseCurve,
36306	LineCurve: LineCurve,
36307	LineCurve3: LineCurve3,
36308	QuadraticBezierCurve: QuadraticBezierCurve,
36309	QuadraticBezierCurve3: QuadraticBezierCurve3,
36310	SplineCurve: SplineCurve
36311});
36312
36313/**************************************************************
36314 *	Curved Path - a curve path is simply a array of connected
36315 *  curves, but retains the api of a curve
36316 **************************************************************/
36317
36318class CurvePath extends Curve {
36319
36320	constructor() {
36321
36322		super();
36323
36324		this.type = 'CurvePath';
36325
36326		this.curves = [];
36327		this.autoClose = false; // Automatically closes the path
36328
36329	}
36330
36331	add( curve ) {
36332
36333		this.curves.push( curve );
36334
36335	}
36336
36337	closePath() {
36338
36339		// Add a line curve if start and end of lines are not connected
36340		const startPoint = this.curves[ 0 ].getPoint( 0 );
36341		const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
36342
36343		if ( ! startPoint.equals( endPoint ) ) {
36344
36345			const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3';
36346			this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) );
36347
36348		}
36349
36350		return this;
36351
36352	}
36353
36354	// To get accurate point with reference to
36355	// entire path distance at time t,
36356	// following has to be done:
36357
36358	// 1. Length of each sub path have to be known
36359	// 2. Locate and identify type of curve
36360	// 3. Get t for the curve
36361	// 4. Return curve.getPointAt(t')
36362
36363	getPoint( t, optionalTarget ) {
36364
36365		const d = t * this.getLength();
36366		const curveLengths = this.getCurveLengths();
36367		let i = 0;
36368
36369		// To think about boundaries points.
36370
36371		while ( i < curveLengths.length ) {
36372
36373			if ( curveLengths[ i ] >= d ) {
36374
36375				const diff = curveLengths[ i ] - d;
36376				const curve = this.curves[ i ];
36377
36378				const segmentLength = curve.getLength();
36379				const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
36380
36381				return curve.getPointAt( u, optionalTarget );
36382
36383			}
36384
36385			i ++;
36386
36387		}
36388
36389		return null;
36390
36391		// loop where sum != 0, sum > d , sum+1 <d
36392
36393	}
36394
36395	// We cannot use the default THREE.Curve getPoint() with getLength() because in
36396	// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
36397	// getPoint() depends on getLength
36398
36399	getLength() {
36400
36401		const lens = this.getCurveLengths();
36402		return lens[ lens.length - 1 ];
36403
36404	}
36405
36406	// cacheLengths must be recalculated.
36407	updateArcLengths() {
36408
36409		this.needsUpdate = true;
36410		this.cacheLengths = null;
36411		this.getCurveLengths();
36412
36413	}
36414
36415	// Compute lengths and cache them
36416	// We cannot overwrite getLengths() because UtoT mapping uses it.
36417
36418	getCurveLengths() {
36419
36420		// We use cache values if curves and cache array are same length
36421
36422		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
36423
36424			return this.cacheLengths;
36425
36426		}
36427
36428		// Get length of sub-curve
36429		// Push sums into cached array
36430
36431		const lengths = [];
36432		let sums = 0;
36433
36434		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
36435
36436			sums += this.curves[ i ].getLength();
36437			lengths.push( sums );
36438
36439		}
36440
36441		this.cacheLengths = lengths;
36442
36443		return lengths;
36444
36445	}
36446
36447	getSpacedPoints( divisions = 40 ) {
36448
36449		const points = [];
36450
36451		for ( let i = 0; i <= divisions; i ++ ) {
36452
36453			points.push( this.getPoint( i / divisions ) );
36454
36455		}
36456
36457		if ( this.autoClose ) {
36458
36459			points.push( points[ 0 ] );
36460
36461		}
36462
36463		return points;
36464
36465	}
36466
36467	getPoints( divisions = 12 ) {
36468
36469		const points = [];
36470		let last;
36471
36472		for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
36473
36474			const curve = curves[ i ];
36475			const resolution = curve.isEllipseCurve ? divisions * 2
36476				: ( curve.isLineCurve || curve.isLineCurve3 ) ? 1
36477					: curve.isSplineCurve ? divisions * curve.points.length
36478						: divisions;
36479
36480			const pts = curve.getPoints( resolution );
36481
36482			for ( let j = 0; j < pts.length; j ++ ) {
36483
36484				const point = pts[ j ];
36485
36486				if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
36487
36488				points.push( point );
36489				last = point;
36490
36491			}
36492
36493		}
36494
36495		if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
36496
36497			points.push( points[ 0 ] );
36498
36499		}
36500
36501		return points;
36502
36503	}
36504
36505	copy( source ) {
36506
36507		super.copy( source );
36508
36509		this.curves = [];
36510
36511		for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
36512
36513			const curve = source.curves[ i ];
36514
36515			this.curves.push( curve.clone() );
36516
36517		}
36518
36519		this.autoClose = source.autoClose;
36520
36521		return this;
36522
36523	}
36524
36525	toJSON() {
36526
36527		const data = super.toJSON();
36528
36529		data.autoClose = this.autoClose;
36530		data.curves = [];
36531
36532		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
36533
36534			const curve = this.curves[ i ];
36535			data.curves.push( curve.toJSON() );
36536
36537		}
36538
36539		return data;
36540
36541	}
36542
36543	fromJSON( json ) {
36544
36545		super.fromJSON( json );
36546
36547		this.autoClose = json.autoClose;
36548		this.curves = [];
36549
36550		for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
36551
36552			const curve = json.curves[ i ];
36553			this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
36554
36555		}
36556
36557		return this;
36558
36559	}
36560
36561}
36562
36563class Path extends CurvePath {
36564
36565	constructor( points ) {
36566
36567		super();
36568
36569		this.type = 'Path';
36570
36571		this.currentPoint = new Vector2();
36572
36573		if ( points ) {
36574
36575			this.setFromPoints( points );
36576
36577		}
36578
36579	}
36580
36581	setFromPoints( points ) {
36582
36583		this.moveTo( points[ 0 ].x, points[ 0 ].y );
36584
36585		for ( let i = 1, l = points.length; i < l; i ++ ) {
36586
36587			this.lineTo( points[ i ].x, points[ i ].y );
36588
36589		}
36590
36591		return this;
36592
36593	}
36594
36595	moveTo( x, y ) {
36596
36597		this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
36598
36599		return this;
36600
36601	}
36602
36603	lineTo( x, y ) {
36604
36605		const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
36606		this.curves.push( curve );
36607
36608		this.currentPoint.set( x, y );
36609
36610		return this;
36611
36612	}
36613
36614	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
36615
36616		const curve = new QuadraticBezierCurve(
36617			this.currentPoint.clone(),
36618			new Vector2( aCPx, aCPy ),
36619			new Vector2( aX, aY )
36620		);
36621
36622		this.curves.push( curve );
36623
36624		this.currentPoint.set( aX, aY );
36625
36626		return this;
36627
36628	}
36629
36630	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
36631
36632		const curve = new CubicBezierCurve(
36633			this.currentPoint.clone(),
36634			new Vector2( aCP1x, aCP1y ),
36635			new Vector2( aCP2x, aCP2y ),
36636			new Vector2( aX, aY )
36637		);
36638
36639		this.curves.push( curve );
36640
36641		this.currentPoint.set( aX, aY );
36642
36643		return this;
36644
36645	}
36646
36647	splineThru( pts /*Array of Vector*/ ) {
36648
36649		const npts = [ this.currentPoint.clone() ].concat( pts );
36650
36651		const curve = new SplineCurve( npts );
36652		this.curves.push( curve );
36653
36654		this.currentPoint.copy( pts[ pts.length - 1 ] );
36655
36656		return this;
36657
36658	}
36659
36660	arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36661
36662		const x0 = this.currentPoint.x;
36663		const y0 = this.currentPoint.y;
36664
36665		this.absarc( aX + x0, aY + y0, aRadius,
36666			aStartAngle, aEndAngle, aClockwise );
36667
36668		return this;
36669
36670	}
36671
36672	absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36673
36674		this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
36675
36676		return this;
36677
36678	}
36679
36680	ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36681
36682		const x0 = this.currentPoint.x;
36683		const y0 = this.currentPoint.y;
36684
36685		this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36686
36687		return this;
36688
36689	}
36690
36691	absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36692
36693		const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36694
36695		if ( this.curves.length > 0 ) {
36696
36697			// if a previous curve is present, attempt to join
36698			const firstPoint = curve.getPoint( 0 );
36699
36700			if ( ! firstPoint.equals( this.currentPoint ) ) {
36701
36702				this.lineTo( firstPoint.x, firstPoint.y );
36703
36704			}
36705
36706		}
36707
36708		this.curves.push( curve );
36709
36710		const lastPoint = curve.getPoint( 1 );
36711		this.currentPoint.copy( lastPoint );
36712
36713		return this;
36714
36715	}
36716
36717	copy( source ) {
36718
36719		super.copy( source );
36720
36721		this.currentPoint.copy( source.currentPoint );
36722
36723		return this;
36724
36725	}
36726
36727	toJSON() {
36728
36729		const data = super.toJSON();
36730
36731		data.currentPoint = this.currentPoint.toArray();
36732
36733		return data;
36734
36735	}
36736
36737	fromJSON( json ) {
36738
36739		super.fromJSON( json );
36740
36741		this.currentPoint.fromArray( json.currentPoint );
36742
36743		return this;
36744
36745	}
36746
36747}
36748
36749class LatheGeometry extends BufferGeometry {
36750
36751	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 ) {
36752
36753		super();
36754
36755		this.type = 'LatheGeometry';
36756
36757		this.parameters = {
36758			points: points,
36759			segments: segments,
36760			phiStart: phiStart,
36761			phiLength: phiLength
36762		};
36763
36764		segments = Math.floor( segments );
36765
36766		// clamp phiLength so it's in range of [ 0, 2PI ]
36767
36768		phiLength = clamp( phiLength, 0, Math.PI * 2 );
36769
36770		// buffers
36771
36772		const indices = [];
36773		const vertices = [];
36774		const uvs = [];
36775		const initNormals = [];
36776		const normals = [];
36777
36778		// helper variables
36779
36780		const inverseSegments = 1.0 / segments;
36781		const vertex = new Vector3();
36782		const uv = new Vector2();
36783		const normal = new Vector3();
36784		const curNormal = new Vector3();
36785		const prevNormal = new Vector3();
36786		let dx = 0;
36787		let dy = 0;
36788
36789		// pre-compute normals for initial "meridian"
36790
36791		for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
36792
36793			switch ( j ) {
36794
36795				case 0:				// special handling for 1st vertex on path
36796
36797					dx = points[ j + 1 ].x - points[ j ].x;
36798					dy = points[ j + 1 ].y - points[ j ].y;
36799
36800					normal.x = dy * 1.0;
36801					normal.y = - dx;
36802					normal.z = dy * 0.0;
36803
36804					prevNormal.copy( normal );
36805
36806					normal.normalize();
36807
36808					initNormals.push( normal.x, normal.y, normal.z );
36809
36810					break;
36811
36812				case ( points.length - 1 ):	// special handling for last Vertex on path
36813
36814					initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z );
36815
36816					break;
36817
36818				default:			// default handling for all vertices in between
36819
36820					dx = points[ j + 1 ].x - points[ j ].x;
36821					dy = points[ j + 1 ].y - points[ j ].y;
36822
36823					normal.x = dy * 1.0;
36824					normal.y = - dx;
36825					normal.z = dy * 0.0;
36826
36827					curNormal.copy( normal );
36828
36829					normal.x += prevNormal.x;
36830					normal.y += prevNormal.y;
36831					normal.z += prevNormal.z;
36832
36833					normal.normalize();
36834
36835					initNormals.push( normal.x, normal.y, normal.z );
36836
36837					prevNormal.copy( curNormal );
36838
36839			}
36840
36841		}
36842
36843		// generate vertices, uvs and normals
36844
36845		for ( let i = 0; i <= segments; i ++ ) {
36846
36847			const phi = phiStart + i * inverseSegments * phiLength;
36848
36849			const sin = Math.sin( phi );
36850			const cos = Math.cos( phi );
36851
36852			for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
36853
36854				// vertex
36855
36856				vertex.x = points[ j ].x * sin;
36857				vertex.y = points[ j ].y;
36858				vertex.z = points[ j ].x * cos;
36859
36860				vertices.push( vertex.x, vertex.y, vertex.z );
36861
36862				// uv
36863
36864				uv.x = i / segments;
36865				uv.y = j / ( points.length - 1 );
36866
36867				uvs.push( uv.x, uv.y );
36868
36869				// normal
36870
36871				const x = initNormals[ 3 * j + 0 ] * sin;
36872				const y = initNormals[ 3 * j + 1 ];
36873				const z = initNormals[ 3 * j + 0 ] * cos;
36874
36875				normals.push( x, y, z );
36876
36877			}
36878
36879		}
36880
36881		// indices
36882
36883		for ( let i = 0; i < segments; i ++ ) {
36884
36885			for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
36886
36887				const base = j + i * points.length;
36888
36889				const a = base;
36890				const b = base + points.length;
36891				const c = base + points.length + 1;
36892				const d = base + 1;
36893
36894				// faces
36895
36896				indices.push( a, b, d );
36897				indices.push( c, d, b );
36898
36899			}
36900
36901		}
36902
36903		// build geometry
36904
36905		this.setIndex( indices );
36906		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36907		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36908		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36909
36910	}
36911
36912	copy( source ) {
36913
36914		super.copy( source );
36915
36916		this.parameters = Object.assign( {}, source.parameters );
36917
36918		return this;
36919
36920	}
36921
36922	static fromJSON( data ) {
36923
36924		return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength );
36925
36926	}
36927
36928}
36929
36930class CapsuleGeometry extends LatheGeometry {
36931
36932	constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) {
36933
36934		const path = new Path();
36935		path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 );
36936		path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 );
36937
36938		super( path.getPoints( capSegments ), radialSegments );
36939
36940		this.type = 'CapsuleGeometry';
36941
36942		this.parameters = {
36943			radius: radius,
36944			length: length,
36945			capSegments: capSegments,
36946			radialSegments: radialSegments,
36947		};
36948
36949	}
36950
36951	static fromJSON( data ) {
36952
36953		return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments );
36954
36955	}
36956
36957}
36958
36959class CircleGeometry extends BufferGeometry {
36960
36961	constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) {
36962
36963		super();
36964
36965		this.type = 'CircleGeometry';
36966
36967		this.parameters = {
36968			radius: radius,
36969			segments: segments,
36970			thetaStart: thetaStart,
36971			thetaLength: thetaLength
36972		};
36973
36974		segments = Math.max( 3, segments );
36975
36976		// buffers
36977
36978		const indices = [];
36979		const vertices = [];
36980		const normals = [];
36981		const uvs = [];
36982
36983		// helper variables
36984
36985		const vertex = new Vector3();
36986		const uv = new Vector2();
36987
36988		// center point
36989
36990		vertices.push( 0, 0, 0 );
36991		normals.push( 0, 0, 1 );
36992		uvs.push( 0.5, 0.5 );
36993
36994		for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
36995
36996			const segment = thetaStart + s / segments * thetaLength;
36997
36998			// vertex
36999
37000			vertex.x = radius * Math.cos( segment );
37001			vertex.y = radius * Math.sin( segment );
37002
37003			vertices.push( vertex.x, vertex.y, vertex.z );
37004
37005			// normal
37006
37007			normals.push( 0, 0, 1 );
37008
37009			// uvs
37010
37011			uv.x = ( vertices[ i ] / radius + 1 ) / 2;
37012			uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
37013
37014			uvs.push( uv.x, uv.y );
37015
37016		}
37017
37018		// indices
37019
37020		for ( let i = 1; i <= segments; i ++ ) {
37021
37022			indices.push( i, i + 1, 0 );
37023
37024		}
37025
37026		// build geometry
37027
37028		this.setIndex( indices );
37029		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,756 bytes, lines 37030-37255
37030		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37031		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37032
37033	}
37034
37035	copy( source ) {
37036
37037		super.copy( source );
37038
37039		this.parameters = Object.assign( {}, source.parameters );
37040
37041		return this;
37042
37043	}
37044
37045	static fromJSON( data ) {
37046
37047		return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength );
37048
37049	}
37050
37051}
37052
37053class CylinderGeometry extends BufferGeometry {
37054
37055	constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
37056
37057		super();
37058
37059		this.type = 'CylinderGeometry';
37060
37061		this.parameters = {
37062			radiusTop: radiusTop,
37063			radiusBottom: radiusBottom,
37064			height: height,
37065			radialSegments: radialSegments,
37066			heightSegments: heightSegments,
37067			openEnded: openEnded,
37068			thetaStart: thetaStart,
37069			thetaLength: thetaLength
37070		};
37071
37072		const scope = this;
37073
37074		radialSegments = Math.floor( radialSegments );
37075		heightSegments = Math.floor( heightSegments );
37076
37077		// buffers
37078
37079		const indices = [];
37080		const vertices = [];
37081		const normals = [];
37082		const uvs = [];
37083
37084		// helper variables
37085
37086		let index = 0;
37087		const indexArray = [];
37088		const halfHeight = height / 2;
37089		let groupStart = 0;
37090
37091		// generate geometry
37092
37093		generateTorso();
37094
37095		if ( openEnded === false ) {
37096
37097			if ( radiusTop > 0 ) generateCap( true );
37098			if ( radiusBottom > 0 ) generateCap( false );
37099
37100		}
37101
37102		// build geometry
37103
37104		this.setIndex( indices );
37105		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37106		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37107		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37108
37109		function generateTorso() {
37110
37111			const normal = new Vector3();
37112			const vertex = new Vector3();
37113
37114			let groupCount = 0;
37115
37116			// this will be used to calculate the normal
37117			const slope = ( radiusBottom - radiusTop ) / height;
37118
37119			// generate vertices, normals and uvs
37120
37121			for ( let y = 0; y <= heightSegments; y ++ ) {
37122
37123				const indexRow = [];
37124
37125				const v = y / heightSegments;
37126
37127				// calculate the radius of the current row
37128
37129				const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
37130
37131				for ( let x = 0; x <= radialSegments; x ++ ) {
37132
37133					const u = x / radialSegments;
37134
37135					const theta = u * thetaLength + thetaStart;
37136
37137					const sinTheta = Math.sin( theta );
37138					const cosTheta = Math.cos( theta );
37139
37140					// vertex
37141
37142					vertex.x = radius * sinTheta;
37143					vertex.y = - v * height + halfHeight;
37144					vertex.z = radius * cosTheta;
37145					vertices.push( vertex.x, vertex.y, vertex.z );
37146
37147					// normal
37148
37149					normal.set( sinTheta, slope, cosTheta ).normalize();
37150					normals.push( normal.x, normal.y, normal.z );
37151
37152					// uv
37153
37154					uvs.push( u, 1 - v );
37155
37156					// save index of vertex in respective row
37157
37158					indexRow.push( index ++ );
37159
37160				}
37161
37162				// now save vertices of the row in our index array
37163
37164				indexArray.push( indexRow );
37165
37166			}
37167
37168			// generate indices
37169
37170			for ( let x = 0; x < radialSegments; x ++ ) {
37171
37172				for ( let y = 0; y < heightSegments; y ++ ) {
37173
37174					// we use the index array to access the correct indices
37175
37176					const a = indexArray[ y ][ x ];
37177					const b = indexArray[ y + 1 ][ x ];
37178					const c = indexArray[ y + 1 ][ x + 1 ];
37179					const d = indexArray[ y ][ x + 1 ];
37180
37181					// faces
37182
37183					indices.push( a, b, d );
37184					indices.push( b, c, d );
37185
37186					// update group counter
37187
37188					groupCount += 6;
37189
37190				}
37191
37192			}
37193
37194			// add a group to the geometry. this will ensure multi material support
37195
37196			scope.addGroup( groupStart, groupCount, 0 );
37197
37198			// calculate new start value for groups
37199
37200			groupStart += groupCount;
37201
37202		}
37203
37204		function generateCap( top ) {
37205
37206			// save the index of the first center vertex
37207			const centerIndexStart = index;
37208
37209			const uv = new Vector2();
37210			const vertex = new Vector3();
37211
37212			let groupCount = 0;
37213
37214			const radius = ( top === true ) ? radiusTop : radiusBottom;
37215			const sign = ( top === true ) ? 1 : - 1;
37216
37217			// first we generate the center vertex data of the cap.
37218			// because the geometry needs one set of uvs per face,
37219			// we must generate a center vertex per face/segment
37220
37221			for ( let x = 1; x <= radialSegments; x ++ ) {
37222
37223				// vertex
37224
37225				vertices.push( 0, halfHeight * sign, 0 );
37226
37227				// normal
37228
37229				normals.push( 0, sign, 0 );
37230
37231				// uv
37232
37233				uvs.push( 0.5, 0.5 );
37234
37235				// increase index
37236
37237				index ++;
37238
37239			}
37240
37241			// save the index of the last center vertex
37242			const centerIndexEnd = index;
37243
37244			// now we generate the surrounding vertices, normals and uvs
37245
37246			for ( let x = 0; x <= radialSegments; x ++ ) {
37247
37248				const u = x / radialSegments;
37249				const theta = u * thetaLength + thetaStart;
37250
37251				const cosTheta = Math.cos( theta );
37252				const sinTheta = Math.sin( theta );
37253
37254				// vertex
37255
vendor: 16,069 bytes, lines 37256-38034
37256				vertex.x = radius * sinTheta;
37257				vertex.y = halfHeight * sign;
37258				vertex.z = radius * cosTheta;
37259				vertices.push( vertex.x, vertex.y, vertex.z );
37260
37261				// normal
37262
37263				normals.push( 0, sign, 0 );
37264
37265				// uv
37266
37267				uv.x = ( cosTheta * 0.5 ) + 0.5;
37268				uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
37269				uvs.push( uv.x, uv.y );
37270
37271				// increase index
37272
37273				index ++;
37274
37275			}
37276
37277			// generate indices
37278
37279			for ( let x = 0; x < radialSegments; x ++ ) {
37280
37281				const c = centerIndexStart + x;
37282				const i = centerIndexEnd + x;
37283
37284				if ( top === true ) {
37285
37286					// face top
37287
37288					indices.push( i, i + 1, c );
37289
37290				} else {
37291
37292					// face bottom
37293
37294					indices.push( i + 1, i, c );
37295
37296				}
37297
37298				groupCount += 3;
37299
37300			}
37301
37302			// add a group to the geometry. this will ensure multi material support
37303
37304			scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
37305
37306			// calculate new start value for groups
37307
37308			groupStart += groupCount;
37309
37310		}
37311
37312	}
37313
37314	copy( source ) {
37315
37316		super.copy( source );
37317
37318		this.parameters = Object.assign( {}, source.parameters );
37319
37320		return this;
37321
37322	}
37323
37324	static fromJSON( data ) {
37325
37326		return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
37327
37328	}
37329
37330}
37331
37332class ConeGeometry extends CylinderGeometry {
37333
37334	constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
37335
37336		super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
37337
37338		this.type = 'ConeGeometry';
37339
37340		this.parameters = {
37341			radius: radius,
37342			height: height,
37343			radialSegments: radialSegments,
37344			heightSegments: heightSegments,
37345			openEnded: openEnded,
37346			thetaStart: thetaStart,
37347			thetaLength: thetaLength
37348		};
37349
37350	}
37351
37352	static fromJSON( data ) {
37353
37354		return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
37355
37356	}
37357
37358}
37359
37360class PolyhedronGeometry extends BufferGeometry {
37361
37362	constructor( vertices = [], indices = [], radius = 1, detail = 0 ) {
37363
37364		super();
37365
37366		this.type = 'PolyhedronGeometry';
37367
37368		this.parameters = {
37369			vertices: vertices,
37370			indices: indices,
37371			radius: radius,
37372			detail: detail
37373		};
37374
37375		// default buffer data
37376
37377		const vertexBuffer = [];
37378		const uvBuffer = [];
37379
37380		// the subdivision creates the vertex buffer data
37381
37382		subdivide( detail );
37383
37384		// all vertices should lie on a conceptual sphere with a given radius
37385
37386		applyRadius( radius );
37387
37388		// finally, create the uv data
37389
37390		generateUVs();
37391
37392		// build non-indexed geometry
37393
37394		this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
37395		this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
37396		this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
37397
37398		if ( detail === 0 ) {
37399
37400			this.computeVertexNormals(); // flat normals
37401
37402		} else {
37403
37404			this.normalizeNormals(); // smooth normals
37405
37406		}
37407
37408		// helper functions
37409
37410		function subdivide( detail ) {
37411
37412			const a = new Vector3();
37413			const b = new Vector3();
37414			const c = new Vector3();
37415
37416			// iterate over all faces and apply a subdivision with the given detail value
37417
37418			for ( let i = 0; i < indices.length; i += 3 ) {
37419
37420				// get the vertices of the face
37421
37422				getVertexByIndex( indices[ i + 0 ], a );
37423				getVertexByIndex( indices[ i + 1 ], b );
37424				getVertexByIndex( indices[ i + 2 ], c );
37425
37426				// perform subdivision
37427
37428				subdivideFace( a, b, c, detail );
37429
37430			}
37431
37432		}
37433
37434		function subdivideFace( a, b, c, detail ) {
37435
37436			const cols = detail + 1;
37437
37438			// we use this multidimensional array as a data structure for creating the subdivision
37439
37440			const v = [];
37441
37442			// construct all of the vertices for this subdivision
37443
37444			for ( let i = 0; i <= cols; i ++ ) {
37445
37446				v[ i ] = [];
37447
37448				const aj = a.clone().lerp( c, i / cols );
37449				const bj = b.clone().lerp( c, i / cols );
37450
37451				const rows = cols - i;
37452
37453				for ( let j = 0; j <= rows; j ++ ) {
37454
37455					if ( j === 0 && i === cols ) {
37456
37457						v[ i ][ j ] = aj;
37458
37459					} else {
37460
37461						v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
37462
37463					}
37464
37465				}
37466
37467			}
37468
37469			// construct all of the faces
37470
37471			for ( let i = 0; i < cols; i ++ ) {
37472
37473				for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
37474
37475					const k = Math.floor( j / 2 );
37476
37477					if ( j % 2 === 0 ) {
37478
37479						pushVertex( v[ i ][ k + 1 ] );
37480						pushVertex( v[ i + 1 ][ k ] );
37481						pushVertex( v[ i ][ k ] );
37482
37483					} else {
37484
37485						pushVertex( v[ i ][ k + 1 ] );
37486						pushVertex( v[ i + 1 ][ k + 1 ] );
37487						pushVertex( v[ i + 1 ][ k ] );
37488
37489					}
37490
37491				}
37492
37493			}
37494
37495		}
37496
37497		function applyRadius( radius ) {
37498
37499			const vertex = new Vector3();
37500
37501			// iterate over the entire buffer and apply the radius to each vertex
37502
37503			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
37504
37505				vertex.x = vertexBuffer[ i + 0 ];
37506				vertex.y = vertexBuffer[ i + 1 ];
37507				vertex.z = vertexBuffer[ i + 2 ];
37508
37509				vertex.normalize().multiplyScalar( radius );
37510
37511				vertexBuffer[ i + 0 ] = vertex.x;
37512				vertexBuffer[ i + 1 ] = vertex.y;
37513				vertexBuffer[ i + 2 ] = vertex.z;
37514
37515			}
37516
37517		}
37518
37519		function generateUVs() {
37520
37521			const vertex = new Vector3();
37522
37523			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
37524
37525				vertex.x = vertexBuffer[ i + 0 ];
37526				vertex.y = vertexBuffer[ i + 1 ];
37527				vertex.z = vertexBuffer[ i + 2 ];
37528
37529				const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
37530				const v = inclination( vertex ) / Math.PI + 0.5;
37531				uvBuffer.push( u, 1 - v );
37532
37533			}
37534
37535			correctUVs();
37536
37537			correctSeam();
37538
37539		}
37540
37541		function correctSeam() {
37542
37543			// handle case when face straddles the seam, see #3269
37544
37545			for ( let i = 0; i < uvBuffer.length; i += 6 ) {
37546
37547				// uv data of a single face
37548
37549				const x0 = uvBuffer[ i + 0 ];
37550				const x1 = uvBuffer[ i + 2 ];
37551				const x2 = uvBuffer[ i + 4 ];
37552
37553				const max = Math.max( x0, x1, x2 );
37554				const min = Math.min( x0, x1, x2 );
37555
37556				// 0.9 is somewhat arbitrary
37557
37558				if ( max > 0.9 && min < 0.1 ) {
37559
37560					if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
37561					if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
37562					if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
37563
37564				}
37565
37566			}
37567
37568		}
37569
37570		function pushVertex( vertex ) {
37571
37572			vertexBuffer.push( vertex.x, vertex.y, vertex.z );
37573
37574		}
37575
37576		function getVertexByIndex( index, vertex ) {
37577
37578			const stride = index * 3;
37579
37580			vertex.x = vertices[ stride + 0 ];
37581			vertex.y = vertices[ stride + 1 ];
37582			vertex.z = vertices[ stride + 2 ];
37583
37584		}
37585
37586		function correctUVs() {
37587
37588			const a = new Vector3();
37589			const b = new Vector3();
37590			const c = new Vector3();
37591
37592			const centroid = new Vector3();
37593
37594			const uvA = new Vector2();
37595			const uvB = new Vector2();
37596			const uvC = new Vector2();
37597
37598			for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
37599
37600				a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
37601				b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
37602				c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
37603
37604				uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
37605				uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
37606				uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
37607
37608				centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
37609
37610				const azi = azimuth( centroid );
37611
37612				correctUV( uvA, j + 0, a, azi );
37613				correctUV( uvB, j + 2, b, azi );
37614				correctUV( uvC, j + 4, c, azi );
37615
37616			}
37617
37618		}
37619
37620		function correctUV( uv, stride, vector, azimuth ) {
37621
37622			if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
37623
37624				uvBuffer[ stride ] = uv.x - 1;
37625
37626			}
37627
37628			if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
37629
37630				uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
37631
37632			}
37633
37634		}
37635
37636		// Angle around the Y axis, counter-clockwise when looking from above.
37637
37638		function azimuth( vector ) {
37639
37640			return Math.atan2( vector.z, - vector.x );
37641
37642		}
37643
37644
37645		// Angle above the XZ plane.
37646
37647		function inclination( vector ) {
37648
37649			return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
37650
37651		}
37652
37653	}
37654
37655	copy( source ) {
37656
37657		super.copy( source );
37658
37659		this.parameters = Object.assign( {}, source.parameters );
37660
37661		return this;
37662
37663	}
37664
37665	static fromJSON( data ) {
37666
37667		return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details );
37668
37669	}
37670
37671}
37672
37673class DodecahedronGeometry extends PolyhedronGeometry {
37674
37675	constructor( radius = 1, detail = 0 ) {
37676
37677		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
37678		const r = 1 / t;
37679
37680		const vertices = [
37681
37682			// (±1, ±1, ±1)
37683			- 1, - 1, - 1,	- 1, - 1, 1,
37684			- 1, 1, - 1, - 1, 1, 1,
37685			1, - 1, - 1, 1, - 1, 1,
37686			1, 1, - 1, 1, 1, 1,
37687
37688			// (0, ±1/φ, ±φ)
37689			0, - r, - t, 0, - r, t,
37690			0, r, - t, 0, r, t,
37691
37692			// (±1/φ, ±φ, 0)
37693			- r, - t, 0, - r, t, 0,
37694			r, - t, 0, r, t, 0,
37695
37696			// (±φ, 0, ±1/φ)
37697			- t, 0, - r, t, 0, - r,
37698			- t, 0, r, t, 0, r
37699		];
37700
37701		const indices = [
37702			3, 11, 7, 	3, 7, 15, 	3, 15, 13,
37703			7, 19, 17, 	7, 17, 6, 	7, 6, 15,
37704			17, 4, 8, 	17, 8, 10, 	17, 10, 6,
37705			8, 0, 16, 	8, 16, 2, 	8, 2, 10,
37706			0, 12, 1, 	0, 1, 18, 	0, 18, 16,
37707			6, 10, 2, 	6, 2, 13, 	6, 13, 15,
37708			2, 16, 18, 	2, 18, 3, 	2, 3, 13,
37709			18, 1, 9, 	18, 9, 11, 	18, 11, 3,
37710			4, 14, 12, 	4, 12, 0, 	4, 0, 8,
37711			11, 9, 5, 	11, 5, 19, 	11, 19, 7,
37712			19, 5, 14, 	19, 14, 4, 	19, 4, 17,
37713			1, 12, 14, 	1, 14, 5, 	1, 5, 9
37714		];
37715
37716		super( vertices, indices, radius, detail );
37717
37718		this.type = 'DodecahedronGeometry';
37719
37720		this.parameters = {
37721			radius: radius,
37722			detail: detail
37723		};
37724
37725	}
37726
37727	static fromJSON( data ) {
37728
37729		return new DodecahedronGeometry( data.radius, data.detail );
37730
37731	}
37732
37733}
37734
37735const _v0 = /*@__PURE__*/ new Vector3();
37736const _v1$1 = /*@__PURE__*/ new Vector3();
37737const _normal = /*@__PURE__*/ new Vector3();
37738const _triangle = /*@__PURE__*/ new Triangle();
37739
37740class EdgesGeometry extends BufferGeometry {
37741
37742	constructor( geometry = null, thresholdAngle = 1 ) {
37743
37744		super();
37745
37746		this.type = 'EdgesGeometry';
37747
37748		this.parameters = {
37749			geometry: geometry,
37750			thresholdAngle: thresholdAngle
37751		};
37752
37753		if ( geometry !== null ) {
37754
37755			const precisionPoints = 4;
37756			const precision = Math.pow( 10, precisionPoints );
37757			const thresholdDot = Math.cos( DEG2RAD * thresholdAngle );
37758
37759			const indexAttr = geometry.getIndex();
37760			const positionAttr = geometry.getAttribute( 'position' );
37761			const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
37762
37763			const indexArr = [ 0, 0, 0 ];
37764			const vertKeys = [ 'a', 'b', 'c' ];
37765			const hashes = new Array( 3 );
37766
37767			const edgeData = {};
37768			const vertices = [];
37769			for ( let i = 0; i < indexCount; i += 3 ) {
37770
37771				if ( indexAttr ) {
37772
37773					indexArr[ 0 ] = indexAttr.getX( i );
37774					indexArr[ 1 ] = indexAttr.getX( i + 1 );
37775					indexArr[ 2 ] = indexAttr.getX( i + 2 );
37776
37777				} else {
37778
37779					indexArr[ 0 ] = i;
37780					indexArr[ 1 ] = i + 1;
37781					indexArr[ 2 ] = i + 2;
37782
37783				}
37784
37785				const { a, b, c } = _triangle;
37786				a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
37787				b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
37788				c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
37789				_triangle.getNormal( _normal );
37790
37791				// create hashes for the edge from the vertices
37792				hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
37793				hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
37794				hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
37795
37796				// skip degenerate triangles
37797				if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
37798
37799					continue;
37800
37801				}
37802
37803				// iterate over every edge
37804				for ( let j = 0; j < 3; j ++ ) {
37805
37806					// get the first and next vertex making up the edge
37807					const jNext = ( j + 1 ) % 3;
37808					const vecHash0 = hashes[ j ];
37809					const vecHash1 = hashes[ jNext ];
37810					const v0 = _triangle[ vertKeys[ j ] ];
37811					const v1 = _triangle[ vertKeys[ jNext ] ];
37812
37813					const hash = `${ vecHash0 }_${ vecHash1 }`;
37814					const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
37815
37816					if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
37817
37818						// if we found a sibling edge add it into the vertex array if
37819						// it meets the angle threshold and delete the edge from the map.
37820						if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
37821
37822							vertices.push( v0.x, v0.y, v0.z );
37823							vertices.push( v1.x, v1.y, v1.z );
37824
37825						}
37826
37827						edgeData[ reverseHash ] = null;
37828
37829					} else if ( ! ( hash in edgeData ) ) {
37830
37831						// if we've already got an edge here then skip adding a new one
37832						edgeData[ hash ] = {
37833
37834							index0: indexArr[ j ],
37835							index1: indexArr[ jNext ],
37836							normal: _normal.clone(),
37837
37838						};
37839
37840					}
37841
37842				}
37843
37844			}
37845
37846			// iterate over all remaining, unmatched edges and add them to the vertex array
37847			for ( const key in edgeData ) {
37848
37849				if ( edgeData[ key ] ) {
37850
37851					const { index0, index1 } = edgeData[ key ];
37852					_v0.fromBufferAttribute( positionAttr, index0 );
37853					_v1$1.fromBufferAttribute( positionAttr, index1 );
37854
37855					vertices.push( _v0.x, _v0.y, _v0.z );
37856					vertices.push( _v1$1.x, _v1$1.y, _v1$1.z );
37857
37858				}
37859
37860			}
37861
37862			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37863
37864		}
37865
37866	}
37867
37868	copy( source ) {
37869
37870		super.copy( source );
37871
37872		this.parameters = Object.assign( {}, source.parameters );
37873
37874		return this;
37875
37876	}
37877
37878}
37879
37880class Shape extends Path {
37881
37882	constructor( points ) {
37883
37884		super( points );
37885
37886		this.uuid = generateUUID();
37887
37888		this.type = 'Shape';
37889
37890		this.holes = [];
37891
37892	}
37893
37894	getPointsHoles( divisions ) {
37895
37896		const holesPts = [];
37897
37898		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
37899
37900			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
37901
37902		}
37903
37904		return holesPts;
37905
37906	}
37907
37908	// get points of shape and holes (keypoints based on segments parameter)
37909
37910	extractPoints( divisions ) {
37911
37912		return {
37913
37914			shape: this.getPoints( divisions ),
37915			holes: this.getPointsHoles( divisions )
37916
37917		};
37918
37919	}
37920
37921	copy( source ) {
37922
37923		super.copy( source );
37924
37925		this.holes = [];
37926
37927		for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
37928
37929			const hole = source.holes[ i ];
37930
37931			this.holes.push( hole.clone() );
37932
37933		}
37934
37935		return this;
37936
37937	}
37938
37939	toJSON() {
37940
37941		const data = super.toJSON();
37942
37943		data.uuid = this.uuid;
37944		data.holes = [];
37945
37946		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
37947
37948			const hole = this.holes[ i ];
37949			data.holes.push( hole.toJSON() );
37950
37951		}
37952
37953		return data;
37954
37955	}
37956
37957	fromJSON( json ) {
37958
37959		super.fromJSON( json );
37960
37961		this.uuid = json.uuid;
37962		this.holes = [];
37963
37964		for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
37965
37966			const hole = json.holes[ i ];
37967			this.holes.push( new Path().fromJSON( hole ) );
37968
37969		}
37970
37971		return this;
37972
37973	}
37974
37975}
37976
37977/**
37978 * Port from https://github.com/mapbox/earcut (v2.2.4)
37979 */
37980
37981const Earcut = {
37982
37983	triangulate: function ( data, holeIndices, dim = 2 ) {
37984
37985		const hasHoles = holeIndices && holeIndices.length;
37986		const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
37987		let outerNode = linkedList( data, 0, outerLen, dim, true );
37988		const triangles = [];
37989
37990		if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles;
37991
37992		let minX, minY, maxX, maxY, x, y, invSize;
37993
37994		if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
37995
37996		// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
37997		if ( data.length > 80 * dim ) {
37998
37999			minX = maxX = data[ 0 ];
38000			minY = maxY = data[ 1 ];
38001
38002			for ( let i = dim; i < outerLen; i += dim ) {
38003
38004				x = data[ i ];
38005				y = data[ i + 1 ];
38006				if ( x < minX ) minX = x;
38007				if ( y < minY ) minY = y;
38008				if ( x > maxX ) maxX = x;
38009				if ( y > maxY ) maxY = y;
38010
38011			}
38012
38013			// minX, minY and invSize are later used to transform coords into integers for z-order calculation
38014			invSize = Math.max( maxX - minX, maxY - minY );
38015			invSize = invSize !== 0 ? 32767 / invSize : 0;
38016
38017		}
38018
38019		earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 );
38020
38021		return triangles;
38022
38023	}
38024
38025};
38026
38027// create a circular doubly linked list from polygon points in the specified winding order
38028function linkedList( data, start, end, dim, clockwise ) {
38029
38030	let i, last;
38031
38032	if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
38033
38034		for ( i = start; i < end;
vendor: 10,405 bytes, lines 38034-38507
38034 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
38035
38036	} else {
38037
38038		for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last );
38039
38040	}
38041
38042	if ( last && equals( last, last.next ) ) {
38043
38044		removeNode( last );
38045		last = last.next;
38046
38047	}
38048
38049	return last;
38050
38051}
38052
38053// eliminate colinear or duplicate points
38054function filterPoints( start, end ) {
38055
38056	if ( ! start ) return start;
38057	if ( ! end ) end = start;
38058
38059	let p = start,
38060		again;
38061	do {
38062
38063		again = false;
38064
38065		if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {
38066
38067			removeNode( p );
38068			p = end = p.prev;
38069			if ( p === p.next ) break;
38070			again = true;
38071
38072		} else {
38073
38074			p = p.next;
38075
38076		}
38077
38078	} while ( again || p !== end );
38079
38080	return end;
38081
38082}
38083
38084// main ear slicing loop which triangulates a polygon (given as a linked list)
38085function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
38086
38087	if ( ! ear ) return;
38088
38089	// interlink polygon nodes in z-order
38090	if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
38091
38092	let stop = ear,
38093		prev, next;
38094
38095	// iterate through ears, slicing them one by one
38096	while ( ear.prev !== ear.next ) {
38097
38098		prev = ear.prev;
38099		next = ear.next;
38100
38101		if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
38102
38103			// cut off the triangle
38104			triangles.push( prev.i / dim | 0 );
38105			triangles.push( ear.i / dim | 0 );
38106			triangles.push( next.i / dim | 0 );
38107
38108			removeNode( ear );
38109
38110			// skipping the next vertex leads to less sliver triangles
38111			ear = next.next;
38112			stop = next.next;
38113
38114			continue;
38115
38116		}
38117
38118		ear = next;
38119
38120		// if we looped through the whole remaining polygon and can't find any more ears
38121		if ( ear === stop ) {
38122
38123			// try filtering points and slicing again
38124			if ( ! pass ) {
38125
38126				earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
38127
38128				// if this didn't work, try curing all small self-intersections locally
38129
38130			} else if ( pass === 1 ) {
38131
38132				ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
38133				earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
38134
38135				// as a last resort, try splitting the remaining polygon into two
38136
38137			} else if ( pass === 2 ) {
38138
38139				splitEarcut( ear, triangles, dim, minX, minY, invSize );
38140
38141			}
38142
38143			break;
38144
38145		}
38146
38147	}
38148
38149}
38150
38151// check whether a polygon node forms a valid ear with adjacent nodes
38152function isEar( ear ) {
38153
38154	const a = ear.prev,
38155		b = ear,
38156		c = ear.next;
38157
38158	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
38159
38160	// now make sure we don't have other points inside the potential ear
38161	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
38162
38163	// triangle bbox; min & max are calculated like this for speed
38164	const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
38165		y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
38166		x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
38167		y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
38168
38169	let p = c.next;
38170	while ( p !== a ) {
38171
38172		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
38173			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) &&
38174			area( p.prev, p, p.next ) >= 0 ) return false;
38175		p = p.next;
38176
38177	}
38178
38179	return true;
38180
38181}
38182
38183function isEarHashed( ear, minX, minY, invSize ) {
38184
38185	const a = ear.prev,
38186		b = ear,
38187		c = ear.next;
38188
38189	if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear
38190
38191	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
38192
38193	// triangle bbox; min & max are calculated like this for speed
38194	const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
38195		y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
38196		x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
38197		y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
38198
38199	// z-order range for the current triangle bbox;
38200	const minZ = zOrder( x0, y0, minX, minY, invSize ),
38201		maxZ = zOrder( x1, y1, minX, minY, invSize );
38202
38203	let p = ear.prevZ,
38204		n = ear.nextZ;
38205
38206	// look for points inside the triangle in both directions
38207	while ( p && p.z >= minZ && n && n.z <= maxZ ) {
38208
38209		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
38210			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
38211		p = p.prevZ;
38212
38213		if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
38214			pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
38215		n = n.nextZ;
38216
38217	}
38218
38219	// look for remaining points in decreasing z-order
38220	while ( p && p.z >= minZ ) {
38221
38222		if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
38223			pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false;
38224		p = p.prevZ;
38225
38226	}
38227
38228	// look for remaining points in increasing z-order
38229	while ( n && n.z <= maxZ ) {
38230
38231		if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
38232			pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false;
38233		n = n.nextZ;
38234
38235	}
38236
38237	return true;
38238
38239}
38240
38241// go through all polygon nodes and cure small local self-intersections
38242function cureLocalIntersections( start, triangles, dim ) {
38243
38244	let p = start;
38245	do {
38246
38247		const a = p.prev,
38248			b = p.next.next;
38249
38250		if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {
38251
38252			triangles.push( a.i / dim | 0 );
38253			triangles.push( p.i / dim | 0 );
38254			triangles.push( b.i / dim | 0 );
38255
38256			// remove two nodes involved
38257			removeNode( p );
38258			removeNode( p.next );
38259
38260			p = start = b;
38261
38262		}
38263
38264		p = p.next;
38265
38266	} while ( p !== start );
38267
38268	return filterPoints( p );
38269
38270}
38271
38272// try splitting polygon into two and triangulate them independently
38273function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
38274
38275	// look for a valid diagonal that divides the polygon into two
38276	let a = start;
38277	do {
38278
38279		let b = a.next.next;
38280		while ( b !== a.prev ) {
38281
38282			if ( a.i !== b.i && isValidDiagonal( a, b ) ) {
38283
38284				// split the polygon in two by the diagonal
38285				let c = splitPolygon( a, b );
38286
38287				// filter colinear points around the cuts
38288				a = filterPoints( a, a.next );
38289				c = filterPoints( c, c.next );
38290
38291				// run earcut on each half
38292				earcutLinked( a, triangles, dim, minX, minY, invSize, 0 );
38293				earcutLinked( c, triangles, dim, minX, minY, invSize, 0 );
38294				return;
38295
38296			}
38297
38298			b = b.next;
38299
38300		}
38301
38302		a = a.next;
38303
38304	} while ( a !== start );
38305
38306}
38307
38308// link every hole into the outer loop, producing a single-ring polygon without holes
38309function eliminateHoles( data, holeIndices, outerNode, dim ) {
38310
38311	const queue = [];
38312	let i, len, start, end, list;
38313
38314	for ( i = 0, len = holeIndices.length; i < len; i ++ ) {
38315
38316		start = holeIndices[ i ] * dim;
38317		end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;
38318		list = linkedList( data, start, end, dim, false );
38319		if ( list === list.next ) list.steiner = true;
38320		queue.push( getLeftmost( list ) );
38321
38322	}
38323
38324	queue.sort( compareX );
38325
38326	// process holes from left to right
38327	for ( i = 0; i < queue.length; i ++ ) {
38328
38329		outerNode = eliminateHole( queue[ i ], outerNode );
38330
38331	}
38332
38333	return outerNode;
38334
38335}
38336
38337function compareX( a, b ) {
38338
38339	return a.x - b.x;
38340
38341}
38342
38343// find a bridge between vertices that connects hole with an outer ring and link it
38344function eliminateHole( hole, outerNode ) {
38345
38346	const bridge = findHoleBridge( hole, outerNode );
38347	if ( ! bridge ) {
38348
38349		return outerNode;
38350
38351	}
38352
38353	const bridgeReverse = splitPolygon( bridge, hole );
38354
38355	// filter collinear points around the cuts
38356	filterPoints( bridgeReverse, bridgeReverse.next );
38357	return filterPoints( bridge, bridge.next );
38358
38359}
38360
38361// David Eberly's algorithm for finding a bridge between hole and outer polygon
38362function findHoleBridge( hole, outerNode ) {
38363
38364	let p = outerNode,
38365		qx = - Infinity,
38366		m;
38367
38368	const hx = hole.x, hy = hole.y;
38369
38370	// find a segment intersected by a ray from the hole's leftmost point to the left;
38371	// segment's endpoint with lesser x will be potential connection point
38372	do {
38373
38374		if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {
38375
38376			const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );
38377			if ( x <= hx && x > qx ) {
38378
38379				qx = x;
38380				m = p.x < p.next.x ? p : p.next;
38381				if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint
38382
38383			}
38384
38385		}
38386
38387		p = p.next;
38388
38389	} while ( p !== outerNode );
38390
38391	if ( ! m ) return null;
38392
38393	// look for points inside the triangle of hole point, segment intersection and endpoint;
38394	// if there are no points found, we have a valid connection;
38395	// otherwise choose the point of the minimum angle with the ray as connection point
38396
38397	const stop = m,
38398		mx = m.x,
38399		my = m.y;
38400	let tanMin = Infinity, tan;
38401
38402	p = m;
38403
38404	do {
38405
38406		if ( hx >= p.x && p.x >= mx && hx !== p.x &&
38407				pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {
38408
38409			tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential
38410
38411			if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) {
38412
38413				m = p;
38414				tanMin = tan;
38415
38416			}
38417
38418		}
38419
38420		p = p.next;
38421
38422	} while ( p !== stop );
38423
38424	return m;
38425
38426}
38427
38428// whether sector in vertex m contains sector in vertex p in the same coordinates
38429function sectorContainsSector( m, p ) {
38430
38431	return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0;
38432
38433}
38434
38435// interlink polygon nodes in z-order
38436function indexCurve( start, minX, minY, invSize ) {
38437
38438	let p = start;
38439	do {
38440
38441		if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize );
38442		p.prevZ = p.prev;
38443		p.nextZ = p.next;
38444		p = p.next;
38445
38446	} while ( p !== start );
38447
38448	p.prevZ.nextZ = null;
38449	p.prevZ = null;
38450
38451	sortLinked( p );
38452
38453}
38454
38455// Simon Tatham's linked list merge sort algorithm
38456// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
38457function sortLinked( list ) {
38458
38459	let i, p, q, e, tail, numMerges, pSize, qSize,
38460		inSize = 1;
38461
38462	do {
38463
38464		p = list;
38465		list = null;
38466		tail = null;
38467		numMerges = 0;
38468
38469		while ( p ) {
38470
38471			numMerges ++;
38472			q = p;
38473			pSize = 0;
38474			for ( i = 0; i < inSize; i ++ ) {
38475
38476				pSize ++;
38477				q = q.nextZ;
38478				if ( ! q ) break;
38479
38480			}
38481
38482			qSize = inSize;
38483
38484			while ( pSize > 0 || ( qSize > 0 && q ) ) {
38485
38486				if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {
38487
38488					e = p;
38489					p = p.nextZ;
38490					pSize --;
38491
38492				} else {
38493
38494					e = q;
38495					q = q.nextZ;
38496					qSize --;
38497
38498				}
38499
38500				if ( tail ) tail.nextZ = e;
38501				else list = e;
38502
38503				e.prevZ = tail;
38504				tail = e;
38505
38506			}
38507
vendor: 9,707 bytes, lines 38508-38935
38508			p = q;
38509
38510		}
38511
38512		tail.nextZ = null;
38513		inSize *= 2;
38514
38515	} while ( numMerges > 1 );
38516
38517	return list;
38518
38519}
38520
38521// z-order of a point given coords and inverse of the longer side of data bbox
38522function zOrder( x, y, minX, minY, invSize ) {
38523
38524	// coords are transformed into non-negative 15-bit integer range
38525	x = ( x - minX ) * invSize | 0;
38526	y = ( y - minY ) * invSize | 0;
38527
38528	x = ( x | ( x << 8 ) ) & 0x00FF00FF;
38529	x = ( x | ( x << 4 ) ) & 0x0F0F0F0F;
38530	x = ( x | ( x << 2 ) ) & 0x33333333;
38531	x = ( x | ( x << 1 ) ) & 0x55555555;
38532
38533	y = ( y | ( y << 8 ) ) & 0x00FF00FF;
38534	y = ( y | ( y << 4 ) ) & 0x0F0F0F0F;
38535	y = ( y | ( y << 2 ) ) & 0x33333333;
38536	y = ( y | ( y << 1 ) ) & 0x55555555;
38537
38538	return x | ( y << 1 );
38539
38540}
38541
38542// find the leftmost node of a polygon ring
38543function getLeftmost( start ) {
38544
38545	let p = start,
38546		leftmost = start;
38547	do {
38548
38549		if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p;
38550		p = p.next;
38551
38552	} while ( p !== start );
38553
38554	return leftmost;
38555
38556}
38557
38558// check if a point lies within a convex triangle
38559function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
38560
38561	return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) &&
38562           ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) &&
38563           ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py );
38564
38565}
38566
38567// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
38568function isValidDiagonal( a, b ) {
38569
38570	return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges
38571           ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible
38572            ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors
38573            equals( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case
38574
38575}
38576
38577// signed area of a triangle
38578function area( p, q, r ) {
38579
38580	return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );
38581
38582}
38583
38584// check if two points are equal
38585function equals( p1, p2 ) {
38586
38587	return p1.x === p2.x && p1.y === p2.y;
38588
38589}
38590
38591// check if two segments intersect
38592function intersects( p1, q1, p2, q2 ) {
38593
38594	const o1 = sign( area( p1, q1, p2 ) );
38595	const o2 = sign( area( p1, q1, q2 ) );
38596	const o3 = sign( area( p2, q2, p1 ) );
38597	const o4 = sign( area( p2, q2, q1 ) );
38598
38599	if ( o1 !== o2 && o3 !== o4 ) return true; // general case
38600
38601	if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
38602	if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
38603	if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
38604	if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
38605
38606	return false;
38607
38608}
38609
38610// for collinear points p, q, r, check if point q lies on segment pr
38611function onSegment( p, q, r ) {
38612
38613	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 );
38614
38615}
38616
38617function sign( num ) {
38618
38619	return num > 0 ? 1 : num < 0 ? - 1 : 0;
38620
38621}
38622
38623// check if a polygon diagonal intersects any polygon segments
38624function intersectsPolygon( a, b ) {
38625
38626	let p = a;
38627	do {
38628
38629		if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
38630			intersects( p, p.next, a, b ) ) return true;
38631		p = p.next;
38632
38633	} while ( p !== a );
38634
38635	return false;
38636
38637}
38638
38639// check if a polygon diagonal is locally inside the polygon
38640function locallyInside( a, b ) {
38641
38642	return area( a.prev, a, a.next ) < 0 ?
38643		area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :
38644		area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;
38645
38646}
38647
38648// check if the middle point of a polygon diagonal is inside the polygon
38649function middleInside( a, b ) {
38650
38651	let p = a,
38652		inside = false;
38653	const px = ( a.x + b.x ) / 2,
38654		py = ( a.y + b.y ) / 2;
38655	do {
38656
38657		if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&
38658			( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )
38659			inside = ! inside;
38660		p = p.next;
38661
38662	} while ( p !== a );
38663
38664	return inside;
38665
38666}
38667
38668// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
38669// if one belongs to the outer ring and another to a hole, it merges it into a single ring
38670function splitPolygon( a, b ) {
38671
38672	const a2 = new Node( a.i, a.x, a.y ),
38673		b2 = new Node( b.i, b.x, b.y ),
38674		an = a.next,
38675		bp = b.prev;
38676
38677	a.next = b;
38678	b.prev = a;
38679
38680	a2.next = an;
38681	an.prev = a2;
38682
38683	b2.next = a2;
38684	a2.prev = b2;
38685
38686	bp.next = b2;
38687	b2.prev = bp;
38688
38689	return b2;
38690
38691}
38692
38693// create a node and optionally link it with previous one (in a circular doubly linked list)
38694function insertNode( i, x, y, last ) {
38695
38696	const p = new Node( i, x, y );
38697
38698	if ( ! last ) {
38699
38700		p.prev = p;
38701		p.next = p;
38702
38703	} else {
38704
38705		p.next = last.next;
38706		p.prev = last;
38707		last.next.prev = p;
38708		last.next = p;
38709
38710	}
38711
38712	return p;
38713
38714}
38715
38716function removeNode( p ) {
38717
38718	p.next.prev = p.prev;
38719	p.prev.next = p.next;
38720
38721	if ( p.prevZ ) p.prevZ.nextZ = p.nextZ;
38722	if ( p.nextZ ) p.nextZ.prevZ = p.prevZ;
38723
38724}
38725
38726function Node( i, x, y ) {
38727
38728	// vertex index in coordinates array
38729	this.i = i;
38730
38731	// vertex coordinates
38732	this.x = x;
38733	this.y = y;
38734
38735	// previous and next vertex nodes in a polygon ring
38736	this.prev = null;
38737	this.next = null;
38738
38739	// z-order curve value
38740	this.z = 0;
38741
38742	// previous and next nodes in z-order
38743	this.prevZ = null;
38744	this.nextZ = null;
38745
38746	// indicates whether this is a steiner point
38747	this.steiner = false;
38748
38749}
38750
38751function signedArea( data, start, end, dim ) {
38752
38753	let sum = 0;
38754	for ( let i = start, j = end - dim; i < end; i += dim ) {
38755
38756		sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );
38757		j = i;
38758
38759	}
38760
38761	return sum;
38762
38763}
38764
38765class ShapeUtils {
38766
38767	// calculate area of the contour polygon
38768
38769	static area( contour ) {
38770
38771		const n = contour.length;
38772		let a = 0.0;
38773
38774		for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
38775
38776			a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
38777
38778		}
38779
38780		return a * 0.5;
38781
38782	}
38783
38784	static isClockWise( pts ) {
38785
38786		return ShapeUtils.area( pts ) < 0;
38787
38788	}
38789
38790	static triangulateShape( contour, holes ) {
38791
38792		const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
38793		const holeIndices = []; // array of hole indices
38794		const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
38795
38796		removeDupEndPts( contour );
38797		addContour( vertices, contour );
38798
38799		//
38800
38801		let holeIndex = contour.length;
38802
38803		holes.forEach( removeDupEndPts );
38804
38805		for ( let i = 0; i < holes.length; i ++ ) {
38806
38807			holeIndices.push( holeIndex );
38808			holeIndex += holes[ i ].length;
38809			addContour( vertices, holes[ i ] );
38810
38811		}
38812
38813		//
38814
38815		const triangles = Earcut.triangulate( vertices, holeIndices );
38816
38817		//
38818
38819		for ( let i = 0; i < triangles.length; i += 3 ) {
38820
38821			faces.push( triangles.slice( i, i + 3 ) );
38822
38823		}
38824
38825		return faces;
38826
38827	}
38828
38829}
38830
38831function removeDupEndPts( points ) {
38832
38833	const l = points.length;
38834
38835	if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
38836
38837		points.pop();
38838
38839	}
38840
38841}
38842
38843function addContour( vertices, contour ) {
38844
38845	for ( let i = 0; i < contour.length; i ++ ) {
38846
38847		vertices.push( contour[ i ].x );
38848		vertices.push( contour[ i ].y );
38849
38850	}
38851
38852}
38853
38854/**
38855 * Creates extruded geometry from a path shape.
38856 *
38857 * parameters = {
38858 *
38859 *  curveSegments: <int>, // number of points on the curves
38860 *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
38861 *  depth: <float>, // Depth to extrude the shape
38862 *
38863 *  bevelEnabled: <bool>, // turn on bevel
38864 *  bevelThickness: <float>, // how deep into the original shape bevel goes
38865 *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
38866 *  bevelOffset: <float>, // how far from shape outline does bevel start
38867 *  bevelSegments: <int>, // number of bevel layers
38868 *
38869 *  extrudePath: <THREE.Curve> // curve to extrude shape along
38870 *
38871 *  UVGenerator: <Object> // object that provides UV generator functions
38872 *
38873 * }
38874 */
38875
38876
38877class ExtrudeGeometry extends BufferGeometry {
38878
38879	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 = {} ) {
38880
38881		super();
38882
38883		this.type = 'ExtrudeGeometry';
38884
38885		this.parameters = {
38886			shapes: shapes,
38887			options: options
38888		};
38889
38890		shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
38891
38892		const scope = this;
38893
38894		const verticesArray = [];
38895		const uvArray = [];
38896
38897		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
38898
38899			const shape = shapes[ i ];
38900			addShape( shape );
38901
38902		}
38903
38904		// build geometry
38905
38906		this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
38907		this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
38908
38909		this.computeVertexNormals();
38910
38911		// functions
38912
38913		function addShape( shape ) {
38914
38915			const placeholder = [];
38916
38917			// options
38918
38919			const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
38920			const steps = options.steps !== undefined ? options.steps : 1;
38921			const depth = options.depth !== undefined ? options.depth : 1;
38922
38923			let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
38924			let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
38925			let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
38926			let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
38927			let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
38928
38929			const extrudePath = options.extrudePath;
38930
38931			const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
38932
38933			//
38934
38935			let extrudePts, extrudeByPath = false;
vendor: 2,791 bytes, lines 38936-39049
38936			let splineTube, binormal, normal, position2;
38937
38938			if ( extrudePath ) {
38939
38940				extrudePts = extrudePath.getSpacedPoints( steps );
38941
38942				extrudeByPath = true;
38943				bevelEnabled = false; // bevels not supported for path extrusion
38944
38945				// SETUP TNB variables
38946
38947				// TODO1 - have a .isClosed in spline?
38948
38949				splineTube = extrudePath.computeFrenetFrames( steps, false );
38950
38951				// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
38952
38953				binormal = new Vector3();
38954				normal = new Vector3();
38955				position2 = new Vector3();
38956
38957			}
38958
38959			// Safeguards if bevels are not enabled
38960
38961			if ( ! bevelEnabled ) {
38962
38963				bevelSegments = 0;
38964				bevelThickness = 0;
38965				bevelSize = 0;
38966				bevelOffset = 0;
38967
38968			}
38969
38970			// Variables initialization
38971
38972			const shapePoints = shape.extractPoints( curveSegments );
38973
38974			let vertices = shapePoints.shape;
38975			const holes = shapePoints.holes;
38976
38977			const reverse = ! ShapeUtils.isClockWise( vertices );
38978
38979			if ( reverse ) {
38980
38981				vertices = vertices.reverse();
38982
38983				// Maybe we should also check if holes are in the opposite direction, just to be safe ...
38984
38985				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
38986
38987					const ahole = holes[ h ];
38988
38989					if ( ShapeUtils.isClockWise( ahole ) ) {
38990
38991						holes[ h ] = ahole.reverse();
38992
38993					}
38994
38995				}
38996
38997			}
38998
38999
39000			const faces = ShapeUtils.triangulateShape( vertices, holes );
39001
39002			/* Vertices */
39003
39004			const contour = vertices; // vertices has all points but contour has only points of circumference
39005
39006			for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
39007
39008				const ahole = holes[ h ];
39009
39010				vertices = vertices.concat( ahole );
39011
39012			}
39013
39014
39015			function scalePt2( pt, vec, size ) {
39016
39017				if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' );
39018
39019				return pt.clone().addScaledVector( vec, size );
39020
39021			}
39022
39023			const vlen = vertices.length, flen = faces.length;
39024
39025
39026			// Find directions for point movement
39027
39028
39029			function getBevelVec( inPt, inPrev, inNext ) {
39030
39031				// computes for inPt the corresponding point inPt' on a new contour
39032				//   shifted by 1 unit (length of normalized vector) to the left
39033				// if we walk along contour clockwise, this new contour is outside the old one
39034				//
39035				// inPt' is the intersection of the two lines parallel to the two
39036				//  adjacent edges of inPt at a distance of 1 unit on the left side.
39037
39038				let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
39039
39040				// good reading for geometry algorithms (here: line-line intersection)
39041				// http://geomalgorithms.com/a05-_intersect-1.html
39042
39043				const v_prev_x = inPt.x - inPrev.x,
39044					v_prev_y = inPt.y - inPrev.y;
39045				const v_next_x = inNext.x - inPt.x,
39046					v_next_y = inNext.y - inPt.y;
39047
39048				const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
39049
vendor: 17,452 bytes, lines 39050-39901
39050				// check for collinear edges
39051				const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
39052
39053				if ( Math.abs( collinear0 ) > Number.EPSILON ) {
39054
39055					// not collinear
39056
39057					// length of vectors for normalizing
39058
39059					const v_prev_len = Math.sqrt( v_prev_lensq );
39060					const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
39061
39062					// shift adjacent points by unit vectors to the left
39063
39064					const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
39065					const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
39066
39067					const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
39068					const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
39069
39070					// scaling factor for v_prev to intersection point
39071
39072					const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
39073							( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
39074						( v_prev_x * v_next_y - v_prev_y * v_next_x );
39075
39076					// vector from inPt to intersection point
39077
39078					v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
39079					v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
39080
39081					// Don't normalize!, otherwise sharp corners become ugly
39082					//  but prevent crazy spikes
39083					const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
39084					if ( v_trans_lensq <= 2 ) {
39085
39086						return new Vector2( v_trans_x, v_trans_y );
39087
39088					} else {
39089
39090						shrink_by = Math.sqrt( v_trans_lensq / 2 );
39091
39092					}
39093
39094				} else {
39095
39096					// handle special case of collinear edges
39097
39098					let direction_eq = false; // assumes: opposite
39099
39100					if ( v_prev_x > Number.EPSILON ) {
39101
39102						if ( v_next_x > Number.EPSILON ) {
39103
39104							direction_eq = true;
39105
39106						}
39107
39108					} else {
39109
39110						if ( v_prev_x < - Number.EPSILON ) {
39111
39112							if ( v_next_x < - Number.EPSILON ) {
39113
39114								direction_eq = true;
39115
39116							}
39117
39118						} else {
39119
39120							if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
39121
39122								direction_eq = true;
39123
39124							}
39125
39126						}
39127
39128					}
39129
39130					if ( direction_eq ) {
39131
39132						// console.log("Warning: lines are a straight sequence");
39133						v_trans_x = - v_prev_y;
39134						v_trans_y = v_prev_x;
39135						shrink_by = Math.sqrt( v_prev_lensq );
39136
39137					} else {
39138
39139						// console.log("Warning: lines are a straight spike");
39140						v_trans_x = v_prev_x;
39141						v_trans_y = v_prev_y;
39142						shrink_by = Math.sqrt( v_prev_lensq / 2 );
39143
39144					}
39145
39146				}
39147
39148				return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
39149
39150			}
39151
39152
39153			const contourMovements = [];
39154
39155			for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
39156
39157				if ( j === il ) j = 0;
39158				if ( k === il ) k = 0;
39159
39160				//  (j)---(i)---(k)
39161				// console.log('i,j,k', i, j , k)
39162
39163				contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
39164
39165			}
39166
39167			const holesMovements = [];
39168			let oneHoleMovements, verticesMovements = contourMovements.concat();
39169
39170			for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
39171
39172				const ahole = holes[ h ];
39173
39174				oneHoleMovements = [];
39175
39176				for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
39177
39178					if ( j === il ) j = 0;
39179					if ( k === il ) k = 0;
39180
39181					//  (j)---(i)---(k)
39182					oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
39183
39184				}
39185
39186				holesMovements.push( oneHoleMovements );
39187				verticesMovements = verticesMovements.concat( oneHoleMovements );
39188
39189			}
39190
39191
39192			// Loop bevelSegments, 1 for the front, 1 for the back
39193
39194			for ( let b = 0; b < bevelSegments; b ++ ) {
39195
39196				//for ( b = bevelSegments; b > 0; b -- ) {
39197
39198				const t = b / bevelSegments;
39199				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
39200				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
39201
39202				// contract shape
39203
39204				for ( let i = 0, il = contour.length; i < il; i ++ ) {
39205
39206					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
39207
39208					v( vert.x, vert.y, - z );
39209
39210				}
39211
39212				// expand holes
39213
39214				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
39215
39216					const ahole = holes[ h ];
39217					oneHoleMovements = holesMovements[ h ];
39218
39219					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
39220
39221						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
39222
39223						v( vert.x, vert.y, - z );
39224
39225					}
39226
39227				}
39228
39229			}
39230
39231			const bs = bevelSize + bevelOffset;
39232
39233			// Back facing vertices
39234
39235			for ( let i = 0; i < vlen; i ++ ) {
39236
39237				const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
39238
39239				if ( ! extrudeByPath ) {
39240
39241					v( vert.x, vert.y, 0 );
39242
39243				} else {
39244
39245					// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
39246
39247					normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
39248					binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
39249
39250					position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
39251
39252					v( position2.x, position2.y, position2.z );
39253
39254				}
39255
39256			}
39257
39258			// Add stepped vertices...
39259			// Including front facing vertices
39260
39261			for ( let s = 1; s <= steps; s ++ ) {
39262
39263				for ( let i = 0; i < vlen; i ++ ) {
39264
39265					const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
39266
39267					if ( ! extrudeByPath ) {
39268
39269						v( vert.x, vert.y, depth / steps * s );
39270
39271					} else {
39272
39273						// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
39274
39275						normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
39276						binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
39277
39278						position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
39279
39280						v( position2.x, position2.y, position2.z );
39281
39282					}
39283
39284				}
39285
39286			}
39287
39288
39289			// Add bevel segments planes
39290
39291			//for ( b = 1; b <= bevelSegments; b ++ ) {
39292			for ( let b = bevelSegments - 1; b >= 0; b -- ) {
39293
39294				const t = b / bevelSegments;
39295				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
39296				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
39297
39298				// contract shape
39299
39300				for ( let i = 0, il = contour.length; i < il; i ++ ) {
39301
39302					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
39303					v( vert.x, vert.y, depth + z );
39304
39305				}
39306
39307				// expand holes
39308
39309				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
39310
39311					const ahole = holes[ h ];
39312					oneHoleMovements = holesMovements[ h ];
39313
39314					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
39315
39316						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
39317
39318						if ( ! extrudeByPath ) {
39319
39320							v( vert.x, vert.y, depth + z );
39321
39322						} else {
39323
39324							v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
39325
39326						}
39327
39328					}
39329
39330				}
39331
39332			}
39333
39334			/* Faces */
39335
39336			// Top and bottom faces
39337
39338			buildLidFaces();
39339
39340			// Sides faces
39341
39342			buildSideFaces();
39343
39344
39345			/////  Internal functions
39346
39347			function buildLidFaces() {
39348
39349				const start = verticesArray.length / 3;
39350
39351				if ( bevelEnabled ) {
39352
39353					let layer = 0; // steps + 1
39354					let offset = vlen * layer;
39355
39356					// Bottom faces
39357
39358					for ( let i = 0; i < flen; i ++ ) {
39359
39360						const face = faces[ i ];
39361						f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
39362
39363					}
39364
39365					layer = steps + bevelSegments * 2;
39366					offset = vlen * layer;
39367
39368					// Top faces
39369
39370					for ( let i = 0; i < flen; i ++ ) {
39371
39372						const face = faces[ i ];
39373						f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
39374
39375					}
39376
39377				} else {
39378
39379					// Bottom faces
39380
39381					for ( let i = 0; i < flen; i ++ ) {
39382
39383						const face = faces[ i ];
39384						f3( face[ 2 ], face[ 1 ], face[ 0 ] );
39385
39386					}
39387
39388					// Top faces
39389
39390					for ( let i = 0; i < flen; i ++ ) {
39391
39392						const face = faces[ i ];
39393						f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
39394
39395					}
39396
39397				}
39398
39399				scope.addGroup( start, verticesArray.length / 3 - start, 0 );
39400
39401			}
39402
39403			// Create faces for the z-sides of the shape
39404
39405			function buildSideFaces() {
39406
39407				const start = verticesArray.length / 3;
39408				let layeroffset = 0;
39409				sidewalls( contour, layeroffset );
39410				layeroffset += contour.length;
39411
39412				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
39413
39414					const ahole = holes[ h ];
39415					sidewalls( ahole, layeroffset );
39416
39417					//, true
39418					layeroffset += ahole.length;
39419
39420				}
39421
39422
39423				scope.addGroup( start, verticesArray.length / 3 - start, 1 );
39424
39425
39426			}
39427
39428			function sidewalls( contour, layeroffset ) {
39429
39430				let i = contour.length;
39431
39432				while ( -- i >= 0 ) {
39433
39434					const j = i;
39435					let k = i - 1;
39436					if ( k < 0 ) k = contour.length - 1;
39437
39438					//console.log('b', i,j, i-1, k,vertices.length);
39439
39440					for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
39441
39442						const slen1 = vlen * s;
39443						const slen2 = vlen * ( s + 1 );
39444
39445						const a = layeroffset + j + slen1,
39446							b = layeroffset + k + slen1,
39447							c = layeroffset + k + slen2,
39448							d = layeroffset + j + slen2;
39449
39450						f4( a, b, c, d );
39451
39452					}
39453
39454				}
39455
39456			}
39457
39458			function v( x, y, z ) {
39459
39460				placeholder.push( x );
39461				placeholder.push( y );
39462				placeholder.push( z );
39463
39464			}
39465
39466
39467			function f3( a, b, c ) {
39468
39469				addVertex( a );
39470				addVertex( b );
39471				addVertex( c );
39472
39473				const nextIndex = verticesArray.length / 3;
39474				const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
39475
39476				addUV( uvs[ 0 ] );
39477				addUV( uvs[ 1 ] );
39478				addUV( uvs[ 2 ] );
39479
39480			}
39481
39482			function f4( a, b, c, d ) {
39483
39484				addVertex( a );
39485				addVertex( b );
39486				addVertex( d );
39487
39488				addVertex( b );
39489				addVertex( c );
39490				addVertex( d );
39491
39492
39493				const nextIndex = verticesArray.length / 3;
39494				const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
39495
39496				addUV( uvs[ 0 ] );
39497				addUV( uvs[ 1 ] );
39498				addUV( uvs[ 3 ] );
39499
39500				addUV( uvs[ 1 ] );
39501				addUV( uvs[ 2 ] );
39502				addUV( uvs[ 3 ] );
39503
39504			}
39505
39506			function addVertex( index ) {
39507
39508				verticesArray.push( placeholder[ index * 3 + 0 ] );
39509				verticesArray.push( placeholder[ index * 3 + 1 ] );
39510				verticesArray.push( placeholder[ index * 3 + 2 ] );
39511
39512			}
39513
39514
39515			function addUV( vector2 ) {
39516
39517				uvArray.push( vector2.x );
39518				uvArray.push( vector2.y );
39519
39520			}
39521
39522		}
39523
39524	}
39525
39526	copy( source ) {
39527
39528		super.copy( source );
39529
39530		this.parameters = Object.assign( {}, source.parameters );
39531
39532		return this;
39533
39534	}
39535
39536	toJSON() {
39537
39538		const data = super.toJSON();
39539
39540		const shapes = this.parameters.shapes;
39541		const options = this.parameters.options;
39542
39543		return toJSON$1( shapes, options, data );
39544
39545	}
39546
39547	static fromJSON( data, shapes ) {
39548
39549		const geometryShapes = [];
39550
39551		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
39552
39553			const shape = shapes[ data.shapes[ j ] ];
39554
39555			geometryShapes.push( shape );
39556
39557		}
39558
39559		const extrudePath = data.options.extrudePath;
39560
39561		if ( extrudePath !== undefined ) {
39562
39563			data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
39564
39565		}
39566
39567		return new ExtrudeGeometry( geometryShapes, data.options );
39568
39569	}
39570
39571}
39572
39573const WorldUVGenerator = {
39574
39575	generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
39576
39577		const a_x = vertices[ indexA * 3 ];
39578		const a_y = vertices[ indexA * 3 + 1 ];
39579		const b_x = vertices[ indexB * 3 ];
39580		const b_y = vertices[ indexB * 3 + 1 ];
39581		const c_x = vertices[ indexC * 3 ];
39582		const c_y = vertices[ indexC * 3 + 1 ];
39583
39584		return [
39585			new Vector2( a_x, a_y ),
39586			new Vector2( b_x, b_y ),
39587			new Vector2( c_x, c_y )
39588		];
39589
39590	},
39591
39592	generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
39593
39594		const a_x = vertices[ indexA * 3 ];
39595		const a_y = vertices[ indexA * 3 + 1 ];
39596		const a_z = vertices[ indexA * 3 + 2 ];
39597		const b_x = vertices[ indexB * 3 ];
39598		const b_y = vertices[ indexB * 3 + 1 ];
39599		const b_z = vertices[ indexB * 3 + 2 ];
39600		const c_x = vertices[ indexC * 3 ];
39601		const c_y = vertices[ indexC * 3 + 1 ];
39602		const c_z = vertices[ indexC * 3 + 2 ];
39603		const d_x = vertices[ indexD * 3 ];
39604		const d_y = vertices[ indexD * 3 + 1 ];
39605		const d_z = vertices[ indexD * 3 + 2 ];
39606
39607		if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) {
39608
39609			return [
39610				new Vector2( a_x, 1 - a_z ),
39611				new Vector2( b_x, 1 - b_z ),
39612				new Vector2( c_x, 1 - c_z ),
39613				new Vector2( d_x, 1 - d_z )
39614			];
39615
39616		} else {
39617
39618			return [
39619				new Vector2( a_y, 1 - a_z ),
39620				new Vector2( b_y, 1 - b_z ),
39621				new Vector2( c_y, 1 - c_z ),
39622				new Vector2( d_y, 1 - d_z )
39623			];
39624
39625		}
39626
39627	}
39628
39629};
39630
39631function toJSON$1( shapes, options, data ) {
39632
39633	data.shapes = [];
39634
39635	if ( Array.isArray( shapes ) ) {
39636
39637		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
39638
39639			const shape = shapes[ i ];
39640
39641			data.shapes.push( shape.uuid );
39642
39643		}
39644
39645	} else {
39646
39647		data.shapes.push( shapes.uuid );
39648
39649	}
39650
39651	data.options = Object.assign( {}, options );
39652
39653	if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
39654
39655	return data;
39656
39657}
39658
39659class IcosahedronGeometry extends PolyhedronGeometry {
39660
39661	constructor( radius = 1, detail = 0 ) {
39662
39663		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
39664
39665		const vertices = [
39666			- 1, t, 0, 	1, t, 0, 	- 1, - t, 0, 	1, - t, 0,
39667			0, - 1, t, 	0, 1, t,	0, - 1, - t, 	0, 1, - t,
39668			t, 0, - 1, 	t, 0, 1, 	- t, 0, - 1, 	- t, 0, 1
39669		];
39670
39671		const indices = [
39672			0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
39673			1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
39674			3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
39675			4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
39676		];
39677
39678		super( vertices, indices, radius, detail );
39679
39680		this.type = 'IcosahedronGeometry';
39681
39682		this.parameters = {
39683			radius: radius,
39684			detail: detail
39685		};
39686
39687	}
39688
39689	static fromJSON( data ) {
39690
39691		return new IcosahedronGeometry( data.radius, data.detail );
39692
39693	}
39694
39695}
39696
39697class OctahedronGeometry extends PolyhedronGeometry {
39698
39699	constructor( radius = 1, detail = 0 ) {
39700
39701		const vertices = [
39702			1, 0, 0, 	- 1, 0, 0,	0, 1, 0,
39703			0, - 1, 0, 	0, 0, 1,	0, 0, - 1
39704		];
39705
39706		const indices = [
39707			0, 2, 4,	0, 4, 3,	0, 3, 5,
39708			0, 5, 2,	1, 2, 5,	1, 5, 3,
39709			1, 3, 4,	1, 4, 2
39710		];
39711
39712		super( vertices, indices, radius, detail );
39713
39714		this.type = 'OctahedronGeometry';
39715
39716		this.parameters = {
39717			radius: radius,
39718			detail: detail
39719		};
39720
39721	}
39722
39723	static fromJSON( data ) {
39724
39725		return new OctahedronGeometry( data.radius, data.detail );
39726
39727	}
39728
39729}
39730
39731class RingGeometry extends BufferGeometry {
39732
39733	constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
39734
39735		super();
39736
39737		this.type = 'RingGeometry';
39738
39739		this.parameters = {
39740			innerRadius: innerRadius,
39741			outerRadius: outerRadius,
39742			thetaSegments: thetaSegments,
39743			phiSegments: phiSegments,
39744			thetaStart: thetaStart,
39745			thetaLength: thetaLength
39746		};
39747
39748		thetaSegments = Math.max( 3, thetaSegments );
39749		phiSegments = Math.max( 1, phiSegments );
39750
39751		// buffers
39752
39753		const indices = [];
39754		const vertices = [];
39755		const normals = [];
39756		const uvs = [];
39757
39758		// some helper variables
39759
39760		let radius = innerRadius;
39761		const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
39762		const vertex = new Vector3();
39763		const uv = new Vector2();
39764
39765		// generate vertices, normals and uvs
39766
39767		for ( let j = 0; j <= phiSegments; j ++ ) {
39768
39769			for ( let i = 0; i <= thetaSegments; i ++ ) {
39770
39771				// values are generate from the inside of the ring to the outside
39772
39773				const segment = thetaStart + i / thetaSegments * thetaLength;
39774
39775				// vertex
39776
39777				vertex.x = radius * Math.cos( segment );
39778				vertex.y = radius * Math.sin( segment );
39779
39780				vertices.push( vertex.x, vertex.y, vertex.z );
39781
39782				// normal
39783
39784				normals.push( 0, 0, 1 );
39785
39786				// uv
39787
39788				uv.x = ( vertex.x / outerRadius + 1 ) / 2;
39789				uv.y = ( vertex.y / outerRadius + 1 ) / 2;
39790
39791				uvs.push( uv.x, uv.y );
39792
39793			}
39794
39795			// increase the radius for next row of vertices
39796
39797			radius += radiusStep;
39798
39799		}
39800
39801		// indices
39802
39803		for ( let j = 0; j < phiSegments; j ++ ) {
39804
39805			const thetaSegmentLevel = j * ( thetaSegments + 1 );
39806
39807			for ( let i = 0; i < thetaSegments; i ++ ) {
39808
39809				const segment = i + thetaSegmentLevel;
39810
39811				const a = segment;
39812				const b = segment + thetaSegments + 1;
39813				const c = segment + thetaSegments + 2;
39814				const d = segment + 1;
39815
39816				// faces
39817
39818				indices.push( a, b, d );
39819				indices.push( b, c, d );
39820
39821			}
39822
39823		}
39824
39825		// build geometry
39826
39827		this.setIndex( indices );
39828		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
39829		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39830		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39831
39832	}
39833
39834	copy( source ) {
39835
39836		super.copy( source );
39837
39838		this.parameters = Object.assign( {}, source.parameters );
39839
39840		return this;
39841
39842	}
39843
39844	static fromJSON( data ) {
39845
39846		return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength );
39847
39848	}
39849
39850}
39851
39852class ShapeGeometry extends BufferGeometry {
39853
39854	constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) {
39855
39856		super();
39857
39858		this.type = 'ShapeGeometry';
39859
39860		this.parameters = {
39861			shapes: shapes,
39862			curveSegments: curveSegments
39863		};
39864
39865		// buffers
39866
39867		const indices = [];
39868		const vertices = [];
39869		const normals = [];
39870		const uvs = [];
39871
39872		// helper variables
39873
39874		let groupStart = 0;
39875		let groupCount = 0;
39876
39877		// allow single and array values for "shapes" parameter
39878
39879		if ( Array.isArray( shapes ) === false ) {
39880
39881			addShape( shapes );
39882
39883		} else {
39884
39885			for ( let i = 0; i < shapes.length; i ++ ) {
39886
39887				addShape( shapes[ i ] );
39888
39889				this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
39890
39891				groupStart += groupCount;
39892				groupCount = 0;
39893
39894			}
39895
39896		}
39897
39898		// build geometry
39899
39900		this.setIndex( indices );
39901		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 4,878 bytes, lines 39902-40148
39902		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
39903		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
39904
39905
39906		// helper functions
39907
39908		function addShape( shape ) {
39909
39910			const indexOffset = vertices.length / 3;
39911			const points = shape.extractPoints( curveSegments );
39912
39913			let shapeVertices = points.shape;
39914			const shapeHoles = points.holes;
39915
39916			// check direction of vertices
39917
39918			if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
39919
39920				shapeVertices = shapeVertices.reverse();
39921
39922			}
39923
39924			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
39925
39926				const shapeHole = shapeHoles[ i ];
39927
39928				if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
39929
39930					shapeHoles[ i ] = shapeHole.reverse();
39931
39932				}
39933
39934			}
39935
39936			const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
39937
39938			// join vertices of inner and outer paths to a single array
39939
39940			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
39941
39942				const shapeHole = shapeHoles[ i ];
39943				shapeVertices = shapeVertices.concat( shapeHole );
39944
39945			}
39946
39947			// vertices, normals, uvs
39948
39949			for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
39950
39951				const vertex = shapeVertices[ i ];
39952
39953				vertices.push( vertex.x, vertex.y, 0 );
39954				normals.push( 0, 0, 1 );
39955				uvs.push( vertex.x, vertex.y ); // world uvs
39956
39957			}
39958
39959			// indices
39960
39961			for ( let i = 0, l = faces.length; i < l; i ++ ) {
39962
39963				const face = faces[ i ];
39964
39965				const a = face[ 0 ] + indexOffset;
39966				const b = face[ 1 ] + indexOffset;
39967				const c = face[ 2 ] + indexOffset;
39968
39969				indices.push( a, b, c );
39970				groupCount += 3;
39971
39972			}
39973
39974		}
39975
39976	}
39977
39978	copy( source ) {
39979
39980		super.copy( source );
39981
39982		this.parameters = Object.assign( {}, source.parameters );
39983
39984		return this;
39985
39986	}
39987
39988	toJSON() {
39989
39990		const data = super.toJSON();
39991
39992		const shapes = this.parameters.shapes;
39993
39994		return toJSON( shapes, data );
39995
39996	}
39997
39998	static fromJSON( data, shapes ) {
39999
40000		const geometryShapes = [];
40001
40002		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
40003
40004			const shape = shapes[ data.shapes[ j ] ];
40005
40006			geometryShapes.push( shape );
40007
40008		}
40009
40010		return new ShapeGeometry( geometryShapes, data.curveSegments );
40011
40012	}
40013
40014}
40015
40016function toJSON( shapes, data ) {
40017
40018	data.shapes = [];
40019
40020	if ( Array.isArray( shapes ) ) {
40021
40022		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
40023
40024			const shape = shapes[ i ];
40025
40026			data.shapes.push( shape.uuid );
40027
40028		}
40029
40030	} else {
40031
40032		data.shapes.push( shapes.uuid );
40033
40034	}
40035
40036	return data;
40037
40038}
40039
40040class SphereGeometry extends BufferGeometry {
40041
40042	constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
40043
40044		super();
40045
40046		this.type = 'SphereGeometry';
40047
40048		this.parameters = {
40049			radius: radius,
40050			widthSegments: widthSegments,
40051			heightSegments: heightSegments,
40052			phiStart: phiStart,
40053			phiLength: phiLength,
40054			thetaStart: thetaStart,
40055			thetaLength: thetaLength
40056		};
40057
40058		widthSegments = Math.max( 3, Math.floor( widthSegments ) );
40059		heightSegments = Math.max( 2, Math.floor( heightSegments ) );
40060
40061		const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
40062
40063		let index = 0;
40064		const grid = [];
40065
40066		const vertex = new Vector3();
40067		const normal = new Vector3();
40068
40069		// buffers
40070
40071		const indices = [];
40072		const vertices = [];
40073		const normals = [];
40074		const uvs = [];
40075
40076		// generate vertices, normals and uvs
40077
40078		for ( let iy = 0; iy <= heightSegments; iy ++ ) {
40079
40080			const verticesRow = [];
40081
40082			const v = iy / heightSegments;
40083
40084			// special case for the poles
40085
40086			let uOffset = 0;
40087
40088			if ( iy === 0 && thetaStart === 0 ) {
40089
40090				uOffset = 0.5 / widthSegments;
40091
40092			} else if ( iy === heightSegments && thetaEnd === Math.PI ) {
40093
40094				uOffset = - 0.5 / widthSegments;
40095
40096			}
40097
40098			for ( let ix = 0; ix <= widthSegments; ix ++ ) {
40099
40100				const u = ix / widthSegments;
40101
40102				// vertex
40103
40104				vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
40105				vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
40106				vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
40107
40108				vertices.push( vertex.x, vertex.y, vertex.z );
40109
40110				// normal
40111
40112				normal.copy( vertex ).normalize();
40113				normals.push( normal.x, normal.y, normal.z );
40114
40115				// uv
40116
40117				uvs.push( u + uOffset, 1 - v );
40118
40119				verticesRow.push( index ++ );
40120
40121			}
40122
40123			grid.push( verticesRow );
40124
40125		}
40126
40127		// indices
40128
40129		for ( let iy = 0; iy < heightSegments; iy ++ ) {
40130
40131			for ( let ix = 0; ix < widthSegments; ix ++ ) {
40132
40133				const a = grid[ iy ][ ix + 1 ];
40134				const b = grid[ iy ][ ix ];
40135				const c = grid[ iy + 1 ][ ix ];
40136				const d = grid[ iy + 1 ][ ix + 1 ];
40137
40138				if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
40139				if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
40140
40141			}
40142
40143		}
40144
40145		// build geometry
40146
40147		this.setIndex( indices );
40148		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 6,566 bytes, lines 40149-40441
40149		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
40150		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
40151
40152	}
40153
40154	copy( source ) {
40155
40156		super.copy( source );
40157
40158		this.parameters = Object.assign( {}, source.parameters );
40159
40160		return this;
40161
40162	}
40163
40164	static fromJSON( data ) {
40165
40166		return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength );
40167
40168	}
40169
40170}
40171
40172class TetrahedronGeometry extends PolyhedronGeometry {
40173
40174	constructor( radius = 1, detail = 0 ) {
40175
40176		const vertices = [
40177			1, 1, 1, 	- 1, - 1, 1, 	- 1, 1, - 1, 	1, - 1, - 1
40178		];
40179
40180		const indices = [
40181			2, 1, 0, 	0, 3, 2,	1, 3, 0,	2, 3, 1
40182		];
40183
40184		super( vertices, indices, radius, detail );
40185
40186		this.type = 'TetrahedronGeometry';
40187
40188		this.parameters = {
40189			radius: radius,
40190			detail: detail
40191		};
40192
40193	}
40194
40195	static fromJSON( data ) {
40196
40197		return new TetrahedronGeometry( data.radius, data.detail );
40198
40199	}
40200
40201}
40202
40203class TorusGeometry extends BufferGeometry {
40204
40205	constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) {
40206
40207		super();
40208
40209		this.type = 'TorusGeometry';
40210
40211		this.parameters = {
40212			radius: radius,
40213			tube: tube,
40214			radialSegments: radialSegments,
40215			tubularSegments: tubularSegments,
40216			arc: arc
40217		};
40218
40219		radialSegments = Math.floor( radialSegments );
40220		tubularSegments = Math.floor( tubularSegments );
40221
40222		// buffers
40223
40224		const indices = [];
40225		const vertices = [];
40226		const normals = [];
40227		const uvs = [];
40228
40229		// helper variables
40230
40231		const center = new Vector3();
40232		const vertex = new Vector3();
40233		const normal = new Vector3();
40234
40235		// generate vertices, normals and uvs
40236
40237		for ( let j = 0; j <= radialSegments; j ++ ) {
40238
40239			for ( let i = 0; i <= tubularSegments; i ++ ) {
40240
40241				const u = i / tubularSegments * arc;
40242				const v = j / radialSegments * Math.PI * 2;
40243
40244				// vertex
40245
40246				vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
40247				vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
40248				vertex.z = tube * Math.sin( v );
40249
40250				vertices.push( vertex.x, vertex.y, vertex.z );
40251
40252				// normal
40253
40254				center.x = radius * Math.cos( u );
40255				center.y = radius * Math.sin( u );
40256				normal.subVectors( vertex, center ).normalize();
40257
40258				normals.push( normal.x, normal.y, normal.z );
40259
40260				// uv
40261
40262				uvs.push( i / tubularSegments );
40263				uvs.push( j / radialSegments );
40264
40265			}
40266
40267		}
40268
40269		// generate indices
40270
40271		for ( let j = 1; j <= radialSegments; j ++ ) {
40272
40273			for ( let i = 1; i <= tubularSegments; i ++ ) {
40274
40275				// indices
40276
40277				const a = ( tubularSegments + 1 ) * j + i - 1;
40278				const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
40279				const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
40280				const d = ( tubularSegments + 1 ) * j + i;
40281
40282				// faces
40283
40284				indices.push( a, b, d );
40285				indices.push( b, c, d );
40286
40287			}
40288
40289		}
40290
40291		// build geometry
40292
40293		this.setIndex( indices );
40294		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
40295		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
40296		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
40297
40298	}
40299
40300	copy( source ) {
40301
40302		super.copy( source );
40303
40304		this.parameters = Object.assign( {}, source.parameters );
40305
40306		return this;
40307
40308	}
40309
40310	static fromJSON( data ) {
40311
40312		return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc );
40313
40314	}
40315
40316}
40317
40318class TorusKnotGeometry extends BufferGeometry {
40319
40320	constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
40321
40322		super();
40323
40324		this.type = 'TorusKnotGeometry';
40325
40326		this.parameters = {
40327			radius: radius,
40328			tube: tube,
40329			tubularSegments: tubularSegments,
40330			radialSegments: radialSegments,
40331			p: p,
40332			q: q
40333		};
40334
40335		tubularSegments = Math.floor( tubularSegments );
40336		radialSegments = Math.floor( radialSegments );
40337
40338		// buffers
40339
40340		const indices = [];
40341		const vertices = [];
40342		const normals = [];
40343		const uvs = [];
40344
40345		// helper variables
40346
40347		const vertex = new Vector3();
40348		const normal = new Vector3();
40349
40350		const P1 = new Vector3();
40351		const P2 = new Vector3();
40352
40353		const B = new Vector3();
40354		const T = new Vector3();
40355		const N = new Vector3();
40356
40357		// generate vertices, normals and uvs
40358
40359		for ( let i = 0; i <= tubularSegments; ++ i ) {
40360
40361			// the radian "u" is used to calculate the position on the torus curve of the current tubular segment
40362
40363			const u = i / tubularSegments * p * Math.PI * 2;
40364
40365			// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
40366			// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
40367
40368			calculatePositionOnCurve( u, p, q, radius, P1 );
40369			calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
40370
40371			// calculate orthonormal basis
40372
40373			T.subVectors( P2, P1 );
40374			N.addVectors( P2, P1 );
40375			B.crossVectors( T, N );
40376			N.crossVectors( B, T );
40377
40378			// normalize B, N. T can be ignored, we don't use it
40379
40380			B.normalize();
40381			N.normalize();
40382
40383			for ( let j = 0; j <= radialSegments; ++ j ) {
40384
40385				// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
40386				// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
40387
40388				const v = j / radialSegments * Math.PI * 2;
40389				const cx = - tube * Math.cos( v );
40390				const cy = tube * Math.sin( v );
40391
40392				// now calculate the final vertex position.
40393				// first we orient the extrusion with our basis vectors, then we add it to the current position on the curve
40394
40395				vertex.x = P1.x + ( cx * N.x + cy * B.x );
40396				vertex.y = P1.y + ( cx * N.y + cy * B.y );
40397				vertex.z = P1.z + ( cx * N.z + cy * B.z );
40398
40399				vertices.push( vertex.x, vertex.y, vertex.z );
40400
40401				// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
40402
40403				normal.subVectors( vertex, P1 ).normalize();
40404
40405				normals.push( normal.x, normal.y, normal.z );
40406
40407				// uv
40408
40409				uvs.push( i / tubularSegments );
40410				uvs.push( j / radialSegments );
40411
40412			}
40413
40414		}
40415
40416		// generate indices
40417
40418		for ( let j = 1; j <= tubularSegments; j ++ ) {
40419
40420			for ( let i = 1; i <= radialSegments; i ++ ) {
40421
40422				// indices
40423
40424				const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
40425				const b = ( radialSegments + 1 ) * j + ( i - 1 );
40426				const c = ( radialSegments + 1 ) * j + i;
40427				const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
40428
40429				// faces
40430
40431				indices.push( a, b, d );
40432				indices.push( b, c, d );
40433
40434			}
40435
40436		}
40437
40438		// build geometry
40439
40440		this.setIndex( indices );
40441		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
vendor: 7,450 bytes, lines 40442-40800
40442		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
40443		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
40444
40445		// this function calculates the current position on the torus curve
40446
40447		function calculatePositionOnCurve( u, p, q, radius, position ) {
40448
40449			const cu = Math.cos( u );
40450			const su = Math.sin( u );
40451			const quOverP = q / p * u;
40452			const cs = Math.cos( quOverP );
40453
40454			position.x = radius * ( 2 + cs ) * 0.5 * cu;
40455			position.y = radius * ( 2 + cs ) * su * 0.5;
40456			position.z = radius * Math.sin( quOverP ) * 0.5;
40457
40458		}
40459
40460	}
40461
40462	copy( source ) {
40463
40464		super.copy( source );
40465
40466		this.parameters = Object.assign( {}, source.parameters );
40467
40468		return this;
40469
40470	}
40471
40472	static fromJSON( data ) {
40473
40474		return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q );
40475
40476	}
40477
40478}
40479
40480class TubeGeometry extends BufferGeometry {
40481
40482	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 ) {
40483
40484		super();
40485
40486		this.type = 'TubeGeometry';
40487
40488		this.parameters = {
40489			path: path,
40490			tubularSegments: tubularSegments,
40491			radius: radius,
40492			radialSegments: radialSegments,
40493			closed: closed
40494		};
40495
40496		const frames = path.computeFrenetFrames( tubularSegments, closed );
40497
40498		// expose internals
40499
40500		this.tangents = frames.tangents;
40501		this.normals = frames.normals;
40502		this.binormals = frames.binormals;
40503
40504		// helper variables
40505
40506		const vertex = new Vector3();
40507		const normal = new Vector3();
40508		const uv = new Vector2();
40509		let P = new Vector3();
40510
40511		// buffer
40512
40513		const vertices = [];
40514		const normals = [];
40515		const uvs = [];
40516		const indices = [];
40517
40518		// create buffer data
40519
40520		generateBufferData();
40521
40522		// build geometry
40523
40524		this.setIndex( indices );
40525		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
40526		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
40527		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
40528
40529		// functions
40530
40531		function generateBufferData() {
40532
40533			for ( let i = 0; i < tubularSegments; i ++ ) {
40534
40535				generateSegment( i );
40536
40537			}
40538
40539			// if the geometry is not closed, generate the last row of vertices and normals
40540			// at the regular position on the given path
40541			//
40542			// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
40543
40544			generateSegment( ( closed === false ) ? tubularSegments : 0 );
40545
40546			// uvs are generated in a separate function.
40547			// this makes it easy compute correct values for closed geometries
40548
40549			generateUVs();
40550
40551			// finally create faces
40552
40553			generateIndices();
40554
40555		}
40556
40557		function generateSegment( i ) {
40558
40559			// we use getPointAt to sample evenly distributed points from the given path
40560
40561			P = path.getPointAt( i / tubularSegments, P );
40562
40563			// retrieve corresponding normal and binormal
40564
40565			const N = frames.normals[ i ];
40566			const B = frames.binormals[ i ];
40567
40568			// generate normals and vertices for the current segment
40569
40570			for ( let j = 0; j <= radialSegments; j ++ ) {
40571
40572				const v = j / radialSegments * Math.PI * 2;
40573
40574				const sin = Math.sin( v );
40575				const cos = - Math.cos( v );
40576
40577				// normal
40578
40579				normal.x = ( cos * N.x + sin * B.x );
40580				normal.y = ( cos * N.y + sin * B.y );
40581				normal.z = ( cos * N.z + sin * B.z );
40582				normal.normalize();
40583
40584				normals.push( normal.x, normal.y, normal.z );
40585
40586				// vertex
40587
40588				vertex.x = P.x + radius * normal.x;
40589				vertex.y = P.y + radius * normal.y;
40590				vertex.z = P.z + radius * normal.z;
40591
40592				vertices.push( vertex.x, vertex.y, vertex.z );
40593
40594			}
40595
40596		}
40597
40598		function generateIndices() {
40599
40600			for ( let j = 1; j <= tubularSegments; j ++ ) {
40601
40602				for ( let i = 1; i <= radialSegments; i ++ ) {
40603
40604					const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
40605					const b = ( radialSegments + 1 ) * j + ( i - 1 );
40606					const c = ( radialSegments + 1 ) * j + i;
40607					const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
40608
40609					// faces
40610
40611					indices.push( a, b, d );
40612					indices.push( b, c, d );
40613
40614				}
40615
40616			}
40617
40618		}
40619
40620		function generateUVs() {
40621
40622			for ( let i = 0; i <= tubularSegments; i ++ ) {
40623
40624				for ( let j = 0; j <= radialSegments; j ++ ) {
40625
40626					uv.x = i / tubularSegments;
40627					uv.y = j / radialSegments;
40628
40629					uvs.push( uv.x, uv.y );
40630
40631				}
40632
40633			}
40634
40635		}
40636
40637	}
40638
40639	copy( source ) {
40640
40641		super.copy( source );
40642
40643		this.parameters = Object.assign( {}, source.parameters );
40644
40645		return this;
40646
40647	}
40648
40649	toJSON() {
40650
40651		const data = super.toJSON();
40652
40653		data.path = this.parameters.path.toJSON();
40654
40655		return data;
40656
40657	}
40658
40659	static fromJSON( data ) {
40660
40661		// This only works for built-in curves (e.g. CatmullRomCurve3).
40662		// User defined curves or instances of CurvePath will not be deserialized.
40663		return new TubeGeometry(
40664			new Curves[ data.path.type ]().fromJSON( data.path ),
40665			data.tubularSegments,
40666			data.radius,
40667			data.radialSegments,
40668			data.closed
40669		);
40670
40671	}
40672
40673}
40674
40675class WireframeGeometry extends BufferGeometry {
40676
40677	constructor( geometry = null ) {
40678
40679		super();
40680
40681		this.type = 'WireframeGeometry';
40682
40683		this.parameters = {
40684			geometry: geometry
40685		};
40686
40687		if ( geometry !== null ) {
40688
40689			// buffer
40690
40691			const vertices = [];
40692			const edges = new Set();
40693
40694			// helper variables
40695
40696			const start = new Vector3();
40697			const end = new Vector3();
40698
40699			if ( geometry.index !== null ) {
40700
40701				// indexed BufferGeometry
40702
40703				const position = geometry.attributes.position;
40704				const indices = geometry.index;
40705				let groups = geometry.groups;
40706
40707				if ( groups.length === 0 ) {
40708
40709					groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
40710
40711				}
40712
40713				// create a data structure that contains all edges without duplicates
40714
40715				for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
40716
40717					const group = groups[ o ];
40718
40719					const groupStart = group.start;
40720					const groupCount = group.count;
40721
40722					for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) {
40723
40724						for ( let j = 0; j < 3; j ++ ) {
40725
40726							const index1 = indices.getX( i + j );
40727							const index2 = indices.getX( i + ( j + 1 ) % 3 );
40728
40729							start.fromBufferAttribute( position, index1 );
40730							end.fromBufferAttribute( position, index2 );
40731
40732							if ( isUniqueEdge( start, end, edges ) === true ) {
40733
40734								vertices.push( start.x, start.y, start.z );
40735								vertices.push( end.x, end.y, end.z );
40736
40737							}
40738
40739						}
40740
40741					}
40742
40743				}
40744
40745			} else {
40746
40747				// non-indexed BufferGeometry
40748
40749				const position = geometry.attributes.position;
40750
40751				for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
40752
40753					for ( let j = 0; j < 3; j ++ ) {
40754
40755						// three edges per triangle, an edge is represented as (index1, index2)
40756						// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
40757
40758						const index1 = 3 * i + j;
40759						const index2 = 3 * i + ( ( j + 1 ) % 3 );
40760
40761						start.fromBufferAttribute( position, index1 );
40762						end.fromBufferAttribute( position, index2 );
40763
40764						if ( isUniqueEdge( start, end, edges ) === true ) {
40765
40766							vertices.push( start.x, start.y, start.z );
40767							vertices.push( end.x, end.y, end.z );
40768
40769						}
40770
40771					}
40772
40773				}
40774
40775			}
40776
40777			// build geometry
40778
40779			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
40780
40781		}
40782
40783	}
40784
40785	copy( source ) {
40786
40787		super.copy( source );
40788
40789		this.parameters = Object.assign( {}, source.parameters );
40790
40791		return this;
40792
40793	}
40794
40795}
40796
40797function isUniqueEdge( start, end, edges ) {
40798
40799	const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`;
40800	const hash2 = `${end.x}
40800,${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge
40801
40802	if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) {
40803
40804		return false;
40805
40806	} else {
40807
40808		edges.add( hash1 );
40809		edges.add( hash2 );
40810		return true;
40811
40812	}
40813
40814}
40815
40816var Geometries = /*#__PURE__*/Object.freeze({
40817	__proto__: null,
40818	BoxGeometry: BoxGeometry,
40819	CapsuleGeometry: CapsuleGeometry,
40820	CircleGeometry: CircleGeometry,
40821	ConeGeometry: ConeGeometry,
40822	CylinderGeometry: CylinderGeometry,
40823	DodecahedronGeometry: DodecahedronGeometry,
40824	EdgesGeometry: EdgesGeometry,
40825	ExtrudeGeometry: ExtrudeGeometry,
40826	IcosahedronGeometry: IcosahedronGeometry,
40827	LatheGeometry: LatheGeometry,
40828	OctahedronGeometry: OctahedronGeometry,
40829	PlaneGeometry: PlaneGeometry,
40830	PolyhedronGeometry: PolyhedronGeometry,
40831	RingGeometry: RingGeometry,
40832	ShapeGeometry: ShapeGeometry,
40833	SphereGeometry: SphereGeometry,
40834	TetrahedronGeometry: TetrahedronGeometry,
40835	TorusGeometry: TorusGeometry,
40836	TorusKnotGeometry: TorusKnotGeometry,
40837	TubeGeometry: TubeGeometry,
40838	WireframeGeometry: WireframeGeometry
40839});
40840
40841class ShadowMaterial extends Material {
40842
40843	constructor( parameters ) {
40844
40845		super();
40846
40847		this.isShadowMaterial = true;
40848
40849		this.type = 'ShadowMaterial';
40850
40851		this.color = new Color( 0x000000 );
40852		this.transparent = true;
40853
40854		this.fog = true;
40855
40856		this.setValues( parameters );
40857
40858	}
40859
40860	copy( source ) {
40861
40862		super.copy( source );
40863
40864		this.color.copy( source.color );
40865
40866		this.fog = source.fog;
40867
40868		return this;
40869
40870	}
40871
40872}
40873
40874class RawShaderMaterial extends ShaderMaterial {
40875
40876	constructor( parameters ) {
40877
40878		super( parameters );
40879
40880		this.isRawShaderMaterial = true;
40881
40882		this.type = 'RawShaderMaterial';
40883
40884	}
40885
40886}
40887
40888class MeshStandardMaterial extends Material {
40889
40890	constructor( parameters ) {
40891
40892		super();
40893
40894		this.isMeshStandardMaterial = true;
40895
40896		this.defines = { 'STANDARD': '' };
40897
40898		this.type = 'MeshStandardMaterial';
40899
40900		this.color = new Color( 0xffffff ); // diffuse
40901		this.roughness = 1.0;
40902		this.metalness = 0.0;
40903
40904		this.map = null;
40905
40906		this.lightMap = null;
40907		this.lightMapIntensity = 1.0;
40908
40909		this.aoMap = null;
40910		this.aoMapIntensity = 1.0;
40911
40912		this.emissive = new Color( 0x000000 );
40913		this.emissiveIntensity = 1.0;
40914		this.emissiveMap = null;
40915
40916		this.bumpMap = null;
40917		this.bumpScale = 1;
40918
40919		this.normalMap = null;
40920		this.normalMapType = TangentSpaceNormalMap;
40921		this.normalScale = new Vector2( 1, 1 );
40922
40923		this.displacementMap = null;
40924		this.displacementScale = 1;
40925		this.displacementBias = 0;
40926
40927		this.roughnessMap = null;
40928
40929		this.metalnessMap = null;
40930
40931		this.alphaMap = null;
40932
40933		this.envMap = null;
40934		this.envMapRotation = new Euler();
40935		this.envMapIntensity = 1.0;
40936
40937		this.wireframe = false;
40938		this.wireframeLinewidth = 1;
40939		this.wireframeLinecap = 'round';
40940		this.wireframeLinejoin = 'round';
40941
40942		this.flatShading = false;
40943
40944		this.fog = true;
40945
40946		this.setValues( parameters );
40947
40948	}
40949
40950	copy( source ) {
40951
40952		super.copy( source );
40953
40954		this.defines = { 'STANDARD': '' };
40955
40956		this.color.copy( source.color );
40957		this.roughness = source.roughness;
40958		this.metalness = source.metalness;
40959
40960		this.map = source.map;
40961
40962		this.lightMap = source.lightMap;
40963		this.lightMapIntensity = source.lightMapIntensity;
40964
40965		this.aoMap = source.aoMap;
40966		this.aoMapIntensity = source.aoMapIntensity;
40967
40968		this.emissive.copy( source.emissive );
40969		this.emissiveMap = source.emissiveMap;
40970		this.emissiveIntensity = source.emissiveIntensity;
40971
40972		this.bumpMap = source.bumpMap;
40973		this.bumpScale = source.bumpScale;
40974
40975		this.normalMap = source.normalMap;
40976		this.normalMapType = source.normalMapType;
40977		this.normalScale.copy( source.normalScale );
40978
40979		this.displacementMap = source.displacementMap;
40980		this.displacementScale = source.displacementScale;
40981		this.displacementBias = source.displacementBias;
40982
40983		this.roughnessMap = source.roughnessMap;
40984
40985		this.metalnessMap = source.metalnessMap;
40986
40987		this.alphaMap = source.alphaMap;
40988
40989		this.envMap = source.envMap;
40990		this.envMapRotation.copy( source.envMapRotation );
40991		this.envMapIntensity = source.envMapIntensity;
40992
40993		this.wireframe = source.wireframe;
40994		this.wireframeLinewidth = source.wireframeLinewidth;
40995		this.wireframeLinecap = source.wireframeLinecap;
40996		this.wireframeLinejoin = source.wireframeLinejoin;
40997
vendor: 5,396 bytes, lines 40998-41293
40998		this.flatShading = source.flatShading;
40999
41000		this.fog = source.fog;
41001
41002		return this;
41003
41004	}
41005
41006}
41007
41008class MeshPhysicalMaterial extends MeshStandardMaterial {
41009
41010	constructor( parameters ) {
41011
41012		super();
41013
41014		this.isMeshPhysicalMaterial = true;
41015
41016		this.defines = {
41017
41018			'STANDARD': '',
41019			'PHYSICAL': ''
41020
41021		};
41022
41023		this.type = 'MeshPhysicalMaterial';
41024
41025		this.anisotropyRotation = 0;
41026		this.anisotropyMap = null;
41027
41028		this.clearcoatMap = null;
41029		this.clearcoatRoughness = 0.0;
41030		this.clearcoatRoughnessMap = null;
41031		this.clearcoatNormalScale = new Vector2( 1, 1 );
41032		this.clearcoatNormalMap = null;
41033
41034		this.ior = 1.5;
41035
41036		Object.defineProperty( this, 'reflectivity', {
41037			get: function () {
41038
41039				return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) );
41040
41041			},
41042			set: function ( reflectivity ) {
41043
41044				this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity );
41045
41046			}
41047		} );
41048
41049		this.iridescenceMap = null;
41050		this.iridescenceIOR = 1.3;
41051		this.iridescenceThicknessRange = [ 100, 400 ];
41052		this.iridescenceThicknessMap = null;
41053
41054		this.sheenColor = new Color( 0x000000 );
41055		this.sheenColorMap = null;
41056		this.sheenRoughness = 1.0;
41057		this.sheenRoughnessMap = null;
41058
41059		this.transmissionMap = null;
41060
41061		this.thickness = 0;
41062		this.thicknessMap = null;
41063		this.attenuationDistance = Infinity;
41064		this.attenuationColor = new Color( 1, 1, 1 );
41065
41066		this.specularIntensity = 1.0;
41067		this.specularIntensityMap = null;
41068		this.specularColor = new Color( 1, 1, 1 );
41069		this.specularColorMap = null;
41070
41071		this._anisotropy = 0;
41072		this._clearcoat = 0;
41073		this._dispersion = 0;
41074		this._iridescence = 0;
41075		this._sheen = 0.0;
41076		this._transmission = 0;
41077
41078		this.setValues( parameters );
41079
41080	}
41081
41082	get anisotropy() {
41083
41084		return this._anisotropy;
41085
41086	}
41087
41088	set anisotropy( value ) {
41089
41090		if ( this._anisotropy > 0 !== value > 0 ) {
41091
41092			this.version ++;
41093
41094		}
41095
41096		this._anisotropy = value;
41097
41098	}
41099
41100	get clearcoat() {
41101
41102		return this._clearcoat;
41103
41104	}
41105
41106	set clearcoat( value ) {
41107
41108		if ( this._clearcoat > 0 !== value > 0 ) {
41109
41110			this.version ++;
41111
41112		}
41113
41114		this._clearcoat = value;
41115
41116	}
41117
41118	get iridescence() {
41119
41120		return this._iridescence;
41121
41122	}
41123
41124	set iridescence( value ) {
41125
41126		if ( this._iridescence > 0 !== value > 0 ) {
41127
41128			this.version ++;
41129
41130		}
41131
41132		this._iridescence = value;
41133
41134	}
41135
41136	get dispersion() {
41137
41138		return this._dispersion;
41139
41140	}
41141
41142	set dispersion( value ) {
41143
41144		if ( this._dispersion > 0 !== value > 0 ) {
41145
41146			this.version ++;
41147
41148		}
41149
41150		this._dispersion = value;
41151
41152	}
41153
41154	get sheen() {
41155
41156		return this._sheen;
41157
41158	}
41159
41160	set sheen( value ) {
41161
41162		if ( this._sheen > 0 !== value > 0 ) {
41163
41164			this.version ++;
41165
41166		}
41167
41168		this._sheen = value;
41169
41170	}
41171
41172	get transmission() {
41173
41174		return this._transmission;
41175
41176	}
41177
41178	set transmission( value ) {
41179
41180		if ( this._transmission > 0 !== value > 0 ) {
41181
41182			this.version ++;
41183
41184		}
41185
41186		this._transmission = value;
41187
41188	}
41189
41190	copy( source ) {
41191
41192		super.copy( source );
41193
41194		this.defines = {
41195
41196			'STANDARD': '',
41197			'PHYSICAL': ''
41198
41199		};
41200
41201		this.anisotropy = source.anisotropy;
41202		this.anisotropyRotation = source.anisotropyRotation;
41203		this.anisotropyMap = source.anisotropyMap;
41204
41205		this.clearcoat = source.clearcoat;
41206		this.clearcoatMap = source.clearcoatMap;
41207		this.clearcoatRoughness = source.clearcoatRoughness;
41208		this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
41209		this.clearcoatNormalMap = source.clearcoatNormalMap;
41210		this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
41211
41212		this.dispersion = source.dispersion;
41213		this.ior = source.ior;
41214
41215		this.iridescence = source.iridescence;
41216		this.iridescenceMap = source.iridescenceMap;
41217		this.iridescenceIOR = source.iridescenceIOR;
41218		this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ];
41219		this.iridescenceThicknessMap = source.iridescenceThicknessMap;
41220
41221		this.sheen = source.sheen;
41222		this.sheenColor.copy( source.sheenColor );
41223		this.sheenColorMap = source.sheenColorMap;
41224		this.sheenRoughness = source.sheenRoughness;
41225		this.sheenRoughnessMap = source.sheenRoughnessMap;
41226
41227		this.transmission = source.transmission;
41228		this.transmissionMap = source.transmissionMap;
41229
41230		this.thickness = source.thickness;
41231		this.thicknessMap = source.thicknessMap;
41232		this.attenuationDistance = source.attenuationDistance;
41233		this.attenuationColor.copy( source.attenuationColor );
41234
41235		this.specularIntensity = source.specularIntensity;
41236		this.specularIntensityMap = source.specularIntensityMap;
41237		this.specularColor.copy( source.specularColor );
41238		this.specularColorMap = source.specularColorMap;
41239
41240		return this;
41241
41242	}
41243
41244}
41245
41246class MeshPhongMaterial extends Material {
41247
41248	constructor( parameters ) {
41249
41250		super();
41251
41252		this.isMeshPhongMaterial = true;
41253
41254		this.type = 'MeshPhongMaterial';
41255
41256		this.color = new Color( 0xffffff ); // diffuse
41257		this.specular = new Color( 0x111111 );
41258		this.shininess = 30;
41259
41260		this.map = null;
41261
41262		this.lightMap = null;
41263		this.lightMapIntensity = 1.0;
41264
41265		this.aoMap = null;
41266		this.aoMapIntensity = 1.0;
41267
41268		this.emissive = new Color( 0x000000 );
41269		this.emissiveIntensity = 1.0;
41270		this.emissiveMap = null;
41271
41272		this.bumpMap = null;
41273		this.bumpScale = 1;
41274
41275		this.normalMap = null;
41276		this.normalMapType = TangentSpaceNormalMap;
41277		this.normalScale = new Vector2( 1, 1 );
41278
41279		this.displacementMap = null;
41280		this.displacementScale = 1;
41281		this.displacementBias = 0;
41282
41283		this.specularMap = null;
41284
41285		this.alphaMap = null;
41286
41287		this.envMap = null;
41288		this.envMapRotation = new Euler();
41289		this.combine = MultiplyOperation;
41290		this.reflectivity = 1;
41291		this.refractionRatio = 0.98;
41292
41293		this.wireframe = false;
41294		this.wireframeLinewidth = 1;
41295		this.wireframeLinecap = 'round';
41296		this.wireframeLinejoin = 'round';
41297
41298		this.flatShading = false;
41299
41300		this.fog = true;
41301
41302		this.setValues( parameters );
41303
41304	}
41305
41306	copy( source ) {
41307
41308		super.copy( source );
41309
41310		this.color.copy( source.color );
41311		this.specular.copy( source.specular );
41312		this.shininess = source.shininess;
41313
41314		this.map = source.map;
41315
41316		this.lightMap = source.lightMap;
41317		this.lightMapIntensity = source.lightMapIntensity;
41318
41319		this.aoMap = source.aoMap;
41320		this.aoMapIntensity = source.aoMapIntensity;
41321
41322		this.emissive.copy( source.emissive );
41323		this.emissiveMap = source.emissiveMap;
41324		this.emissiveIntensity = source.emissiveIntensity;
41325
41326		this.bumpMap = source.bumpMap;
41327		this.bumpScale = source.bumpScale;
41328
41329		this.normalMap = source.normalMap;
41330		this.normalMapType = source.normalMapType;
41331		this.normalScale.copy( source.normalScale );
41332
41333		this.displacementMap = source.displacementMap;
41334		this.displacementScale = source.displacementScale;
41335		this.displacementBias = source.displacementBias;
41336
41337		this.specularMap = source.specularMap;
41338
41339		this.alphaMap = source.alphaMap;
41340
41341		this.envMap = source.envMap;
41342		this.envMapRotation.copy( source.envMapRotation );
41343		this.combine = source.combine;
41344		this.reflectivity = source.reflectivity;
41345		this.refractionRatio = source.refractionRatio;
41346
41347		this.wireframe = source.wireframe;
41348		this.wireframeLinewidth = source.wireframeLinewidth;
41349		this.wireframeLinecap = source.wireframeLinecap;
41350		this.wireframeLinejoin = source.wireframeLinejoin;
41351
41352		this.flatShading = source.flatShading;
41353
41354		this.fog = source.fog;
41355
41356		return this;
41357
41358	}
41359
41360}
41361
41362class MeshToonMaterial extends Material {
41363
41364	constructor( parameters ) {
41365
41366		super();
41367
41368		this.isMeshToonMaterial = true;
41369
41370		this.defines = { 'TOON': '' };
41371
41372		this.type = 'MeshToonMaterial';
41373
41374		this.color = new Color( 0xffffff );
41375
41376		this.map = null;
41377		this.gradientMap = null;
41378
41379		this.lightMap = null;
41380		this.lightMapIntensity = 1.0;
41381
41382		this.aoMap = null;
41383		this.aoMapIntensity = 1.0;
41384
41385		this.emissive = new Color( 0x000000 );
41386		this.emissiveIntensity = 1.0;
41387		this.emissiveMap = null;
41388
41389		this.bumpMap = null;
41390		this.bumpScale = 1;
41391
41392		this.normalMap = null;
41393		this.normalMapType = TangentSpaceNormalMap;
41394		this.normalScale = new Vector2( 1, 1 );
41395
41396		this.displacementMap = null;
41397		this.displacementScale = 1;
41398		this.displacementBias = 0;
41399
41400		this.alphaMap = null;
41401
41402		this.wireframe = false;
41403		this.wireframeLinewidth = 1;
41404		this.wireframeLinecap = 'round';
41405		this.wireframeLinejoin = 'round';
41406
41407		this.fog = true;
41408
41409		this.setValues( parameters );
41410
41411	}
41412
41413	copy( source ) {
41414
41415		super.copy( source );
41416
41417		this.color.copy( source.color );
41418
41419		this.map = source.map;
41420		this.gradientMap = source.gradientMap;
41421
41422		this.lightMap = source.lightMap;
41423		this.lightMapIntensity = source.lightMapIntensity;
41424
41425		this.aoMap = source.aoMap;
41426		this.aoMapIntensity = source.aoMapIntensity;
41427
41428		this.emissive.copy( source.emissive );
41429		this.emissiveMap = source.emissiveMap;
41430		this.emissiveIntensity = source.emissiveIntensity;
41431
41432		this.bumpMap = source.bumpMap;
41433		this.bumpScale = source.bumpScale;
41434
41435		this.normalMap = source.normalMap;
41436		this.normalMapType = source.normalMapType;
41437		this.normalScale.copy( source.normalScale );
41438
41439		this.displacementMap = source.displacementMap;
41440		this.displacementScale = source.displacementScale;
41441		this.displacementBias = source.displacementBias;
41442
41443		this.alphaMap = source.alphaMap;
41444
41445		this.wireframe = source.wireframe;
41446		this.wireframeLinewidth = source.wireframeLinewidth;
41447		this.wireframeLinecap = source.wireframeLinecap;
41448		this.wireframeLinejoin = source.wireframeLinejoin;
41449
41450		this.fog = source.fog;
41451
41452		return this;
41453
41454	}
41455
41456}
41457
41458class MeshNormalMaterial extends Material {
41459
41460	constructor( parameters ) {
41461
41462		super();
41463
41464		this.isMeshNormalMaterial = true;
41465
41466		this.type = 'MeshNormalMaterial';
41467
41468		this.bumpMap = null;
41469		this.bumpScale = 1;
41470
41471		this.normalMap = null;
41472		this.normalMapType = TangentSpaceNormalMap;
41473		this.normalScale = new Vector2( 1, 1 );
41474
41475		this.displacementMap = null;
41476		this.displacementScale = 1;
41477		this.displacementBias = 0;
41478
41479		this.wireframe = false;
41480		this.wireframeLinewidth = 1;
41481
41482		this.flatShading = false;
vendor: 20,656 bytes, lines 41483-42523
41483
41484		this.setValues( parameters );
41485
41486	}
41487
41488	copy( source ) {
41489
41490		super.copy( source );
41491
41492		this.bumpMap = source.bumpMap;
41493		this.bumpScale = source.bumpScale;
41494
41495		this.normalMap = source.normalMap;
41496		this.normalMapType = source.normalMapType;
41497		this.normalScale.copy( source.normalScale );
41498
41499		this.displacementMap = source.displacementMap;
41500		this.displacementScale = source.displacementScale;
41501		this.displacementBias = source.displacementBias;
41502
41503		this.wireframe = source.wireframe;
41504		this.wireframeLinewidth = source.wireframeLinewidth;
41505
41506		this.flatShading = source.flatShading;
41507
41508		return this;
41509
41510	}
41511
41512}
41513
41514class MeshLambertMaterial extends Material {
41515
41516	constructor( parameters ) {
41517
41518		super();
41519
41520		this.isMeshLambertMaterial = true;
41521
41522		this.type = 'MeshLambertMaterial';
41523
41524		this.color = new Color( 0xffffff ); // diffuse
41525
41526		this.map = null;
41527
41528		this.lightMap = null;
41529		this.lightMapIntensity = 1.0;
41530
41531		this.aoMap = null;
41532		this.aoMapIntensity = 1.0;
41533
41534		this.emissive = new Color( 0x000000 );
41535		this.emissiveIntensity = 1.0;
41536		this.emissiveMap = null;
41537
41538		this.bumpMap = null;
41539		this.bumpScale = 1;
41540
41541		this.normalMap = null;
41542		this.normalMapType = TangentSpaceNormalMap;
41543		this.normalScale = new Vector2( 1, 1 );
41544
41545		this.displacementMap = null;
41546		this.displacementScale = 1;
41547		this.displacementBias = 0;
41548
41549		this.specularMap = null;
41550
41551		this.alphaMap = null;
41552
41553		this.envMap = null;
41554		this.envMapRotation = new Euler();
41555		this.combine = MultiplyOperation;
41556		this.reflectivity = 1;
41557		this.refractionRatio = 0.98;
41558
41559		this.wireframe = false;
41560		this.wireframeLinewidth = 1;
41561		this.wireframeLinecap = 'round';
41562		this.wireframeLinejoin = 'round';
41563
41564		this.flatShading = false;
41565
41566		this.fog = true;
41567
41568		this.setValues( parameters );
41569
41570	}
41571
41572	copy( source ) {
41573
41574		super.copy( source );
41575
41576		this.color.copy( source.color );
41577
41578		this.map = source.map;
41579
41580		this.lightMap = source.lightMap;
41581		this.lightMapIntensity = source.lightMapIntensity;
41582
41583		this.aoMap = source.aoMap;
41584		this.aoMapIntensity = source.aoMapIntensity;
41585
41586		this.emissive.copy( source.emissive );
41587		this.emissiveMap = source.emissiveMap;
41588		this.emissiveIntensity = source.emissiveIntensity;
41589
41590		this.bumpMap = source.bumpMap;
41591		this.bumpScale = source.bumpScale;
41592
41593		this.normalMap = source.normalMap;
41594		this.normalMapType = source.normalMapType;
41595		this.normalScale.copy( source.normalScale );
41596
41597		this.displacementMap = source.displacementMap;
41598		this.displacementScale = source.displacementScale;
41599		this.displacementBias = source.displacementBias;
41600
41601		this.specularMap = source.specularMap;
41602
41603		this.alphaMap = source.alphaMap;
41604
41605		this.envMap = source.envMap;
41606		this.envMapRotation.copy( source.envMapRotation );
41607		this.combine = source.combine;
41608		this.reflectivity = source.reflectivity;
41609		this.refractionRatio = source.refractionRatio;
41610
41611		this.wireframe = source.wireframe;
41612		this.wireframeLinewidth = source.wireframeLinewidth;
41613		this.wireframeLinecap = source.wireframeLinecap;
41614		this.wireframeLinejoin = source.wireframeLinejoin;
41615
41616		this.flatShading = source.flatShading;
41617
41618		this.fog = source.fog;
41619
41620		return this;
41621
41622	}
41623
41624}
41625
41626class MeshMatcapMaterial extends Material {
41627
41628	constructor( parameters ) {
41629
41630		super();
41631
41632		this.isMeshMatcapMaterial = true;
41633
41634		this.defines = { 'MATCAP': '' };
41635
41636		this.type = 'MeshMatcapMaterial';
41637
41638		this.color = new Color( 0xffffff ); // diffuse
41639
41640		this.matcap = null;
41641
41642		this.map = null;
41643
41644		this.bumpMap = null;
41645		this.bumpScale = 1;
41646
41647		this.normalMap = null;
41648		this.normalMapType = TangentSpaceNormalMap;
41649		this.normalScale = new Vector2( 1, 1 );
41650
41651		this.displacementMap = null;
41652		this.displacementScale = 1;
41653		this.displacementBias = 0;
41654
41655		this.alphaMap = null;
41656
41657		this.flatShading = false;
41658
41659		this.fog = true;
41660
41661		this.setValues( parameters );
41662
41663	}
41664
41665
41666	copy( source ) {
41667
41668		super.copy( source );
41669
41670		this.defines = { 'MATCAP': '' };
41671
41672		this.color.copy( source.color );
41673
41674		this.matcap = source.matcap;
41675
41676		this.map = source.map;
41677
41678		this.bumpMap = source.bumpMap;
41679		this.bumpScale = source.bumpScale;
41680
41681		this.normalMap = source.normalMap;
41682		this.normalMapType = source.normalMapType;
41683		this.normalScale.copy( source.normalScale );
41684
41685		this.displacementMap = source.displacementMap;
41686		this.displacementScale = source.displacementScale;
41687		this.displacementBias = source.displacementBias;
41688
41689		this.alphaMap = source.alphaMap;
41690
41691		this.flatShading = source.flatShading;
41692
41693		this.fog = source.fog;
41694
41695		return this;
41696
41697	}
41698
41699}
41700
41701class LineDashedMaterial extends LineBasicMaterial {
41702
41703	constructor( parameters ) {
41704
41705		super();
41706
41707		this.isLineDashedMaterial = true;
41708
41709		this.type = 'LineDashedMaterial';
41710
41711		this.scale = 1;
41712		this.dashSize = 3;
41713		this.gapSize = 1;
41714
41715		this.setValues( parameters );
41716
41717	}
41718
41719	copy( source ) {
41720
41721		super.copy( source );
41722
41723		this.scale = source.scale;
41724		this.dashSize = source.dashSize;
41725		this.gapSize = source.gapSize;
41726
41727		return this;
41728
41729	}
41730
41731}
41732
41733// converts an array to a specific type
41734function convertArray( array, type, forceClone ) {
41735
41736	if ( ! array || // let 'undefined' and 'null' pass
41737		! forceClone && array.constructor === type ) return array;
41738
41739	if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
41740
41741		return new type( array ); // create typed array
41742
41743	}
41744
41745	return Array.prototype.slice.call( array ); // create Array
41746
41747}
41748
41749function isTypedArray( object ) {
41750
41751	return ArrayBuffer.isView( object ) &&
41752		! ( object instanceof DataView );
41753
41754}
41755
41756// returns an array by which times and values can be sorted
41757function getKeyframeOrder( times ) {
41758
41759	function compareTime( i, j ) {
41760
41761		return times[ i ] - times[ j ];
41762
41763	}
41764
41765	const n = times.length;
41766	const result = new Array( n );
41767	for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
41768
41769	result.sort( compareTime );
41770
41771	return result;
41772
41773}
41774
41775// uses the array previously returned by 'getKeyframeOrder' to sort data
41776function sortedArray( values, stride, order ) {
41777
41778	const nValues = values.length;
41779	const result = new values.constructor( nValues );
41780
41781	for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
41782
41783		const srcOffset = order[ i ] * stride;
41784
41785		for ( let j = 0; j !== stride; ++ j ) {
41786
41787			result[ dstOffset ++ ] = values[ srcOffset + j ];
41788
41789		}
41790
41791	}
41792
41793	return result;
41794
41795}
41796
41797// function for parsing AOS keyframe formats
41798function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
41799
41800	let i = 1, key = jsonKeys[ 0 ];
41801
41802	while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
41803
41804		key = jsonKeys[ i ++ ];
41805
41806	}
41807
41808	if ( key === undefined ) return; // no data
41809
41810	let value = key[ valuePropertyName ];
41811	if ( value === undefined ) return; // no data
41812
41813	if ( Array.isArray( value ) ) {
41814
41815		do {
41816
41817			value = key[ valuePropertyName ];
41818
41819			if ( value !== undefined ) {
41820
41821				times.push( key.time );
41822				values.push.apply( values, value ); // push all elements
41823
41824			}
41825
41826			key = jsonKeys[ i ++ ];
41827
41828		} while ( key !== undefined );
41829
41830	} else if ( value.toArray !== undefined ) {
41831
41832		// ...assume THREE.Math-ish
41833
41834		do {
41835
41836			value = key[ valuePropertyName ];
41837
41838			if ( value !== undefined ) {
41839
41840				times.push( key.time );
41841				value.toArray( values, values.length );
41842
41843			}
41844
41845			key = jsonKeys[ i ++ ];
41846
41847		} while ( key !== undefined );
41848
41849	} else {
41850
41851		// otherwise push as-is
41852
41853		do {
41854
41855			value = key[ valuePropertyName ];
41856
41857			if ( value !== undefined ) {
41858
41859				times.push( key.time );
41860				values.push( value );
41861
41862			}
41863
41864			key = jsonKeys[ i ++ ];
41865
41866		} while ( key !== undefined );
41867
41868	}
41869
41870}
41871
41872function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
41873
41874	const clip = sourceClip.clone();
41875
41876	clip.name = name;
41877
41878	const tracks = [];
41879
41880	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41881
41882		const track = clip.tracks[ i ];
41883		const valueSize = track.getValueSize();
41884
41885		const times = [];
41886		const values = [];
41887
41888		for ( let j = 0; j < track.times.length; ++ j ) {
41889
41890			const frame = track.times[ j ] * fps;
41891
41892			if ( frame < startFrame || frame >= endFrame ) continue;
41893
41894			times.push( track.times[ j ] );
41895
41896			for ( let k = 0; k < valueSize; ++ k ) {
41897
41898				values.push( track.values[ j * valueSize + k ] );
41899
41900			}
41901
41902		}
41903
41904		if ( times.length === 0 ) continue;
41905
41906		track.times = convertArray( times, track.times.constructor );
41907		track.values = convertArray( values, track.values.constructor );
41908
41909		tracks.push( track );
41910
41911	}
41912
41913	clip.tracks = tracks;
41914
41915	// find minimum .times value across all tracks in the trimmed clip
41916
41917	let minStartTime = Infinity;
41918
41919	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41920
41921		if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
41922
41923			minStartTime = clip.tracks[ i ].times[ 0 ];
41924
41925		}
41926
41927	}
41928
41929	// shift all tracks such that clip begins at t=0
41930
41931	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41932
41933		clip.tracks[ i ].shift( - 1 * minStartTime );
41934
41935	}
41936
41937	clip.resetDuration();
41938
41939	return clip;
41940
41941}
41942
41943function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
41944
41945	if ( fps <= 0 ) fps = 30;
41946
41947	const numTracks = referenceClip.tracks.length;
41948	const referenceTime = referenceFrame / fps;
41949
41950	// Make each track's values relative to the values at the reference frame
41951	for ( let i = 0; i < numTracks; ++ i ) {
41952
41953		const referenceTrack = referenceClip.tracks[ i ];
41954		const referenceTrackType = referenceTrack.ValueTypeName;
41955
41956		// Skip this track if it's non-numeric
41957		if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
41958
41959		// Find the track in the target clip whose name and type matches the reference track
41960		const targetTrack = targetClip.tracks.find( function ( track ) {
41961
41962			return track.name === referenceTrack.name
41963				&& track.ValueTypeName === referenceTrackType;
41964
41965		} );
41966
41967		if ( targetTrack === undefined ) continue;
41968
41969		let referenceOffset = 0;
41970		const referenceValueSize = referenceTrack.getValueSize();
41971
41972		if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
41973
41974			referenceOffset = referenceValueSize / 3;
41975
41976		}
41977
41978		let targetOffset = 0;
41979		const targetValueSize = targetTrack.getValueSize();
41980
41981		if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
41982
41983			targetOffset = targetValueSize / 3;
41984
41985		}
41986
41987		const lastIndex = referenceTrack.times.length - 1;
41988		let referenceValue;
41989
41990		// Find the value to subtract out of the track
41991		if ( referenceTime <= referenceTrack.times[ 0 ] ) {
41992
41993			// Reference frame is earlier than the first keyframe, so just use the first keyframe
41994			const startIndex = referenceOffset;
41995			const endIndex = referenceValueSize - referenceOffset;
41996			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
41997
41998		} else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
41999
42000			// Reference frame is after the last keyframe, so just use the last keyframe
42001			const startIndex = lastIndex * referenceValueSize + referenceOffset;
42002			const endIndex = startIndex + referenceValueSize - referenceOffset;
42003			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
42004
42005		} else {
42006
42007			// Interpolate to the reference value
42008			const interpolant = referenceTrack.createInterpolant();
42009			const startIndex = referenceOffset;
42010			const endIndex = referenceValueSize - referenceOffset;
42011			interpolant.evaluate( referenceTime );
42012			referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex );
42013
42014		}
42015
42016		// Conjugate the quaternion
42017		if ( referenceTrackType === 'quaternion' ) {
42018
42019			const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
42020			referenceQuat.toArray( referenceValue );
42021
42022		}
42023
42024		// Subtract the reference value from all of the track values
42025
42026		const numTimes = targetTrack.times.length;
42027		for ( let j = 0; j < numTimes; ++ j ) {
42028
42029			const valueStart = j * targetValueSize + targetOffset;
42030
42031			if ( referenceTrackType === 'quaternion' ) {
42032
42033				// Multiply the conjugate for quaternion track types
42034				Quaternion.multiplyQuaternionsFlat(
42035					targetTrack.values,
42036					valueStart,
42037					referenceValue,
42038					0,
42039					targetTrack.values,
42040					valueStart
42041				);
42042
42043			} else {
42044
42045				const valueEnd = targetValueSize - targetOffset * 2;
42046
42047				// Subtract each value for all other numeric track types
42048				for ( let k = 0; k < valueEnd; ++ k ) {
42049
42050					targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
42051
42052				}
42053
42054			}
42055
42056		}
42057
42058	}
42059
42060	targetClip.blendMode = AdditiveAnimationBlendMode;
42061
42062	return targetClip;
42063
42064}
42065
42066const AnimationUtils = {
42067	convertArray: convertArray,
42068	isTypedArray: isTypedArray,
42069	getKeyframeOrder: getKeyframeOrder,
42070	sortedArray: sortedArray,
42071	flattenJSON: flattenJSON,
42072	subclip: subclip,
42073	makeClipAdditive: makeClipAdditive
42074};
42075
42076/**
42077 * Abstract base class of interpolants over parametric samples.
42078 *
42079 * The parameter domain is one dimensional, typically the time or a path
42080 * along a curve defined by the data.
42081 *
42082 * The sample values can have any dimensionality and derived classes may
42083 * apply special interpretations to the data.
42084 *
42085 * This class provides the interval seek in a Template Method, deferring
42086 * the actual interpolation to derived classes.
42087 *
42088 * Time complexity is O(1) for linear access crossing at most two points
42089 * and O(log N) for random access, where N is the number of positions.
42090 *
42091 * References:
42092 *
42093 * 		http://www.oodesign.com/template-method-pattern.html
42094 *
42095 */
42096
42097class Interpolant {
42098
42099	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42100
42101		this.parameterPositions = parameterPositions;
42102		this._cachedIndex = 0;
42103
42104		this.resultBuffer = resultBuffer !== undefined ?
42105			resultBuffer : new sampleValues.constructor( sampleSize );
42106		this.sampleValues = sampleValues;
42107		this.valueSize = sampleSize;
42108
42109		this.settings = null;
42110		this.DefaultSettings_ = {};
42111
42112	}
42113
42114	evaluate( t ) {
42115
42116		const pp = this.parameterPositions;
42117		let i1 = this._cachedIndex,
42118			t1 = pp[ i1 ],
42119			t0 = pp[ i1 - 1 ];
42120
42121		validate_interval: {
42122
42123			seek: {
42124
42125				let right;
42126
42127				linear_scan: {
42128
42129					//- See http://jsperf.com/comparison-to-undefined/3
42130					//- slower code:
42131					//-
42132					//- 				if ( t >= t1 || t1 === undefined ) {
42133					forward_scan: if ( ! ( t < t1 ) ) {
42134
42135						for ( let giveUpAt = i1 + 2; ; ) {
42136
42137							if ( t1 === undefined ) {
42138
42139								if ( t < t0 ) break forward_scan;
42140
42141								// after end
42142
42143								i1 = pp.length;
42144								this._cachedIndex = i1;
42145								return this.copySampleValue_( i1 - 1 );
42146
42147							}
42148
42149							if ( i1 === giveUpAt ) break; // this loop
42150
42151							t0 = t1;
42152							t1 = pp[ ++ i1 ];
42153
42154							if ( t < t1 ) {
42155
42156								// we have arrived at the sought interval
42157								break seek;
42158
42159							}
42160
42161						}
42162
42163						// prepare binary search on the right side of the index
42164						right = pp.length;
42165						break linear_scan;
42166
42167					}
42168
42169					//- slower code:
42170					//-					if ( t < t0 || t0 === undefined ) {
42171					if ( ! ( t >= t0 ) ) {
42172
42173						// looping?
42174
42175						const t1global = pp[ 1 ];
42176
42177						if ( t < t1global ) {
42178
42179							i1 = 2; // + 1, using the scan for the details
42180							t0 = t1global;
42181
42182						}
42183
42184						// linear reverse scan
42185
42186						for ( let giveUpAt = i1 - 2; ; ) {
42187
42188							if ( t0 === undefined ) {
42189
42190								// before start
42191
42192								this._cachedIndex = 0;
42193								return this.copySampleValue_( 0 );
42194
42195							}
42196
42197							if ( i1 === giveUpAt ) break; // this loop
42198
42199							t1 = t0;
42200							t0 = pp[ -- i1 - 1 ];
42201
42202							if ( t >= t0 ) {
42203
42204								// we have arrived at the sought interval
42205								break seek;
42206
42207							}
42208
42209						}
42210
42211						// prepare binary search on the left side of the index
42212						right = i1;
42213						i1 = 0;
42214						break linear_scan;
42215
42216					}
42217
42218					// the interval is valid
42219
42220					break validate_interval;
42221
42222				} // linear scan
42223
42224				// binary search
42225
42226				while ( i1 < right ) {
42227
42228					const mid = ( i1 + right ) >>> 1;
42229
42230					if ( t < pp[ mid ] ) {
42231
42232						right = mid;
42233
42234					} else {
42235
42236						i1 = mid + 1;
42237
42238					}
42239
42240				}
42241
42242				t1 = pp[ i1 ];
42243				t0 = pp[ i1 - 1 ];
42244
42245				// check boundary cases, again
42246
42247				if ( t0 === undefined ) {
42248
42249					this._cachedIndex = 0;
42250					return this.copySampleValue_( 0 );
42251
42252				}
42253
42254				if ( t1 === undefined ) {
42255
42256					i1 = pp.length;
42257					this._cachedIndex = i1;
42258					return this.copySampleValue_( i1 - 1 );
42259
42260				}
42261
42262			} // seek
42263
42264			this._cachedIndex = i1;
42265
42266			this.intervalChanged_( i1, t0, t1 );
42267
42268		} // validate_interval
42269
42270		return this.interpolate_( i1, t0, t, t1 );
42271
42272	}
42273
42274	getSettings_() {
42275
42276		return this.settings || this.DefaultSettings_;
42277
42278	}
42279
42280	copySampleValue_( index ) {
42281
42282		// copies a sample value to the result buffer
42283
42284		const result = this.resultBuffer,
42285			values = this.sampleValues,
42286			stride = this.valueSize,
42287			offset = index * stride;
42288
42289		for ( let i = 0; i !== stride; ++ i ) {
42290
42291			result[ i ] = values[ offset + i ];
42292
42293		}
42294
42295		return result;
42296
42297	}
42298
42299	// Template methods for derived classes:
42300
42301	interpolate_( /* i1, t0, t, t1 */ ) {
42302
42303		throw new Error( 'call to abstract method' );
42304		// implementations shall return this.resultBuffer
42305
42306	}
42307
42308	intervalChanged_( /* i1, t0, t1 */ ) {
42309
42310		// empty
42311
42312	}
42313
42314}
42315
42316/**
42317 * Fast and simple cubic spline interpolant.
42318 *
42319 * It was derived from a Hermitian construction setting the first derivative
42320 * at each sample position to the linear slope between neighboring positions
42321 * over their parameter interval.
42322 */
42323
42324class CubicInterpolant extends Interpolant {
42325
42326	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42327
42328		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42329
42330		this._weightPrev = - 0;
42331		this._offsetPrev = - 0;
42332		this._weightNext = - 0;
42333		this._offsetNext = - 0;
42334
42335		this.DefaultSettings_ = {
42336
42337			endingStart: ZeroCurvatureEnding,
42338			endingEnd: ZeroCurvatureEnding
42339
42340		};
42341
42342	}
42343
42344	intervalChanged_( i1, t0, t1 ) {
42345
42346		const pp = this.parameterPositions;
42347		let iPrev = i1 - 2,
42348			iNext = i1 + 1,
42349
42350			tPrev = pp[ iPrev ],
42351			tNext = pp[ iNext ];
42352
42353		if ( tPrev === undefined ) {
42354
42355			switch ( this.getSettings_().endingStart ) {
42356
42357				case ZeroSlopeEnding:
42358
42359					// f'(t0) = 0
42360					iPrev = i1;
42361					tPrev = 2 * t0 - t1;
42362
42363					break;
42364
42365				case WrapAroundEnding:
42366
42367					// use the other end of the curve
42368					iPrev = pp.length - 2;
42369					tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
42370
42371					break;
42372
42373				default: // ZeroCurvatureEnding
42374
42375					// f''(t0) = 0 a.k.a. Natural Spline
42376					iPrev = i1;
42377					tPrev = t1;
42378
42379			}
42380
42381		}
42382
42383		if ( tNext === undefined ) {
42384
42385			switch ( this.getSettings_().endingEnd ) {
42386
42387				case ZeroSlopeEnding:
42388
42389					// f'(tN) = 0
42390					iNext = i1;
42391					tNext = 2 * t1 - t0;
42392
42393					break;
42394
42395				case WrapAroundEnding:
42396
42397					// use the other end of the curve
42398					iNext = 1;
42399					tNext = t1 + pp[ 1 ] - pp[ 0 ];
42400
42401					break;
42402
42403				default: // ZeroCurvatureEnding
42404
42405					// f''(tN) = 0, a.k.a. Natural Spline
42406					iNext = i1 - 1;
42407					tNext = t0;
42408
42409			}
42410
42411		}
42412
42413		const halfDt = ( t1 - t0 ) * 0.5,
42414			stride = this.valueSize;
42415
42416		this._weightPrev = halfDt / ( t0 - tPrev );
42417		this._weightNext = halfDt / ( tNext - t1 );
42418		this._offsetPrev = iPrev * stride;
42419		this._offsetNext = iNext * stride;
42420
42421	}
42422
42423	interpolate_( i1, t0, t, t1 ) {
42424
42425		const result = this.resultBuffer,
42426			values = this.sampleValues,
42427			stride = this.valueSize,
42428
42429			o1 = i1 * stride,		o0 = o1 - stride,
42430			oP = this._offsetPrev, 	oN = this._offsetNext,
42431			wP = this._weightPrev,	wN = this._weightNext,
42432
42433			p = ( t - t0 ) / ( t1 - t0 ),
42434			pp = p * p,
42435			ppp = pp * p;
42436
42437		// evaluate polynomials
42438
42439		const sP = - wP * ppp + 2 * wP * pp - wP * p;
42440		const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;
42441		const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
42442		const sN = wN * ppp - wN * pp;
42443
42444		// combine data linearly
42445
42446		for ( let i = 0; i !== stride; ++ i ) {
42447
42448			result[ i ] =
42449					sP * values[ oP + i ] +
42450					s0 * values[ o0 + i ] +
42451					s1 * values[ o1 + i ] +
42452					sN * values[ oN + i ];
42453
42454		}
42455
42456		return result;
42457
42458	}
42459
42460}
42461
42462class LinearInterpolant extends Interpolant {
42463
42464	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42465
42466		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42467
42468	}
42469
42470	interpolate_( i1, t0, t, t1 ) {
42471
42472		const result = this.resultBuffer,
42473			values = this.sampleValues,
42474			stride = this.valueSize,
42475
42476			offset1 = i1 * stride,
42477			offset0 = offset1 - stride,
42478
42479			weight1 = ( t - t0 ) / ( t1 - t0 ),
42480			weight0 = 1 - weight1;
42481
42482		for ( let i = 0; i !== stride; ++ i ) {
42483
42484			result[ i ] =
42485					values[ offset0 + i ] * weight0 +
42486					values[ offset1 + i ] * weight1;
42487
42488		}
42489
42490		return result;
42491
42492	}
42493
42494}
42495
42496/**
42497 *
42498 * Interpolant that evaluates to the sample value at the position preceding
42499 * the parameter.
42500 */
42501
42502class DiscreteInterpolant extends Interpolant {
42503
42504	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42505
42506		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42507
42508	}
42509
42510	interpolate_( i1 /*, t0, t, t1 */ ) {
42511
42512		return this.copySampleValue_( i1 - 1 );
42513
42514	}
42515
42516}
42517
42518class KeyframeTrack {
42519
42520	constructor( name, times, values, interpolation ) {
42521
42522		if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
42523		if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 22,519 bytes, lines 42523-43731
42523ame );
42524
42525		this.name = name;
42526
42527		this.times = convertArray( times, this.TimeBufferType );
42528		this.values = convertArray( values, this.ValueBufferType );
42529
42530		this.setInterpolation( interpolation || this.DefaultInterpolation );
42531
42532	}
42533
42534	// Serialization (in static context, because of constructor invocation
42535	// and automatic invocation of .toJSON):
42536
42537	static toJSON( track ) {
42538
42539		const trackType = track.constructor;
42540
42541		let json;
42542
42543		// derived classes can define a static toJSON method
42544		if ( trackType.toJSON !== this.toJSON ) {
42545
42546			json = trackType.toJSON( track );
42547
42548		} else {
42549
42550			// by default, we assume the data can be serialized as-is
42551			json = {
42552
42553				'name': track.name,
42554				'times': convertArray( track.times, Array ),
42555				'values': convertArray( track.values, Array )
42556
42557			};
42558
42559			const interpolation = track.getInterpolation();
42560
42561			if ( interpolation !== track.DefaultInterpolation ) {
42562
42563				json.interpolation = interpolation;
42564
42565			}
42566
42567		}
42568
42569		json.type = track.ValueTypeName; // mandatory
42570
42571		return json;
42572
42573	}
42574
42575	InterpolantFactoryMethodDiscrete( result ) {
42576
42577		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
42578
42579	}
42580
42581	InterpolantFactoryMethodLinear( result ) {
42582
42583		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
42584
42585	}
42586
42587	InterpolantFactoryMethodSmooth( result ) {
42588
42589		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
42590
42591	}
42592
42593	setInterpolation( interpolation ) {
42594
42595		let factoryMethod;
42596
42597		switch ( interpolation ) {
42598
42599			case InterpolateDiscrete:
42600
42601				factoryMethod = this.InterpolantFactoryMethodDiscrete;
42602
42603				break;
42604
42605			case InterpolateLinear:
42606
42607				factoryMethod = this.InterpolantFactoryMethodLinear;
42608
42609				break;
42610
42611			case InterpolateSmooth:
42612
42613				factoryMethod = this.InterpolantFactoryMethodSmooth;
42614
42615				break;
42616
42617		}
42618
42619		if ( factoryMethod === undefined ) {
42620
42621			const message = 'unsupported interpolation for ' +
42622				this.ValueTypeName + ' keyframe track named ' + this.name;
42623
42624			if ( this.createInterpolant === undefined ) {
42625
42626				// fall back to default, unless the default itself is messed up
42627				if ( interpolation !== this.DefaultInterpolation ) {
42628
42629					this.setInterpolation( this.DefaultInterpolation );
42630
42631				} else {
42632
42633					throw new Error( message ); // fatal, in this case
42634
42635				}
42636
42637			}
42638
42639			console.warn( 'THREE.KeyframeTrack:', message );
42640			return this;
42641
42642		}
42643
42644		this.createInterpolant = factoryMethod;
42645
42646		return this;
42647
42648	}
42649
42650	getInterpolation() {
42651
42652		switch ( this.createInterpolant ) {
42653
42654			case this.InterpolantFactoryMethodDiscrete:
42655
42656				return InterpolateDiscrete;
42657
42658			case this.InterpolantFactoryMethodLinear:
42659
42660				return InterpolateLinear;
42661
42662			case this.InterpolantFactoryMethodSmooth:
42663
42664				return InterpolateSmooth;
42665
42666		}
42667
42668	}
42669
42670	getValueSize() {
42671
42672		return this.values.length / this.times.length;
42673
42674	}
42675
42676	// move all keyframes either forwards or backwards in time
42677	shift( timeOffset ) {
42678
42679		if ( timeOffset !== 0.0 ) {
42680
42681			const times = this.times;
42682
42683			for ( let i = 0, n = times.length; i !== n; ++ i ) {
42684
42685				times[ i ] += timeOffset;
42686
42687			}
42688
42689		}
42690
42691		return this;
42692
42693	}
42694
42695	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
42696	scale( timeScale ) {
42697
42698		if ( timeScale !== 1.0 ) {
42699
42700			const times = this.times;
42701
42702			for ( let i = 0, n = times.length; i !== n; ++ i ) {
42703
42704				times[ i ] *= timeScale;
42705
42706			}
42707
42708		}
42709
42710		return this;
42711
42712	}
42713
42714	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
42715	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
42716	trim( startTime, endTime ) {
42717
42718		const times = this.times,
42719			nKeys = times.length;
42720
42721		let from = 0,
42722			to = nKeys - 1;
42723
42724		while ( from !== nKeys && times[ from ] < startTime ) {
42725
42726			++ from;
42727
42728		}
42729
42730		while ( to !== - 1 && times[ to ] > endTime ) {
42731
42732			-- to;
42733
42734		}
42735
42736		++ to; // inclusive -> exclusive bound
42737
42738		if ( from !== 0 || to !== nKeys ) {
42739
42740			// empty tracks are forbidden, so keep at least one keyframe
42741			if ( from >= to ) {
42742
42743				to = Math.max( to, 1 );
42744				from = to - 1;
42745
42746			}
42747
42748			const stride = this.getValueSize();
42749			this.times = times.slice( from, to );
42750			this.values = this.values.slice( from * stride, to * stride );
42751
42752		}
42753
42754		return this;
42755
42756	}
42757
42758	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
42759	validate() {
42760
42761		let valid = true;
42762
42763		const valueSize = this.getValueSize();
42764		if ( valueSize - Math.floor( valueSize ) !== 0 ) {
42765
42766			console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
42767			valid = false;
42768
42769		}
42770
42771		const times = this.times,
42772			values = this.values,
42773
42774			nKeys = times.length;
42775
42776		if ( nKeys === 0 ) {
42777
42778			console.error( 'THREE.KeyframeTrack: Track is empty.', this );
42779			valid = false;
42780
42781		}
42782
42783		let prevTime = null;
42784
42785		for ( let i = 0; i !== nKeys; i ++ ) {
42786
42787			const currTime = times[ i ];
42788
42789			if ( typeof currTime === 'number' && isNaN( currTime ) ) {
42790
42791				console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
42792				valid = false;
42793				break;
42794
42795			}
42796
42797			if ( prevTime !== null && prevTime > currTime ) {
42798
42799				console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
42800				valid = false;
42801				break;
42802
42803			}
42804
42805			prevTime = currTime;
42806
42807		}
42808
42809		if ( values !== undefined ) {
42810
42811			if ( isTypedArray( values ) ) {
42812
42813				for ( let i = 0, n = values.length; i !== n; ++ i ) {
42814
42815					const value = values[ i ];
42816
42817					if ( isNaN( value ) ) {
42818
42819						console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
42820						valid = false;
42821						break;
42822
42823					}
42824
42825				}
42826
42827			}
42828
42829		}
42830
42831		return valid;
42832
42833	}
42834
42835	// removes equivalent sequential keys as common in morph target sequences
42836	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
42837	optimize() {
42838
42839		// times or values may be shared with other tracks, so overwriting is unsafe
42840		const times = this.times.slice(),
42841			values = this.values.slice(),
42842			stride = this.getValueSize(),
42843
42844			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
42845
42846			lastIndex = times.length - 1;
42847
42848		let writeIndex = 1;
42849
42850		for ( let i = 1; i < lastIndex; ++ i ) {
42851
42852			let keep = false;
42853
42854			const time = times[ i ];
42855			const timeNext = times[ i + 1 ];
42856
42857			// remove adjacent keyframes scheduled at the same time
42858
42859			if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
42860
42861				if ( ! smoothInterpolation ) {
42862
42863					// remove unnecessary keyframes same as their neighbors
42864
42865					const offset = i * stride,
42866						offsetP = offset - stride,
42867						offsetN = offset + stride;
42868
42869					for ( let j = 0; j !== stride; ++ j ) {
42870
42871						const value = values[ offset + j ];
42872
42873						if ( value !== values[ offsetP + j ] ||
42874							value !== values[ offsetN + j ] ) {
42875
42876							keep = true;
42877							break;
42878
42879						}
42880
42881					}
42882
42883				} else {
42884
42885					keep = true;
42886
42887				}
42888
42889			}
42890
42891			// in-place compaction
42892
42893			if ( keep ) {
42894
42895				if ( i !== writeIndex ) {
42896
42897					times[ writeIndex ] = times[ i ];
42898
42899					const readOffset = i * stride,
42900						writeOffset = writeIndex * stride;
42901
42902					for ( let j = 0; j !== stride; ++ j ) {
42903
42904						values[ writeOffset + j ] = values[ readOffset + j ];
42905
42906					}
42907
42908				}
42909
42910				++ writeIndex;
42911
42912			}
42913
42914		}
42915
42916		// flush last keyframe (compaction looks ahead)
42917
42918		if ( lastIndex > 0 ) {
42919
42920			times[ writeIndex ] = times[ lastIndex ];
42921
42922			for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
42923
42924				values[ writeOffset + j ] = values[ readOffset + j ];
42925
42926			}
42927
42928			++ writeIndex;
42929
42930		}
42931
42932		if ( writeIndex !== times.length ) {
42933
42934			this.times = times.slice( 0, writeIndex );
42935			this.values = values.slice( 0, writeIndex * stride );
42936
42937		} else {
42938
42939			this.times = times;
42940			this.values = values;
42941
42942		}
42943
42944		return this;
42945
42946	}
42947
42948	clone() {
42949
42950		const times = this.times.slice();
42951		const values = this.values.slice();
42952
42953		const TypedKeyframeTrack = this.constructor;
42954		const track = new TypedKeyframeTrack( this.name, times, values );
42955
42956		// Interpolant argument to constructor is not saved, so copy the factory method directly.
42957		track.createInterpolant = this.createInterpolant;
42958
42959		return track;
42960
42961	}
42962
42963}
42964
42965KeyframeTrack.prototype.TimeBufferType = Float32Array;
42966KeyframeTrack.prototype.ValueBufferType = Float32Array;
42967KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42968
42969/**
42970 * A Track of Boolean keyframe values.
42971 */
42972class BooleanKeyframeTrack extends KeyframeTrack {
42973
42974	// No interpolation parameter because only InterpolateDiscrete is valid.
42975	constructor( name, times, values ) {
42976
42977		super( name, times, values );
42978
42979	}
42980
42981}
42982
42983BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
42984BooleanKeyframeTrack.prototype.ValueBufferType = Array;
42985BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42986BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
42987BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42988
42989/**
42990 * A Track of keyframe values that represent color.
42991 */
42992class ColorKeyframeTrack extends KeyframeTrack {}
42993
42994ColorKeyframeTrack.prototype.ValueTypeName = 'color';
42995
42996/**
42997 * A Track of numeric keyframe values.
42998 */
42999class NumberKeyframeTrack extends KeyframeTrack {}
43000
43001NumberKeyframeTrack.prototype.ValueTypeName = 'number';
43002
43003/**
43004 * Spherical linear unit quaternion interpolant.
43005 */
43006
43007class QuaternionLinearInterpolant extends Interpolant {
43008
43009	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
43010
43011		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
43012
43013	}
43014
43015	interpolate_( i1, t0, t, t1 ) {
43016
43017		const result = this.resultBuffer,
43018			values = this.sampleValues,
43019			stride = this.valueSize,
43020
43021			alpha = ( t - t0 ) / ( t1 - t0 );
43022
43023		let offset = i1 * stride;
43024
43025		for ( let end = offset + stride; offset !== end; offset += 4 ) {
43026
43027			Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
43028
43029		}
43030
43031		return result;
43032
43033	}
43034
43035}
43036
43037/**
43038 * A Track of quaternion keyframe values.
43039 */
43040class QuaternionKeyframeTrack extends KeyframeTrack {
43041
43042	InterpolantFactoryMethodLinear( result ) {
43043
43044		return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
43045
43046	}
43047
43048}
43049
43050QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
43051// ValueBufferType is inherited
43052// DefaultInterpolation is inherited;
43053QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
43054
43055/**
43056 * A Track that interpolates Strings
43057 */
43058class StringKeyframeTrack extends KeyframeTrack {
43059
43060	// No interpolation parameter because only InterpolateDiscrete is valid.
43061	constructor( name, times, values ) {
43062
43063		super( name, times, values );
43064
43065	}
43066
43067}
43068
43069StringKeyframeTrack.prototype.ValueTypeName = 'string';
43070StringKeyframeTrack.prototype.ValueBufferType = Array;
43071StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
43072StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
43073StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
43074
43075/**
43076 * A Track of vectored keyframe values.
43077 */
43078class VectorKeyframeTrack extends KeyframeTrack {}
43079
43080VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
43081
43082class AnimationClip {
43083
43084	constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) {
43085
43086		this.name = name;
43087		this.tracks = tracks;
43088		this.duration = duration;
43089		this.blendMode = blendMode;
43090
43091		this.uuid = generateUUID();
43092
43093		// this means it should figure out its duration by scanning the tracks
43094		if ( this.duration < 0 ) {
43095
43096			this.resetDuration();
43097
43098		}
43099
43100	}
43101
43102
43103	static parse( json ) {
43104
43105		const tracks = [],
43106			jsonTracks = json.tracks,
43107			frameTime = 1.0 / ( json.fps || 1.0 );
43108
43109		for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
43110
43111			tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
43112
43113		}
43114
43115		const clip = new this( json.name, json.duration, tracks, json.blendMode );
43116		clip.uuid = json.uuid;
43117
43118		return clip;
43119
43120	}
43121
43122	static toJSON( clip ) {
43123
43124		const tracks = [],
43125			clipTracks = clip.tracks;
43126
43127		const json = {
43128
43129			'name': clip.name,
43130			'duration': clip.duration,
43131			'tracks': tracks,
43132			'uuid': clip.uuid,
43133			'blendMode': clip.blendMode
43134
43135		};
43136
43137		for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
43138
43139			tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
43140
43141		}
43142
43143		return json;
43144
43145	}
43146
43147	static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
43148
43149		const numMorphTargets = morphTargetSequence.length;
43150		const tracks = [];
43151
43152		for ( let i = 0; i < numMorphTargets; i ++ ) {
43153
43154			let times = [];
43155			let values = [];
43156
43157			times.push(
43158				( i + numMorphTargets - 1 ) % numMorphTargets,
43159				i,
43160				( i + 1 ) % numMorphTargets );
43161
43162			values.push( 0, 1, 0 );
43163
43164			const order = getKeyframeOrder( times );
43165			times = sortedArray( times, 1, order );
43166			values = sortedArray( values, 1, order );
43167
43168			// if there is a key at the first frame, duplicate it as the
43169			// last frame as well for perfect loop.
43170			if ( ! noLoop && times[ 0 ] === 0 ) {
43171
43172				times.push( numMorphTargets );
43173				values.push( values[ 0 ] );
43174
43175			}
43176
43177			tracks.push(
43178				new NumberKeyframeTrack(
43179					'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
43180					times, values
43181				).scale( 1.0 / fps ) );
43182
43183		}
43184
43185		return new this( name, - 1, tracks );
43186
43187	}
43188
43189	static findByName( objectOrClipArray, name ) {
43190
43191		let clipArray = objectOrClipArray;
43192
43193		if ( ! Array.isArray( objectOrClipArray ) ) {
43194
43195			const o = objectOrClipArray;
43196			clipArray = o.geometry && o.geometry.animations || o.animations;
43197
43198		}
43199
43200		for ( let i = 0; i < clipArray.length; i ++ ) {
43201
43202			if ( clipArray[ i ].name === name ) {
43203
43204				return clipArray[ i ];
43205
43206			}
43207
43208		}
43209
43210		return null;
43211
43212	}
43213
43214	static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
43215
43216		const animationToMorphTargets = {};
43217
43218		// tested with https://regex101.com/ on trick sequences
43219		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
43220		const pattern = /^([\w-]*?)([\d]+)$/;
43221
43222		// sort morph target names into animation groups based
43223		// patterns like Walk_001, Walk_002, Run_001, Run_002
43224		for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
43225
43226			const morphTarget = morphTargets[ i ];
43227			const parts = morphTarget.name.match( pattern );
43228
43229			if ( parts && parts.length > 1 ) {
43230
43231				const name = parts[ 1 ];
43232
43233				let animationMorphTargets = animationToMorphTargets[ name ];
43234
43235				if ( ! animationMorphTargets ) {
43236
43237					animationToMorphTargets[ name ] = animationMorphTargets = [];
43238
43239				}
43240
43241				animationMorphTargets.push( morphTarget );
43242
43243			}
43244
43245		}
43246
43247		const clips = [];
43248
43249		for ( const name in animationToMorphTargets ) {
43250
43251			clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
43252
43253		}
43254
43255		return clips;
43256
43257	}
43258
43259	// parse the animation.hierarchy format
43260	static parseAnimation( animation, bones ) {
43261
43262		if ( ! animation ) {
43263
43264			console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );
43265			return null;
43266
43267		}
43268
43269		const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
43270
43271			// only return track if there are actually keys.
43272			if ( animationKeys.length !== 0 ) {
43273
43274				const times = [];
43275				const values = [];
43276
43277				flattenJSON( animationKeys, times, values, propertyName );
43278
43279				// empty keys are filtered out, so check again
43280				if ( times.length !== 0 ) {
43281
43282					destTracks.push( new trackType( trackName, times, values ) );
43283
43284				}
43285
43286			}
43287
43288		};
43289
43290		const tracks = [];
43291
43292		const clipName = animation.name || 'default';
43293		const fps = animation.fps || 30;
43294		const blendMode = animation.blendMode;
43295
43296		// automatic length determination in AnimationClip.
43297		let duration = animation.length || - 1;
43298
43299		const hierarchyTracks = animation.hierarchy || [];
43300
43301		for ( let h = 0; h < hierarchyTracks.length; h ++ ) {
43302
43303			const animationKeys = hierarchyTracks[ h ].keys;
43304
43305			// skip empty tracks
43306			if ( ! animationKeys || animationKeys.length === 0 ) continue;
43307
43308			// process morph targets
43309			if ( animationKeys[ 0 ].morphTargets ) {
43310
43311				// figure out all morph targets used in this track
43312				const morphTargetNames = {};
43313
43314				let k;
43315
43316				for ( k = 0; k < animationKeys.length; k ++ ) {
43317
43318					if ( animationKeys[ k ].morphTargets ) {
43319
43320						for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {
43321
43322							morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;
43323
43324						}
43325
43326					}
43327
43328				}
43329
43330				// create a track for each morph target with all zero
43331				// morphTargetInfluences except for the keys in which
43332				// the morphTarget is named.
43333				for ( const morphTargetName in morphTargetNames ) {
43334
43335					const times = [];
43336					const values = [];
43337
43338					for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {
43339
43340						const animationKey = animationKeys[ k ];
43341
43342						times.push( animationKey.time );
43343						values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
43344
43345					}
43346
43347					tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );
43348
43349				}
43350
43351				duration = morphTargetNames.length * fps;
43352
43353			} else {
43354
43355				// ...assume skeletal animation
43356
43357				const boneName = '.bones[' + bones[ h ].name + ']';
43358
43359				addNonemptyTrack(
43360					VectorKeyframeTrack, boneName + '.position',
43361					animationKeys, 'pos', tracks );
43362
43363				addNonemptyTrack(
43364					QuaternionKeyframeTrack, boneName + '.quaternion',
43365					animationKeys, 'rot', tracks );
43366
43367				addNonemptyTrack(
43368					VectorKeyframeTrack, boneName + '.scale',
43369					animationKeys, 'scl', tracks );
43370
43371			}
43372
43373		}
43374
43375		if ( tracks.length === 0 ) {
43376
43377			return null;
43378
43379		}
43380
43381		const clip = new this( clipName, duration, tracks, blendMode );
43382
43383		return clip;
43384
43385	}
43386
43387	resetDuration() {
43388
43389		const tracks = this.tracks;
43390		let duration = 0;
43391
43392		for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
43393
43394			const track = this.tracks[ i ];
43395
43396			duration = Math.max( duration, track.times[ track.times.length - 1 ] );
43397
43398		}
43399
43400		this.duration = duration;
43401
43402		return this;
43403
43404	}
43405
43406	trim() {
43407
43408		for ( let i = 0; i < this.tracks.length; i ++ ) {
43409
43410			this.tracks[ i ].trim( 0, this.duration );
43411
43412		}
43413
43414		return this;
43415
43416	}
43417
43418	validate() {
43419
43420		let valid = true;
43421
43422		for ( let i = 0; i < this.tracks.length; i ++ ) {
43423
43424			valid = valid && this.tracks[ i ].validate();
43425
43426		}
43427
43428		return valid;
43429
43430	}
43431
43432	optimize() {
43433
43434		for ( let i = 0; i < this.tracks.length; i ++ ) {
43435
43436			this.tracks[ i ].optimize();
43437
43438		}
43439
43440		return this;
43441
43442	}
43443
43444	clone() {
43445
43446		const tracks = [];
43447
43448		for ( let i = 0; i < this.tracks.length; i ++ ) {
43449
43450			tracks.push( this.tracks[ i ].clone() );
43451
43452		}
43453
43454		return new this.constructor( this.name, this.duration, tracks, this.blendMode );
43455
43456	}
43457
43458	toJSON() {
43459
43460		return this.constructor.toJSON( this );
43461
43462	}
43463
43464}
43465
43466function getTrackTypeForValueTypeName( typeName ) {
43467
43468	switch ( typeName.toLowerCase() ) {
43469
43470		case 'scalar':
43471		case 'double':
43472		case 'float':
43473		case 'number':
43474		case 'integer':
43475
43476			return NumberKeyframeTrack;
43477
43478		case 'vector':
43479		case 'vector2':
43480		case 'vector3':
43481		case 'vector4':
43482
43483			return VectorKeyframeTrack;
43484
43485		case 'color':
43486
43487			return ColorKeyframeTrack;
43488
43489		case 'quaternion':
43490
43491			return QuaternionKeyframeTrack;
43492
43493		case 'bool':
43494		case 'boolean':
43495
43496			return BooleanKeyframeTrack;
43497
43498		case 'string':
43499
43500			return StringKeyframeTrack;
43501
43502	}
43503
43504	throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
43505
43506}
43507
43508function parseKeyframeTrack( json ) {
43509
43510	if ( json.type === undefined ) {
43511
43512		throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
43513
43514	}
43515
43516	const trackType = getTrackTypeForValueTypeName( json.type );
43517
43518	if ( json.times === undefined ) {
43519
43520		const times = [], values = [];
43521
43522		flattenJSON( json.keys, times, values, 'value' );
43523
43524		json.times = times;
43525		json.values = values;
43526
43527	}
43528
43529	// derived classes can define a static parse method
43530	if ( trackType.parse !== undefined ) {
43531
43532		return trackType.parse( json );
43533
43534	} else {
43535
43536		// by default, we assume a constructor compatible with the base
43537		return new trackType( json.name, json.times, json.values, json.interpolation );
43538
43539	}
43540
43541}
43542
43543const Cache = {
43544
43545	enabled: false,
43546
43547	files: {},
43548
43549	add: function ( key, file ) {
43550
43551		if ( this.enabled === false ) return;
43552
43553		// console.log( 'THREE.Cache', 'Adding key:', key );
43554
43555		this.files[ key ] = file;
43556
43557	},
43558
43559	get: function ( key ) {
43560
43561		if ( this.enabled === false ) return;
43562
43563		// console.log( 'THREE.Cache', 'Checking key:', key );
43564
43565		return this.files[ key ];
43566
43567	},
43568
43569	remove: function ( key ) {
43570
43571		delete this.files[ key ];
43572
43573	},
43574
43575	clear: function () {
43576
43577		this.files = {};
43578
43579	}
43580
43581};
43582
43583class LoadingManager {
43584
43585	constructor( onLoad, onProgress, onError ) {
43586
43587		const scope = this;
43588
43589		let isLoading = false;
43590		let itemsLoaded = 0;
43591		let itemsTotal = 0;
43592		let urlModifier = undefined;
43593		const handlers = [];
43594
43595		// Refer to #5689 for the reason why we don't set .onStart
43596		// in the constructor
43597
43598		this.onStart = undefined;
43599		this.onLoad = onLoad;
43600		this.onProgress = onProgress;
43601		this.onError = onError;
43602
43603		this.itemStart = function ( url ) {
43604
43605			itemsTotal ++;
43606
43607			if ( isLoading === false ) {
43608
43609				if ( scope.onStart !== undefined ) {
43610
43611					scope.onStart( url, itemsLoaded, itemsTotal );
43612
43613				}
43614
43615			}
43616
43617			isLoading = true;
43618
43619		};
43620
43621		this.itemEnd = function ( url ) {
43622
43623			itemsLoaded ++;
43624
43625			if ( scope.onProgress !== undefined ) {
43626
43627				scope.onProgress( url, itemsLoaded, itemsTotal );
43628
43629			}
43630
43631			if ( itemsLoaded === itemsTotal ) {
43632
43633				isLoading = false;
43634
43635				if ( scope.onLoad !== undefined ) {
43636
43637					scope.onLoad();
43638
43639				}
43640
43641			}
43642
43643		};
43644
43645		this.itemError = function ( url ) {
43646
43647			if ( scope.onError !== undefined ) {
43648
43649				scope.onError( url );
43650
43651			}
43652
43653		};
43654
43655		this.resolveURL = function ( url ) {
43656
43657			if ( urlModifier ) {
43658
43659				return urlModifier( url );
43660
43661			}
43662
43663			return url;
43664
43665		};
43666
43667		this.setURLModifier = function ( transform ) {
43668
43669			urlModifier = transform;
43670
43671			return this;
43672
43673		};
43674
43675		this.addHandler = function ( regex, loader ) {
43676
43677			handlers.push( regex, loader );
43678
43679			return this;
43680
43681		};
43682
43683		this.removeHandler = function ( regex ) {
43684
43685			const index = handlers.indexOf( regex );
43686
43687			if ( index !== - 1 ) {
43688
43689				handlers.splice( index, 2 );
43690
43691			}
43692
43693			return this;
43694
43695		};
43696
43697		this.getHandler = function ( file ) {
43698
43699			for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
43700
43701				const regex = handlers[ i ];
43702				const loader = handlers[ i + 1 ];
43703
43704				if ( regex.global ) regex.lastIndex = 0; // see #17920
43705
43706				if ( regex.test( file ) ) {
43707
43708					return loader;
43709
43710				}
43711
43712			}
43713
43714			return null;
43715
43716		};
43717
43718	}
43719
43720}
43721
43722const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager();
43723
43724class Loader {
43725
43726	constructor( manager ) {
43727
43728		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
43729
43730		this.crossOrigin = 'anonymous';
43731		this.withCredentials = false;
vendor: 12,944 bytes, lines 43732-44461
43732		this.path = '';
43733		this.resourcePath = '';
43734		this.requestHeader = {};
43735
43736	}
43737
43738	load( /* url, onLoad, onProgress, onError */ ) {}
43739
43740	loadAsync( url, onProgress ) {
43741
43742		const scope = this;
43743
43744		return new Promise( function ( resolve, reject ) {
43745
43746			scope.load( url, resolve, onProgress, reject );
43747
43748		} );
43749
43750	}
43751
43752	parse( /* data */ ) {}
43753
43754	setCrossOrigin( crossOrigin ) {
43755
43756		this.crossOrigin = crossOrigin;
43757		return this;
43758
43759	}
43760
43761	setWithCredentials( value ) {
43762
43763		this.withCredentials = value;
43764		return this;
43765
43766	}
43767
43768	setPath( path ) {
43769
43770		this.path = path;
43771		return this;
43772
43773	}
43774
43775	setResourcePath( resourcePath ) {
43776
43777		this.resourcePath = resourcePath;
43778		return this;
43779
43780	}
43781
43782	setRequestHeader( requestHeader ) {
43783
43784		this.requestHeader = requestHeader;
43785		return this;
43786
43787	}
43788
43789}
43790
43791Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT';
43792
43793const loading = {};
43794
43795class HttpError extends Error {
43796
43797	constructor( message, response ) {
43798
43799		super( message );
43800		this.response = response;
43801
43802	}
43803
43804}
43805
43806class FileLoader extends Loader {
43807
43808	constructor( manager ) {
43809
43810		super( manager );
43811
43812	}
43813
43814	load( url, onLoad, onProgress, onError ) {
43815
43816		if ( url === undefined ) url = '';
43817
43818		if ( this.path !== undefined ) url = this.path + url;
43819
43820		url = this.manager.resolveURL( url );
43821
43822		const cached = Cache.get( url );
43823
43824		if ( cached !== undefined ) {
43825
43826			this.manager.itemStart( url );
43827
43828			setTimeout( () => {
43829
43830				if ( onLoad ) onLoad( cached );
43831
43832				this.manager.itemEnd( url );
43833
43834			}, 0 );
43835
43836			return cached;
43837
43838		}
43839
43840		// Check if request is duplicate
43841
43842		if ( loading[ url ] !== undefined ) {
43843
43844			loading[ url ].push( {
43845
43846				onLoad: onLoad,
43847				onProgress: onProgress,
43848				onError: onError
43849
43850			} );
43851
43852			return;
43853
43854		}
43855
43856		// Initialise array for duplicate requests
43857		loading[ url ] = [];
43858
43859		loading[ url ].push( {
43860			onLoad: onLoad,
43861			onProgress: onProgress,
43862			onError: onError,
43863		} );
43864
43865		// create request
43866		const req = new Request( url, {
43867			headers: new Headers( this.requestHeader ),
43868			credentials: this.withCredentials ? 'include' : 'same-origin',
43869			// An abort controller could be added within a future PR
43870		} );
43871
43872		// record states ( avoid data race )
43873		const mimeType = this.mimeType;
43874		const responseType = this.responseType;
43875
43876		// start the fetch
43877		fetch( req )
43878			.then( response => {
43879
43880				if ( response.status === 200 || response.status === 0 ) {
43881
43882					// Some browsers return HTTP Status 0 when using non-http protocol
43883					// e.g. 'file://' or 'data://'. Handle as success.
43884
43885					if ( response.status === 0 ) {
43886
43887						console.warn( 'THREE.FileLoader: HTTP Status 0 received.' );
43888
43889					}
43890
43891					// Workaround: Checking if response.body === undefined for Alipay browser #23548
43892
43893					if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) {
43894
43895						return response;
43896
43897					}
43898
43899					const callbacks = loading[ url ];
43900					const reader = response.body.getReader();
43901
43902					// Nginx needs X-File-Size check
43903					// https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content
43904					const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' );
43905					const total = contentLength ? parseInt( contentLength ) : 0;
43906					const lengthComputable = total !== 0;
43907					let loaded = 0;
43908
43909					// periodically read data into the new stream tracking while download progress
43910					const stream = new ReadableStream( {
43911						start( controller ) {
43912
43913							readData();
43914
43915							function readData() {
43916
43917								reader.read().then( ( { done, value } ) => {
43918
43919									if ( done ) {
43920
43921										controller.close();
43922
43923									} else {
43924
43925										loaded += value.byteLength;
43926
43927										const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } );
43928										for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
43929
43930											const callback = callbacks[ i ];
43931											if ( callback.onProgress ) callback.onProgress( event );
43932
43933										}
43934
43935										controller.enqueue( value );
43936										readData();
43937
43938									}
43939
43940								}, ( e ) => {
43941
43942									controller.error( e );
43943
43944								} );
43945
43946							}
43947
43948						}
43949
43950					} );
43951
43952					return new Response( stream );
43953
43954				} else {
43955
43956					throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response );
43957
43958				}
43959
43960			} )
43961			.then( response => {
43962
43963				switch ( responseType ) {
43964
43965					case 'arraybuffer':
43966
43967						return response.arrayBuffer();
43968
43969					case 'blob':
43970
43971						return response.blob();
43972
43973					case 'document':
43974
43975						return response.text()
43976							.then( text => {
43977
43978								const parser = new DOMParser();
43979								return parser.parseFromString( text, mimeType );
43980
43981							} );
43982
43983					case 'json':
43984
43985						return response.json();
43986
43987					default:
43988
43989						if ( mimeType === undefined ) {
43990
43991							return response.text();
43992
43993						} else {
43994
43995							// sniff encoding
43996							const re = /charset="?([^;"\s]*)"?/i;
43997							const exec = re.exec( mimeType );
43998							const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined;
43999							const decoder = new TextDecoder( label );
44000							return response.arrayBuffer().then( ab => decoder.decode( ab ) );
44001
44002						}
44003
44004				}
44005
44006			} )
44007			.then( data => {
44008
44009				// Add to cache only on HTTP success, so that we do not cache
44010				// error response bodies as proper responses to requests.
44011				Cache.add( url, data );
44012
44013				const callbacks = loading[ url ];
44014				delete loading[ url ];
44015
44016				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
44017
44018					const callback = callbacks[ i ];
44019					if ( callback.onLoad ) callback.onLoad( data );
44020
44021				}
44022
44023			} )
44024			.catch( err => {
44025
44026				// Abort errors and other errors are handled the same
44027
44028				const callbacks = loading[ url ];
44029
44030				if ( callbacks === undefined ) {
44031
44032					// When onLoad was called and url was deleted in `loading`
44033					this.manager.itemError( url );
44034					throw err;
44035
44036				}
44037
44038				delete loading[ url ];
44039
44040				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
44041
44042					const callback = callbacks[ i ];
44043					if ( callback.onError ) callback.onError( err );
44044
44045				}
44046
44047				this.manager.itemError( url );
44048
44049			} )
44050			.finally( () => {
44051
44052				this.manager.itemEnd( url );
44053
44054			} );
44055
44056		this.manager.itemStart( url );
44057
44058	}
44059
44060	setResponseType( value ) {
44061
44062		this.responseType = value;
44063		return this;
44064
44065	}
44066
44067	setMimeType( value ) {
44068
44069		this.mimeType = value;
44070		return this;
44071
44072	}
44073
44074}
44075
44076class AnimationLoader extends Loader {
44077
44078	constructor( manager ) {
44079
44080		super( manager );
44081
44082	}
44083
44084	load( url, onLoad, onProgress, onError ) {
44085
44086		const scope = this;
44087
44088		const loader = new FileLoader( this.manager );
44089		loader.setPath( this.path );
44090		loader.setRequestHeader( this.requestHeader );
44091		loader.setWithCredentials( this.withCredentials );
44092		loader.load( url, function ( text ) {
44093
44094			try {
44095
44096				onLoad( scope.parse( JSON.parse( text ) ) );
44097
44098			} catch ( e ) {
44099
44100				if ( onError ) {
44101
44102					onError( e );
44103
44104				} else {
44105
44106					console.error( e );
44107
44108				}
44109
44110				scope.manager.itemError( url );
44111
44112			}
44113
44114		}, onProgress, onError );
44115
44116	}
44117
44118	parse( json ) {
44119
44120		const animations = [];
44121
44122		for ( let i = 0; i < json.length; i ++ ) {
44123
44124			const clip = AnimationClip.parse( json[ i ] );
44125
44126			animations.push( clip );
44127
44128		}
44129
44130		return animations;
44131
44132	}
44133
44134}
44135
44136/**
44137 * Abstract Base class to block based textures loader (dds, pvr, ...)
44138 *
44139 * Sub classes have to implement the parse() method which will be used in load().
44140 */
44141
44142class CompressedTextureLoader extends Loader {
44143
44144	constructor( manager ) {
44145
44146		super( manager );
44147
44148	}
44149
44150	load( url, onLoad, onProgress, onError ) {
44151
44152		const scope = this;
44153
44154		const images = [];
44155
44156		const texture = new CompressedTexture();
44157
44158		const loader = new FileLoader( this.manager );
44159		loader.setPath( this.path );
44160		loader.setResponseType( 'arraybuffer' );
44161		loader.setRequestHeader( this.requestHeader );
44162		loader.setWithCredentials( scope.withCredentials );
44163
44164		let loaded = 0;
44165
44166		function loadTexture( i ) {
44167
44168			loader.load( url[ i ], function ( buffer ) {
44169
44170				const texDatas = scope.parse( buffer, true );
44171
44172				images[ i ] = {
44173					width: texDatas.width,
44174					height: texDatas.height,
44175					format: texDatas.format,
44176					mipmaps: texDatas.mipmaps
44177				};
44178
44179				loaded += 1;
44180
44181				if ( loaded === 6 ) {
44182
44183					if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
44184
44185					texture.image = images;
44186					texture.format = texDatas.format;
44187					texture.needsUpdate = true;
44188
44189					if ( onLoad ) onLoad( texture );
44190
44191				}
44192
44193			}, onProgress, onError );
44194
44195		}
44196
44197		if ( Array.isArray( url ) ) {
44198
44199			for ( let i = 0, il = url.length; i < il; ++ i ) {
44200
44201				loadTexture( i );
44202
44203			}
44204
44205		} else {
44206
44207			// compressed cubemap texture stored in a single DDS file
44208
44209			loader.load( url, function ( buffer ) {
44210
44211				const texDatas = scope.parse( buffer, true );
44212
44213				if ( texDatas.isCubemap ) {
44214
44215					const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
44216
44217					for ( let f = 0; f < faces; f ++ ) {
44218
44219						images[ f ] = { mipmaps: [] };
44220
44221						for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
44222
44223							images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
44224							images[ f ].format = texDatas.format;
44225							images[ f ].width = texDatas.width;
44226							images[ f ].height = texDatas.height;
44227
44228						}
44229
44230					}
44231
44232					texture.image = images;
44233
44234				} else {
44235
44236					texture.image.width = texDatas.width;
44237					texture.image.height = texDatas.height;
44238					texture.mipmaps = texDatas.mipmaps;
44239
44240				}
44241
44242				if ( texDatas.mipmapCount === 1 ) {
44243
44244					texture.minFilter = LinearFilter;
44245
44246				}
44247
44248				texture.format = texDatas.format;
44249				texture.needsUpdate = true;
44250
44251				if ( onLoad ) onLoad( texture );
44252
44253			}, onProgress, onError );
44254
44255		}
44256
44257		return texture;
44258
44259	}
44260
44261}
44262
44263class ImageLoader extends Loader {
44264
44265	constructor( manager ) {
44266
44267		super( manager );
44268
44269	}
44270
44271	load( url, onLoad, onProgress, onError ) {
44272
44273		if ( this.path !== undefined ) url = this.path + url;
44274
44275		url = this.manager.resolveURL( url );
44276
44277		const scope = this;
44278
44279		const cached = Cache.get( url );
44280
44281		if ( cached !== undefined ) {
44282
44283			scope.manager.itemStart( url );
44284
44285			setTimeout( function () {
44286
44287				if ( onLoad ) onLoad( cached );
44288
44289				scope.manager.itemEnd( url );
44290
44291			}, 0 );
44292
44293			return cached;
44294
44295		}
44296
44297		const image = createElementNS( 'img' );
44298
44299		function onImageLoad() {
44300
44301			removeEventListeners();
44302
44303			Cache.add( url, this );
44304
44305			if ( onLoad ) onLoad( this );
44306
44307			scope.manager.itemEnd( url );
44308
44309		}
44310
44311		function onImageError( event ) {
44312
44313			removeEventListeners();
44314
44315			if ( onError ) onError( event );
44316
44317			scope.manager.itemError( url );
44318			scope.manager.itemEnd( url );
44319
44320		}
44321
44322		function removeEventListeners() {
44323
44324			image.removeEventListener( 'load', onImageLoad, false );
44325			image.removeEventListener( 'error', onImageError, false );
44326
44327		}
44328
44329		image.addEventListener( 'load', onImageLoad, false );
44330		image.addEventListener( 'error', onImageError, false );
44331
44332		if ( url.slice( 0, 5 ) !== 'data:' ) {
44333
44334			if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
44335
44336		}
44337
44338		scope.manager.itemStart( url );
44339
44340		image.src = url;
44341
44342		return image;
44343
44344	}
44345
44346}
44347
44348class CubeTextureLoader extends Loader {
44349
44350	constructor( manager ) {
44351
44352		super( manager );
44353
44354	}
44355
44356	load( urls, onLoad, onProgress, onError ) {
44357
44358		const texture = new CubeTexture();
44359		texture.colorSpace = SRGBColorSpace;
44360
44361		const loader = new ImageLoader( this.manager );
44362		loader.setCrossOrigin( this.crossOrigin );
44363		loader.setPath( this.path );
44364
44365		let loaded = 0;
44366
44367		function loadTexture( i ) {
44368
44369			loader.load( urls[ i ], function ( image ) {
44370
44371				texture.images[ i ] = image;
44372
44373				loaded ++;
44374
44375				if ( loaded === 6 ) {
44376
44377					texture.needsUpdate = true;
44378
44379					if ( onLoad ) onLoad( texture );
44380
44381				}
44382
44383			}, undefined, onError );
44384
44385		}
44386
44387		for ( let i = 0; i < urls.length; ++ i ) {
44388
44389			loadTexture( i );
44390
44391		}
44392
44393		return texture;
44394
44395	}
44396
44397}
44398
44399/**
44400 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
44401 *
44402 * Sub classes have to implement the parse() method which will be used in load().
44403 */
44404
44405class DataTextureLoader extends Loader {
44406
44407	constructor( manager ) {
44408
44409		super( manager );
44410
44411	}
44412
44413	load( url, onLoad, onProgress, onError ) {
44414
44415		const scope = this;
44416
44417		const texture = new DataTexture();
44418
44419		const loader = new FileLoader( this.manager );
44420		loader.setResponseType( 'arraybuffer' );
44421		loader.setRequestHeader( this.requestHeader );
44422		loader.setPath( this.path );
44423		loader.setWithCredentials( scope.withCredentials );
44424		loader.load( url, function ( buffer ) {
44425
44426			let texData;
44427
44428			try {
44429
44430				texData = scope.parse( buffer );
44431
44432			} catch ( error ) {
44433
44434				if ( onError !== undefined ) {
44435
44436					onError( error );
44437
44438				} else {
44439
44440					console.error( error );
44441					return;
44442
44443				}
44444
44445			}
44446
44447			if ( texData.image !== undefined ) {
44448
44449				texture.image = texData.image;
44450
44451			} else if ( texData.data !== undefined ) {
44452
44453				texture.image.width = texData.width;
44454				texture.image.height = texData.height;
44455				texture.image.data = texData.data;
44456
44457			}
44458
44459			texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
44460			texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
44461
vendor: 4,953 bytes, lines 44462-44748
44462			texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
44463			texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
44464
44465			texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
44466
44467			if ( texData.colorSpace !== undefined ) {
44468
44469				texture.colorSpace = texData.colorSpace;
44470
44471			}
44472
44473			if ( texData.flipY !== undefined ) {
44474
44475				texture.flipY = texData.flipY;
44476
44477			}
44478
44479			if ( texData.format !== undefined ) {
44480
44481				texture.format = texData.format;
44482
44483			}
44484
44485			if ( texData.type !== undefined ) {
44486
44487				texture.type = texData.type;
44488
44489			}
44490
44491			if ( texData.mipmaps !== undefined ) {
44492
44493				texture.mipmaps = texData.mipmaps;
44494				texture.minFilter = LinearMipmapLinearFilter; // presumably...
44495
44496			}
44497
44498			if ( texData.mipmapCount === 1 ) {
44499
44500				texture.minFilter = LinearFilter;
44501
44502			}
44503
44504			if ( texData.generateMipmaps !== undefined ) {
44505
44506				texture.generateMipmaps = texData.generateMipmaps;
44507
44508			}
44509
44510			texture.needsUpdate = true;
44511
44512			if ( onLoad ) onLoad( texture, texData );
44513
44514		}, onProgress, onError );
44515
44516
44517		return texture;
44518
44519	}
44520
44521}
44522
44523class TextureLoader extends Loader {
44524
44525	constructor( manager ) {
44526
44527		super( manager );
44528
44529	}
44530
44531	load( url, onLoad, onProgress, onError ) {
44532
44533		const texture = new Texture();
44534
44535		const loader = new ImageLoader( this.manager );
44536		loader.setCrossOrigin( this.crossOrigin );
44537		loader.setPath( this.path );
44538
44539		loader.load( url, function ( image ) {
44540
44541			texture.image = image;
44542			texture.needsUpdate = true;
44543
44544			if ( onLoad !== undefined ) {
44545
44546				onLoad( texture );
44547
44548			}
44549
44550		}, onProgress, onError );
44551
44552		return texture;
44553
44554	}
44555
44556}
44557
44558class Light extends Object3D {
44559
44560	constructor( color, intensity = 1 ) {
44561
44562		super();
44563
44564		this.isLight = true;
44565
44566		this.type = 'Light';
44567
44568		this.color = new Color( color );
44569		this.intensity = intensity;
44570
44571	}
44572
44573	dispose() {
44574
44575		// Empty here in base class; some subclasses override.
44576
44577	}
44578
44579	copy( source, recursive ) {
44580
44581		super.copy( source, recursive );
44582
44583		this.color.copy( source.color );
44584		this.intensity = source.intensity;
44585
44586		return this;
44587
44588	}
44589
44590	toJSON( meta ) {
44591
44592		const data = super.toJSON( meta );
44593
44594		data.object.color = this.color.getHex();
44595		data.object.intensity = this.intensity;
44596
44597		if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
44598
44599		if ( this.distance !== undefined ) data.object.distance = this.distance;
44600		if ( this.angle !== undefined ) data.object.angle = this.angle;
44601		if ( this.decay !== undefined ) data.object.decay = this.decay;
44602		if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
44603
44604		if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
44605
44606		return data;
44607
44608	}
44609
44610}
44611
44612class HemisphereLight extends Light {
44613
44614	constructor( skyColor, groundColor, intensity ) {
44615
44616		super( skyColor, intensity );
44617
44618		this.isHemisphereLight = true;
44619
44620		this.type = 'HemisphereLight';
44621
44622		this.position.copy( Object3D.DEFAULT_UP );
44623		this.updateMatrix();
44624
44625		this.groundColor = new Color( groundColor );
44626
44627	}
44628
44629	copy( source, recursive ) {
44630
44631		super.copy( source, recursive );
44632
44633		this.groundColor.copy( source.groundColor );
44634
44635		return this;
44636
44637	}
44638
44639}
44640
44641const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
44642const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3();
44643const _lookTarget$1 = /*@__PURE__*/ new Vector3();
44644
44645class LightShadow {
44646
44647	constructor( camera ) {
44648
44649		this.camera = camera;
44650
44651		this.bias = 0;
44652		this.normalBias = 0;
44653		this.radius = 1;
44654		this.blurSamples = 8;
44655
44656		this.mapSize = new Vector2( 512, 512 );
44657
44658		this.map = null;
44659		this.mapPass = null;
44660		this.matrix = new Matrix4();
44661
44662		this.autoUpdate = true;
44663		this.needsUpdate = false;
44664
44665		this._frustum = new Frustum();
44666		this._frameExtents = new Vector2( 1, 1 );
44667
44668		this._viewportCount = 1;
44669
44670		this._viewports = [
44671
44672			new Vector4( 0, 0, 1, 1 )
44673
44674		];
44675
44676	}
44677
44678	getViewportCount() {
44679
44680		return this._viewportCount;
44681
44682	}
44683
44684	getFrustum() {
44685
44686		return this._frustum;
44687
44688	}
44689
44690	updateMatrices( light ) {
44691
44692		const shadowCamera = this.camera;
44693		const shadowMatrix = this.matrix;
44694
44695		_lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld );
44696		shadowCamera.position.copy( _lightPositionWorld$1 );
44697
44698		_lookTarget$1.setFromMatrixPosition( light.target.matrixWorld );
44699		shadowCamera.lookAt( _lookTarget$1 );
44700		shadowCamera.updateMatrixWorld();
44701
44702		_projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
44703		this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 );
44704
44705		shadowMatrix.set(
44706			0.5, 0.0, 0.0, 0.5,
44707			0.0, 0.5, 0.0, 0.5,
44708			0.0, 0.0, 0.5, 0.5,
44709			0.0, 0.0, 0.0, 1.0
44710		);
44711
44712		shadowMatrix.multiply( _projScreenMatrix$1 );
44713
44714	}
44715
44716	getViewport( viewportIndex ) {
44717
44718		return this._viewports[ viewportIndex ];
44719
44720	}
44721
44722	getFrameExtents() {
44723
44724		return this._frameExtents;
44725
44726	}
44727
44728	dispose() {
44729
44730		if ( this.map ) {
44731
44732			this.map.dispose();
44733
44734		}
44735
44736		if ( this.mapPass ) {
44737
44738			this.mapPass.dispose();
44739
44740		}
44741
44742	}
44743
44744	copy( source ) {
44745
44746		this.camera = source.camera.clone();
44747
44748		this.bias = source.bias;
vendor: 5,709 bytes, lines 44749-45036
44749		this.radius = source.radius;
44750
44751		this.mapSize.copy( source.mapSize );
44752
44753		return this;
44754
44755	}
44756
44757	clone() {
44758
44759		return new this.constructor().copy( this );
44760
44761	}
44762
44763	toJSON() {
44764
44765		const object = {};
44766
44767		if ( this.bias !== 0 ) object.bias = this.bias;
44768		if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
44769		if ( this.radius !== 1 ) object.radius = this.radius;
44770		if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
44771
44772		object.camera = this.camera.toJSON( false ).object;
44773		delete object.camera.matrix;
44774
44775		return object;
44776
44777	}
44778
44779}
44780
44781class SpotLightShadow extends LightShadow {
44782
44783	constructor() {
44784
44785		super( new PerspectiveCamera( 50, 1, 0.5, 500 ) );
44786
44787		this.isSpotLightShadow = true;
44788
44789		this.focus = 1;
44790
44791	}
44792
44793	updateMatrices( light ) {
44794
44795		const camera = this.camera;
44796
44797		const fov = RAD2DEG * 2 * light.angle * this.focus;
44798		const aspect = this.mapSize.width / this.mapSize.height;
44799		const far = light.distance || camera.far;
44800
44801		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
44802
44803			camera.fov = fov;
44804			camera.aspect = aspect;
44805			camera.far = far;
44806			camera.updateProjectionMatrix();
44807
44808		}
44809
44810		super.updateMatrices( light );
44811
44812	}
44813
44814	copy( source ) {
44815
44816		super.copy( source );
44817
44818		this.focus = source.focus;
44819
44820		return this;
44821
44822	}
44823
44824}
44825
44826class SpotLight extends Light {
44827
44828	constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) {
44829
44830		super( color, intensity );
44831
44832		this.isSpotLight = true;
44833
44834		this.type = 'SpotLight';
44835
44836		this.position.copy( Object3D.DEFAULT_UP );
44837		this.updateMatrix();
44838
44839		this.target = new Object3D();
44840
44841		this.distance = distance;
44842		this.angle = angle;
44843		this.penumbra = penumbra;
44844		this.decay = decay;
44845
44846		this.map = null;
44847
44848		this.shadow = new SpotLightShadow();
44849
44850	}
44851
44852	get power() {
44853
44854		// compute the light's luminous power (in lumens) from its intensity (in candela)
44855		// by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
44856		return this.intensity * Math.PI;
44857
44858	}
44859
44860	set power( power ) {
44861
44862		// set the light's intensity (in candela) from the desired luminous power (in lumens)
44863		this.intensity = power / Math.PI;
44864
44865	}
44866
44867	dispose() {
44868
44869		this.shadow.dispose();
44870
44871	}
44872
44873	copy( source, recursive ) {
44874
44875		super.copy( source, recursive );
44876
44877		this.distance = source.distance;
44878		this.angle = source.angle;
44879		this.penumbra = source.penumbra;
44880		this.decay = source.decay;
44881
44882		this.target = source.target.clone();
44883
44884		this.shadow = source.shadow.clone();
44885
44886		return this;
44887
44888	}
44889
44890}
44891
44892const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
44893const _lightPositionWorld = /*@__PURE__*/ new Vector3();
44894const _lookTarget = /*@__PURE__*/ new Vector3();
44895
44896class PointLightShadow extends LightShadow {
44897
44898	constructor() {
44899
44900		super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
44901
44902		this.isPointLightShadow = true;
44903
44904		this._frameExtents = new Vector2( 4, 2 );
44905
44906		this._viewportCount = 6;
44907
44908		this._viewports = [
44909			// These viewports map a cube-map onto a 2D texture with the
44910			// following orientation:
44911			//
44912			//  xzXZ
44913			//   y Y
44914			//
44915			// X - Positive x direction
44916			// x - Negative x direction
44917			// Y - Positive y direction
44918			// y - Negative y direction
44919			// Z - Positive z direction
44920			// z - Negative z direction
44921
44922			// positive X
44923			new Vector4( 2, 1, 1, 1 ),
44924			// negative X
44925			new Vector4( 0, 1, 1, 1 ),
44926			// positive Z
44927			new Vector4( 3, 1, 1, 1 ),
44928			// negative Z
44929			new Vector4( 1, 1, 1, 1 ),
44930			// positive Y
44931			new Vector4( 3, 0, 1, 1 ),
44932			// negative Y
44933			new Vector4( 1, 0, 1, 1 )
44934		];
44935
44936		this._cubeDirections = [
44937			new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
44938			new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
44939		];
44940
44941		this._cubeUps = [
44942			new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
44943			new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),	new Vector3( 0, 0, - 1 )
44944		];
44945
44946	}
44947
44948	updateMatrices( light, viewportIndex = 0 ) {
44949
44950		const camera = this.camera;
44951		const shadowMatrix = this.matrix;
44952
44953		const far = light.distance || camera.far;
44954
44955		if ( far !== camera.far ) {
44956
44957			camera.far = far;
44958			camera.updateProjectionMatrix();
44959
44960		}
44961
44962		_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
44963		camera.position.copy( _lightPositionWorld );
44964
44965		_lookTarget.copy( camera.position );
44966		_lookTarget.add( this._cubeDirections[ viewportIndex ] );
44967		camera.up.copy( this._cubeUps[ viewportIndex ] );
44968		camera.lookAt( _lookTarget );
44969		camera.updateMatrixWorld();
44970
44971		shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
44972
44973		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
44974		this._frustum.setFromProjectionMatrix( _projScreenMatrix );
44975
44976	}
44977
44978}
44979
44980class PointLight extends Light {
44981
44982	constructor( color, intensity, distance = 0, decay = 2 ) {
44983
44984		super( color, intensity );
44985
44986		this.isPointLight = true;
44987
44988		this.type = 'PointLight';
44989
44990		this.distance = distance;
44991		this.decay = decay;
44992
44993		this.shadow = new PointLightShadow();
44994
44995	}
44996
44997	get power() {
44998
44999		// compute the light's luminous power (in lumens) from its intensity (in candela)
45000		// for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
45001		return this.intensity * 4 * Math.PI;
45002
45003	}
45004
45005	set power( power ) {
45006
45007		// set the light's intensity (in candela) from the desired luminous power (in lumens)
45008		this.intensity = power / ( 4 * Math.PI );
45009
45010	}
45011
45012	dispose() {
45013
45014		this.shadow.dispose();
45015
45016	}
45017
45018	copy( source, recursive ) {
45019
45020		super.copy( source, recursive );
45021
45022		this.distance = source.distance;
45023		this.decay = source.decay;
45024
45025		this.shadow = source.shadow.clone();
45026
45027		return this;
45028
45029	}
45030
45031}
45032
45033class DirectionalLightShadow extends LightShadow {
45034
45035	constructor() {
45036
vendor: 4,273 bytes, lines 45037-45258
45037		super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
45038
45039		this.isDirectionalLightShadow = true;
45040
45041	}
45042
45043}
45044
45045class DirectionalLight extends Light {
45046
45047	constructor( color, intensity ) {
45048
45049		super( color, intensity );
45050
45051		this.isDirectionalLight = true;
45052
45053		this.type = 'DirectionalLight';
45054
45055		this.position.copy( Object3D.DEFAULT_UP );
45056		this.updateMatrix();
45057
45058		this.target = new Object3D();
45059
45060		this.shadow = new DirectionalLightShadow();
45061
45062	}
45063
45064	dispose() {
45065
45066		this.shadow.dispose();
45067
45068	}
45069
45070	copy( source ) {
45071
45072		super.copy( source );
45073
45074		this.target = source.target.clone();
45075		this.shadow = source.shadow.clone();
45076
45077		return this;
45078
45079	}
45080
45081}
45082
45083class AmbientLight extends Light {
45084
45085	constructor( color, intensity ) {
45086
45087		super( color, intensity );
45088
45089		this.isAmbientLight = true;
45090
45091		this.type = 'AmbientLight';
45092
45093	}
45094
45095}
45096
45097class RectAreaLight extends Light {
45098
45099	constructor( color, intensity, width = 10, height = 10 ) {
45100
45101		super( color, intensity );
45102
45103		this.isRectAreaLight = true;
45104
45105		this.type = 'RectAreaLight';
45106
45107		this.width = width;
45108		this.height = height;
45109
45110	}
45111
45112	get power() {
45113
45114		// compute the light's luminous power (in lumens) from its intensity (in nits)
45115		return this.intensity * this.width * this.height * Math.PI;
45116
45117	}
45118
45119	set power( power ) {
45120
45121		// set the light's intensity (in nits) from the desired luminous power (in lumens)
45122		this.intensity = power / ( this.width * this.height * Math.PI );
45123
45124	}
45125
45126	copy( source ) {
45127
45128		super.copy( source );
45129
45130		this.width = source.width;
45131		this.height = source.height;
45132
45133		return this;
45134
45135	}
45136
45137	toJSON( meta ) {
45138
45139		const data = super.toJSON( meta );
45140
45141		data.object.width = this.width;
45142		data.object.height = this.height;
45143
45144		return data;
45145
45146	}
45147
45148}
45149
45150/**
45151 * Primary reference:
45152 *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
45153 *
45154 * Secondary reference:
45155 *   https://www.ppsloan.org/publications/StupidSH36.pdf
45156 */
45157
45158// 3-band SH defined by 9 coefficients
45159
45160class SphericalHarmonics3 {
45161
45162	constructor() {
45163
45164		this.isSphericalHarmonics3 = true;
45165
45166		this.coefficients = [];
45167
45168		for ( let i = 0; i < 9; i ++ ) {
45169
45170			this.coefficients.push( new Vector3() );
45171
45172		}
45173
45174	}
45175
45176	set( coefficients ) {
45177
45178		for ( let i = 0; i < 9; i ++ ) {
45179
45180			this.coefficients[ i ].copy( coefficients[ i ] );
45181
45182		}
45183
45184		return this;
45185
45186	}
45187
45188	zero() {
45189
45190		for ( let i = 0; i < 9; i ++ ) {
45191
45192			this.coefficients[ i ].set( 0, 0, 0 );
45193
45194		}
45195
45196		return this;
45197
45198	}
45199
45200	// get the radiance in the direction of the normal
45201	// target is a Vector3
45202	getAt( normal, target ) {
45203
45204		// normal is assumed to be unit length
45205
45206		const x = normal.x, y = normal.y, z = normal.z;
45207
45208		const coeff = this.coefficients;
45209
45210		// band 0
45211		target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
45212
45213		// band 1
45214		target.addScaledVector( coeff[ 1 ], 0.488603 * y );
45215		target.addScaledVector( coeff[ 2 ], 0.488603 * z );
45216		target.addScaledVector( coeff[ 3 ], 0.488603 * x );
45217
45218		// band 2
45219		target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
45220		target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
45221		target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
45222		target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
45223		target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
45224
45225		return target;
45226
45227	}
45228
45229	// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
45230	// target is a Vector3
45231	// https://graphics.stanford.edu/papers/envmap/envmap.pdf
45232	getIrradianceAt( normal, target ) {
45233
45234		// normal is assumed to be unit length
45235
45236		const x = normal.x, y = normal.y, z = normal.z;
45237
45238		const coeff = this.coefficients;
45239
45240		// band 0
45241		target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
45242
45243		// band 1
45244		target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
45245		target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
45246		target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
45247
45248		// band 2
45249		target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
45250		target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
45251		target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
45252		target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
45253		target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
45254
45255		return target;
45256
45257	}
45258
vendor: 40,043 bytes, lines 45259-46905
45259	add( sh ) {
45260
45261		for ( let i = 0; i < 9; i ++ ) {
45262
45263			this.coefficients[ i ].add( sh.coefficients[ i ] );
45264
45265		}
45266
45267		return this;
45268
45269	}
45270
45271	addScaledSH( sh, s ) {
45272
45273		for ( let i = 0; i < 9; i ++ ) {
45274
45275			this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
45276
45277		}
45278
45279		return this;
45280
45281	}
45282
45283	scale( s ) {
45284
45285		for ( let i = 0; i < 9; i ++ ) {
45286
45287			this.coefficients[ i ].multiplyScalar( s );
45288
45289		}
45290
45291		return this;
45292
45293	}
45294
45295	lerp( sh, alpha ) {
45296
45297		for ( let i = 0; i < 9; i ++ ) {
45298
45299			this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
45300
45301		}
45302
45303		return this;
45304
45305	}
45306
45307	equals( sh ) {
45308
45309		for ( let i = 0; i < 9; i ++ ) {
45310
45311			if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
45312
45313				return false;
45314
45315			}
45316
45317		}
45318
45319		return true;
45320
45321	}
45322
45323	copy( sh ) {
45324
45325		return this.set( sh.coefficients );
45326
45327	}
45328
45329	clone() {
45330
45331		return new this.constructor().copy( this );
45332
45333	}
45334
45335	fromArray( array, offset = 0 ) {
45336
45337		const coefficients = this.coefficients;
45338
45339		for ( let i = 0; i < 9; i ++ ) {
45340
45341			coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
45342
45343		}
45344
45345		return this;
45346
45347	}
45348
45349	toArray( array = [], offset = 0 ) {
45350
45351		const coefficients = this.coefficients;
45352
45353		for ( let i = 0; i < 9; i ++ ) {
45354
45355			coefficients[ i ].toArray( array, offset + ( i * 3 ) );
45356
45357		}
45358
45359		return array;
45360
45361	}
45362
45363	// evaluate the basis functions
45364	// shBasis is an Array[ 9 ]
45365	static getBasisAt( normal, shBasis ) {
45366
45367		// normal is assumed to be unit length
45368
45369		const x = normal.x, y = normal.y, z = normal.z;
45370
45371		// band 0
45372		shBasis[ 0 ] = 0.282095;
45373
45374		// band 1
45375		shBasis[ 1 ] = 0.488603 * y;
45376		shBasis[ 2 ] = 0.488603 * z;
45377		shBasis[ 3 ] = 0.488603 * x;
45378
45379		// band 2
45380		shBasis[ 4 ] = 1.092548 * x * y;
45381		shBasis[ 5 ] = 1.092548 * y * z;
45382		shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
45383		shBasis[ 7 ] = 1.092548 * x * z;
45384		shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
45385
45386	}
45387
45388}
45389
45390class LightProbe extends Light {
45391
45392	constructor( sh = new SphericalHarmonics3(), intensity = 1 ) {
45393
45394		super( undefined, intensity );
45395
45396		this.isLightProbe = true;
45397
45398		this.sh = sh;
45399
45400	}
45401
45402	copy( source ) {
45403
45404		super.copy( source );
45405
45406		this.sh.copy( source.sh );
45407
45408		return this;
45409
45410	}
45411
45412	fromJSON( json ) {
45413
45414		this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
45415		this.sh.fromArray( json.sh );
45416
45417		return this;
45418
45419	}
45420
45421	toJSON( meta ) {
45422
45423		const data = super.toJSON( meta );
45424
45425		data.object.sh = this.sh.toArray();
45426
45427		return data;
45428
45429	}
45430
45431}
45432
45433class MaterialLoader extends Loader {
45434
45435	constructor( manager ) {
45436
45437		super( manager );
45438		this.textures = {};
45439
45440	}
45441
45442	load( url, onLoad, onProgress, onError ) {
45443
45444		const scope = this;
45445
45446		const loader = new FileLoader( scope.manager );
45447		loader.setPath( scope.path );
45448		loader.setRequestHeader( scope.requestHeader );
45449		loader.setWithCredentials( scope.withCredentials );
45450		loader.load( url, function ( text ) {
45451
45452			try {
45453
45454				onLoad( scope.parse( JSON.parse( text ) ) );
45455
45456			} catch ( e ) {
45457
45458				if ( onError ) {
45459
45460					onError( e );
45461
45462				} else {
45463
45464					console.error( e );
45465
45466				}
45467
45468				scope.manager.itemError( url );
45469
45470			}
45471
45472		}, onProgress, onError );
45473
45474	}
45475
45476	parse( json ) {
45477
45478		const textures = this.textures;
45479
45480		function getTexture( name ) {
45481
45482			if ( textures[ name ] === undefined ) {
45483
45484				console.warn( 'THREE.MaterialLoader: Undefined texture', name );
45485
45486			}
45487
45488			return textures[ name ];
45489
45490		}
45491
45492		const material = MaterialLoader.createMaterialFromType( json.type );
45493
45494		if ( json.uuid !== undefined ) material.uuid = json.uuid;
45495		if ( json.name !== undefined ) material.name = json.name;
45496		if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
45497		if ( json.roughness !== undefined ) material.roughness = json.roughness;
45498		if ( json.metalness !== undefined ) material.metalness = json.metalness;
45499		if ( json.sheen !== undefined ) material.sheen = json.sheen;
45500		if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor );
45501		if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness;
45502		if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
45503		if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
45504		if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity;
45505		if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor );
45506		if ( json.shininess !== undefined ) material.shininess = json.shininess;
45507		if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
45508		if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
45509		if ( json.dispersion !== undefined ) material.dispersion = json.dispersion;
45510		if ( json.iridescence !== undefined ) material.iridescence = json.iridescence;
45511		if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR;
45512		if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange;
45513		if ( json.transmission !== undefined ) material.transmission = json.transmission;
45514		if ( json.thickness !== undefined ) material.thickness = json.thickness;
45515		if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance;
45516		if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor );
45517		if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy;
45518		if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation;
45519		if ( json.fog !== undefined ) material.fog = json.fog;
45520		if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
45521		if ( json.blending !== undefined ) material.blending = json.blending;
45522		if ( json.combine !== undefined ) material.combine = json.combine;
45523		if ( json.side !== undefined ) material.side = json.side;
45524		if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide;
45525		if ( json.opacity !== undefined ) material.opacity = json.opacity;
45526		if ( json.transparent !== undefined ) material.transparent = json.transparent;
45527		if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
45528		if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash;
45529		if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc;
45530		if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
45531		if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
45532		if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
45533		if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc;
45534		if ( json.blendDst !== undefined ) material.blendDst = json.blendDst;
45535		if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation;
45536		if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha;
45537		if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha;
45538		if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha;
45539		if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor );
45540		if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha;
45541		if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
45542		if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
45543		if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
45544		if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
45545		if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
45546		if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
45547		if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
45548		if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
45549
45550		if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
45551		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
45552		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
45553		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
45554
45555		if ( json.rotation !== undefined ) material.rotation = json.rotation;
45556
45557		if ( json.linewidth !== undefined ) material.linewidth = json.linewidth;
45558		if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
45559		if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
45560		if ( json.scale !== undefined ) material.scale = json.scale;
45561
45562		if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
45563		if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
45564		if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
45565
45566		if ( json.dithering !== undefined ) material.dithering = json.dithering;
45567
45568		if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage;
45569		if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha;
45570		if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass;
45571
45572		if ( json.visible !== undefined ) material.visible = json.visible;
45573
45574		if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
45575
45576		if ( json.userData !== undefined ) material.userData = json.userData;
45577
45578		if ( json.vertexColors !== undefined ) {
45579
45580			if ( typeof json.vertexColors === 'number' ) {
45581
45582				material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
45583
45584			} else {
45585
45586				material.vertexColors = json.vertexColors;
45587
45588			}
45589
45590		}
45591
45592		// Shader Material
45593
45594		if ( json.uniforms !== undefined ) {
45595
45596			for ( const name in json.uniforms ) {
45597
45598				const uniform = json.uniforms[ name ];
45599
45600				material.uniforms[ name ] = {};
45601
45602				switch ( uniform.type ) {
45603
45604					case 't':
45605						material.uniforms[ name ].value = getTexture( uniform.value );
45606						break;
45607
45608					case 'c':
45609						material.uniforms[ name ].value = new Color().setHex( uniform.value );
45610						break;
45611
45612					case 'v2':
45613						material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
45614						break;
45615
45616					case 'v3':
45617						material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
45618						break;
45619
45620					case 'v4':
45621						material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
45622						break;
45623
45624					case 'm3':
45625						material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
45626						break;
45627
45628					case 'm4':
45629						material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
45630						break;
45631
45632					default:
45633						material.uniforms[ name ].value = uniform.value;
45634
45635				}
45636
45637			}
45638
45639		}
45640
45641		if ( json.defines !== undefined ) material.defines = json.defines;
45642		if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
45643		if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
45644		if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion;
45645
45646		if ( json.extensions !== undefined ) {
45647
45648			for ( const key in json.extensions ) {
45649
45650				material.extensions[ key ] = json.extensions[ key ];
45651
45652			}
45653
45654		}
45655
45656		if ( json.lights !== undefined ) material.lights = json.lights;
45657		if ( json.clipping !== undefined ) material.clipping = json.clipping;
45658
45659		// for PointsMaterial
45660
45661		if ( json.size !== undefined ) material.size = json.size;
45662		if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
45663
45664		// maps
45665
45666		if ( json.map !== undefined ) material.map = getTexture( json.map );
45667		if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
45668
45669		if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
45670
45671		if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
45672		if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
45673
45674		if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
45675		if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
45676		if ( json.normalScale !== undefined ) {
45677
45678			let normalScale = json.normalScale;
45679
45680			if ( Array.isArray( normalScale ) === false ) {
45681
45682				// Blender exporter used to export a scalar. See #7459
45683
45684				normalScale = [ normalScale, normalScale ];
45685
45686			}
45687
45688			material.normalScale = new Vector2().fromArray( normalScale );
45689
45690		}
45691
45692		if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
45693		if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
45694		if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
45695
45696		if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
45697		if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
45698
45699		if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
45700		if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
45701
45702		if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
45703		if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap );
45704		if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap );
45705
45706		if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
45707		if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation );
45708		if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
45709
45710		if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
45711		if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
45712
45713		if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
45714		if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
45715
45716		if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
45717		if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
45718
45719		if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
45720
45721		if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
45722		if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
45723		if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
45724		if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
45725
45726		if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap );
45727		if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap );
45728
45729		if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
45730		if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap );
45731
45732		if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap );
45733
45734		if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap );
45735		if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap );
45736
45737		return material;
45738
45739	}
45740
45741	setTextures( value ) {
45742
45743		this.textures = value;
45744		return this;
45745
45746	}
45747
45748	static createMaterialFromType( type ) {
45749
45750		const materialLib = {
45751			ShadowMaterial,
45752			SpriteMaterial,
45753			RawShaderMaterial,
45754			ShaderMaterial,
45755			PointsMaterial,
45756			MeshPhysicalMaterial,
45757			MeshStandardMaterial,
45758			MeshPhongMaterial,
45759			MeshToonMaterial,
45760			MeshNormalMaterial,
45761			MeshLambertMaterial,
45762			MeshDepthMaterial,
45763			MeshDistanceMaterial,
45764			MeshBasicMaterial,
45765			MeshMatcapMaterial,
45766			LineDashedMaterial,
45767			LineBasicMaterial,
45768			Material
45769		};
45770
45771		return new materialLib[ type ]();
45772
45773	}
45774
45775}
45776
45777class LoaderUtils {
45778
45779	static decodeText( array ) { // @deprecated, r165
45780
45781		console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' );
45782
45783		if ( typeof TextDecoder !== 'undefined' ) {
45784
45785			return new TextDecoder().decode( array );
45786
45787		}
45788
45789		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
45790		// throws a "maximum call stack size exceeded" error for large arrays.
45791
45792		let s = '';
45793
45794		for ( let i = 0, il = array.length; i < il; i ++ ) {
45795
45796			// Implicitly assumes little-endian.
45797			s += String.fromCharCode( array[ i ] );
45798
45799		}
45800
45801		try {
45802
45803			// merges multi-byte utf-8 characters.
45804
45805			return decodeURIComponent( escape( s ) );
45806
45807		} catch ( e ) { // see #16358
45808
45809			return s;
45810
45811		}
45812
45813	}
45814
45815	static extractUrlBase( url ) {
45816
45817		const index = url.lastIndexOf( '/' );
45818
45819		if ( index === - 1 ) return './';
45820
45821		return url.slice( 0, index + 1 );
45822
45823	}
45824
45825	static resolveURL( url, path ) {
45826
45827		// Invalid URL
45828		if ( typeof url !== 'string' || url === '' ) return '';
45829
45830		// Host Relative URL
45831		if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
45832
45833			path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
45834
45835		}
45836
45837		// Absolute URL http://,https://,//
45838		if ( /^(https?:)?\/\//i.test( url ) ) return url;
45839
45840		// Data URI
45841		if ( /^data:.*,.*$/i.test( url ) ) return url;
45842
45843		// Blob URL
45844		if ( /^blob:.*$/i.test( url ) ) return url;
45845
45846		// Relative URL
45847		return path + url;
45848
45849	}
45850
45851}
45852
45853class InstancedBufferGeometry extends BufferGeometry {
45854
45855	constructor() {
45856
45857		super();
45858
45859		this.isInstancedBufferGeometry = true;
45860
45861		this.type = 'InstancedBufferGeometry';
45862		this.instanceCount = Infinity;
45863
45864	}
45865
45866	copy( source ) {
45867
45868		super.copy( source );
45869
45870		this.instanceCount = source.instanceCount;
45871
45872		return this;
45873
45874	}
45875
45876	toJSON() {
45877
45878		const data = super.toJSON();
45879
45880		data.instanceCount = this.instanceCount;
45881
45882		data.isInstancedBufferGeometry = true;
45883
45884		return data;
45885
45886	}
45887
45888}
45889
45890class BufferGeometryLoader extends Loader {
45891
45892	constructor( manager ) {
45893
45894		super( manager );
45895
45896	}
45897
45898	load( url, onLoad, onProgress, onError ) {
45899
45900		const scope = this;
45901
45902		const loader = new FileLoader( scope.manager );
45903		loader.setPath( scope.path );
45904		loader.setRequestHeader( scope.requestHeader );
45905		loader.setWithCredentials( scope.withCredentials );
45906		loader.load( url, function ( text ) {
45907
45908			try {
45909
45910				onLoad( scope.parse( JSON.parse( text ) ) );
45911
45912			} catch ( e ) {
45913
45914				if ( onError ) {
45915
45916					onError( e );
45917
45918				} else {
45919
45920					console.error( e );
45921
45922				}
45923
45924				scope.manager.itemError( url );
45925
45926			}
45927
45928		}, onProgress, onError );
45929
45930	}
45931
45932	parse( json ) {
45933
45934		const interleavedBufferMap = {};
45935		const arrayBufferMap = {};
45936
45937		function getInterleavedBuffer( json, uuid ) {
45938
45939			if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
45940
45941			const interleavedBuffers = json.interleavedBuffers;
45942			const interleavedBuffer = interleavedBuffers[ uuid ];
45943
45944			const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
45945
45946			const array = getTypedArray( interleavedBuffer.type, buffer );
45947			const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
45948			ib.uuid = interleavedBuffer.uuid;
45949
45950			interleavedBufferMap[ uuid ] = ib;
45951
45952			return ib;
45953
45954		}
45955
45956		function getArrayBuffer( json, uuid ) {
45957
45958			if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
45959
45960			const arrayBuffers = json.arrayBuffers;
45961			const arrayBuffer = arrayBuffers[ uuid ];
45962
45963			const ab = new Uint32Array( arrayBuffer ).buffer;
45964
45965			arrayBufferMap[ uuid ] = ab;
45966
45967			return ab;
45968
45969		}
45970
45971		const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
45972
45973		const index = json.data.index;
45974
45975		if ( index !== undefined ) {
45976
45977			const typedArray = getTypedArray( index.type, index.array );
45978			geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
45979
45980		}
45981
45982		const attributes = json.data.attributes;
45983
45984		for ( const key in attributes ) {
45985
45986			const attribute = attributes[ key ];
45987			let bufferAttribute;
45988
45989			if ( attribute.isInterleavedBufferAttribute ) {
45990
45991				const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
45992				bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
45993
45994			} else {
45995
45996				const typedArray = getTypedArray( attribute.type, attribute.array );
45997				const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
45998				bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
45999
46000			}
46001
46002			if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
46003			if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
46004
46005			geometry.setAttribute( key, bufferAttribute );
46006
46007		}
46008
46009		const morphAttributes = json.data.morphAttributes;
46010
46011		if ( morphAttributes ) {
46012
46013			for ( const key in morphAttributes ) {
46014
46015				const attributeArray = morphAttributes[ key ];
46016
46017				const array = [];
46018
46019				for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
46020
46021					const attribute = attributeArray[ i ];
46022					let bufferAttribute;
46023
46024					if ( attribute.isInterleavedBufferAttribute ) {
46025
46026						const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
46027						bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
46028
46029					} else {
46030
46031						const typedArray = getTypedArray( attribute.type, attribute.array );
46032						bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
46033
46034					}
46035
46036					if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
46037					array.push( bufferAttribute );
46038
46039				}
46040
46041				geometry.morphAttributes[ key ] = array;
46042
46043			}
46044
46045		}
46046
46047		const morphTargetsRelative = json.data.morphTargetsRelative;
46048
46049		if ( morphTargetsRelative ) {
46050
46051			geometry.morphTargetsRelative = true;
46052
46053		}
46054
46055		const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
46056
46057		if ( groups !== undefined ) {
46058
46059			for ( let i = 0, n = groups.length; i !== n; ++ i ) {
46060
46061				const group = groups[ i ];
46062
46063				geometry.addGroup( group.start, group.count, group.materialIndex );
46064
46065			}
46066
46067		}
46068
46069		const boundingSphere = json.data.boundingSphere;
46070
46071		if ( boundingSphere !== undefined ) {
46072
46073			const center = new Vector3();
46074
46075			if ( boundingSphere.center !== undefined ) {
46076
46077				center.fromArray( boundingSphere.center );
46078
46079			}
46080
46081			geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
46082
46083		}
46084
46085		if ( json.name ) geometry.name = json.name;
46086		if ( json.userData ) geometry.userData = json.userData;
46087
46088		return geometry;
46089
46090	}
46091
46092}
46093
46094class ObjectLoader extends Loader {
46095
46096	constructor( manager ) {
46097
46098		super( manager );
46099
46100	}
46101
46102	load( url, onLoad, onProgress, onError ) {
46103
46104		const scope = this;
46105
46106		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
46107		this.resourcePath = this.resourcePath || path;
46108
46109		const loader = new FileLoader( this.manager );
46110		loader.setPath( this.path );
46111		loader.setRequestHeader( this.requestHeader );
46112		loader.setWithCredentials( this.withCredentials );
46113		loader.load( url, function ( text ) {
46114
46115			let json = null;
46116
46117			try {
46118
46119				json = JSON.parse( text );
46120
46121			} catch ( error ) {
46122
46123				if ( onError !== undefined ) onError( error );
46124
46125				console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
46126
46127				return;
46128
46129			}
46130
46131			const metadata = json.metadata;
46132
46133			if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
46134
46135				if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) );
46136
46137				console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
46138				return;
46139
46140			}
46141
46142			scope.parse( json, onLoad );
46143
46144		}, onProgress, onError );
46145
46146	}
46147
46148	async loadAsync( url, onProgress ) {
46149
46150		const scope = this;
46151
46152		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
46153		this.resourcePath = this.resourcePath || path;
46154
46155		const loader = new FileLoader( this.manager );
46156		loader.setPath( this.path );
46157		loader.setRequestHeader( this.requestHeader );
46158		loader.setWithCredentials( this.withCredentials );
46159
46160		const text = await loader.loadAsync( url, onProgress );
46161
46162		const json = JSON.parse( text );
46163
46164		const metadata = json.metadata;
46165
46166		if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
46167
46168			throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url );
46169
46170		}
46171
46172		return await scope.parseAsync( json );
46173
46174	}
46175
46176	parse( json, onLoad ) {
46177
46178		const animations = this.parseAnimations( json.animations );
46179		const shapes = this.parseShapes( json.shapes );
46180		const geometries = this.parseGeometries( json.geometries, shapes );
46181
46182		const images = this.parseImages( json.images, function () {
46183
46184			if ( onLoad !== undefined ) onLoad( object );
46185
46186		} );
46187
46188		const textures = this.parseTextures( json.textures, images );
46189		const materials = this.parseMaterials( json.materials, textures );
46190
46191		const object = this.parseObject( json.object, geometries, materials, textures, animations );
46192		const skeletons = this.parseSkeletons( json.skeletons, object );
46193
46194		this.bindSkeletons( object, skeletons );
46195
46196		//
46197
46198		if ( onLoad !== undefined ) {
46199
46200			let hasImages = false;
46201
46202			for ( const uuid in images ) {
46203
46204				if ( images[ uuid ].data instanceof HTMLImageElement ) {
46205
46206					hasImages = true;
46207					break;
46208
46209				}
46210
46211			}
46212
46213			if ( hasImages === false ) onLoad( object );
46214
46215		}
46216
46217		return object;
46218
46219	}
46220
46221	async parseAsync( json ) {
46222
46223		const animations = this.parseAnimations( json.animations );
46224		const shapes = this.parseShapes( json.shapes );
46225		const geometries = this.parseGeometries( json.geometries, shapes );
46226
46227		const images = await this.parseImagesAsync( json.images );
46228
46229		const textures = this.parseTextures( json.textures, images );
46230		const materials = this.parseMaterials( json.materials, textures );
46231
46232		const object = this.parseObject( json.object, geometries, materials, textures, animations );
46233		const skeletons = this.parseSkeletons( json.skeletons, object );
46234
46235		this.bindSkeletons( object, skeletons );
46236
46237		return object;
46238
46239	}
46240
46241	parseShapes( json ) {
46242
46243		const shapes = {};
46244
46245		if ( json !== undefined ) {
46246
46247			for ( let i = 0, l = json.length; i < l; i ++ ) {
46248
46249				const shape = new Shape().fromJSON( json[ i ] );
46250
46251				shapes[ shape.uuid ] = shape;
46252
46253			}
46254
46255		}
46256
46257		return shapes;
46258
46259	}
46260
46261	parseSkeletons( json, object ) {
46262
46263		const skeletons = {};
46264		const bones = {};
46265
46266		// generate bone lookup table
46267
46268		object.traverse( function ( child ) {
46269
46270			if ( child.isBone ) bones[ child.uuid ] = child;
46271
46272		} );
46273
46274		// create skeletons
46275
46276		if ( json !== undefined ) {
46277
46278			for ( let i = 0, l = json.length; i < l; i ++ ) {
46279
46280				const skeleton = new Skeleton().fromJSON( json[ i ], bones );
46281
46282				skeletons[ skeleton.uuid ] = skeleton;
46283
46284			}
46285
46286		}
46287
46288		return skeletons;
46289
46290	}
46291
46292	parseGeometries( json, shapes ) {
46293
46294		const geometries = {};
46295
46296		if ( json !== undefined ) {
46297
46298			const bufferGeometryLoader = new BufferGeometryLoader();
46299
46300			for ( let i = 0, l = json.length; i < l; i ++ ) {
46301
46302				let geometry;
46303				const data = json[ i ];
46304
46305				switch ( data.type ) {
46306
46307					case 'BufferGeometry':
46308					case 'InstancedBufferGeometry':
46309
46310						geometry = bufferGeometryLoader.parse( data );
46311						break;
46312
46313					default:
46314
46315						if ( data.type in Geometries ) {
46316
46317							geometry = Geometries[ data.type ].fromJSON( data, shapes );
46318
46319						} else {
46320
46321							console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` );
46322
46323						}
46324
46325				}
46326
46327				geometry.uuid = data.uuid;
46328
46329				if ( data.name !== undefined ) geometry.name = data.name;
46330				if ( data.userData !== undefined ) geometry.userData = data.userData;
46331
46332				geometries[ data.uuid ] = geometry;
46333
46334			}
46335
46336		}
46337
46338		return geometries;
46339
46340	}
46341
46342	parseMaterials( json, textures ) {
46343
46344		const cache = {}; // MultiMaterial
46345		const materials = {};
46346
46347		if ( json !== undefined ) {
46348
46349			const loader = new MaterialLoader();
46350			loader.setTextures( textures );
46351
46352			for ( let i = 0, l = json.length; i < l; i ++ ) {
46353
46354				const data = json[ i ];
46355
46356				if ( cache[ data.uuid ] === undefined ) {
46357
46358					cache[ data.uuid ] = loader.parse( data );
46359
46360				}
46361
46362				materials[ data.uuid ] = cache[ data.uuid ];
46363
46364			}
46365
46366		}
46367
46368		return materials;
46369
46370	}
46371
46372	parseAnimations( json ) {
46373
46374		const animations = {};
46375
46376		if ( json !== undefined ) {
46377
46378			for ( let i = 0; i < json.length; i ++ ) {
46379
46380				const data = json[ i ];
46381
46382				const clip = AnimationClip.parse( data );
46383
46384				animations[ clip.uuid ] = clip;
46385
46386			}
46387
46388		}
46389
46390		return animations;
46391
46392	}
46393
46394	parseImages( json, onLoad ) {
46395
46396		const scope = this;
46397		const images = {};
46398
46399		let loader;
46400
46401		function loadImage( url ) {
46402
46403			scope.manager.itemStart( url );
46404
46405			return loader.load( url, function () {
46406
46407				scope.manager.itemEnd( url );
46408
46409			}, undefined, function () {
46410
46411				scope.manager.itemError( url );
46412				scope.manager.itemEnd( url );
46413
46414			} );
46415
46416		}
46417
46418		function deserializeImage( image ) {
46419
46420			if ( typeof image === 'string' ) {
46421
46422				const url = image;
46423
46424				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
46425
46426				return loadImage( path );
46427
46428			} else {
46429
46430				if ( image.data ) {
46431
46432					return {
46433						data: getTypedArray( image.type, image.data ),
46434						width: image.width,
46435						height: image.height
46436					};
46437
46438				} else {
46439
46440					return null;
46441
46442				}
46443
46444			}
46445
46446		}
46447
46448		if ( json !== undefined && json.length > 0 ) {
46449
46450			const manager = new LoadingManager( onLoad );
46451
46452			loader = new ImageLoader( manager );
46453			loader.setCrossOrigin( this.crossOrigin );
46454
46455			for ( let i = 0, il = json.length; i < il; i ++ ) {
46456
46457				const image = json[ i ];
46458				const url = image.url;
46459
46460				if ( Array.isArray( url ) ) {
46461
46462					// load array of images e.g CubeTexture
46463
46464					const imageArray = [];
46465
46466					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
46467
46468						const currentUrl = url[ j ];
46469
46470						const deserializedImage = deserializeImage( currentUrl );
46471
46472						if ( deserializedImage !== null ) {
46473
46474							if ( deserializedImage instanceof HTMLImageElement ) {
46475
46476								imageArray.push( deserializedImage );
46477
46478							} else {
46479
46480								// special case: handle array of data textures for cube textures
46481
46482								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
46483
46484							}
46485
46486						}
46487
46488					}
46489
46490					images[ image.uuid ] = new Source( imageArray );
46491
46492				} else {
46493
46494					// load single image
46495
46496					const deserializedImage = deserializeImage( image.url );
46497					images[ image.uuid ] = new Source( deserializedImage );
46498
46499
46500				}
46501
46502			}
46503
46504		}
46505
46506		return images;
46507
46508	}
46509
46510	async parseImagesAsync( json ) {
46511
46512		const scope = this;
46513		const images = {};
46514
46515		let loader;
46516
46517		async function deserializeImage( image ) {
46518
46519			if ( typeof image === 'string' ) {
46520
46521				const url = image;
46522
46523				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
46524
46525				return await loader.loadAsync( path );
46526
46527			} else {
46528
46529				if ( image.data ) {
46530
46531					return {
46532						data: getTypedArray( image.type, image.data ),
46533						width: image.width,
46534						height: image.height
46535					};
46536
46537				} else {
46538
46539					return null;
46540
46541				}
46542
46543			}
46544
46545		}
46546
46547		if ( json !== undefined && json.length > 0 ) {
46548
46549			loader = new ImageLoader( this.manager );
46550			loader.setCrossOrigin( this.crossOrigin );
46551
46552			for ( let i = 0, il = json.length; i < il; i ++ ) {
46553
46554				const image = json[ i ];
46555				const url = image.url;
46556
46557				if ( Array.isArray( url ) ) {
46558
46559					// load array of images e.g CubeTexture
46560
46561					const imageArray = [];
46562
46563					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
46564
46565						const currentUrl = url[ j ];
46566
46567						const deserializedImage = await deserializeImage( currentUrl );
46568
46569						if ( deserializedImage !== null ) {
46570
46571							if ( deserializedImage instanceof HTMLImageElement ) {
46572
46573								imageArray.push( deserializedImage );
46574
46575							} else {
46576
46577								// special case: handle array of data textures for cube textures
46578
46579								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
46580
46581							}
46582
46583						}
46584
46585					}
46586
46587					images[ image.uuid ] = new Source( imageArray );
46588
46589				} else {
46590
46591					// load single image
46592
46593					const deserializedImage = await deserializeImage( image.url );
46594					images[ image.uuid ] = new Source( deserializedImage );
46595
46596				}
46597
46598			}
46599
46600		}
46601
46602		return images;
46603
46604	}
46605
46606	parseTextures( json, images ) {
46607
46608		function parseConstant( value, type ) {
46609
46610			if ( typeof value === 'number' ) return value;
46611
46612			console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
46613
46614			return type[ value ];
46615
46616		}
46617
46618		const textures = {};
46619
46620		if ( json !== undefined ) {
46621
46622			for ( let i = 0, l = json.length; i < l; i ++ ) {
46623
46624				const data = json[ i ];
46625
46626				if ( data.image === undefined ) {
46627
46628					console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid );
46629
46630				}
46631
46632				if ( images[ data.image ] === undefined ) {
46633
46634					console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
46635
46636				}
46637
46638				const source = images[ data.image ];
46639				const image = source.data;
46640
46641				let texture;
46642
46643				if ( Array.isArray( image ) ) {
46644
46645					texture = new CubeTexture();
46646
46647					if ( image.length === 6 ) texture.needsUpdate = true;
46648
46649				} else {
46650
46651					if ( image && image.data ) {
46652
46653						texture = new DataTexture();
46654
46655					} else {
46656
46657						texture = new Texture();
46658
46659					}
46660
46661					if ( image ) texture.needsUpdate = true; // textures can have undefined image data
46662
46663				}
46664
46665				texture.source = source;
46666
46667				texture.uuid = data.uuid;
46668
46669				if ( data.name !== undefined ) texture.name = data.name;
46670
46671				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
46672				if ( data.channel !== undefined ) texture.channel = data.channel;
46673
46674				if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
46675				if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
46676				if ( data.center !== undefined ) texture.center.fromArray( data.center );
46677				if ( data.rotation !== undefined ) texture.rotation = data.rotation;
46678
46679				if ( data.wrap !== undefined ) {
46680
46681					texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
46682					texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
46683
46684				}
46685
46686				if ( data.format !== undefined ) texture.format = data.format;
46687				if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat;
46688				if ( data.type !== undefined ) texture.type = data.type;
46689				if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace;
46690
46691				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
46692				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
46693				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
46694
46695				if ( data.flipY !== undefined ) texture.flipY = data.flipY;
46696
46697				if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps;
46698				if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
46699				if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
46700				if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction;
46701
46702				if ( data.userData !== undefined ) texture.userData = data.userData;
46703
46704				textures[ data.uuid ] = texture;
46705
46706			}
46707
46708		}
46709
46710		return textures;
46711
46712	}
46713
46714	parseObject( data, geometries, materials, textures, animations ) {
46715
46716		let object;
46717
46718		function getGeometry( name ) {
46719
46720			if ( geometries[ name ] === undefined ) {
46721
46722				console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
46723
46724			}
46725
46726			return geometries[ name ];
46727
46728		}
46729
46730		function getMaterial( name ) {
46731
46732			if ( name === undefined ) return undefined;
46733
46734			if ( Array.isArray( name ) ) {
46735
46736				const array = [];
46737
46738				for ( let i = 0, l = name.length; i < l; i ++ ) {
46739
46740					const uuid = name[ i ];
46741
46742					if ( materials[ uuid ] === undefined ) {
46743
46744						console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
46745
46746					}
46747
46748					array.push( materials[ uuid ] );
46749
46750				}
46751
46752				return array;
46753
46754			}
46755
46756			if ( materials[ name ] === undefined ) {
46757
46758				console.warn( 'THREE.ObjectLoader: Undefined material', name );
46759
46760			}
46761
46762			return materials[ name ];
46763
46764		}
46765
46766		function getTexture( uuid ) {
46767
46768			if ( textures[ uuid ] === undefined ) {
46769
46770				console.warn( 'THREE.ObjectLoader: Undefined texture', uuid );
46771
46772			}
46773
46774			return textures[ uuid ];
46775
46776		}
46777
46778		let geometry, material;
46779
46780		switch ( data.type ) {
46781
46782			case 'Scene':
46783
46784				object = new Scene();
46785
46786				if ( data.background !== undefined ) {
46787
46788					if ( Number.isInteger( data.background ) ) {
46789
46790						object.background = new Color( data.background );
46791
46792					} else {
46793
46794						object.background = getTexture( data.background );
46795
46796					}
46797
46798				}
46799
46800				if ( data.environment !== undefined ) {
46801
46802					object.environment = getTexture( data.environment );
46803
46804				}
46805
46806				if ( data.fog !== undefined ) {
46807
46808					if ( data.fog.type === 'Fog' ) {
46809
46810						object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
46811
46812					} else if ( data.fog.type === 'FogExp2' ) {
46813
46814						object.fog = new FogExp2( data.fog.color, data.fog.density );
46815
46816					}
46817
46818					if ( data.fog.name !== '' ) {
46819
46820						object.fog.name = data.fog.name;
46821
46822					}
46823
46824				}
46825
46826				if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness;
46827				if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity;
46828				if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation );
46829
46830				if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity;
46831				if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation );
46832
46833				break;
46834
46835			case 'PerspectiveCamera':
46836
46837				object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
46838
46839				if ( data.focus !== undefined ) object.focus = data.focus;
46840				if ( data.zoom !== undefined ) object.zoom = data.zoom;
46841				if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
46842				if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
46843				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46844
46845				break;
46846
46847			case 'OrthographicCamera':
46848
46849				object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
46850
46851				if ( data.zoom !== undefined ) object.zoom = data.zoom;
46852				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46853
46854				break;
46855
46856			case 'AmbientLight':
46857
46858				object = new AmbientLight( data.color, data.intensity );
46859
46860				break;
46861
46862			case 'DirectionalLight':
46863
46864				object = new DirectionalLight( data.color, data.intensity );
46865
46866				break;
46867
46868			case 'PointLight':
46869
46870				object = new PointLight( data.color, data.intensity, data.distance, data.decay );
46871
46872				break;
46873
46874			case 'RectAreaLight':
46875
46876				object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
46877
46878				break;
46879
46880			case 'SpotLight':
46881
46882				object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
46883
46884				break;
46885
46886			case 'HemisphereLight':
46887
46888				object = new HemisphereLight( data.color, data.groundColor, data.intensity );
46889
46890				break;
46891
46892			case 'LightProbe':
46893
46894				object = new LightProbe().fromJSON( data );
46895
46896				break;
46897
46898			case 'SkinnedMesh':
46899
46900				geometry = getGeometry( data.geometry );
46901			 	material = getMaterial( data.material );
46902
46903				object = new SkinnedMesh( geometry, material );
46904
46905				if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
vendor: 17,558 bytes, lines 46906-47737
46906				if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
46907				if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
46908
46909				break;
46910
46911			case 'Mesh':
46912
46913				geometry = getGeometry( data.geometry );
46914				material = getMaterial( data.material );
46915
46916				object = new Mesh( geometry, material );
46917
46918				break;
46919
46920			case 'InstancedMesh':
46921
46922				geometry = getGeometry( data.geometry );
46923				material = getMaterial( data.material );
46924				const count = data.count;
46925				const instanceMatrix = data.instanceMatrix;
46926				const instanceColor = data.instanceColor;
46927
46928				object = new InstancedMesh( geometry, material, count );
46929				object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
46930				if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
46931
46932				break;
46933
46934			case 'BatchedMesh':
46935
46936				geometry = getGeometry( data.geometry );
46937				material = getMaterial( data.material );
46938
46939				object = new BatchedMesh( data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material );
46940				object.geometry = geometry;
46941				object.perObjectFrustumCulled = data.perObjectFrustumCulled;
46942				object.sortObjects = data.sortObjects;
46943
46944				object._drawRanges = data.drawRanges;
46945				object._reservedRanges = data.reservedRanges;
46946
46947				object._visibility = data.visibility;
46948				object._active = data.active;
46949				object._bounds = data.bounds.map( bound => {
46950
46951					const box = new Box3();
46952					box.min.fromArray( bound.boxMin );
46953					box.max.fromArray( bound.boxMax );
46954
46955					const sphere = new Sphere();
46956					sphere.radius = bound.sphereRadius;
46957					sphere.center.fromArray( bound.sphereCenter );
46958
46959					return {
46960						boxInitialized: bound.boxInitialized,
46961						box: box,
46962
46963						sphereInitialized: bound.sphereInitialized,
46964						sphere: sphere
46965					};
46966
46967				} );
46968
46969				object._maxGeometryCount = data.maxGeometryCount;
46970				object._maxVertexCount = data.maxVertexCount;
46971				object._maxIndexCount = data.maxIndexCount;
46972
46973				object._geometryInitialized = data.geometryInitialized;
46974				object._geometryCount = data.geometryCount;
46975
46976				object._matricesTexture = getTexture( data.matricesTexture.uuid );
46977				if ( data.colorsTexture !== undefined ) object._colorsTexture = getTexture( data.colorsTexture.uuid );
46978
46979				break;
46980
46981			case 'LOD':
46982
46983				object = new LOD();
46984
46985				break;
46986
46987			case 'Line':
46988
46989				object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
46990
46991				break;
46992
46993			case 'LineLoop':
46994
46995				object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
46996
46997				break;
46998
46999			case 'LineSegments':
47000
47001				object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
47002
47003				break;
47004
47005			case 'PointCloud':
47006			case 'Points':
47007
47008				object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
47009
47010				break;
47011
47012			case 'Sprite':
47013
47014				object = new Sprite( getMaterial( data.material ) );
47015
47016				break;
47017
47018			case 'Group':
47019
47020				object = new Group();
47021
47022				break;
47023
47024			case 'Bone':
47025
47026				object = new Bone();
47027
47028				break;
47029
47030			default:
47031
47032				object = new Object3D();
47033
47034		}
47035
47036		object.uuid = data.uuid;
47037
47038		if ( data.name !== undefined ) object.name = data.name;
47039
47040		if ( data.matrix !== undefined ) {
47041
47042			object.matrix.fromArray( data.matrix );
47043
47044			if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
47045			if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
47046
47047		} else {
47048
47049			if ( data.position !== undefined ) object.position.fromArray( data.position );
47050			if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
47051			if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
47052			if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
47053
47054		}
47055
47056		if ( data.up !== undefined ) object.up.fromArray( data.up );
47057
47058		if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
47059		if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
47060
47061		if ( data.shadow ) {
47062
47063			if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
47064			if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
47065			if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
47066			if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
47067			if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
47068
47069		}
47070
47071		if ( data.visible !== undefined ) object.visible = data.visible;
47072		if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
47073		if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
47074		if ( data.userData !== undefined ) object.userData = data.userData;
47075		if ( data.layers !== undefined ) object.layers.mask = data.layers;
47076
47077		if ( data.children !== undefined ) {
47078
47079			const children = data.children;
47080
47081			for ( let i = 0; i < children.length; i ++ ) {
47082
47083				object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) );
47084
47085			}
47086
47087		}
47088
47089		if ( data.animations !== undefined ) {
47090
47091			const objectAnimations = data.animations;
47092
47093			for ( let i = 0; i < objectAnimations.length; i ++ ) {
47094
47095				const uuid = objectAnimations[ i ];
47096
47097				object.animations.push( animations[ uuid ] );
47098
47099			}
47100
47101		}
47102
47103		if ( data.type === 'LOD' ) {
47104
47105			if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
47106
47107			const levels = data.levels;
47108
47109			for ( let l = 0; l < levels.length; l ++ ) {
47110
47111				const level = levels[ l ];
47112				const child = object.getObjectByProperty( 'uuid', level.object );
47113
47114				if ( child !== undefined ) {
47115
47116					object.addLevel( child, level.distance, level.hysteresis );
47117
47118				}
47119
47120			}
47121
47122		}
47123
47124		return object;
47125
47126	}
47127
47128	bindSkeletons( object, skeletons ) {
47129
47130		if ( Object.keys( skeletons ).length === 0 ) return;
47131
47132		object.traverse( function ( child ) {
47133
47134			if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
47135
47136				const skeleton = skeletons[ child.skeleton ];
47137
47138				if ( skeleton === undefined ) {
47139
47140					console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton );
47141
47142				} else {
47143
47144					child.bind( skeleton, child.bindMatrix );
47145
47146				}
47147
47148			}
47149
47150		} );
47151
47152	}
47153
47154}
47155
47156const TEXTURE_MAPPING = {
47157	UVMapping: UVMapping,
47158	CubeReflectionMapping: CubeReflectionMapping,
47159	CubeRefractionMapping: CubeRefractionMapping,
47160	EquirectangularReflectionMapping: EquirectangularReflectionMapping,
47161	EquirectangularRefractionMapping: EquirectangularRefractionMapping,
47162	CubeUVReflectionMapping: CubeUVReflectionMapping
47163};
47164
47165const TEXTURE_WRAPPING = {
47166	RepeatWrapping: RepeatWrapping,
47167	ClampToEdgeWrapping: ClampToEdgeWrapping,
47168	MirroredRepeatWrapping: MirroredRepeatWrapping
47169};
47170
47171const TEXTURE_FILTER = {
47172	NearestFilter: NearestFilter,
47173	NearestMipmapNearestFilter: NearestMipmapNearestFilter,
47174	NearestMipmapLinearFilter: NearestMipmapLinearFilter,
47175	LinearFilter: LinearFilter,
47176	LinearMipmapNearestFilter: LinearMipmapNearestFilter,
47177	LinearMipmapLinearFilter: LinearMipmapLinearFilter
47178};
47179
47180class ImageBitmapLoader extends Loader {
47181
47182	constructor( manager ) {
47183
47184		super( manager );
47185
47186		this.isImageBitmapLoader = true;
47187
47188		if ( typeof createImageBitmap === 'undefined' ) {
47189
47190			console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
47191
47192		}
47193
47194		if ( typeof fetch === 'undefined' ) {
47195
47196			console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
47197
47198		}
47199
47200		this.options = { premultiplyAlpha: 'none' };
47201
47202	}
47203
47204	setOptions( options ) {
47205
47206		this.options = options;
47207
47208		return this;
47209
47210	}
47211
47212	load( url, onLoad, onProgress, onError ) {
47213
47214		if ( url === undefined ) url = '';
47215
47216		if ( this.path !== undefined ) url = this.path + url;
47217
47218		url = this.manager.resolveURL( url );
47219
47220		const scope = this;
47221
47222		const cached = Cache.get( url );
47223
47224		if ( cached !== undefined ) {
47225
47226			scope.manager.itemStart( url );
47227
47228			// If cached is a promise, wait for it to resolve
47229			if ( cached.then ) {
47230
47231				cached.then( imageBitmap => {
47232
47233					if ( onLoad ) onLoad( imageBitmap );
47234
47235					scope.manager.itemEnd( url );
47236
47237				} ).catch( e => {
47238
47239					if ( onError ) onError( e );
47240
47241				} );
47242				return;
47243
47244			}
47245
47246			// If cached is not a promise (i.e., it's already an imageBitmap)
47247			setTimeout( function () {
47248
47249				if ( onLoad ) onLoad( cached );
47250
47251				scope.manager.itemEnd( url );
47252
47253			}, 0 );
47254
47255			return cached;
47256
47257		}
47258
47259		const fetchOptions = {};
47260		fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
47261		fetchOptions.headers = this.requestHeader;
47262
47263		const promise = fetch( url, fetchOptions ).then( function ( res ) {
47264
47265			return res.blob();
47266
47267		} ).then( function ( blob ) {
47268
47269			return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) );
47270
47271		} ).then( function ( imageBitmap ) {
47272
47273			Cache.add( url, imageBitmap );
47274
47275			if ( onLoad ) onLoad( imageBitmap );
47276
47277			scope.manager.itemEnd( url );
47278
47279			return imageBitmap;
47280
47281		} ).catch( function ( e ) {
47282
47283			if ( onError ) onError( e );
47284
47285			Cache.remove( url );
47286
47287			scope.manager.itemError( url );
47288			scope.manager.itemEnd( url );
47289
47290		} );
47291
47292		Cache.add( url, promise );
47293		scope.manager.itemStart( url );
47294
47295	}
47296
47297}
47298
47299let _context;
47300
47301class AudioContext {
47302
47303	static getContext() {
47304
47305		if ( _context === undefined ) {
47306
47307			_context = new ( window.AudioContext || window.webkitAudioContext )();
47308
47309		}
47310
47311		return _context;
47312
47313	}
47314
47315	static setContext( value ) {
47316
47317		_context = value;
47318
47319	}
47320
47321}
47322
47323class AudioLoader extends Loader {
47324
47325	constructor( manager ) {
47326
47327		super( manager );
47328
47329	}
47330
47331	load( url, onLoad, onProgress, onError ) {
47332
47333		const scope = this;
47334
47335		const loader = new FileLoader( this.manager );
47336		loader.setResponseType( 'arraybuffer' );
47337		loader.setPath( this.path );
47338		loader.setRequestHeader( this.requestHeader );
47339		loader.setWithCredentials( this.withCredentials );
47340		loader.load( url, function ( buffer ) {
47341
47342			try {
47343
47344				// Create a copy of the buffer. The `decodeAudioData` method
47345				// detaches the buffer when complete, preventing reuse.
47346				const bufferCopy = buffer.slice( 0 );
47347
47348				const context = AudioContext.getContext();
47349				context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
47350
47351					onLoad( audioBuffer );
47352
47353				} ).catch( handleError );
47354
47355			} catch ( e ) {
47356
47357				handleError( e );
47358
47359			}
47360
47361		}, onProgress, onError );
47362
47363		function handleError( e ) {
47364
47365			if ( onError ) {
47366
47367				onError( e );
47368
47369			} else {
47370
47371				console.error( e );
47372
47373			}
47374
47375			scope.manager.itemError( url );
47376
47377		}
47378
47379	}
47380
47381}
47382
47383const _eyeRight = /*@__PURE__*/ new Matrix4();
47384const _eyeLeft = /*@__PURE__*/ new Matrix4();
47385const _projectionMatrix = /*@__PURE__*/ new Matrix4();
47386
47387class StereoCamera {
47388
47389	constructor() {
47390
47391		this.type = 'StereoCamera';
47392
47393		this.aspect = 1;
47394
47395		this.eyeSep = 0.064;
47396
47397		this.cameraL = new PerspectiveCamera();
47398		this.cameraL.layers.enable( 1 );
47399		this.cameraL.matrixAutoUpdate = false;
47400
47401		this.cameraR = new PerspectiveCamera();
47402		this.cameraR.layers.enable( 2 );
47403		this.cameraR.matrixAutoUpdate = false;
47404
47405		this._cache = {
47406			focus: null,
47407			fov: null,
47408			aspect: null,
47409			near: null,
47410			far: null,
47411			zoom: null,
47412			eyeSep: null
47413		};
47414
47415	}
47416
47417	update( camera ) {
47418
47419		const cache = this._cache;
47420
47421		const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
47422			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
47423			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
47424
47425		if ( needsUpdate ) {
47426
47427			cache.focus = camera.focus;
47428			cache.fov = camera.fov;
47429			cache.aspect = camera.aspect * this.aspect;
47430			cache.near = camera.near;
47431			cache.far = camera.far;
47432			cache.zoom = camera.zoom;
47433			cache.eyeSep = this.eyeSep;
47434
47435			// Off-axis stereoscopic effect based on
47436			// http://paulbourke.net/stereographics/stereorender/
47437
47438			_projectionMatrix.copy( camera.projectionMatrix );
47439			const eyeSepHalf = cache.eyeSep / 2;
47440			const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
47441			const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
47442			let xmin, xmax;
47443
47444			// translate xOffset
47445
47446			_eyeLeft.elements[ 12 ] = - eyeSepHalf;
47447			_eyeRight.elements[ 12 ] = eyeSepHalf;
47448
47449			// for left eye
47450
47451			xmin = - ymax * cache.aspect + eyeSepOnProjection;
47452			xmax = ymax * cache.aspect + eyeSepOnProjection;
47453
47454			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
47455			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
47456
47457			this.cameraL.projectionMatrix.copy( _projectionMatrix );
47458
47459			// for right eye
47460
47461			xmin = - ymax * cache.aspect - eyeSepOnProjection;
47462			xmax = ymax * cache.aspect - eyeSepOnProjection;
47463
47464			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
47465			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
47466
47467			this.cameraR.projectionMatrix.copy( _projectionMatrix );
47468
47469		}
47470
47471		this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
47472		this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
47473
47474	}
47475
47476}
47477
47478class Clock {
47479
47480	constructor( autoStart = true ) {
47481
47482		this.autoStart = autoStart;
47483
47484		this.startTime = 0;
47485		this.oldTime = 0;
47486		this.elapsedTime = 0;
47487
47488		this.running = false;
47489
47490	}
47491
47492	start() {
47493
47494		this.startTime = now();
47495
47496		this.oldTime = this.startTime;
47497		this.elapsedTime = 0;
47498		this.running = true;
47499
47500	}
47501
47502	stop() {
47503
47504		this.getElapsedTime();
47505		this.running = false;
47506		this.autoStart = false;
47507
47508	}
47509
47510	getElapsedTime() {
47511
47512		this.getDelta();
47513		return this.elapsedTime;
47514
47515	}
47516
47517	getDelta() {
47518
47519		let diff = 0;
47520
47521		if ( this.autoStart && ! this.running ) {
47522
47523			this.start();
47524			return 0;
47525
47526		}
47527
47528		if ( this.running ) {
47529
47530			const newTime = now();
47531
47532			diff = ( newTime - this.oldTime ) / 1000;
47533			this.oldTime = newTime;
47534
47535			this.elapsedTime += diff;
47536
47537		}
47538
47539		return diff;
47540
47541	}
47542
47543}
47544
47545function now() {
47546
47547	return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
47548
47549}
47550
47551const _position$1 = /*@__PURE__*/ new Vector3();
47552const _quaternion$1 = /*@__PURE__*/ new Quaternion();
47553const _scale$1 = /*@__PURE__*/ new Vector3();
47554const _orientation$1 = /*@__PURE__*/ new Vector3();
47555
47556class AudioListener extends Object3D {
47557
47558	constructor() {
47559
47560		super();
47561
47562		this.type = 'AudioListener';
47563
47564		this.context = AudioContext.getContext();
47565
47566		this.gain = this.context.createGain();
47567		this.gain.connect( this.context.destination );
47568
47569		this.filter = null;
47570
47571		this.timeDelta = 0;
47572
47573		// private
47574
47575		this._clock = new Clock();
47576
47577	}
47578
47579	getInput() {
47580
47581		return this.gain;
47582
47583	}
47584
47585	removeFilter() {
47586
47587		if ( this.filter !== null ) {
47588
47589			this.gain.disconnect( this.filter );
47590			this.filter.disconnect( this.context.destination );
47591			this.gain.connect( this.context.destination );
47592			this.filter = null;
47593
47594		}
47595
47596		return this;
47597
47598	}
47599
47600	getFilter() {
47601
47602		return this.filter;
47603
47604	}
47605
47606	setFilter( value ) {
47607
47608		if ( this.filter !== null ) {
47609
47610			this.gain.disconnect( this.filter );
47611			this.filter.disconnect( this.context.destination );
47612
47613		} else {
47614
47615			this.gain.disconnect( this.context.destination );
47616
47617		}
47618
47619		this.filter = value;
47620		this.gain.connect( this.filter );
47621		this.filter.connect( this.context.destination );
47622
47623		return this;
47624
47625	}
47626
47627	getMasterVolume() {
47628
47629		return this.gain.gain.value;
47630
47631	}
47632
47633	setMasterVolume( value ) {
47634
47635		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
47636
47637		return this;
47638
47639	}
47640
47641	updateMatrixWorld( force ) {
47642
47643		super.updateMatrixWorld( force );
47644
47645		const listener = this.context.listener;
47646		const up = this.up;
47647
47648		this.timeDelta = this._clock.getDelta();
47649
47650		this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 );
47651
47652		_orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 );
47653
47654		if ( listener.positionX ) {
47655
47656			// code path for Chrome (see #14393)
47657
47658			const endTime = this.context.currentTime + this.timeDelta;
47659
47660			listener.positionX.linearRampToValueAtTime( _position$1.x, endTime );
47661			listener.positionY.linearRampToValueAtTime( _position$1.y, endTime );
47662			listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime );
47663			listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime );
47664			listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime );
47665			listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime );
47666			listener.upX.linearRampToValueAtTime( up.x, endTime );
47667			listener.upY.linearRampToValueAtTime( up.y, endTime );
47668			listener.upZ.linearRampToValueAtTime( up.z, endTime );
47669
47670		} else {
47671
47672			listener.setPosition( _position$1.x, _position$1.y, _position$1.z );
47673			listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z );
47674
47675		}
47676
47677	}
47678
47679}
47680
47681class Audio extends Object3D {
47682
47683	constructor( listener ) {
47684
47685		super();
47686
47687		this.type = 'Audio';
47688
47689		this.listener = listener;
47690		this.context = listener.context;
47691
47692		this.gain = this.context.createGain();
47693		this.gain.connect( listener.getInput() );
47694
47695		this.autoplay = false;
47696
47697		this.buffer = null;
47698		this.detune = 0;
47699		this.loop = false;
47700		this.loopStart = 0;
47701		this.loopEnd = 0;
47702		this.offset = 0;
47703		this.duration = undefined;
47704		this.playbackRate = 1;
47705		this.isPlaying = false;
47706		this.hasPlaybackControl = true;
47707		this.source = null;
47708		this.sourceType = 'empty';
47709
47710		this._startedAt = 0;
47711		this._progress = 0;
47712		this._connected = false;
47713
47714		this.filters = [];
47715
47716	}
47717
47718	getOutput() {
47719
47720		return this.gain;
47721
47722	}
47723
47724	setNodeSource( audioNode ) {
47725
47726		this.hasPlaybackControl = false;
47727		this.sourceType = 'audioNode';
47728		this.source = audioNode;
47729		this.connect();
47730
47731		return this;
47732
47733	}
47734
47735	setMediaElementSource( mediaElement ) {
47736
47737		this.hasPlaybackControl = false;
vendor: 8,682 bytes, lines 47738-48281
47738		this.sourceType = 'mediaNode';
47739		this.source = this.context.createMediaElementSource( mediaElement );
47740		this.connect();
47741
47742		return this;
47743
47744	}
47745
47746	setMediaStreamSource( mediaStream ) {
47747
47748		this.hasPlaybackControl = false;
47749		this.sourceType = 'mediaStreamNode';
47750		this.source = this.context.createMediaStreamSource( mediaStream );
47751		this.connect();
47752
47753		return this;
47754
47755	}
47756
47757	setBuffer( audioBuffer ) {
47758
47759		this.buffer = audioBuffer;
47760		this.sourceType = 'buffer';
47761
47762		if ( this.autoplay ) this.play();
47763
47764		return this;
47765
47766	}
47767
47768	play( delay = 0 ) {
47769
47770		if ( this.isPlaying === true ) {
47771
47772			console.warn( 'THREE.Audio: Audio is already playing.' );
47773			return;
47774
47775		}
47776
47777		if ( this.hasPlaybackControl === false ) {
47778
47779			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47780			return;
47781
47782		}
47783
47784		this._startedAt = this.context.currentTime + delay;
47785
47786		const source = this.context.createBufferSource();
47787		source.buffer = this.buffer;
47788		source.loop = this.loop;
47789		source.loopStart = this.loopStart;
47790		source.loopEnd = this.loopEnd;
47791		source.onended = this.onEnded.bind( this );
47792		source.start( this._startedAt, this._progress + this.offset, this.duration );
47793
47794		this.isPlaying = true;
47795
47796		this.source = source;
47797
47798		this.setDetune( this.detune );
47799		this.setPlaybackRate( this.playbackRate );
47800
47801		return this.connect();
47802
47803	}
47804
47805	pause() {
47806
47807		if ( this.hasPlaybackControl === false ) {
47808
47809			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47810			return;
47811
47812		}
47813
47814		if ( this.isPlaying === true ) {
47815
47816			// update current progress
47817
47818			this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
47819
47820			if ( this.loop === true ) {
47821
47822				// ensure _progress does not exceed duration with looped audios
47823
47824				this._progress = this._progress % ( this.duration || this.buffer.duration );
47825
47826			}
47827
47828			this.source.stop();
47829			this.source.onended = null;
47830
47831			this.isPlaying = false;
47832
47833		}
47834
47835		return this;
47836
47837	}
47838
47839	stop() {
47840
47841		if ( this.hasPlaybackControl === false ) {
47842
47843			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47844			return;
47845
47846		}
47847
47848		this._progress = 0;
47849
47850		if ( this.source !== null ) {
47851
47852			this.source.stop();
47853			this.source.onended = null;
47854
47855		}
47856
47857		this.isPlaying = false;
47858
47859		return this;
47860
47861	}
47862
47863	connect() {
47864
47865		if ( this.filters.length > 0 ) {
47866
47867			this.source.connect( this.filters[ 0 ] );
47868
47869			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
47870
47871				this.filters[ i - 1 ].connect( this.filters[ i ] );
47872
47873			}
47874
47875			this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
47876
47877		} else {
47878
47879			this.source.connect( this.getOutput() );
47880
47881		}
47882
47883		this._connected = true;
47884
47885		return this;
47886
47887	}
47888
47889	disconnect() {
47890
47891		if ( this._connected === false ) {
47892
47893			return;
47894
47895		}
47896
47897		if ( this.filters.length > 0 ) {
47898
47899			this.source.disconnect( this.filters[ 0 ] );
47900
47901			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
47902
47903				this.filters[ i - 1 ].disconnect( this.filters[ i ] );
47904
47905			}
47906
47907			this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
47908
47909		} else {
47910
47911			this.source.disconnect( this.getOutput() );
47912
47913		}
47914
47915		this._connected = false;
47916
47917		return this;
47918
47919	}
47920
47921	getFilters() {
47922
47923		return this.filters;
47924
47925	}
47926
47927	setFilters( value ) {
47928
47929		if ( ! value ) value = [];
47930
47931		if ( this._connected === true ) {
47932
47933			this.disconnect();
47934			this.filters = value.slice();
47935			this.connect();
47936
47937		} else {
47938
47939			this.filters = value.slice();
47940
47941		}
47942
47943		return this;
47944
47945	}
47946
47947	setDetune( value ) {
47948
47949		this.detune = value;
47950
47951		if ( this.isPlaying === true && this.source.detune !== undefined ) {
47952
47953			this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
47954
47955		}
47956
47957		return this;
47958
47959	}
47960
47961	getDetune() {
47962
47963		return this.detune;
47964
47965	}
47966
47967	getFilter() {
47968
47969		return this.getFilters()[ 0 ];
47970
47971	}
47972
47973	setFilter( filter ) {
47974
47975		return this.setFilters( filter ? [ filter ] : [] );
47976
47977	}
47978
47979	setPlaybackRate( value ) {
47980
47981		if ( this.hasPlaybackControl === false ) {
47982
47983			console.warn( 'THREE.Audio: this Audio has no playback control.' );
47984			return;
47985
47986		}
47987
47988		this.playbackRate = value;
47989
47990		if ( this.isPlaying === true ) {
47991
47992			this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
47993
47994		}
47995
47996		return this;
47997
47998	}
47999
48000	getPlaybackRate() {
48001
48002		return this.playbackRate;
48003
48004	}
48005
48006	onEnded() {
48007
48008		this.isPlaying = false;
48009
48010	}
48011
48012	getLoop() {
48013
48014		if ( this.hasPlaybackControl === false ) {
48015
48016			console.warn( 'THREE.Audio: this Audio has no playback control.' );
48017			return false;
48018
48019		}
48020
48021		return this.loop;
48022
48023	}
48024
48025	setLoop( value ) {
48026
48027		if ( this.hasPlaybackControl === false ) {
48028
48029			console.warn( 'THREE.Audio: this Audio has no playback control.' );
48030			return;
48031
48032		}
48033
48034		this.loop = value;
48035
48036		if ( this.isPlaying === true ) {
48037
48038			this.source.loop = this.loop;
48039
48040		}
48041
48042		return this;
48043
48044	}
48045
48046	setLoopStart( value ) {
48047
48048		this.loopStart = value;
48049
48050		return this;
48051
48052	}
48053
48054	setLoopEnd( value ) {
48055
48056		this.loopEnd = value;
48057
48058		return this;
48059
48060	}
48061
48062	getVolume() {
48063
48064		return this.gain.gain.value;
48065
48066	}
48067
48068	setVolume( value ) {
48069
48070		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
48071
48072		return this;
48073
48074	}
48075
48076}
48077
48078const _position = /*@__PURE__*/ new Vector3();
48079const _quaternion = /*@__PURE__*/ new Quaternion();
48080const _scale = /*@__PURE__*/ new Vector3();
48081const _orientation = /*@__PURE__*/ new Vector3();
48082
48083class PositionalAudio extends Audio {
48084
48085	constructor( listener ) {
48086
48087		super( listener );
48088
48089		this.panner = this.context.createPanner();
48090		this.panner.panningModel = 'HRTF';
48091		this.panner.connect( this.gain );
48092
48093	}
48094
48095	connect() {
48096
48097		super.connect();
48098
48099		this.panner.connect( this.gain );
48100
48101	}
48102
48103	disconnect() {
48104
48105		super.disconnect();
48106
48107		this.panner.disconnect( this.gain );
48108
48109	}
48110
48111	getOutput() {
48112
48113		return this.panner;
48114
48115	}
48116
48117	getRefDistance() {
48118
48119		return this.panner.refDistance;
48120
48121	}
48122
48123	setRefDistance( value ) {
48124
48125		this.panner.refDistance = value;
48126
48127		return this;
48128
48129	}
48130
48131	getRolloffFactor() {
48132
48133		return this.panner.rolloffFactor;
48134
48135	}
48136
48137	setRolloffFactor( value ) {
48138
48139		this.panner.rolloffFactor = value;
48140
48141		return this;
48142
48143	}
48144
48145	getDistanceModel() {
48146
48147		return this.panner.distanceModel;
48148
48149	}
48150
48151	setDistanceModel( value ) {
48152
48153		this.panner.distanceModel = value;
48154
48155		return this;
48156
48157	}
48158
48159	getMaxDistance() {
48160
48161		return this.panner.maxDistance;
48162
48163	}
48164
48165	setMaxDistance( value ) {
48166
48167		this.panner.maxDistance = value;
48168
48169		return this;
48170
48171	}
48172
48173	setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
48174
48175		this.panner.coneInnerAngle = coneInnerAngle;
48176		this.panner.coneOuterAngle = coneOuterAngle;
48177		this.panner.coneOuterGain = coneOuterGain;
48178
48179		return this;
48180
48181	}
48182
48183	updateMatrixWorld( force ) {
48184
48185		super.updateMatrixWorld( force );
48186
48187		if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
48188
48189		this.matrixWorld.decompose( _position, _quaternion, _scale );
48190
48191		_orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
48192
48193		const panner = this.panner;
48194
48195		if ( panner.positionX ) {
48196
48197			// code path for Chrome and Firefox (see #14393)
48198
48199			const endTime = this.context.currentTime + this.listener.timeDelta;
48200
48201			panner.positionX.linearRampToValueAtTime( _position.x, endTime );
48202			panner.positionY.linearRampToValueAtTime( _position.y, endTime );
48203			panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
48204			panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
48205			panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
48206			panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
48207
48208		} else {
48209
48210			panner.setPosition( _position.x, _position.y, _position.z );
48211			panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
48212
48213		}
48214
48215	}
48216
48217}
48218
48219class AudioAnalyser {
48220
48221	constructor( audio, fftSize = 2048 ) {
48222
48223		this.analyser = audio.context.createAnalyser();
48224		this.analyser.fftSize = fftSize;
48225
48226		this.data = new Uint8Array( this.analyser.frequencyBinCount );
48227
48228		audio.getOutput().connect( this.analyser );
48229
48230	}
48231
48232
48233	getFrequencyData() {
48234
48235		this.analyser.getByteFrequencyData( this.data );
48236
48237		return this.data;
48238
48239	}
48240
48241	getAverageFrequency() {
48242
48243		let value = 0;
48244		const data = this.getFrequencyData();
48245
48246		for ( let i = 0; i < data.length; i ++ ) {
48247
48248			value += data[ i ];
48249
48250		}
48251
48252		return value / data.length;
48253
48254	}
48255
48256}
48257
48258class PropertyMixer {
48259
48260	constructor( binding, typeName, valueSize ) {
48261
48262		this.binding = binding;
48263		this.valueSize = valueSize;
48264
48265		let mixFunction,
48266			mixFunctionAdditive,
48267			setIdentity;
48268
48269		// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
48270		//
48271		// interpolators can use .buffer as their .result
48272		// the data then goes to 'incoming'
48273		//
48274		// 'accu0' and 'accu1' are used frame-interleaved for
48275		// the cumulative result and are compared to detect
48276		// changes
48277		//
48278		// 'orig' stores the original state of the property
48279		//
48280		// 'add' is used for additive cumulative results
48281		//
vendor: 13,778 bytes, lines 48282-48912
48282		// 'work' is optional and is only present for quaternion types. It is used
48283		// to store intermediate quaternion multiplication results
48284
48285		switch ( typeName ) {
48286
48287			case 'quaternion':
48288				mixFunction = this._slerp;
48289				mixFunctionAdditive = this._slerpAdditive;
48290				setIdentity = this._setAdditiveIdentityQuaternion;
48291
48292				this.buffer = new Float64Array( valueSize * 6 );
48293				this._workIndex = 5;
48294				break;
48295
48296			case 'string':
48297			case 'bool':
48298				mixFunction = this._select;
48299
48300				// Use the regular mix function and for additive on these types,
48301				// additive is not relevant for non-numeric types
48302				mixFunctionAdditive = this._select;
48303
48304				setIdentity = this._setAdditiveIdentityOther;
48305
48306				this.buffer = new Array( valueSize * 5 );
48307				break;
48308
48309			default:
48310				mixFunction = this._lerp;
48311				mixFunctionAdditive = this._lerpAdditive;
48312				setIdentity = this._setAdditiveIdentityNumeric;
48313
48314				this.buffer = new Float64Array( valueSize * 5 );
48315
48316		}
48317
48318		this._mixBufferRegion = mixFunction;
48319		this._mixBufferRegionAdditive = mixFunctionAdditive;
48320		this._setIdentity = setIdentity;
48321		this._origIndex = 3;
48322		this._addIndex = 4;
48323
48324		this.cumulativeWeight = 0;
48325		this.cumulativeWeightAdditive = 0;
48326
48327		this.useCount = 0;
48328		this.referenceCount = 0;
48329
48330	}
48331
48332	// accumulate data in the 'incoming' region into 'accu<i>'
48333	accumulate( accuIndex, weight ) {
48334
48335		// note: happily accumulating nothing when weight = 0, the caller knows
48336		// the weight and shouldn't have made the call in the first place
48337
48338		const buffer = this.buffer,
48339			stride = this.valueSize,
48340			offset = accuIndex * stride + stride;
48341
48342		let currentWeight = this.cumulativeWeight;
48343
48344		if ( currentWeight === 0 ) {
48345
48346			// accuN := incoming * weight
48347
48348			for ( let i = 0; i !== stride; ++ i ) {
48349
48350				buffer[ offset + i ] = buffer[ i ];
48351
48352			}
48353
48354			currentWeight = weight;
48355
48356		} else {
48357
48358			// accuN := accuN + incoming * weight
48359
48360			currentWeight += weight;
48361			const mix = weight / currentWeight;
48362			this._mixBufferRegion( buffer, offset, 0, mix, stride );
48363
48364		}
48365
48366		this.cumulativeWeight = currentWeight;
48367
48368	}
48369
48370	// accumulate data in the 'incoming' region into 'add'
48371	accumulateAdditive( weight ) {
48372
48373		const buffer = this.buffer,
48374			stride = this.valueSize,
48375			offset = stride * this._addIndex;
48376
48377		if ( this.cumulativeWeightAdditive === 0 ) {
48378
48379			// add = identity
48380
48381			this._setIdentity();
48382
48383		}
48384
48385		// add := add + incoming * weight
48386
48387		this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
48388		this.cumulativeWeightAdditive += weight;
48389
48390	}
48391
48392	// apply the state of 'accu<i>' to the binding when accus differ
48393	apply( accuIndex ) {
48394
48395		const stride = this.valueSize,
48396			buffer = this.buffer,
48397			offset = accuIndex * stride + stride,
48398
48399			weight = this.cumulativeWeight,
48400			weightAdditive = this.cumulativeWeightAdditive,
48401
48402			binding = this.binding;
48403
48404		this.cumulativeWeight = 0;
48405		this.cumulativeWeightAdditive = 0;
48406
48407		if ( weight < 1 ) {
48408
48409			// accuN := accuN + original * ( 1 - cumulativeWeight )
48410
48411			const originalValueOffset = stride * this._origIndex;
48412
48413			this._mixBufferRegion(
48414				buffer, offset, originalValueOffset, 1 - weight, stride );
48415
48416		}
48417
48418		if ( weightAdditive > 0 ) {
48419
48420			// accuN := accuN + additive accuN
48421
48422			this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
48423
48424		}
48425
48426		for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
48427
48428			if ( buffer[ i ] !== buffer[ i + stride ] ) {
48429
48430				// value has changed -> update scene graph
48431
48432				binding.setValue( buffer, offset );
48433				break;
48434
48435			}
48436
48437		}
48438
48439	}
48440
48441	// remember the state of the bound property and copy it to both accus
48442	saveOriginalState() {
48443
48444		const binding = this.binding;
48445
48446		const buffer = this.buffer,
48447			stride = this.valueSize,
48448
48449			originalValueOffset = stride * this._origIndex;
48450
48451		binding.getValue( buffer, originalValueOffset );
48452
48453		// accu[0..1] := orig -- initially detect changes against the original
48454		for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
48455
48456			buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
48457
48458		}
48459
48460		// Add to identity for additive
48461		this._setIdentity();
48462
48463		this.cumulativeWeight = 0;
48464		this.cumulativeWeightAdditive = 0;
48465
48466	}
48467
48468	// apply the state previously taken via 'saveOriginalState' to the binding
48469	restoreOriginalState() {
48470
48471		const originalValueOffset = this.valueSize * 3;
48472		this.binding.setValue( this.buffer, originalValueOffset );
48473
48474	}
48475
48476	_setAdditiveIdentityNumeric() {
48477
48478		const startIndex = this._addIndex * this.valueSize;
48479		const endIndex = startIndex + this.valueSize;
48480
48481		for ( let i = startIndex; i < endIndex; i ++ ) {
48482
48483			this.buffer[ i ] = 0;
48484
48485		}
48486
48487	}
48488
48489	_setAdditiveIdentityQuaternion() {
48490
48491		this._setAdditiveIdentityNumeric();
48492		this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
48493
48494	}
48495
48496	_setAdditiveIdentityOther() {
48497
48498		const startIndex = this._origIndex * this.valueSize;
48499		const targetIndex = this._addIndex * this.valueSize;
48500
48501		for ( let i = 0; i < this.valueSize; i ++ ) {
48502
48503			this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
48504
48505		}
48506
48507	}
48508
48509
48510	// mix functions
48511
48512	_select( buffer, dstOffset, srcOffset, t, stride ) {
48513
48514		if ( t >= 0.5 ) {
48515
48516			for ( let i = 0; i !== stride; ++ i ) {
48517
48518				buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
48519
48520			}
48521
48522		}
48523
48524	}
48525
48526	_slerp( buffer, dstOffset, srcOffset, t ) {
48527
48528		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
48529
48530	}
48531
48532	_slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
48533
48534		const workOffset = this._workIndex * stride;
48535
48536		// Store result in intermediate buffer offset
48537		Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
48538
48539		// Slerp to the intermediate result
48540		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
48541
48542	}
48543
48544	_lerp( buffer, dstOffset, srcOffset, t, stride ) {
48545
48546		const s = 1 - t;
48547
48548		for ( let i = 0; i !== stride; ++ i ) {
48549
48550			const j = dstOffset + i;
48551
48552			buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
48553
48554		}
48555
48556	}
48557
48558	_lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
48559
48560		for ( let i = 0; i !== stride; ++ i ) {
48561
48562			const j = dstOffset + i;
48563
48564			buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
48565
48566		}
48567
48568	}
48569
48570}
48571
48572// Characters [].:/ are reserved for track binding syntax.
48573const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
48574const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
48575
48576// Attempts to allow node names from any language. ES5's `\w` regexp matches
48577// only latin characters, and the unicode \p{L} is not yet supported. So
48578// instead, we exclude reserved characters and match everything else.
48579const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
48580const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
48581
48582// Parent directories, delimited by '/' or ':'. Currently unused, but must
48583// be matched to parse the rest of the track name.
48584const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
48585
48586// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
48587const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
48588
48589// Object on target node, and accessor. May not contain reserved
48590// characters. Accessor may contain any character except closing bracket.
48591const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
48592
48593// Property and accessor. May not contain reserved characters. Accessor may
48594// contain any non-bracket characters.
48595const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
48596
48597const _trackRe = new RegExp( ''
48598	+ '^'
48599	+ _directoryRe
48600	+ _nodeRe
48601	+ _objectRe
48602	+ _propertyRe
48603	+ '$'
48604);
48605
48606const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ];
48607
48608class Composite {
48609
48610	constructor( targetGroup, path, optionalParsedPath ) {
48611
48612		const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
48613
48614		this._targetGroup = targetGroup;
48615		this._bindings = targetGroup.subscribe_( path, parsedPath );
48616
48617	}
48618
48619	getValue( array, offset ) {
48620
48621		this.bind(); // bind all binding
48622
48623		const firstValidIndex = this._targetGroup.nCachedObjects_,
48624			binding = this._bindings[ firstValidIndex ];
48625
48626		// and only call .getValue on the first
48627		if ( binding !== undefined ) binding.getValue( array, offset );
48628
48629	}
48630
48631	setValue( array, offset ) {
48632
48633		const bindings = this._bindings;
48634
48635		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
48636
48637			bindings[ i ].setValue( array, offset );
48638
48639		}
48640
48641	}
48642
48643	bind() {
48644
48645		const bindings = this._bindings;
48646
48647		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
48648
48649			bindings[ i ].bind();
48650
48651		}
48652
48653	}
48654
48655	unbind() {
48656
48657		const bindings = this._bindings;
48658
48659		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
48660
48661			bindings[ i ].unbind();
48662
48663		}
48664
48665	}
48666
48667}
48668
48669// Note: This class uses a State pattern on a per-method basis:
48670// 'bind' sets 'this.getValue' / 'setValue' and shadows the
48671// prototype version of these methods with one that represents
48672// the bound state. When the property is not found, the methods
48673// become no-ops.
48674class PropertyBinding {
48675
48676	constructor( rootNode, path, parsedPath ) {
48677
48678		this.path = path;
48679		this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
48680
48681		this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
48682
48683		this.rootNode = rootNode;
48684
48685		// initial state of these methods that calls 'bind'
48686		this.getValue = this._getValue_unbound;
48687		this.setValue = this._setValue_unbound;
48688
48689	}
48690
48691
48692	static create( root, path, parsedPath ) {
48693
48694		if ( ! ( root && root.isAnimationObjectGroup ) ) {
48695
48696			return new PropertyBinding( root, path, parsedPath );
48697
48698		} else {
48699
48700			return new PropertyBinding.Composite( root, path, parsedPath );
48701
48702		}
48703
48704	}
48705
48706	/**
48707	 * Replaces spaces with underscores and removes unsupported characters from
48708	 * node names, to ensure compatibility with parseTrackName().
48709	 *
48710	 * @param {string} name Node name to be sanitized.
48711	 * @return {string}
48712	 */
48713	static sanitizeNodeName( name ) {
48714
48715		return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
48716
48717	}
48718
48719	static parseTrackName( trackName ) {
48720
48721		const matches = _trackRe.exec( trackName );
48722
48723		if ( matches === null ) {
48724
48725			throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
48726
48727		}
48728
48729		const results = {
48730			// directoryName: matches[ 1 ], // (tschw) currently unused
48731			nodeName: matches[ 2 ],
48732			objectName: matches[ 3 ],
48733			objectIndex: matches[ 4 ],
48734			propertyName: matches[ 5 ], // required
48735			propertyIndex: matches[ 6 ]
48736		};
48737
48738		const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
48739
48740		if ( lastDot !== undefined && lastDot !== - 1 ) {
48741
48742			const objectName = results.nodeName.substring( lastDot + 1 );
48743
48744			// Object names must be checked against an allowlist. Otherwise, there
48745			// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
48746			// 'bar' could be the objectName, or part of a nodeName (which can
48747			// include '.' characters).
48748			if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
48749
48750				results.nodeName = results.nodeName.substring( 0, lastDot );
48751				results.objectName = objectName;
48752
48753			}
48754
48755		}
48756
48757		if ( results.propertyName === null || results.propertyName.length === 0 ) {
48758
48759			throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
48760
48761		}
48762
48763		return results;
48764
48765	}
48766
48767	static findNode( root, nodeName ) {
48768
48769		if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
48770
48771			return root;
48772
48773		}
48774
48775		// search into skeleton bones.
48776		if ( root.skeleton ) {
48777
48778			const bone = root.skeleton.getBoneByName( nodeName );
48779
48780			if ( bone !== undefined ) {
48781
48782				return bone;
48783
48784			}
48785
48786		}
48787
48788		// search into node subtree.
48789		if ( root.children ) {
48790
48791			const searchNodeSubtree = function ( children ) {
48792
48793				for ( let i = 0; i < children.length; i ++ ) {
48794
48795					const childNode = children[ i ];
48796
48797					if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
48798
48799						return childNode;
48800
48801					}
48802
48803					const result = searchNodeSubtree( childNode.children );
48804
48805					if ( result ) return result;
48806
48807				}
48808
48809				return null;
48810
48811			};
48812
48813			const subTreeNode = searchNodeSubtree( root.children );
48814
48815			if ( subTreeNode ) {
48816
48817				return subTreeNode;
48818
48819			}
48820
48821		}
48822
48823		return null;
48824
48825	}
48826
48827	// these are used to "bind" a nonexistent property
48828	_getValue_unavailable() {}
48829	_setValue_unavailable() {}
48830
48831	// Getters
48832
48833	_getValue_direct( buffer, offset ) {
48834
48835		buffer[ offset ] = this.targetObject[ this.propertyName ];
48836
48837	}
48838
48839	_getValue_array( buffer, offset ) {
48840
48841		const source = this.resolvedProperty;
48842
48843		for ( let i = 0, n = source.length; i !== n; ++ i ) {
48844
48845			buffer[ offset ++ ] = source[ i ];
48846
48847		}
48848
48849	}
48850
48851	_getValue_arrayElement( buffer, offset ) {
48852
48853		buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
48854
48855	}
48856
48857	_getValue_toArray( buffer, offset ) {
48858
48859		this.resolvedProperty.toArray( buffer, offset );
48860
48861	}
48862
48863	// Direct
48864
48865	_setValue_direct( buffer, offset ) {
48866
48867		this.targetObject[ this.propertyName ] = buffer[ offset ];
48868
48869	}
48870
48871	_setValue_direct_setNeedsUpdate( buffer, offset ) {
48872
48873		this.targetObject[ this.propertyName ] = buffer[ offset ];
48874		this.targetObject.needsUpdate = true;
48875
48876	}
48877
48878	_setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
48879
48880		this.targetObject[ this.propertyName ] = buffer[ offset ];
48881		this.targetObject.matrixWorldNeedsUpdate = true;
48882
48883	}
48884
48885	// EntireArray
48886
48887	_setValue_array( buffer, offset ) {
48888
48889		const dest = this.resolvedProperty;
48890
48891		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48892
48893			dest[ i ] = buffer[ offset ++ ];
48894
48895		}
48896
48897	}
48898
48899	_setValue_array_setNeedsUpdate( buffer, offset ) {
48900
48901		const dest = this.resolvedProperty;
48902
48903		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48904
48905			dest[ i ] = buffer[ offset ++ ];
48906
48907		}
48908
48909		this.targetObject.needsUpdate = true;
48910
48911	}
48912
vendor: 8,185 bytes, lines 48913-49268
48913	_setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
48914
48915		const dest = this.resolvedProperty;
48916
48917		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48918
48919			dest[ i ] = buffer[ offset ++ ];
48920
48921		}
48922
48923		this.targetObject.matrixWorldNeedsUpdate = true;
48924
48925	}
48926
48927	// ArrayElement
48928
48929	_setValue_arrayElement( buffer, offset ) {
48930
48931		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48932
48933	}
48934
48935	_setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
48936
48937		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48938		this.targetObject.needsUpdate = true;
48939
48940	}
48941
48942	_setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
48943
48944		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48945		this.targetObject.matrixWorldNeedsUpdate = true;
48946
48947	}
48948
48949	// HasToFromArray
48950
48951	_setValue_fromArray( buffer, offset ) {
48952
48953		this.resolvedProperty.fromArray( buffer, offset );
48954
48955	}
48956
48957	_setValue_fromArray_setNeedsUpdate( buffer, offset ) {
48958
48959		this.resolvedProperty.fromArray( buffer, offset );
48960		this.targetObject.needsUpdate = true;
48961
48962	}
48963
48964	_setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
48965
48966		this.resolvedProperty.fromArray( buffer, offset );
48967		this.targetObject.matrixWorldNeedsUpdate = true;
48968
48969	}
48970
48971	_getValue_unbound( targetArray, offset ) {
48972
48973		this.bind();
48974		this.getValue( targetArray, offset );
48975
48976	}
48977
48978	_setValue_unbound( sourceArray, offset ) {
48979
48980		this.bind();
48981		this.setValue( sourceArray, offset );
48982
48983	}
48984
48985	// create getter / setter pair for a property in the scene graph
48986	bind() {
48987
48988		let targetObject = this.node;
48989		const parsedPath = this.parsedPath;
48990
48991		const objectName = parsedPath.objectName;
48992		const propertyName = parsedPath.propertyName;
48993		let propertyIndex = parsedPath.propertyIndex;
48994
48995		if ( ! targetObject ) {
48996
48997			targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName );
48998
48999			this.node = targetObject;
49000
49001		}
49002
49003		// set fail state so we can just 'return' on error
49004		this.getValue = this._getValue_unavailable;
49005		this.setValue = this._setValue_unavailable;
49006
49007		// ensure there is a value node
49008		if ( ! targetObject ) {
49009
49010			console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' );
49011			return;
49012
49013		}
49014
49015		if ( objectName ) {
49016
49017			let objectIndex = parsedPath.objectIndex;
49018
49019			// special cases were we need to reach deeper into the hierarchy to get the face materials....
49020			switch ( objectName ) {
49021
49022				case 'materials':
49023
49024					if ( ! targetObject.material ) {
49025
49026						console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
49027						return;
49028
49029					}
49030
49031					if ( ! targetObject.material.materials ) {
49032
49033						console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
49034						return;
49035
49036					}
49037
49038					targetObject = targetObject.material.materials;
49039
49040					break;
49041
49042				case 'bones':
49043
49044					if ( ! targetObject.skeleton ) {
49045
49046						console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
49047						return;
49048
49049					}
49050
49051					// potential future optimization: skip this if propertyIndex is already an integer
49052					// and convert the integer string to a true integer.
49053
49054					targetObject = targetObject.skeleton.bones;
49055
49056					// support resolving morphTarget names into indices.
49057					for ( let i = 0; i < targetObject.length; i ++ ) {
49058
49059						if ( targetObject[ i ].name === objectIndex ) {
49060
49061							objectIndex = i;
49062							break;
49063
49064						}
49065
49066					}
49067
49068					break;
49069
49070				case 'map':
49071
49072					if ( 'map' in targetObject ) {
49073
49074						targetObject = targetObject.map;
49075						break;
49076
49077					}
49078
49079					if ( ! targetObject.material ) {
49080
49081						console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
49082						return;
49083
49084					}
49085
49086					if ( ! targetObject.material.map ) {
49087
49088						console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this );
49089						return;
49090
49091					}
49092
49093					targetObject = targetObject.material.map;
49094					break;
49095
49096				default:
49097
49098					if ( targetObject[ objectName ] === undefined ) {
49099
49100						console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
49101						return;
49102
49103					}
49104
49105					targetObject = targetObject[ objectName ];
49106
49107			}
49108
49109
49110			if ( objectIndex !== undefined ) {
49111
49112				if ( targetObject[ objectIndex ] === undefined ) {
49113
49114					console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
49115					return;
49116
49117				}
49118
49119				targetObject = targetObject[ objectIndex ];
49120
49121			}
49122
49123		}
49124
49125		// resolve property
49126		const nodeProperty = targetObject[ propertyName ];
49127
49128		if ( nodeProperty === undefined ) {
49129
49130			const nodeName = parsedPath.nodeName;
49131
49132			console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
49133				'.' + propertyName + ' but it wasn\'t found.', targetObject );
49134			return;
49135
49136		}
49137
49138		// determine versioning scheme
49139		let versioning = this.Versioning.None;
49140
49141		this.targetObject = targetObject;
49142
49143		if ( targetObject.needsUpdate !== undefined ) { // material
49144
49145			versioning = this.Versioning.NeedsUpdate;
49146
49147		} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
49148
49149			versioning = this.Versioning.MatrixWorldNeedsUpdate;
49150
49151		}
49152
49153		// determine how the property gets bound
49154		let bindingType = this.BindingType.Direct;
49155
49156		if ( propertyIndex !== undefined ) {
49157
49158			// access a sub element of the property array (only primitives are supported right now)
49159
49160			if ( propertyName === 'morphTargetInfluences' ) {
49161
49162				// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
49163
49164				// support resolving morphTarget names into indices.
49165				if ( ! targetObject.geometry ) {
49166
49167					console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
49168					return;
49169
49170				}
49171
49172				if ( ! targetObject.geometry.morphAttributes ) {
49173
49174					console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
49175					return;
49176
49177				}
49178
49179				if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
49180
49181					propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
49182
49183				}
49184
49185			}
49186
49187			bindingType = this.BindingType.ArrayElement;
49188
49189			this.resolvedProperty = nodeProperty;
49190			this.propertyIndex = propertyIndex;
49191
49192		} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
49193
49194			// must use copy for Object3D.Euler/Quaternion
49195
49196			bindingType = this.BindingType.HasFromToArray;
49197
49198			this.resolvedProperty = nodeProperty;
49199
49200		} else if ( Array.isArray( nodeProperty ) ) {
49201
49202			bindingType = this.BindingType.EntireArray;
49203
49204			this.resolvedProperty = nodeProperty;
49205
49206		} else {
49207
49208			this.propertyName = propertyName;
49209
49210		}
49211
49212		// select getter / setter
49213		this.getValue = this.GetterByBindingType[ bindingType ];
49214		this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
49215
49216	}
49217
49218	unbind() {
49219
49220		this.node = null;
49221
49222		// back to the prototype version of getValue / setValue
49223		// note: avoiding to mutate the shape of 'this' via 'delete'
49224		this.getValue = this._getValue_unbound;
49225		this.setValue = this._setValue_unbound;
49226
49227	}
49228
49229}
49230
49231PropertyBinding.Composite = Composite;
49232
49233PropertyBinding.prototype.BindingType = {
49234	Direct: 0,
49235	EntireArray: 1,
49236	ArrayElement: 2,
49237	HasFromToArray: 3
49238};
49239
49240PropertyBinding.prototype.Versioning = {
49241	None: 0,
49242	NeedsUpdate: 1,
49243	MatrixWorldNeedsUpdate: 2
49244};
49245
49246PropertyBinding.prototype.GetterByBindingType = [
49247
49248	PropertyBinding.prototype._getValue_direct,
49249	PropertyBinding.prototype._getValue_array,
49250	PropertyBinding.prototype._getValue_arrayElement,
49251	PropertyBinding.prototype._getValue_toArray,
49252
49253];
49254
49255PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
49256
49257	[
49258		// Direct
49259		PropertyBinding.prototype._setValue_direct,
49260		PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
49261		PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
49262
49263	], [
49264
49265		// EntireArray
49266
49267		PropertyBinding.prototype._setValue_array,
49268		PropertyBinding.prototype._setValue_array_setNeedsUpdate,
vendor: 4,282 bytes, lines 49269-49449
49269		PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
49270
49271	], [
49272
49273		// ArrayElement
49274		PropertyBinding.prototype._setValue_arrayElement,
49275		PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
49276		PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
49277
49278	], [
49279
49280		// HasToFromArray
49281		PropertyBinding.prototype._setValue_fromArray,
49282		PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
49283		PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
49284
49285	]
49286
49287];
49288
49289/**
49290 *
49291 * A group of objects that receives a shared animation state.
49292 *
49293 * Usage:
49294 *
49295 *  - Add objects you would otherwise pass as 'root' to the
49296 *    constructor or the .clipAction method of AnimationMixer.
49297 *
49298 *  - Instead pass this object as 'root'.
49299 *
49300 *  - You can also add and remove objects later when the mixer
49301 *    is running.
49302 *
49303 * Note:
49304 *
49305 *    Objects of this class appear as one object to the mixer,
49306 *    so cache control of the individual objects must be done
49307 *    on the group.
49308 *
49309 * Limitation:
49310 *
49311 *  - The animated properties must be compatible among the
49312 *    all objects in the group.
49313 *
49314 *  - A single property can either be controlled through a
49315 *    target group or directly, but not both.
49316 */
49317
49318class AnimationObjectGroup {
49319
49320	constructor() {
49321
49322		this.isAnimationObjectGroup = true;
49323
49324		this.uuid = generateUUID();
49325
49326		// cached objects followed by the active ones
49327		this._objects = Array.prototype.slice.call( arguments );
49328
49329		this.nCachedObjects_ = 0; // threshold
49330		// note: read by PropertyBinding.Composite
49331
49332		const indices = {};
49333		this._indicesByUUID = indices; // for bookkeeping
49334
49335		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
49336
49337			indices[ arguments[ i ].uuid ] = i;
49338
49339		}
49340
49341		this._paths = []; // inside: string
49342		this._parsedPaths = []; // inside: { we don't care, here }
49343		this._bindings = []; // inside: Array< PropertyBinding >
49344		this._bindingsIndicesByPath = {}; // inside: indices in these arrays
49345
49346		const scope = this;
49347
49348		this.stats = {
49349
49350			objects: {
49351				get total() {
49352
49353					return scope._objects.length;
49354
49355				},
49356				get inUse() {
49357
49358					return this.total - scope.nCachedObjects_;
49359
49360				}
49361			},
49362			get bindingsPerObject() {
49363
49364				return scope._bindings.length;
49365
49366			}
49367
49368		};
49369
49370	}
49371
49372	add() {
49373
49374		const objects = this._objects,
49375			indicesByUUID = this._indicesByUUID,
49376			paths = this._paths,
49377			parsedPaths = this._parsedPaths,
49378			bindings = this._bindings,
49379			nBindings = bindings.length;
49380
49381		let knownObject = undefined,
49382			nObjects = objects.length,
49383			nCachedObjects = this.nCachedObjects_;
49384
49385		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
49386
49387			const object = arguments[ i ],
49388				uuid = object.uuid;
49389			let index = indicesByUUID[ uuid ];
49390
49391			if ( index === undefined ) {
49392
49393				// unknown object -> add it to the ACTIVE region
49394
49395				index = nObjects ++;
49396				indicesByUUID[ uuid ] = index;
49397				objects.push( object );
49398
49399				// accounting is done, now do the same for all bindings
49400
49401				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49402
49403					bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
49404
49405				}
49406
49407			} else if ( index < nCachedObjects ) {
49408
49409				knownObject = objects[ index ];
49410
49411				// move existing object to the ACTIVE region
49412
49413				const firstActiveIndex = -- nCachedObjects,
49414					lastCachedObject = objects[ firstActiveIndex ];
49415
49416				indicesByUUID[ lastCachedObject.uuid ] = index;
49417				objects[ index ] = lastCachedObject;
49418
49419				indicesByUUID[ uuid ] = firstActiveIndex;
49420				objects[ firstActiveIndex ] = object;
49421
49422				// accounting is done, now do the same for all bindings
49423
49424				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49425
49426					const bindingsForPath = bindings[ j ],
49427						lastCached = bindingsForPath[ firstActiveIndex ];
49428
49429					let binding = bindingsForPath[ index ];
49430
49431					bindingsForPath[ index ] = lastCached;
49432
49433					if ( binding === undefined ) {
49434
49435						// since we do not bother to create new bindings
49436						// for objects that are cached, the binding may
49437						// or may not exist
49438
49439						binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
49440
49441					}
49442
49443					bindingsForPath[ firstActiveIndex ] = binding;
49444
49445				}
49446
49447			} else if ( objects[ index ] !== knownObject ) {
49448
49449				console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
vendor: 4,120 bytes, lines 49450-49616
49450					'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
49451
49452			} // else the object is already where we want it to be
49453
49454		} // for arguments
49455
49456		this.nCachedObjects_ = nCachedObjects;
49457
49458	}
49459
49460	remove() {
49461
49462		const objects = this._objects,
49463			indicesByUUID = this._indicesByUUID,
49464			bindings = this._bindings,
49465			nBindings = bindings.length;
49466
49467		let nCachedObjects = this.nCachedObjects_;
49468
49469		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
49470
49471			const object = arguments[ i ],
49472				uuid = object.uuid,
49473				index = indicesByUUID[ uuid ];
49474
49475			if ( index !== undefined && index >= nCachedObjects ) {
49476
49477				// move existing object into the CACHED region
49478
49479				const lastCachedIndex = nCachedObjects ++,
49480					firstActiveObject = objects[ lastCachedIndex ];
49481
49482				indicesByUUID[ firstActiveObject.uuid ] = index;
49483				objects[ index ] = firstActiveObject;
49484
49485				indicesByUUID[ uuid ] = lastCachedIndex;
49486				objects[ lastCachedIndex ] = object;
49487
49488				// accounting is done, now do the same for all bindings
49489
49490				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49491
49492					const bindingsForPath = bindings[ j ],
49493						firstActive = bindingsForPath[ lastCachedIndex ],
49494						binding = bindingsForPath[ index ];
49495
49496					bindingsForPath[ index ] = firstActive;
49497					bindingsForPath[ lastCachedIndex ] = binding;
49498
49499				}
49500
49501			}
49502
49503		} // for arguments
49504
49505		this.nCachedObjects_ = nCachedObjects;
49506
49507	}
49508
49509	// remove & forget
49510	uncache() {
49511
49512		const objects = this._objects,
49513			indicesByUUID = this._indicesByUUID,
49514			bindings = this._bindings,
49515			nBindings = bindings.length;
49516
49517		let nCachedObjects = this.nCachedObjects_,
49518			nObjects = objects.length;
49519
49520		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
49521
49522			const object = arguments[ i ],
49523				uuid = object.uuid,
49524				index = indicesByUUID[ uuid ];
49525
49526			if ( index !== undefined ) {
49527
49528				delete indicesByUUID[ uuid ];
49529
49530				if ( index < nCachedObjects ) {
49531
49532					// object is cached, shrink the CACHED region
49533
49534					const firstActiveIndex = -- nCachedObjects,
49535						lastCachedObject = objects[ firstActiveIndex ],
49536						lastIndex = -- nObjects,
49537						lastObject = objects[ lastIndex ];
49538
49539					// last cached object takes this object's place
49540					indicesByUUID[ lastCachedObject.uuid ] = index;
49541					objects[ index ] = lastCachedObject;
49542
49543					// last object goes to the activated slot and pop
49544					indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
49545					objects[ firstActiveIndex ] = lastObject;
49546					objects.pop();
49547
49548					// accounting is done, now do the same for all bindings
49549
49550					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49551
49552						const bindingsForPath = bindings[ j ],
49553							lastCached = bindingsForPath[ firstActiveIndex ],
49554							last = bindingsForPath[ lastIndex ];
49555
49556						bindingsForPath[ index ] = lastCached;
49557						bindingsForPath[ firstActiveIndex ] = last;
49558						bindingsForPath.pop();
49559
49560					}
49561
49562				} else {
49563
49564					// object is active, just swap with the last and pop
49565
49566					const lastIndex = -- nObjects,
49567						lastObject = objects[ lastIndex ];
49568
49569					if ( lastIndex > 0 ) {
49570
49571						indicesByUUID[ lastObject.uuid ] = index;
49572
49573					}
49574
49575					objects[ index ] = lastObject;
49576					objects.pop();
49577
49578					// accounting is done, now do the same for all bindings
49579
49580					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49581
49582						const bindingsForPath = bindings[ j ];
49583
49584						bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
49585						bindingsForPath.pop();
49586
49587					}
49588
49589				} // cached or active
49590
49591			} // if object is known
49592
49593		} // for arguments
49594
49595		this.nCachedObjects_ = nCachedObjects;
49596
49597	}
49598
49599	// Internal interface used by befriended PropertyBinding.Composite:
49600
49601	subscribe_( path, parsedPath ) {
49602
49603		// returns an array of bindings for the given path that is changed
49604		// according to the contained objects in the group
49605
49606		const indicesByPath = this._bindingsIndicesByPath;
49607		let index = indicesByPath[ path ];
49608		const bindings = this._bindings;
49609
49610		if ( index !== undefined ) return bindings[ index ];
49611
49612		const paths = this._paths,
49613			parsedPaths = this._parsedPaths,
49614			objects = this._objects,
49615			nObjects = objects.length,
49616			nCachedObjects = this.nCachedObjects_,
vendor: 7,613 bytes, lines 49617-50010
49617			bindingsForPath = new Array( nObjects );
49618
49619		index = bindings.length;
49620
49621		indicesByPath[ path ] = index;
49622
49623		paths.push( path );
49624		parsedPaths.push( parsedPath );
49625		bindings.push( bindingsForPath );
49626
49627		for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
49628
49629			const object = objects[ i ];
49630			bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
49631
49632		}
49633
49634		return bindingsForPath;
49635
49636	}
49637
49638	unsubscribe_( path ) {
49639
49640		// tells the group to forget about a property path and no longer
49641		// update the array previously obtained with 'subscribe_'
49642
49643		const indicesByPath = this._bindingsIndicesByPath,
49644			index = indicesByPath[ path ];
49645
49646		if ( index !== undefined ) {
49647
49648			const paths = this._paths,
49649				parsedPaths = this._parsedPaths,
49650				bindings = this._bindings,
49651				lastBindingsIndex = bindings.length - 1,
49652				lastBindings = bindings[ lastBindingsIndex ],
49653				lastBindingsPath = path[ lastBindingsIndex ];
49654
49655			indicesByPath[ lastBindingsPath ] = index;
49656
49657			bindings[ index ] = lastBindings;
49658			bindings.pop();
49659
49660			parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
49661			parsedPaths.pop();
49662
49663			paths[ index ] = paths[ lastBindingsIndex ];
49664			paths.pop();
49665
49666		}
49667
49668	}
49669
49670}
49671
49672class AnimationAction {
49673
49674	constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
49675
49676		this._mixer = mixer;
49677		this._clip = clip;
49678		this._localRoot = localRoot;
49679		this.blendMode = blendMode;
49680
49681		const tracks = clip.tracks,
49682			nTracks = tracks.length,
49683			interpolants = new Array( nTracks );
49684
49685		const interpolantSettings = {
49686			endingStart: ZeroCurvatureEnding,
49687			endingEnd: ZeroCurvatureEnding
49688		};
49689
49690		for ( let i = 0; i !== nTracks; ++ i ) {
49691
49692			const interpolant = tracks[ i ].createInterpolant( null );
49693			interpolants[ i ] = interpolant;
49694			interpolant.settings = interpolantSettings;
49695
49696		}
49697
49698		this._interpolantSettings = interpolantSettings;
49699
49700		this._interpolants = interpolants; // bound by the mixer
49701
49702		// inside: PropertyMixer (managed by the mixer)
49703		this._propertyBindings = new Array( nTracks );
49704
49705		this._cacheIndex = null; // for the memory manager
49706		this._byClipCacheIndex = null; // for the memory manager
49707
49708		this._timeScaleInterpolant = null;
49709		this._weightInterpolant = null;
49710
49711		this.loop = LoopRepeat;
49712		this._loopCount = - 1;
49713
49714		// global mixer time when the action is to be started
49715		// it's set back to 'null' upon start of the action
49716		this._startTime = null;
49717
49718		// scaled local time of the action
49719		// gets clamped or wrapped to 0..clip.duration according to loop
49720		this.time = 0;
49721
49722		this.timeScale = 1;
49723		this._effectiveTimeScale = 1;
49724
49725		this.weight = 1;
49726		this._effectiveWeight = 1;
49727
49728		this.repetitions = Infinity; // no. of repetitions when looping
49729
49730		this.paused = false; // true -> zero effective time scale
49731		this.enabled = true; // false -> zero effective weight
49732
49733		this.clampWhenFinished = false;// keep feeding the last frame?
49734
49735		this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
49736		this.zeroSlopeAtEnd = true;// clips for start, loop and end
49737
49738	}
49739
49740	// State & Scheduling
49741
49742	play() {
49743
49744		this._mixer._activateAction( this );
49745
49746		return this;
49747
49748	}
49749
49750	stop() {
49751
49752		this._mixer._deactivateAction( this );
49753
49754		return this.reset();
49755
49756	}
49757
49758	reset() {
49759
49760		this.paused = false;
49761		this.enabled = true;
49762
49763		this.time = 0; // restart clip
49764		this._loopCount = - 1;// forget previous loops
49765		this._startTime = null;// forget scheduling
49766
49767		return this.stopFading().stopWarping();
49768
49769	}
49770
49771	isRunning() {
49772
49773		return this.enabled && ! this.paused && this.timeScale !== 0 &&
49774			this._startTime === null && this._mixer._isActiveAction( this );
49775
49776	}
49777
49778	// return true when play has been called
49779	isScheduled() {
49780
49781		return this._mixer._isActiveAction( this );
49782
49783	}
49784
49785	startAt( time ) {
49786
49787		this._startTime = time;
49788
49789		return this;
49790
49791	}
49792
49793	setLoop( mode, repetitions ) {
49794
49795		this.loop = mode;
49796		this.repetitions = repetitions;
49797
49798		return this;
49799
49800	}
49801
49802	// Weight
49803
49804	// set the weight stopping any scheduled fading
49805	// although .enabled = false yields an effective weight of zero, this
49806	// method does *not* change .enabled, because it would be confusing
49807	setEffectiveWeight( weight ) {
49808
49809		this.weight = weight;
49810
49811		// note: same logic as when updated at runtime
49812		this._effectiveWeight = this.enabled ? weight : 0;
49813
49814		return this.stopFading();
49815
49816	}
49817
49818	// return the weight considering fading and .enabled
49819	getEffectiveWeight() {
49820
49821		return this._effectiveWeight;
49822
49823	}
49824
49825	fadeIn( duration ) {
49826
49827		return this._scheduleFading( duration, 0, 1 );
49828
49829	}
49830
49831	fadeOut( duration ) {
49832
49833		return this._scheduleFading( duration, 1, 0 );
49834
49835	}
49836
49837	crossFadeFrom( fadeOutAction, duration, warp ) {
49838
49839		fadeOutAction.fadeOut( duration );
49840		this.fadeIn( duration );
49841
49842		if ( warp ) {
49843
49844			const fadeInDuration = this._clip.duration,
49845				fadeOutDuration = fadeOutAction._clip.duration,
49846
49847				startEndRatio = fadeOutDuration / fadeInDuration,
49848				endStartRatio = fadeInDuration / fadeOutDuration;
49849
49850			fadeOutAction.warp( 1.0, startEndRatio, duration );
49851			this.warp( endStartRatio, 1.0, duration );
49852
49853		}
49854
49855		return this;
49856
49857	}
49858
49859	crossFadeTo( fadeInAction, duration, warp ) {
49860
49861		return fadeInAction.crossFadeFrom( this, duration, warp );
49862
49863	}
49864
49865	stopFading() {
49866
49867		const weightInterpolant = this._weightInterpolant;
49868
49869		if ( weightInterpolant !== null ) {
49870
49871			this._weightInterpolant = null;
49872			this._mixer._takeBackControlInterpolant( weightInterpolant );
49873
49874		}
49875
49876		return this;
49877
49878	}
49879
49880	// Time Scale Control
49881
49882	// set the time scale stopping any scheduled warping
49883	// although .paused = true yields an effective time scale of zero, this
49884	// method does *not* change .paused, because it would be confusing
49885	setEffectiveTimeScale( timeScale ) {
49886
49887		this.timeScale = timeScale;
49888		this._effectiveTimeScale = this.paused ? 0 : timeScale;
49889
49890		return this.stopWarping();
49891
49892	}
49893
49894	// return the time scale considering warping and .paused
49895	getEffectiveTimeScale() {
49896
49897		return this._effectiveTimeScale;
49898
49899	}
49900
49901	setDuration( duration ) {
49902
49903		this.timeScale = this._clip.duration / duration;
49904
49905		return this.stopWarping();
49906
49907	}
49908
49909	syncWith( action ) {
49910
49911		this.time = action.time;
49912		this.timeScale = action.timeScale;
49913
49914		return this.stopWarping();
49915
49916	}
49917
49918	halt( duration ) {
49919
49920		return this.warp( this._effectiveTimeScale, 0, duration );
49921
49922	}
49923
49924	warp( startTimeScale, endTimeScale, duration ) {
49925
49926		const mixer = this._mixer,
49927			now = mixer.time,
49928			timeScale = this.timeScale;
49929
49930		let interpolant = this._timeScaleInterpolant;
49931
49932		if ( interpolant === null ) {
49933
49934			interpolant = mixer._lendControlInterpolant();
49935			this._timeScaleInterpolant = interpolant;
49936
49937		}
49938
49939		const times = interpolant.parameterPositions,
49940			values = interpolant.sampleValues;
49941
49942		times[ 0 ] = now;
49943		times[ 1 ] = now + duration;
49944
49945		values[ 0 ] = startTimeScale / timeScale;
49946		values[ 1 ] = endTimeScale / timeScale;
49947
49948		return this;
49949
49950	}
49951
49952	stopWarping() {
49953
49954		const timeScaleInterpolant = this._timeScaleInterpolant;
49955
49956		if ( timeScaleInterpolant !== null ) {
49957
49958			this._timeScaleInterpolant = null;
49959			this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
49960
49961		}
49962
49963		return this;
49964
49965	}
49966
49967	// Object Accessors
49968
49969	getMixer() {
49970
49971		return this._mixer;
49972
49973	}
49974
49975	getClip() {
49976
49977		return this._clip;
49978
49979	}
49980
49981	getRoot() {
49982
49983		return this._localRoot || this._mixer._root;
49984
49985	}
49986
49987	// Interna
49988
49989	_update( time, deltaTime, timeDirection, accuIndex ) {
49990
49991		// called by the mixer
49992
49993		if ( ! this.enabled ) {
49994
49995			// call ._updateWeight() to update ._effectiveWeight
49996
49997			this._updateWeight( time );
49998			return;
49999
50000		}
50001
50002		const startTime = this._startTime;
50003
50004		if ( startTime !== null ) {
50005
50006			// check for scheduled start of action
50007
50008			const timeRunning = ( time - startTime ) * timeDirection;
50009			if ( timeRunning < 0 || timeDirection === 0 ) {
50010
vendor: 6,044 bytes, lines 50011-50369
50011				deltaTime = 0;
50012
50013			} else {
50014
50015
50016				this._startTime = null; // unschedule
50017				deltaTime = timeDirection * timeRunning;
50018
50019			}
50020
50021		}
50022
50023		// apply time scale and advance time
50024
50025		deltaTime *= this._updateTimeScale( time );
50026		const clipTime = this._updateTime( deltaTime );
50027
50028		// note: _updateTime may disable the action resulting in
50029		// an effective weight of 0
50030
50031		const weight = this._updateWeight( time );
50032
50033		if ( weight > 0 ) {
50034
50035			const interpolants = this._interpolants;
50036			const propertyMixers = this._propertyBindings;
50037
50038			switch ( this.blendMode ) {
50039
50040				case AdditiveAnimationBlendMode:
50041
50042					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
50043
50044						interpolants[ j ].evaluate( clipTime );
50045						propertyMixers[ j ].accumulateAdditive( weight );
50046
50047					}
50048
50049					break;
50050
50051				case NormalAnimationBlendMode:
50052				default:
50053
50054					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
50055
50056						interpolants[ j ].evaluate( clipTime );
50057						propertyMixers[ j ].accumulate( accuIndex, weight );
50058
50059					}
50060
50061			}
50062
50063		}
50064
50065	}
50066
50067	_updateWeight( time ) {
50068
50069		let weight = 0;
50070
50071		if ( this.enabled ) {
50072
50073			weight = this.weight;
50074			const interpolant = this._weightInterpolant;
50075
50076			if ( interpolant !== null ) {
50077
50078				const interpolantValue = interpolant.evaluate( time )[ 0 ];
50079
50080				weight *= interpolantValue;
50081
50082				if ( time > interpolant.parameterPositions[ 1 ] ) {
50083
50084					this.stopFading();
50085
50086					if ( interpolantValue === 0 ) {
50087
50088						// faded out, disable
50089						this.enabled = false;
50090
50091					}
50092
50093				}
50094
50095			}
50096
50097		}
50098
50099		this._effectiveWeight = weight;
50100		return weight;
50101
50102	}
50103
50104	_updateTimeScale( time ) {
50105
50106		let timeScale = 0;
50107
50108		if ( ! this.paused ) {
50109
50110			timeScale = this.timeScale;
50111
50112			const interpolant = this._timeScaleInterpolant;
50113
50114			if ( interpolant !== null ) {
50115
50116				const interpolantValue = interpolant.evaluate( time )[ 0 ];
50117
50118				timeScale *= interpolantValue;
50119
50120				if ( time > interpolant.parameterPositions[ 1 ] ) {
50121
50122					this.stopWarping();
50123
50124					if ( timeScale === 0 ) {
50125
50126						// motion has halted, pause
50127						this.paused = true;
50128
50129					} else {
50130
50131						// warp done - apply final time scale
50132						this.timeScale = timeScale;
50133
50134					}
50135
50136				}
50137
50138			}
50139
50140		}
50141
50142		this._effectiveTimeScale = timeScale;
50143		return timeScale;
50144
50145	}
50146
50147	_updateTime( deltaTime ) {
50148
50149		const duration = this._clip.duration;
50150		const loop = this.loop;
50151
50152		let time = this.time + deltaTime;
50153		let loopCount = this._loopCount;
50154
50155		const pingPong = ( loop === LoopPingPong );
50156
50157		if ( deltaTime === 0 ) {
50158
50159			if ( loopCount === - 1 ) return time;
50160
50161			return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
50162
50163		}
50164
50165		if ( loop === LoopOnce ) {
50166
50167			if ( loopCount === - 1 ) {
50168
50169				// just started
50170
50171				this._loopCount = 0;
50172				this._setEndings( true, true, false );
50173
50174			}
50175
50176			handle_stop: {
50177
50178				if ( time >= duration ) {
50179
50180					time = duration;
50181
50182				} else if ( time < 0 ) {
50183
50184					time = 0;
50185
50186				} else {
50187
50188					this.time = time;
50189
50190					break handle_stop;
50191
50192				}
50193
50194				if ( this.clampWhenFinished ) this.paused = true;
50195				else this.enabled = false;
50196
50197				this.time = time;
50198
50199				this._mixer.dispatchEvent( {
50200					type: 'finished', action: this,
50201					direction: deltaTime < 0 ? - 1 : 1
50202				} );
50203
50204			}
50205
50206		} else { // repetitive Repeat or PingPong
50207
50208			if ( loopCount === - 1 ) {
50209
50210				// just started
50211
50212				if ( deltaTime >= 0 ) {
50213
50214					loopCount = 0;
50215
50216					this._setEndings( true, this.repetitions === 0, pingPong );
50217
50218				} else {
50219
50220					// when looping in reverse direction, the initial
50221					// transition through zero counts as a repetition,
50222					// so leave loopCount at -1
50223
50224					this._setEndings( this.repetitions === 0, true, pingPong );
50225
50226				}
50227
50228			}
50229
50230			if ( time >= duration || time < 0 ) {
50231
50232				// wrap around
50233
50234				const loopDelta = Math.floor( time / duration ); // signed
50235				time -= duration * loopDelta;
50236
50237				loopCount += Math.abs( loopDelta );
50238
50239				const pending = this.repetitions - loopCount;
50240
50241				if ( pending <= 0 ) {
50242
50243					// have to stop (switch state, clamp time, fire event)
50244
50245					if ( this.clampWhenFinished ) this.paused = true;
50246					else this.enabled = false;
50247
50248					time = deltaTime > 0 ? duration : 0;
50249
50250					this.time = time;
50251
50252					this._mixer.dispatchEvent( {
50253						type: 'finished', action: this,
50254						direction: deltaTime > 0 ? 1 : - 1
50255					} );
50256
50257				} else {
50258
50259					// keep running
50260
50261					if ( pending === 1 ) {
50262
50263						// entering the last round
50264
50265						const atStart = deltaTime < 0;
50266						this._setEndings( atStart, ! atStart, pingPong );
50267
50268					} else {
50269
50270						this._setEndings( false, false, pingPong );
50271
50272					}
50273
50274					this._loopCount = loopCount;
50275
50276					this.time = time;
50277
50278					this._mixer.dispatchEvent( {
50279						type: 'loop', action: this, loopDelta: loopDelta
50280					} );
50281
50282				}
50283
50284			} else {
50285
50286				this.time = time;
50287
50288			}
50289
50290			if ( pingPong && ( loopCount & 1 ) === 1 ) {
50291
50292				// invert time for the "pong round"
50293
50294				return duration - time;
50295
50296			}
50297
50298		}
50299
50300		return time;
50301
50302	}
50303
50304	_setEndings( atStart, atEnd, pingPong ) {
50305
50306		const settings = this._interpolantSettings;
50307
50308		if ( pingPong ) {
50309
50310			settings.endingStart = ZeroSlopeEnding;
50311			settings.endingEnd = ZeroSlopeEnding;
50312
50313		} else {
50314
50315			// assuming for LoopOnce atStart == atEnd == true
50316
50317			if ( atStart ) {
50318
50319				settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
50320
50321			} else {
50322
50323				settings.endingStart = WrapAroundEnding;
50324
50325			}
50326
50327			if ( atEnd ) {
50328
50329				settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
50330
50331			} else {
50332
50333				settings.endingEnd 	 = WrapAroundEnding;
50334
50335			}
50336
50337		}
50338
50339	}
50340
50341	_scheduleFading( duration, weightNow, weightThen ) {
50342
50343		const mixer = this._mixer, now = mixer.time;
50344		let interpolant = this._weightInterpolant;
50345
50346		if ( interpolant === null ) {
50347
50348			interpolant = mixer._lendControlInterpolant();
50349			this._weightInterpolant = interpolant;
50350
50351		}
50352
50353		const times = interpolant.parameterPositions,
50354			values = interpolant.sampleValues;
50355
50356		times[ 0 ] = now;
50357		values[ 0 ] = weightNow;
50358		times[ 1 ] = now + duration;
50359		values[ 1 ] = weightThen;
50360
50361		return this;
50362
50363	}
50364
50365}
50366
50367const _controlInterpolantsResultBuffer = new Float32Array( 1 );
50368
50369
vendor: 13,381 bytes, lines 50370-51010
50370class AnimationMixer extends EventDispatcher {
50371
50372	constructor( root ) {
50373
50374		super();
50375
50376		this._root = root;
50377		this._initMemoryManager();
50378		this._accuIndex = 0;
50379		this.time = 0;
50380		this.timeScale = 1.0;
50381
50382	}
50383
50384	_bindAction( action, prototypeAction ) {
50385
50386		const root = action._localRoot || this._root,
50387			tracks = action._clip.tracks,
50388			nTracks = tracks.length,
50389			bindings = action._propertyBindings,
50390			interpolants = action._interpolants,
50391			rootUuid = root.uuid,
50392			bindingsByRoot = this._bindingsByRootAndName;
50393
50394		let bindingsByName = bindingsByRoot[ rootUuid ];
50395
50396		if ( bindingsByName === undefined ) {
50397
50398			bindingsByName = {};
50399			bindingsByRoot[ rootUuid ] = bindingsByName;
50400
50401		}
50402
50403		for ( let i = 0; i !== nTracks; ++ i ) {
50404
50405			const track = tracks[ i ],
50406				trackName = track.name;
50407
50408			let binding = bindingsByName[ trackName ];
50409
50410			if ( binding !== undefined ) {
50411
50412				++ binding.referenceCount;
50413				bindings[ i ] = binding;
50414
50415			} else {
50416
50417				binding = bindings[ i ];
50418
50419				if ( binding !== undefined ) {
50420
50421					// existing binding, make sure the cache knows
50422
50423					if ( binding._cacheIndex === null ) {
50424
50425						++ binding.referenceCount;
50426						this._addInactiveBinding( binding, rootUuid, trackName );
50427
50428					}
50429
50430					continue;
50431
50432				}
50433
50434				const path = prototypeAction && prototypeAction.
50435					_propertyBindings[ i ].binding.parsedPath;
50436
50437				binding = new PropertyMixer(
50438					PropertyBinding.create( root, trackName, path ),
50439					track.ValueTypeName, track.getValueSize() );
50440
50441				++ binding.referenceCount;
50442				this._addInactiveBinding( binding, rootUuid, trackName );
50443
50444				bindings[ i ] = binding;
50445
50446			}
50447
50448			interpolants[ i ].resultBuffer = binding.buffer;
50449
50450		}
50451
50452	}
50453
50454	_activateAction( action ) {
50455
50456		if ( ! this._isActiveAction( action ) ) {
50457
50458			if ( action._cacheIndex === null ) {
50459
50460				// this action has been forgotten by the cache, but the user
50461				// appears to be still using it -> rebind
50462
50463				const rootUuid = ( action._localRoot || this._root ).uuid,
50464					clipUuid = action._clip.uuid,
50465					actionsForClip = this._actionsByClip[ clipUuid ];
50466
50467				this._bindAction( action,
50468					actionsForClip && actionsForClip.knownActions[ 0 ] );
50469
50470				this._addInactiveAction( action, clipUuid, rootUuid );
50471
50472			}
50473
50474			const bindings = action._propertyBindings;
50475
50476			// increment reference counts / sort out state
50477			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
50478
50479				const binding = bindings[ i ];
50480
50481				if ( binding.useCount ++ === 0 ) {
50482
50483					this._lendBinding( binding );
50484					binding.saveOriginalState();
50485
50486				}
50487
50488			}
50489
50490			this._lendAction( action );
50491
50492		}
50493
50494	}
50495
50496	_deactivateAction( action ) {
50497
50498		if ( this._isActiveAction( action ) ) {
50499
50500			const bindings = action._propertyBindings;
50501
50502			// decrement reference counts / sort out state
50503			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
50504
50505				const binding = bindings[ i ];
50506
50507				if ( -- binding.useCount === 0 ) {
50508
50509					binding.restoreOriginalState();
50510					this._takeBackBinding( binding );
50511
50512				}
50513
50514			}
50515
50516			this._takeBackAction( action );
50517
50518		}
50519
50520	}
50521
50522	// Memory manager
50523
50524	_initMemoryManager() {
50525
50526		this._actions = []; // 'nActiveActions' followed by inactive ones
50527		this._nActiveActions = 0;
50528
50529		this._actionsByClip = {};
50530		// inside:
50531		// {
50532		// 	knownActions: Array< AnimationAction > - used as prototypes
50533		// 	actionByRoot: AnimationAction - lookup
50534		// }
50535
50536
50537		this._bindings = []; // 'nActiveBindings' followed by inactive ones
50538		this._nActiveBindings = 0;
50539
50540		this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
50541
50542
50543		this._controlInterpolants = []; // same game as above
50544		this._nActiveControlInterpolants = 0;
50545
50546		const scope = this;
50547
50548		this.stats = {
50549
50550			actions: {
50551				get total() {
50552
50553					return scope._actions.length;
50554
50555				},
50556				get inUse() {
50557
50558					return scope._nActiveActions;
50559
50560				}
50561			},
50562			bindings: {
50563				get total() {
50564
50565					return scope._bindings.length;
50566
50567				},
50568				get inUse() {
50569
50570					return scope._nActiveBindings;
50571
50572				}
50573			},
50574			controlInterpolants: {
50575				get total() {
50576
50577					return scope._controlInterpolants.length;
50578
50579				},
50580				get inUse() {
50581
50582					return scope._nActiveControlInterpolants;
50583
50584				}
50585			}
50586
50587		};
50588
50589	}
50590
50591	// Memory management for AnimationAction objects
50592
50593	_isActiveAction( action ) {
50594
50595		const index = action._cacheIndex;
50596		return index !== null && index < this._nActiveActions;
50597
50598	}
50599
50600	_addInactiveAction( action, clipUuid, rootUuid ) {
50601
50602		const actions = this._actions,
50603			actionsByClip = this._actionsByClip;
50604
50605		let actionsForClip = actionsByClip[ clipUuid ];
50606
50607		if ( actionsForClip === undefined ) {
50608
50609			actionsForClip = {
50610
50611				knownActions: [ action ],
50612				actionByRoot: {}
50613
50614			};
50615
50616			action._byClipCacheIndex = 0;
50617
50618			actionsByClip[ clipUuid ] = actionsForClip;
50619
50620		} else {
50621
50622			const knownActions = actionsForClip.knownActions;
50623
50624			action._byClipCacheIndex = knownActions.length;
50625			knownActions.push( action );
50626
50627		}
50628
50629		action._cacheIndex = actions.length;
50630		actions.push( action );
50631
50632		actionsForClip.actionByRoot[ rootUuid ] = action;
50633
50634	}
50635
50636	_removeInactiveAction( action ) {
50637
50638		const actions = this._actions,
50639			lastInactiveAction = actions[ actions.length - 1 ],
50640			cacheIndex = action._cacheIndex;
50641
50642		lastInactiveAction._cacheIndex = cacheIndex;
50643		actions[ cacheIndex ] = lastInactiveAction;
50644		actions.pop();
50645
50646		action._cacheIndex = null;
50647
50648
50649		const clipUuid = action._clip.uuid,
50650			actionsByClip = this._actionsByClip,
50651			actionsForClip = actionsByClip[ clipUuid ],
50652			knownActionsForClip = actionsForClip.knownActions,
50653
50654			lastKnownAction =
50655				knownActionsForClip[ knownActionsForClip.length - 1 ],
50656
50657			byClipCacheIndex = action._byClipCacheIndex;
50658
50659		lastKnownAction._byClipCacheIndex = byClipCacheIndex;
50660		knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
50661		knownActionsForClip.pop();
50662
50663		action._byClipCacheIndex = null;
50664
50665
50666		const actionByRoot = actionsForClip.actionByRoot,
50667			rootUuid = ( action._localRoot || this._root ).uuid;
50668
50669		delete actionByRoot[ rootUuid ];
50670
50671		if ( knownActionsForClip.length === 0 ) {
50672
50673			delete actionsByClip[ clipUuid ];
50674
50675		}
50676
50677		this._removeInactiveBindingsForAction( action );
50678
50679	}
50680
50681	_removeInactiveBindingsForAction( action ) {
50682
50683		const bindings = action._propertyBindings;
50684
50685		for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
50686
50687			const binding = bindings[ i ];
50688
50689			if ( -- binding.referenceCount === 0 ) {
50690
50691				this._removeInactiveBinding( binding );
50692
50693			}
50694
50695		}
50696
50697	}
50698
50699	_lendAction( action ) {
50700
50701		// [ active actions |  inactive actions  ]
50702		// [  active actions >| inactive actions ]
50703		//                 s        a
50704		//                  <-swap->
50705		//                 a        s
50706
50707		const actions = this._actions,
50708			prevIndex = action._cacheIndex,
50709
50710			lastActiveIndex = this._nActiveActions ++,
50711
50712			firstInactiveAction = actions[ lastActiveIndex ];
50713
50714		action._cacheIndex = lastActiveIndex;
50715		actions[ lastActiveIndex ] = action;
50716
50717		firstInactiveAction._cacheIndex = prevIndex;
50718		actions[ prevIndex ] = firstInactiveAction;
50719
50720	}
50721
50722	_takeBackAction( action ) {
50723
50724		// [  active actions  | inactive actions ]
50725		// [ active actions |< inactive actions  ]
50726		//        a        s
50727		//         <-swap->
50728		//        s        a
50729
50730		const actions = this._actions,
50731			prevIndex = action._cacheIndex,
50732
50733			firstInactiveIndex = -- this._nActiveActions,
50734
50735			lastActiveAction = actions[ firstInactiveIndex ];
50736
50737		action._cacheIndex = firstInactiveIndex;
50738		actions[ firstInactiveIndex ] = action;
50739
50740		lastActiveAction._cacheIndex = prevIndex;
50741		actions[ prevIndex ] = lastActiveAction;
50742
50743	}
50744
50745	// Memory management for PropertyMixer objects
50746
50747	_addInactiveBinding( binding, rootUuid, trackName ) {
50748
50749		const bindingsByRoot = this._bindingsByRootAndName,
50750			bindings = this._bindings;
50751
50752		let bindingByName = bindingsByRoot[ rootUuid ];
50753
50754		if ( bindingByName === undefined ) {
50755
50756			bindingByName = {};
50757			bindingsByRoot[ rootUuid ] = bindingByName;
50758
50759		}
50760
50761		bindingByName[ trackName ] = binding;
50762
50763		binding._cacheIndex = bindings.length;
50764		bindings.push( binding );
50765
50766	}
50767
50768	_removeInactiveBinding( binding ) {
50769
50770		const bindings = this._bindings,
50771			propBinding = binding.binding,
50772			rootUuid = propBinding.rootNode.uuid,
50773			trackName = propBinding.path,
50774			bindingsByRoot = this._bindingsByRootAndName,
50775			bindingByName = bindingsByRoot[ rootUuid ],
50776
50777			lastInactiveBinding = bindings[ bindings.length - 1 ],
50778			cacheIndex = binding._cacheIndex;
50779
50780		lastInactiveBinding._cacheIndex = cacheIndex;
50781		bindings[ cacheIndex ] = lastInactiveBinding;
50782		bindings.pop();
50783
50784		delete bindingByName[ trackName ];
50785
50786		if ( Object.keys( bindingByName ).length === 0 ) {
50787
50788			delete bindingsByRoot[ rootUuid ];
50789
50790		}
50791
50792	}
50793
50794	_lendBinding( binding ) {
50795
50796		const bindings = this._bindings,
50797			prevIndex = binding._cacheIndex,
50798
50799			lastActiveIndex = this._nActiveBindings ++,
50800
50801			firstInactiveBinding = bindings[ lastActiveIndex ];
50802
50803		binding._cacheIndex = lastActiveIndex;
50804		bindings[ lastActiveIndex ] = binding;
50805
50806		firstInactiveBinding._cacheIndex = prevIndex;
50807		bindings[ prevIndex ] = firstInactiveBinding;
50808
50809	}
50810
50811	_takeBackBinding( binding ) {
50812
50813		const bindings = this._bindings,
50814			prevIndex = binding._cacheIndex,
50815
50816			firstInactiveIndex = -- this._nActiveBindings,
50817
50818			lastActiveBinding = bindings[ firstInactiveIndex ];
50819
50820		binding._cacheIndex = firstInactiveIndex;
50821		bindings[ firstInactiveIndex ] = binding;
50822
50823		lastActiveBinding._cacheIndex = prevIndex;
50824		bindings[ prevIndex ] = lastActiveBinding;
50825
50826	}
50827
50828
50829	// Memory management of Interpolants for weight and time scale
50830
50831	_lendControlInterpolant() {
50832
50833		const interpolants = this._controlInterpolants,
50834			lastActiveIndex = this._nActiveControlInterpolants ++;
50835
50836		let interpolant = interpolants[ lastActiveIndex ];
50837
50838		if ( interpolant === undefined ) {
50839
50840			interpolant = new LinearInterpolant(
50841				new Float32Array( 2 ), new Float32Array( 2 ),
50842				1, _controlInterpolantsResultBuffer );
50843
50844			interpolant.__cacheIndex = lastActiveIndex;
50845			interpolants[ lastActiveIndex ] = interpolant;
50846
50847		}
50848
50849		return interpolant;
50850
50851	}
50852
50853	_takeBackControlInterpolant( interpolant ) {
50854
50855		const interpolants = this._controlInterpolants,
50856			prevIndex = interpolant.__cacheIndex,
50857
50858			firstInactiveIndex = -- this._nActiveControlInterpolants,
50859
50860			lastActiveInterpolant = interpolants[ firstInactiveIndex ];
50861
50862		interpolant.__cacheIndex = firstInactiveIndex;
50863		interpolants[ firstInactiveIndex ] = interpolant;
50864
50865		lastActiveInterpolant.__cacheIndex = prevIndex;
50866		interpolants[ prevIndex ] = lastActiveInterpolant;
50867
50868	}
50869
50870	// return an action for a clip optionally using a custom root target
50871	// object (this method allocates a lot of dynamic memory in case a
50872	// previously unknown clip/root combination is specified)
50873	clipAction( clip, optionalRoot, blendMode ) {
50874
50875		const root = optionalRoot || this._root,
50876			rootUuid = root.uuid;
50877
50878		let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
50879
50880		const clipUuid = clipObject !== null ? clipObject.uuid : clip;
50881
50882		const actionsForClip = this._actionsByClip[ clipUuid ];
50883		let prototypeAction = null;
50884
50885		if ( blendMode === undefined ) {
50886
50887			if ( clipObject !== null ) {
50888
50889				blendMode = clipObject.blendMode;
50890
50891			} else {
50892
50893				blendMode = NormalAnimationBlendMode;
50894
50895			}
50896
50897		}
50898
50899		if ( actionsForClip !== undefined ) {
50900
50901			const existingAction = actionsForClip.actionByRoot[ rootUuid ];
50902
50903			if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
50904
50905				return existingAction;
50906
50907			}
50908
50909			// we know the clip, so we don't have to parse all
50910			// the bindings again but can just copy
50911			prototypeAction = actionsForClip.knownActions[ 0 ];
50912
50913			// also, take the clip from the prototype action
50914			if ( clipObject === null )
50915				clipObject = prototypeAction._clip;
50916
50917		}
50918
50919		// clip must be known when specified via string
50920		if ( clipObject === null ) return null;
50921
50922		// allocate all resources required to run it
50923		const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
50924
50925		this._bindAction( newAction, prototypeAction );
50926
50927		// and make the action known to the memory manager
50928		this._addInactiveAction( newAction, clipUuid, rootUuid );
50929
50930		return newAction;
50931
50932	}
50933
50934	// get an existing action
50935	existingAction( clip, optionalRoot ) {
50936
50937		const root = optionalRoot || this._root,
50938			rootUuid = root.uuid,
50939
50940			clipObject = typeof clip === 'string' ?
50941				AnimationClip.findByName( root, clip ) : clip,
50942
50943			clipUuid = clipObject ? clipObject.uuid : clip,
50944
50945			actionsForClip = this._actionsByClip[ clipUuid ];
50946
50947		if ( actionsForClip !== undefined ) {
50948
50949			return actionsForClip.actionByRoot[ rootUuid ] || null;
50950
50951		}
50952
50953		return null;
50954
50955	}
50956
50957	// deactivates all previously scheduled actions
50958	stopAllAction() {
50959
50960		const actions = this._actions,
50961			nActions = this._nActiveActions;
50962
50963		for ( let i = nActions - 1; i >= 0; -- i ) {
50964
50965			actions[ i ].stop();
50966
50967		}
50968
50969		return this;
50970
50971	}
50972
50973	// advance the time and update apply the animation
50974	update( deltaTime ) {
50975
50976		deltaTime *= this.timeScale;
50977
50978		const actions = this._actions,
50979			nActions = this._nActiveActions,
50980
50981			time = this.time += deltaTime,
50982			timeDirection = Math.sign( deltaTime ),
50983
50984			accuIndex = this._accuIndex ^= 1;
50985
50986		// run active actions
50987
50988		for ( let i = 0; i !== nActions; ++ i ) {
50989
50990			const action = actions[ i ];
50991
50992			action._update( time, deltaTime, timeDirection, accuIndex );
50993
50994		}
50995
50996		// update scene graph
50997
50998		const bindings = this._bindings,
50999			nBindings = this._nActiveBindings;
51000
51001		for ( let i = 0; i !== nBindings; ++ i ) {
51002
51003			bindings[ i ].apply( accuIndex );
51004
51005		}
51006
51007		return this;
51008
51009	}
51010
vendor: 2,763 bytes, lines 51011-51144
51011	// Allows you to seek to a specific time in an animation.
51012	setTime( timeInSeconds ) {
51013
51014		this.time = 0; // Zero out time attribute for AnimationMixer object;
51015		for ( let i = 0; i < this._actions.length; i ++ ) {
51016
51017			this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
51018
51019		}
51020
51021		return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
51022
51023	}
51024
51025	// return this mixer's root target object
51026	getRoot() {
51027
51028		return this._root;
51029
51030	}
51031
51032	// free all resources specific to a particular clip
51033	uncacheClip( clip ) {
51034
51035		const actions = this._actions,
51036			clipUuid = clip.uuid,
51037			actionsByClip = this._actionsByClip,
51038			actionsForClip = actionsByClip[ clipUuid ];
51039
51040		if ( actionsForClip !== undefined ) {
51041
51042			// note: just calling _removeInactiveAction would mess up the
51043			// iteration state and also require updating the state we can
51044			// just throw away
51045
51046			const actionsToRemove = actionsForClip.knownActions;
51047
51048			for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
51049
51050				const action = actionsToRemove[ i ];
51051
51052				this._deactivateAction( action );
51053
51054				const cacheIndex = action._cacheIndex,
51055					lastInactiveAction = actions[ actions.length - 1 ];
51056
51057				action._cacheIndex = null;
51058				action._byClipCacheIndex = null;
51059
51060				lastInactiveAction._cacheIndex = cacheIndex;
51061				actions[ cacheIndex ] = lastInactiveAction;
51062				actions.pop();
51063
51064				this._removeInactiveBindingsForAction( action );
51065
51066			}
51067
51068			delete actionsByClip[ clipUuid ];
51069
51070		}
51071
51072	}
51073
51074	// free all resources specific to a particular root target object
51075	uncacheRoot( root ) {
51076
51077		const rootUuid = root.uuid,
51078			actionsByClip = this._actionsByClip;
51079
51080		for ( const clipUuid in actionsByClip ) {
51081
51082			const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
51083				action = actionByRoot[ rootUuid ];
51084
51085			if ( action !== undefined ) {
51086
51087				this._deactivateAction( action );
51088				this._removeInactiveAction( action );
51089
51090			}
51091
51092		}
51093
51094		const bindingsByRoot = this._bindingsByRootAndName,
51095			bindingByName = bindingsByRoot[ rootUuid ];
51096
51097		if ( bindingByName !== undefined ) {
51098
51099			for ( const trackName in bindingByName ) {
51100
51101				const binding = bindingByName[ trackName ];
51102				binding.restoreOriginalState();
51103				this._removeInactiveBinding( binding );
51104
51105			}
51106
51107		}
51108
51109	}
51110
51111	// remove a targeted clip from the cache
51112	uncacheAction( clip, optionalRoot ) {
51113
51114		const action = this.existingAction( clip, optionalRoot );
51115
51116		if ( action !== null ) {
51117
51118			this._deactivateAction( action );
51119			this._removeInactiveAction( action );
51120
51121		}
51122
51123	}
51124
51125}
51126
51127class Uniform {
51128
51129	constructor( value ) {
51130
51131		this.value = value;
51132
51133	}
51134
51135	clone() {
51136
51137		return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
51138
51139	}
51140
51141}
51142
51143let _id = 0;
51144
vendor: 4,828 bytes, lines 51145-51446
51145class UniformsGroup extends EventDispatcher {
51146
51147	constructor() {
51148
51149		super();
51150
51151		this.isUniformsGroup = true;
51152
51153		Object.defineProperty( this, 'id', { value: _id ++ } );
51154
51155		this.name = '';
51156
51157		this.usage = StaticDrawUsage;
51158		this.uniforms = [];
51159
51160	}
51161
51162	add( uniform ) {
51163
51164		this.uniforms.push( uniform );
51165
51166		return this;
51167
51168	}
51169
51170	remove( uniform ) {
51171
51172		const index = this.uniforms.indexOf( uniform );
51173
51174		if ( index !== - 1 ) this.uniforms.splice( index, 1 );
51175
51176		return this;
51177
51178	}
51179
51180	setName( name ) {
51181
51182		this.name = name;
51183
51184		return this;
51185
51186	}
51187
51188	setUsage( value ) {
51189
51190		this.usage = value;
51191
51192		return this;
51193
51194	}
51195
51196	dispose() {
51197
51198		this.dispatchEvent( { type: 'dispose' } );
51199
51200		return this;
51201
51202	}
51203
51204	copy( source ) {
51205
51206		this.name = source.name;
51207		this.usage = source.usage;
51208
51209		const uniformsSource = source.uniforms;
51210
51211		this.uniforms.length = 0;
51212
51213		for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) {
51214
51215			const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ];
51216
51217			for ( let j = 0; j < uniforms.length; j ++ ) {
51218
51219				this.uniforms.push( uniforms[ j ].clone() );
51220
51221			}
51222
51223		}
51224
51225		return this;
51226
51227	}
51228
51229	clone() {
51230
51231		return new this.constructor().copy( this );
51232
51233	}
51234
51235}
51236
51237class InstancedInterleavedBuffer extends InterleavedBuffer {
51238
51239	constructor( array, stride, meshPerAttribute = 1 ) {
51240
51241		super( array, stride );
51242
51243		this.isInstancedInterleavedBuffer = true;
51244
51245		this.meshPerAttribute = meshPerAttribute;
51246
51247	}
51248
51249	copy( source ) {
51250
51251		super.copy( source );
51252
51253		this.meshPerAttribute = source.meshPerAttribute;
51254
51255		return this;
51256
51257	}
51258
51259	clone( data ) {
51260
51261		const ib = super.clone( data );
51262
51263		ib.meshPerAttribute = this.meshPerAttribute;
51264
51265		return ib;
51266
51267	}
51268
51269	toJSON( data ) {
51270
51271		const json = super.toJSON( data );
51272
51273		json.isInstancedInterleavedBuffer = true;
51274		json.meshPerAttribute = this.meshPerAttribute;
51275
51276		return json;
51277
51278	}
51279
51280}
51281
51282class GLBufferAttribute {
51283
51284	constructor( buffer, type, itemSize, elementSize, count ) {
51285
51286		this.isGLBufferAttribute = true;
51287
51288		this.name = '';
51289
51290		this.buffer = buffer;
51291		this.type = type;
51292		this.itemSize = itemSize;
51293		this.elementSize = elementSize;
51294		this.count = count;
51295
51296		this.version = 0;
51297
51298	}
51299
51300	set needsUpdate( value ) {
51301
51302		if ( value === true ) this.version ++;
51303
51304	}
51305
51306	setBuffer( buffer ) {
51307
51308		this.buffer = buffer;
51309
51310		return this;
51311
51312	}
51313
51314	setType( type, elementSize ) {
51315
51316		this.type = type;
51317		this.elementSize = elementSize;
51318
51319		return this;
51320
51321	}
51322
51323	setItemSize( itemSize ) {
51324
51325		this.itemSize = itemSize;
51326
51327		return this;
51328
51329	}
51330
51331	setCount( count ) {
51332
51333		this.count = count;
51334
51335		return this;
51336
51337	}
51338
51339}
51340
51341const _matrix = /*@__PURE__*/ new Matrix4();
51342
51343class Raycaster {
51344
51345	constructor( origin, direction, near = 0, far = Infinity ) {
51346
51347		this.ray = new Ray( origin, direction );
51348		// direction is assumed to be normalized (for accurate distance calculations)
51349
51350		this.near = near;
51351		this.far = far;
51352		this.camera = null;
51353		this.layers = new Layers();
51354
51355		this.params = {
51356			Mesh: {},
51357			Line: { threshold: 1 },
51358			LOD: {},
51359			Points: { threshold: 1 },
51360			Sprite: {}
51361		};
51362
51363	}
51364
51365	set( origin, direction ) {
51366
51367		// direction is assumed to be normalized (for accurate distance calculations)
51368
51369		this.ray.set( origin, direction );
51370
51371	}
51372
51373	setFromCamera( coords, camera ) {
51374
51375		if ( camera.isPerspectiveCamera ) {
51376
51377			this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
51378			this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
51379			this.camera = camera;
51380
51381		} else if ( camera.isOrthographicCamera ) {
51382
51383			this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
51384			this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
51385			this.camera = camera;
51386
51387		} else {
51388
51389			console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
51390
51391		}
51392
51393	}
51394
51395	setFromXRController( controller ) {
51396
51397		_matrix.identity().extractRotation( controller.matrixWorld );
51398
51399		this.ray.origin.setFromMatrixPosition( controller.matrixWorld );
51400		this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix );
51401
51402		return this;
51403
51404	}
51405
51406	intersectObject( object, recursive = true, intersects = [] ) {
51407
51408		intersect( object, this, intersects, recursive );
51409
51410		intersects.sort( ascSort );
51411
51412		return intersects;
51413
51414	}
51415
51416	intersectObjects( objects, recursive = true, intersects = [] ) {
51417
51418		for ( let i = 0, l = objects.length; i < l; i ++ ) {
51419
51420			intersect( objects[ i ], this, intersects, recursive );
51421
51422		}
51423
51424		intersects.sort( ascSort );
51425
51426		return intersects;
51427
51428	}
51429
51430}
51431
51432function ascSort( a, b ) {
51433
51434	return a.distance - b.distance;
51435
51436}
51437
51438function intersect( object, raycaster, intersects, recursive ) {
51439
51440	let propagate = true;
51441
51442	if ( object.layers.test( raycaster.layers ) ) {
51443
51444		const result = object.raycast( raycaster, intersects );
51445
51446		if ( result === false ) propagate = false;
vendor: 21,614 bytes, lines 51447-52624
51447
51448	}
51449
51450	if ( propagate === true && recursive === true ) {
51451
51452		const children = object.children;
51453
51454		for ( let i = 0, l = children.length; i < l; i ++ ) {
51455
51456			intersect( children[ i ], raycaster, intersects, true );
51457
51458		}
51459
51460	}
51461
51462}
51463
51464/**
51465 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
51466 *
51467 * phi (the polar angle) is measured from the positive y-axis. The positive y-axis is up.
51468 * theta (the azimuthal angle) is measured from the positive z-axis.
51469 */
51470class Spherical {
51471
51472	constructor( radius = 1, phi = 0, theta = 0 ) {
51473
51474		this.radius = radius;
51475		this.phi = phi; // polar angle
51476		this.theta = theta; // azimuthal angle
51477
51478		return this;
51479
51480	}
51481
51482	set( radius, phi, theta ) {
51483
51484		this.radius = radius;
51485		this.phi = phi;
51486		this.theta = theta;
51487
51488		return this;
51489
51490	}
51491
51492	copy( other ) {
51493
51494		this.radius = other.radius;
51495		this.phi = other.phi;
51496		this.theta = other.theta;
51497
51498		return this;
51499
51500	}
51501
51502	// restrict phi to be between EPS and PI-EPS
51503	makeSafe() {
51504
51505		const EPS = 0.000001;
51506		this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
51507
51508		return this;
51509
51510	}
51511
51512	setFromVector3( v ) {
51513
51514		return this.setFromCartesianCoords( v.x, v.y, v.z );
51515
51516	}
51517
51518	setFromCartesianCoords( x, y, z ) {
51519
51520		this.radius = Math.sqrt( x * x + y * y + z * z );
51521
51522		if ( this.radius === 0 ) {
51523
51524			this.theta = 0;
51525			this.phi = 0;
51526
51527		} else {
51528
51529			this.theta = Math.atan2( x, z );
51530			this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) );
51531
51532		}
51533
51534		return this;
51535
51536	}
51537
51538	clone() {
51539
51540		return new this.constructor().copy( this );
51541
51542	}
51543
51544}
51545
51546/**
51547 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
51548 */
51549
51550class Cylindrical {
51551
51552	constructor( radius = 1, theta = 0, y = 0 ) {
51553
51554		this.radius = radius; // distance from the origin to a point in the x-z plane
51555		this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
51556		this.y = y; // height above the x-z plane
51557
51558		return this;
51559
51560	}
51561
51562	set( radius, theta, y ) {
51563
51564		this.radius = radius;
51565		this.theta = theta;
51566		this.y = y;
51567
51568		return this;
51569
51570	}
51571
51572	copy( other ) {
51573
51574		this.radius = other.radius;
51575		this.theta = other.theta;
51576		this.y = other.y;
51577
51578		return this;
51579
51580	}
51581
51582	setFromVector3( v ) {
51583
51584		return this.setFromCartesianCoords( v.x, v.y, v.z );
51585
51586	}
51587
51588	setFromCartesianCoords( x, y, z ) {
51589
51590		this.radius = Math.sqrt( x * x + z * z );
51591		this.theta = Math.atan2( x, z );
51592		this.y = y;
51593
51594		return this;
51595
51596	}
51597
51598	clone() {
51599
51600		return new this.constructor().copy( this );
51601
51602	}
51603
51604}
51605
51606const _vector$4 = /*@__PURE__*/ new Vector2();
51607
51608class Box2 {
51609
51610	constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) {
51611
51612		this.isBox2 = true;
51613
51614		this.min = min;
51615		this.max = max;
51616
51617	}
51618
51619	set( min, max ) {
51620
51621		this.min.copy( min );
51622		this.max.copy( max );
51623
51624		return this;
51625
51626	}
51627
51628	setFromPoints( points ) {
51629
51630		this.makeEmpty();
51631
51632		for ( let i = 0, il = points.length; i < il; i ++ ) {
51633
51634			this.expandByPoint( points[ i ] );
51635
51636		}
51637
51638		return this;
51639
51640	}
51641
51642	setFromCenterAndSize( center, size ) {
51643
51644		const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 );
51645		this.min.copy( center ).sub( halfSize );
51646		this.max.copy( center ).add( halfSize );
51647
51648		return this;
51649
51650	}
51651
51652	clone() {
51653
51654		return new this.constructor().copy( this );
51655
51656	}
51657
51658	copy( box ) {
51659
51660		this.min.copy( box.min );
51661		this.max.copy( box.max );
51662
51663		return this;
51664
51665	}
51666
51667	makeEmpty() {
51668
51669		this.min.x = this.min.y = + Infinity;
51670		this.max.x = this.max.y = - Infinity;
51671
51672		return this;
51673
51674	}
51675
51676	isEmpty() {
51677
51678		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
51679
51680		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
51681
51682	}
51683
51684	getCenter( target ) {
51685
51686		return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
51687
51688	}
51689
51690	getSize( target ) {
51691
51692		return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
51693
51694	}
51695
51696	expandByPoint( point ) {
51697
51698		this.min.min( point );
51699		this.max.max( point );
51700
51701		return this;
51702
51703	}
51704
51705	expandByVector( vector ) {
51706
51707		this.min.sub( vector );
51708		this.max.add( vector );
51709
51710		return this;
51711
51712	}
51713
51714	expandByScalar( scalar ) {
51715
51716		this.min.addScalar( - scalar );
51717		this.max.addScalar( scalar );
51718
51719		return this;
51720
51721	}
51722
51723	containsPoint( point ) {
51724
51725		return point.x < this.min.x || point.x > this.max.x ||
51726			point.y < this.min.y || point.y > this.max.y ? false : true;
51727
51728	}
51729
51730	containsBox( box ) {
51731
51732		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
51733			this.min.y <= box.min.y && box.max.y <= this.max.y;
51734
51735	}
51736
51737	getParameter( point, target ) {
51738
51739		// This can potentially have a divide by zero if the box
51740		// has a size dimension of 0.
51741
51742		return target.set(
51743			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
51744			( point.y - this.min.y ) / ( this.max.y - this.min.y )
51745		);
51746
51747	}
51748
51749	intersectsBox( box ) {
51750
51751		// using 4 splitting planes to rule out intersections
51752
51753		return box.max.x < this.min.x || box.min.x > this.max.x ||
51754			box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
51755
51756	}
51757
51758	clampPoint( point, target ) {
51759
51760		return target.copy( point ).clamp( this.min, this.max );
51761
51762	}
51763
51764	distanceToPoint( point ) {
51765
51766		return this.clampPoint( point, _vector$4 ).distanceTo( point );
51767
51768	}
51769
51770	intersect( box ) {
51771
51772		this.min.max( box.min );
51773		this.max.min( box.max );
51774
51775		if ( this.isEmpty() ) this.makeEmpty();
51776
51777		return this;
51778
51779	}
51780
51781	union( box ) {
51782
51783		this.min.min( box.min );
51784		this.max.max( box.max );
51785
51786		return this;
51787
51788	}
51789
51790	translate( offset ) {
51791
51792		this.min.add( offset );
51793		this.max.add( offset );
51794
51795		return this;
51796
51797	}
51798
51799	equals( box ) {
51800
51801		return box.min.equals( this.min ) && box.max.equals( this.max );
51802
51803	}
51804
51805}
51806
51807const _startP = /*@__PURE__*/ new Vector3();
51808const _startEnd = /*@__PURE__*/ new Vector3();
51809
51810class Line3 {
51811
51812	constructor( start = new Vector3(), end = new Vector3() ) {
51813
51814		this.start = start;
51815		this.end = end;
51816
51817	}
51818
51819	set( start, end ) {
51820
51821		this.start.copy( start );
51822		this.end.copy( end );
51823
51824		return this;
51825
51826	}
51827
51828	copy( line ) {
51829
51830		this.start.copy( line.start );
51831		this.end.copy( line.end );
51832
51833		return this;
51834
51835	}
51836
51837	getCenter( target ) {
51838
51839		return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
51840
51841	}
51842
51843	delta( target ) {
51844
51845		return target.subVectors( this.end, this.start );
51846
51847	}
51848
51849	distanceSq() {
51850
51851		return this.start.distanceToSquared( this.end );
51852
51853	}
51854
51855	distance() {
51856
51857		return this.start.distanceTo( this.end );
51858
51859	}
51860
51861	at( t, target ) {
51862
51863		return this.delta( target ).multiplyScalar( t ).add( this.start );
51864
51865	}
51866
51867	closestPointToPointParameter( point, clampToLine ) {
51868
51869		_startP.subVectors( point, this.start );
51870		_startEnd.subVectors( this.end, this.start );
51871
51872		const startEnd2 = _startEnd.dot( _startEnd );
51873		const startEnd_startP = _startEnd.dot( _startP );
51874
51875		let t = startEnd_startP / startEnd2;
51876
51877		if ( clampToLine ) {
51878
51879			t = clamp( t, 0, 1 );
51880
51881		}
51882
51883		return t;
51884
51885	}
51886
51887	closestPointToPoint( point, clampToLine, target ) {
51888
51889		const t = this.closestPointToPointParameter( point, clampToLine );
51890
51891		return this.delta( target ).multiplyScalar( t ).add( this.start );
51892
51893	}
51894
51895	applyMatrix4( matrix ) {
51896
51897		this.start.applyMatrix4( matrix );
51898		this.end.applyMatrix4( matrix );
51899
51900		return this;
51901
51902	}
51903
51904	equals( line ) {
51905
51906		return line.start.equals( this.start ) && line.end.equals( this.end );
51907
51908	}
51909
51910	clone() {
51911
51912		return new this.constructor().copy( this );
51913
51914	}
51915
51916}
51917
51918const _vector$3 = /*@__PURE__*/ new Vector3();
51919
51920class SpotLightHelper extends Object3D {
51921
51922	constructor( light, color ) {
51923
51924		super();
51925
51926		this.light = light;
51927
51928		this.matrixAutoUpdate = false;
51929
51930		this.color = color;
51931
51932		this.type = 'SpotLightHelper';
51933
51934		const geometry = new BufferGeometry();
51935
51936		const positions = [
51937			0, 0, 0, 	0, 0, 1,
51938			0, 0, 0, 	1, 0, 1,
51939			0, 0, 0,	- 1, 0, 1,
51940			0, 0, 0, 	0, 1, 1,
51941			0, 0, 0, 	0, - 1, 1
51942		];
51943
51944		for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
51945
51946			const p1 = ( i / l ) * Math.PI * 2;
51947			const p2 = ( j / l ) * Math.PI * 2;
51948
51949			positions.push(
51950				Math.cos( p1 ), Math.sin( p1 ), 1,
51951				Math.cos( p2 ), Math.sin( p2 ), 1
51952			);
51953
51954		}
51955
51956		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
51957
51958		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
51959
51960		this.cone = new LineSegments( geometry, material );
51961		this.add( this.cone );
51962
51963		this.update();
51964
51965	}
51966
51967	dispose() {
51968
51969		this.cone.geometry.dispose();
51970		this.cone.material.dispose();
51971
51972	}
51973
51974	update() {
51975
51976		this.light.updateWorldMatrix( true, false );
51977		this.light.target.updateWorldMatrix( true, false );
51978
51979		// update the local matrix based on the parent and light target transforms
51980		if ( this.parent ) {
51981
51982			this.parent.updateWorldMatrix( true );
51983
51984			this.matrix
51985				.copy( this.parent.matrixWorld )
51986				.invert()
51987				.multiply( this.light.matrixWorld );
51988
51989		} else {
51990
51991			this.matrix.copy( this.light.matrixWorld );
51992
51993		}
51994
51995		this.matrixWorld.copy( this.light.matrixWorld );
51996
51997		const coneLength = this.light.distance ? this.light.distance : 1000;
51998		const coneWidth = coneLength * Math.tan( this.light.angle );
51999
52000		this.cone.scale.set( coneWidth, coneWidth, coneLength );
52001
52002		_vector$3.setFromMatrixPosition( this.light.target.matrixWorld );
52003
52004		this.cone.lookAt( _vector$3 );
52005
52006		if ( this.color !== undefined ) {
52007
52008			this.cone.material.color.set( this.color );
52009
52010		} else {
52011
52012			this.cone.material.color.copy( this.light.color );
52013
52014		}
52015
52016	}
52017
52018}
52019
52020const _vector$2 = /*@__PURE__*/ new Vector3();
52021const _boneMatrix = /*@__PURE__*/ new Matrix4();
52022const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
52023
52024
52025class SkeletonHelper extends LineSegments {
52026
52027	constructor( object ) {
52028
52029		const bones = getBoneList( object );
52030
52031		const geometry = new BufferGeometry();
52032
52033		const vertices = [];
52034		const colors = [];
52035
52036		const color1 = new Color( 0, 0, 1 );
52037		const color2 = new Color( 0, 1, 0 );
52038
52039		for ( let i = 0; i < bones.length; i ++ ) {
52040
52041			const bone = bones[ i ];
52042
52043			if ( bone.parent && bone.parent.isBone ) {
52044
52045				vertices.push( 0, 0, 0 );
52046				vertices.push( 0, 0, 0 );
52047				colors.push( color1.r, color1.g, color1.b );
52048				colors.push( color2.r, color2.g, color2.b );
52049
52050			}
52051
52052		}
52053
52054		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52055		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52056
52057		const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
52058
52059		super( geometry, material );
52060
52061		this.isSkeletonHelper = true;
52062
52063		this.type = 'SkeletonHelper';
52064
52065		this.root = object;
52066		this.bones = bones;
52067
52068		this.matrix = object.matrixWorld;
52069		this.matrixAutoUpdate = false;
52070
52071	}
52072
52073	updateMatrixWorld( force ) {
52074
52075		const bones = this.bones;
52076
52077		const geometry = this.geometry;
52078		const position = geometry.getAttribute( 'position' );
52079
52080		_matrixWorldInv.copy( this.root.matrixWorld ).invert();
52081
52082		for ( let i = 0, j = 0; i < bones.length; i ++ ) {
52083
52084			const bone = bones[ i ];
52085
52086			if ( bone.parent && bone.parent.isBone ) {
52087
52088				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
52089				_vector$2.setFromMatrixPosition( _boneMatrix );
52090				position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z );
52091
52092				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
52093				_vector$2.setFromMatrixPosition( _boneMatrix );
52094				position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z );
52095
52096				j += 2;
52097
52098			}
52099
52100		}
52101
52102		geometry.getAttribute( 'position' ).needsUpdate = true;
52103
52104		super.updateMatrixWorld( force );
52105
52106	}
52107
52108	dispose() {
52109
52110		this.geometry.dispose();
52111		this.material.dispose();
52112
52113	}
52114
52115}
52116
52117
52118function getBoneList( object ) {
52119
52120	const boneList = [];
52121
52122	if ( object.isBone === true ) {
52123
52124		boneList.push( object );
52125
52126	}
52127
52128	for ( let i = 0; i < object.children.length; i ++ ) {
52129
52130		boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
52131
52132	}
52133
52134	return boneList;
52135
52136}
52137
52138class PointLightHelper extends Mesh {
52139
52140	constructor( light, sphereSize, color ) {
52141
52142		const geometry = new SphereGeometry( sphereSize, 4, 2 );
52143		const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
52144
52145		super( geometry, material );
52146
52147		this.light = light;
52148
52149		this.color = color;
52150
52151		this.type = 'PointLightHelper';
52152
52153		this.matrix = this.light.matrixWorld;
52154		this.matrixAutoUpdate = false;
52155
52156		this.update();
52157
52158
52159		/*
52160	// TODO: delete this comment?
52161	const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
52162	const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
52163
52164	this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
52165	this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
52166
52167	const d = light.distance;
52168
52169	if ( d === 0.0 ) {
52170
52171		this.lightDistance.visible = false;
52172
52173	} else {
52174
52175		this.lightDistance.scale.set( d, d, d );
52176
52177	}
52178
52179	this.add( this.lightDistance );
52180	*/
52181
52182	}
52183
52184	dispose() {
52185
52186		this.geometry.dispose();
52187		this.material.dispose();
52188
52189	}
52190
52191	update() {
52192
52193		this.light.updateWorldMatrix( true, false );
52194
52195		if ( this.color !== undefined ) {
52196
52197			this.material.color.set( this.color );
52198
52199		} else {
52200
52201			this.material.color.copy( this.light.color );
52202
52203		}
52204
52205		/*
52206		const d = this.light.distance;
52207
52208		if ( d === 0.0 ) {
52209
52210			this.lightDistance.visible = false;
52211
52212		} else {
52213
52214			this.lightDistance.visible = true;
52215			this.lightDistance.scale.set( d, d, d );
52216
52217		}
52218		*/
52219
52220	}
52221
52222}
52223
52224const _vector$1 = /*@__PURE__*/ new Vector3();
52225const _color1 = /*@__PURE__*/ new Color();
52226const _color2 = /*@__PURE__*/ new Color();
52227
52228class HemisphereLightHelper extends Object3D {
52229
52230	constructor( light, size, color ) {
52231
52232		super();
52233
52234		this.light = light;
52235
52236		this.matrix = light.matrixWorld;
52237		this.matrixAutoUpdate = false;
52238
52239		this.color = color;
52240
52241		this.type = 'HemisphereLightHelper';
52242
52243		const geometry = new OctahedronGeometry( size );
52244		geometry.rotateY( Math.PI * 0.5 );
52245
52246		this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
52247		if ( this.color === undefined ) this.material.vertexColors = true;
52248
52249		const position = geometry.getAttribute( 'position' );
52250		const colors = new Float32Array( position.count * 3 );
52251
52252		geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
52253
52254		this.add( new Mesh( geometry, this.material ) );
52255
52256		this.update();
52257
52258	}
52259
52260	dispose() {
52261
52262		this.children[ 0 ].geometry.dispose();
52263		this.children[ 0 ].material.dispose();
52264
52265	}
52266
52267	update() {
52268
52269		const mesh = this.children[ 0 ];
52270
52271		if ( this.color !== undefined ) {
52272
52273			this.material.color.set( this.color );
52274
52275		} else {
52276
52277			const colors = mesh.geometry.getAttribute( 'color' );
52278
52279			_color1.copy( this.light.color );
52280			_color2.copy( this.light.groundColor );
52281
52282			for ( let i = 0, l = colors.count; i < l; i ++ ) {
52283
52284				const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
52285
52286				colors.setXYZ( i, color.r, color.g, color.b );
52287
52288			}
52289
52290			colors.needsUpdate = true;
52291
52292		}
52293
52294		this.light.updateWorldMatrix( true, false );
52295
52296		mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() );
52297
52298	}
52299
52300}
52301
52302class GridHelper extends LineSegments {
52303
52304	constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
52305
52306		color1 = new Color( color1 );
52307		color2 = new Color( color2 );
52308
52309		const center = divisions / 2;
52310		const step = size / divisions;
52311		const halfSize = size / 2;
52312
52313		const vertices = [], colors = [];
52314
52315		for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
52316
52317			vertices.push( - halfSize, 0, k, halfSize, 0, k );
52318			vertices.push( k, 0, - halfSize, k, 0, halfSize );
52319
52320			const color = i === center ? color1 : color2;
52321
52322			color.toArray( colors, j ); j += 3;
52323			color.toArray( colors, j ); j += 3;
52324			color.toArray( colors, j ); j += 3;
52325			color.toArray( colors, j ); j += 3;
52326
52327		}
52328
52329		const geometry = new BufferGeometry();
52330		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52331		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52332
52333		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
52334
52335		super( geometry, material );
52336
52337		this.type = 'GridHelper';
52338
52339	}
52340
52341	dispose() {
52342
52343		this.geometry.dispose();
52344		this.material.dispose();
52345
52346	}
52347
52348}
52349
52350class PolarGridHelper extends LineSegments {
52351
52352	constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
52353
52354		color1 = new Color( color1 );
52355		color2 = new Color( color2 );
52356
52357		const vertices = [];
52358		const colors = [];
52359
52360		// create the sectors
52361
52362		if ( sectors > 1 ) {
52363
52364			for ( let i = 0; i < sectors; i ++ ) {
52365
52366				const v = ( i / sectors ) * ( Math.PI * 2 );
52367
52368				const x = Math.sin( v ) * radius;
52369				const z = Math.cos( v ) * radius;
52370
52371				vertices.push( 0, 0, 0 );
52372				vertices.push( x, 0, z );
52373
52374				const color = ( i & 1 ) ? color1 : color2;
52375
52376				colors.push( color.r, color.g, color.b );
52377				colors.push( color.r, color.g, color.b );
52378
52379			}
52380
52381		}
52382
52383		// create the rings
52384
52385		for ( let i = 0; i < rings; i ++ ) {
52386
52387			const color = ( i & 1 ) ? color1 : color2;
52388
52389			const r = radius - ( radius / rings * i );
52390
52391			for ( let j = 0; j < divisions; j ++ ) {
52392
52393				// first vertex
52394
52395				let v = ( j / divisions ) * ( Math.PI * 2 );
52396
52397				let x = Math.sin( v ) * r;
52398				let z = Math.cos( v ) * r;
52399
52400				vertices.push( x, 0, z );
52401				colors.push( color.r, color.g, color.b );
52402
52403				// second vertex
52404
52405				v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
52406
52407				x = Math.sin( v ) * r;
52408				z = Math.cos( v ) * r;
52409
52410				vertices.push( x, 0, z );
52411				colors.push( color.r, color.g, color.b );
52412
52413			}
52414
52415		}
52416
52417		const geometry = new BufferGeometry();
52418		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52419		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52420
52421		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
52422
52423		super( geometry, material );
52424
52425		this.type = 'PolarGridHelper';
52426
52427	}
52428
52429	dispose() {
52430
52431		this.geometry.dispose();
52432		this.material.dispose();
52433
52434	}
52435
52436}
52437
52438const _v1 = /*@__PURE__*/ new Vector3();
52439const _v2 = /*@__PURE__*/ new Vector3();
52440const _v3 = /*@__PURE__*/ new Vector3();
52441
52442class DirectionalLightHelper extends Object3D {
52443
52444	constructor( light, size, color ) {
52445
52446		super();
52447
52448		this.light = light;
52449
52450		this.matrix = light.matrixWorld;
52451		this.matrixAutoUpdate = false;
52452
52453		this.color = color;
52454
52455		this.type = 'DirectionalLightHelper';
52456
52457		if ( size === undefined ) size = 1;
52458
52459		let geometry = new BufferGeometry();
52460		geometry.setAttribute( 'position', new Float32BufferAttribute( [
52461			- size, size, 0,
52462			size, size, 0,
52463			size, - size, 0,
52464			- size, - size, 0,
52465			- size, size, 0
52466		], 3 ) );
52467
52468		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
52469
52470		this.lightPlane = new Line( geometry, material );
52471		this.add( this.lightPlane );
52472
52473		geometry = new BufferGeometry();
52474		geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
52475
52476		this.targetLine = new Line( geometry, material );
52477		this.add( this.targetLine );
52478
52479		this.update();
52480
52481	}
52482
52483	dispose() {
52484
52485		this.lightPlane.geometry.dispose();
52486		this.lightPlane.material.dispose();
52487		this.targetLine.geometry.dispose();
52488		this.targetLine.material.dispose();
52489
52490	}
52491
52492	update() {
52493
52494		this.light.updateWorldMatrix( true, false );
52495		this.light.target.updateWorldMatrix( true, false );
52496
52497		_v1.setFromMatrixPosition( this.light.matrixWorld );
52498		_v2.setFromMatrixPosition( this.light.target.matrixWorld );
52499		_v3.subVectors( _v2, _v1 );
52500
52501		this.lightPlane.lookAt( _v2 );
52502
52503		if ( this.color !== undefined ) {
52504
52505			this.lightPlane.material.color.set( this.color );
52506			this.targetLine.material.color.set( this.color );
52507
52508		} else {
52509
52510			this.lightPlane.material.color.copy( this.light.color );
52511			this.targetLine.material.color.copy( this.light.color );
52512
52513		}
52514
52515		this.targetLine.lookAt( _v2 );
52516		this.targetLine.scale.z = _v3.length();
52517
52518	}
52519
52520}
52521
52522const _vector = /*@__PURE__*/ new Vector3();
52523const _camera = /*@__PURE__*/ new Camera();
52524
52525/**
52526 *	- shows frustum, line of sight and up of the camera
52527 *	- suitable for fast updates
52528 * 	- based on frustum visualization in lightgl.js shadowmap example
52529 *		https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html
52530 */
52531
52532class CameraHelper extends LineSegments {
52533
52534	constructor( camera ) {
52535
52536		const geometry = new BufferGeometry();
52537		const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
52538
52539		const vertices = [];
52540		const colors = [];
52541
52542		const pointMap = {};
52543
52544		// near
52545
52546		addLine( 'n1', 'n2' );
52547		addLine( 'n2', 'n4' );
52548		addLine( 'n4', 'n3' );
52549		addLine( 'n3', 'n1' );
52550
52551		// far
52552
52553		addLine( 'f1', 'f2' );
52554		addLine( 'f2', 'f4' );
52555		addLine( 'f4', 'f3' );
52556		addLine( 'f3', 'f1' );
52557
52558		// sides
52559
52560		addLine( 'n1', 'f1' );
52561		addLine( 'n2', 'f2' );
52562		addLine( 'n3', 'f3' );
52563		addLine( 'n4', 'f4' );
52564
52565		// cone
52566
52567		addLine( 'p', 'n1' );
52568		addLine( 'p', 'n2' );
52569		addLine( 'p', 'n3' );
52570		addLine( 'p', 'n4' );
52571
52572		// up
52573
52574		addLine( 'u1', 'u2' );
52575		addLine( 'u2', 'u3' );
52576		addLine( 'u3', 'u1' );
52577
52578		// target
52579
52580		addLine( 'c', 't' );
52581		addLine( 'p', 'c' );
52582
52583		// cross
52584
52585		addLine( 'cn1', 'cn2' );
52586		addLine( 'cn3', 'cn4' );
52587
52588		addLine( 'cf1', 'cf2' );
52589		addLine( 'cf3', 'cf4' );
52590
52591		function addLine( a, b ) {
52592
52593			addPoint( a );
52594			addPoint( b );
52595
52596		}
52597
52598		function addPoint( id ) {
52599
52600			vertices.push( 0, 0, 0 );
52601			colors.push( 0, 0, 0 );
52602
52603			if ( pointMap[ id ] === undefined ) {
52604
52605				pointMap[ id ] = [];
52606
52607			}
52608
52609			pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
52610
52611		}
52612
52613		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52614		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52615
52616		super( geometry, material );
52617
52618		this.type = 'CameraHelper';
52619
52620		this.camera = camera;
52621		if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
52622
52623		this.matrix = camera.matrixWorld;
52624		this.matrixAutoUpdate = false;
52625
52626		this.pointMap = pointMap;
52627
52628		this.update();
52629
52630		// colors
52631
52632		const colorFrustum = new Color( 0xffaa00 );
52633		const colorCone = new Color( 0xff0000 );
52634		const colorUp = new Color( 0x00aaff );
52635		const colorTarget = new Color( 0xffffff );
52636		const colorCross = new Color( 0x333333 );
52637
52638		this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross );
52639
52640	}
52641
52642	setColors( frustum, cone, up, target, cross ) {
52643
52644		const geometry = this.geometry;
52645
52646		const colorAttribute = geometry.getAttribute( 'color' );
52647
52648		// near
52649
52650		colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2
52651		colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4
52652		colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3
52653		colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1
52654
52655		// far
52656
52657		colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2
52658		colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4
52659		colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3
52660		colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1
52661
52662		// sides
52663
52664		colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1
52665		colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2
52666		colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3
52667		colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4
52668
52669		// cone
52670
52671		colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1
52672		colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2
52673		colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3
52674		colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4
52675
52676		// up
52677
52678		colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2
52679		colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3
52680		colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1
52681
52682		// target
52683
52684		colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t
52685		colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c
52686
52687		// cross
52688
52689		colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2
52690		colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4
52691
52692		colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2
52693		colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4
52694
52695		colorAttribute.needsUpdate = true;
52696
52697	}
52698
52699	update() {
52700
52701		const geometry = this.geometry;
52702		const pointMap = this.pointMap;
52703
52704		const w = 1, h = 1;
52705
52706		// we need just camera projection matrix inverse
52707		// world matrix must be identity
52708
52709		_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
52710
52711		// center / target
52712
52713		setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
52714		setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
52715
52716		// near
52717
52718		setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
52719		setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
52720		setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
52721		setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
52722
52723		// far
52724
52725		setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
52726		setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
52727		setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
52728		setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
52729
52730		// up
52731
52732		setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
52733		setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
52734		setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
52735
52736		// cross
52737
52738		setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
52739		setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
52740		setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
52741		setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
52742
52743		setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
52744		setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
52745		setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
52746		setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
52747
52748		geometry.getAttribute( 'position' ).needsUpdate = true;
52749
52750	}
52751
52752	dispose() {
52753
52754		this.geometry.dispose();
52755		this.material.dispose();
52756
52757	}
52758
52759}
52760
52761
52762function setPoint( point, pointMap, geometry, camera, x, y, z ) {
52763
52764	_vector.set( x, y, z ).unproject( camera );
52765
52766	const points = pointMap[ point ];
52767
52768	if ( points !== undefined ) {
52769
52770		const position = geometry.getAttribute( 'position' );
52771
52772		for ( let i = 0, l = points.length; i < l; i ++ ) {
52773
52774			position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z );
52775
52776		}
52777
52778	}
52779
52780}
52781
52782const _box = /*@__PURE__*/ new Box3();
52783
52784class BoxHelper extends LineSegments {
52785
52786	constructor( object, color = 0xffff00 ) {
52787
52788		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 ] );
52789		const positions = new Float32Array( 8 * 3 );
52790
52791		const geometry = new BufferGeometry();
52792		geometry.setIndex( new BufferAttribute( indices, 1 ) );
52793		geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
52794
52795		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52796
52797		this.object = object;
52798		this.type = 'BoxHelper';
52799
52800		this.matrixAutoUpdate = false;
vendor: 4,705 bytes, lines 52801-53017
52801
52802		this.update();
52803
52804	}
52805
52806	update( object ) {
52807
52808		if ( object !== undefined ) {
52809
52810			console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
52811
52812		}
52813
52814		if ( this.object !== undefined ) {
52815
52816			_box.setFromObject( this.object );
52817
52818		}
52819
52820		if ( _box.isEmpty() ) return;
52821
52822		const min = _box.min;
52823		const max = _box.max;
52824
52825		/*
52826			5____4
52827		1/___0/|
52828		| 6__|_7
52829		2/___3/
52830
52831		0: max.x, max.y, max.z
52832		1: min.x, max.y, max.z
52833		2: min.x, min.y, max.z
52834		3: max.x, min.y, max.z
52835		4: max.x, max.y, min.z
52836		5: min.x, max.y, min.z
52837		6: min.x, min.y, min.z
52838		7: max.x, min.y, min.z
52839		*/
52840
52841		const position = this.geometry.attributes.position;
52842		const array = position.array;
52843
52844		array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
52845		array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
52846		array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
52847		array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
52848		array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
52849		array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
52850		array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
52851		array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
52852
52853		position.needsUpdate = true;
52854
52855		this.geometry.computeBoundingSphere();
52856
52857	}
52858
52859	setFromObject( object ) {
52860
52861		this.object = object;
52862		this.update();
52863
52864		return this;
52865
52866	}
52867
52868	copy( source, recursive ) {
52869
52870		super.copy( source, recursive );
52871
52872		this.object = source.object;
52873
52874		return this;
52875
52876	}
52877
52878	dispose() {
52879
52880		this.geometry.dispose();
52881		this.material.dispose();
52882
52883	}
52884
52885}
52886
52887class Box3Helper extends LineSegments {
52888
52889	constructor( box, color = 0xffff00 ) {
52890
52891		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 ] );
52892
52893		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 ];
52894
52895		const geometry = new BufferGeometry();
52896
52897		geometry.setIndex( new BufferAttribute( indices, 1 ) );
52898
52899		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52900
52901		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52902
52903		this.box = box;
52904
52905		this.type = 'Box3Helper';
52906
52907		this.geometry.computeBoundingSphere();
52908
52909	}
52910
52911	updateMatrixWorld( force ) {
52912
52913		const box = this.box;
52914
52915		if ( box.isEmpty() ) return;
52916
52917		box.getCenter( this.position );
52918
52919		box.getSize( this.scale );
52920
52921		this.scale.multiplyScalar( 0.5 );
52922
52923		super.updateMatrixWorld( force );
52924
52925	}
52926
52927	dispose() {
52928
52929		this.geometry.dispose();
52930		this.material.dispose();
52931
52932	}
52933
52934}
52935
52936class PlaneHelper extends Line {
52937
52938	constructor( plane, size = 1, hex = 0xffff00 ) {
52939
52940		const color = hex;
52941
52942		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 ];
52943
52944		const geometry = new BufferGeometry();
52945		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52946		geometry.computeBoundingSphere();
52947
52948		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52949
52950		this.type = 'PlaneHelper';
52951
52952		this.plane = plane;
52953
52954		this.size = size;
52955
52956		const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];
52957
52958		const geometry2 = new BufferGeometry();
52959		geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
52960		geometry2.computeBoundingSphere();
52961
52962		this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
52963
52964	}
52965
52966	updateMatrixWorld( force ) {
52967
52968		this.position.set( 0, 0, 0 );
52969
52970		this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 );
52971
52972		this.lookAt( this.plane.normal );
52973
52974		this.translateZ( - this.plane.constant );
52975
52976		super.updateMatrixWorld( force );
52977
52978	}
52979
52980	dispose() {
52981
52982		this.geometry.dispose();
52983		this.material.dispose();
52984		this.children[ 0 ].geometry.dispose();
52985		this.children[ 0 ].material.dispose();
52986
52987	}
52988
52989}
52990
52991const _axis = /*@__PURE__*/ new Vector3();
52992let _lineGeometry, _coneGeometry;
52993
52994class ArrowHelper extends Object3D {
52995
52996	// dir is assumed to be normalized
52997
52998	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 ) {
52999
53000		super();
53001
53002		this.type = 'ArrowHelper';
53003
53004		if ( _lineGeometry === undefined ) {
53005
53006			_lineGeometry = new BufferGeometry();
53007			_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
53008
53009			_coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 );
53010			_coneGeometry.translate( 0, - 0.5, 0 );
53011
53012		}
53013
53014		this.position.copy( origin );
53015
53016		this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
53017		this.line.matrixAutoUpdate = false;
vendor: 3,957 bytes, lines 53018-53237
53018		this.add( this.line );
53019
53020		this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
53021		this.cone.matrixAutoUpdate = false;
53022		this.add( this.cone );
53023
53024		this.setDirection( dir );
53025		this.setLength( length, headLength, headWidth );
53026
53027	}
53028
53029	setDirection( dir ) {
53030
53031		// dir is assumed to be normalized
53032
53033		if ( dir.y > 0.99999 ) {
53034
53035			this.quaternion.set( 0, 0, 0, 1 );
53036
53037		} else if ( dir.y < - 0.99999 ) {
53038
53039			this.quaternion.set( 1, 0, 0, 0 );
53040
53041		} else {
53042
53043			_axis.set( dir.z, 0, - dir.x ).normalize();
53044
53045			const radians = Math.acos( dir.y );
53046
53047			this.quaternion.setFromAxisAngle( _axis, radians );
53048
53049		}
53050
53051	}
53052
53053	setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
53054
53055		this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
53056		this.line.updateMatrix();
53057
53058		this.cone.scale.set( headWidth, headLength, headWidth );
53059		this.cone.position.y = length;
53060		this.cone.updateMatrix();
53061
53062	}
53063
53064	setColor( color ) {
53065
53066		this.line.material.color.set( color );
53067		this.cone.material.color.set( color );
53068
53069	}
53070
53071	copy( source ) {
53072
53073		super.copy( source, false );
53074
53075		this.line.copy( source.line );
53076		this.cone.copy( source.cone );
53077
53078		return this;
53079
53080	}
53081
53082	dispose() {
53083
53084		this.line.geometry.dispose();
53085		this.line.material.dispose();
53086		this.cone.geometry.dispose();
53087		this.cone.material.dispose();
53088
53089	}
53090
53091}
53092
53093class AxesHelper extends LineSegments {
53094
53095	constructor( size = 1 ) {
53096
53097		const vertices = [
53098			0, 0, 0,	size, 0, 0,
53099			0, 0, 0,	0, size, 0,
53100			0, 0, 0,	0, 0, size
53101		];
53102
53103		const colors = [
53104			1, 0, 0,	1, 0.6, 0,
53105			0, 1, 0,	0.6, 1, 0,
53106			0, 0, 1,	0, 0.6, 1
53107		];
53108
53109		const geometry = new BufferGeometry();
53110		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
53111		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
53112
53113		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
53114
53115		super( geometry, material );
53116
53117		this.type = 'AxesHelper';
53118
53119	}
53120
53121	setColors( xAxisColor, yAxisColor, zAxisColor ) {
53122
53123		const color = new Color();
53124		const array = this.geometry.attributes.color.array;
53125
53126		color.set( xAxisColor );
53127		color.toArray( array, 0 );
53128		color.toArray( array, 3 );
53129
53130		color.set( yAxisColor );
53131		color.toArray( array, 6 );
53132		color.toArray( array, 9 );
53133
53134		color.set( zAxisColor );
53135		color.toArray( array, 12 );
53136		color.toArray( array, 15 );
53137
53138		this.geometry.attributes.color.needsUpdate = true;
53139
53140		return this;
53141
53142	}
53143
53144	dispose() {
53145
53146		this.geometry.dispose();
53147		this.material.dispose();
53148
53149	}
53150
53151}
53152
53153class ShapePath {
53154
53155	constructor() {
53156
53157		this.type = 'ShapePath';
53158
53159		this.color = new Color();
53160
53161		this.subPaths = [];
53162		this.currentPath = null;
53163
53164	}
53165
53166	moveTo( x, y ) {
53167
53168		this.currentPath = new Path();
53169		this.subPaths.push( this.currentPath );
53170		this.currentPath.moveTo( x, y );
53171
53172		return this;
53173
53174	}
53175
53176	lineTo( x, y ) {
53177
53178		this.currentPath.lineTo( x, y );
53179
53180		return this;
53181
53182	}
53183
53184	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
53185
53186		this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
53187
53188		return this;
53189
53190	}
53191
53192	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
53193
53194		this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
53195
53196		return this;
53197
53198	}
53199
53200	splineThru( pts ) {
53201
53202		this.currentPath.splineThru( pts );
53203
53204		return this;
53205
53206	}
53207
53208	toShapes( isCCW ) {
53209
53210		function toShapesNoHoles( inSubpaths ) {
53211
53212			const shapes = [];
53213
53214			for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
53215
53216				const tmpPath = inSubpaths[ i ];
53217
53218				const tmpShape = new Shape();
53219				tmpShape.curves = tmpPath.curves;
53220
53221				shapes.push( tmpShape );
53222
53223			}
53224
53225			return shapes;
53226
53227		}
53228
53229		function isPointInsidePolygon( inPt, inPolygon ) {
53230
53231			const polyLen = inPolygon.length;
53232
53233			// inPt on polygon contour => immediate success    or
53234			// toggling of inside/outside at every single! intersection point of an edge
53235			//  with the horizontal line through inPt, left of inPt
53236			//  not counting lowerY endpoints of edges and whole edges on that line
53237			let inside = false;
53238			for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
53239
53240				let edgeLowPt = inPolygon[ p ];
53241				let edgeHighPt = inPolygon[ q ];
53242
53243				let edgeDx = edgeHighPt.x - edgeLowPt.x;
53244				let edgeDy = edgeHighPt.y - edgeLowPt.y;
53245
53246				if ( Math.abs( edgeDy ) > Number.EPSILON ) {
53247
53248					// not parallel
53249					if ( edgeDy < 0 ) {
53250
53251						edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
53252						edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
53253
53254					}
53255
53256					if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) 		continue;
53257
53258					if ( inPt.y === edgeLowPt.y ) {
53259
53260						if ( inPt.x === edgeLowPt.x )		return	true;		// inPt is on contour ?
53261						// continue;				// no intersection or edgeLowPt => doesn't count !!!
53262
53263					} else {
53264
53265						const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
53266						if ( perpEdge === 0 )				return	true;		// inPt is on contour ?
53267						if ( perpEdge < 0 ) 				continue;
53268						inside = ! inside;		// true intersection left of inPt
53269
53270					}
53271
53272				} else {
53273
53274					// parallel or collinear
53275					if ( inPt.y !== edgeLowPt.y ) 		continue;			// parallel
53276					// edge lies on the same horizontal line as inPt
53277					if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
53278						 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )		return	true;	// inPt: Point on contour !
53279					// continue;
53280
53281				}
53282
53283			}
53284
53285			return	inside;
53286
53287		}
53288
53289		const isClockWise = ShapeUtils.isClockWise;
53290
53291		const subPaths = this.subPaths;
53292		if ( subPaths.length === 0 ) return [];
53293
53294		let solid, tmpPath, tmpShape;
53295		const shapes = [];
53296
53297		if ( subPaths.length === 1 ) {
53298
53299			tmpPath = subPaths[ 0 ];
53300			tmpShape = new Shape();
53301			tmpShape.curves = tmpPath.curves;
53302			shapes.push( tmpShape );
53303			return shapes;
53304
53305		}
53306
53307		let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
53308		holesFirst = isCCW ? ! holesFirst : holesFirst;
53309
53310		// console.log("Holes first", holesFirst);
53311
53312		const betterShapeHoles = [];
53313		const newShapes = [];
53314		let newShapeHoles = [];
53315		let mainIdx = 0;
53316		let tmpPoints;
53317
53318		newShapes[ mainIdx ] = undefined;
53319		newShapeHoles[ mainIdx ] = [];
53320
53321		for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
53322
53323			tmpPath = subPaths[ i ];
53324			tmpPoints = tmpPath.getPoints();
53325			solid = isClockWise( tmpPoints );
53326			solid = isCCW ? ! solid : solid;
53327
53328			if ( solid ) {
53329
53330				if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )	mainIdx ++;
53331
53332				newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
53333				newShapes[ mainIdx ].s.curves = tmpPath.curves;
53334
53335				if ( holesFirst )	mainIdx ++;
53336				newShapeHoles[ mainIdx ] = [];
53337
53338				//console.log('cw', i);
53339
53340			} else {
53341
53342				newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
53343
53344				//console.log('ccw', i);
53345
53346			}
53347
53348		}
53349
53350		// only Holes? -> probably all Shapes with wrong orientation
53351		if ( ! newShapes[ 0 ] )	return	toShapesNoHoles( subPaths );
53352
53353
53354		if ( newShapes.length > 1 ) {
53355
53356			let ambiguous = false;
53357			let toChange = 0;
53358
53359			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
53360
53361				betterShapeHoles[ sIdx ] = [];
53362
53363			}
53364
53365			for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
53366
53367				const sho = newShapeHoles[ sIdx ];
53368
53369				for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
53370
53371					const ho = sho[ hIdx ];
53372					let hole_unassigned = true;
53373
53374					for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
53375
53376						if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
53377
53378							if ( sIdx !== s2Idx )	toChange ++;
53379
53380							if ( hole_unassigned ) {
53381
53382								hole_unassigned = false;
53383								betterShapeHoles[ s2Idx ].push( ho );
53384
53385							} else {
53386
53387								ambiguous = true;
53388
53389							}
53390
53391						}
53392
53393					}
53394
53395					if ( hole_unassigned ) {
53396
53397						betterShapeHoles[ sIdx ].push( ho );
53398
53399					}
53400
53401				}
53402
53403			}
53404
53405			if ( toChange > 0 && ambiguous === false ) {
53406
53407				newShapeHoles = betterShapeHoles;
53408
53409			}
53410
53411		}
53412
53413		let tmpHoles;
53414
53415		for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
53416
53417			tmpShape = newShapes[ i ].s;
53418			shapes.push( tmpShape );
53419			tmpHoles = newShapeHoles[ i ];
53420
53421			for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
53422
53423				tmpShape.holes.push( tmpHoles[ j ].h );
53424
53425			}
53426
53427		}
53428
53429		//console.log("shape", shapes);
53430
53431		return shapes;
53432
53433	}
53434
53435}
53436
53437class WebGLMultipleRenderTargets extends WebGLRenderTarget { // @deprecated, r162
53438
53439	constructor( width = 1, height = 1, count = 1, options = {} ) {
53440
53441		console.warn( 'THREE.WebGLMultipleRenderTargets has been deprecated and will be removed in r172. Use THREE.WebGLRenderTarget and set the "count" parameter to enable MRT.' );
53442
53443		super( width, height, { ...options, count } );
53444
53445		this.isWebGLMultipleRenderTargets = true;
53446
53447	}
53448
53449	get texture() {
53450
53451		return this.textures;
53452
53453	}
53454
53455}
53456
53457if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
53458
53459	__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
53460		revision: REVISION,
53461	} } ) );
53462
53463}
53464
53465if ( typeof window !== 'undefined' ) {
53466
53467	if ( window.__THREE__ ) {
53468
53469		console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
53470
53471	} else {
53472
53473		window.__THREE__ = REVISION;
53474
53475	}
53476
53477}
53478
53479export { 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
53479phicCamera, 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.