PageSourceSearch

https://www.eisk.cn/static/2017/js/three.module.js

js eisk.cn collected 2026-10-02 10:09:05 UTC 1,294,940 bytes, 53,062 lines download raw bytes

1/**
2 * @license
3 * Copyright 2010-2023 Three.js Authors
4 * SPDX-License-Identifier: MIT
5 */
6const REVISION = '160';
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 TwoPassDoubleSide = 2; // r149
22const NoBlending = 0;
23const NormalBlending = 1;
24const AdditiveBlending = 2;
25const SubtractiveBlending = 3;
26const MultiplyBlending = 4;
27const CustomBlending = 5;
28const AddEquation = 100;
29const SubtractEquation = 101;
30const ReverseSubtractEquation = 102;
31const MinEquation = 103;
32const MaxEquation = 104;
33const ZeroFactor = 200;
34const OneFactor = 201;
35const SrcColorFactor = 202;
36const OneMinusSrcColorFactor = 203;
37const SrcAlphaFactor = 204;
38const OneMinusSrcAlphaFactor = 205;
39const DstAlphaFactor = 206;
40const OneMinusDstAlphaFactor = 207;
41const DstColorFactor = 208;
42const OneMinusDstColorFactor = 209;
43const SrcAlphaSaturateFactor = 210;
44const ConstantColorFactor = 211;
45const OneMinusConstantColorFactor = 212;
46const ConstantAlphaFactor = 213;
47const OneMinusConstantAlphaFactor = 214;
48const NeverDepth = 0;
49const AlwaysDepth = 1;
50const LessDepth = 2;
51const LessEqualDepth = 3;
52const EqualDepth = 4;
53const GreaterEqualDepth = 5;
54const GreaterDepth = 6;
55const NotEqualDepth = 7;
56const MultiplyOperation = 0;
57const MixOperation = 1;
58const AddOperation = 2;
59const NoToneMapping = 0;
60const LinearToneMapping = 1;
61const ReinhardToneMapping = 2;
62const CineonToneMapping = 3;
63const ACESFilmicToneMapping = 4;
64const CustomToneMapping = 5;
65const AgXToneMapping = 6;
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 AlphaFormat = 1021;
100const RGBAFormat = 1023;
101const LuminanceFormat = 1024;
102const LuminanceAlphaFormat = 1025;
103const DepthFormat = 1026;
104const DepthStencilFormat = 1027;
105const RedFormat = 1028;
106const RedIntegerFormat = 1029;
107const RGFormat = 1030;
108const RGIntegerFormat = 1031;
109const RGBAIntegerFormat = 1033;
110
111const RGB_S3TC_DXT1_Format = 33776;
112const RGBA_S3TC_DXT1_Format = 33777;
113const RGBA_S3TC_DXT3_Format = 33778;
114const RGBA_S3TC_DXT5_Format = 33779;
115const RGB_PVRTC_4BPPV1_Format = 35840;
116const RGB_PVRTC_2BPPV1_Format = 35841;
117const RGBA_PVRTC_4BPPV1_Format = 35842;
118const RGBA_PVRTC_2BPPV1_Format = 35843;
119const RGB_ETC1_Format = 36196;
120const RGB_ETC2_Format = 37492;
121const RGBA_ETC2_EAC_Format = 37496;
122const RGBA_ASTC_4x4_Format = 37808;
123const RGBA_ASTC_5x4_Format = 37809;
124const RGBA_ASTC_5x5_Format = 37810;
125const RGBA_ASTC_6x5_Format = 37811;
126const RGBA_ASTC_6x6_Format = 37812;
127const RGBA_ASTC_8x5_Format = 37813;
128const RGBA_ASTC_8x6_Format = 37814;
129const RGBA_ASTC_8x8_Format = 37815;
130const RGBA_ASTC_10x5_Format = 37816;
131const RGBA_ASTC_10x6_Format = 37817;
132const RGBA_ASTC_10x8_Format = 37818;
133const RGBA_ASTC_10x10_Format = 37819;
134const RGBA_ASTC_12x10_Format = 37820;
135const RGBA_ASTC_12x12_Format = 37821;
136const RGBA_BPTC_Format = 36492;
137const RGB_BPTC_SIGNED_Format = 36494;
138const RGB_BPTC_UNSIGNED_Format = 36495;
139const RED_RGTC1_Format = 36283;
140const SIGNED_RED_RGTC1_Format = 36284;
141const RED_GREEN_RGTC2_Format = 36285;
142const SIGNED_RED_GREEN_RGTC2_Format = 36286;
143const LoopOnce = 2200;
144const LoopRepeat = 2201;
145const LoopPingPong = 2202;
146const InterpolateDiscrete = 2300;
147const InterpolateLinear = 2301;
148const InterpolateSmooth = 2302;
149const ZeroCurvatureEnding = 2400;
150const ZeroSlopeEnding = 2401;
151const WrapAroundEnding = 2402;
152const NormalAnimationBlendMode = 2500;
153const AdditiveAnimationBlendMode = 2501;
154const TrianglesDrawMode = 0;
155const TriangleStripDrawMode = 1;
156const TriangleFanDrawMode = 2;
157/** @deprecated Use LinearSRGBColorSpace or NoColorSpace in three.js r152+. */
158const LinearEncoding = 3000;
159/** @deprecated Use SRGBColorSpace in three.js r152+. */
160const sRGBEncoding = 3001;
161const BasicDepthPacking = 3200;
162const RGBADepthPacking = 3201;
163const TangentSpaceNormalMap = 0;
164const ObjectSpaceNormalMap = 1;
165
166// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU n
vendor: 7,093 bytes, lines 166-410
166ames where available.
167const NoColorSpace = '';
168const SRGBColorSpace = 'srgb';
169const LinearSRGBColorSpace = 'srgb-linear';
170const DisplayP3ColorSpace = 'display-p3';
171const LinearDisplayP3ColorSpace = 'display-p3-linear';
172
173const LinearTransfer = 'linear';
174const SRGBTransfer = 'srgb';
175
176const Rec709Primaries = 'rec709';
177const P3Primaries = 'p3';
178
179const ZeroStencilOp = 0;
180const KeepStencilOp = 7680;
181const ReplaceStencilOp = 7681;
182const IncrementStencilOp = 7682;
183const DecrementStencilOp = 7683;
184const IncrementWrapStencilOp = 34055;
185const DecrementWrapStencilOp = 34056;
186const InvertStencilOp = 5386;
187
188const NeverStencilFunc = 512;
189const LessStencilFunc = 513;
190const EqualStencilFunc = 514;
191const LessEqualStencilFunc = 515;
192const GreaterStencilFunc = 516;
193const NotEqualStencilFunc = 517;
194const GreaterEqualStencilFunc = 518;
195const AlwaysStencilFunc = 519;
196
197const NeverCompare = 512;
198const LessCompare = 513;
199const EqualCompare = 514;
200const LessEqualCompare = 515;
201const GreaterCompare = 516;
202const NotEqualCompare = 517;
203const GreaterEqualCompare = 518;
204const AlwaysCompare = 519;
205
206const StaticDrawUsage = 35044;
207const DynamicDrawUsage = 35048;
208const StreamDrawUsage = 35040;
209const StaticReadUsage = 35045;
210const DynamicReadUsage = 35049;
211const StreamReadUsage = 35041;
212const StaticCopyUsage = 35046;
213const DynamicCopyUsage = 35050;
214const StreamCopyUsage = 35042;
215
216const GLSL1 = '100';
217const GLSL3 = '300 es';
218
219const _SRGBAFormat = 1035; // fallback for WebGL 1
220
221const WebGLCoordinateSystem = 2000;
222const WebGPUCoordinateSystem = 2001;
223
224/**
225 * https://github.com/mrdoob/eventdispatcher.js/
226 */
227
228class EventDispatcher {
229
230	addEventListener(type, listener) {
231
232		if (this._listeners === undefined) this._listeners = {};
233
234		const listeners = this._listeners;
235
236		if (listeners[type] === undefined) {
237
238			listeners[type] = [];
239
240		}
241
242		if (listeners[type].indexOf(listener) === - 1) {
243
244			listeners[type].push(listener);
245
246		}
247
248	}
249
250	hasEventListener(type, listener) {
251
252		if (this._listeners === undefined) return false;
253
254		const listeners = this._listeners;
255
256		return listeners[type] !== undefined && listeners[type].indexOf(listener) !== - 1;
257
258	}
259
260	removeEventListener(type, listener) {
261
262		if (this._listeners === undefined) return;
263
264		const listeners = this._listeners;
265		const listenerArray = listeners[type];
266
267		if (listenerArray !== undefined) {
268
269			const index = listenerArray.indexOf(listener);
270
271			if (index !== - 1) {
272
273				listenerArray.splice(index, 1);
274
275			}
276
277		}
278
279	}
280
281	dispatchEvent(event) {
282
283		if (this._listeners === undefined) return;
284
285		const listeners = this._listeners;
286		const listenerArray = listeners[event.type];
287
288		if (listenerArray !== undefined) {
289
290			event.target = this;
291
292			// Make a copy, in case listeners are removed while iterating.
293			const array = listenerArray.slice(0);
294
295			for (let i = 0, l = array.length; i < l; i++) {
296
297				array[i].call(this, event);
298
299			}
300
301			event.target = null;
302
303		}
304
305	}
306
307}
308
309const _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'];
310
311let _seed = 1234567;
312
313
314const DEG2RAD = Math.PI / 180;
315const RAD2DEG = 180 / Math.PI;
316
317// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
318function generateUUID() {
319
320	const d0 = Math.random() * 0xffffffff | 0;
321	const d1 = Math.random() * 0xffffffff | 0;
322	const d2 = Math.random() * 0xffffffff | 0;
323	const d3 = Math.random() * 0xffffffff | 0;
324	const uuid = _lut[d0 & 0xff] + _lut[d0 >> 8 & 0xff] + _lut[d0 >> 16 & 0xff] + _lut[d0 >> 24 & 0xff] + '-' +
325		_lut[d1 & 0xff] + _lut[d1 >> 8 & 0xff] + '-' + _lut[d1 >> 16 & 0x0f | 0x40] + _lut[d1 >> 24 & 0xff] + '-' +
326		_lut[d2 & 0x3f | 0x80] + _lut[d2 >> 8 & 0xff] + '-' + _lut[d2 >> 16 & 0xff] + _lut[d2 >> 24 & 0xff] +
327		_lut[d3 & 0xff] + _lut[d3 >> 8 & 0xff] + _lut[d3 >> 16 & 0xff] + _lut[d3 >> 24 & 0xff];
328
329	// .toLowerCase() here flattens concatenated strings to save heap memory space.
330	return uuid.toLowerCase();
331
332}
333
334function clamp(value, min, max) {
335
336	return Math.max(min, Math.min(max, value));
337
338}
339
340// compute euclidean modulo of m % n
341// https://en.wikipedia.org/wiki/Modulo_operation
342function euclideanModulo(n, m) {
343
344	return ((n % m) + m) % m;
345
346}
347
348// Linear mapping from range <a1, a2> to range <b1, b2>
349function mapLinear(x, a1, a2, b1, b2) {
350
351	return b1 + (x - a1) * (b2 - b1) / (a2 - a1);
352
353}
354
355// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
356function inverseLerp(x, y, value) {
357
358	if (x !== y) {
359
360		return (value - x) / (y - x);
361
362	} else {
363
364		return 0;
365
366	}
367
368}
369
370// https://en.wikipedia.org/wiki/Linear_interpolation
371function lerp(x, y, t) {
372
373	return (1 - t) * x + t * y;
374
375}
376
377// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
378function damp(x, y, lambda, dt) {
379
380	return lerp(x, y, 1 - Math.exp(- lambda * dt));
381
382}
383
384// https://www.desmos.com/calculator/vcsjnyz7x4
385function pingpong(x, length = 1) {
386
387	return length - Math.abs(euclideanModulo(x, length * 2) - length);
388
389}
390
391// http://en.wikipedia.org/wiki/Smoothstep
392function smoothstep(x, min, max) {
393
394	if (x <= min) return 0;
395	if (x >= max) return 1;
396
397	x = (x - min) / (max - min);
398
399	return x * x * (3 - 2 * x);
400
401}
402
403function smootherstep(x, min, max) {
404
405	if (x <= min) return 0;
406	if (x >= max) return 1;
407
408	x = (x - min) / (max - min);
409
410	return x * x * x * (x * (x * 6 - 15) + 10);
vendor: 6,188 bytes, lines 411-835
411
412}
413
414// Random integer from <low, high> interval
415function randInt(low, high) {
416
417	return low + Math.floor(Math.random() * (high - low + 1));
418
419}
420
421// Random float from <low, high> interval
422function randFloat(low, high) {
423
424	return low + Math.random() * (high - low);
425
426}
427
428// Random float from <-range/2, range/2> interval
429function randFloatSpread(range) {
430
431	return range * (0.5 - Math.random());
432
433}
434
435// Deterministic pseudo-random float in the interval [ 0, 1 ]
436function seededRandom(s) {
437
438	if (s !== undefined) _seed = s;
439
440	// Mulberry32 generator
441
442	let t = _seed += 0x6D2B79F5;
443
444	t = Math.imul(t ^ t >>> 15, t | 1);
445
446	t ^= t + Math.imul(t ^ t >>> 7, t | 61);
447
448	return ((t ^ t >>> 14) >>> 0) / 4294967296;
449
450}
451
452function degToRad(degrees) {
453
454	return degrees * DEG2RAD;
455
456}
457
458function radToDeg(radians) {
459
460	return radians * RAD2DEG;
461
462}
463
464function isPowerOfTwo(value) {
465
466	return (value & (value - 1)) === 0 && value !== 0;
467
468}
469
470function ceilPowerOfTwo(value) {
471
472	return Math.pow(2, Math.ceil(Math.log(value) / Math.LN2));
473
474}
475
476function floorPowerOfTwo(value) {
477
478	return Math.pow(2, Math.floor(Math.log(value) / Math.LN2));
479
480}
481
482function setQuaternionFromProperEuler(q, a, b, c, order) {
483
484	// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
485
486	// rotations are applied to the axes in the order specified by 'order'
487	// rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
488	// angles are in radians
489
490	const cos = Math.cos;
491	const sin = Math.sin;
492
493	const c2 = cos(b / 2);
494	const s2 = sin(b / 2);
495
496	const c13 = cos((a + c) / 2);
497	const s13 = sin((a + c) / 2);
498
499	const c1_3 = cos((a - c) / 2);
500	const s1_3 = sin((a - c) / 2);
501
502	const c3_1 = cos((c - a) / 2);
503	const s3_1 = sin((c - a) / 2);
504
505	switch (order) {
506
507		case 'XYX':
508			q.set(c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13);
509			break;
510
511		case 'YZY':
512			q.set(s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13);
513			break;
514
515		case 'ZXZ':
516			q.set(s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13);
517			break;
518
519		case 'XZX':
520			q.set(c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13);
521			break;
522
523		case 'YXY':
524			q.set(s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13);
525			break;
526
527		case 'ZYZ':
528			q.set(s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13);
529			break;
530
531		default:
532			console.warn('THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order);
533
534	}
535
536}
537
538function denormalize(value, array) {
539
540	switch (array.constructor) {
541
542		case Float32Array:
543
544			return value;
545
546		case Uint32Array:
547
548			return value / 4294967295.0;
549
550		case Uint16Array:
551
552			return value / 65535.0;
553
554		case Uint8Array:
555
556			return value / 255.0;
557
558		case Int32Array:
559
560			return Math.max(value / 2147483647.0, - 1.0);
561
562		case Int16Array:
563
564			return Math.max(value / 32767.0, - 1.0);
565
566		case Int8Array:
567
568			return Math.max(value / 127.0, - 1.0);
569
570		default:
571
572			throw new Error('Invalid component type.');
573
574	}
575
576}
577
578function normalize(value, array) {
579
580	switch (array.constructor) {
581
582		case Float32Array:
583
584			return value;
585
586		case Uint32Array:
587
588			return Math.round(value * 4294967295.0);
589
590		case Uint16Array:
591
592			return Math.round(value * 65535.0);
593
594		case Uint8Array:
595
596			return Math.round(value * 255.0);
597
598		case Int32Array:
599
600			return Math.round(value * 2147483647.0);
601
602		case Int16Array:
603
604			return Math.round(value * 32767.0);
605
606		case Int8Array:
607
608			return Math.round(value * 127.0);
609
610		default:
611
612			throw new Error('Invalid component type.');
613
614	}
615
616}
617
618const MathUtils = {
619	DEG2RAD: DEG2RAD,
620	RAD2DEG: RAD2DEG,
621	generateUUID: generateUUID,
622	clamp: clamp,
623	euclideanModulo: euclideanModulo,
624	mapLinear: mapLinear,
625	inverseLerp: inverseLerp,
626	lerp: lerp,
627	damp: damp,
628	pingpong: pingpong,
629	smoothstep: smoothstep,
630	smootherstep: smootherstep,
631	randInt: randInt,
632	randFloat: randFloat,
633	randFloatSpread: randFloatSpread,
634	seededRandom: seededRandom,
635	degToRad: degToRad,
636	radToDeg: radToDeg,
637	isPowerOfTwo: isPowerOfTwo,
638	ceilPowerOfTwo: ceilPowerOfTwo,
639	floorPowerOfTwo: floorPowerOfTwo,
640	setQuaternionFromProperEuler: setQuaternionFromProperEuler,
641	normalize: normalize,
642	denormalize: denormalize
643};
644
645class Vector2 {
646
647	constructor(x = 0, y = 0) {
648
649		Vector2.prototype.isVector2 = true;
650
651		this.x = x;
652		this.y = y;
653
654	}
655
656	get width() {
657
658		return this.x;
659
660	}
661
662	set width(value) {
663
664		this.x = value;
665
666	}
667
668	get height() {
669
670		return this.y;
671
672	}
673
674	set height(value) {
675
676		this.y = value;
677
678	}
679
680	set(x, y) {
681
682		this.x = x;
683		this.y = y;
684
685		return this;
686
687	}
688
689	setScalar(scalar) {
690
691		this.x = scalar;
692		this.y = scalar;
693
694		return this;
695
696	}
697
698	setX(x) {
699
700		this.x = x;
701
702		return this;
703
704	}
705
706	setY(y) {
707
708		this.y = y;
709
710		return this;
711
712	}
713
714	setComponent(index, value) {
715
716		switch (index) {
717
718			case 0: this.x = value; break;
719			case 1: this.y = value; break;
720			default: throw new Error('index is out of range: ' + index);
721
722		}
723
724		return this;
725
726	}
727
728	getComponent(index) {
729
730		switch (index) {
731
732			case 0: return this.x;
733			case 1: return this.y;
734			default: throw new Error('index is out of range: ' + index);
735
736		}
737
738	}
739
740	clone() {
741
742		return new this.constructor(this.x, this.y);
743
744	}
745
746	copy(v) {
747
748		this.x = v.x;
749		this.y = v.y;
750
751		return this;
752
753	}
754
755	add(v) {
756
757		this.x += v.x;
758		this.y += v.y;
759
760		return this;
761
762	}
763
764	addScalar(s) {
765
766		this.x += s;
767		this.y += s;
768
769		return this;
770
771	}
772
773	addVectors(a, b) {
774
775		this.x = a.x + b.x;
776		this.y = a.y + b.y;
777
778		return this;
779
780	}
781
782	addScaledVector(v, s) {
783
784		this.x += v.x * s;
785		this.y += v.y * s;
786
787		return this;
788
789	}
790
791	sub(v) {
792
793		this.x -= v.x;
794		this.y -= v.y;
795
796		return this;
797
798	}
799
800	subScalar(s) {
801
802		this.x -= s;
803		this.y -= s;
804
805		return this;
806
807	}
808
809	subVectors(a, b) {
810
811		this.x = a.x - b.x;
812		this.y = a.y - b.y;
813
814		return this;
815
816	}
817
818	multiply(v) {
819
820		this.x *= v.x;
821		this.y *= v.y;
822
823		return this;
824
825	}
826
827	multiplyScalar(scalar) {
828
829		this.x *= scalar;
830		this.y *= scalar;
831
832		return this;
833
834	}
835
vendor: 63,929 bytes, lines 836-4475
836	divide(v) {
837
838		this.x /= v.x;
839		this.y /= v.y;
840
841		return this;
842
843	}
844
845	divideScalar(scalar) {
846
847		return this.multiplyScalar(1 / scalar);
848
849	}
850
851	applyMatrix3(m) {
852
853		const x = this.x, y = this.y;
854		const e = m.elements;
855
856		this.x = e[0] * x + e[3] * y + e[6];
857		this.y = e[1] * x + e[4] * y + e[7];
858
859		return this;
860
861	}
862
863	min(v) {
864
865		this.x = Math.min(this.x, v.x);
866		this.y = Math.min(this.y, v.y);
867
868		return this;
869
870	}
871
872	max(v) {
873
874		this.x = Math.max(this.x, v.x);
875		this.y = Math.max(this.y, v.y);
876
877		return this;
878
879	}
880
881	clamp(min, max) {
882
883		// assumes min < max, componentwise
884
885		this.x = Math.max(min.x, Math.min(max.x, this.x));
886		this.y = Math.max(min.y, Math.min(max.y, this.y));
887
888		return this;
889
890	}
891
892	clampScalar(minVal, maxVal) {
893
894		this.x = Math.max(minVal, Math.min(maxVal, this.x));
895		this.y = Math.max(minVal, Math.min(maxVal, this.y));
896
897		return this;
898
899	}
900
901	clampLength(min, max) {
902
903		const length = this.length();
904
905		return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
906
907	}
908
909	floor() {
910
911		this.x = Math.floor(this.x);
912		this.y = Math.floor(this.y);
913
914		return this;
915
916	}
917
918	ceil() {
919
920		this.x = Math.ceil(this.x);
921		this.y = Math.ceil(this.y);
922
923		return this;
924
925	}
926
927	round() {
928
929		this.x = Math.round(this.x);
930		this.y = Math.round(this.y);
931
932		return this;
933
934	}
935
936	roundToZero() {
937
938		this.x = Math.trunc(this.x);
939		this.y = Math.trunc(this.y);
940
941		return this;
942
943	}
944
945	negate() {
946
947		this.x = - this.x;
948		this.y = - this.y;
949
950		return this;
951
952	}
953
954	dot(v) {
955
956		return this.x * v.x + this.y * v.y;
957
958	}
959
960	cross(v) {
961
962		return this.x * v.y - this.y * v.x;
963
964	}
965
966	lengthSq() {
967
968		return this.x * this.x + this.y * this.y;
969
970	}
971
972	length() {
973
974		return Math.sqrt(this.x * this.x + this.y * this.y);
975
976	}
977
978	manhattanLength() {
979
980		return Math.abs(this.x) + Math.abs(this.y);
981
982	}
983
984	normalize() {
985
986		return this.divideScalar(this.length() || 1);
987
988	}
989
990	angle() {
991
992		// computes the angle in radians with respect to the positive x-axis
993
994		const angle = Math.atan2(- this.y, - this.x) + Math.PI;
995
996		return angle;
997
998	}
999
1000	angleTo(v) {
1001
1002		const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());
1003
1004		if (denominator === 0) return Math.PI / 2;
1005
1006		const theta = this.dot(v) / denominator;
1007
1008		// clamp, to handle numerical problems
1009
1010		return Math.acos(clamp(theta, - 1, 1));
1011
1012	}
1013
1014	distanceTo(v) {
1015
1016		return Math.sqrt(this.distanceToSquared(v));
1017
1018	}
1019
1020	distanceToSquared(v) {
1021
1022		const dx = this.x - v.x, dy = this.y - v.y;
1023		return dx * dx + dy * dy;
1024
1025	}
1026
1027	manhattanDistanceTo(v) {
1028
1029		return Math.abs(this.x - v.x) + Math.abs(this.y - v.y);
1030
1031	}
1032
1033	setLength(length) {
1034
1035		return this.normalize().multiplyScalar(length);
1036
1037	}
1038
1039	lerp(v, alpha) {
1040
1041		this.x += (v.x - this.x) * alpha;
1042		this.y += (v.y - this.y) * alpha;
1043
1044		return this;
1045
1046	}
1047
1048	lerpVectors(v1, v2, alpha) {
1049
1050		this.x = v1.x + (v2.x - v1.x) * alpha;
1051		this.y = v1.y + (v2.y - v1.y) * alpha;
1052
1053		return this;
1054
1055	}
1056
1057	equals(v) {
1058
1059		return ((v.x === this.x) && (v.y === this.y));
1060
1061	}
1062
1063	fromArray(array, offset = 0) {
1064
1065		this.x = array[offset];
1066		this.y = array[offset + 1];
1067
1068		return this;
1069
1070	}
1071
1072	toArray(array = [], offset = 0) {
1073
1074		array[offset] = this.x;
1075		array[offset + 1] = this.y;
1076
1077		return array;
1078
1079	}
1080
1081	fromBufferAttribute(attribute, index) {
1082
1083		this.x = attribute.getX(index);
1084		this.y = attribute.getY(index);
1085
1086		return this;
1087
1088	}
1089
1090	rotateAround(center, angle) {
1091
1092		const c = Math.cos(angle), s = Math.sin(angle);
1093
1094		const x = this.x - center.x;
1095		const y = this.y - center.y;
1096
1097		this.x = x * c - y * s + center.x;
1098		this.y = x * s + y * c + center.y;
1099
1100		return this;
1101
1102	}
1103
1104	random() {
1105
1106		this.x = Math.random();
1107		this.y = Math.random();
1108
1109		return this;
1110
1111	}
1112
1113	*[Symbol.iterator]() {
1114
1115		yield this.x;
1116		yield this.y;
1117
1118	}
1119
1120}
1121
1122class Matrix3 {
1123
1124	constructor(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
1125
1126		Matrix3.prototype.isMatrix3 = true;
1127
1128		this.elements = [
1129
1130			1, 0, 0,
1131			0, 1, 0,
1132			0, 0, 1
1133
1134		];
1135
1136		if (n11 !== undefined) {
1137
1138			this.set(n11, n12, n13, n21, n22, n23, n31, n32, n33);
1139
1140		}
1141
1142	}
1143
1144	set(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
1145
1146		const te = this.elements;
1147
1148		te[0] = n11; te[1] = n21; te[2] = n31;
1149		te[3] = n12; te[4] = n22; te[5] = n32;
1150		te[6] = n13; te[7] = n23; te[8] = n33;
1151
1152		return this;
1153
1154	}
1155
1156	identity() {
1157
1158		this.set(
1159
1160			1, 0, 0,
1161			0, 1, 0,
1162			0, 0, 1
1163
1164		);
1165
1166		return this;
1167
1168	}
1169
1170	copy(m) {
1171
1172		const te = this.elements;
1173		const me = m.elements;
1174
1175		te[0] = me[0]; te[1] = me[1]; te[2] = me[2];
1176		te[3] = me[3]; te[4] = me[4]; te[5] = me[5];
1177		te[6] = me[6]; te[7] = me[7]; te[8] = me[8];
1178
1179		return this;
1180
1181	}
1182
1183	extractBasis(xAxis, yAxis, zAxis) {
1184
1185		xAxis.setFromMatrix3Column(this, 0);
1186		yAxis.setFromMatrix3Column(this, 1);
1187		zAxis.setFromMatrix3Column(this, 2);
1188
1189		return this;
1190
1191	}
1192
1193	setFromMatrix4(m) {
1194
1195		const me = m.elements;
1196
1197		this.set(
1198
1199			me[0], me[4], me[8],
1200			me[1], me[5], me[9],
1201			me[2], me[6], me[10]
1202
1203		);
1204
1205		return this;
1206
1207	}
1208
1209	multiply(m) {
1210
1211		return this.multiplyMatrices(this, m);
1212
1213	}
1214
1215	premultiply(m) {
1216
1217		return this.multiplyMatrices(m, this);
1218
1219	}
1220
1221	multiplyMatrices(a, b) {
1222
1223		const ae = a.elements;
1224		const be = b.elements;
1225		const te = this.elements;
1226
1227		const a11 = ae[0], a12 = ae[3], a13 = ae[6];
1228		const a21 = ae[1], a22 = ae[4], a23 = ae[7];
1229		const a31 = ae[2], a32 = ae[5], a33 = ae[8];
1230
1231		const b11 = be[0], b12 = be[3], b13 = be[6];
1232		const b21 = be[1], b22 = be[4], b23 = be[7];
1233		const b31 = be[2], b32 = be[5], b33 = be[8];
1234
1235		te[0] = a11 * b11 + a12 * b21 + a13 * b31;
1236		te[3] = a11 * b12 + a12 * b22 + a13 * b32;
1237		te[6] = a11 * b13 + a12 * b23 + a13 * b33;
1238
1239		te[1] = a21 * b11 + a22 * b21 + a23 * b31;
1240		te[4] = a21 * b12 + a22 * b22 + a23 * b32;
1241		te[7] = a21 * b13 + a22 * b23 + a23 * b33;
1242
1243		te[2] = a31 * b11 + a32 * b21 + a33 * b31;
1244		te[5] = a31 * b12 + a32 * b22 + a33 * b32;
1245		te[8] = a31 * b13 + a32 * b23 + a33 * b33;
1246
1247		return this;
1248
1249	}
1250
1251	multiplyScalar(s) {
1252
1253		const te = this.elements;
1254
1255		te[0] *= s; te[3] *= s; te[6] *= s;
1256		te[1] *= s; te[4] *= s; te[7] *= s;
1257		te[2] *= s; te[5] *= s; te[8] *= s;
1258
1259		return this;
1260
1261	}
1262
1263	determinant() {
1264
1265		const te = this.elements;
1266
1267		const a = te[0], b = te[1], c = te[2],
1268			d = te[3], e = te[4], f = te[5],
1269			g = te[6], h = te[7], i = te[8];
1270
1271		return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
1272
1273	}
1274
1275	invert() {
1276
1277		const te = this.elements,
1278
1279			n11 = te[0], n21 = te[1], n31 = te[2],
1280			n12 = te[3], n22 = te[4], n32 = te[5],
1281			n13 = te[6], n23 = te[7], n33 = te[8],
1282
1283			t11 = n33 * n22 - n32 * n23,
1284			t12 = n32 * n13 - n33 * n12,
1285			t13 = n23 * n12 - n22 * n13,
1286
1287			det = n11 * t11 + n21 * t12 + n31 * t13;
1288
1289		if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0);
1290
1291		const detInv = 1 / det;
1292
1293		te[0] = t11 * detInv;
1294		te[1] = (n31 * n23 - n33 * n21) * detInv;
1295		te[2] = (n32 * n21 - n31 * n22) * detInv;
1296
1297		te[3] = t12 * detInv;
1298		te[4] = (n33 * n11 - n31 * n13) * detInv;
1299		te[5] = (n31 * n12 - n32 * n11) * detInv;
1300
1301		te[6] = t13 * detInv;
1302		te[7] = (n21 * n13 - n23 * n11) * detInv;
1303		te[8] = (n22 * n11 - n21 * n12) * detInv;
1304
1305		return this;
1306
1307	}
1308
1309	transpose() {
1310
1311		let tmp;
1312		const m = this.elements;
1313
1314		tmp = m[1]; m[1] = m[3]; m[3] = tmp;
1315		tmp = m[2]; m[2] = m[6]; m[6] = tmp;
1316		tmp = m[5]; m[5] = m[7]; m[7] = tmp;
1317
1318		return this;
1319
1320	}
1321
1322	getNormalMatrix(matrix4) {
1323
1324		return this.setFromMatrix4(matrix4).invert().transpose();
1325
1326	}
1327
1328	transposeIntoArray(r) {
1329
1330		const m = this.elements;
1331
1332		r[0] = m[0];
1333		r[1] = m[3];
1334		r[2] = m[6];
1335		r[3] = m[1];
1336		r[4] = m[4];
1337		r[5] = m[7];
1338		r[6] = m[2];
1339		r[7] = m[5];
1340		r[8] = m[8];
1341
1342		return this;
1343
1344	}
1345
1346	setUvTransform(tx, ty, sx, sy, rotation, cx, cy) {
1347
1348		const c = Math.cos(rotation);
1349		const s = Math.sin(rotation);
1350
1351		this.set(
1352			sx * c, sx * s, - sx * (c * cx + s * cy) + cx + tx,
1353			- sy * s, sy * c, - sy * (- s * cx + c * cy) + cy + ty,
1354			0, 0, 1
1355		);
1356
1357		return this;
1358
1359	}
1360
1361	//
1362
1363	scale(sx, sy) {
1364
1365		this.premultiply(_m3.makeScale(sx, sy));
1366
1367		return this;
1368
1369	}
1370
1371	rotate(theta) {
1372
1373		this.premultiply(_m3.makeRotation(- theta));
1374
1375		return this;
1376
1377	}
1378
1379	translate(tx, ty) {
1380
1381		this.premultiply(_m3.makeTranslation(tx, ty));
1382
1383		return this;
1384
1385	}
1386
1387	// for 2D Transforms
1388
1389	makeTranslation(x, y) {
1390
1391		if (x.isVector2) {
1392
1393			this.set(
1394
1395				1, 0, x.x,
1396				0, 1, x.y,
1397				0, 0, 1
1398
1399			);
1400
1401		} else {
1402
1403			this.set(
1404
1405				1, 0, x,
1406				0, 1, y,
1407				0, 0, 1
1408
1409			);
1410
1411		}
1412
1413		return this;
1414
1415	}
1416
1417	makeRotation(theta) {
1418
1419		// counterclockwise
1420
1421		const c = Math.cos(theta);
1422		const s = Math.sin(theta);
1423
1424		this.set(
1425
1426			c, - s, 0,
1427			s, c, 0,
1428			0, 0, 1
1429
1430		);
1431
1432		return this;
1433
1434	}
1435
1436	makeScale(x, y) {
1437
1438		this.set(
1439
1440			x, 0, 0,
1441			0, y, 0,
1442			0, 0, 1
1443
1444		);
1445
1446		return this;
1447
1448	}
1449
1450	//
1451
1452	equals(matrix) {
1453
1454		const te = this.elements;
1455		const me = matrix.elements;
1456
1457		for (let i = 0; i < 9; i++) {
1458
1459			if (te[i] !== me[i]) return false;
1460
1461		}
1462
1463		return true;
1464
1465	}
1466
1467	fromArray(array, offset = 0) {
1468
1469		for (let i = 0; i < 9; i++) {
1470
1471			this.elements[i] = array[i + offset];
1472
1473		}
1474
1475		return this;
1476
1477	}
1478
1479	toArray(array = [], offset = 0) {
1480
1481		const te = this.elements;
1482
1483		array[offset] = te[0];
1484		array[offset + 1] = te[1];
1485		array[offset + 2] = te[2];
1486
1487		array[offset + 3] = te[3];
1488		array[offset + 4] = te[4];
1489		array[offset + 5] = te[5];
1490
1491		array[offset + 6] = te[6];
1492		array[offset + 7] = te[7];
1493		array[offset + 8] = te[8];
1494
1495		return array;
1496
1497	}
1498
1499	clone() {
1500
1501		return new this.constructor().fromArray(this.elements);
1502
1503	}
1504
1505}
1506
1507const _m3 = /*@__PURE__*/ new Matrix3();
1508
1509function arrayNeedsUint32(array) {
1510
1511	// assumes larger values usually on last
1512
1513	for (let i = array.length - 1; i >= 0; --i) {
1514
1515		if (array[i] >= 65535) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
1516
1517	}
1518
1519	return false;
1520
1521}
1522
1523const TYPED_ARRAYS = {
1524	Int8Array: Int8Array,
1525	Uint8Array: Uint8Array,
1526	Uint8ClampedArray: Uint8ClampedArray,
1527	Int16Array: Int16Array,
1528	Uint16Array: Uint16Array,
1529	Int32Array: Int32Array,
1530	Uint32Array: Uint32Array,
1531	Float32Array: Float32Array,
1532	Float64Array: Float64Array
1533};
1534
1535function getTypedArray(type, buffer) {
1536
1537	return new TYPED_ARRAYS[type](buffer);
1538
1539}
1540
1541function createElementNS(name) {
1542
1543	return document.createElementNS('http://www.w3.org/1999/xhtml', name);
1544
1545}
1546
1547function createCanvasElement() {
1548
1549	const canvas = createElementNS('canvas');
1550	canvas.style.display = 'block';
1551	return canvas;
1552
1553}
1554
1555const _cache = {};
1556
1557function warnOnce(message) {
1558
1559	if (message in _cache) return;
1560
1561	_cache[message] = true;
1562
1563	console.warn(message);
1564
1565}
1566
1567/**
1568 * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping
1569 * or clipping. Based on W3C specifications for sRGB and Display P3,
1570 * and ICC specifications for the D50 connection space. Values in/out
1571 * are _linear_ sRGB and _linear_ Display P3.
1572 *
1573 * Note that both sRGB and Display P3 use the sRGB transfer functions.
1574 *
1575 * Reference:
1576 * - http://www.russellcottrell.com/photo/matrixCalculator.htm
1577 */
1578
1579const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set(
1580	0.8224621, 0.177538, 0.0,
1581	0.0331941, 0.9668058, 0.0,
1582	0.0170827, 0.0723974, 0.9105199,
1583);
1584
1585const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set(
1586	1.2249401, - 0.2249404, 0.0,
1587	- 0.0420569, 1.0420571, 0.0,
1588	- 0.0196376, - 0.0786361, 1.0982735
1589);
1590
1591/**
1592 * Defines supported color spaces by transfer function and primaries,
1593 * and provides conversions to/from the Linear-sRGB reference space.
1594 */
1595const COLOR_SPACES = {
1596	[LinearSRGBColorSpace]: {
1597		transfer: LinearTransfer,
1598		primaries: Rec709Primaries,
1599		toReference: (color) => color,
1600		fromReference: (color) => color,
1601	},
1602	[SRGBColorSpace]: {
1603		transfer: SRGBTransfer,
1604		primaries: Rec709Primaries,
1605		toReference: (color) => color.convertSRGBToLinear(),
1606		fromReference: (color) => color.convertLinearToSRGB(),
1607	},
1608	[LinearDisplayP3ColorSpace]: {
1609		transfer: LinearTransfer,
1610		primaries: P3Primaries,
1611		toReference: (color) => color.applyMatrix3(LINEAR_DISPLAY_P3_TO_LINEAR_SRGB),
1612		fromReference: (color) => color.applyMatrix3(LINEAR_SRGB_TO_LINEAR_DISPLAY_P3),
1613	},
1614	[DisplayP3ColorSpace]: {
1615		transfer: SRGBTransfer,
1616		primaries: P3Primaries,
1617		toReference: (color) => color.convertSRGBToLinear().applyMatrix3(LINEAR_DISPLAY_P3_TO_LINEAR_SRGB),
1618		fromReference: (color) => color.applyMatrix3(LINEAR_SRGB_TO_LINEAR_DISPLAY_P3).convertLinearToSRGB(),
1619	},
1620};
1621
1622const SUPPORTED_WORKING_COLOR_SPACES = new Set([LinearSRGBColorSpace, LinearDisplayP3ColorSpace]);
1623
1624const ColorManagement = {
1625
1626	enabled: true,
1627
1628	_workingColorSpace: LinearSRGBColorSpace,
1629
1630	get workingColorSpace() {
1631
1632		return this._workingColorSpace;
1633
1634	},
1635
1636	set workingColorSpace(colorSpace) {
1637
1638		if (!SUPPORTED_WORKING_COLOR_SPACES.has(colorSpace)) {
1639
1640			throw new Error(`Unsupported working color space, "${colorSpace}".`);
1641
1642		}
1643
1644		this._workingColorSpace = colorSpace;
1645
1646	},
1647
1648	convert: function (color, sourceColorSpace, targetColorSpace) {
1649
1650		if (this.enabled === false || sourceColorSpace === targetColorSpace || !sourceColorSpace || !targetColorSpace) {
1651
1652			return color;
1653
1654		}
1655
1656		const sourceToReference = COLOR_SPACES[sourceColorSpace].toReference;
1657		const targetFromReference = COLOR_SPACES[targetColorSpace].fromReference;
1658
1659		return targetFromReference(sourceToReference(color));
1660
1661	},
1662
1663	fromWorkingColorSpace: function (color, targetColorSpace) {
1664
1665		return this.convert(color, this._workingColorSpace, targetColorSpace);
1666
1667	},
1668
1669	toWorkingColorSpace: function (color, sourceColorSpace) {
1670
1671		return this.convert(color, sourceColorSpace, this._workingColorSpace);
1672
1673	},
1674
1675	getPrimaries: function (colorSpace) {
1676
1677		return COLOR_SPACES[colorSpace].primaries;
1678
1679	},
1680
1681	getTransfer: function (colorSpace) {
1682
1683		if (colorSpace === NoColorSpace) return LinearTransfer;
1684
1685		return COLOR_SPACES[colorSpace].transfer;
1686
1687	},
1688
1689};
1690
1691
1692function SRGBToLinear(c) {
1693
1694	return (c < 0.04045) ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);
1695
1696}
1697
1698function LinearToSRGB(c) {
1699
1700	return (c < 0.0031308) ? c * 12.92 : 1.055 * (Math.pow(c, 0.41666)) - 0.055;
1701
1702}
1703
1704let _canvas;
1705
1706class ImageUtils {
1707
1708	static getDataURL(image) {
1709
1710		if (/^data:/i.test(image.src)) {
1711
1712			return image.src;
1713
1714		}
1715
1716		if (typeof HTMLCanvasElement === 'undefined') {
1717
1718			return image.src;
1719
1720		}
1721
1722		let canvas;
1723
1724		if (image instanceof HTMLCanvasElement) {
1725
1726			canvas = image;
1727
1728		} else {
1729
1730			if (_canvas === undefined) _canvas = createElementNS('canvas');
1731
1732			_canvas.width = image.width;
1733			_canvas.height = image.height;
1734
1735			const context = _canvas.getContext('2d');
1736
1737			if (image instanceof ImageData) {
1738
1739				context.putImageData(image, 0, 0);
1740
1741			} else {
1742
1743				context.drawImage(image, 0, 0, image.width, image.height);
1744
1745			}
1746
1747			canvas = _canvas;
1748
1749		}
1750
1751		if (canvas.width > 2048 || canvas.height > 2048) {
1752
1753			console.warn('THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image);
1754
1755			return canvas.toDataURL('image/jpeg', 0.6);
1756
1757		} else {
1758
1759			return canvas.toDataURL('image/png');
1760
1761		}
1762
1763	}
1764
1765	static sRGBToLinear(image) {
1766
1767		if ((typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement) ||
1768			(typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
1769			(typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap)) {
1770
1771			const canvas = createElementNS('canvas');
1772
1773			canvas.width = image.width;
1774			canvas.height = image.height;
1775
1776			const context = canvas.getContext('2d');
1777			context.drawImage(image, 0, 0, image.width, image.height);
1778
1779			const imageData = context.getImageData(0, 0, image.width, image.height);
1780			const data = imageData.data;
1781
1782			for (let i = 0; i < data.length; i++) {
1783
1784				data[i] = SRGBToLinear(data[i] / 255) * 255;
1785
1786			}
1787
1788			context.putImageData(imageData, 0, 0);
1789
1790			return canvas;
1791
1792		} else if (image.data) {
1793
1794			const data = image.data.slice(0);
1795
1796			for (let i = 0; i < data.length; i++) {
1797
1798				if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) {
1799
1800					data[i] = Math.floor(SRGBToLinear(data[i] / 255) * 255);
1801
1802				} else {
1803
1804					// assuming float
1805
1806					data[i] = SRGBToLinear(data[i]);
1807
1808				}
1809
1810			}
1811
1812			return {
1813				data: data,
1814				width: image.width,
1815				height: image.height
1816			};
1817
1818		} else {
1819
1820			console.warn('THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.');
1821			return image;
1822
1823		}
1824
1825	}
1826
1827}
1828
1829let _sourceId = 0;
1830
1831class Source {
1832
1833	constructor(data = null) {
1834
1835		this.isSource = true;
1836
1837		Object.defineProperty(this, 'id', { value: _sourceId++ });
1838
1839		this.uuid = generateUUID();
1840
1841		this.data = data;
1842
1843		this.version = 0;
1844
1845	}
1846
1847	set needsUpdate(value) {
1848
1849		if (value === true) this.version++;
1850
1851	}
1852
1853	toJSON(meta) {
1854
1855		const isRootObject = (meta === undefined || typeof meta === 'string');
1856
1857		if (!isRootObject && meta.images[this.uuid] !== undefined) {
1858
1859			return meta.images[this.uuid];
1860
1861		}
1862
1863		const output = {
1864			uuid: this.uuid,
1865			url: ''
1866		};
1867
1868		const data = this.data;
1869
1870		if (data !== null) {
1871
1872			let url;
1873
1874			if (Array.isArray(data)) {
1875
1876				// cube texture
1877
1878				url = [];
1879
1880				for (let i = 0, l = data.length; i < l; i++) {
1881
1882					if (data[i].isDataTexture) {
1883
1884						url.push(serializeImage(data[i].image));
1885
1886					} else {
1887
1888						url.push(serializeImage(data[i]));
1889
1890					}
1891
1892				}
1893
1894			} else {
1895
1896				// texture
1897
1898				url = serializeImage(data);
1899
1900			}
1901
1902			output.url = url;
1903
1904		}
1905
1906		if (!isRootObject) {
1907
1908			meta.images[this.uuid] = output;
1909
1910		}
1911
1912		return output;
1913
1914	}
1915
1916}
1917
1918function serializeImage(image) {
1919
1920	if ((typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement) ||
1921		(typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
1922		(typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap)) {
1923
1924		// default images
1925
1926		return ImageUtils.getDataURL(image);
1927
1928	} else {
1929
1930		if (image.data) {
1931
1932			// images of DataTexture
1933
1934			return {
1935				data: Array.from(image.data),
1936				width: image.width,
1937				height: image.height,
1938				type: image.data.constructor.name
1939			};
1940
1941		} else {
1942
1943			console.warn('THREE.Texture: Unable to serialize Texture.');
1944			return {};
1945
1946		}
1947
1948	}
1949
1950}
1951
1952let _textureId = 0;
1953
1954class Texture extends EventDispatcher {
1955
1956	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) {
1957
1958		super();
1959
1960		this.isTexture = true;
1961
1962		Object.defineProperty(this, 'id', { value: _textureId++ });
1963
1964		this.uuid = generateUUID();
1965
1966		this.name = '';
1967
1968		this.source = new Source(image);
1969		this.mipmaps = [];
1970
1971		this.mapping = mapping;
1972		this.channel = 0;
1973
1974		this.wrapS = wrapS;
1975		this.wrapT = wrapT;
1976
1977		this.magFilter = magFilter;
1978		this.minFilter = minFilter;
1979
1980		this.anisotropy = anisotropy;
1981
1982		this.format = format;
1983		this.internalFormat = null;
1984		this.type = type;
1985
1986		this.offset = new Vector2(0, 0);
1987		this.repeat = new Vector2(1, 1);
1988		this.center = new Vector2(0, 0);
1989		this.rotation = 0;
1990
1991		this.matrixAutoUpdate = true;
1992		this.matrix = new Matrix3();
1993
1994		this.generateMipmaps = true;
1995		this.premultiplyAlpha = false;
1996		this.flipY = true;
1997		this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
1998
1999		if (typeof colorSpace === 'string') {
2000
2001			this.colorSpace = colorSpace;
2002
2003		} else { // @deprecated, r152
2004
2005			warnOnce('THREE.Texture: Property .encoding has been replaced by .colorSpace.');
2006			this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
2007
2008		}
2009
2010
2011		this.userData = {};
2012
2013		this.version = 0;
2014		this.onUpdate = null;
2015
2016		this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not
2017		this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures)
2018
2019	}
2020
2021	get image() {
2022
2023		return this.source.data;
2024
2025	}
2026
2027	set image(value = null) {
2028
2029		this.source.data = value;
2030
2031	}
2032
2033	updateMatrix() {
2034
2035		this.matrix.setUvTransform(this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y);
2036
2037	}
2038
2039	clone() {
2040
2041		return new this.constructor().copy(this);
2042
2043	}
2044
2045	copy(source) {
2046
2047		this.name = source.name;
2048
2049		this.source = source.source;
2050		this.mipmaps = source.mipmaps.slice(0);
2051
2052		this.mapping = source.mapping;
2053		this.channel = source.channel;
2054
2055		this.wrapS = source.wrapS;
2056		this.wrapT = source.wrapT;
2057
2058		this.magFilter = source.magFilter;
2059		this.minFilter = source.minFilter;
2060
2061		this.anisotropy = source.anisotropy;
2062
2063		this.format = source.format;
2064		this.internalFormat = source.internalFormat;
2065		this.type = source.type;
2066
2067		this.offset.copy(source.offset);
2068		this.repeat.copy(source.repeat);
2069		this.center.copy(source.center);
2070		this.rotation = source.rotation;
2071
2072		this.matrixAutoUpdate = source.matrixAutoUpdate;
2073		this.matrix.copy(source.matrix);
2074
2075		this.generateMipmaps = source.generateMipmaps;
2076		this.premultiplyAlpha = source.premultiplyAlpha;
2077		this.flipY = source.flipY;
2078		this.unpackAlignment = source.unpackAlignment;
2079		this.colorSpace = source.colorSpace;
2080
2081		this.userData = JSON.parse(JSON.stringify(source.userData));
2082
2083		this.needsUpdate = true;
2084
2085		return this;
2086
2087	}
2088
2089	toJSON(meta) {
2090
2091		const isRootObject = (meta === undefined || typeof meta === 'string');
2092
2093		if (!isRootObject && meta.textures[this.uuid] !== undefined) {
2094
2095			return meta.textures[this.uuid];
2096
2097		}
2098
2099		const output = {
2100
2101			metadata: {
2102				version: 4.6,
2103				type: 'Texture',
2104				generator: 'Texture.toJSON'
2105			},
2106
2107			uuid: this.uuid,
2108			name: this.name,
2109
2110			image: this.source.toJSON(meta).uuid,
2111
2112			mapping: this.mapping,
2113			channel: this.channel,
2114
2115			repeat: [this.repeat.x, this.repeat.y],
2116			offset: [this.offset.x, this.offset.y],
2117			center: [this.center.x, this.center.y],
2118			rotation: this.rotation,
2119
2120			wrap: [this.wrapS, this.wrapT],
2121
2122			format: this.format,
2123			internalFormat: this.internalFormat,
2124			type: this.type,
2125			colorSpace: this.colorSpace,
2126
2127			minFilter: this.minFilter,
2128			magFilter: this.magFilter,
2129			anisotropy: this.anisotropy,
2130
2131			flipY: this.flipY,
2132
2133			generateMipmaps: this.generateMipmaps,
2134			premultiplyAlpha: this.premultiplyAlpha,
2135			unpackAlignment: this.unpackAlignment
2136
2137		};
2138
2139		if (Object.keys(this.userData).length > 0) output.userData = this.userData;
2140
2141		if (!isRootObject) {
2142
2143			meta.textures[this.uuid] = output;
2144
2145		}
2146
2147		return output;
2148
2149	}
2150
2151	dispose() {
2152
2153		this.dispatchEvent({ type: 'dispose' });
2154
2155	}
2156
2157	transformUv(uv) {
2158
2159		if (this.mapping !== UVMapping) return uv;
2160
2161		uv.applyMatrix3(this.matrix);
2162
2163		if (uv.x < 0 || uv.x > 1) {
2164
2165			switch (this.wrapS) {
2166
2167				case RepeatWrapping:
2168
2169					uv.x = uv.x - Math.floor(uv.x);
2170					break;
2171
2172				case ClampToEdgeWrapping:
2173
2174					uv.x = uv.x < 0 ? 0 : 1;
2175					break;
2176
2177				case MirroredRepeatWrapping:
2178
2179					if (Math.abs(Math.floor(uv.x) % 2) === 1) {
2180
2181						uv.x = Math.ceil(uv.x) - uv.x;
2182
2183					} else {
2184
2185						uv.x = uv.x - Math.floor(uv.x);
2186
2187					}
2188
2189					break;
2190
2191			}
2192
2193		}
2194
2195		if (uv.y < 0 || uv.y > 1) {
2196
2197			switch (this.wrapT) {
2198
2199				case RepeatWrapping:
2200
2201					uv.y = uv.y - Math.floor(uv.y);
2202					break;
2203
2204				case ClampToEdgeWrapping:
2205
2206					uv.y = uv.y < 0 ? 0 : 1;
2207					break;
2208
2209				case MirroredRepeatWrapping:
2210
2211					if (Math.abs(Math.floor(uv.y) % 2) === 1) {
2212
2213						uv.y = Math.ceil(uv.y) - uv.y;
2214
2215					} else {
2216
2217						uv.y = uv.y - Math.floor(uv.y);
2218
2219					}
2220
2221					break;
2222
2223			}
2224
2225		}
2226
2227		if (this.flipY) {
2228
2229			uv.y = 1 - uv.y;
2230
2231		}
2232
2233		return uv;
2234
2235	}
2236
2237	set needsUpdate(value) {
2238
2239		if (value === true) {
2240
2241			this.version++;
2242			this.source.needsUpdate = true;
2243
2244		}
2245
2246	}
2247
2248	get encoding() { // @deprecated, r152
2249
2250		warnOnce('THREE.Texture: Property .encoding has been replaced by .colorSpace.');
2251		return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
2252
2253	}
2254
2255	set encoding(encoding) { // @deprecated, r152
2256
2257		warnOnce('THREE.Texture: Property .encoding has been replaced by .colorSpace.');
2258		this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
2259
2260	}
2261
2262}
2263
2264Texture.DEFAULT_IMAGE = null;
2265Texture.DEFAULT_MAPPING = UVMapping;
2266Texture.DEFAULT_ANISOTROPY = 1;
2267
2268class Vector4 {
2269
2270	constructor(x = 0, y = 0, z = 0, w = 1) {
2271
2272		Vector4.prototype.isVector4 = true;
2273
2274		this.x = x;
2275		this.y = y;
2276		this.z = z;
2277		this.w = w;
2278
2279	}
2280
2281	get width() {
2282
2283		return this.z;
2284
2285	}
2286
2287	set width(value) {
2288
2289		this.z = value;
2290
2291	}
2292
2293	get height() {
2294
2295		return this.w;
2296
2297	}
2298
2299	set height(value) {
2300
2301		this.w = value;
2302
2303	}
2304
2305	set(x, y, z, w) {
2306
2307		this.x = x;
2308		this.y = y;
2309		this.z = z;
2310		this.w = w;
2311
2312		return this;
2313
2314	}
2315
2316	setScalar(scalar) {
2317
2318		this.x = scalar;
2319		this.y = scalar;
2320		this.z = scalar;
2321		this.w = scalar;
2322
2323		return this;
2324
2325	}
2326
2327	setX(x) {
2328
2329		this.x = x;
2330
2331		return this;
2332
2333	}
2334
2335	setY(y) {
2336
2337		this.y = y;
2338
2339		return this;
2340
2341	}
2342
2343	setZ(z) {
2344
2345		this.z = z;
2346
2347		return this;
2348
2349	}
2350
2351	setW(w) {
2352
2353		this.w = w;
2354
2355		return this;
2356
2357	}
2358
2359	setComponent(index, value) {
2360
2361		switch (index) {
2362
2363			case 0: this.x = value; break;
2364			case 1: this.y = value; break;
2365			case 2: this.z = value; break;
2366			case 3: this.w = value; break;
2367			default: throw new Error('index is out of range: ' + index);
2368
2369		}
2370
2371		return this;
2372
2373	}
2374
2375	getComponent(index) {
2376
2377		switch (index) {
2378
2379			case 0: return this.x;
2380			case 1: return this.y;
2381			case 2: return this.z;
2382			case 3: return this.w;
2383			default: throw new Error('index is out of range: ' + index);
2384
2385		}
2386
2387	}
2388
2389	clone() {
2390
2391		return new this.constructor(this.x, this.y, this.z, this.w);
2392
2393	}
2394
2395	copy(v) {
2396
2397		this.x = v.x;
2398		this.y = v.y;
2399		this.z = v.z;
2400		this.w = (v.w !== undefined) ? v.w : 1;
2401
2402		return this;
2403
2404	}
2405
2406	add(v) {
2407
2408		this.x += v.x;
2409		this.y += v.y;
2410		this.z += v.z;
2411		this.w += v.w;
2412
2413		return this;
2414
2415	}
2416
2417	addScalar(s) {
2418
2419		this.x += s;
2420		this.y += s;
2421		this.z += s;
2422		this.w += s;
2423
2424		return this;
2425
2426	}
2427
2428	addVectors(a, b) {
2429
2430		this.x = a.x + b.x;
2431		this.y = a.y + b.y;
2432		this.z = a.z + b.z;
2433		this.w = a.w + b.w;
2434
2435		return this;
2436
2437	}
2438
2439	addScaledVector(v, s) {
2440
2441		this.x += v.x * s;
2442		this.y += v.y * s;
2443		this.z += v.z * s;
2444		this.w += v.w * s;
2445
2446		return this;
2447
2448	}
2449
2450	sub(v) {
2451
2452		this.x -= v.x;
2453		this.y -= v.y;
2454		this.z -= v.z;
2455		this.w -= v.w;
2456
2457		return this;
2458
2459	}
2460
2461	subScalar(s) {
2462
2463		this.x -= s;
2464		this.y -= s;
2465		this.z -= s;
2466		this.w -= s;
2467
2468		return this;
2469
2470	}
2471
2472	subVectors(a, b) {
2473
2474		this.x = a.x - b.x;
2475		this.y = a.y - b.y;
2476		this.z = a.z - b.z;
2477		this.w = a.w - b.w;
2478
2479		return this;
2480
2481	}
2482
2483	multiply(v) {
2484
2485		this.x *= v.x;
2486		this.y *= v.y;
2487		this.z *= v.z;
2488		this.w *= v.w;
2489
2490		return this;
2491
2492	}
2493
2494	multiplyScalar(scalar) {
2495
2496		this.x *= scalar;
2497		this.y *= scalar;
2498		this.z *= scalar;
2499		this.w *= scalar;
2500
2501		return this;
2502
2503	}
2504
2505	applyMatrix4(m) {
2506
2507		const x = this.x, y = this.y, z = this.z, w = this.w;
2508		const e = m.elements;
2509
2510		this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w;
2511		this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w;
2512		this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w;
2513		this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w;
2514
2515		return this;
2516
2517	}
2518
2519	divideScalar(scalar) {
2520
2521		return this.multiplyScalar(1 / scalar);
2522
2523	}
2524
2525	setAxisAngleFromQuaternion(q) {
2526
2527		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
2528
2529		// q is assumed to be normalized
2530
2531		this.w = 2 * Math.acos(q.w);
2532
2533		const s = Math.sqrt(1 - q.w * q.w);
2534
2535		if (s < 0.0001) {
2536
2537			this.x = 1;
2538			this.y = 0;
2539			this.z = 0;
2540
2541		} else {
2542
2543			this.x = q.x / s;
2544			this.y = q.y / s;
2545			this.z = q.z / s;
2546
2547		}
2548
2549		return this;
2550
2551	}
2552
2553	setAxisAngleFromRotationMatrix(m) {
2554
2555		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
2556
2557		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
2558
2559		let angle, x, y, z; // variables for result
2560		const epsilon = 0.01,		// margin to allow for rounding errors
2561			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
2562
2563			te = m.elements,
2564
2565			m11 = te[0], m12 = te[4], m13 = te[8],
2566			m21 = te[1], m22 = te[5], m23 = te[9],
2567			m31 = te[2], m32 = te[6], m33 = te[10];
2568
2569		if ((Math.abs(m12 - m21) < epsilon) &&
2570			(Math.abs(m13 - m31) < epsilon) &&
2571			(Math.abs(m23 - m32) < epsilon)) {
2572
2573			// singularity found
2574			// first check for identity matrix which must have +1 for all terms
2575			// in leading diagonal and zero in other terms
2576
2577			if ((Math.abs(m12 + m21) < epsilon2) &&
2578				(Math.abs(m13 + m31) < epsilon2) &&
2579				(Math.abs(m23 + m32) < epsilon2) &&
2580				(Math.abs(m11 + m22 + m33 - 3) < epsilon2)) {
2581
2582				// this singularity is identity matrix so angle = 0
2583
2584				this.set(1, 0, 0, 0);
2585
2586				return this; // zero angle, arbitrary axis
2587
2588			}
2589
2590			// otherwise this singularity is angle = 180
2591
2592			angle = Math.PI;
2593
2594			const xx = (m11 + 1) / 2;
2595			const yy = (m22 + 1) / 2;
2596			const zz = (m33 + 1) / 2;
2597			const xy = (m12 + m21) / 4;
2598			const xz = (m13 + m31) / 4;
2599			const yz = (m23 + m32) / 4;
2600
2601			if ((xx > yy) && (xx > zz)) {
2602
2603				// m11 is the largest diagonal term
2604
2605				if (xx < epsilon) {
2606
2607					x = 0;
2608					y = 0.707106781;
2609					z = 0.707106781;
2610
2611				} else {
2612
2613					x = Math.sqrt(xx);
2614					y = xy / x;
2615					z = xz / x;
2616
2617				}
2618
2619			} else if (yy > zz) {
2620
2621				// m22 is the largest diagonal term
2622
2623				if (yy < epsilon) {
2624
2625					x = 0.707106781;
2626					y = 0;
2627					z = 0.707106781;
2628
2629				} else {
2630
2631					y = Math.sqrt(yy);
2632					x = xy / y;
2633					z = yz / y;
2634
2635				}
2636
2637			} else {
2638
2639				// m33 is the largest diagonal term so base result on this
2640
2641				if (zz < epsilon) {
2642
2643					x = 0.707106781;
2644					y = 0.707106781;
2645					z = 0;
2646
2647				} else {
2648
2649					z = Math.sqrt(zz);
2650					x = xz / z;
2651					y = yz / z;
2652
2653				}
2654
2655			}
2656
2657			this.set(x, y, z, angle);
2658
2659			return this; // return 180 deg rotation
2660
2661		}
2662
2663		// as we have reached here there are no singularities so we can handle normally
2664
2665		let s = Math.sqrt((m32 - m23) * (m32 - m23) +
2666			(m13 - m31) * (m13 - m31) +
2667			(m21 - m12) * (m21 - m12)); // used to normalize
2668
2669		if (Math.abs(s) < 0.001) s = 1;
2670
2671		// prevent divide by zero, should not happen if matrix is orthogonal and should be
2672		// caught by singularity test above, but I've left it in just in case
2673
2674		this.x = (m32 - m23) / s;
2675		this.y = (m13 - m31) / s;
2676		this.z = (m21 - m12) / s;
2677		this.w = Math.acos((m11 + m22 + m33 - 1) / 2);
2678
2679		return this;
2680
2681	}
2682
2683	min(v) {
2684
2685		this.x = Math.min(this.x, v.x);
2686		this.y = Math.min(this.y, v.y);
2687		this.z = Math.min(this.z, v.z);
2688		this.w = Math.min(this.w, v.w);
2689
2690		return this;
2691
2692	}
2693
2694	max(v) {
2695
2696		this.x = Math.max(this.x, v.x);
2697		this.y = Math.max(this.y, v.y);
2698		this.z = Math.max(this.z, v.z);
2699		this.w = Math.max(this.w, v.w);
2700
2701		return this;
2702
2703	}
2704
2705	clamp(min, max) {
2706
2707		// assumes min < max, componentwise
2708
2709		this.x = Math.max(min.x, Math.min(max.x, this.x));
2710		this.y = Math.max(min.y, Math.min(max.y, this.y));
2711		this.z = Math.max(min.z, Math.min(max.z, this.z));
2712		this.w = Math.max(min.w, Math.min(max.w, this.w));
2713
2714		return this;
2715
2716	}
2717
2718	clampScalar(minVal, maxVal) {
2719
2720		this.x = Math.max(minVal, Math.min(maxVal, this.x));
2721		this.y = Math.max(minVal, Math.min(maxVal, this.y));
2722		this.z = Math.max(minVal, Math.min(maxVal, this.z));
2723		this.w = Math.max(minVal, Math.min(maxVal, this.w));
2724
2725		return this;
2726
2727	}
2728
2729	clampLength(min, max) {
2730
2731		const length = this.length();
2732
2733		return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
2734
2735	}
2736
2737	floor() {
2738
2739		this.x = Math.floor(this.x);
2740		this.y = Math.floor(this.y);
2741		this.z = Math.floor(this.z);
2742		this.w = Math.floor(this.w);
2743
2744		return this;
2745
2746	}
2747
2748	ceil() {
2749
2750		this.x = Math.ceil(this.x);
2751		this.y = Math.ceil(this.y);
2752		this.z = Math.ceil(this.z);
2753		this.w = Math.ceil(this.w);
2754
2755		return this;
2756
2757	}
2758
2759	round() {
2760
2761		this.x = Math.round(this.x);
2762		this.y = Math.round(this.y);
2763		this.z = Math.round(this.z);
2764		this.w = Math.round(this.w);
2765
2766		return this;
2767
2768	}
2769
2770	roundToZero() {
2771
2772		this.x = Math.trunc(this.x);
2773		this.y = Math.trunc(this.y);
2774		this.z = Math.trunc(this.z);
2775		this.w = Math.trunc(this.w);
2776
2777		return this;
2778
2779	}
2780
2781	negate() {
2782
2783		this.x = - this.x;
2784		this.y = - this.y;
2785		this.z = - this.z;
2786		this.w = - this.w;
2787
2788		return this;
2789
2790	}
2791
2792	dot(v) {
2793
2794		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
2795
2796	}
2797
2798	lengthSq() {
2799
2800		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
2801
2802	}
2803
2804	length() {
2805
2806		return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
2807
2808	}
2809
2810	manhattanLength() {
2811
2812		return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w);
2813
2814	}
2815
2816	normalize() {
2817
2818		return this.divideScalar(this.length() || 1);
2819
2820	}
2821
2822	setLength(length) {
2823
2824		return this.normalize().multiplyScalar(length);
2825
2826	}
2827
2828	lerp(v, alpha) {
2829
2830		this.x += (v.x - this.x) * alpha;
2831		this.y += (v.y - this.y) * alpha;
2832		this.z += (v.z - this.z) * alpha;
2833		this.w += (v.w - this.w) * alpha;
2834
2835		return this;
2836
2837	}
2838
2839	lerpVectors(v1, v2, alpha) {
2840
2841		this.x = v1.x + (v2.x - v1.x) * alpha;
2842		this.y = v1.y + (v2.y - v1.y) * alpha;
2843		this.z = v1.z + (v2.z - v1.z) * alpha;
2844		this.w = v1.w + (v2.w - v1.w) * alpha;
2845
2846		return this;
2847
2848	}
2849
2850	equals(v) {
2851
2852		return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z) && (v.w === this.w));
2853
2854	}
2855
2856	fromArray(array, offset = 0) {
2857
2858		this.x = array[offset];
2859		this.y = array[offset + 1];
2860		this.z = array[offset + 2];
2861		this.w = array[offset + 3];
2862
2863		return this;
2864
2865	}
2866
2867	toArray(array = [], offset = 0) {
2868
2869		array[offset] = this.x;
2870		array[offset + 1] = this.y;
2871		array[offset + 2] = this.z;
2872		array[offset + 3] = this.w;
2873
2874		return array;
2875
2876	}
2877
2878	fromBufferAttribute(attribute, index) {
2879
2880		this.x = attribute.getX(index);
2881		this.y = attribute.getY(index);
2882		this.z = attribute.getZ(index);
2883		this.w = attribute.getW(index);
2884
2885		return this;
2886
2887	}
2888
2889	random() {
2890
2891		this.x = Math.random();
2892		this.y = Math.random();
2893		this.z = Math.random();
2894		this.w = Math.random();
2895
2896		return this;
2897
2898	}
2899
2900	*[Symbol.iterator]() {
2901
2902		yield this.x;
2903		yield this.y;
2904		yield this.z;
2905		yield this.w;
2906
2907	}
2908
2909}
2910
2911/*
2912 In options, we can specify:
2913 * Texture parameters for an auto-generated target texture
2914 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
2915*/
2916class RenderTarget extends EventDispatcher {
2917
2918	constructor(width = 1, height = 1, options = {}) {
2919
2920		super();
2921
2922		this.isRenderTarget = true;
2923
2924		this.width = width;
2925		this.height = height;
2926		this.depth = 1;
2927
2928		this.scissor = new Vector4(0, 0, width, height);
2929		this.scissorTest = false;
2930
2931		this.viewport = new Vector4(0, 0, width, height);
2932
2933		const image = { width: width, height: height, depth: 1 };
2934
2935		if (options.encoding !== undefined) {
2936
2937			// @deprecated, r152
2938			warnOnce('THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.');
2939			options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
2940
2941		}
2942
2943		options = Object.assign({
2944			generateMipmaps: false,
2945			internalFormat: null,
2946			minFilter: LinearFilter,
2947			depthBuffer: true,
2948			stencilBuffer: false,
2949			depthTexture: null,
2950			samples: 0
2951		}, options);
2952
2953		this.texture = new Texture(image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace);
2954		this.texture.isRenderTargetTexture = true;
2955
2956		this.texture.flipY = false;
2957		this.texture.generateMipmaps = options.generateMipmaps;
2958		this.texture.internalFormat = options.internalFormat;
2959
2960		this.depthBuffer = options.depthBuffer;
2961		this.stencilBuffer = options.stencilBuffer;
2962
2963		this.depthTexture = options.depthTexture;
2964
2965		this.samples = options.samples;
2966
2967	}
2968
2969	setSize(width, height, depth = 1) {
2970
2971		if (this.width !== width || this.height !== height || this.depth !== depth) {
2972
2973			this.width = width;
2974			this.height = height;
2975			this.depth = depth;
2976
2977			this.texture.image.width = width;
2978			this.texture.image.height = height;
2979			this.texture.image.depth = depth;
2980
2981			this.dispose();
2982
2983		}
2984
2985		this.viewport.set(0, 0, width, height);
2986		this.scissor.set(0, 0, width, height);
2987
2988	}
2989
2990	clone() {
2991
2992		return new this.constructor().copy(this);
2993
2994	}
2995
2996	copy(source) {
2997
2998		this.width = source.width;
2999		this.height = source.height;
3000		this.depth = source.depth;
3001
3002		this.scissor.copy(source.scissor);
3003		this.scissorTest = source.scissorTest;
3004
3005		this.viewport.copy(source.viewport);
3006
3007		this.texture = source.texture.clone();
3008		this.texture.isRenderTargetTexture = true;
3009
3010		// ensure image object is not shared, see #20328
3011
3012		const image = Object.assign({}, source.texture.image);
3013		this.texture.source = new Source(image);
3014
3015		this.depthBuffer = source.depthBuffer;
3016		this.stencilBuffer = source.stencilBuffer;
3017
3018		if (source.depthTexture !== null) this.depthTexture = source.depthTexture.clone();
3019
3020		this.samples = source.samples;
3021
3022		return this;
3023
3024	}
3025
3026	dispose() {
3027
3028		this.dispatchEvent({ type: 'dispose' });
3029
3030	}
3031
3032}
3033
3034class WebGLRenderTarget extends RenderTarget {
3035
3036	constructor(width = 1, height = 1, options = {}) {
3037
3038		super(width, height, options);
3039
3040		this.isWebGLRenderTarget = true;
3041
3042	}
3043
3044}
3045
3046class DataArrayTexture extends Texture {
3047
3048	constructor(data = null, width = 1, height = 1, depth = 1) {
3049
3050		super(null);
3051
3052		this.isDataArrayTexture = true;
3053
3054		this.image = { data, width, height, depth };
3055
3056		this.magFilter = NearestFilter;
3057		this.minFilter = NearestFilter;
3058
3059		this.wrapR = ClampToEdgeWrapping;
3060
3061		this.generateMipmaps = false;
3062		this.flipY = false;
3063		this.unpackAlignment = 1;
3064
3065	}
3066
3067}
3068
3069class WebGLArrayRenderTarget extends WebGLRenderTarget {
3070
3071	constructor(width = 1, height = 1, depth = 1, options = {}) {
3072
3073		super(width, height, options);
3074
3075		this.isWebGLArrayRenderTarget = true;
3076
3077		this.depth = depth;
3078
3079		this.texture = new DataArrayTexture(null, width, height, depth);
3080
3081		this.texture.isRenderTargetTexture = true;
3082
3083	}
3084
3085}
3086
3087class Data3DTexture extends Texture {
3088
3089	constructor(data = null, width = 1, height = 1, depth = 1) {
3090
3091		// We're going to add .setXXX() methods for setting properties later.
3092		// Users can still set in DataTexture3D directly.
3093		//
3094		//	const texture = new THREE.DataTexture3D( data, width, height, depth );
3095		// 	texture.anisotropy = 16;
3096		//
3097		// See #14839
3098
3099		super(null);
3100
3101		this.isData3DTexture = true;
3102
3103		this.image = { data, width, height, depth };
3104
3105		this.magFilter = NearestFilter;
3106		this.minFilter = NearestFilter;
3107
3108		this.wrapR = ClampToEdgeWrapping;
3109
3110		this.generateMipmaps = false;
3111		this.flipY = false;
3112		this.unpackAlignment = 1;
3113
3114	}
3115
3116}
3117
3118class WebGL3DRenderTarget extends WebGLRenderTarget {
3119
3120	constructor(width = 1, height = 1, depth = 1, options = {}) {
3121
3122		super(width, height, options);
3123
3124		this.isWebGL3DRenderTarget = true;
3125
3126		this.depth = depth;
3127
3128		this.texture = new Data3DTexture(null, width, height, depth);
3129
3130		this.texture.isRenderTargetTexture = true;
3131
3132	}
3133
3134}
3135
3136class WebGLMultipleRenderTargets extends WebGLRenderTarget {
3137
3138	constructor(width = 1, height = 1, count = 1, options = {}) {
3139
3140		super(width, height, options);
3141
3142		this.isWebGLMultipleRenderTargets = true;
3143
3144		const texture = this.texture;
3145
3146		this.texture = [];
3147
3148		for (let i = 0; i < count; i++) {
3149
3150			this.texture[i] = texture.clone();
3151			this.texture[i].isRenderTargetTexture = true;
3152
3153		}
3154
3155	}
3156
3157	setSize(width, height, depth = 1) {
3158
3159		if (this.width !== width || this.height !== height || this.depth !== depth) {
3160
3161			this.width = width;
3162			this.height = height;
3163			this.depth = depth;
3164
3165			for (let i = 0, il = this.texture.length; i < il; i++) {
3166
3167				this.texture[i].image.width = width;
3168				this.texture[i].image.height = height;
3169				this.texture[i].image.depth = depth;
3170
3171			}
3172
3173			this.dispose();
3174
3175		}
3176
3177		this.viewport.set(0, 0, width, height);
3178		this.scissor.set(0, 0, width, height);
3179
3180	}
3181
3182	copy(source) {
3183
3184		this.dispose();
3185
3186		this.width = source.width;
3187		this.height = source.height;
3188		this.depth = source.depth;
3189
3190		this.scissor.copy(source.scissor);
3191		this.scissorTest = source.scissorTest;
3192
3193		this.viewport.copy(source.viewport);
3194
3195		this.depthBuffer = source.depthBuffer;
3196		this.stencilBuffer = source.stencilBuffer;
3197
3198		if (source.depthTexture !== null) this.depthTexture = source.depthTexture.clone();
3199
3200		this.texture.length = 0;
3201
3202		for (let i = 0, il = source.texture.length; i < il; i++) {
3203
3204			this.texture[i] = source.texture[i].clone();
3205			this.texture[i].isRenderTargetTexture = true;
3206
3207		}
3208
3209		return this;
3210
3211	}
3212
3213}
3214
3215class Quaternion {
3216
3217	constructor(x = 0, y = 0, z = 0, w = 1) {
3218
3219		this.isQuaternion = true;
3220
3221		this._x = x;
3222		this._y = y;
3223		this._z = z;
3224		this._w = w;
3225
3226	}
3227
3228	static slerpFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) {
3229
3230		// fuzz-free, array-based Quaternion SLERP operation
3231
3232		let x0 = src0[srcOffset0 + 0],
3233			y0 = src0[srcOffset0 + 1],
3234			z0 = src0[srcOffset0 + 2],
3235			w0 = src0[srcOffset0 + 3];
3236
3237		const x1 = src1[srcOffset1 + 0],
3238			y1 = src1[srcOffset1 + 1],
3239			z1 = src1[srcOffset1 + 2],
3240			w1 = src1[srcOffset1 + 3];
3241
3242		if (t === 0) {
3243
3244			dst[dstOffset + 0] = x0;
3245			dst[dstOffset + 1] = y0;
3246			dst[dstOffset + 2] = z0;
3247			dst[dstOffset + 3] = w0;
3248			return;
3249
3250		}
3251
3252		if (t === 1) {
3253
3254			dst[dstOffset + 0] = x1;
3255			dst[dstOffset + 1] = y1;
3256			dst[dstOffset + 2] = z1;
3257			dst[dstOffset + 3] = w1;
3258			return;
3259
3260		}
3261
3262		if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {
3263
3264			let s = 1 - t;
3265			const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
3266				dir = (cos >= 0 ? 1 : - 1),
3267				sqrSin = 1 - cos * cos;
3268
3269			// Skip the Slerp for tiny steps to avoid numeric problems:
3270			if (sqrSin > Number.EPSILON) {
3271
3272				const sin = Math.sqrt(sqrSin),
3273					len = Math.atan2(sin, cos * dir);
3274
3275				s = Math.sin(s * len) / sin;
3276				t = Math.sin(t * len) / sin;
3277
3278			}
3279
3280			const tDir = t * dir;
3281
3282			x0 = x0 * s + x1 * tDir;
3283			y0 = y0 * s + y1 * tDir;
3284			z0 = z0 * s + z1 * tDir;
3285			w0 = w0 * s + w1 * tDir;
3286
3287			// Normalize in case we just did a lerp:
3288			if (s === 1 - t) {
3289
3290				const f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0);
3291
3292				x0 *= f;
3293				y0 *= f;
3294				z0 *= f;
3295				w0 *= f;
3296
3297			}
3298
3299		}
3300
3301		dst[dstOffset] = x0;
3302		dst[dstOffset + 1] = y0;
3303		dst[dstOffset + 2] = z0;
3304		dst[dstOffset + 3] = w0;
3305
3306	}
3307
3308	static multiplyQuaternionsFlat(dst, dstOffset, src0, srcOffset0, src1, srcOffset1) {
3309
3310		const x0 = src0[srcOffset0];
3311		const y0 = src0[srcOffset0 + 1];
3312		const z0 = src0[srcOffset0 + 2];
3313		const w0 = src0[srcOffset0 + 3];
3314
3315		const x1 = src1[srcOffset1];
3316		const y1 = src1[srcOffset1 + 1];
3317		const z1 = src1[srcOffset1 + 2];
3318		const w1 = src1[srcOffset1 + 3];
3319
3320		dst[dstOffset] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
3321		dst[dstOffset + 1] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
3322		dst[dstOffset + 2] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
3323		dst[dstOffset + 3] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
3324
3325		return dst;
3326
3327	}
3328
3329	get x() {
3330
3331		return this._x;
3332
3333	}
3334
3335	set x(value) {
3336
3337		this._x = value;
3338		this._onChangeCallback();
3339
3340	}
3341
3342	get y() {
3343
3344		return this._y;
3345
3346	}
3347
3348	set y(value) {
3349
3350		this._y = value;
3351		this._onChangeCallback();
3352
3353	}
3354
3355	get z() {
3356
3357		return this._z;
3358
3359	}
3360
3361	set z(value) {
3362
3363		this._z = value;
3364		this._onChangeCallback();
3365
3366	}
3367
3368	get w() {
3369
3370		return this._w;
3371
3372	}
3373
3374	set w(value) {
3375
3376		this._w = value;
3377		this._onChangeCallback();
3378
3379	}
3380
3381	set(x, y, z, w) {
3382
3383		this._x = x;
3384		this._y = y;
3385		this._z = z;
3386		this._w = w;
3387
3388		this._onChangeCallback();
3389
3390		return this;
3391
3392	}
3393
3394	clone() {
3395
3396		return new this.constructor(this._x, this._y, this._z, this._w);
3397
3398	}
3399
3400	copy(quaternion) {
3401
3402		this._x = quaternion.x;
3403		this._y = quaternion.y;
3404		this._z = quaternion.z;
3405		this._w = quaternion.w;
3406
3407		this._onChangeCallback();
3408
3409		return this;
3410
3411	}
3412
3413	setFromEuler(euler, update = true) {
3414
3415		const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
3416
3417		// http://www.mathworks.com/matlabcentral/fileexchange/
3418		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
3419		//	content/SpinCalc.m
3420
3421		const cos = Math.cos;
3422		const sin = Math.sin;
3423
3424		const c1 = cos(x / 2);
3425		const c2 = cos(y / 2);
3426		const c3 = cos(z / 2);
3427
3428		const s1 = sin(x / 2);
3429		const s2 = sin(y / 2);
3430		const s3 = sin(z / 2);
3431
3432		switch (order) {
3433
3434			case 'XYZ':
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 'YXZ':
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 'ZXY':
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			case 'ZYX':
3456				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3457				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3458				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3459				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3460				break;
3461
3462			case 'YZX':
3463				this._x = s1 * c2 * c3 + c1 * s2 * s3;
3464				this._y = c1 * s2 * c3 + s1 * c2 * s3;
3465				this._z = c1 * c2 * s3 - s1 * s2 * c3;
3466				this._w = c1 * c2 * c3 - s1 * s2 * s3;
3467				break;
3468
3469			case 'XZY':
3470				this._x = s1 * c2 * c3 - c1 * s2 * s3;
3471				this._y = c1 * s2 * c3 - s1 * c2 * s3;
3472				this._z = c1 * c2 * s3 + s1 * s2 * c3;
3473				this._w = c1 * c2 * c3 + s1 * s2 * s3;
3474				break;
3475
3476			default:
3477				console.warn('THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order);
3478
3479		}
3480
3481		if (update === true) this._onChangeCallback();
3482
3483		return this;
3484
3485	}
3486
3487	setFromAxisAngle(axis, angle) {
3488
3489		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
3490
3491		// assumes axis is normalized
3492
3493		const halfAngle = angle / 2, s = Math.sin(halfAngle);
3494
3495		this._x = axis.x * s;
3496		this._y = axis.y * s;
3497		this._z = axis.z * s;
3498		this._w = Math.cos(halfAngle);
3499
3500		this._onChangeCallback();
3501
3502		return this;
3503
3504	}
3505
3506	setFromRotationMatrix(m) {
3507
3508		// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
3509
3510		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
3511
3512		const te = m.elements,
3513
3514			m11 = te[0], m12 = te[4], m13 = te[8],
3515			m21 = te[1], m22 = te[5], m23 = te[9],
3516			m31 = te[2], m32 = te[6], m33 = te[10],
3517
3518			trace = m11 + m22 + m33;
3519
3520		if (trace > 0) {
3521
3522			const s = 0.5 / Math.sqrt(trace + 1.0);
3523
3524			this._w = 0.25 / s;
3525			this._x = (m32 - m23) * s;
3526			this._y = (m13 - m31) * s;
3527			this._z = (m21 - m12) * s;
3528
3529		} else if (m11 > m22 && m11 > m33) {
3530
3531			const s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
3532
3533			this._w = (m32 - m23) / s;
3534			this._x = 0.25 * s;
3535			this._y = (m12 + m21) / s;
3536			this._z = (m13 + m31) / s;
3537
3538		} else if (m22 > m33) {
3539
3540			const s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
3541
3542			this._w = (m13 - m31) / s;
3543			this._x = (m12 + m21) / s;
3544			this._y = 0.25 * s;
3545			this._z = (m23 + m32) / s;
3546
3547		} else {
3548
3549			const s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
3550
3551			this._w = (m21 - m12) / s;
3552			this._x = (m13 + m31) / s;
3553			this._y = (m23 + m32) / s;
3554			this._z = 0.25 * s;
3555
3556		}
3557
3558		this._onChangeCallback();
3559
3560		return this;
3561
3562	}
3563
3564	setFromUnitVectors(vFrom, vTo) {
3565
3566		// assumes direction vectors vFrom and vTo are normalized
3567
3568		let r = vFrom.dot(vTo) + 1;
3569
3570		if (r < Number.EPSILON) {
3571
3572			// vFrom and vTo point in opposite directions
3573
3574			r = 0;
3575
3576			if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
3577
3578				this._x = - vFrom.y;
3579				this._y = vFrom.x;
3580				this._z = 0;
3581				this._w = r;
3582
3583			} else {
3584
3585				this._x = 0;
3586				this._y = - vFrom.z;
3587				this._z = vFrom.y;
3588				this._w = r;
3589
3590			}
3591
3592		} else {
3593
3594			// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
3595
3596			this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
3597			this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
3598			this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
3599			this._w = r;
3600
3601		}
3602
3603		return this.normalize();
3604
3605	}
3606
3607	angleTo(q) {
3608
3609		return 2 * Math.acos(Math.abs(clamp(this.dot(q), - 1, 1)));
3610
3611	}
3612
3613	rotateTowards(q, step) {
3614
3615		const angle = this.angleTo(q);
3616
3617		if (angle === 0) return this;
3618
3619		const t = Math.min(1, step / angle);
3620
3621		this.slerp(q, t);
3622
3623		return this;
3624
3625	}
3626
3627	identity() {
3628
3629		return this.set(0, 0, 0, 1);
3630
3631	}
3632
3633	invert() {
3634
3635		// quaternion is assumed to have unit length
3636
3637		return this.conjugate();
3638
3639	}
3640
3641	conjugate() {
3642
3643		this._x *= - 1;
3644		this._y *= - 1;
3645		this._z *= - 1;
3646
3647		this._onChangeCallback();
3648
3649		return this;
3650
3651	}
3652
3653	dot(v) {
3654
3655		return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
3656
3657	}
3658
3659	lengthSq() {
3660
3661		return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
3662
3663	}
3664
3665	length() {
3666
3667		return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);
3668
3669	}
3670
3671	normalize() {
3672
3673		let l = this.length();
3674
3675		if (l === 0) {
3676
3677			this._x = 0;
3678			this._y = 0;
3679			this._z = 0;
3680			this._w = 1;
3681
3682		} else {
3683
3684			l = 1 / l;
3685
3686			this._x = this._x * l;
3687			this._y = this._y * l;
3688			this._z = this._z * l;
3689			this._w = this._w * l;
3690
3691		}
3692
3693		this._onChangeCallback();
3694
3695		return this;
3696
3697	}
3698
3699	multiply(q) {
3700
3701		return this.multiplyQuaternions(this, q);
3702
3703	}
3704
3705	premultiply(q) {
3706
3707		return this.multiplyQuaternions(q, this);
3708
3709	}
3710
3711	multiplyQuaternions(a, b) {
3712
3713		// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
3714
3715		const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
3716		const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
3717
3718		this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
3719		this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
3720		this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
3721		this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
3722
3723		this._onChangeCallback();
3724
3725		return this;
3726
3727	}
3728
3729	slerp(qb, t) {
3730
3731		if (t === 0) return this;
3732		if (t === 1) return this.copy(qb);
3733
3734		const x = this._x, y = this._y, z = this._z, w = this._w;
3735
3736		// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
3737
3738		let cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
3739
3740		if (cosHalfTheta < 0) {
3741
3742			this._w = - qb._w;
3743			this._x = - qb._x;
3744			this._y = - qb._y;
3745			this._z = - qb._z;
3746
3747			cosHalfTheta = - cosHalfTheta;
3748
3749		} else {
3750
3751			this.copy(qb);
3752
3753		}
3754
3755		if (cosHalfTheta >= 1.0) {
3756
3757			this._w = w;
3758			this._x = x;
3759			this._y = y;
3760			this._z = z;
3761
3762			return this;
3763
3764		}
3765
3766		const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
3767
3768		if (sqrSinHalfTheta <= Number.EPSILON) {
3769
3770			const s = 1 - t;
3771			this._w = s * w + t * this._w;
3772			this._x = s * x + t * this._x;
3773			this._y = s * y + t * this._y;
3774			this._z = s * z + t * this._z;
3775
3776			this.normalize(); // normalize calls _onChangeCallback()
3777
3778			return this;
3779
3780		}
3781
3782		const sinHalfTheta = Math.sqrt(sqrSinHalfTheta);
3783		const halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta);
3784		const ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta,
3785			ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
3786
3787		this._w = (w * ratioA + this._w * ratioB);
3788		this._x = (x * ratioA + this._x * ratioB);
3789		this._y = (y * ratioA + this._y * ratioB);
3790		this._z = (z * ratioA + this._z * ratioB);
3791
3792		this._onChangeCallback();
3793
3794		return this;
3795
3796	}
3797
3798	slerpQuaternions(qa, qb, t) {
3799
3800		return this.copy(qa).slerp(qb, t);
3801
3802	}
3803
3804	random() {
3805
3806		// Derived from http://planning.cs.uiuc.edu/node198.html
3807		// Note, this source uses w, x, y, z ordering,
3808		// so we swap the order below.
3809
3810		const u1 = Math.random();
3811		const sqrt1u1 = Math.sqrt(1 - u1);
3812		const sqrtu1 = Math.sqrt(u1);
3813
3814		const u2 = 2 * Math.PI * Math.random();
3815
3816		const u3 = 2 * Math.PI * Math.random();
3817
3818		return this.set(
3819			sqrt1u1 * Math.cos(u2),
3820			sqrtu1 * Math.sin(u3),
3821			sqrtu1 * Math.cos(u3),
3822			sqrt1u1 * Math.sin(u2),
3823		);
3824
3825	}
3826
3827	equals(quaternion) {
3828
3829		return (quaternion._x === this._x) && (quaternion._y === this._y) && (quaternion._z === this._z) && (quaternion._w === this._w);
3830
3831	}
3832
3833	fromArray(array, offset = 0) {
3834
3835		this._x = array[offset];
3836		this._y = array[offset + 1];
3837		this._z = array[offset + 2];
3838		this._w = array[offset + 3];
3839
3840		this._onChangeCallback();
3841
3842		return this;
3843
3844	}
3845
3846	toArray(array = [], offset = 0) {
3847
3848		array[offset] = this._x;
3849		array[offset + 1] = this._y;
3850		array[offset + 2] = this._z;
3851		array[offset + 3] = this._w;
3852
3853		return array;
3854
3855	}
3856
3857	fromBufferAttribute(attribute, index) {
3858
3859		this._x = attribute.getX(index);
3860		this._y = attribute.getY(index);
3861		this._z = attribute.getZ(index);
3862		this._w = attribute.getW(index);
3863
3864		this._onChangeCallback();
3865
3866		return this;
3867
3868	}
3869
3870	toJSON() {
3871
3872		return this.toArray();
3873
3874	}
3875
3876	_onChange(callback) {
3877
3878		this._onChangeCallback = callback;
3879
3880		return this;
3881
3882	}
3883
3884	_onChangeCallback() { }
3885
3886	*[Symbol.iterator]() {
3887
3888		yield this._x;
3889		yield this._y;
3890		yield this._z;
3891		yield this._w;
3892
3893	}
3894
3895}
3896
3897class Vector3 {
3898
3899	constructor(x = 0, y = 0, z = 0) {
3900
3901		Vector3.prototype.isVector3 = true;
3902
3903		this.x = x;
3904		this.y = y;
3905		this.z = z;
3906
3907	}
3908
3909	set(x, y, z) {
3910
3911		if (z === undefined) z = this.z; // sprite.scale.set(x,y)
3912
3913		this.x = x;
3914		this.y = y;
3915		this.z = z;
3916
3917		return this;
3918
3919	}
3920
3921	setScalar(scalar) {
3922
3923		this.x = scalar;
3924		this.y = scalar;
3925		this.z = scalar;
3926
3927		return this;
3928
3929	}
3930
3931	setX(x) {
3932
3933		this.x = x;
3934
3935		return this;
3936
3937	}
3938
3939	setY(y) {
3940
3941		this.y = y;
3942
3943		return this;
3944
3945	}
3946
3947	setZ(z) {
3948
3949		this.z = z;
3950
3951		return this;
3952
3953	}
3954
3955	setComponent(index, value) {
3956
3957		switch (index) {
3958
3959			case 0: this.x = value; break;
3960			case 1: this.y = value; break;
3961			case 2: this.z = value; break;
3962			default: throw new Error('index is out of range: ' + index);
3963
3964		}
3965
3966		return this;
3967
3968	}
3969
3970	getComponent(index) {
3971
3972		switch (index) {
3973
3974			case 0: return this.x;
3975			case 1: return this.y;
3976			case 2: return this.z;
3977			default: throw new Error('index is out of range: ' + index);
3978
3979		}
3980
3981	}
3982
3983	clone() {
3984
3985		return new this.constructor(this.x, this.y, this.z);
3986
3987	}
3988
3989	copy(v) {
3990
3991		this.x = v.x;
3992		this.y = v.y;
3993		this.z = v.z;
3994
3995		return this;
3996
3997	}
3998
3999	add(v) {
4000
4001		this.x += v.x;
4002		this.y += v.y;
4003		this.z += v.z;
4004
4005		return this;
4006
4007	}
4008
4009	addScalar(s) {
4010
4011		this.x += s;
4012		this.y += s;
4013		this.z += s;
4014
4015		return this;
4016
4017	}
4018
4019	addVectors(a, b) {
4020
4021		this.x = a.x + b.x;
4022		this.y = a.y + b.y;
4023		this.z = a.z + b.z;
4024
4025		return this;
4026
4027	}
4028
4029	addScaledVector(v, s) {
4030
4031		this.x += v.x * s;
4032		this.y += v.y * s;
4033		this.z += v.z * s;
4034
4035		return this;
4036
4037	}
4038
4039	sub(v) {
4040
4041		this.x -= v.x;
4042		this.y -= v.y;
4043		this.z -= v.z;
4044
4045		return this;
4046
4047	}
4048
4049	subScalar(s) {
4050
4051		this.x -= s;
4052		this.y -= s;
4053		this.z -= s;
4054
4055		return this;
4056
4057	}
4058
4059	subVectors(a, b) {
4060
4061		this.x = a.x - b.x;
4062		this.y = a.y - b.y;
4063		this.z = a.z - b.z;
4064
4065		return this;
4066
4067	}
4068
4069	multiply(v) {
4070
4071		this.x *= v.x;
4072		this.y *= v.y;
4073		this.z *= v.z;
4074
4075		return this;
4076
4077	}
4078
4079	multiplyScalar(scalar) {
4080
4081		this.x *= scalar;
4082		this.y *= scalar;
4083		this.z *= scalar;
4084
4085		return this;
4086
4087	}
4088
4089	multiplyVectors(a, b) {
4090
4091		this.x = a.x * b.x;
4092		this.y = a.y * b.y;
4093		this.z = a.z * b.z;
4094
4095		return this;
4096
4097	}
4098
4099	applyEuler(euler) {
4100
4101		return this.applyQuaternion(_quaternion$4.setFromEuler(euler));
4102
4103	}
4104
4105	applyAxisAngle(axis, angle) {
4106
4107		return this.applyQuaternion(_quaternion$4.setFromAxisAngle(axis, angle));
4108
4109	}
4110
4111	applyMatrix3(m) {
4112
4113		const x = this.x, y = this.y, z = this.z;
4114		const e = m.elements;
4115
4116		this.x = e[0] * x + e[3] * y + e[6] * z;
4117		this.y = e[1] * x + e[4] * y + e[7] * z;
4118		this.z = e[2] * x + e[5] * y + e[8] * z;
4119
4120		return this;
4121
4122	}
4123
4124	applyNormalMatrix(m) {
4125
4126		return this.applyMatrix3(m).normalize();
4127
4128	}
4129
4130	applyMatrix4(m) {
4131
4132		const x = this.x, y = this.y, z = this.z;
4133		const e = m.elements;
4134
4135		const w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
4136
4137		this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w;
4138		this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w;
4139		this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w;
4140
4141		return this;
4142
4143	}
4144
4145	applyQuaternion(q) {
4146
4147		// quaternion q is assumed to have unit length
4148
4149		const vx = this.x, vy = this.y, vz = this.z;
4150		const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
4151
4152		// t = 2 * cross( q.xyz, v );
4153		const tx = 2 * (qy * vz - qz * vy);
4154		const ty = 2 * (qz * vx - qx * vz);
4155		const tz = 2 * (qx * vy - qy * vx);
4156
4157		// v + q.w * t + cross( q.xyz, t );
4158		this.x = vx + qw * tx + qy * tz - qz * ty;
4159		this.y = vy + qw * ty + qz * tx - qx * tz;
4160		this.z = vz + qw * tz + qx * ty - qy * tx;
4161
4162		return this;
4163
4164	}
4165
4166	project(camera) {
4167
4168		return this.applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix);
4169
4170	}
4171
4172	unproject(camera) {
4173
4174		return this.applyMatrix4(camera.projectionMatrixInverse).applyMatrix4(camera.matrixWorld);
4175
4176	}
4177
4178	transformDirection(m) {
4179
4180		// input: THREE.Matrix4 affine matrix
4181		// vector interpreted as a direction
4182
4183		const x = this.x, y = this.y, z = this.z;
4184		const e = m.elements;
4185
4186		this.x = e[0] * x + e[4] * y + e[8] * z;
4187		this.y = e[1] * x + e[5] * y + e[9] * z;
4188		this.z = e[2] * x + e[6] * y + e[10] * z;
4189
4190		return this.normalize();
4191
4192	}
4193
4194	divide(v) {
4195
4196		this.x /= v.x;
4197		this.y /= v.y;
4198		this.z /= v.z;
4199
4200		return this;
4201
4202	}
4203
4204	divideScalar(scalar) {
4205
4206		return this.multiplyScalar(1 / scalar);
4207
4208	}
4209
4210	min(v) {
4211
4212		this.x = Math.min(this.x, v.x);
4213		this.y = Math.min(this.y, v.y);
4214		this.z = Math.min(this.z, v.z);
4215
4216		return this;
4217
4218	}
4219
4220	max(v) {
4221
4222		this.x = Math.max(this.x, v.x);
4223		this.y = Math.max(this.y, v.y);
4224		this.z = Math.max(this.z, v.z);
4225
4226		return this;
4227
4228	}
4229
4230	clamp(min, max) {
4231
4232		// assumes min < max, componentwise
4233
4234		this.x = Math.max(min.x, Math.min(max.x, this.x));
4235		this.y = Math.max(min.y, Math.min(max.y, this.y));
4236		this.z = Math.max(min.z, Math.min(max.z, this.z));
4237
4238		return this;
4239
4240	}
4241
4242	clampScalar(minVal, maxVal) {
4243
4244		this.x = Math.max(minVal, Math.min(maxVal, this.x));
4245		this.y = Math.max(minVal, Math.min(maxVal, this.y));
4246		this.z = Math.max(minVal, Math.min(maxVal, this.z));
4247
4248		return this;
4249
4250	}
4251
4252	clampLength(min, max) {
4253
4254		const length = this.length();
4255
4256		return this.divideScalar(length || 1).multiplyScalar(Math.max(min, Math.min(max, length)));
4257
4258	}
4259
4260	floor() {
4261
4262		this.x = Math.floor(this.x);
4263		this.y = Math.floor(this.y);
4264		this.z = Math.floor(this.z);
4265
4266		return this;
4267
4268	}
4269
4270	ceil() {
4271
4272		this.x = Math.ceil(this.x);
4273		this.y = Math.ceil(this.y);
4274		this.z = Math.ceil(this.z);
4275
4276		return this;
4277
4278	}
4279
4280	round() {
4281
4282		this.x = Math.round(this.x);
4283		this.y = Math.round(this.y);
4284		this.z = Math.round(this.z);
4285
4286		return this;
4287
4288	}
4289
4290	roundToZero() {
4291
4292		this.x = Math.trunc(this.x);
4293		this.y = Math.trunc(this.y);
4294		this.z = Math.trunc(this.z);
4295
4296		return this;
4297
4298	}
4299
4300	negate() {
4301
4302		this.x = - this.x;
4303		this.y = - this.y;
4304		this.z = - this.z;
4305
4306		return this;
4307
4308	}
4309
4310	dot(v) {
4311
4312		return this.x * v.x + this.y * v.y + this.z * v.z;
4313
4314	}
4315
4316	// TODO lengthSquared?
4317
4318	lengthSq() {
4319
4320		return this.x * this.x + this.y * this.y + this.z * this.z;
4321
4322	}
4323
4324	length() {
4325
4326		return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
4327
4328	}
4329
4330	manhattanLength() {
4331
4332		return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);
4333
4334	}
4335
4336	normalize() {
4337
4338		return this.divideScalar(this.length() || 1);
4339
4340	}
4341
4342	setLength(length) {
4343
4344		return this.normalize().multiplyScalar(length);
4345
4346	}
4347
4348	lerp(v, alpha) {
4349
4350		this.x += (v.x - this.x) * alpha;
4351		this.y += (v.y - this.y) * alpha;
4352		this.z += (v.z - this.z) * alpha;
4353
4354		return this;
4355
4356	}
4357
4358	lerpVectors(v1, v2, alpha) {
4359
4360		this.x = v1.x + (v2.x - v1.x) * alpha;
4361		this.y = v1.y + (v2.y - v1.y) * alpha;
4362		this.z = v1.z + (v2.z - v1.z) * alpha;
4363
4364		return this;
4365
4366	}
4367
4368	cross(v) {
4369
4370		return this.crossVectors(this, v);
4371
4372	}
4373
4374	crossVectors(a, b) {
4375
4376		const ax = a.x, ay = a.y, az = a.z;
4377		const bx = b.x, by = b.y, bz = b.z;
4378
4379		this.x = ay * bz - az * by;
4380		this.y = az * bx - ax * bz;
4381		this.z = ax * by - ay * bx;
4382
4383		return this;
4384
4385	}
4386
4387	projectOnVector(v) {
4388
4389		const denominator = v.lengthSq();
4390
4391		if (denominator === 0) return this.set(0, 0, 0);
4392
4393		const scalar = v.dot(this) / denominator;
4394
4395		return this.copy(v).multiplyScalar(scalar);
4396
4397	}
4398
4399	projectOnPlane(planeNormal) {
4400
4401		_vector$c.copy(this).projectOnVector(planeNormal);
4402
4403		return this.sub(_vector$c);
4404
4405	}
4406
4407	reflect(normal) {
4408
4409		// reflect incident vector off plane orthogonal to normal
4410		// normal is assumed to have unit length
4411
4412		return this.sub(_vector$c.copy(normal).multiplyScalar(2 * this.dot(normal)));
4413
4414	}
4415
4416	angleTo(v) {
4417
4418		const denominator = Math.sqrt(this.lengthSq() * v.lengthSq());
4419
4420		if (denominator === 0) return Math.PI / 2;
4421
4422		const theta = this.dot(v) / denominator;
4423
4424		// clamp, to handle numerical problems
4425
4426		return Math.acos(clamp(theta, - 1, 1));
4427
4428	}
4429
4430	distanceTo(v) {
4431
4432		return Math.sqrt(this.distanceToSquared(v));
4433
4434	}
4435
4436	distanceToSquared(v) {
4437
4438		const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
4439
4440		return dx * dx + dy * dy + dz * dz;
4441
4442	}
4443
4444	manhattanDistanceTo(v) {
4445
4446		return Math.abs(this.x - v.x) + Math.abs(this.y - v.y) + Math.abs(this.z - v.z);
4447
4448	}
4449
4450	setFromSpherical(s) {
4451
4452		return this.setFromSphericalCoords(s.radius, s.phi, s.theta);
4453
4454	}
4455
4456	setFromSphericalCoords(radius, phi, theta) {
4457
4458		const sinPhiRadius = Math.sin(phi) * radius;
4459
4460		this.x = sinPhiRadius * Math.sin(theta);
4461		this.y = Math.cos(phi) * radius;
4462		this.z = sinPhiRadius * Math.cos(theta);
4463
4464		return this;
4465
4466	}
4467
4468	setFromCylindrical(c) {
4469
4470		return this.setFromCylindricalCoords(c.radius, c.theta, c.y);
4471
4472	}
4473
4474	setFromCylindricalCoords(radius, theta, y) {
4475
vendor: 4,544 bytes, lines 4476-4770
4476		this.x = radius * Math.sin(theta);
4477		this.y = y;
4478		this.z = radius * Math.cos(theta);
4479
4480		return this;
4481
4482	}
4483
4484	setFromMatrixPosition(m) {
4485
4486		const e = m.elements;
4487
4488		this.x = e[12];
4489		this.y = e[13];
4490		this.z = e[14];
4491
4492		return this;
4493
4494	}
4495
4496	setFromMatrixScale(m) {
4497
4498		const sx = this.setFromMatrixColumn(m, 0).length();
4499		const sy = this.setFromMatrixColumn(m, 1).length();
4500		const sz = this.setFromMatrixColumn(m, 2).length();
4501
4502		this.x = sx;
4503		this.y = sy;
4504		this.z = sz;
4505
4506		return this;
4507
4508	}
4509
4510	setFromMatrixColumn(m, index) {
4511
4512		return this.fromArray(m.elements, index * 4);
4513
4514	}
4515
4516	setFromMatrix3Column(m, index) {
4517
4518		return this.fromArray(m.elements, index * 3);
4519
4520	}
4521
4522	setFromEuler(e) {
4523
4524		this.x = e._x;
4525		this.y = e._y;
4526		this.z = e._z;
4527
4528		return this;
4529
4530	}
4531
4532	setFromColor(c) {
4533
4534		this.x = c.r;
4535		this.y = c.g;
4536		this.z = c.b;
4537
4538		return this;
4539
4540	}
4541
4542	equals(v) {
4543
4544		return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
4545
4546	}
4547
4548	fromArray(array, offset = 0) {
4549
4550		this.x = array[offset];
4551		this.y = array[offset + 1];
4552		this.z = array[offset + 2];
4553
4554		return this;
4555
4556	}
4557
4558	toArray(array = [], offset = 0) {
4559
4560		array[offset] = this.x;
4561		array[offset + 1] = this.y;
4562		array[offset + 2] = this.z;
4563
4564		return array;
4565
4566	}
4567
4568	fromBufferAttribute(attribute, index) {
4569
4570		this.x = attribute.getX(index);
4571		this.y = attribute.getY(index);
4572		this.z = attribute.getZ(index);
4573
4574		return this;
4575
4576	}
4577
4578	random() {
4579
4580		this.x = Math.random();
4581		this.y = Math.random();
4582		this.z = Math.random();
4583
4584		return this;
4585
4586	}
4587
4588	randomDirection() {
4589
4590		// Derived from https://mathworld.wolfram.com/SpherePointPicking.html
4591
4592		const u = (Math.random() - 0.5) * 2;
4593		const t = Math.random() * Math.PI * 2;
4594		const f = Math.sqrt(1 - u ** 2);
4595
4596		this.x = f * Math.cos(t);
4597		this.y = f * Math.sin(t);
4598		this.z = u;
4599
4600		return this;
4601
4602	}
4603
4604	*[Symbol.iterator]() {
4605
4606		yield this.x;
4607		yield this.y;
4608		yield this.z;
4609
4610	}
4611
4612}
4613
4614const _vector$c = /*@__PURE__*/ new Vector3();
4615const _quaternion$4 = /*@__PURE__*/ new Quaternion();
4616
4617class Box3 {
4618
4619	constructor(min = new Vector3(+ Infinity, + Infinity, + Infinity), max = new Vector3(- Infinity, - Infinity, - Infinity)) {
4620
4621		this.isBox3 = true;
4622
4623		this.min = min;
4624		this.max = max;
4625
4626	}
4627
4628	set(min, max) {
4629
4630		this.min.copy(min);
4631		this.max.copy(max);
4632
4633		return this;
4634
4635	}
4636
4637	setFromArray(array) {
4638
4639		this.makeEmpty();
4640
4641		for (let i = 0, il = array.length; i < il; i += 3) {
4642
4643			this.expandByPoint(_vector$b.fromArray(array, i));
4644
4645		}
4646
4647		return this;
4648
4649	}
4650
4651	setFromBufferAttribute(attribute) {
4652
4653		this.makeEmpty();
4654
4655		for (let i = 0, il = attribute.count; i < il; i++) {
4656
4657			this.expandByPoint(_vector$b.fromBufferAttribute(attribute, i));
4658
4659		}
4660
4661		return this;
4662
4663	}
4664
4665	setFromPoints(points) {
4666
4667		this.makeEmpty();
4668
4669		for (let i = 0, il = points.length; i < il; i++) {
4670
4671			this.expandByPoint(points[i]);
4672
4673		}
4674
4675		return this;
4676
4677	}
4678
4679	setFromCenterAndSize(center, size) {
4680
4681		const halfSize = _vector$b.copy(size).multiplyScalar(0.5);
4682
4683		this.min.copy(center).sub(halfSize);
4684		this.max.copy(center).add(halfSize);
4685
4686		return this;
4687
4688	}
4689
4690	setFromObject(object, precise = false) {
4691
4692		this.makeEmpty();
4693
4694		return this.expandByObject(object, precise);
4695
4696	}
4697
4698	clone() {
4699
4700		return new this.constructor().copy(this);
4701
4702	}
4703
4704	copy(box) {
4705
4706		this.min.copy(box.min);
4707		this.max.copy(box.max);
4708
4709		return this;
4710
4711	}
4712
4713	makeEmpty() {
4714
4715		this.min.x = this.min.y = this.min.z = + Infinity;
4716		this.max.x = this.max.y = this.max.z = - Infinity;
4717
4718		return this;
4719
4720	}
4721
4722	isEmpty() {
4723
4724		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
4725
4726		return (this.max.x < this.min.x) || (this.max.y < this.min.y) || (this.max.z < this.min.z);
4727
4728	}
4729
4730	getCenter(target) {
4731
4732		return this.isEmpty() ? target.set(0, 0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5);
4733
4734	}
4735
4736	getSize(target) {
4737
4738		return this.isEmpty() ? target.set(0, 0, 0) : target.subVectors(this.max, this.min);
4739
4740	}
4741
4742	expandByPoint(point) {
4743
4744		this.min.min(point);
4745		this.max.max(point);
4746
4747		return this;
4748
4749	}
4750
4751	expandByVector(vector) {
4752
4753		this.min.sub(vector);
4754		this.max.add(vector);
4755
4756		return this;
4757
4758	}
4759
4760	expandByScalar(scalar) {
4761
4762		this.min.addScalar(- scalar);
4763		this.max.addScalar(scalar);
4764
4765		return this;
4766
4767	}
4768
4769	expandByObject(object, precise = false) {
4770
vendor: 9,510 bytes, lines 4771-5158
4771		// Computes the world-axis-aligned bounding box of an object (including its children),
4772		// accounting for both the object's, and children's, world transforms
4773
4774		object.updateWorldMatrix(false, false);
4775
4776		const geometry = object.geometry;
4777
4778		if (geometry !== undefined) {
4779
4780			const positionAttribute = geometry.getAttribute('position');
4781
4782			// precise AABB computation based on vertex data requires at least a position attribute.
4783			// instancing isn't supported so far and uses the normal (conservative) code path.
4784
4785			if (precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true) {
4786
4787				for (let i = 0, l = positionAttribute.count; i < l; i++) {
4788
4789					if (object.isMesh === true) {
4790
4791						object.getVertexPosition(i, _vector$b);
4792
4793					} else {
4794
4795						_vector$b.fromBufferAttribute(positionAttribute, i);
4796
4797					}
4798
4799					_vector$b.applyMatrix4(object.matrixWorld);
4800					this.expandByPoint(_vector$b);
4801
4802				}
4803
4804			} else {
4805
4806				if (object.boundingBox !== undefined) {
4807
4808					// object-level bounding box
4809
4810					if (object.boundingBox === null) {
4811
4812						object.computeBoundingBox();
4813
4814					}
4815
4816					_box$4.copy(object.boundingBox);
4817
4818
4819				} else {
4820
4821					// geometry-level bounding box
4822
4823					if (geometry.boundingBox === null) {
4824
4825						geometry.computeBoundingBox();
4826
4827					}
4828
4829					_box$4.copy(geometry.boundingBox);
4830
4831				}
4832
4833				_box$4.applyMatrix4(object.matrixWorld);
4834
4835				this.union(_box$4);
4836
4837			}
4838
4839		}
4840
4841		const children = object.children;
4842
4843		for (let i = 0, l = children.length; i < l; i++) {
4844
4845			this.expandByObject(children[i], precise);
4846
4847		}
4848
4849		return this;
4850
4851	}
4852
4853	containsPoint(point) {
4854
4855		return point.x < this.min.x || point.x > this.max.x ||
4856			point.y < this.min.y || point.y > this.max.y ||
4857			point.z < this.min.z || point.z > this.max.z ? false : true;
4858
4859	}
4860
4861	containsBox(box) {
4862
4863		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
4864			this.min.y <= box.min.y && box.max.y <= this.max.y &&
4865			this.min.z <= box.min.z && box.max.z <= this.max.z;
4866
4867	}
4868
4869	getParameter(point, target) {
4870
4871		// This can potentially have a divide by zero if the box
4872		// has a size dimension of 0.
4873
4874		return target.set(
4875			(point.x - this.min.x) / (this.max.x - this.min.x),
4876			(point.y - this.min.y) / (this.max.y - this.min.y),
4877			(point.z - this.min.z) / (this.max.z - this.min.z)
4878		);
4879
4880	}
4881
4882	intersectsBox(box) {
4883
4884		// using 6 splitting planes to rule out intersections.
4885		return box.max.x < this.min.x || box.min.x > this.max.x ||
4886			box.max.y < this.min.y || box.min.y > this.max.y ||
4887			box.max.z < this.min.z || box.min.z > this.max.z ? false : true;
4888
4889	}
4890
4891	intersectsSphere(sphere) {
4892
4893		// Find the point on the AABB closest to the sphere center.
4894		this.clampPoint(sphere.center, _vector$b);
4895
4896		// If that point is inside the sphere, the AABB and sphere intersect.
4897		return _vector$b.distanceToSquared(sphere.center) <= (sphere.radius * sphere.radius);
4898
4899	}
4900
4901	intersectsPlane(plane) {
4902
4903		// We compute the minimum and maximum dot product values. If those values
4904		// are on the same side (back or front) of the plane, then there is no intersection.
4905
4906		let min, max;
4907
4908		if (plane.normal.x > 0) {
4909
4910			min = plane.normal.x * this.min.x;
4911			max = plane.normal.x * this.max.x;
4912
4913		} else {
4914
4915			min = plane.normal.x * this.max.x;
4916			max = plane.normal.x * this.min.x;
4917
4918		}
4919
4920		if (plane.normal.y > 0) {
4921
4922			min += plane.normal.y * this.min.y;
4923			max += plane.normal.y * this.max.y;
4924
4925		} else {
4926
4927			min += plane.normal.y * this.max.y;
4928			max += plane.normal.y * this.min.y;
4929
4930		}
4931
4932		if (plane.normal.z > 0) {
4933
4934			min += plane.normal.z * this.min.z;
4935			max += plane.normal.z * this.max.z;
4936
4937		} else {
4938
4939			min += plane.normal.z * this.max.z;
4940			max += plane.normal.z * this.min.z;
4941
4942		}
4943
4944		return (min <= - plane.constant && max >= - plane.constant);
4945
4946	}
4947
4948	intersectsTriangle(triangle) {
4949
4950		if (this.isEmpty()) {
4951
4952			return false;
4953
4954		}
4955
4956		// compute box center and extents
4957		this.getCenter(_center);
4958		_extents.subVectors(this.max, _center);
4959
4960		// translate triangle to aabb origin
4961		_v0$2.subVectors(triangle.a, _center);
4962		_v1$7.subVectors(triangle.b, _center);
4963		_v2$4.subVectors(triangle.c, _center);
4964
4965		// compute edge vectors for triangle
4966		_f0.subVectors(_v1$7, _v0$2);
4967		_f1.subVectors(_v2$4, _v1$7);
4968		_f2.subVectors(_v0$2, _v2$4);
4969
4970		// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
4971		// 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
4972		// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
4973		let axes = [
4974			0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
4975			_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
4976			- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
4977		];
4978		if (!satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents)) {
4979
4980			return false;
4981
4982		}
4983
4984		// test 3 face normals from the aabb
4985		axes = [1, 0, 0, 0, 1, 0, 0, 0, 1];
4986		if (!satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents)) {
4987
4988			return false;
4989
4990		}
4991
4992		// finally testing the face normal of the triangle
4993		// use already existing triangle edge vectors here
4994		_triangleNormal.crossVectors(_f0, _f1);
4995		axes = [_triangleNormal.x, _triangleNormal.y, _triangleNormal.z];
4996
4997		return satForAxes(axes, _v0$2, _v1$7, _v2$4, _extents);
4998
4999	}
5000
5001	clampPoint(point, target) {
5002
5003		return target.copy(point).clamp(this.min, this.max);
5004
5005	}
5006
5007	distanceToPoint(point) {
5008
5009		return this.clampPoint(point, _vector$b).distanceTo(point);
5010
5011	}
5012
5013	getBoundingSphere(target) {
5014
5015		if (this.isEmpty()) {
5016
5017			target.makeEmpty();
5018
5019		} else {
5020
5021			this.getCenter(target.center);
5022
5023			target.radius = this.getSize(_vector$b).length() * 0.5;
5024
5025		}
5026
5027		return target;
5028
5029	}
5030
5031	intersect(box) {
5032
5033		this.min.max(box.min);
5034		this.max.min(box.max);
5035
5036		// 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.
5037		if (this.isEmpty()) this.makeEmpty();
5038
5039		return this;
5040
5041	}
5042
5043	union(box) {
5044
5045		this.min.min(box.min);
5046		this.max.max(box.max);
5047
5048		return this;
5049
5050	}
5051
5052	applyMatrix4(matrix) {
5053
5054		// transform of empty box is an empty box.
5055		if (this.isEmpty()) return this;
5056
5057		// NOTE: I am using a binary pattern to specify all 2^3 combinations below
5058		_points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix); // 000
5059		_points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix); // 001
5060		_points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix); // 010
5061		_points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix); // 011
5062		_points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix); // 100
5063		_points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix); // 101
5064		_points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix); // 110
5065		_points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix); // 111
5066
5067		this.setFromPoints(_points);
5068
5069		return this;
5070
5071	}
5072
5073	translate(offset) {
5074
5075		this.min.add(offset);
5076		this.max.add(offset);
5077
5078		return this;
5079
5080	}
5081
5082	equals(box) {
5083
5084		return box.min.equals(this.min) && box.max.equals(this.max);
5085
5086	}
5087
5088}
5089
5090const _points = [
5091	/*@__PURE__*/ new Vector3(),
5092	/*@__PURE__*/ new Vector3(),
5093	/*@__PURE__*/ new Vector3(),
5094	/*@__PURE__*/ new Vector3(),
5095	/*@__PURE__*/ new Vector3(),
5096	/*@__PURE__*/ new Vector3(),
5097	/*@__PURE__*/ new Vector3(),
5098	/*@__PURE__*/ new Vector3()
5099];
5100
5101const _vector$b = /*@__PURE__*/ new Vector3();
5102
5103const _box$4 = /*@__PURE__*/ new Box3();
5104
5105// triangle centered vertices
5106
5107const _v0$2 = /*@__PURE__*/ new Vector3();
5108const _v1$7 = /*@__PURE__*/ new Vector3();
5109const _v2$4 = /*@__PURE__*/ new Vector3();
5110
5111// triangle edge vectors
5112
5113const _f0 = /*@__PURE__*/ new Vector3();
5114const _f1 = /*@__PURE__*/ new Vector3();
5115const _f2 = /*@__PURE__*/ new Vector3();
5116
5117const _center = /*@__PURE__*/ new Vector3();
5118const _extents = /*@__PURE__*/ new Vector3();
5119const _triangleNormal = /*@__PURE__*/ new Vector3();
5120const _testAxis = /*@__PURE__*/ new Vector3();
5121
5122function satForAxes(axes, v0, v1, v2, extents) {
5123
5124	for (let i = 0, j = axes.length - 3; i <= j; i += 3) {
5125
5126		_testAxis.fromArray(axes, i);
5127		// project the aabb onto the separating axis
5128		const r = extents.x * Math.abs(_testAxis.x) + extents.y * Math.abs(_testAxis.y) + extents.z * Math.abs(_testAxis.z);
5129		// project all 3 vertices of the triangle onto the separating axis
5130		const p0 = v0.dot(_testAxis);
5131		const p1 = v1.dot(_testAxis);
5132		const p2 = v2.dot(_testAxis);
5133		// actual test, basically see if either of the most extreme of the triangle points intersects r
5134		if (Math.max(- Math.max(p0, p1, p2), Math.min(p0, p1, p2)) > r) {
5135
5136			// points of the projected triangle are outside the projected half-length of the aabb
5137			// the axis is separating and we can exit
5138			return false;
5139
5140		}
5141
5142	}
5143
5144	return true;
5145
5146}
5147
5148const _box$3 = /*@__PURE__*/ new Box3();
5149const _v1$6 = /*@__PURE__*/ new Vector3();
5150const _v2$3 = /*@__PURE__*/ new Vector3();
5151
5152class Sphere {
5153
5154	constructor(center = new Vector3(), radius = - 1) {
5155
5156		this.isSphere = true;
5157
5158		this.center = center;
vendor: 4,528 bytes, lines 5159-5450
5159		this.radius = radius;
5160
5161	}
5162
5163	set(center, radius) {
5164
5165		this.center.copy(center);
5166		this.radius = radius;
5167
5168		return this;
5169
5170	}
5171
5172	setFromPoints(points, optionalCenter) {
5173
5174		const center = this.center;
5175
5176		if (optionalCenter !== undefined) {
5177
5178			center.copy(optionalCenter);
5179
5180		} else {
5181
5182			_box$3.setFromPoints(points).getCenter(center);
5183
5184		}
5185
5186		let maxRadiusSq = 0;
5187
5188		for (let i = 0, il = points.length; i < il; i++) {
5189
5190			maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]));
5191
5192		}
5193
5194		this.radius = Math.sqrt(maxRadiusSq);
5195
5196		return this;
5197
5198	}
5199
5200	copy(sphere) {
5201
5202		this.center.copy(sphere.center);
5203		this.radius = sphere.radius;
5204
5205		return this;
5206
5207	}
5208
5209	isEmpty() {
5210
5211		return (this.radius < 0);
5212
5213	}
5214
5215	makeEmpty() {
5216
5217		this.center.set(0, 0, 0);
5218		this.radius = - 1;
5219
5220		return this;
5221
5222	}
5223
5224	containsPoint(point) {
5225
5226		return (point.distanceToSquared(this.center) <= (this.radius * this.radius));
5227
5228	}
5229
5230	distanceToPoint(point) {
5231
5232		return (point.distanceTo(this.center) - this.radius);
5233
5234	}
5235
5236	intersectsSphere(sphere) {
5237
5238		const radiusSum = this.radius + sphere.radius;
5239
5240		return sphere.center.distanceToSquared(this.center) <= (radiusSum * radiusSum);
5241
5242	}
5243
5244	intersectsBox(box) {
5245
5246		return box.intersectsSphere(this);
5247
5248	}
5249
5250	intersectsPlane(plane) {
5251
5252		return Math.abs(plane.distanceToPoint(this.center)) <= this.radius;
5253
5254	}
5255
5256	clampPoint(point, target) {
5257
5258		const deltaLengthSq = this.center.distanceToSquared(point);
5259
5260		target.copy(point);
5261
5262		if (deltaLengthSq > (this.radius * this.radius)) {
5263
5264			target.sub(this.center).normalize();
5265			target.multiplyScalar(this.radius).add(this.center);
5266
5267		}
5268
5269		return target;
5270
5271	}
5272
5273	getBoundingBox(target) {
5274
5275		if (this.isEmpty()) {
5276
5277			// Empty sphere produces empty bounding box
5278			target.makeEmpty();
5279			return target;
5280
5281		}
5282
5283		target.set(this.center, this.center);
5284		target.expandByScalar(this.radius);
5285
5286		return target;
5287
5288	}
5289
5290	applyMatrix4(matrix) {
5291
5292		this.center.applyMatrix4(matrix);
5293		this.radius = this.radius * matrix.getMaxScaleOnAxis();
5294
5295		return this;
5296
5297	}
5298
5299	translate(offset) {
5300
5301		this.center.add(offset);
5302
5303		return this;
5304
5305	}
5306
5307	expandByPoint(point) {
5308
5309		if (this.isEmpty()) {
5310
5311			this.center.copy(point);
5312
5313			this.radius = 0;
5314
5315			return this;
5316
5317		}
5318
5319		_v1$6.subVectors(point, this.center);
5320
5321		const lengthSq = _v1$6.lengthSq();
5322
5323		if (lengthSq > (this.radius * this.radius)) {
5324
5325			// calculate the minimal sphere
5326
5327			const length = Math.sqrt(lengthSq);
5328
5329			const delta = (length - this.radius) * 0.5;
5330
5331			this.center.addScaledVector(_v1$6, delta / length);
5332
5333			this.radius += delta;
5334
5335		}
5336
5337		return this;
5338
5339	}
5340
5341	union(sphere) {
5342
5343		if (sphere.isEmpty()) {
5344
5345			return this;
5346
5347		}
5348
5349		if (this.isEmpty()) {
5350
5351			this.copy(sphere);
5352
5353			return this;
5354
5355		}
5356
5357		if (this.center.equals(sphere.center) === true) {
5358
5359			this.radius = Math.max(this.radius, sphere.radius);
5360
5361		} else {
5362
5363			_v2$3.subVectors(sphere.center, this.center).setLength(sphere.radius);
5364
5365			this.expandByPoint(_v1$6.copy(sphere.center).add(_v2$3));
5366
5367			this.expandByPoint(_v1$6.copy(sphere.center).sub(_v2$3));
5368
5369		}
5370
5371		return this;
5372
5373	}
5374
5375	equals(sphere) {
5376
5377		return sphere.center.equals(this.center) && (sphere.radius === this.radius);
5378
5379	}
5380
5381	clone() {
5382
5383		return new this.constructor().copy(this);
5384
5385	}
5386
5387}
5388
5389const _vector$a = /*@__PURE__*/ new Vector3();
5390const _segCenter = /*@__PURE__*/ new Vector3();
5391const _segDir = /*@__PURE__*/ new Vector3();
5392const _diff = /*@__PURE__*/ new Vector3();
5393
5394const _edge1 = /*@__PURE__*/ new Vector3();
5395const _edge2 = /*@__PURE__*/ new Vector3();
5396const _normal$1 = /*@__PURE__*/ new Vector3();
5397
5398class Ray {
5399
5400	constructor(origin = new Vector3(), direction = new Vector3(0, 0, - 1)) {
5401
5402		this.origin = origin;
5403		this.direction = direction;
5404
5405	}
5406
5407	set(origin, direction) {
5408
5409		this.origin.copy(origin);
5410		this.direction.copy(direction);
5411
5412		return this;
5413
5414	}
5415
5416	copy(ray) {
5417
5418		this.origin.copy(ray.origin);
5419		this.direction.copy(ray.direction);
5420
5421		return this;
5422
5423	}
5424
5425	at(t, target) {
5426
5427		return target.copy(this.origin).addScaledVector(this.direction, t);
5428
5429	}
5430
5431	lookAt(v) {
5432
5433		this.direction.copy(v).sub(this.origin).normalize();
5434
5435		return this;
5436
5437	}
5438
5439	recast(t) {
5440
5441		this.origin.copy(this.at(t, _vector$a));
5442
5443		return this;
5444
5445	}
5446
5447	closestPointToPoint(point, target) {
5448
5449		target.subVectors(point, this.origin);
5450
vendor: 4,268 bytes, lines 5451-5628
5451		const directionDistance = target.dot(this.direction);
5452
5453		if (directionDistance < 0) {
5454
5455			return target.copy(this.origin);
5456
5457		}
5458
5459		return target.copy(this.origin).addScaledVector(this.direction, directionDistance);
5460
5461	}
5462
5463	distanceToPoint(point) {
5464
5465		return Math.sqrt(this.distanceSqToPoint(point));
5466
5467	}
5468
5469	distanceSqToPoint(point) {
5470
5471		const directionDistance = _vector$a.subVectors(point, this.origin).dot(this.direction);
5472
5473		// point behind the ray
5474
5475		if (directionDistance < 0) {
5476
5477			return this.origin.distanceToSquared(point);
5478
5479		}
5480
5481		_vector$a.copy(this.origin).addScaledVector(this.direction, directionDistance);
5482
5483		return _vector$a.distanceToSquared(point);
5484
5485	}
5486
5487	distanceSqToSegment(v0, v1, optionalPointOnRay, optionalPointOnSegment) {
5488
5489		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
5490		// It returns the min distance between the ray and the segment
5491		// defined by v0 and v1
5492		// It can also set two optional targets :
5493		// - The closest point on the ray
5494		// - The closest point on the segment
5495
5496		_segCenter.copy(v0).add(v1).multiplyScalar(0.5);
5497		_segDir.copy(v1).sub(v0).normalize();
5498		_diff.copy(this.origin).sub(_segCenter);
5499
5500		const segExtent = v0.distanceTo(v1) * 0.5;
5501		const a01 = - this.direction.dot(_segDir);
5502		const b0 = _diff.dot(this.direction);
5503		const b1 = - _diff.dot(_segDir);
5504		const c = _diff.lengthSq();
5505		const det = Math.abs(1 - a01 * a01);
5506		let s0, s1, sqrDist, extDet;
5507
5508		if (det > 0) {
5509
5510			// The ray and segment are not parallel.
5511
5512			s0 = a01 * b1 - b0;
5513			s1 = a01 * b0 - b1;
5514			extDet = segExtent * det;
5515
5516			if (s0 >= 0) {
5517
5518				if (s1 >= - extDet) {
5519
5520					if (s1 <= extDet) {
5521
5522						// region 0
5523						// Minimum at interior points of ray and segment.
5524
5525						const invDet = 1 / det;
5526						s0 *= invDet;
5527						s1 *= invDet;
5528						sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c;
5529
5530					} else {
5531
5532						// region 1
5533
5534						s1 = segExtent;
5535						s0 = Math.max(0, - (a01 * s1 + b0));
5536						sqrDist = - s0 * s0 + s1 * (s1 + 2 * b1) + c;
5537
5538					}
5539
5540				} else {
5541
5542					// region 5
5543
5544					s1 = - segExtent;
5545					s0 = Math.max(0, - (a01 * s1 + b0));
5546					sqrDist = - s0 * s0 + s1 * (s1 + 2 * b1) + c;
5547
5548				}
5549
5550			} else {
5551
5552				if (s1 <= - extDet) {
5553
5554					// region 4
5555
5556					s0 = Math.max(0, - (- a01 * segExtent + b0));
5557					s1 = (s0 > 0) ? - segExtent : Math.min(Math.max(- segExtent, - b1), segExtent);
5558					sqrDist = - s0 * s0 + s1 * (s1 + 2 * b1) + c;
5559
5560				} else if (s1 <= extDet) {
5561
5562					// region 3
5563
5564					s0 = 0;
5565					s1 = Math.min(Math.max(- segExtent, - b1), segExtent);
5566					sqrDist = s1 * (s1 + 2 * b1) + c;
5567
5568				} else {
5569
5570					// region 2
5571
5572					s0 = Math.max(0, - (a01 * segExtent + b0));
5573					s1 = (s0 > 0) ? segExtent : Math.min(Math.max(- segExtent, - b1), segExtent);
5574					sqrDist = - s0 * s0 + s1 * (s1 + 2 * b1) + c;
5575
5576				}
5577
5578			}
5579
5580		} else {
5581
5582			// Ray and segment are parallel.
5583
5584			s1 = (a01 > 0) ? - segExtent : segExtent;
5585			s0 = Math.max(0, - (a01 * s1 + b0));
5586			sqrDist = - s0 * s0 + s1 * (s1 + 2 * b1) + c;
5587
5588		}
5589
5590		if (optionalPointOnRay) {
5591
5592			optionalPointOnRay.copy(this.origin).addScaledVector(this.direction, s0);
5593
5594		}
5595
5596		if (optionalPointOnSegment) {
5597
5598			optionalPointOnSegment.copy(_segCenter).addScaledVector(_segDir, s1);
5599
5600		}
5601
5602		return sqrDist;
5603
5604	}
5605
5606	intersectSphere(sphere, target) {
5607
5608		_vector$a.subVectors(sphere.center, this.origin);
5609		const tca = _vector$a.dot(this.direction);
5610		const d2 = _vector$a.dot(_vector$a) - tca * tca;
5611		const radius2 = sphere.radius * sphere.radius;
5612
5613		if (d2 > radius2) return null;
5614
5615		const thc = Math.sqrt(radius2 - d2);
5616
5617		// t0 = first intersect point - entrance on front of sphere
5618		const t0 = tca - thc;
5619
5620		// t1 = second intersect point - exit point on back of sphere
5621		const t1 = tca + thc;
5622
5623		// test to see if t1 is behind the ray - if so, return null
5624		if (t1 < 0) return null;
5625
5626		// test to see if t0 is behind the ray:
5627		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
5628		// in order to always return an intersect point that is in front of the ray.
vendor: 4,218 bytes, lines 5629-5841
5629		if (t0 < 0) return this.at(t1, target);
5630
5631		// else t0 is in front of the ray, so return the first collision point scaled by t0
5632		return this.at(t0, target);
5633
5634	}
5635
5636	intersectsSphere(sphere) {
5637
5638		return this.distanceSqToPoint(sphere.center) <= (sphere.radius * sphere.radius);
5639
5640	}
5641
5642	distanceToPlane(plane) {
5643
5644		const denominator = plane.normal.dot(this.direction);
5645
5646		if (denominator === 0) {
5647
5648			// line is coplanar, return origin
5649			if (plane.distanceToPoint(this.origin) === 0) {
5650
5651				return 0;
5652
5653			}
5654
5655			// Null is preferable to undefined since undefined means.... it is undefined
5656
5657			return null;
5658
5659		}
5660
5661		const t = - (this.origin.dot(plane.normal) + plane.constant) / denominator;
5662
5663		// Return if the ray never intersects the plane
5664
5665		return t >= 0 ? t : null;
5666
5667	}
5668
5669	intersectPlane(plane, target) {
5670
5671		const t = this.distanceToPlane(plane);
5672
5673		if (t === null) {
5674
5675			return null;
5676
5677		}
5678
5679		return this.at(t, target);
5680
5681	}
5682
5683	intersectsPlane(plane) {
5684
5685		// check if the ray lies on the plane first
5686
5687		const distToPoint = plane.distanceToPoint(this.origin);
5688
5689		if (distToPoint === 0) {
5690
5691			return true;
5692
5693		}
5694
5695		const denominator = plane.normal.dot(this.direction);
5696
5697		if (denominator * distToPoint < 0) {
5698
5699			return true;
5700
5701		}
5702
5703		// ray origin is behind the plane (and is pointing behind it)
5704
5705		return false;
5706
5707	}
5708
5709	intersectBox(box, target) {
5710
5711		let tmin, tmax, tymin, tymax, tzmin, tzmax;
5712
5713		const invdirx = 1 / this.direction.x,
5714			invdiry = 1 / this.direction.y,
5715			invdirz = 1 / this.direction.z;
5716
5717		const origin = this.origin;
5718
5719		if (invdirx >= 0) {
5720
5721			tmin = (box.min.x - origin.x) * invdirx;
5722			tmax = (box.max.x - origin.x) * invdirx;
5723
5724		} else {
5725
5726			tmin = (box.max.x - origin.x) * invdirx;
5727			tmax = (box.min.x - origin.x) * invdirx;
5728
5729		}
5730
5731		if (invdiry >= 0) {
5732
5733			tymin = (box.min.y - origin.y) * invdiry;
5734			tymax = (box.max.y - origin.y) * invdiry;
5735
5736		} else {
5737
5738			tymin = (box.max.y - origin.y) * invdiry;
5739			tymax = (box.min.y - origin.y) * invdiry;
5740
5741		}
5742
5743		if ((tmin > tymax) || (tymin > tmax)) return null;
5744
5745		if (tymin > tmin || isNaN(tmin)) tmin = tymin;
5746
5747		if (tymax < tmax || isNaN(tmax)) tmax = tymax;
5748
5749		if (invdirz >= 0) {
5750
5751			tzmin = (box.min.z - origin.z) * invdirz;
5752			tzmax = (box.max.z - origin.z) * invdirz;
5753
5754		} else {
5755
5756			tzmin = (box.max.z - origin.z) * invdirz;
5757			tzmax = (box.min.z - origin.z) * invdirz;
5758
5759		}
5760
5761		if ((tmin > tzmax) || (tzmin > tmax)) return null;
5762
5763		if (tzmin > tmin || tmin !== tmin) tmin = tzmin;
5764
5765		if (tzmax < tmax || tmax !== tmax) tmax = tzmax;
5766
5767		//return point closest to the ray (positive side)
5768
5769		if (tmax < 0) return null;
5770
5771		return this.at(tmin >= 0 ? tmin : tmax, target);
5772
5773	}
5774
5775	intersectsBox(box) {
5776
5777		return this.intersectBox(box, _vector$a) !== null;
5778
5779	}
5780
5781	intersectTriangle(a, b, c, backfaceCulling, target) {
5782
5783		// Compute the offset origin, edges, and normal.
5784
5785		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h
5786
5787		_edge1.subVectors(b, a);
5788		_edge2.subVectors(c, a);
5789		_normal$1.crossVectors(_edge1, _edge2);
5790
5791		// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
5792		// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
5793		//   |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
5794		//   |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
5795		//   |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
5796		let DdN = this.direction.dot(_normal$1);
5797		let sign;
5798
5799		if (DdN > 0) {
5800
5801			if (backfaceCulling) return null;
5802			sign = 1;
5803
5804		} else if (DdN < 0) {
5805
5806			sign = - 1;
5807			DdN = - DdN;
5808
5809		} else {
5810
5811			return null;
5812
5813		}
5814
5815		_diff.subVectors(this.origin, a);
5816		const DdQxE2 = sign * this.direction.dot(_edge2.crossVectors(_diff, _edge2));
5817
5818		// b1 < 0, no intersection
5819		if (DdQxE2 < 0) {
5820
5821			return null;
5822
5823		}
5824
5825		const DdE1xQ = sign * this.direction.dot(_edge1.cross(_diff));
5826
5827		// b2 < 0, no intersection
5828		if (DdE1xQ < 0) {
5829
5830			return null;
5831
5832		}
5833
5834		// b1+b2 > 1, no intersection
5835		if (DdQxE2 + DdE1xQ > DdN) {
5836
5837			return null;
5838
5839		}
5840
5841		// Line intersects triangle, check if ray does.
vendor: 4,722 bytes, lines 5842-6107
5842		const QdN = - sign * _diff.dot(_normal$1);
5843
5844		// t < 0, no intersection
5845		if (QdN < 0) {
5846
5847			return null;
5848
5849		}
5850
5851		// Ray intersects triangle.
5852		return this.at(QdN / DdN, target);
5853
5854	}
5855
5856	applyMatrix4(matrix4) {
5857
5858		this.origin.applyMatrix4(matrix4);
5859		this.direction.transformDirection(matrix4);
5860
5861		return this;
5862
5863	}
5864
5865	equals(ray) {
5866
5867		return ray.origin.equals(this.origin) && ray.direction.equals(this.direction);
5868
5869	}
5870
5871	clone() {
5872
5873		return new this.constructor().copy(this);
5874
5875	}
5876
5877}
5878
5879class Matrix4 {
5880
5881	constructor(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
5882
5883		Matrix4.prototype.isMatrix4 = true;
5884
5885		this.elements = [
5886
5887			1, 0, 0, 0,
5888			0, 1, 0, 0,
5889			0, 0, 1, 0,
5890			0, 0, 0, 1
5891
5892		];
5893
5894		if (n11 !== undefined) {
5895
5896			this.set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44);
5897
5898		}
5899
5900	}
5901
5902	set(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
5903
5904		const te = this.elements;
5905
5906		te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
5907		te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
5908		te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
5909		te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;
5910
5911		return this;
5912
5913	}
5914
5915	identity() {
5916
5917		this.set(
5918
5919			1, 0, 0, 0,
5920			0, 1, 0, 0,
5921			0, 0, 1, 0,
5922			0, 0, 0, 1
5923
5924		);
5925
5926		return this;
5927
5928	}
5929
5930	clone() {
5931
5932		return new Matrix4().fromArray(this.elements);
5933
5934	}
5935
5936	copy(m) {
5937
5938		const te = this.elements;
5939		const me = m.elements;
5940
5941		te[0] = me[0]; te[1] = me[1]; te[2] = me[2]; te[3] = me[3];
5942		te[4] = me[4]; te[5] = me[5]; te[6] = me[6]; te[7] = me[7];
5943		te[8] = me[8]; te[9] = me[9]; te[10] = me[10]; te[11] = me[11];
5944		te[12] = me[12]; te[13] = me[13]; te[14] = me[14]; te[15] = me[15];
5945
5946		return this;
5947
5948	}
5949
5950	copyPosition(m) {
5951
5952		const te = this.elements, me = m.elements;
5953
5954		te[12] = me[12];
5955		te[13] = me[13];
5956		te[14] = me[14];
5957
5958		return this;
5959
5960	}
5961
5962	setFromMatrix3(m) {
5963
5964		const me = m.elements;
5965
5966		this.set(
5967
5968			me[0], me[3], me[6], 0,
5969			me[1], me[4], me[7], 0,
5970			me[2], me[5], me[8], 0,
5971			0, 0, 0, 1
5972
5973		);
5974
5975		return this;
5976
5977	}
5978
5979	extractBasis(xAxis, yAxis, zAxis) {
5980
5981		xAxis.setFromMatrixColumn(this, 0);
5982		yAxis.setFromMatrixColumn(this, 1);
5983		zAxis.setFromMatrixColumn(this, 2);
5984
5985		return this;
5986
5987	}
5988
5989	makeBasis(xAxis, yAxis, zAxis) {
5990
5991		this.set(
5992			xAxis.x, yAxis.x, zAxis.x, 0,
5993			xAxis.y, yAxis.y, zAxis.y, 0,
5994			xAxis.z, yAxis.z, zAxis.z, 0,
5995			0, 0, 0, 1
5996		);
5997
5998		return this;
5999
6000	}
6001
6002	extractRotation(m) {
6003
6004		// this method does not support reflection matrices
6005
6006		const te = this.elements;
6007		const me = m.elements;
6008
6009		const scaleX = 1 / _v1$5.setFromMatrixColumn(m, 0).length();
6010		const scaleY = 1 / _v1$5.setFromMatrixColumn(m, 1).length();
6011		const scaleZ = 1 / _v1$5.setFromMatrixColumn(m, 2).length();
6012
6013		te[0] = me[0] * scaleX;
6014		te[1] = me[1] * scaleX;
6015		te[2] = me[2] * scaleX;
6016		te[3] = 0;
6017
6018		te[4] = me[4] * scaleY;
6019		te[5] = me[5] * scaleY;
6020		te[6] = me[6] * scaleY;
6021		te[7] = 0;
6022
6023		te[8] = me[8] * scaleZ;
6024		te[9] = me[9] * scaleZ;
6025		te[10] = me[10] * scaleZ;
6026		te[11] = 0;
6027
6028		te[12] = 0;
6029		te[13] = 0;
6030		te[14] = 0;
6031		te[15] = 1;
6032
6033		return this;
6034
6035	}
6036
6037	makeRotationFromEuler(euler) {
6038
6039		const te = this.elements;
6040
6041		const x = euler.x, y = euler.y, z = euler.z;
6042		const a = Math.cos(x), b = Math.sin(x);
6043		const c = Math.cos(y), d = Math.sin(y);
6044		const e = Math.cos(z), f = Math.sin(z);
6045
6046		if (euler.order === 'XYZ') {
6047
6048			const ae = a * e, af = a * f, be = b * e, bf = b * f;
6049
6050			te[0] = c * e;
6051			te[4] = - c * f;
6052			te[8] = d;
6053
6054			te[1] = af + be * d;
6055			te[5] = ae - bf * d;
6056			te[9] = - b * c;
6057
6058			te[2] = bf - ae * d;
6059			te[6] = be + af * d;
6060			te[10] = a * c;
6061
6062		} else if (euler.order === 'YXZ') {
6063
6064			const ce = c * e, cf = c * f, de = d * e, df = d * f;
6065
6066			te[0] = ce + df * b;
6067			te[4] = de * b - cf;
6068			te[8] = a * d;
6069
6070			te[1] = a * f;
6071			te[5] = a * e;
6072			te[9] = - b;
6073
6074			te[2] = cf * b - de;
6075			te[6] = df + ce * b;
6076			te[10] = a * c;
6077
6078		} else if (euler.order === 'ZXY') {
6079
6080			const ce = c * e, cf = c * f, de = d * e, df = d * f;
6081
6082			te[0] = ce - df * b;
6083			te[4] = - a * f;
6084			te[8] = de + cf * b;
6085
6086			te[1] = cf + de * b;
6087			te[5] = a * e;
6088			te[9] = df - ce * b;
6089
6090			te[2] = - a * d;
6091			te[6] = b;
6092			te[10] = a * c;
6093
6094		} else if (euler.order === 'ZYX') {
6095
6096			const ae = a * e, af = a * f, be = b * e, bf = b * f;
6097
6098			te[0] = c * e;
6099			te[4] = be * d - af;
6100			te[8] = ae * d + bf;
6101
6102			te[1] = c * f;
6103			te[5] = bf * d + ae;
6104			te[9] = af * d - be;
6105
6106			te[2] = - d;
6107			te[6] = b * c;
vendor: 35,895 bytes, lines 6108-7968
6108			te[10] = a * c;
6109
6110		} else if (euler.order === 'YZX') {
6111
6112			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
6113
6114			te[0] = c * e;
6115			te[4] = bd - ac * f;
6116			te[8] = bc * f + ad;
6117
6118			te[1] = f;
6119			te[5] = a * e;
6120			te[9] = - b * e;
6121
6122			te[2] = - d * e;
6123			te[6] = ad * f + bc;
6124			te[10] = ac - bd * f;
6125
6126		} else if (euler.order === 'XZY') {
6127
6128			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
6129
6130			te[0] = c * e;
6131			te[4] = - f;
6132			te[8] = d * e;
6133
6134			te[1] = ac * f + bd;
6135			te[5] = a * e;
6136			te[9] = ad * f - bc;
6137
6138			te[2] = bc * f - ad;
6139			te[6] = b * e;
6140			te[10] = bd * f + ac;
6141
6142		}
6143
6144		// bottom row
6145		te[3] = 0;
6146		te[7] = 0;
6147		te[11] = 0;
6148
6149		// last column
6150		te[12] = 0;
6151		te[13] = 0;
6152		te[14] = 0;
6153		te[15] = 1;
6154
6155		return this;
6156
6157	}
6158
6159	makeRotationFromQuaternion(q) {
6160
6161		return this.compose(_zero, q, _one);
6162
6163	}
6164
6165	lookAt(eye, target, up) {
6166
6167		const te = this.elements;
6168
6169		_z.subVectors(eye, target);
6170
6171		if (_z.lengthSq() === 0) {
6172
6173			// eye and target are in the same position
6174
6175			_z.z = 1;
6176
6177		}
6178
6179		_z.normalize();
6180		_x.crossVectors(up, _z);
6181
6182		if (_x.lengthSq() === 0) {
6183
6184			// up and z are parallel
6185
6186			if (Math.abs(up.z) === 1) {
6187
6188				_z.x += 0.0001;
6189
6190			} else {
6191
6192				_z.z += 0.0001;
6193
6194			}
6195
6196			_z.normalize();
6197			_x.crossVectors(up, _z);
6198
6199		}
6200
6201		_x.normalize();
6202		_y.crossVectors(_z, _x);
6203
6204		te[0] = _x.x; te[4] = _y.x; te[8] = _z.x;
6205		te[1] = _x.y; te[5] = _y.y; te[9] = _z.y;
6206		te[2] = _x.z; te[6] = _y.z; te[10] = _z.z;
6207
6208		return this;
6209
6210	}
6211
6212	multiply(m) {
6213
6214		return this.multiplyMatrices(this, m);
6215
6216	}
6217
6218	premultiply(m) {
6219
6220		return this.multiplyMatrices(m, this);
6221
6222	}
6223
6224	multiplyMatrices(a, b) {
6225
6226		const ae = a.elements;
6227		const be = b.elements;
6228		const te = this.elements;
6229
6230		const a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
6231		const a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
6232		const a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
6233		const a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];
6234
6235		const b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
6236		const b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
6237		const b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
6238		const b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];
6239
6240		te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
6241		te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
6242		te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
6243		te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
6244
6245		te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
6246		te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
6247		te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
6248		te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
6249
6250		te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
6251		te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
6252		te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
6253		te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
6254
6255		te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
6256		te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
6257		te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
6258		te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
6259
6260		return this;
6261
6262	}
6263
6264	multiplyScalar(s) {
6265
6266		const te = this.elements;
6267
6268		te[0] *= s; te[4] *= s; te[8] *= s; te[12] *= s;
6269		te[1] *= s; te[5] *= s; te[9] *= s; te[13] *= s;
6270		te[2] *= s; te[6] *= s; te[10] *= s; te[14] *= s;
6271		te[3] *= s; te[7] *= s; te[11] *= s; te[15] *= s;
6272
6273		return this;
6274
6275	}
6276
6277	determinant() {
6278
6279		const te = this.elements;
6280
6281		const n11 = te[0], n12 = te[4], n13 = te[8], n14 = te[12];
6282		const n21 = te[1], n22 = te[5], n23 = te[9], n24 = te[13];
6283		const n31 = te[2], n32 = te[6], n33 = te[10], n34 = te[14];
6284		const n41 = te[3], n42 = te[7], n43 = te[11], n44 = te[15];
6285
6286		//TODO: make this more efficient
6287		//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
6288
6289		return (
6290			n41 * (
6291				+ n14 * n23 * n32
6292				- n13 * n24 * n32
6293				- n14 * n22 * n33
6294				+ n12 * n24 * n33
6295				+ n13 * n22 * n34
6296				- n12 * n23 * n34
6297			) +
6298			n42 * (
6299				+ n11 * n23 * n34
6300				- n11 * n24 * n33
6301				+ n14 * n21 * n33
6302				- n13 * n21 * n34
6303				+ n13 * n24 * n31
6304				- n14 * n23 * n31
6305			) +
6306			n43 * (
6307				+ n11 * n24 * n32
6308				- n11 * n22 * n34
6309				- n14 * n21 * n32
6310				+ n12 * n21 * n34
6311				+ n14 * n22 * n31
6312				- n12 * n24 * n31
6313			) +
6314			n44 * (
6315				- n13 * n22 * n31
6316				- n11 * n23 * n32
6317				+ n11 * n22 * n33
6318				+ n13 * n21 * n32
6319				- n12 * n21 * n33
6320				+ n12 * n23 * n31
6321			)
6322
6323		);
6324
6325	}
6326
6327	transpose() {
6328
6329		const te = this.elements;
6330		let tmp;
6331
6332		tmp = te[1]; te[1] = te[4]; te[4] = tmp;
6333		tmp = te[2]; te[2] = te[8]; te[8] = tmp;
6334		tmp = te[6]; te[6] = te[9]; te[9] = tmp;
6335
6336		tmp = te[3]; te[3] = te[12]; te[12] = tmp;
6337		tmp = te[7]; te[7] = te[13]; te[13] = tmp;
6338		tmp = te[11]; te[11] = te[14]; te[14] = tmp;
6339
6340		return this;
6341
6342	}
6343
6344	setPosition(x, y, z) {
6345
6346		const te = this.elements;
6347
6348		if (x.isVector3) {
6349
6350			te[12] = x.x;
6351			te[13] = x.y;
6352			te[14] = x.z;
6353
6354		} else {
6355
6356			te[12] = x;
6357			te[13] = y;
6358			te[14] = z;
6359
6360		}
6361
6362		return this;
6363
6364	}
6365
6366	invert() {
6367
6368		// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
6369		const te = this.elements,
6370
6371			n11 = te[0], n21 = te[1], n31 = te[2], n41 = te[3],
6372			n12 = te[4], n22 = te[5], n32 = te[6], n42 = te[7],
6373			n13 = te[8], n23 = te[9], n33 = te[10], n43 = te[11],
6374			n14 = te[12], n24 = te[13], n34 = te[14], n44 = te[15],
6375
6376			t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
6377			t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
6378			t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
6379			t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
6380
6381		const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
6382
6383		if (det === 0) return this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
6384
6385		const detInv = 1 / det;
6386
6387		te[0] = t11 * detInv;
6388		te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv;
6389		te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv;
6390		te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv;
6391
6392		te[4] = t12 * detInv;
6393		te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv;
6394		te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv;
6395		te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv;
6396
6397		te[8] = t13 * detInv;
6398		te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv;
6399		te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv;
6400		te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv;
6401
6402		te[12] = t14 * detInv;
6403		te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv;
6404		te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv;
6405		te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv;
6406
6407		return this;
6408
6409	}
6410
6411	scale(v) {
6412
6413		const te = this.elements;
6414		const x = v.x, y = v.y, z = v.z;
6415
6416		te[0] *= x; te[4] *= y; te[8] *= z;
6417		te[1] *= x; te[5] *= y; te[9] *= z;
6418		te[2] *= x; te[6] *= y; te[10] *= z;
6419		te[3] *= x; te[7] *= y; te[11] *= z;
6420
6421		return this;
6422
6423	}
6424
6425	getMaxScaleOnAxis() {
6426
6427		const te = this.elements;
6428
6429		const scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
6430		const scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
6431		const scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
6432
6433		return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq));
6434
6435	}
6436
6437	makeTranslation(x, y, z) {
6438
6439		if (x.isVector3) {
6440
6441			this.set(
6442
6443				1, 0, 0, x.x,
6444				0, 1, 0, x.y,
6445				0, 0, 1, x.z,
6446				0, 0, 0, 1
6447
6448			);
6449
6450		} else {
6451
6452			this.set(
6453
6454				1, 0, 0, x,
6455				0, 1, 0, y,
6456				0, 0, 1, z,
6457				0, 0, 0, 1
6458
6459			);
6460
6461		}
6462
6463		return this;
6464
6465	}
6466
6467	makeRotationX(theta) {
6468
6469		const c = Math.cos(theta), s = Math.sin(theta);
6470
6471		this.set(
6472
6473			1, 0, 0, 0,
6474			0, c, - s, 0,
6475			0, s, c, 0,
6476			0, 0, 0, 1
6477
6478		);
6479
6480		return this;
6481
6482	}
6483
6484	makeRotationY(theta) {
6485
6486		const c = Math.cos(theta), s = Math.sin(theta);
6487
6488		this.set(
6489
6490			c, 0, s, 0,
6491			0, 1, 0, 0,
6492			- s, 0, c, 0,
6493			0, 0, 0, 1
6494
6495		);
6496
6497		return this;
6498
6499	}
6500
6501	makeRotationZ(theta) {
6502
6503		const c = Math.cos(theta), s = Math.sin(theta);
6504
6505		this.set(
6506
6507			c, - s, 0, 0,
6508			s, c, 0, 0,
6509			0, 0, 1, 0,
6510			0, 0, 0, 1
6511
6512		);
6513
6514		return this;
6515
6516	}
6517
6518	makeRotationAxis(axis, angle) {
6519
6520		// Based on http://www.gamedev.net/reference/articles/article1199.asp
6521
6522		const c = Math.cos(angle);
6523		const s = Math.sin(angle);
6524		const t = 1 - c;
6525		const x = axis.x, y = axis.y, z = axis.z;
6526		const tx = t * x, ty = t * y;
6527
6528		this.set(
6529
6530			tx * x + c, tx * y - s * z, tx * z + s * y, 0,
6531			tx * y + s * z, ty * y + c, ty * z - s * x, 0,
6532			tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
6533			0, 0, 0, 1
6534
6535		);
6536
6537		return this;
6538
6539	}
6540
6541	makeScale(x, y, z) {
6542
6543		this.set(
6544
6545			x, 0, 0, 0,
6546			0, y, 0, 0,
6547			0, 0, z, 0,
6548			0, 0, 0, 1
6549
6550		);
6551
6552		return this;
6553
6554	}
6555
6556	makeShear(xy, xz, yx, yz, zx, zy) {
6557
6558		this.set(
6559
6560			1, yx, zx, 0,
6561			xy, 1, zy, 0,
6562			xz, yz, 1, 0,
6563			0, 0, 0, 1
6564
6565		);
6566
6567		return this;
6568
6569	}
6570
6571	compose(position, quaternion, scale) {
6572
6573		const te = this.elements;
6574
6575		const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
6576		const x2 = x + x, y2 = y + y, z2 = z + z;
6577		const xx = x * x2, xy = x * y2, xz = x * z2;
6578		const yy = y * y2, yz = y * z2, zz = z * z2;
6579		const wx = w * x2, wy = w * y2, wz = w * z2;
6580
6581		const sx = scale.x, sy = scale.y, sz = scale.z;
6582
6583		te[0] = (1 - (yy + zz)) * sx;
6584		te[1] = (xy + wz) * sx;
6585		te[2] = (xz - wy) * sx;
6586		te[3] = 0;
6587
6588		te[4] = (xy - wz) * sy;
6589		te[5] = (1 - (xx + zz)) * sy;
6590		te[6] = (yz + wx) * sy;
6591		te[7] = 0;
6592
6593		te[8] = (xz + wy) * sz;
6594		te[9] = (yz - wx) * sz;
6595		te[10] = (1 - (xx + yy)) * sz;
6596		te[11] = 0;
6597
6598		te[12] = position.x;
6599		te[13] = position.y;
6600		te[14] = position.z;
6601		te[15] = 1;
6602
6603		return this;
6604
6605	}
6606
6607	decompose(position, quaternion, scale) {
6608
6609		const te = this.elements;
6610
6611		let sx = _v1$5.set(te[0], te[1], te[2]).length();
6612		const sy = _v1$5.set(te[4], te[5], te[6]).length();
6613		const sz = _v1$5.set(te[8], te[9], te[10]).length();
6614
6615		// if determine is negative, we need to invert one scale
6616		const det = this.determinant();
6617		if (det < 0) sx = - sx;
6618
6619		position.x = te[12];
6620		position.y = te[13];
6621		position.z = te[14];
6622
6623		// scale the rotation part
6624		_m1$2.copy(this);
6625
6626		const invSX = 1 / sx;
6627		const invSY = 1 / sy;
6628		const invSZ = 1 / sz;
6629
6630		_m1$2.elements[0] *= invSX;
6631		_m1$2.elements[1] *= invSX;
6632		_m1$2.elements[2] *= invSX;
6633
6634		_m1$2.elements[4] *= invSY;
6635		_m1$2.elements[5] *= invSY;
6636		_m1$2.elements[6] *= invSY;
6637
6638		_m1$2.elements[8] *= invSZ;
6639		_m1$2.elements[9] *= invSZ;
6640		_m1$2.elements[10] *= invSZ;
6641
6642		quaternion.setFromRotationMatrix(_m1$2);
6643
6644		scale.x = sx;
6645		scale.y = sy;
6646		scale.z = sz;
6647
6648		return this;
6649
6650	}
6651
6652	makePerspective(left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem) {
6653
6654		const te = this.elements;
6655		const x = 2 * near / (right - left);
6656		const y = 2 * near / (top - bottom);
6657
6658		const a = (right + left) / (right - left);
6659		const b = (top + bottom) / (top - bottom);
6660
6661		let c, d;
6662
6663		if (coordinateSystem === WebGLCoordinateSystem) {
6664
6665			c = - (far + near) / (far - near);
6666			d = (- 2 * far * near) / (far - near);
6667
6668		} else if (coordinateSystem === WebGPUCoordinateSystem) {
6669
6670			c = - far / (far - near);
6671			d = (- far * near) / (far - near);
6672
6673		} else {
6674
6675			throw new Error('THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem);
6676
6677		}
6678
6679		te[0] = x; te[4] = 0; te[8] = a; te[12] = 0;
6680		te[1] = 0; te[5] = y; te[9] = b; te[13] = 0;
6681		te[2] = 0; te[6] = 0; te[10] = c; te[14] = d;
6682		te[3] = 0; te[7] = 0; te[11] = - 1; te[15] = 0;
6683
6684		return this;
6685
6686	}
6687
6688	makeOrthographic(left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem) {
6689
6690		const te = this.elements;
6691		const w = 1.0 / (right - left);
6692		const h = 1.0 / (top - bottom);
6693		const p = 1.0 / (far - near);
6694
6695		const x = (right + left) * w;
6696		const y = (top + bottom) * h;
6697
6698		let z, zInv;
6699
6700		if (coordinateSystem === WebGLCoordinateSystem) {
6701
6702			z = (far + near) * p;
6703			zInv = - 2 * p;
6704
6705		} else if (coordinateSystem === WebGPUCoordinateSystem) {
6706
6707			z = near * p;
6708			zInv = - 1 * p;
6709
6710		} else {
6711
6712			throw new Error('THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem);
6713
6714		}
6715
6716		te[0] = 2 * w; te[4] = 0; te[8] = 0; te[12] = - x;
6717		te[1] = 0; te[5] = 2 * h; te[9] = 0; te[13] = - y;
6718		te[2] = 0; te[6] = 0; te[10] = zInv; te[14] = - z;
6719		te[3] = 0; te[7] = 0; te[11] = 0; te[15] = 1;
6720
6721		return this;
6722
6723	}
6724
6725	equals(matrix) {
6726
6727		const te = this.elements;
6728		const me = matrix.elements;
6729
6730		for (let i = 0; i < 16; i++) {
6731
6732			if (te[i] !== me[i]) return false;
6733
6734		}
6735
6736		return true;
6737
6738	}
6739
6740	fromArray(array, offset = 0) {
6741
6742		for (let i = 0; i < 16; i++) {
6743
6744			this.elements[i] = array[i + offset];
6745
6746		}
6747
6748		return this;
6749
6750	}
6751
6752	toArray(array = [], offset = 0) {
6753
6754		const te = this.elements;
6755
6756		array[offset] = te[0];
6757		array[offset + 1] = te[1];
6758		array[offset + 2] = te[2];
6759		array[offset + 3] = te[3];
6760
6761		array[offset + 4] = te[4];
6762		array[offset + 5] = te[5];
6763		array[offset + 6] = te[6];
6764		array[offset + 7] = te[7];
6765
6766		array[offset + 8] = te[8];
6767		array[offset + 9] = te[9];
6768		array[offset + 10] = te[10];
6769		array[offset + 11] = te[11];
6770
6771		array[offset + 12] = te[12];
6772		array[offset + 13] = te[13];
6773		array[offset + 14] = te[14];
6774		array[offset + 15] = te[15];
6775
6776		return array;
6777
6778	}
6779
6780}
6781
6782const _v1$5 = /*@__PURE__*/ new Vector3();
6783const _m1$2 = /*@__PURE__*/ new Matrix4();
6784const _zero = /*@__PURE__*/ new Vector3(0, 0, 0);
6785const _one = /*@__PURE__*/ new Vector3(1, 1, 1);
6786const _x = /*@__PURE__*/ new Vector3();
6787const _y = /*@__PURE__*/ new Vector3();
6788const _z = /*@__PURE__*/ new Vector3();
6789
6790const _matrix$1 = /*@__PURE__*/ new Matrix4();
6791const _quaternion$3 = /*@__PURE__*/ new Quaternion();
6792
6793class Euler {
6794
6795	constructor(x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER) {
6796
6797		this.isEuler = true;
6798
6799		this._x = x;
6800		this._y = y;
6801		this._z = z;
6802		this._order = order;
6803
6804	}
6805
6806	get x() {
6807
6808		return this._x;
6809
6810	}
6811
6812	set x(value) {
6813
6814		this._x = value;
6815		this._onChangeCallback();
6816
6817	}
6818
6819	get y() {
6820
6821		return this._y;
6822
6823	}
6824
6825	set y(value) {
6826
6827		this._y = value;
6828		this._onChangeCallback();
6829
6830	}
6831
6832	get z() {
6833
6834		return this._z;
6835
6836	}
6837
6838	set z(value) {
6839
6840		this._z = value;
6841		this._onChangeCallback();
6842
6843	}
6844
6845	get order() {
6846
6847		return this._order;
6848
6849	}
6850
6851	set order(value) {
6852
6853		this._order = value;
6854		this._onChangeCallback();
6855
6856	}
6857
6858	set(x, y, z, order = this._order) {
6859
6860		this._x = x;
6861		this._y = y;
6862		this._z = z;
6863		this._order = order;
6864
6865		this._onChangeCallback();
6866
6867		return this;
6868
6869	}
6870
6871	clone() {
6872
6873		return new this.constructor(this._x, this._y, this._z, this._order);
6874
6875	}
6876
6877	copy(euler) {
6878
6879		this._x = euler._x;
6880		this._y = euler._y;
6881		this._z = euler._z;
6882		this._order = euler._order;
6883
6884		this._onChangeCallback();
6885
6886		return this;
6887
6888	}
6889
6890	setFromRotationMatrix(m, order = this._order, update = true) {
6891
6892		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
6893
6894		const te = m.elements;
6895		const m11 = te[0], m12 = te[4], m13 = te[8];
6896		const m21 = te[1], m22 = te[5], m23 = te[9];
6897		const m31 = te[2], m32 = te[6], m33 = te[10];
6898
6899		switch (order) {
6900
6901			case 'XYZ':
6902
6903				this._y = Math.asin(clamp(m13, - 1, 1));
6904
6905				if (Math.abs(m13) < 0.9999999) {
6906
6907					this._x = Math.atan2(- m23, m33);
6908					this._z = Math.atan2(- m12, m11);
6909
6910				} else {
6911
6912					this._x = Math.atan2(m32, m22);
6913					this._z = 0;
6914
6915				}
6916
6917				break;
6918
6919			case 'YXZ':
6920
6921				this._x = Math.asin(- clamp(m23, - 1, 1));
6922
6923				if (Math.abs(m23) < 0.9999999) {
6924
6925					this._y = Math.atan2(m13, m33);
6926					this._z = Math.atan2(m21, m22);
6927
6928				} else {
6929
6930					this._y = Math.atan2(- m31, m11);
6931					this._z = 0;
6932
6933				}
6934
6935				break;
6936
6937			case 'ZXY':
6938
6939				this._x = Math.asin(clamp(m32, - 1, 1));
6940
6941				if (Math.abs(m32) < 0.9999999) {
6942
6943					this._y = Math.atan2(- m31, m33);
6944					this._z = Math.atan2(- m12, m22);
6945
6946				} else {
6947
6948					this._y = 0;
6949					this._z = Math.atan2(m21, m11);
6950
6951				}
6952
6953				break;
6954
6955			case 'ZYX':
6956
6957				this._y = Math.asin(- clamp(m31, - 1, 1));
6958
6959				if (Math.abs(m31) < 0.9999999) {
6960
6961					this._x = Math.atan2(m32, m33);
6962					this._z = Math.atan2(m21, m11);
6963
6964				} else {
6965
6966					this._x = 0;
6967					this._z = Math.atan2(- m12, m22);
6968
6969				}
6970
6971				break;
6972
6973			case 'YZX':
6974
6975				this._z = Math.asin(clamp(m21, - 1, 1));
6976
6977				if (Math.abs(m21) < 0.9999999) {
6978
6979					this._x = Math.atan2(- m23, m22);
6980					this._y = Math.atan2(- m31, m11);
6981
6982				} else {
6983
6984					this._x = 0;
6985					this._y = Math.atan2(m13, m33);
6986
6987				}
6988
6989				break;
6990
6991			case 'XZY':
6992
6993				this._z = Math.asin(- clamp(m12, - 1, 1));
6994
6995				if (Math.abs(m12) < 0.9999999) {
6996
6997					this._x = Math.atan2(m32, m22);
6998					this._y = Math.atan2(m13, m11);
6999
7000				} else {
7001
7002					this._x = Math.atan2(- m23, m33);
7003					this._y = 0;
7004
7005				}
7006
7007				break;
7008
7009			default:
7010
7011				console.warn('THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order);
7012
7013		}
7014
7015		this._order = order;
7016
7017		if (update === true) this._onChangeCallback();
7018
7019		return this;
7020
7021	}
7022
7023	setFromQuaternion(q, order, update) {
7024
7025		_matrix$1.makeRotationFromQuaternion(q);
7026
7027		return this.setFromRotationMatrix(_matrix$1, order, update);
7028
7029	}
7030
7031	setFromVector3(v, order = this._order) {
7032
7033		return this.set(v.x, v.y, v.z, order);
7034
7035	}
7036
7037	reorder(newOrder) {
7038
7039		// WARNING: this discards revolution information -bhouston
7040
7041		_quaternion$3.setFromEuler(this);
7042
7043		return this.setFromQuaternion(_quaternion$3, newOrder);
7044
7045	}
7046
7047	equals(euler) {
7048
7049		return (euler._x === this._x) && (euler._y === this._y) && (euler._z === this._z) && (euler._order === this._order);
7050
7051	}
7052
7053	fromArray(array) {
7054
7055		this._x = array[0];
7056		this._y = array[1];
7057		this._z = array[2];
7058		if (array[3] !== undefined) this._order = array[3];
7059
7060		this._onChangeCallback();
7061
7062		return this;
7063
7064	}
7065
7066	toArray(array = [], offset = 0) {
7067
7068		array[offset] = this._x;
7069		array[offset + 1] = this._y;
7070		array[offset + 2] = this._z;
7071		array[offset + 3] = this._order;
7072
7073		return array;
7074
7075	}
7076
7077	_onChange(callback) {
7078
7079		this._onChangeCallback = callback;
7080
7081		return this;
7082
7083	}
7084
7085	_onChangeCallback() { }
7086
7087	*[Symbol.iterator]() {
7088
7089		yield this._x;
7090		yield this._y;
7091		yield this._z;
7092		yield this._order;
7093
7094	}
7095
7096}
7097
7098Euler.DEFAULT_ORDER = 'XYZ';
7099
7100class Layers {
7101
7102	constructor() {
7103
7104		this.mask = 1 | 0;
7105
7106	}
7107
7108	set(channel) {
7109
7110		this.mask = (1 << channel | 0) >>> 0;
7111
7112	}
7113
7114	enable(channel) {
7115
7116		this.mask |= 1 << channel | 0;
7117
7118	}
7119
7120	enableAll() {
7121
7122		this.mask = 0xffffffff | 0;
7123
7124	}
7125
7126	toggle(channel) {
7127
7128		this.mask ^= 1 << channel | 0;
7129
7130	}
7131
7132	disable(channel) {
7133
7134		this.mask &= ~(1 << channel | 0);
7135
7136	}
7137
7138	disableAll() {
7139
7140		this.mask = 0;
7141
7142	}
7143
7144	test(layers) {
7145
7146		return (this.mask & layers.mask) !== 0;
7147
7148	}
7149
7150	isEnabled(channel) {
7151
7152		return (this.mask & (1 << channel | 0)) !== 0;
7153
7154	}
7155
7156}
7157
7158let _object3DId = 0;
7159
7160const _v1$4 = /*@__PURE__*/ new Vector3();
7161const _q1 = /*@__PURE__*/ new Quaternion();
7162const _m1$1 = /*@__PURE__*/ new Matrix4();
7163const _target = /*@__PURE__*/ new Vector3();
7164
7165const _position$3 = /*@__PURE__*/ new Vector3();
7166const _scale$2 = /*@__PURE__*/ new Vector3();
7167const _quaternion$2 = /*@__PURE__*/ new Quaternion();
7168
7169const _xAxis = /*@__PURE__*/ new Vector3(1, 0, 0);
7170const _yAxis = /*@__PURE__*/ new Vector3(0, 1, 0);
7171const _zAxis = /*@__PURE__*/ new Vector3(0, 0, 1);
7172
7173const _addedEvent = { type: 'added' };
7174const _removedEvent = { type: 'removed' };
7175
7176class Object3D extends EventDispatcher {
7177
7178	constructor() {
7179
7180		super();
7181
7182		this.isObject3D = true;
7183
7184		Object.defineProperty(this, 'id', { value: _object3DId++ });
7185
7186		this.uuid = generateUUID();
7187
7188		this.name = '';
7189		this.type = 'Object3D';
7190
7191		this.parent = null;
7192		this.children = [];
7193
7194		this.up = Object3D.DEFAULT_UP.clone();
7195
7196		const position = new Vector3();
7197		const rotation = new Euler();
7198		const quaternion = new Quaternion();
7199		const scale = new Vector3(1, 1, 1);
7200
7201		function onRotationChange() {
7202
7203			quaternion.setFromEuler(rotation, false);
7204
7205		}
7206
7207		function onQuaternionChange() {
7208
7209			rotation.setFromQuaternion(quaternion, undefined, false);
7210
7211		}
7212
7213		rotation._onChange(onRotationChange);
7214		quaternion._onChange(onQuaternionChange);
7215
7216		Object.defineProperties(this, {
7217			position: {
7218				configurable: true,
7219				enumerable: true,
7220				value: position
7221			},
7222			rotation: {
7223				configurable: true,
7224				enumerable: true,
7225				value: rotation
7226			},
7227			quaternion: {
7228				configurable: true,
7229				enumerable: true,
7230				value: quaternion
7231			},
7232			scale: {
7233				configurable: true,
7234				enumerable: true,
7235				value: scale
7236			},
7237			modelViewMatrix: {
7238				value: new Matrix4()
7239			},
7240			normalMatrix: {
7241				value: new Matrix3()
7242			}
7243		});
7244
7245		this.matrix = new Matrix4();
7246		this.matrixWorld = new Matrix4();
7247
7248		this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
7249
7250		this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
7251		this.matrixWorldNeedsUpdate = false;
7252
7253		this.layers = new Layers();
7254		this.visible = true;
7255
7256		this.castShadow = false;
7257		this.receiveShadow = false;
7258
7259		this.frustumCulled = true;
7260		this.renderOrder = 0;
7261
7262		this.animations = [];
7263
7264		this.userData = {};
7265
7266	}
7267
7268	onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */) { }
7269
7270	onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */) { }
7271
7272	onBeforeRender( /* renderer, scene, camera, geometry, material, group */) { }
7273
7274	onAfterRender( /* renderer, scene, camera, geometry, material, group */) { }
7275
7276	applyMatrix4(matrix) {
7277
7278		if (this.matrixAutoUpdate) this.updateMatrix();
7279
7280		this.matrix.premultiply(matrix);
7281
7282		this.matrix.decompose(this.position, this.quaternion, this.scale);
7283
7284	}
7285
7286	applyQuaternion(q) {
7287
7288		this.quaternion.premultiply(q);
7289
7290		return this;
7291
7292	}
7293
7294	setRotationFromAxisAngle(axis, angle) {
7295
7296		// assumes axis is normalized
7297
7298		this.quaternion.setFromAxisAngle(axis, angle);
7299
7300	}
7301
7302	setRotationFromEuler(euler) {
7303
7304		this.quaternion.setFromEuler(euler, true);
7305
7306	}
7307
7308	setRotationFromMatrix(m) {
7309
7310		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
7311
7312		this.quaternion.setFromRotationMatrix(m);
7313
7314	}
7315
7316	setRotationFromQuaternion(q) {
7317
7318		// assumes q is normalized
7319
7320		this.quaternion.copy(q);
7321
7322	}
7323
7324	rotateOnAxis(axis, angle) {
7325
7326		// rotate object on axis in object space
7327		// axis is assumed to be normalized
7328
7329		_q1.setFromAxisAngle(axis, angle);
7330
7331		this.quaternion.multiply(_q1);
7332
7333		return this;
7334
7335	}
7336
7337	rotateOnWorldAxis(axis, angle) {
7338
7339		// rotate object on axis in world space
7340		// axis is assumed to be normalized
7341		// method assumes no rotated parent
7342
7343		_q1.setFromAxisAngle(axis, angle);
7344
7345		this.quaternion.premultiply(_q1);
7346
7347		return this;
7348
7349	}
7350
7351	rotateX(angle) {
7352
7353		return this.rotateOnAxis(_xAxis, angle);
7354
7355	}
7356
7357	rotateY(angle) {
7358
7359		return this.rotateOnAxis(_yAxis, angle);
7360
7361	}
7362
7363	rotateZ(angle) {
7364
7365		return this.rotateOnAxis(_zAxis, angle);
7366
7367	}
7368
7369	translateOnAxis(axis, distance) {
7370
7371		// translate object by distance along axis in object space
7372		// axis is assumed to be normalized
7373
7374		_v1$4.copy(axis).applyQuaternion(this.quaternion);
7375
7376		this.position.add(_v1$4.multiplyScalar(distance));
7377
7378		return this;
7379
7380	}
7381
7382	translateX(distance) {
7383
7384		return this.translateOnAxis(_xAxis, distance);
7385
7386	}
7387
7388	translateY(distance) {
7389
7390		return this.translateOnAxis(_yAxis, distance);
7391
7392	}
7393
7394	translateZ(distance) {
7395
7396		return this.translateOnAxis(_zAxis, distance);
7397
7398	}
7399
7400	localToWorld(vector) {
7401
7402		this.updateWorldMatrix(true, false);
7403
7404		return vector.applyMatrix4(this.matrixWorld);
7405
7406	}
7407
7408	worldToLocal(vector) {
7409
7410		this.updateWorldMatrix(true, false);
7411
7412		return vector.applyMatrix4(_m1$1.copy(this.matrixWorld).invert());
7413
7414	}
7415
7416	lookAt(x, y, z) {
7417
7418		// This method does not support objects having non-uniformly-scaled parent(s)
7419
7420		if (x.isVector3) {
7421
7422			_target.copy(x);
7423
7424		} else {
7425
7426			_target.set(x, y, z);
7427
7428		}
7429
7430		const parent = this.parent;
7431
7432		this.updateWorldMatrix(true, false);
7433
7434		_position$3.setFromMatrixPosition(this.matrixWorld);
7435
7436		if (this.isCamera || this.isLight) {
7437
7438			_m1$1.lookAt(_position$3, _target, this.up);
7439
7440		} else {
7441
7442			_m1$1.lookAt(_target, _position$3, this.up);
7443
7444		}
7445
7446		this.quaternion.setFromRotationMatrix(_m1$1);
7447
7448		if (parent) {
7449
7450			_m1$1.extractRotation(parent.matrixWorld);
7451			_q1.setFromRotationMatrix(_m1$1);
7452			this.quaternion.premultiply(_q1.invert());
7453
7454		}
7455
7456	}
7457
7458	add(object) {
7459
7460		if (arguments.length > 1) {
7461
7462			for (let i = 0; i < arguments.length; i++) {
7463
7464				this.add(arguments[i]);
7465
7466			}
7467
7468			return this;
7469
7470		}
7471
7472		if (object === this) {
7473
7474			console.error('THREE.Object3D.add: object can\'t be added as a child of itself.', object);
7475			return this;
7476
7477		}
7478
7479		if (object && object.isObject3D) {
7480
7481			if (object.parent !== null) {
7482
7483				object.parent.remove(object);
7484
7485			}
7486
7487			object.parent = this;
7488			this.children.push(object);
7489
7490			object.dispatchEvent(_addedEvent);
7491
7492		} else {
7493
7494			console.error('THREE.Object3D.add: object not an instance of THREE.Object3D.', object);
7495
7496		}
7497
7498		return this;
7499
7500	}
7501
7502	remove(object) {
7503
7504		if (arguments.length > 1) {
7505
7506			for (let i = 0; i < arguments.length; i++) {
7507
7508				this.remove(arguments[i]);
7509
7510			}
7511
7512			return this;
7513
7514		}
7515
7516		const index = this.children.indexOf(object);
7517
7518		if (index !== - 1) {
7519
7520			object.parent = null;
7521			this.children.splice(index, 1);
7522
7523			object.dispatchEvent(_removedEvent);
7524
7525		}
7526
7527		return this;
7528
7529	}
7530
7531	removeFromParent() {
7532
7533		const parent = this.parent;
7534
7535		if (parent !== null) {
7536
7537			parent.remove(this);
7538
7539		}
7540
7541		return this;
7542
7543	}
7544
7545	clear() {
7546
7547		return this.remove(... this.children);
7548
7549	}
7550
7551	attach(object) {
7552
7553		// adds object as a child of this, while maintaining the object's world transform
7554
7555		// Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
7556
7557		this.updateWorldMatrix(true, false);
7558
7559		_m1$1.copy(this.matrixWorld).invert();
7560
7561		if (object.parent !== null) {
7562
7563			object.parent.updateWorldMatrix(true, false);
7564
7565			_m1$1.multiply(object.parent.matrixWorld);
7566
7567		}
7568
7569		object.applyMatrix4(_m1$1);
7570
7571		this.add(object);
7572
7573		object.updateWorldMatrix(false, true);
7574
7575		return this;
7576
7577	}
7578
7579	getObjectById(id) {
7580
7581		return this.getObjectByProperty('id', id);
7582
7583	}
7584
7585	getObjectByName(name) {
7586
7587		return this.getObjectByProperty('name', name);
7588
7589	}
7590
7591	getObjectByProperty(name, value) {
7592
7593		if (this[name] === value) return this;
7594
7595		for (let i = 0, l = this.children.length; i < l; i++) {
7596
7597			const child = this.children[i];
7598			const object = child.getObjectByProperty(name, value);
7599
7600			if (object !== undefined) {
7601
7602				return object;
7603
7604			}
7605
7606		}
7607
7608		return undefined;
7609
7610	}
7611
7612	getObjectsByProperty(name, value, result = []) {
7613
7614		if (this[name] === value) result.push(this);
7615
7616		const children = this.children;
7617
7618		for (let i = 0, l = children.length; i < l; i++) {
7619
7620			children[i].getObjectsByProperty(name, value, result);
7621
7622		}
7623
7624		return result;
7625
7626	}
7627
7628	getWorldPosition(target) {
7629
7630		this.updateWorldMatrix(true, false);
7631
7632		return target.setFromMatrixPosition(this.matrixWorld);
7633
7634	}
7635
7636	getWorldQuaternion(target) {
7637
7638		this.updateWorldMatrix(true, false);
7639
7640		this.matrixWorld.decompose(_position$3, target, _scale$2);
7641
7642		return target;
7643
7644	}
7645
7646	getWorldScale(target) {
7647
7648		this.updateWorldMatrix(true, false);
7649
7650		this.matrixWorld.decompose(_position$3, _quaternion$2, target);
7651
7652		return target;
7653
7654	}
7655
7656	getWorldDirection(target) {
7657
7658		this.updateWorldMatrix(true, false);
7659
7660		const e = this.matrixWorld.elements;
7661
7662		return target.set(e[8], e[9], e[10]).normalize();
7663
7664	}
7665
7666	raycast( /* raycaster, intersects */) { }
7667
7668	traverse(callback) {
7669
7670		callback(this);
7671
7672		const children = this.children;
7673
7674		for (let i = 0, l = children.length; i < l; i++) {
7675
7676			children[i].traverse(callback);
7677
7678		}
7679
7680	}
7681
7682	traverseVisible(callback) {
7683
7684		if (this.visible === false) return;
7685
7686		callback(this);
7687
7688		const children = this.children;
7689
7690		for (let i = 0, l = children.length; i < l; i++) {
7691
7692			children[i].traverseVisible(callback);
7693
7694		}
7695
7696	}
7697
7698	traverseAncestors(callback) {
7699
7700		const parent = this.parent;
7701
7702		if (parent !== null) {
7703
7704			callback(parent);
7705
7706			parent.traverseAncestors(callback);
7707
7708		}
7709
7710	}
7711
7712	updateMatrix() {
7713
7714		this.matrix.compose(this.position, this.quaternion, this.scale);
7715
7716		this.matrixWorldNeedsUpdate = true;
7717
7718	}
7719
7720	updateMatrixWorld(force) {
7721
7722		if (this.matrixAutoUpdate) this.updateMatrix();
7723
7724		if (this.matrixWorldNeedsUpdate || force) {
7725
7726			if (this.parent === null) {
7727
7728				this.matrixWorld.copy(this.matrix);
7729
7730			} else {
7731
7732				this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
7733
7734			}
7735
7736			this.matrixWorldNeedsUpdate = false;
7737
7738			force = true;
7739
7740		}
7741
7742		// update children
7743
7744		const children = this.children;
7745
7746		for (let i = 0, l = children.length; i < l; i++) {
7747
7748			const child = children[i];
7749
7750			if (child.matrixWorldAutoUpdate === true || force === true) {
7751
7752				child.updateMatrixWorld(force);
7753
7754			}
7755
7756		}
7757
7758	}
7759
7760	updateWorldMatrix(updateParents, updateChildren) {
7761
7762		const parent = this.parent;
7763
7764		if (updateParents === true && parent !== null && parent.matrixWorldAutoUpdate === true) {
7765
7766			parent.updateWorldMatrix(true, false);
7767
7768		}
7769
7770		if (this.matrixAutoUpdate) this.updateMatrix();
7771
7772		if (this.parent === null) {
7773
7774			this.matrixWorld.copy(this.matrix);
7775
7776		} else {
7777
7778			this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
7779
7780		}
7781
7782		// update children
7783
7784		if (updateChildren === true) {
7785
7786			const children = this.children;
7787
7788			for (let i = 0, l = children.length; i < l; i++) {
7789
7790				const child = children[i];
7791
7792				if (child.matrixWorldAutoUpdate === true) {
7793
7794					child.updateWorldMatrix(false, true);
7795
7796				}
7797
7798			}
7799
7800		}
7801
7802	}
7803
7804	toJSON(meta) {
7805
7806		// meta is a string when called from JSON.stringify
7807		const isRootObject = (meta === undefined || typeof meta === 'string');
7808
7809		const output = {};
7810
7811		// meta is a hash used to collect geometries, materials.
7812		// not providing it implies that this is the root object
7813		// being serialized.
7814		if (isRootObject) {
7815
7816			// initialize meta obj
7817			meta = {
7818				geometries: {},
7819				materials: {},
7820				textures: {},
7821				images: {},
7822				shapes: {},
7823				skeletons: {},
7824				animations: {},
7825				nodes: {}
7826			};
7827
7828			output.metadata = {
7829				version: 4.6,
7830				type: 'Object',
7831				generator: 'Object3D.toJSON'
7832			};
7833
7834		}
7835
7836		// standard Object3D serialization
7837
7838		const object = {};
7839
7840		object.uuid = this.uuid;
7841		object.type = this.type;
7842
7843		if (this.name !== '') object.name = this.name;
7844		if (this.castShadow === true) object.castShadow = true;
7845		if (this.receiveShadow === true) object.receiveShadow = true;
7846		if (this.visible === false) object.visible = false;
7847		if (this.frustumCulled === false) object.frustumCulled = false;
7848		if (this.renderOrder !== 0) object.renderOrder = this.renderOrder;
7849		if (Object.keys(this.userData).length > 0) object.userData = this.userData;
7850
7851		object.layers = this.layers.mask;
7852		object.matrix = this.matrix.toArray();
7853		object.up = this.up.toArray();
7854
7855		if (this.matrixAutoUpdate === false) object.matrixAutoUpdate = false;
7856
7857		// object specific properties
7858
7859		if (this.isInstancedMesh) {
7860
7861			object.type = 'InstancedMesh';
7862			object.count = this.count;
7863			object.instanceMatrix = this.instanceMatrix.toJSON();
7864			if (this.instanceColor !== null) object.instanceColor = this.instanceColor.toJSON();
7865
7866		}
7867
7868		if (this.isBatchedMesh) {
7869
7870			object.type = 'BatchedMesh';
7871			object.perObjectFrustumCulled = this.perObjectFrustumCulled;
7872			object.sortObjects = this.sortObjects;
7873
7874			object.drawRanges = this._drawRanges;
7875			object.reservedRanges = this._reservedRanges;
7876
7877			object.visibility = this._visibility;
7878			object.active = this._active;
7879			object.bounds = this._bounds.map(bound => ({
7880				boxInitialized: bound.boxInitialized,
7881				boxMin: bound.box.min.toArray(),
7882				boxMax: bound.box.max.toArray(),
7883
7884				sphereInitialized: bound.sphereInitialized,
7885				sphereRadius: bound.sphere.radius,
7886				sphereCenter: bound.sphere.center.toArray()
7887			}));
7888
7889			object.maxGeometryCount = this._maxGeometryCount;
7890			object.maxVertexCount = this._maxVertexCount;
7891			object.maxIndexCount = this._maxIndexCount;
7892
7893			object.geometryInitialized = this._geometryInitialized;
7894			object.geometryCount = this._geometryCount;
7895
7896			object.matricesTexture = this._matricesTexture.toJSON(meta);
7897
7898			if (this.boundingSphere !== null) {
7899
7900				object.boundingSphere = {
7901					center: object.boundingSphere.center.toArray(),
7902					radius: object.boundingSphere.radius
7903				};
7904
7905			}
7906
7907			if (this.boundingBox !== null) {
7908
7909				object.boundingBox = {
7910					min: object.boundingBox.min.toArray(),
7911					max: object.boundingBox.max.toArray()
7912				};
7913
7914			}
7915
7916		}
7917
7918		//
7919
7920		function serialize(library, element) {
7921
7922			if (library[element.uuid] === undefined) {
7923
7924				library[element.uuid] = element.toJSON(meta);
7925
7926			}
7927
7928			return element.uuid;
7929
7930		}
7931
7932		if (this.isScene) {
7933
7934			if (this.background) {
7935
7936				if (this.background.isColor) {
7937
7938					object.background = this.background.toJSON();
7939
7940				} else if (this.background.isTexture) {
7941
7942					object.background = this.background.toJSON(meta).uuid;
7943
7944				}
7945
7946			}
7947
7948			if (this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true) {
7949
7950				object.environment = this.environment.toJSON(meta).uuid;
7951
7952			}
7953
7954		} else if (this.isMesh || this.isLine || this.isPoints) {
7955
7956			object.geometry = serialize(meta.geometries, this.geometry);
7957
7958			const parameters = this.geometry.parameters;
7959
7960			if (parameters !== undefined && parameters.shapes !== undefined) {
7961
7962				const shapes = parameters.shapes;
7963
7964				if (Array.isArray(shapes)) {
7965
7966					for (let i = 0, l = shapes.length; i < l; i++) {
7967
7968						const shape = shapes[i];
vendor: 9,257 bytes, lines 7969-8412
7969
7970						serialize(meta.shapes, shape);
7971
7972					}
7973
7974				} else {
7975
7976					serialize(meta.shapes, shapes);
7977
7978				}
7979
7980			}
7981
7982		}
7983
7984		if (this.isSkinnedMesh) {
7985
7986			object.bindMode = this.bindMode;
7987			object.bindMatrix = this.bindMatrix.toArray();
7988
7989			if (this.skeleton !== undefined) {
7990
7991				serialize(meta.skeletons, this.skeleton);
7992
7993				object.skeleton = this.skeleton.uuid;
7994
7995			}
7996
7997		}
7998
7999		if (this.material !== undefined) {
8000
8001			if (Array.isArray(this.material)) {
8002
8003				const uuids = [];
8004
8005				for (let i = 0, l = this.material.length; i < l; i++) {
8006
8007					uuids.push(serialize(meta.materials, this.material[i]));
8008
8009				}
8010
8011				object.material = uuids;
8012
8013			} else {
8014
8015				object.material = serialize(meta.materials, this.material);
8016
8017			}
8018
8019		}
8020
8021		//
8022
8023		if (this.children.length > 0) {
8024
8025			object.children = [];
8026
8027			for (let i = 0; i < this.children.length; i++) {
8028
8029				object.children.push(this.children[i].toJSON(meta).object);
8030
8031			}
8032
8033		}
8034
8035		//
8036
8037		if (this.animations.length > 0) {
8038
8039			object.animations = [];
8040
8041			for (let i = 0; i < this.animations.length; i++) {
8042
8043				const animation = this.animations[i];
8044
8045				object.animations.push(serialize(meta.animations, animation));
8046
8047			}
8048
8049		}
8050
8051		if (isRootObject) {
8052
8053			const geometries = extractFromCache(meta.geometries);
8054			const materials = extractFromCache(meta.materials);
8055			const textures = extractFromCache(meta.textures);
8056			const images = extractFromCache(meta.images);
8057			const shapes = extractFromCache(meta.shapes);
8058			const skeletons = extractFromCache(meta.skeletons);
8059			const animations = extractFromCache(meta.animations);
8060			const nodes = extractFromCache(meta.nodes);
8061
8062			if (geometries.length > 0) output.geometries = geometries;
8063			if (materials.length > 0) output.materials = materials;
8064			if (textures.length > 0) output.textures = textures;
8065			if (images.length > 0) output.images = images;
8066			if (shapes.length > 0) output.shapes = shapes;
8067			if (skeletons.length > 0) output.skeletons = skeletons;
8068			if (animations.length > 0) output.animations = animations;
8069			if (nodes.length > 0) output.nodes = nodes;
8070
8071		}
8072
8073		output.object = object;
8074
8075		return output;
8076
8077		// extract data from the cache hash
8078		// remove metadata on each item
8079		// and return as array
8080		function extractFromCache(cache) {
8081
8082			const values = [];
8083			for (const key in cache) {
8084
8085				const data = cache[key];
8086				delete data.metadata;
8087				values.push(data);
8088
8089			}
8090
8091			return values;
8092
8093		}
8094
8095	}
8096
8097	clone(recursive) {
8098
8099		return new this.constructor().copy(this, recursive);
8100
8101	}
8102
8103	copy(source, recursive = true) {
8104
8105		this.name = source.name;
8106
8107		this.up.copy(source.up);
8108
8109		this.position.copy(source.position);
8110		this.rotation.order = source.rotation.order;
8111		this.quaternion.copy(source.quaternion);
8112		this.scale.copy(source.scale);
8113
8114		this.matrix.copy(source.matrix);
8115		this.matrixWorld.copy(source.matrixWorld);
8116
8117		this.matrixAutoUpdate = source.matrixAutoUpdate;
8118
8119		this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
8120		this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
8121
8122		this.layers.mask = source.layers.mask;
8123		this.visible = source.visible;
8124
8125		this.castShadow = source.castShadow;
8126		this.receiveShadow = source.receiveShadow;
8127
8128		this.frustumCulled = source.frustumCulled;
8129		this.renderOrder = source.renderOrder;
8130
8131		this.animations = source.animations.slice();
8132
8133		this.userData = JSON.parse(JSON.stringify(source.userData));
8134
8135		if (recursive === true) {
8136
8137			for (let i = 0; i < source.children.length; i++) {
8138
8139				const child = source.children[i];
8140				this.add(child.clone());
8141
8142			}
8143
8144		}
8145
8146		return this;
8147
8148	}
8149
8150}
8151
8152Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3(0, 1, 0);
8153Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
8154Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
8155
8156const _v0$1 = /*@__PURE__*/ new Vector3();
8157const _v1$3 = /*@__PURE__*/ new Vector3();
8158const _v2$2 = /*@__PURE__*/ new Vector3();
8159const _v3$1 = /*@__PURE__*/ new Vector3();
8160
8161const _vab = /*@__PURE__*/ new Vector3();
8162const _vac = /*@__PURE__*/ new Vector3();
8163const _vbc = /*@__PURE__*/ new Vector3();
8164const _vap = /*@__PURE__*/ new Vector3();
8165const _vbp = /*@__PURE__*/ new Vector3();
8166const _vcp = /*@__PURE__*/ new Vector3();
8167
8168let warnedGetUV = false;
8169
8170class Triangle {
8171
8172	constructor(a = new Vector3(), b = new Vector3(), c = new Vector3()) {
8173
8174		this.a = a;
8175		this.b = b;
8176		this.c = c;
8177
8178	}
8179
8180	static getNormal(a, b, c, target) {
8181
8182		target.subVectors(c, b);
8183		_v0$1.subVectors(a, b);
8184		target.cross(_v0$1);
8185
8186		const targetLengthSq = target.lengthSq();
8187		if (targetLengthSq > 0) {
8188
8189			return target.multiplyScalar(1 / Math.sqrt(targetLengthSq));
8190
8191		}
8192
8193		return target.set(0, 0, 0);
8194
8195	}
8196
8197	// static/instance method to calculate barycentric coordinates
8198	// based on: http://www.blackpawn.com/texts/pointinpoly/default.html
8199	static getBarycoord(point, a, b, c, target) {
8200
8201		_v0$1.subVectors(c, a);
8202		_v1$3.subVectors(b, a);
8203		_v2$2.subVectors(point, a);
8204
8205		const dot00 = _v0$1.dot(_v0$1);
8206		const dot01 = _v0$1.dot(_v1$3);
8207		const dot02 = _v0$1.dot(_v2$2);
8208		const dot11 = _v1$3.dot(_v1$3);
8209		const dot12 = _v1$3.dot(_v2$2);
8210
8211		const denom = (dot00 * dot11 - dot01 * dot01);
8212
8213		// collinear or singular triangle
8214		if (denom === 0) {
8215
8216			target.set(0, 0, 0);
8217			return null;
8218
8219		}
8220
8221		const invDenom = 1 / denom;
8222		const u = (dot11 * dot02 - dot01 * dot12) * invDenom;
8223		const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
8224
8225		// barycentric coordinates must always sum to 1
8226		return target.set(1 - u - v, v, u);
8227
8228	}
8229
8230	static containsPoint(point, a, b, c) {
8231
8232		// if the triangle is degenerate then we can't contain a point
8233		if (this.getBarycoord(point, a, b, c, _v3$1) === null) {
8234
8235			return false;
8236
8237		}
8238
8239		return (_v3$1.x >= 0) && (_v3$1.y >= 0) && ((_v3$1.x + _v3$1.y) <= 1);
8240
8241	}
8242
8243	static getUV(point, p1, p2, p3, uv1, uv2, uv3, target) { // @deprecated, r151
8244
8245		if (warnedGetUV === false) {
8246
8247			console.warn('THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().');
8248
8249			warnedGetUV = true;
8250
8251		}
8252
8253		return this.getInterpolation(point, p1, p2, p3, uv1, uv2, uv3, target);
8254
8255	}
8256
8257	static getInterpolation(point, p1, p2, p3, v1, v2, v3, target) {
8258
8259		if (this.getBarycoord(point, p1, p2, p3, _v3$1) === null) {
8260
8261			target.x = 0;
8262			target.y = 0;
8263			if ('z' in target) target.z = 0;
8264			if ('w' in target) target.w = 0;
8265			return null;
8266
8267		}
8268
8269		target.setScalar(0);
8270		target.addScaledVector(v1, _v3$1.x);
8271		target.addScaledVector(v2, _v3$1.y);
8272		target.addScaledVector(v3, _v3$1.z);
8273
8274		return target;
8275
8276	}
8277
8278	static isFrontFacing(a, b, c, direction) {
8279
8280		_v0$1.subVectors(c, b);
8281		_v1$3.subVectors(a, b);
8282
8283		// strictly front facing
8284		return (_v0$1.cross(_v1$3).dot(direction) < 0) ? true : false;
8285
8286	}
8287
8288	set(a, b, c) {
8289
8290		this.a.copy(a);
8291		this.b.copy(b);
8292		this.c.copy(c);
8293
8294		return this;
8295
8296	}
8297
8298	setFromPointsAndIndices(points, i0, i1, i2) {
8299
8300		this.a.copy(points[i0]);
8301		this.b.copy(points[i1]);
8302		this.c.copy(points[i2]);
8303
8304		return this;
8305
8306	}
8307
8308	setFromAttributeAndIndices(attribute, i0, i1, i2) {
8309
8310		this.a.fromBufferAttribute(attribute, i0);
8311		this.b.fromBufferAttribute(attribute, i1);
8312		this.c.fromBufferAttribute(attribute, i2);
8313
8314		return this;
8315
8316	}
8317
8318	clone() {
8319
8320		return new this.constructor().copy(this);
8321
8322	}
8323
8324	copy(triangle) {
8325
8326		this.a.copy(triangle.a);
8327		this.b.copy(triangle.b);
8328		this.c.copy(triangle.c);
8329
8330		return this;
8331
8332	}
8333
8334	getArea() {
8335
8336		_v0$1.subVectors(this.c, this.b);
8337		_v1$3.subVectors(this.a, this.b);
8338
8339		return _v0$1.cross(_v1$3).length() * 0.5;
8340
8341	}
8342
8343	getMidpoint(target) {
8344
8345		return target.addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3);
8346
8347	}
8348
8349	getNormal(target) {
8350
8351		return Triangle.getNormal(this.a, this.b, this.c, target);
8352
8353	}
8354
8355	getPlane(target) {
8356
8357		return target.setFromCoplanarPoints(this.a, this.b, this.c);
8358
8359	}
8360
8361	getBarycoord(point, target) {
8362
8363		return Triangle.getBarycoord(point, this.a, this.b, this.c, target);
8364
8365	}
8366
8367	getUV(point, uv1, uv2, uv3, target) { // @deprecated, r151
8368
8369		if (warnedGetUV === false) {
8370
8371			console.warn('THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().');
8372
8373			warnedGetUV = true;
8374
8375		}
8376
8377		return Triangle.getInterpolation(point, this.a, this.b, this.c, uv1, uv2, uv3, target);
8378
8379	}
8380
8381	getInterpolation(point, v1, v2, v3, target) {
8382
8383		return Triangle.getInterpolation(point, this.a, this.b, this.c, v1, v2, v3, target);
8384
8385	}
8386
8387	containsPoint(point) {
8388
8389		return Triangle.containsPoint(point, this.a, this.b, this.c);
8390
8391	}
8392
8393	isFrontFacing(direction) {
8394
8395		return Triangle.isFrontFacing(this.a, this.b, this.c, direction);
8396
8397	}
8398
8399	intersectsBox(box) {
8400
8401		return box.intersectsTriangle(this);
8402
8403	}
8404
8405	closestPointToPoint(p, target) {
8406
8407		const a = this.a, b = this.b, c = this.c;
8408		let v, w;
8409
8410		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
8411		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
8412		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
vendor: 26,380 bytes, lines 8413-9456
8413		// basically, we're distinguishing which of the voronoi regions of the triangle
8414		// the point lies in with the minimum amount of redundant computation.
8415
8416		_vab.subVectors(b, a);
8417		_vac.subVectors(c, a);
8418		_vap.subVectors(p, a);
8419		const d1 = _vab.dot(_vap);
8420		const d2 = _vac.dot(_vap);
8421		if (d1 <= 0 && d2 <= 0) {
8422
8423			// vertex region of A; barycentric coords (1, 0, 0)
8424			return target.copy(a);
8425
8426		}
8427
8428		_vbp.subVectors(p, b);
8429		const d3 = _vab.dot(_vbp);
8430		const d4 = _vac.dot(_vbp);
8431		if (d3 >= 0 && d4 <= d3) {
8432
8433			// vertex region of B; barycentric coords (0, 1, 0)
8434			return target.copy(b);
8435
8436		}
8437
8438		const vc = d1 * d4 - d3 * d2;
8439		if (vc <= 0 && d1 >= 0 && d3 <= 0) {
8440
8441			v = d1 / (d1 - d3);
8442			// edge region of AB; barycentric coords (1-v, v, 0)
8443			return target.copy(a).addScaledVector(_vab, v);
8444
8445		}
8446
8447		_vcp.subVectors(p, c);
8448		const d5 = _vab.dot(_vcp);
8449		const d6 = _vac.dot(_vcp);
8450		if (d6 >= 0 && d5 <= d6) {
8451
8452			// vertex region of C; barycentric coords (0, 0, 1)
8453			return target.copy(c);
8454
8455		}
8456
8457		const vb = d5 * d2 - d1 * d6;
8458		if (vb <= 0 && d2 >= 0 && d6 <= 0) {
8459
8460			w = d2 / (d2 - d6);
8461			// edge region of AC; barycentric coords (1-w, 0, w)
8462			return target.copy(a).addScaledVector(_vac, w);
8463
8464		}
8465
8466		const va = d3 * d6 - d5 * d4;
8467		if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
8468
8469			_vbc.subVectors(c, b);
8470			w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
8471			// edge region of BC; barycentric coords (0, 1-w, w)
8472			return target.copy(b).addScaledVector(_vbc, w); // edge region of BC
8473
8474		}
8475
8476		// face region
8477		const denom = 1 / (va + vb + vc);
8478		// u = va * denom
8479		v = vb * denom;
8480		w = vc * denom;
8481
8482		return target.copy(a).addScaledVector(_vab, v).addScaledVector(_vac, w);
8483
8484	}
8485
8486	equals(triangle) {
8487
8488		return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c);
8489
8490	}
8491
8492}
8493
8494const _colorKeywords = {
8495	'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
8496	'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
8497	'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
8498	'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
8499	'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
8500	'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
8501	'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
8502	'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
8503	'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
8504	'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
8505	'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
8506	'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
8507	'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
8508	'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
8509	'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
8510	'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
8511	'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
8512	'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
8513	'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
8514	'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
8515	'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
8516	'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
8517	'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
8518	'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32
8519};
8520
8521const _hslA = { h: 0, s: 0, l: 0 };
8522const _hslB = { h: 0, s: 0, l: 0 };
8523
8524function hue2rgb(p, q, t) {
8525
8526	if (t < 0) t += 1;
8527	if (t > 1) t -= 1;
8528	if (t < 1 / 6) return p + (q - p) * 6 * t;
8529	if (t < 1 / 2) return q;
8530	if (t < 2 / 3) return p + (q - p) * 6 * (2 / 3 - t);
8531	return p;
8532
8533}
8534
8535class Color {
8536
8537	constructor(r, g, b) {
8538
8539		this.isColor = true;
8540
8541		this.r = 1;
8542		this.g = 1;
8543		this.b = 1;
8544
8545		return this.set(r, g, b);
8546
8547	}
8548
8549	set(r, g, b) {
8550
8551		if (g === undefined && b === undefined) {
8552
8553			// r is THREE.Color, hex or string
8554
8555			const value = r;
8556
8557			if (value && value.isColor) {
8558
8559				this.copy(value);
8560
8561			} else if (typeof value === 'number') {
8562
8563				this.setHex(value);
8564
8565			} else if (typeof value === 'string') {
8566
8567				this.setStyle(value);
8568
8569			}
8570
8571		} else {
8572
8573			this.setRGB(r, g, b);
8574
8575		}
8576
8577		return this;
8578
8579	}
8580
8581	setScalar(scalar) {
8582
8583		this.r = scalar;
8584		this.g = scalar;
8585		this.b = scalar;
8586
8587		return this;
8588
8589	}
8590
8591	setHex(hex, colorSpace = SRGBColorSpace) {
8592
8593		hex = Math.floor(hex);
8594
8595		this.r = (hex >> 16 & 255) / 255;
8596		this.g = (hex >> 8 & 255) / 255;
8597		this.b = (hex & 255) / 255;
8598
8599		ColorManagement.toWorkingColorSpace(this, colorSpace);
8600
8601		return this;
8602
8603	}
8604
8605	setRGB(r, g, b, colorSpace = ColorManagement.workingColorSpace) {
8606
8607		this.r = r;
8608		this.g = g;
8609		this.b = b;
8610
8611		ColorManagement.toWorkingColorSpace(this, colorSpace);
8612
8613		return this;
8614
8615	}
8616
8617	setHSL(h, s, l, colorSpace = ColorManagement.workingColorSpace) {
8618
8619		// h,s,l ranges are in 0.0 - 1.0
8620		h = euclideanModulo(h, 1);
8621		s = clamp(s, 0, 1);
8622		l = clamp(l, 0, 1);
8623
8624		if (s === 0) {
8625
8626			this.r = this.g = this.b = l;
8627
8628		} else {
8629
8630			const p = l <= 0.5 ? l * (1 + s) : l + s - (l * s);
8631			const q = (2 * l) - p;
8632
8633			this.r = hue2rgb(q, p, h + 1 / 3);
8634			this.g = hue2rgb(q, p, h);
8635			this.b = hue2rgb(q, p, h - 1 / 3);
8636
8637		}
8638
8639		ColorManagement.toWorkingColorSpace(this, colorSpace);
8640
8641		return this;
8642
8643	}
8644
8645	setStyle(style, colorSpace = SRGBColorSpace) {
8646
8647		function handleAlpha(string) {
8648
8649			if (string === undefined) return;
8650
8651			if (parseFloat(string) < 1) {
8652
8653				console.warn('THREE.Color: Alpha component of ' + style + ' will be ignored.');
8654
8655			}
8656
8657		}
8658
8659
8660		let m;
8661
8662		if (m = /^(\w+)\(([^\)]*)\)/.exec(style)) {
8663
8664			// rgb / hsl
8665
8666			let color;
8667			const name = m[1];
8668			const components = m[2];
8669
8670			switch (name) {
8671
8672				case 'rgb':
8673				case 'rgba':
8674
8675					if (color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
8676
8677						// rgb(255,0,0) rgba(255,0,0,0.5)
8678
8679						handleAlpha(color[4]);
8680
8681						return this.setRGB(
8682							Math.min(255, parseInt(color[1], 10)) / 255,
8683							Math.min(255, parseInt(color[2], 10)) / 255,
8684							Math.min(255, parseInt(color[3], 10)) / 255,
8685							colorSpace
8686						);
8687
8688					}
8689
8690					if (color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
8691
8692						// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
8693
8694						handleAlpha(color[4]);
8695
8696						return this.setRGB(
8697							Math.min(100, parseInt(color[1], 10)) / 100,
8698							Math.min(100, parseInt(color[2], 10)) / 100,
8699							Math.min(100, parseInt(color[3], 10)) / 100,
8700							colorSpace
8701						);
8702
8703					}
8704
8705					break;
8706
8707				case 'hsl':
8708				case 'hsla':
8709
8710					if (color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components)) {
8711
8712						// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
8713
8714						handleAlpha(color[4]);
8715
8716						return this.setHSL(
8717							parseFloat(color[1]) / 360,
8718							parseFloat(color[2]) / 100,
8719							parseFloat(color[3]) / 100,
8720							colorSpace
8721						);
8722
8723					}
8724
8725					break;
8726
8727				default:
8728
8729					console.warn('THREE.Color: Unknown color model ' + style);
8730
8731			}
8732
8733		} else if (m = /^\#([A-Fa-f\d]+)$/.exec(style)) {
8734
8735			// hex color
8736
8737			const hex = m[1];
8738			const size = hex.length;
8739
8740			if (size === 3) {
8741
8742				// #ff0
8743				return this.setRGB(
8744					parseInt(hex.charAt(0), 16) / 15,
8745					parseInt(hex.charAt(1), 16) / 15,
8746					parseInt(hex.charAt(2), 16) / 15,
8747					colorSpace
8748				);
8749
8750			} else if (size === 6) {
8751
8752				// #ff0000
8753				return this.setHex(parseInt(hex, 16), colorSpace);
8754
8755			} else {
8756
8757				console.warn('THREE.Color: Invalid hex color ' + style);
8758
8759			}
8760
8761		} else if (style && style.length > 0) {
8762
8763			return this.setColorName(style, colorSpace);
8764
8765		}
8766
8767		return this;
8768
8769	}
8770
8771	setColorName(style, colorSpace = SRGBColorSpace) {
8772
8773		// color keywords
8774		const hex = _colorKeywords[style.toLowerCase()];
8775
8776		if (hex !== undefined) {
8777
8778			// red
8779			this.setHex(hex, colorSpace);
8780
8781		} else {
8782
8783			// unknown color
8784			console.warn('THREE.Color: Unknown color ' + style);
8785
8786		}
8787
8788		return this;
8789
8790	}
8791
8792	clone() {
8793
8794		return new this.constructor(this.r, this.g, this.b);
8795
8796	}
8797
8798	copy(color) {
8799
8800		this.r = color.r;
8801		this.g = color.g;
8802		this.b = color.b;
8803
8804		return this;
8805
8806	}
8807
8808	copySRGBToLinear(color) {
8809
8810		this.r = SRGBToLinear(color.r);
8811		this.g = SRGBToLinear(color.g);
8812		this.b = SRGBToLinear(color.b);
8813
8814		return this;
8815
8816	}
8817
8818	copyLinearToSRGB(color) {
8819
8820		this.r = LinearToSRGB(color.r);
8821		this.g = LinearToSRGB(color.g);
8822		this.b = LinearToSRGB(color.b);
8823
8824		return this;
8825
8826	}
8827
8828	convertSRGBToLinear() {
8829
8830		this.copySRGBToLinear(this);
8831
8832		return this;
8833
8834	}
8835
8836	convertLinearToSRGB() {
8837
8838		this.copyLinearToSRGB(this);
8839
8840		return this;
8841
8842	}
8843
8844	getHex(colorSpace = SRGBColorSpace) {
8845
8846		ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);
8847
8848		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));
8849
8850	}
8851
8852	getHexString(colorSpace = SRGBColorSpace) {
8853
8854		return ('000000' + this.getHex(colorSpace).toString(16)).slice(- 6);
8855
8856	}
8857
8858	getHSL(target, colorSpace = ColorManagement.workingColorSpace) {
8859
8860		// h,s,l ranges are in 0.0 - 1.0
8861
8862		ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);
8863
8864		const r = _color.r, g = _color.g, b = _color.b;
8865
8866		const max = Math.max(r, g, b);
8867		const min = Math.min(r, g, b);
8868
8869		let hue, saturation;
8870		const lightness = (min + max) / 2.0;
8871
8872		if (min === max) {
8873
8874			hue = 0;
8875			saturation = 0;
8876
8877		} else {
8878
8879			const delta = max - min;
8880
8881			saturation = lightness <= 0.5 ? delta / (max + min) : delta / (2 - max - min);
8882
8883			switch (max) {
8884
8885				case r: hue = (g - b) / delta + (g < b ? 6 : 0); break;
8886				case g: hue = (b - r) / delta + 2; break;
8887				case b: hue = (r - g) / delta + 4; break;
8888
8889			}
8890
8891			hue /= 6;
8892
8893		}
8894
8895		target.h = hue;
8896		target.s = saturation;
8897		target.l = lightness;
8898
8899		return target;
8900
8901	}
8902
8903	getRGB(target, colorSpace = ColorManagement.workingColorSpace) {
8904
8905		ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);
8906
8907		target.r = _color.r;
8908		target.g = _color.g;
8909		target.b = _color.b;
8910
8911		return target;
8912
8913	}
8914
8915	getStyle(colorSpace = SRGBColorSpace) {
8916
8917		ColorManagement.fromWorkingColorSpace(_color.copy(this), colorSpace);
8918
8919		const r = _color.r, g = _color.g, b = _color.b;
8920
8921		if (colorSpace !== SRGBColorSpace) {
8922
8923			// Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
8924			return `color(${colorSpace} ${r.toFixed(3)} ${g.toFixed(3)} ${b.toFixed(3)})`;
8925
8926		}
8927
8928		return `rgb(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)})`;
8929
8930	}
8931
8932	offsetHSL(h, s, l) {
8933
8934		this.getHSL(_hslA);
8935
8936		return this.setHSL(_hslA.h + h, _hslA.s + s, _hslA.l + l);
8937
8938	}
8939
8940	add(color) {
8941
8942		this.r += color.r;
8943		this.g += color.g;
8944		this.b += color.b;
8945
8946		return this;
8947
8948	}
8949
8950	addColors(color1, color2) {
8951
8952		this.r = color1.r + color2.r;
8953		this.g = color1.g + color2.g;
8954		this.b = color1.b + color2.b;
8955
8956		return this;
8957
8958	}
8959
8960	addScalar(s) {
8961
8962		this.r += s;
8963		this.g += s;
8964		this.b += s;
8965
8966		return this;
8967
8968	}
8969
8970	sub(color) {
8971
8972		this.r = Math.max(0, this.r - color.r);
8973		this.g = Math.max(0, this.g - color.g);
8974		this.b = Math.max(0, this.b - color.b);
8975
8976		return this;
8977
8978	}
8979
8980	multiply(color) {
8981
8982		this.r *= color.r;
8983		this.g *= color.g;
8984		this.b *= color.b;
8985
8986		return this;
8987
8988	}
8989
8990	multiplyScalar(s) {
8991
8992		this.r *= s;
8993		this.g *= s;
8994		this.b *= s;
8995
8996		return this;
8997
8998	}
8999
9000	lerp(color, alpha) {
9001
9002		this.r += (color.r - this.r) * alpha;
9003		this.g += (color.g - this.g) * alpha;
9004		this.b += (color.b - this.b) * alpha;
9005
9006		return this;
9007
9008	}
9009
9010	lerpColors(color1, color2, alpha) {
9011
9012		this.r = color1.r + (color2.r - color1.r) * alpha;
9013		this.g = color1.g + (color2.g - color1.g) * alpha;
9014		this.b = color1.b + (color2.b - color1.b) * alpha;
9015
9016		return this;
9017
9018	}
9019
9020	lerpHSL(color, alpha) {
9021
9022		this.getHSL(_hslA);
9023		color.getHSL(_hslB);
9024
9025		const h = lerp(_hslA.h, _hslB.h, alpha);
9026		const s = lerp(_hslA.s, _hslB.s, alpha);
9027		const l = lerp(_hslA.l, _hslB.l, alpha);
9028
9029		this.setHSL(h, s, l);
9030
9031		return this;
9032
9033	}
9034
9035	setFromVector3(v) {
9036
9037		this.r = v.x;
9038		this.g = v.y;
9039		this.b = v.z;
9040
9041		return this;
9042
9043	}
9044
9045	applyMatrix3(m) {
9046
9047		const r = this.r, g = this.g, b = this.b;
9048		const e = m.elements;
9049
9050		this.r = e[0] * r + e[3] * g + e[6] * b;
9051		this.g = e[1] * r + e[4] * g + e[7] * b;
9052		this.b = e[2] * r + e[5] * g + e[8] * b;
9053
9054		return this;
9055
9056	}
9057
9058	equals(c) {
9059
9060		return (c.r === this.r) && (c.g === this.g) && (c.b === this.b);
9061
9062	}
9063
9064	fromArray(array, offset = 0) {
9065
9066		this.r = array[offset];
9067		this.g = array[offset + 1];
9068		this.b = array[offset + 2];
9069
9070		return this;
9071
9072	}
9073
9074	toArray(array = [], offset = 0) {
9075
9076		array[offset] = this.r;
9077		array[offset + 1] = this.g;
9078		array[offset + 2] = this.b;
9079
9080		return array;
9081
9082	}
9083
9084	fromBufferAttribute(attribute, index) {
9085
9086		this.r = attribute.getX(index);
9087		this.g = attribute.getY(index);
9088		this.b = attribute.getZ(index);
9089
9090		return this;
9091
9092	}
9093
9094	toJSON() {
9095
9096		return this.getHex();
9097
9098	}
9099
9100	*[Symbol.iterator]() {
9101
9102		yield this.r;
9103		yield this.g;
9104		yield this.b;
9105
9106	}
9107
9108}
9109
9110const _color = /*@__PURE__*/ new Color();
9111
9112Color.NAMES = _colorKeywords;
9113
9114let _materialId = 0;
9115
9116class Material extends EventDispatcher {
9117
9118	constructor() {
9119
9120		super();
9121
9122		this.isMaterial = true;
9123
9124		Object.defineProperty(this, 'id', { value: _materialId++ });
9125
9126		this.uuid = generateUUID();
9127
9128		this.name = '';
9129		this.type = 'Material';
9130
9131		this.blending = NormalBlending;
9132		this.side = FrontSide;
9133		this.vertexColors = false;
9134
9135		this.opacity = 1;
9136		this.transparent = false;
9137		this.alphaHash = false;
9138
9139		this.blendSrc = SrcAlphaFactor;
9140		this.blendDst = OneMinusSrcAlphaFactor;
9141		this.blendEquation = AddEquation;
9142		this.blendSrcAlpha = null;
9143		this.blendDstAlpha = null;
9144		this.blendEquationAlpha = null;
9145		this.blendColor = new Color(0, 0, 0);
9146		this.blendAlpha = 0;
9147
9148		this.depthFunc = LessEqualDepth;
9149		this.depthTest = true;
9150		this.depthWrite = true;
9151
9152		this.stencilWriteMask = 0xff;
9153		this.stencilFunc = AlwaysStencilFunc;
9154		this.stencilRef = 0;
9155		this.stencilFuncMask = 0xff;
9156		this.stencilFail = KeepStencilOp;
9157		this.stencilZFail = KeepStencilOp;
9158		this.stencilZPass = KeepStencilOp;
9159		this.stencilWrite = false;
9160
9161		this.clippingPlanes = null;
9162		this.clipIntersection = false;
9163		this.clipShadows = false;
9164
9165		this.shadowSide = null;
9166
9167		this.colorWrite = true;
9168
9169		this.precision = null; // override the renderer's default precision for this material
9170
9171		this.polygonOffset = false;
9172		this.polygonOffsetFactor = 0;
9173		this.polygonOffsetUnits = 0;
9174
9175		this.dithering = false;
9176
9177		this.alphaToCoverage = false;
9178		this.premultipliedAlpha = false;
9179		this.forceSinglePass = false;
9180
9181		this.visible = true;
9182
9183		this.toneMapped = true;
9184
9185		this.userData = {};
9186
9187		this.version = 0;
9188
9189		this._alphaTest = 0;
9190
9191	}
9192
9193	get alphaTest() {
9194
9195		return this._alphaTest;
9196
9197	}
9198
9199	set alphaTest(value) {
9200
9201		if (this._alphaTest > 0 !== value > 0) {
9202
9203			this.version++;
9204
9205		}
9206
9207		this._alphaTest = value;
9208
9209	}
9210
9211	onBuild( /* shaderobject, renderer */) { }
9212
9213	onBeforeRender( /* renderer, scene, camera, geometry, object, group */) { }
9214
9215	onBeforeCompile( /* shaderobject, renderer */) { }
9216
9217	customProgramCacheKey() {
9218
9219		return this.onBeforeCompile.toString();
9220
9221	}
9222
9223	setValues(values) {
9224
9225		if (values === undefined) return;
9226
9227		for (const key in values) {
9228
9229			const newValue = values[key];
9230
9231			if (newValue === undefined) {
9232
9233				console.warn(`THREE.Material: parameter '${key}' has value of undefined.`);
9234				continue;
9235
9236			}
9237
9238			const currentValue = this[key];
9239
9240			if (currentValue === undefined) {
9241
9242				console.warn(`THREE.Material: '${key}' is not a property of THREE.${this.type}.`);
9243				continue;
9244
9245			}
9246
9247			if (currentValue && currentValue.isColor) {
9248
9249				currentValue.set(newValue);
9250
9251			} else if ((currentValue && currentValue.isVector3) && (newValue && newValue.isVector3)) {
9252
9253				currentValue.copy(newValue);
9254
9255			} else {
9256
9257				this[key] = newValue;
9258
9259			}
9260
9261		}
9262
9263	}
9264
9265	toJSON(meta) {
9266
9267		const isRootObject = (meta === undefined || typeof meta === 'string');
9268
9269		if (isRootObject) {
9270
9271			meta = {
9272				textures: {},
9273				images: {}
9274			};
9275
9276		}
9277
9278		const data = {
9279			metadata: {
9280				version: 4.6,
9281				type: 'Material',
9282				generator: 'Material.toJSON'
9283			}
9284		};
9285
9286		// standard Material serialization
9287		data.uuid = this.uuid;
9288		data.type = this.type;
9289
9290		if (this.name !== '') data.name = this.name;
9291
9292		if (this.color && this.color.isColor) data.color = this.color.getHex();
9293
9294		if (this.roughness !== undefined) data.roughness = this.roughness;
9295		if (this.metalness !== undefined) data.metalness = this.metalness;
9296
9297		if (this.sheen !== undefined) data.sheen = this.sheen;
9298		if (this.sheenColor && this.sheenColor.isColor) data.sheenColor = this.sheenColor.getHex();
9299		if (this.sheenRoughness !== undefined) data.sheenRoughness = this.sheenRoughness;
9300		if (this.emissive && this.emissive.isColor) data.emissive = this.emissive.getHex();
9301		if (this.emissiveIntensity && this.emissiveIntensity !== 1) data.emissiveIntensity = this.emissiveIntensity;
9302
9303		if (this.specular && this.specular.isColor) data.specular = this.specular.getHex();
9304		if (this.specularIntensity !== undefined) data.specularIntensity = this.specularIntensity;
9305		if (this.specularColor && this.specularColor.isColor) data.specularColor = this.specularColor.getHex();
9306		if (this.shininess !== undefined) data.shininess = this.shininess;
9307		if (this.clearcoat !== undefined) data.clearcoat = this.clearcoat;
9308		if (this.clearcoatRoughness !== undefined) data.clearcoatRoughness = this.clearcoatRoughness;
9309
9310		if (this.clearcoatMap && this.clearcoatMap.isTexture) {
9311
9312			data.clearcoatMap = this.clearcoatMap.toJSON(meta).uuid;
9313
9314		}
9315
9316		if (this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture) {
9317
9318			data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON(meta).uuid;
9319
9320		}
9321
9322		if (this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture) {
9323
9324			data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON(meta).uuid;
9325			data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
9326
9327		}
9328
9329		if (this.iridescence !== undefined) data.iridescence = this.iridescence;
9330		if (this.iridescenceIOR !== undefined) data.iridescenceIOR = this.iridescenceIOR;
9331		if (this.iridescenceThicknessRange !== undefined) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
9332
9333		if (this.iridescenceMap && this.iridescenceMap.isTexture) {
9334
9335			data.iridescenceMap = this.iridescenceMap.toJSON(meta).uuid;
9336
9337		}
9338
9339		if (this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture) {
9340
9341			data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON(meta).uuid;
9342
9343		}
9344
9345		if (this.anisotropy !== undefined) data.anisotropy = this.anisotropy;
9346		if (this.anisotropyRotation !== undefined) data.anisotropyRotation = this.anisotropyRotation;
9347
9348		if (this.anisotropyMap && this.anisotropyMap.isTexture) {
9349
9350			data.anisotropyMap = this.anisotropyMap.toJSON(meta).uuid;
9351
9352		}
9353
9354		if (this.map && this.map.isTexture) data.map = this.map.toJSON(meta).uuid;
9355		if (this.matcap && this.matcap.isTexture) data.matcap = this.matcap.toJSON(meta).uuid;
9356		if (this.alphaMap && this.alphaMap.isTexture) data.alphaMap = this.alphaMap.toJSON(meta).uuid;
9357
9358		if (this.lightMap && this.lightMap.isTexture) {
9359
9360			data.lightMap = this.lightMap.toJSON(meta).uuid;
9361			data.lightMapIntensity = this.lightMapIntensity;
9362
9363		}
9364
9365		if (this.aoMap && this.aoMap.isTexture) {
9366
9367			data.aoMap = this.aoMap.toJSON(meta).uuid;
9368			data.aoMapIntensity = this.aoMapIntensity;
9369
9370		}
9371
9372		if (this.bumpMap && this.bumpMap.isTexture) {
9373
9374			data.bumpMap = this.bumpMap.toJSON(meta).uuid;
9375			data.bumpScale = this.bumpScale;
9376
9377		}
9378
9379		if (this.normalMap && this.normalMap.isTexture) {
9380
9381			data.normalMap = this.normalMap.toJSON(meta).uuid;
9382			data.normalMapType = this.normalMapType;
9383			data.normalScale = this.normalScale.toArray();
9384
9385		}
9386
9387		if (this.displacementMap && this.displacementMap.isTexture) {
9388
9389			data.displacementMap = this.displacementMap.toJSON(meta).uuid;
9390			data.displacementScale = this.displacementScale;
9391			data.displacementBias = this.displacementBias;
9392
9393		}
9394
9395		if (this.roughnessMap && this.roughnessMap.isTexture) data.roughnessMap = this.roughnessMap.toJSON(meta).uuid;
9396		if (this.metalnessMap && this.metalnessMap.isTexture) data.metalnessMap = this.metalnessMap.toJSON(meta).uuid;
9397
9398		if (this.emissiveMap && this.emissiveMap.isTexture) data.emissiveMap = this.emissiveMap.toJSON(meta).uuid;
9399		if (this.specularMap && this.specularMap.isTexture) data.specularMap = this.specularMap.toJSON(meta).uuid;
9400		if (this.specularIntensityMap && this.specularIntensityMap.isTexture) data.specularIntensityMap = this.specularIntensityMap.toJSON(meta).uuid;
9401		if (this.specularColorMap && this.specularColorMap.isTexture) data.specularColorMap = this.specularColorMap.toJSON(meta).uuid;
9402
9403		if (this.envMap && this.envMap.isTexture) {
9404
9405			data.envMap = this.envMap.toJSON(meta).uuid;
9406
9407			if (this.combine !== undefined) data.combine = this.combine;
9408
9409		}
9410
9411		if (this.envMapIntensity !== undefined) data.envMapIntensity = this.envMapIntensity;
9412		if (this.reflectivity !== undefined) data.reflectivity = this.reflectivity;
9413		if (this.refractionRatio !== undefined) data.refractionRatio = this.refractionRatio;
9414
9415		if (this.gradientMap && this.gradientMap.isTexture) {
9416
9417			data.gradientMap = this.gradientMap.toJSON(meta).uuid;
9418
9419		}
9420
9421		if (this.transmission !== undefined) data.transmission = this.transmission;
9422		if (this.transmissionMap && this.transmissionMap.isTexture) data.transmissionMap = this.transmissionMap.toJSON(meta).uuid;
9423		if (this.thickness !== undefined) data.thickness = this.thickness;
9424		if (this.thicknessMap && this.thicknessMap.isTexture) data.thicknessMap = this.thicknessMap.toJSON(meta).uuid;
9425		if (this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity) data.attenuationDistance = this.attenuationDistance;
9426		if (this.attenuationColor !== undefined) data.attenuationColor = this.attenuationColor.getHex();
9427
9428		if (this.size !== undefined) data.size = this.size;
9429		if (this.shadowSide !== null) data.shadowSide = this.shadowSide;
9430		if (this.sizeAttenuation !== undefined) data.sizeAttenuation = this.sizeAttenuation;
9431
9432		if (this.blending !== NormalBlending) data.blending = this.blending;
9433		if (this.side !== FrontSide) data.side = this.side;
9434		if (this.vertexColors === true) data.vertexColors = true;
9435
9436		if (this.opacity < 1) data.opacity = this.opacity;
9437		if (this.transparent === true) data.transparent = true;
9438
9439		if (this.blendSrc !== SrcAlphaFactor) data.blendSrc = this.blendSrc;
9440		if (this.blendDst !== OneMinusSrcAlphaFactor) data.blendDst = this.blendDst;
9441		if (this.blendEquation !== AddEquation) data.blendEquation = this.blendEquation;
9442		if (this.blendSrcAlpha !== null) data.blendSrcAlpha = this.blendSrcAlpha;
9443		if (this.blendDstAlpha !== null) data.blendDstAlpha = this.blendDstAlpha;
9444		if (this.blendEquationAlpha !== null) data.blendEquationAlpha = this.blendEquationAlpha;
9445		if (this.blendColor && this.blendColor.isColor) data.blendColor = this.blendColor.getHex();
9446		if (this.blendAlpha !== 0) data.blendAlpha = this.blendAlpha;
9447
9448		if (this.depthFunc !== LessEqualDepth) data.depthFunc = this.depthFunc;
9449		if (this.depthTest === false) data.depthTest = this.depthTest;
9450		if (this.depthWrite === false) data.depthWrite = this.depthWrite;
9451		if (this.colorWrite === false) data.colorWrite = this.colorWrite;
9452
9453		if (this.stencilWriteMask !== 0xff) data.stencilWriteMask = this.stencilWriteMask;
9454		if (this.stencilFunc !== AlwaysStencilFunc) data.stencilFunc = this.stencilFunc;
9455		if (this.stencilRef !== 0) data.stencilRef = this.stencilRef;
9456		if (this.stencilFuncMask !== 0xff) data.stencilFuncMask = this.stencilFuncMask;
vendor: 3,811 bytes, lines 9457-9574
9457		if (this.stencilFail !== KeepStencilOp) data.stencilFail = this.stencilFail;
9458		if (this.stencilZFail !== KeepStencilOp) data.stencilZFail = this.stencilZFail;
9459		if (this.stencilZPass !== KeepStencilOp) data.stencilZPass = this.stencilZPass;
9460		if (this.stencilWrite === true) data.stencilWrite = this.stencilWrite;
9461
9462		// rotation (SpriteMaterial)
9463		if (this.rotation !== undefined && this.rotation !== 0) data.rotation = this.rotation;
9464
9465		if (this.polygonOffset === true) data.polygonOffset = true;
9466		if (this.polygonOffsetFactor !== 0) data.polygonOffsetFactor = this.polygonOffsetFactor;
9467		if (this.polygonOffsetUnits !== 0) data.polygonOffsetUnits = this.polygonOffsetUnits;
9468
9469		if (this.linewidth !== undefined && this.linewidth !== 1) data.linewidth = this.linewidth;
9470		if (this.dashSize !== undefined) data.dashSize = this.dashSize;
9471		if (this.gapSize !== undefined) data.gapSize = this.gapSize;
9472		if (this.scale !== undefined) data.scale = this.scale;
9473
9474		if (this.dithering === true) data.dithering = true;
9475
9476		if (this.alphaTest > 0) data.alphaTest = this.alphaTest;
9477		if (this.alphaHash === true) data.alphaHash = true;
9478		if (this.alphaToCoverage === true) data.alphaToCoverage = true;
9479		if (this.premultipliedAlpha === true) data.premultipliedAlpha = true;
9480		if (this.forceSinglePass === true) data.forceSinglePass = true;
9481
9482		if (this.wireframe === true) data.wireframe = true;
9483		if (this.wireframeLinewidth > 1) data.wireframeLinewidth = this.wireframeLinewidth;
9484		if (this.wireframeLinecap !== 'round') data.wireframeLinecap = this.wireframeLinecap;
9485		if (this.wireframeLinejoin !== 'round') data.wireframeLinejoin = this.wireframeLinejoin;
9486
9487		if (this.flatShading === true) data.flatShading = true;
9488
9489		if (this.visible === false) data.visible = false;
9490
9491		if (this.toneMapped === false) data.toneMapped = false;
9492
9493		if (this.fog === false) data.fog = false;
9494
9495		if (Object.keys(this.userData).length > 0) data.userData = this.userData;
9496
9497		// TODO: Copied from Object3D.toJSON
9498
9499		function extractFromCache(cache) {
9500
9501			const values = [];
9502
9503			for (const key in cache) {
9504
9505				const data = cache[key];
9506				delete data.metadata;
9507				values.push(data);
9508
9509			}
9510
9511			return values;
9512
9513		}
9514
9515		if (isRootObject) {
9516
9517			const textures = extractFromCache(meta.textures);
9518			const images = extractFromCache(meta.images);
9519
9520			if (textures.length > 0) data.textures = textures;
9521			if (images.length > 0) data.images = images;
9522
9523		}
9524
9525		return data;
9526
9527	}
9528
9529	clone() {
9530
9531		return new this.constructor().copy(this);
9532
9533	}
9534
9535	copy(source) {
9536
9537		this.name = source.name;
9538
9539		this.blending = source.blending;
9540		this.side = source.side;
9541		this.vertexColors = source.vertexColors;
9542
9543		this.opacity = source.opacity;
9544		this.transparent = source.transparent;
9545
9546		this.blendSrc = source.blendSrc;
9547		this.blendDst = source.blendDst;
9548		this.blendEquation = source.blendEquation;
9549		this.blendSrcAlpha = source.blendSrcAlpha;
9550		this.blendDstAlpha = source.blendDstAlpha;
9551		this.blendEquationAlpha = source.blendEquationAlpha;
9552		this.blendColor.copy(source.blendColor);
9553		this.blendAlpha = source.blendAlpha;
9554
9555		this.depthFunc = source.depthFunc;
9556		this.depthTest = source.depthTest;
9557		this.depthWrite = source.depthWrite;
9558
9559		this.stencilWriteMask = source.stencilWriteMask;
9560		this.stencilFunc = source.stencilFunc;
9561		this.stencilRef = source.stencilRef;
9562		this.stencilFuncMask = source.stencilFuncMask;
9563		this.stencilFail = source.stencilFail;
9564		this.stencilZFail = source.stencilZFail;
9565		this.stencilZPass = source.stencilZPass;
9566		this.stencilWrite = source.stencilWrite;
9567
9568		const srcPlanes = source.clippingPlanes;
9569		let dstPlanes = null;
9570
9571		if (srcPlanes !== null) {
9572
9573			const n = srcPlanes.length;
9574			dstPlanes = new Array(n);
vendor: 7,338 bytes, lines 9575-9944
9575
9576			for (let i = 0; i !== n; ++i) {
9577
9578				dstPlanes[i] = srcPlanes[i].clone();
9579
9580			}
9581
9582		}
9583
9584		this.clippingPlanes = dstPlanes;
9585		this.clipIntersection = source.clipIntersection;
9586		this.clipShadows = source.clipShadows;
9587
9588		this.shadowSide = source.shadowSide;
9589
9590		this.colorWrite = source.colorWrite;
9591
9592		this.precision = source.precision;
9593
9594		this.polygonOffset = source.polygonOffset;
9595		this.polygonOffsetFactor = source.polygonOffsetFactor;
9596		this.polygonOffsetUnits = source.polygonOffsetUnits;
9597
9598		this.dithering = source.dithering;
9599
9600		this.alphaTest = source.alphaTest;
9601		this.alphaHash = source.alphaHash;
9602		this.alphaToCoverage = source.alphaToCoverage;
9603		this.premultipliedAlpha = source.premultipliedAlpha;
9604		this.forceSinglePass = source.forceSinglePass;
9605
9606		this.visible = source.visible;
9607
9608		this.toneMapped = source.toneMapped;
9609
9610		this.userData = JSON.parse(JSON.stringify(source.userData));
9611
9612		return this;
9613
9614	}
9615
9616	dispose() {
9617
9618		this.dispatchEvent({ type: 'dispose' });
9619
9620	}
9621
9622	set needsUpdate(value) {
9623
9624		if (value === true) this.version++;
9625
9626	}
9627
9628}
9629
9630class MeshBasicMaterial extends Material {
9631
9632	constructor(parameters) {
9633
9634		super();
9635
9636		this.isMeshBasicMaterial = true;
9637
9638		this.type = 'MeshBasicMaterial';
9639
9640		this.color = new Color(0xffffff); // emissive
9641
9642		this.map = null;
9643
9644		this.lightMap = null;
9645		this.lightMapIntensity = 1.0;
9646
9647		this.aoMap = null;
9648		this.aoMapIntensity = 1.0;
9649
9650		this.specularMap = null;
9651
9652		this.alphaMap = null;
9653
9654		this.envMap = null;
9655		this.combine = MultiplyOperation;
9656		this.reflectivity = 1;
9657		this.refractionRatio = 0.98;
9658
9659		this.wireframe = false;
9660		this.wireframeLinewidth = 1;
9661		this.wireframeLinecap = 'round';
9662		this.wireframeLinejoin = 'round';
9663
9664		this.fog = true;
9665
9666		this.setValues(parameters);
9667
9668	}
9669
9670	copy(source) {
9671
9672		super.copy(source);
9673
9674		this.color.copy(source.color);
9675
9676		this.map = source.map;
9677
9678		this.lightMap = source.lightMap;
9679		this.lightMapIntensity = source.lightMapIntensity;
9680
9681		this.aoMap = source.aoMap;
9682		this.aoMapIntensity = source.aoMapIntensity;
9683
9684		this.specularMap = source.specularMap;
9685
9686		this.alphaMap = source.alphaMap;
9687
9688		this.envMap = source.envMap;
9689		this.combine = source.combine;
9690		this.reflectivity = source.reflectivity;
9691		this.refractionRatio = source.refractionRatio;
9692
9693		this.wireframe = source.wireframe;
9694		this.wireframeLinewidth = source.wireframeLinewidth;
9695		this.wireframeLinecap = source.wireframeLinecap;
9696		this.wireframeLinejoin = source.wireframeLinejoin;
9697
9698		this.fog = source.fog;
9699
9700		return this;
9701
9702	}
9703
9704}
9705
9706// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
9707
9708const _tables = /*@__PURE__*/ _generateTables();
9709
9710function _generateTables() {
9711
9712	// float32 to float16 helpers
9713
9714	const buffer = new ArrayBuffer(4);
9715	const floatView = new Float32Array(buffer);
9716	const uint32View = new Uint32Array(buffer);
9717
9718	const baseTable = new Uint32Array(512);
9719	const shiftTable = new Uint32Array(512);
9720
9721	for (let i = 0; i < 256; ++i) {
9722
9723		const e = i - 127;
9724
9725		// very small number (0, -0)
9726
9727		if (e < - 27) {
9728
9729			baseTable[i] = 0x0000;
9730			baseTable[i | 0x100] = 0x8000;
9731			shiftTable[i] = 24;
9732			shiftTable[i | 0x100] = 24;
9733
9734			// small number (denorm)
9735
9736		} else if (e < - 14) {
9737
9738			baseTable[i] = 0x0400 >> (- e - 14);
9739			baseTable[i | 0x100] = (0x0400 >> (- e - 14)) | 0x8000;
9740			shiftTable[i] = - e - 1;
9741			shiftTable[i | 0x100] = - e - 1;
9742
9743			// normal number
9744
9745		} else if (e <= 15) {
9746
9747			baseTable[i] = (e + 15) << 10;
9748			baseTable[i | 0x100] = ((e + 15) << 10) | 0x8000;
9749			shiftTable[i] = 13;
9750			shiftTable[i | 0x100] = 13;
9751
9752			// large number (Infinity, -Infinity)
9753
9754		} else if (e < 128) {
9755
9756			baseTable[i] = 0x7c00;
9757			baseTable[i | 0x100] = 0xfc00;
9758			shiftTable[i] = 24;
9759			shiftTable[i | 0x100] = 24;
9760
9761			// stay (NaN, Infinity, -Infinity)
9762
9763		} else {
9764
9765			baseTable[i] = 0x7c00;
9766			baseTable[i | 0x100] = 0xfc00;
9767			shiftTable[i] = 13;
9768			shiftTable[i | 0x100] = 13;
9769
9770		}
9771
9772	}
9773
9774	// float16 to float32 helpers
9775
9776	const mantissaTable = new Uint32Array(2048);
9777	const exponentTable = new Uint32Array(64);
9778	const offsetTable = new Uint32Array(64);
9779
9780	for (let i = 1; i < 1024; ++i) {
9781
9782		let m = i << 13; // zero pad mantissa bits
9783		let e = 0; // zero exponent
9784
9785		// normalized
9786		while ((m & 0x00800000) === 0) {
9787
9788			m <<= 1;
9789			e -= 0x00800000; // decrement exponent
9790
9791		}
9792
9793		m &= ~0x00800000; // clear leading 1 bit
9794		e += 0x38800000; // adjust bias
9795
9796		mantissaTable[i] = m | e;
9797
9798	}
9799
9800	for (let i = 1024; i < 2048; ++i) {
9801
9802		mantissaTable[i] = 0x38000000 + ((i - 1024) << 13);
9803
9804	}
9805
9806	for (let i = 1; i < 31; ++i) {
9807
9808		exponentTable[i] = i << 23;
9809
9810	}
9811
9812	exponentTable[31] = 0x47800000;
9813	exponentTable[32] = 0x80000000;
9814
9815	for (let i = 33; i < 63; ++i) {
9816
9817		exponentTable[i] = 0x80000000 + ((i - 32) << 23);
9818
9819	}
9820
9821	exponentTable[63] = 0xc7800000;
9822
9823	for (let i = 1; i < 64; ++i) {
9824
9825		if (i !== 32) {
9826
9827			offsetTable[i] = 1024;
9828
9829		}
9830
9831	}
9832
9833	return {
9834		floatView: floatView,
9835		uint32View: uint32View,
9836		baseTable: baseTable,
9837		shiftTable: shiftTable,
9838		mantissaTable: mantissaTable,
9839		exponentTable: exponentTable,
9840		offsetTable: offsetTable
9841	};
9842
9843}
9844
9845// float32 to float16
9846
9847function toHalfFloat(val) {
9848
9849	if (Math.abs(val) > 65504) console.warn('THREE.DataUtils.toHalfFloat(): Value out of range.');
9850
9851	val = clamp(val, - 65504, 65504);
9852
9853	_tables.floatView[0] = val;
9854	const f = _tables.uint32View[0];
9855	const e = (f >> 23) & 0x1ff;
9856	return _tables.baseTable[e] + ((f & 0x007fffff) >> _tables.shiftTable[e]);
9857
9858}
9859
9860// float16 to float32
9861
9862function fromHalfFloat(val) {
9863
9864	const m = val >> 10;
9865	_tables.uint32View[0] = _tables.mantissaTable[_tables.offsetTable[m] + (val & 0x3ff)] + _tables.exponentTable[m];
9866	return _tables.floatView[0];
9867
9868}
9869
9870const DataUtils = {
9871	toHalfFloat: toHalfFloat,
9872	fromHalfFloat: fromHalfFloat,
9873};
9874
9875const _vector$9 = /*@__PURE__*/ new Vector3();
9876const _vector2$1 = /*@__PURE__*/ new Vector2();
9877
9878class BufferAttribute {
9879
9880	constructor(array, itemSize, normalized = false) {
9881
9882		if (Array.isArray(array)) {
9883
9884			throw new TypeError('THREE.BufferAttribute: array should be a Typed Array.');
9885
9886		}
9887
9888		this.isBufferAttribute = true;
9889
9890		this.name = '';
9891
9892		this.array = array;
9893		this.itemSize = itemSize;
9894		this.count = array !== undefined ? array.length / itemSize : 0;
9895		this.normalized = normalized;
9896
9897		this.usage = StaticDrawUsage;
9898		this._updateRange = { offset: 0, count: - 1 };
9899		this.updateRanges = [];
9900		this.gpuType = FloatType;
9901
9902		this.version = 0;
9903
9904	}
9905
9906	onUploadCallback() { }
9907
9908	set needsUpdate(value) {
9909
9910		if (value === true) this.version++;
9911
9912	}
9913
9914	get updateRange() {
9915
9916		console.warn('THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.'); // @deprecated, r159
9917		return this._updateRange;
9918
9919	}
9920
9921	setUsage(value) {
9922
9923		this.usage = value;
9924
9925		return this;
9926
9927	}
9928
9929	addUpdateRange(start, count) {
9930
9931		this.updateRanges.push({ start, count });
9932
9933	}
9934
9935	clearUpdateRanges() {
9936
9937		this.updateRanges.length = 0;
9938
9939	}
9940
9941	copy(source) {
9942
9943		this.name = source.name;
9944		this.array = new source.array.constructor(source.array);
vendor: 9,392 bytes, lines 9945-10511
9945		this.itemSize = source.itemSize;
9946		this.count = source.count;
9947		this.normalized = source.normalized;
9948
9949		this.usage = source.usage;
9950		this.gpuType = source.gpuType;
9951
9952		return this;
9953
9954	}
9955
9956	copyAt(index1, attribute, index2) {
9957
9958		index1 *= this.itemSize;
9959		index2 *= attribute.itemSize;
9960
9961		for (let i = 0, l = this.itemSize; i < l; i++) {
9962
9963			this.array[index1 + i] = attribute.array[index2 + i];
9964
9965		}
9966
9967		return this;
9968
9969	}
9970
9971	copyArray(array) {
9972
9973		this.array.set(array);
9974
9975		return this;
9976
9977	}
9978
9979	applyMatrix3(m) {
9980
9981		if (this.itemSize === 2) {
9982
9983			for (let i = 0, l = this.count; i < l; i++) {
9984
9985				_vector2$1.fromBufferAttribute(this, i);
9986				_vector2$1.applyMatrix3(m);
9987
9988				this.setXY(i, _vector2$1.x, _vector2$1.y);
9989
9990			}
9991
9992		} else if (this.itemSize === 3) {
9993
9994			for (let i = 0, l = this.count; i < l; i++) {
9995
9996				_vector$9.fromBufferAttribute(this, i);
9997				_vector$9.applyMatrix3(m);
9998
9999				this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
10000
10001			}
10002
10003		}
10004
10005		return this;
10006
10007	}
10008
10009	applyMatrix4(m) {
10010
10011		for (let i = 0, l = this.count; i < l; i++) {
10012
10013			_vector$9.fromBufferAttribute(this, i);
10014
10015			_vector$9.applyMatrix4(m);
10016
10017			this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
10018
10019		}
10020
10021		return this;
10022
10023	}
10024
10025	applyNormalMatrix(m) {
10026
10027		for (let i = 0, l = this.count; i < l; i++) {
10028
10029			_vector$9.fromBufferAttribute(this, i);
10030
10031			_vector$9.applyNormalMatrix(m);
10032
10033			this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
10034
10035		}
10036
10037		return this;
10038
10039	}
10040
10041	transformDirection(m) {
10042
10043		for (let i = 0, l = this.count; i < l; i++) {
10044
10045			_vector$9.fromBufferAttribute(this, i);
10046
10047			_vector$9.transformDirection(m);
10048
10049			this.setXYZ(i, _vector$9.x, _vector$9.y, _vector$9.z);
10050
10051		}
10052
10053		return this;
10054
10055	}
10056
10057	set(value, offset = 0) {
10058
10059		// Matching BufferAttribute constructor, do not normalize the array.
10060		this.array.set(value, offset);
10061
10062		return this;
10063
10064	}
10065
10066	getComponent(index, component) {
10067
10068		let value = this.array[index * this.itemSize + component];
10069
10070		if (this.normalized) value = denormalize(value, this.array);
10071
10072		return value;
10073
10074	}
10075
10076	setComponent(index, component, value) {
10077
10078		if (this.normalized) value = normalize(value, this.array);
10079
10080		this.array[index * this.itemSize + component] = value;
10081
10082		return this;
10083
10084	}
10085
10086	getX(index) {
10087
10088		let x = this.array[index * this.itemSize];
10089
10090		if (this.normalized) x = denormalize(x, this.array);
10091
10092		return x;
10093
10094	}
10095
10096	setX(index, x) {
10097
10098		if (this.normalized) x = normalize(x, this.array);
10099
10100		this.array[index * this.itemSize] = x;
10101
10102		return this;
10103
10104	}
10105
10106	getY(index) {
10107
10108		let y = this.array[index * this.itemSize + 1];
10109
10110		if (this.normalized) y = denormalize(y, this.array);
10111
10112		return y;
10113
10114	}
10115
10116	setY(index, y) {
10117
10118		if (this.normalized) y = normalize(y, this.array);
10119
10120		this.array[index * this.itemSize + 1] = y;
10121
10122		return this;
10123
10124	}
10125
10126	getZ(index) {
10127
10128		let z = this.array[index * this.itemSize + 2];
10129
10130		if (this.normalized) z = denormalize(z, this.array);
10131
10132		return z;
10133
10134	}
10135
10136	setZ(index, z) {
10137
10138		if (this.normalized) z = normalize(z, this.array);
10139
10140		this.array[index * this.itemSize + 2] = z;
10141
10142		return this;
10143
10144	}
10145
10146	getW(index) {
10147
10148		let w = this.array[index * this.itemSize + 3];
10149
10150		if (this.normalized) w = denormalize(w, this.array);
10151
10152		return w;
10153
10154	}
10155
10156	setW(index, w) {
10157
10158		if (this.normalized) w = normalize(w, this.array);
10159
10160		this.array[index * this.itemSize + 3] = w;
10161
10162		return this;
10163
10164	}
10165
10166	setXY(index, x, y) {
10167
10168		index *= this.itemSize;
10169
10170		if (this.normalized) {
10171
10172			x = normalize(x, this.array);
10173			y = normalize(y, this.array);
10174
10175		}
10176
10177		this.array[index + 0] = x;
10178		this.array[index + 1] = y;
10179
10180		return this;
10181
10182	}
10183
10184	setXYZ(index, x, y, z) {
10185
10186		index *= this.itemSize;
10187
10188		if (this.normalized) {
10189
10190			x = normalize(x, this.array);
10191			y = normalize(y, this.array);
10192			z = normalize(z, this.array);
10193
10194		}
10195
10196		this.array[index + 0] = x;
10197		this.array[index + 1] = y;
10198		this.array[index + 2] = z;
10199
10200		return this;
10201
10202	}
10203
10204	setXYZW(index, x, y, z, w) {
10205
10206		index *= this.itemSize;
10207
10208		if (this.normalized) {
10209
10210			x = normalize(x, this.array);
10211			y = normalize(y, this.array);
10212			z = normalize(z, this.array);
10213			w = normalize(w, this.array);
10214
10215		}
10216
10217		this.array[index + 0] = x;
10218		this.array[index + 1] = y;
10219		this.array[index + 2] = z;
10220		this.array[index + 3] = w;
10221
10222		return this;
10223
10224	}
10225
10226	onUpload(callback) {
10227
10228		this.onUploadCallback = callback;
10229
10230		return this;
10231
10232	}
10233
10234	clone() {
10235
10236		return new this.constructor(this.array, this.itemSize).copy(this);
10237
10238	}
10239
10240	toJSON() {
10241
10242		const data = {
10243			itemSize: this.itemSize,
10244			type: this.array.constructor.name,
10245			array: Array.from(this.array),
10246			normalized: this.normalized
10247		};
10248
10249		if (this.name !== '') data.name = this.name;
10250		if (this.usage !== StaticDrawUsage) data.usage = this.usage;
10251
10252		return data;
10253
10254	}
10255
10256}
10257
10258//
10259
10260class Int8BufferAttribute extends BufferAttribute {
10261
10262	constructor(array, itemSize, normalized) {
10263
10264		super(new Int8Array(array), itemSize, normalized);
10265
10266	}
10267
10268}
10269
10270class Uint8BufferAttribute extends BufferAttribute {
10271
10272	constructor(array, itemSize, normalized) {
10273
10274		super(new Uint8Array(array), itemSize, normalized);
10275
10276	}
10277
10278}
10279
10280class Uint8ClampedBufferAttribute extends BufferAttribute {
10281
10282	constructor(array, itemSize, normalized) {
10283
10284		super(new Uint8ClampedArray(array), itemSize, normalized);
10285
10286	}
10287
10288}
10289
10290class Int16BufferAttribute extends BufferAttribute {
10291
10292	constructor(array, itemSize, normalized) {
10293
10294		super(new Int16Array(array), itemSize, normalized);
10295
10296	}
10297
10298}
10299
10300class Uint16BufferAttribute extends BufferAttribute {
10301
10302	constructor(array, itemSize, normalized) {
10303
10304		super(new Uint16Array(array), itemSize, normalized);
10305
10306	}
10307
10308}
10309
10310class Int32BufferAttribute extends BufferAttribute {
10311
10312	constructor(array, itemSize, normalized) {
10313
10314		super(new Int32Array(array), itemSize, normalized);
10315
10316	}
10317
10318}
10319
10320class Uint32BufferAttribute extends BufferAttribute {
10321
10322	constructor(array, itemSize, normalized) {
10323
10324		super(new Uint32Array(array), itemSize, normalized);
10325
10326	}
10327
10328}
10329
10330class Float16BufferAttribute extends BufferAttribute {
10331
10332	constructor(array, itemSize, normalized) {
10333
10334		super(new Uint16Array(array), itemSize, normalized);
10335
10336		this.isFloat16BufferAttribute = true;
10337
10338	}
10339
10340	getX(index) {
10341
10342		let x = fromHalfFloat(this.array[index * this.itemSize]);
10343
10344		if (this.normalized) x = denormalize(x, this.array);
10345
10346		return x;
10347
10348	}
10349
10350	setX(index, x) {
10351
10352		if (this.normalized) x = normalize(x, this.array);
10353
10354		this.array[index * this.itemSize] = toHalfFloat(x);
10355
10356		return this;
10357
10358	}
10359
10360	getY(index) {
10361
10362		let y = fromHalfFloat(this.array[index * this.itemSize + 1]);
10363
10364		if (this.normalized) y = denormalize(y, this.array);
10365
10366		return y;
10367
10368	}
10369
10370	setY(index, y) {
10371
10372		if (this.normalized) y = normalize(y, this.array);
10373
10374		this.array[index * this.itemSize + 1] = toHalfFloat(y);
10375
10376		return this;
10377
10378	}
10379
10380	getZ(index) {
10381
10382		let z = fromHalfFloat(this.array[index * this.itemSize + 2]);
10383
10384		if (this.normalized) z = denormalize(z, this.array);
10385
10386		return z;
10387
10388	}
10389
10390	setZ(index, z) {
10391
10392		if (this.normalized) z = normalize(z, this.array);
10393
10394		this.array[index * this.itemSize + 2] = toHalfFloat(z);
10395
10396		return this;
10397
10398	}
10399
10400	getW(index) {
10401
10402		let w = fromHalfFloat(this.array[index * this.itemSize + 3]);
10403
10404		if (this.normalized) w = denormalize(w, this.array);
10405
10406		return w;
10407
10408	}
10409
10410	setW(index, w) {
10411
10412		if (this.normalized) w = normalize(w, this.array);
10413
10414		this.array[index * this.itemSize + 3] = toHalfFloat(w);
10415
10416		return this;
10417
10418	}
10419
10420	setXY(index, x, y) {
10421
10422		index *= this.itemSize;
10423
10424		if (this.normalized) {
10425
10426			x = normalize(x, this.array);
10427			y = normalize(y, this.array);
10428
10429		}
10430
10431		this.array[index + 0] = toHalfFloat(x);
10432		this.array[index + 1] = toHalfFloat(y);
10433
10434		return this;
10435
10436	}
10437
10438	setXYZ(index, x, y, z) {
10439
10440		index *= this.itemSize;
10441
10442		if (this.normalized) {
10443
10444			x = normalize(x, this.array);
10445			y = normalize(y, this.array);
10446			z = normalize(z, this.array);
10447
10448		}
10449
10450		this.array[index + 0] = toHalfFloat(x);
10451		this.array[index + 1] = toHalfFloat(y);
10452		this.array[index + 2] = toHalfFloat(z);
10453
10454		return this;
10455
10456	}
10457
10458	setXYZW(index, x, y, z, w) {
10459
10460		index *= this.itemSize;
10461
10462		if (this.normalized) {
10463
10464			x = normalize(x, this.array);
10465			y = normalize(y, this.array);
10466			z = normalize(z, this.array);
10467			w = normalize(w, this.array);
10468
10469		}
10470
10471		this.array[index + 0] = toHalfFloat(x);
10472		this.array[index + 1] = toHalfFloat(y);
10473		this.array[index + 2] = toHalfFloat(z);
10474		this.array[index + 3] = toHalfFloat(w);
10475
10476		return this;
10477
10478	}
10479
10480}
10481
10482
10483class Float32BufferAttribute extends BufferAttribute {
10484
10485	constructor(array, itemSize, normalized) {
10486
10487		super(new Float32Array(array), itemSize, normalized);
10488
10489	}
10490
10491}
10492
10493class Float64BufferAttribute extends BufferAttribute {
10494
10495	constructor(array, itemSize, normalized) {
10496
10497		super(new Float64Array(array), itemSize, normalized);
10498
10499	}
10500
10501}
10502
10503let _id$2 = 0;
10504
10505const _m1 = /*@__PURE__*/ new Matrix4();
10506const _obj = /*@__PURE__*/ new Object3D();
10507const _offset = /*@__PURE__*/ new Vector3();
10508const _box$2 = /*@__PURE__*/ new Box3();
10509const _boxMorphTargets = /*@__PURE__*/ new Box3();
10510const _vector$8 = /*@__PURE__*/ new Vector3();
10511
vendor: 5,870 bytes, lines 10512-10863
10512class BufferGeometry extends EventDispatcher {
10513
10514	constructor() {
10515
10516		super();
10517
10518		this.isBufferGeometry = true;
10519
10520		Object.defineProperty(this, 'id', { value: _id$2++ });
10521
10522		this.uuid = generateUUID();
10523
10524		this.name = '';
10525		this.type = 'BufferGeometry';
10526
10527		this.index = null;
10528		this.attributes = {};
10529
10530		this.morphAttributes = {};
10531		this.morphTargetsRelative = false;
10532
10533		this.groups = [];
10534
10535		this.boundingBox = null;
10536		this.boundingSphere = null;
10537
10538		this.drawRange = { start: 0, count: Infinity };
10539
10540		this.userData = {};
10541
10542	}
10543
10544	getIndex() {
10545
10546		return this.index;
10547
10548	}
10549
10550	setIndex(index) {
10551
10552		if (Array.isArray(index)) {
10553
10554			this.index = new (arrayNeedsUint32(index) ? Uint32BufferAttribute : Uint16BufferAttribute)(index, 1);
10555
10556		} else {
10557
10558			this.index = index;
10559
10560		}
10561
10562		return this;
10563
10564	}
10565
10566	getAttribute(name) {
10567
10568		return this.attributes[name];
10569
10570	}
10571
10572	setAttribute(name, attribute) {
10573
10574		this.attributes[name] = attribute;
10575
10576		return this;
10577
10578	}
10579
10580	deleteAttribute(name) {
10581
10582		delete this.attributes[name];
10583
10584		return this;
10585
10586	}
10587
10588	hasAttribute(name) {
10589
10590		return this.attributes[name] !== undefined;
10591
10592	}
10593
10594	addGroup(start, count, materialIndex = 0) {
10595
10596		this.groups.push({
10597
10598			start: start,
10599			count: count,
10600			materialIndex: materialIndex
10601
10602		});
10603
10604	}
10605
10606	clearGroups() {
10607
10608		this.groups = [];
10609
10610	}
10611
10612	setDrawRange(start, count) {
10613
10614		this.drawRange.start = start;
10615		this.drawRange.count = count;
10616
10617	}
10618
10619	applyMatrix4(matrix) {
10620
10621		const position = this.attributes.position;
10622
10623		if (position !== undefined) {
10624
10625			position.applyMatrix4(matrix);
10626
10627			position.needsUpdate = true;
10628
10629		}
10630
10631		const normal = this.attributes.normal;
10632
10633		if (normal !== undefined) {
10634
10635			const normalMatrix = new Matrix3().getNormalMatrix(matrix);
10636
10637			normal.applyNormalMatrix(normalMatrix);
10638
10639			normal.needsUpdate = true;
10640
10641		}
10642
10643		const tangent = this.attributes.tangent;
10644
10645		if (tangent !== undefined) {
10646
10647			tangent.transformDirection(matrix);
10648
10649			tangent.needsUpdate = true;
10650
10651		}
10652
10653		if (this.boundingBox !== null) {
10654
10655			this.computeBoundingBox();
10656
10657		}
10658
10659		if (this.boundingSphere !== null) {
10660
10661			this.computeBoundingSphere();
10662
10663		}
10664
10665		return this;
10666
10667	}
10668
10669	applyQuaternion(q) {
10670
10671		_m1.makeRotationFromQuaternion(q);
10672
10673		this.applyMatrix4(_m1);
10674
10675		return this;
10676
10677	}
10678
10679	rotateX(angle) {
10680
10681		// rotate geometry around world x-axis
10682
10683		_m1.makeRotationX(angle);
10684
10685		this.applyMatrix4(_m1);
10686
10687		return this;
10688
10689	}
10690
10691	rotateY(angle) {
10692
10693		// rotate geometry around world y-axis
10694
10695		_m1.makeRotationY(angle);
10696
10697		this.applyMatrix4(_m1);
10698
10699		return this;
10700
10701	}
10702
10703	rotateZ(angle) {
10704
10705		// rotate geometry around world z-axis
10706
10707		_m1.makeRotationZ(angle);
10708
10709		this.applyMatrix4(_m1);
10710
10711		return this;
10712
10713	}
10714
10715	translate(x, y, z) {
10716
10717		// translate geometry
10718
10719		_m1.makeTranslation(x, y, z);
10720
10721		this.applyMatrix4(_m1);
10722
10723		return this;
10724
10725	}
10726
10727	scale(x, y, z) {
10728
10729		// scale geometry
10730
10731		_m1.makeScale(x, y, z);
10732
10733		this.applyMatrix4(_m1);
10734
10735		return this;
10736
10737	}
10738
10739	lookAt(vector) {
10740
10741		_obj.lookAt(vector);
10742
10743		_obj.updateMatrix();
10744
10745		this.applyMatrix4(_obj.matrix);
10746
10747		return this;
10748
10749	}
10750
10751	center() {
10752
10753		this.computeBoundingBox();
10754
10755		this.boundingBox.getCenter(_offset).negate();
10756
10757		this.translate(_offset.x, _offset.y, _offset.z);
10758
10759		return this;
10760
10761	}
10762
10763	setFromPoints(points) {
10764
10765		const position = [];
10766
10767		for (let i = 0, l = points.length; i < l; i++) {
10768
10769			const point = points[i];
10770			position.push(point.x, point.y, point.z || 0);
10771
10772		}
10773
10774		this.setAttribute('position', new Float32BufferAttribute(position, 3));
10775
10776		return this;
10777
10778	}
10779
10780	computeBoundingBox() {
10781
10782		if (this.boundingBox === null) {
10783
10784			this.boundingBox = new Box3();
10785
10786		}
10787
10788		const position = this.attributes.position;
10789		const morphAttributesPosition = this.morphAttributes.position;
10790
10791		if (position && position.isGLBufferAttribute) {
10792
10793			console.error('THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".', this);
10794
10795			this.boundingBox.set(
10796				new Vector3(- Infinity, - Infinity, - Infinity),
10797				new Vector3(+ Infinity, + Infinity, + Infinity)
10798			);
10799
10800			return;
10801
10802		}
10803
10804		if (position !== undefined) {
10805
10806			this.boundingBox.setFromBufferAttribute(position);
10807
10808			// process morph attributes if present
10809
10810			if (morphAttributesPosition) {
10811
10812				for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
10813
10814					const morphAttribute = morphAttributesPosition[i];
10815					_box$2.setFromBufferAttribute(morphAttribute);
10816
10817					if (this.morphTargetsRelative) {
10818
10819						_vector$8.addVectors(this.boundingBox.min, _box$2.min);
10820						this.boundingBox.expandByPoint(_vector$8);
10821
10822						_vector$8.addVectors(this.boundingBox.max, _box$2.max);
10823						this.boundingBox.expandByPoint(_vector$8);
10824
10825					} else {
10826
10827						this.boundingBox.expandByPoint(_box$2.min);
10828						this.boundingBox.expandByPoint(_box$2.max);
10829
10830					}
10831
10832				}
10833
10834			}
10835
10836		} else {
10837
10838			this.boundingBox.makeEmpty();
10839
10840		}
10841
10842		if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) {
10843
10844			console.error('THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this);
10845
10846		}
10847
10848	}
10849
10850	computeBoundingSphere() {
10851
10852		if (this.boundingSphere === null) {
10853
10854			this.boundingSphere = new Sphere();
10855
10856		}
10857
10858		const position = this.attributes.position;
10859		const morphAttributesPosition = this.morphAttributes.position;
10860
10861		if (position && position.isGLBufferAttribute) {
10862
10863			console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "fal
vendor: 5,054 bytes, lines 10863-11091
10863se".', this);
10864
10865			this.boundingSphere.set(new Vector3(), Infinity);
10866
10867			return;
10868
10869		}
10870
10871		if (position) {
10872
10873			// first, find the center of the bounding sphere
10874
10875			const center = this.boundingSphere.center;
10876
10877			_box$2.setFromBufferAttribute(position);
10878
10879			// process morph attributes if present
10880
10881			if (morphAttributesPosition) {
10882
10883				for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
10884
10885					const morphAttribute = morphAttributesPosition[i];
10886					_boxMorphTargets.setFromBufferAttribute(morphAttribute);
10887
10888					if (this.morphTargetsRelative) {
10889
10890						_vector$8.addVectors(_box$2.min, _boxMorphTargets.min);
10891						_box$2.expandByPoint(_vector$8);
10892
10893						_vector$8.addVectors(_box$2.max, _boxMorphTargets.max);
10894						_box$2.expandByPoint(_vector$8);
10895
10896					} else {
10897
10898						_box$2.expandByPoint(_boxMorphTargets.min);
10899						_box$2.expandByPoint(_boxMorphTargets.max);
10900
10901					}
10902
10903				}
10904
10905			}
10906
10907			_box$2.getCenter(center);
10908
10909			// second, try to find a boundingSphere with a radius smaller than the
10910			// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
10911
10912			let maxRadiusSq = 0;
10913
10914			for (let i = 0, il = position.count; i < il; i++) {
10915
10916				_vector$8.fromBufferAttribute(position, i);
10917
10918				maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8));
10919
10920			}
10921
10922			// process morph attributes if present
10923
10924			if (morphAttributesPosition) {
10925
10926				for (let i = 0, il = morphAttributesPosition.length; i < il; i++) {
10927
10928					const morphAttribute = morphAttributesPosition[i];
10929					const morphTargetsRelative = this.morphTargetsRelative;
10930
10931					for (let j = 0, jl = morphAttribute.count; j < jl; j++) {
10932
10933						_vector$8.fromBufferAttribute(morphAttribute, j);
10934
10935						if (morphTargetsRelative) {
10936
10937							_offset.fromBufferAttribute(position, j);
10938							_vector$8.add(_offset);
10939
10940						}
10941
10942						maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(_vector$8));
10943
10944					}
10945
10946				}
10947
10948			}
10949
10950			this.boundingSphere.radius = Math.sqrt(maxRadiusSq);
10951
10952			if (isNaN(this.boundingSphere.radius)) {
10953
10954				console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this);
10955
10956			}
10957
10958		}
10959
10960	}
10961
10962	computeTangents() {
10963
10964		const index = this.index;
10965		const attributes = this.attributes;
10966
10967		// based on http://www.terathon.com/code/tangent.html
10968		// (per vertex tangents)
10969
10970		if (index === null ||
10971			attributes.position === undefined ||
10972			attributes.normal === undefined ||
10973			attributes.uv === undefined) {
10974
10975			console.error('THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)');
10976			return;
10977
10978		}
10979
10980		const indices = index.array;
10981		const positions = attributes.position.array;
10982		const normals = attributes.normal.array;
10983		const uvs = attributes.uv.array;
10984
10985		const nVertices = positions.length / 3;
10986
10987		if (this.hasAttribute('tangent') === false) {
10988
10989			this.setAttribute('tangent', new BufferAttribute(new Float32Array(4 * nVertices), 4));
10990
10991		}
10992
10993		const tangents = this.getAttribute('tangent').array;
10994
10995		const tan1 = [], tan2 = [];
10996
10997		for (let i = 0; i < nVertices; i++) {
10998
10999			tan1[i] = new Vector3();
11000			tan2[i] = new Vector3();
11001
11002		}
11003
11004		const vA = new Vector3(),
11005			vB = new Vector3(),
11006			vC = new Vector3(),
11007
11008			uvA = new Vector2(),
11009			uvB = new Vector2(),
11010			uvC = new Vector2(),
11011
11012			sdir = new Vector3(),
11013			tdir = new Vector3();
11014
11015		function handleTriangle(a, b, c) {
11016
11017			vA.fromArray(positions, a * 3);
11018			vB.fromArray(positions, b * 3);
11019			vC.fromArray(positions, c * 3);
11020
11021			uvA.fromArray(uvs, a * 2);
11022			uvB.fromArray(uvs, b * 2);
11023			uvC.fromArray(uvs, c * 2);
11024
11025			vB.sub(vA);
11026			vC.sub(vA);
11027
11028			uvB.sub(uvA);
11029			uvC.sub(uvA);
11030
11031			const r = 1.0 / (uvB.x * uvC.y - uvC.x * uvB.y);
11032
11033			// silently ignore degenerate uv triangles having coincident or colinear vertices
11034
11035			if (!isFinite(r)) return;
11036
11037			sdir.copy(vB).multiplyScalar(uvC.y).addScaledVector(vC, - uvB.y).multiplyScalar(r);
11038			tdir.copy(vC).multiplyScalar(uvB.x).addScaledVector(vB, - uvC.x).multiplyScalar(r);
11039
11040			tan1[a].add(sdir);
11041			tan1[b].add(sdir);
11042			tan1[c].add(sdir);
11043
11044			tan2[a].add(tdir);
11045			tan2[b].add(tdir);
11046			tan2[c].add(tdir);
11047
11048		}
11049
11050		let groups = this.groups;
11051
11052		if (groups.length === 0) {
11053
11054			groups = [{
11055				start: 0,
11056				count: indices.length
11057			}];
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				handleTriangle(
11071					indices[j + 0],
11072					indices[j + 1],
11073					indices[j + 2]
11074				);
11075
11076			}
11077
11078		}
11079
11080		const tmp = new Vector3(), tmp2 = new Vector3();
11081		const n = new Vector3(), n2 = new Vector3();
11082
11083		function handleVertex(v) {
11084
11085			n.fromArray(normals, v * 3);
11086			n2.copy(n);
11087
11088			const t = tan1[v];
11089
11090			// Gram-Schmidt orthogonalize
11091
vendor: 4,638 bytes, lines 11092-11303
11092			tmp.copy(t);
11093			tmp.sub(n.multiplyScalar(n.dot(t))).normalize();
11094
11095			// Calculate handedness
11096
11097			tmp2.crossVectors(n2, t);
11098			const test = tmp2.dot(tan2[v]);
11099			const w = (test < 0.0) ? - 1.0 : 1.0;
11100
11101			tangents[v * 4] = tmp.x;
11102			tangents[v * 4 + 1] = tmp.y;
11103			tangents[v * 4 + 2] = tmp.z;
11104			tangents[v * 4 + 3] = w;
11105
11106		}
11107
11108		for (let i = 0, il = groups.length; i < il; ++i) {
11109
11110			const group = groups[i];
11111
11112			const start = group.start;
11113			const count = group.count;
11114
11115			for (let j = start, jl = start + count; j < jl; j += 3) {
11116
11117				handleVertex(indices[j + 0]);
11118				handleVertex(indices[j + 1]);
11119				handleVertex(indices[j + 2]);
11120
11121			}
11122
11123		}
11124
11125	}
11126
11127	computeVertexNormals() {
11128
11129		const index = this.index;
11130		const positionAttribute = this.getAttribute('position');
11131
11132		if (positionAttribute !== undefined) {
11133
11134			let normalAttribute = this.getAttribute('normal');
11135
11136			if (normalAttribute === undefined) {
11137
11138				normalAttribute = new BufferAttribute(new Float32Array(positionAttribute.count * 3), 3);
11139				this.setAttribute('normal', normalAttribute);
11140
11141			} else {
11142
11143				// reset existing normals to zero
11144
11145				for (let i = 0, il = normalAttribute.count; i < il; i++) {
11146
11147					normalAttribute.setXYZ(i, 0, 0, 0);
11148
11149				}
11150
11151			}
11152
11153			const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
11154			const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
11155			const cb = new Vector3(), ab = new Vector3();
11156
11157			// indexed elements
11158
11159			if (index) {
11160
11161				for (let i = 0, il = index.count; i < il; i += 3) {
11162
11163					const vA = index.getX(i + 0);
11164					const vB = index.getX(i + 1);
11165					const vC = index.getX(i + 2);
11166
11167					pA.fromBufferAttribute(positionAttribute, vA);
11168					pB.fromBufferAttribute(positionAttribute, vB);
11169					pC.fromBufferAttribute(positionAttribute, vC);
11170
11171					cb.subVectors(pC, pB);
11172					ab.subVectors(pA, pB);
11173					cb.cross(ab);
11174
11175					nA.fromBufferAttribute(normalAttribute, vA);
11176					nB.fromBufferAttribute(normalAttribute, vB);
11177					nC.fromBufferAttribute(normalAttribute, vC);
11178
11179					nA.add(cb);
11180					nB.add(cb);
11181					nC.add(cb);
11182
11183					normalAttribute.setXYZ(vA, nA.x, nA.y, nA.z);
11184					normalAttribute.setXYZ(vB, nB.x, nB.y, nB.z);
11185					normalAttribute.setXYZ(vC, nC.x, nC.y, nC.z);
11186
11187				}
11188
11189			} else {
11190
11191				// non-indexed elements (unconnected triangle soup)
11192
11193				for (let i = 0, il = positionAttribute.count; i < il; i += 3) {
11194
11195					pA.fromBufferAttribute(positionAttribute, i + 0);
11196					pB.fromBufferAttribute(positionAttribute, i + 1);
11197					pC.fromBufferAttribute(positionAttribute, i + 2);
11198
11199					cb.subVectors(pC, pB);
11200					ab.subVectors(pA, pB);
11201					cb.cross(ab);
11202
11203					normalAttribute.setXYZ(i + 0, cb.x, cb.y, cb.z);
11204					normalAttribute.setXYZ(i + 1, cb.x, cb.y, cb.z);
11205					normalAttribute.setXYZ(i + 2, cb.x, cb.y, cb.z);
11206
11207				}
11208
11209			}
11210
11211			this.normalizeNormals();
11212
11213			normalAttribute.needsUpdate = true;
11214
11215		}
11216
11217	}
11218
11219	normalizeNormals() {
11220
11221		const normals = this.attributes.normal;
11222
11223		for (let i = 0, il = normals.count; i < il; i++) {
11224
11225			_vector$8.fromBufferAttribute(normals, i);
11226
11227			_vector$8.normalize();
11228
11229			normals.setXYZ(i, _vector$8.x, _vector$8.y, _vector$8.z);
11230
11231		}
11232
11233	}
11234
11235	toNonIndexed() {
11236
11237		function convertBufferAttribute(attribute, indices) {
11238
11239			const array = attribute.array;
11240			const itemSize = attribute.itemSize;
11241			const normalized = attribute.normalized;
11242
11243			const array2 = new array.constructor(indices.length * itemSize);
11244
11245			let index = 0, index2 = 0;
11246
11247			for (let i = 0, l = indices.length; i < l; i++) {
11248
11249				if (attribute.isInterleavedBufferAttribute) {
11250
11251					index = indices[i] * attribute.data.stride + attribute.offset;
11252
11253				} else {
11254
11255					index = indices[i] * itemSize;
11256
11257				}
11258
11259				for (let j = 0; j < itemSize; j++) {
11260
11261					array2[index2++] = array[index++];
11262
11263				}
11264
11265			}
11266
11267			return new BufferAttribute(array2, itemSize, normalized);
11268
11269		}
11270
11271		//
11272
11273		if (this.index === null) {
11274
11275			console.warn('THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.');
11276			return this;
11277
11278		}
11279
11280		const geometry2 = new BufferGeometry();
11281
11282		const indices = this.index.array;
11283		const attributes = this.attributes;
11284
11285		// attributes
11286
11287		for (const name in attributes) {
11288
11289			const attribute = attributes[name];
11290
11291			const newAttribute = convertBufferAttribute(attribute, indices);
11292
11293			geometry2.setAttribute(name, newAttribute);
11294
11295		}
11296
11297		// morph attributes
11298
11299		const morphAttributes = this.morphAttributes;
11300
11301		for (const name in morphAttributes) {
11302
11303			const morphArray = [];
vendor: 6,640 bytes, lines 11304-11641
11304			const morphAttribute = morphAttributes[name]; // morphAttribute: array of Float32BufferAttributes
11305
11306			for (let i = 0, il = morphAttribute.length; i < il; i++) {
11307
11308				const attribute = morphAttribute[i];
11309
11310				const newAttribute = convertBufferAttribute(attribute, indices);
11311
11312				morphArray.push(newAttribute);
11313
11314			}
11315
11316			geometry2.morphAttributes[name] = morphArray;
11317
11318		}
11319
11320		geometry2.morphTargetsRelative = this.morphTargetsRelative;
11321
11322		// groups
11323
11324		const groups = this.groups;
11325
11326		for (let i = 0, l = groups.length; i < l; i++) {
11327
11328			const group = groups[i];
11329			geometry2.addGroup(group.start, group.count, group.materialIndex);
11330
11331		}
11332
11333		return geometry2;
11334
11335	}
11336
11337	toJSON() {
11338
11339		const data = {
11340			metadata: {
11341				version: 4.6,
11342				type: 'BufferGeometry',
11343				generator: 'BufferGeometry.toJSON'
11344			}
11345		};
11346
11347		// standard BufferGeometry serialization
11348
11349		data.uuid = this.uuid;
11350		data.type = this.type;
11351		if (this.name !== '') data.name = this.name;
11352		if (Object.keys(this.userData).length > 0) data.userData = this.userData;
11353
11354		if (this.parameters !== undefined) {
11355
11356			const parameters = this.parameters;
11357
11358			for (const key in parameters) {
11359
11360				if (parameters[key] !== undefined) data[key] = parameters[key];
11361
11362			}
11363
11364			return data;
11365
11366		}
11367
11368		// for simplicity the code assumes attributes are not shared across geometries, see #15811
11369
11370		data.data = { attributes: {} };
11371
11372		const index = this.index;
11373
11374		if (index !== null) {
11375
11376			data.data.index = {
11377				type: index.array.constructor.name,
11378				array: Array.prototype.slice.call(index.array)
11379			};
11380
11381		}
11382
11383		const attributes = this.attributes;
11384
11385		for (const key in attributes) {
11386
11387			const attribute = attributes[key];
11388
11389			data.data.attributes[key] = attribute.toJSON(data.data);
11390
11391		}
11392
11393		const morphAttributes = {};
11394		let hasMorphAttributes = false;
11395
11396		for (const key in this.morphAttributes) {
11397
11398			const attributeArray = this.morphAttributes[key];
11399
11400			const array = [];
11401
11402			for (let i = 0, il = attributeArray.length; i < il; i++) {
11403
11404				const attribute = attributeArray[i];
11405
11406				array.push(attribute.toJSON(data.data));
11407
11408			}
11409
11410			if (array.length > 0) {
11411
11412				morphAttributes[key] = array;
11413
11414				hasMorphAttributes = true;
11415
11416			}
11417
11418		}
11419
11420		if (hasMorphAttributes) {
11421
11422			data.data.morphAttributes = morphAttributes;
11423			data.data.morphTargetsRelative = this.morphTargetsRelative;
11424
11425		}
11426
11427		const groups = this.groups;
11428
11429		if (groups.length > 0) {
11430
11431			data.data.groups = JSON.parse(JSON.stringify(groups));
11432
11433		}
11434
11435		const boundingSphere = this.boundingSphere;
11436
11437		if (boundingSphere !== null) {
11438
11439			data.data.boundingSphere = {
11440				center: boundingSphere.center.toArray(),
11441				radius: boundingSphere.radius
11442			};
11443
11444		}
11445
11446		return data;
11447
11448	}
11449
11450	clone() {
11451
11452		return new this.constructor().copy(this);
11453
11454	}
11455
11456	copy(source) {
11457
11458		// reset
11459
11460		this.index = null;
11461		this.attributes = {};
11462		this.morphAttributes = {};
11463		this.groups = [];
11464		this.boundingBox = null;
11465		this.boundingSphere = null;
11466
11467		// used for storing cloned, shared data
11468
11469		const data = {};
11470
11471		// name
11472
11473		this.name = source.name;
11474
11475		// index
11476
11477		const index = source.index;
11478
11479		if (index !== null) {
11480
11481			this.setIndex(index.clone(data));
11482
11483		}
11484
11485		// attributes
11486
11487		const attributes = source.attributes;
11488
11489		for (const name in attributes) {
11490
11491			const attribute = attributes[name];
11492			this.setAttribute(name, attribute.clone(data));
11493
11494		}
11495
11496		// morph attributes
11497
11498		const morphAttributes = source.morphAttributes;
11499
11500		for (const name in morphAttributes) {
11501
11502			const array = [];
11503			const morphAttribute = morphAttributes[name]; // morphAttribute: array of Float32BufferAttributes
11504
11505			for (let i = 0, l = morphAttribute.length; i < l; i++) {
11506
11507				array.push(morphAttribute[i].clone(data));
11508
11509			}
11510
11511			this.morphAttributes[name] = array;
11512
11513		}
11514
11515		this.morphTargetsRelative = source.morphTargetsRelative;
11516
11517		// groups
11518
11519		const groups = source.groups;
11520
11521		for (let i = 0, l = groups.length; i < l; i++) {
11522
11523			const group = groups[i];
11524			this.addGroup(group.start, group.count, group.materialIndex);
11525
11526		}
11527
11528		// bounding box
11529
11530		const boundingBox = source.boundingBox;
11531
11532		if (boundingBox !== null) {
11533
11534			this.boundingBox = boundingBox.clone();
11535
11536		}
11537
11538		// bounding sphere
11539
11540		const boundingSphere = source.boundingSphere;
11541
11542		if (boundingSphere !== null) {
11543
11544			this.boundingSphere = boundingSphere.clone();
11545
11546		}
11547
11548		// draw range
11549
11550		this.drawRange.start = source.drawRange.start;
11551		this.drawRange.count = source.drawRange.count;
11552
11553		// user data
11554
11555		this.userData = source.userData;
11556
11557		return this;
11558
11559	}
11560
11561	dispose() {
11562
11563		this.dispatchEvent({ type: 'dispose' });
11564
11565	}
11566
11567}
11568
11569const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4();
11570const _ray$3 = /*@__PURE__*/ new Ray();
11571const _sphere$6 = /*@__PURE__*/ new Sphere();
11572const _sphereHitAt = /*@__PURE__*/ new Vector3();
11573
11574const _vA$1 = /*@__PURE__*/ new Vector3();
11575const _vB$1 = /*@__PURE__*/ new Vector3();
11576const _vC$1 = /*@__PURE__*/ new Vector3();
11577
11578const _tempA = /*@__PURE__*/ new Vector3();
11579const _morphA = /*@__PURE__*/ new Vector3();
11580
11581const _uvA$1 = /*@__PURE__*/ new Vector2();
11582const _uvB$1 = /*@__PURE__*/ new Vector2();
11583const _uvC$1 = /*@__PURE__*/ new Vector2();
11584
11585const _normalA = /*@__PURE__*/ new Vector3();
11586const _normalB = /*@__PURE__*/ new Vector3();
11587const _normalC = /*@__PURE__*/ new Vector3();
11588
11589const _intersectionPoint = /*@__PURE__*/ new Vector3();
11590const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
11591
11592class Mesh extends Object3D {
11593
11594	constructor(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) {
11595
11596		super();
11597
11598		this.isMesh = true;
11599
11600		this.type = 'Mesh';
11601
11602		this.geometry = geometry;
11603		this.material = material;
11604
11605		this.updateMorphTargets();
11606
11607	}
11608
11609	copy(source, recursive) {
11610
11611		super.copy(source, recursive);
11612
11613		if (source.morphTargetInfluences !== undefined) {
11614
11615			this.morphTargetInfluences = source.morphTargetInfluences.slice();
11616
11617		}
11618
11619		if (source.morphTargetDictionary !== undefined) {
11620
11621			this.morphTargetDictionary = Object.assign({}, source.morphTargetDictionary);
11622
11623		}
11624
11625		this.material = Array.isArray(source.material) ? source.material.slice() : source.material;
11626		this.geometry = source.geometry;
11627
11628		return this;
11629
11630	}
11631
11632	updateMorphTargets() {
11633
11634		const geometry = this.geometry;
11635
11636		const morphAttributes = geometry.morphAttributes;
11637		const keys = Object.keys(morphAttributes);
11638
11639		if (keys.length > 0) {
11640
11641			const morphAttribute = morphAttributes[keys[0]];
vendor: 7,934 bytes, lines 11642-11957
11642
11643			if (morphAttribute !== undefined) {
11644
11645				this.morphTargetInfluences = [];
11646				this.morphTargetDictionary = {};
11647
11648				for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
11649
11650					const name = morphAttribute[m].name || String(m);
11651
11652					this.morphTargetInfluences.push(0);
11653					this.morphTargetDictionary[name] = m;
11654
11655				}
11656
11657			}
11658
11659		}
11660
11661	}
11662
11663	getVertexPosition(index, target) {
11664
11665		const geometry = this.geometry;
11666		const position = geometry.attributes.position;
11667		const morphPosition = geometry.morphAttributes.position;
11668		const morphTargetsRelative = geometry.morphTargetsRelative;
11669
11670		target.fromBufferAttribute(position, index);
11671
11672		const morphInfluences = this.morphTargetInfluences;
11673
11674		if (morphPosition && morphInfluences) {
11675
11676			_morphA.set(0, 0, 0);
11677
11678			for (let i = 0, il = morphPosition.length; i < il; i++) {
11679
11680				const influence = morphInfluences[i];
11681				const morphAttribute = morphPosition[i];
11682
11683				if (influence === 0) continue;
11684
11685				_tempA.fromBufferAttribute(morphAttribute, index);
11686
11687				if (morphTargetsRelative) {
11688
11689					_morphA.addScaledVector(_tempA, influence);
11690
11691				} else {
11692
11693					_morphA.addScaledVector(_tempA.sub(target), influence);
11694
11695				}
11696
11697			}
11698
11699			target.add(_morphA);
11700
11701		}
11702
11703		return target;
11704
11705	}
11706
11707	raycast(raycaster, intersects) {
11708
11709		const geometry = this.geometry;
11710		const material = this.material;
11711		const matrixWorld = this.matrixWorld;
11712
11713		if (material === undefined) return;
11714
11715		// test with bounding sphere in world space
11716
11717		if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
11718
11719		_sphere$6.copy(geometry.boundingSphere);
11720		_sphere$6.applyMatrix4(matrixWorld);
11721
11722		// check distance from ray origin to bounding sphere
11723
11724		_ray$3.copy(raycaster.ray).recast(raycaster.near);
11725
11726		if (_sphere$6.containsPoint(_ray$3.origin) === false) {
11727
11728			if (_ray$3.intersectSphere(_sphere$6, _sphereHitAt) === null) return;
11729
11730			if (_ray$3.origin.distanceToSquared(_sphereHitAt) > (raycaster.far - raycaster.near) ** 2) return;
11731
11732		}
11733
11734		// convert ray to local space of mesh
11735
11736		_inverseMatrix$3.copy(matrixWorld).invert();
11737		_ray$3.copy(raycaster.ray).applyMatrix4(_inverseMatrix$3);
11738
11739		// test with bounding box in local space
11740
11741		if (geometry.boundingBox !== null) {
11742
11743			if (_ray$3.intersectsBox(geometry.boundingBox) === false) return;
11744
11745		}
11746
11747		// test for intersections with geometry
11748
11749		this._computeIntersections(raycaster, intersects, _ray$3);
11750
11751	}
11752
11753	_computeIntersections(raycaster, intersects, rayLocalSpace) {
11754
11755		let intersection;
11756
11757		const geometry = this.geometry;
11758		const material = this.material;
11759
11760		const index = geometry.index;
11761		const position = geometry.attributes.position;
11762		const uv = geometry.attributes.uv;
11763		const uv1 = geometry.attributes.uv1;
11764		const normal = geometry.attributes.normal;
11765		const groups = geometry.groups;
11766		const drawRange = geometry.drawRange;
11767
11768		if (index !== null) {
11769
11770			// indexed buffer geometry
11771
11772			if (Array.isArray(material)) {
11773
11774				for (let i = 0, il = groups.length; i < il; i++) {
11775
11776					const group = groups[i];
11777					const groupMaterial = material[group.materialIndex];
11778
11779					const start = Math.max(group.start, drawRange.start);
11780					const end = Math.min(index.count, Math.min((group.start + group.count), (drawRange.start + drawRange.count)));
11781
11782					for (let j = start, jl = end; j < jl; j += 3) {
11783
11784						const a = index.getX(j);
11785						const b = index.getX(j + 1);
11786						const c = index.getX(j + 2);
11787
11788						intersection = checkGeometryIntersection(this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c);
11789
11790						if (intersection) {
11791
11792							intersection.faceIndex = Math.floor(j / 3); // triangle number in indexed buffer semantics
11793							intersection.face.materialIndex = group.materialIndex;
11794							intersects.push(intersection);
11795
11796						}
11797
11798					}
11799
11800				}
11801
11802			} else {
11803
11804				const start = Math.max(0, drawRange.start);
11805				const end = Math.min(index.count, (drawRange.start + drawRange.count));
11806
11807				for (let i = start, il = end; i < il; i += 3) {
11808
11809					const a = index.getX(i);
11810					const b = index.getX(i + 1);
11811					const c = index.getX(i + 2);
11812
11813					intersection = checkGeometryIntersection(this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c);
11814
11815					if (intersection) {
11816
11817						intersection.faceIndex = Math.floor(i / 3); // triangle number in indexed buffer semantics
11818						intersects.push(intersection);
11819
11820					}
11821
11822				}
11823
11824			}
11825
11826		} else if (position !== undefined) {
11827
11828			// non-indexed buffer geometry
11829
11830			if (Array.isArray(material)) {
11831
11832				for (let i = 0, il = groups.length; i < il; i++) {
11833
11834					const group = groups[i];
11835					const groupMaterial = material[group.materialIndex];
11836
11837					const start = Math.max(group.start, drawRange.start);
11838					const end = Math.min(position.count, Math.min((group.start + group.count), (drawRange.start + drawRange.count)));
11839
11840					for (let j = start, jl = end; j < jl; j += 3) {
11841
11842						const a = j;
11843						const b = j + 1;
11844						const c = j + 2;
11845
11846						intersection = checkGeometryIntersection(this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c);
11847
11848						if (intersection) {
11849
11850							intersection.faceIndex = Math.floor(j / 3); // triangle number in non-indexed buffer semantics
11851							intersection.face.materialIndex = group.materialIndex;
11852							intersects.push(intersection);
11853
11854						}
11855
11856					}
11857
11858				}
11859
11860			} else {
11861
11862				const start = Math.max(0, drawRange.start);
11863				const end = Math.min(position.count, (drawRange.start + drawRange.count));
11864
11865				for (let i = start, il = end; i < il; i += 3) {
11866
11867					const a = i;
11868					const b = i + 1;
11869					const c = i + 2;
11870
11871					intersection = checkGeometryIntersection(this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c);
11872
11873					if (intersection) {
11874
11875						intersection.faceIndex = Math.floor(i / 3); // triangle number in non-indexed buffer semantics
11876						intersects.push(intersection);
11877
11878					}
11879
11880				}
11881
11882			}
11883
11884		}
11885
11886	}
11887
11888}
11889
11890function checkIntersection(object, material, raycaster, ray, pA, pB, pC, point) {
11891
11892	let intersect;
11893
11894	if (material.side === BackSide) {
11895
11896		intersect = ray.intersectTriangle(pC, pB, pA, true, point);
11897
11898	} else {
11899
11900		intersect = ray.intersectTriangle(pA, pB, pC, (material.side === FrontSide), point);
11901
11902	}
11903
11904	if (intersect === null) return null;
11905
11906	_intersectionPointWorld.copy(point);
11907	_intersectionPointWorld.applyMatrix4(object.matrixWorld);
11908
11909	const distance = raycaster.ray.origin.distanceTo(_intersectionPointWorld);
11910
11911	if (distance < raycaster.near || distance > raycaster.far) return null;
11912
11913	return {
11914		distance: distance,
11915		point: _intersectionPointWorld.clone(),
11916		object: object
11917	};
11918
11919}
11920
11921function checkGeometryIntersection(object, material, raycaster, ray, uv, uv1, normal, a, b, c) {
11922
11923	object.getVertexPosition(a, _vA$1);
11924	object.getVertexPosition(b, _vB$1);
11925	object.getVertexPosition(c, _vC$1);
11926
11927	const intersection = checkIntersection(object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint);
11928
11929	if (intersection) {
11930
11931		if (uv) {
11932
11933			_uvA$1.fromBufferAttribute(uv, a);
11934			_uvB$1.fromBufferAttribute(uv, b);
11935			_uvC$1.fromBufferAttribute(uv, c);
11936
11937			intersection.uv = Triangle.getInterpolation(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
11938
11939		}
11940
11941		if (uv1) {
11942
11943			_uvA$1.fromBufferAttribute(uv1, a);
11944			_uvB$1.fromBufferAttribute(uv1, b);
11945			_uvC$1.fromBufferAttribute(uv1, c);
11946
11947			intersection.uv1 = Triangle.getInterpolation(_intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2());
11948			intersection.uv2 = intersection.uv1; // @deprecated, r152
11949
11950		}
11951
11952		if (normal) {
11953
11954			_normalA.fromBufferAttribute(normal, a);
11955			_normalB.fromBufferAttribute(normal, b);
11956			_normalC.fromBufferAttribute(normal, c);
11957
vendor: 42,323 bytes, lines 11958-13846
11958			intersection.normal = Triangle.getInterpolation(_intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3());
11959
11960			if (intersection.normal.dot(ray.direction) > 0) {
11961
11962				intersection.normal.multiplyScalar(- 1);
11963
11964			}
11965
11966		}
11967
11968		const face = {
11969			a: a,
11970			b: b,
11971			c: c,
11972			normal: new Vector3(),
11973			materialIndex: 0
11974		};
11975
11976		Triangle.getNormal(_vA$1, _vB$1, _vC$1, face.normal);
11977
11978		intersection.face = face;
11979
11980	}
11981
11982	return intersection;
11983
11984}
11985
11986class BoxGeometry extends BufferGeometry {
11987
11988	constructor(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) {
11989
11990		super();
11991
11992		this.type = 'BoxGeometry';
11993
11994		this.parameters = {
11995			width: width,
11996			height: height,
11997			depth: depth,
11998			widthSegments: widthSegments,
11999			heightSegments: heightSegments,
12000			depthSegments: depthSegments
12001		};
12002
12003		const scope = this;
12004
12005		// segments
12006
12007		widthSegments = Math.floor(widthSegments);
12008		heightSegments = Math.floor(heightSegments);
12009		depthSegments = Math.floor(depthSegments);
12010
12011		// buffers
12012
12013		const indices = [];
12014		const vertices = [];
12015		const normals = [];
12016		const uvs = [];
12017
12018		// helper variables
12019
12020		let numberOfVertices = 0;
12021		let groupStart = 0;
12022
12023		// build each side of the box geometry
12024
12025		buildPlane('z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0); // px
12026		buildPlane('z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1); // nx
12027		buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2); // py
12028		buildPlane('x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3); // ny
12029		buildPlane('x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4); // pz
12030		buildPlane('x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5); // nz
12031
12032		// build geometry
12033
12034		this.setIndex(indices);
12035		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
12036		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
12037		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
12038
12039		function buildPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex) {
12040
12041			const segmentWidth = width / gridX;
12042			const segmentHeight = height / gridY;
12043
12044			const widthHalf = width / 2;
12045			const heightHalf = height / 2;
12046			const depthHalf = depth / 2;
12047
12048			const gridX1 = gridX + 1;
12049			const gridY1 = gridY + 1;
12050
12051			let vertexCounter = 0;
12052			let groupCount = 0;
12053
12054			const vector = new Vector3();
12055
12056			// generate vertices, normals and uvs
12057
12058			for (let iy = 0; iy < gridY1; iy++) {
12059
12060				const y = iy * segmentHeight - heightHalf;
12061
12062				for (let ix = 0; ix < gridX1; ix++) {
12063
12064					const x = ix * segmentWidth - widthHalf;
12065
12066					// set values to correct vector component
12067
12068					vector[u] = x * udir;
12069					vector[v] = y * vdir;
12070					vector[w] = depthHalf;
12071
12072					// now apply vector to vertex buffer
12073
12074					vertices.push(vector.x, vector.y, vector.z);
12075
12076					// set values to correct vector component
12077
12078					vector[u] = 0;
12079					vector[v] = 0;
12080					vector[w] = depth > 0 ? 1 : - 1;
12081
12082					// now apply vector to normal buffer
12083
12084					normals.push(vector.x, vector.y, vector.z);
12085
12086					// uvs
12087
12088					uvs.push(ix / gridX);
12089					uvs.push(1 - (iy / gridY));
12090
12091					// counters
12092
12093					vertexCounter += 1;
12094
12095				}
12096
12097			}
12098
12099			// indices
12100
12101			// 1. you need three indices to draw a single face
12102			// 2. a single segment consists of two faces
12103			// 3. so we need to generate six (2*3) indices per segment
12104
12105			for (let iy = 0; iy < gridY; iy++) {
12106
12107				for (let ix = 0; ix < gridX; ix++) {
12108
12109					const a = numberOfVertices + ix + gridX1 * iy;
12110					const b = numberOfVertices + ix + gridX1 * (iy + 1);
12111					const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
12112					const d = numberOfVertices + (ix + 1) + gridX1 * iy;
12113
12114					// faces
12115
12116					indices.push(a, b, d);
12117					indices.push(b, c, d);
12118
12119					// increase counter
12120
12121					groupCount += 6;
12122
12123				}
12124
12125			}
12126
12127			// add a group to the geometry. this will ensure multi material support
12128
12129			scope.addGroup(groupStart, groupCount, materialIndex);
12130
12131			// calculate new start value for groups
12132
12133			groupStart += groupCount;
12134
12135			// update total number of vertices
12136
12137			numberOfVertices += vertexCounter;
12138
12139		}
12140
12141	}
12142
12143	copy(source) {
12144
12145		super.copy(source);
12146
12147		this.parameters = Object.assign({}, source.parameters);
12148
12149		return this;
12150
12151	}
12152
12153	static fromJSON(data) {
12154
12155		return new BoxGeometry(data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments);
12156
12157	}
12158
12159}
12160
12161/**
12162 * Uniform Utilities
12163 */
12164
12165function cloneUniforms(src) {
12166
12167	const dst = {};
12168
12169	for (const u in src) {
12170
12171		dst[u] = {};
12172
12173		for (const p in src[u]) {
12174
12175			const property = src[u][p];
12176
12177			if (property && (property.isColor ||
12178				property.isMatrix3 || property.isMatrix4 ||
12179				property.isVector2 || property.isVector3 || property.isVector4 ||
12180				property.isTexture || property.isQuaternion)) {
12181
12182				if (property.isRenderTargetTexture) {
12183
12184					console.warn('UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().');
12185					dst[u][p] = null;
12186
12187				} else {
12188
12189					dst[u][p] = property.clone();
12190
12191				}
12192
12193			} else if (Array.isArray(property)) {
12194
12195				dst[u][p] = property.slice();
12196
12197			} else {
12198
12199				dst[u][p] = property;
12200
12201			}
12202
12203		}
12204
12205	}
12206
12207	return dst;
12208
12209}
12210
12211function mergeUniforms(uniforms) {
12212
12213	const merged = {};
12214
12215	for (let u = 0; u < uniforms.length; u++) {
12216
12217		const tmp = cloneUniforms(uniforms[u]);
12218
12219		for (const p in tmp) {
12220
12221			merged[p] = tmp[p];
12222
12223		}
12224
12225	}
12226
12227	return merged;
12228
12229}
12230
12231function cloneUniformsGroups(src) {
12232
12233	const dst = [];
12234
12235	for (let u = 0; u < src.length; u++) {
12236
12237		dst.push(src[u].clone());
12238
12239	}
12240
12241	return dst;
12242
12243}
12244
12245function getUnlitUniformColorSpace(renderer) {
12246
12247	if (renderer.getRenderTarget() === null) {
12248
12249		// https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398
12250		return renderer.outputColorSpace;
12251
12252	}
12253
12254	return ColorManagement.workingColorSpace;
12255
12256}
12257
12258// Legacy
12259
12260const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
12261
12262var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
12263
12264var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
12265
12266class ShaderMaterial extends Material {
12267
12268	constructor(parameters) {
12269
12270		super();
12271
12272		this.isShaderMaterial = true;
12273
12274		this.type = 'ShaderMaterial';
12275
12276		this.defines = {};
12277		this.uniforms = {};
12278		this.uniformsGroups = [];
12279
12280		this.vertexShader = default_vertex;
12281		this.fragmentShader = default_fragment;
12282
12283		this.linewidth = 1;
12284
12285		this.wireframe = false;
12286		this.wireframeLinewidth = 1;
12287
12288		this.fog = false; // set to use scene fog
12289		this.lights = false; // set to use scene lights
12290		this.clipping = false; // set to use user-defined clipping planes
12291
12292		this.forceSinglePass = true;
12293
12294		this.extensions = {
12295			derivatives: false, // set to use derivatives
12296			fragDepth: false, // set to use fragment depth values
12297			drawBuffers: false, // set to use draw buffers
12298			shaderTextureLOD: false, // set to use shader texture LOD
12299			clipCullDistance: false // set to use vertex shader clipping
12300		};
12301
12302		// When rendered geometry doesn't include these attributes but the material does,
12303		// use these default values in WebGL. This avoids errors when buffer data is missing.
12304		this.defaultAttributeValues = {
12305			'color': [1, 1, 1],
12306			'uv': [0, 0],
12307			'uv1': [0, 0]
12308		};
12309
12310		this.index0AttributeName = undefined;
12311		this.uniformsNeedUpdate = false;
12312
12313		this.glslVersion = null;
12314
12315		if (parameters !== undefined) {
12316
12317			this.setValues(parameters);
12318
12319		}
12320
12321	}
12322
12323	copy(source) {
12324
12325		super.copy(source);
12326
12327		this.fragmentShader = source.fragmentShader;
12328		this.vertexShader = source.vertexShader;
12329
12330		this.uniforms = cloneUniforms(source.uniforms);
12331		this.uniformsGroups = cloneUniformsGroups(source.uniformsGroups);
12332
12333		this.defines = Object.assign({}, source.defines);
12334
12335		this.wireframe = source.wireframe;
12336		this.wireframeLinewidth = source.wireframeLinewidth;
12337
12338		this.fog = source.fog;
12339		this.lights = source.lights;
12340		this.clipping = source.clipping;
12341
12342		this.extensions = Object.assign({}, source.extensions);
12343
12344		this.glslVersion = source.glslVersion;
12345
12346		return this;
12347
12348	}
12349
12350	toJSON(meta) {
12351
12352		const data = super.toJSON(meta);
12353
12354		data.glslVersion = this.glslVersion;
12355		data.uniforms = {};
12356
12357		for (const name in this.uniforms) {
12358
12359			const uniform = this.uniforms[name];
12360			const value = uniform.value;
12361
12362			if (value && value.isTexture) {
12363
12364				data.uniforms[name] = {
12365					type: 't',
12366					value: value.toJSON(meta).uuid
12367				};
12368
12369			} else if (value && value.isColor) {
12370
12371				data.uniforms[name] = {
12372					type: 'c',
12373					value: value.getHex()
12374				};
12375
12376			} else if (value && value.isVector2) {
12377
12378				data.uniforms[name] = {
12379					type: 'v2',
12380					value: value.toArray()
12381				};
12382
12383			} else if (value && value.isVector3) {
12384
12385				data.uniforms[name] = {
12386					type: 'v3',
12387					value: value.toArray()
12388				};
12389
12390			} else if (value && value.isVector4) {
12391
12392				data.uniforms[name] = {
12393					type: 'v4',
12394					value: value.toArray()
12395				};
12396
12397			} else if (value && value.isMatrix3) {
12398
12399				data.uniforms[name] = {
12400					type: 'm3',
12401					value: value.toArray()
12402				};
12403
12404			} else if (value && value.isMatrix4) {
12405
12406				data.uniforms[name] = {
12407					type: 'm4',
12408					value: value.toArray()
12409				};
12410
12411			} else {
12412
12413				data.uniforms[name] = {
12414					value: value
12415				};
12416
12417				// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
12418
12419			}
12420
12421		}
12422
12423		if (Object.keys(this.defines).length > 0) data.defines = this.defines;
12424
12425		data.vertexShader = this.vertexShader;
12426		data.fragmentShader = this.fragmentShader;
12427
12428		data.lights = this.lights;
12429		data.clipping = this.clipping;
12430
12431		const extensions = {};
12432
12433		for (const key in this.extensions) {
12434
12435			if (this.extensions[key] === true) extensions[key] = true;
12436
12437		}
12438
12439		if (Object.keys(extensions).length > 0) data.extensions = extensions;
12440
12441		return data;
12442
12443	}
12444
12445}
12446
12447class Camera extends Object3D {
12448
12449	constructor() {
12450
12451		super();
12452
12453		this.isCamera = true;
12454
12455		this.type = 'Camera';
12456
12457		this.matrixWorldInverse = new Matrix4();
12458
12459		this.projectionMatrix = new Matrix4();
12460		this.projectionMatrixInverse = new Matrix4();
12461
12462		this.coordinateSystem = WebGLCoordinateSystem;
12463
12464	}
12465
12466	copy(source, recursive) {
12467
12468		super.copy(source, recursive);
12469
12470		this.matrixWorldInverse.copy(source.matrixWorldInverse);
12471
12472		this.projectionMatrix.copy(source.projectionMatrix);
12473		this.projectionMatrixInverse.copy(source.projectionMatrixInverse);
12474
12475		this.coordinateSystem = source.coordinateSystem;
12476
12477		return this;
12478
12479	}
12480
12481	getWorldDirection(target) {
12482
12483		return super.getWorldDirection(target).negate();
12484
12485	}
12486
12487	updateMatrixWorld(force) {
12488
12489		super.updateMatrixWorld(force);
12490
12491		this.matrixWorldInverse.copy(this.matrixWorld).invert();
12492
12493	}
12494
12495	updateWorldMatrix(updateParents, updateChildren) {
12496
12497		super.updateWorldMatrix(updateParents, updateChildren);
12498
12499		this.matrixWorldInverse.copy(this.matrixWorld).invert();
12500
12501	}
12502
12503	clone() {
12504
12505		return new this.constructor().copy(this);
12506
12507	}
12508
12509}
12510
12511class PerspectiveCamera extends Camera {
12512
12513	constructor(fov = 50, aspect = 1, near = 0.1, far = 2000) {
12514
12515		super();
12516
12517		this.isPerspectiveCamera = true;
12518
12519		this.type = 'PerspectiveCamera';
12520
12521		this.fov = fov;
12522		this.zoom = 1;
12523
12524		this.near = near;
12525		this.far = far;
12526		this.focus = 10;
12527
12528		this.aspect = aspect;
12529		this.view = null;
12530
12531		this.filmGauge = 35;	// width of the film (default in millimeters)
12532		this.filmOffset = 0;	// horizontal film offset (same unit as gauge)
12533
12534		this.updateProjectionMatrix();
12535
12536	}
12537
12538	copy(source, recursive) {
12539
12540		super.copy(source, recursive);
12541
12542		this.fov = source.fov;
12543		this.zoom = source.zoom;
12544
12545		this.near = source.near;
12546		this.far = source.far;
12547		this.focus = source.focus;
12548
12549		this.aspect = source.aspect;
12550		this.view = source.view === null ? null : Object.assign({}, source.view);
12551
12552		this.filmGauge = source.filmGauge;
12553		this.filmOffset = source.filmOffset;
12554
12555		return this;
12556
12557	}
12558
12559	/**
12560	 * Sets the FOV by focal length in respect to the current .filmGauge.
12561	 *
12562	 * The default film gauge is 35, so that the focal length can be specified for
12563	 * a 35mm (full frame) camera.
12564	 *
12565	 * Values for focal length and film gauge must have the same unit.
12566	 */
12567	setFocalLength(focalLength) {
12568
12569		/** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
12570		const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
12571
12572		this.fov = RAD2DEG * 2 * Math.atan(vExtentSlope);
12573		this.updateProjectionMatrix();
12574
12575	}
12576
12577	/**
12578	 * Calculates the focal length from the current .fov and .filmGauge.
12579	 */
12580	getFocalLength() {
12581
12582		const vExtentSlope = Math.tan(DEG2RAD * 0.5 * this.fov);
12583
12584		return 0.5 * this.getFilmHeight() / vExtentSlope;
12585
12586	}
12587
12588	getEffectiveFOV() {
12589
12590		return RAD2DEG * 2 * Math.atan(
12591			Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom);
12592
12593	}
12594
12595	getFilmWidth() {
12596
12597		// film not completely covered in portrait format (aspect < 1)
12598		return this.filmGauge * Math.min(this.aspect, 1);
12599
12600	}
12601
12602	getFilmHeight() {
12603
12604		// film not completely covered in landscape format (aspect > 1)
12605		return this.filmGauge / Math.max(this.aspect, 1);
12606
12607	}
12608
12609	/**
12610	 * Sets an offset in a larger frustum. This is useful for multi-window or
12611	 * multi-monitor/multi-machine setups.
12612	 *
12613	 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
12614	 * the monitors are in grid like this
12615	 *
12616	 *   +---+---+---+
12617	 *   | A | B | C |
12618	 *   +---+---+---+
12619	 *   | D | E | F |
12620	 *   +---+---+---+
12621	 *
12622	 * then for each monitor you would call it like this
12623	 *
12624	 *   const w = 1920;
12625	 *   const h = 1080;
12626	 *   const fullWidth = w * 3;
12627	 *   const fullHeight = h * 2;
12628	 *
12629	 *   --A--
12630	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
12631	 *   --B--
12632	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
12633	 *   --C--
12634	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
12635	 *   --D--
12636	 *   camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
12637	 *   --E--
12638	 *   camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
12639	 *   --F--
12640	 *   camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
12641	 *
12642	 *   Note there is no reason monitors have to be the same size or in a grid.
12643	 */
12644	setViewOffset(fullWidth, fullHeight, x, y, width, height) {
12645
12646		this.aspect = fullWidth / fullHeight;
12647
12648		if (this.view === null) {
12649
12650			this.view = {
12651				enabled: true,
12652				fullWidth: 1,
12653				fullHeight: 1,
12654				offsetX: 0,
12655				offsetY: 0,
12656				width: 1,
12657				height: 1
12658			};
12659
12660		}
12661
12662		this.view.enabled = true;
12663		this.view.fullWidth = fullWidth;
12664		this.view.fullHeight = fullHeight;
12665		this.view.offsetX = x;
12666		this.view.offsetY = y;
12667		this.view.width = width;
12668		this.view.height = height;
12669
12670		this.updateProjectionMatrix();
12671
12672	}
12673
12674	clearViewOffset() {
12675
12676		if (this.view !== null) {
12677
12678			this.view.enabled = false;
12679
12680		}
12681
12682		this.updateProjectionMatrix();
12683
12684	}
12685
12686	updateProjectionMatrix() {
12687
12688		const near = this.near;
12689		let top = near * Math.tan(DEG2RAD * 0.5 * this.fov) / this.zoom;
12690		let height = 2 * top;
12691		let width = this.aspect * height;
12692		let left = - 0.5 * width;
12693		const view = this.view;
12694
12695		if (this.view !== null && this.view.enabled) {
12696
12697			const fullWidth = view.fullWidth,
12698				fullHeight = view.fullHeight;
12699
12700			left += view.offsetX * width / fullWidth;
12701			top -= view.offsetY * height / fullHeight;
12702			width *= view.width / fullWidth;
12703			height *= view.height / fullHeight;
12704
12705		}
12706
12707		const skew = this.filmOffset;
12708		if (skew !== 0) left += near * skew / this.getFilmWidth();
12709
12710		this.projectionMatrix.makePerspective(left, left + width, top, top - height, near, this.far, this.coordinateSystem);
12711
12712		this.projectionMatrixInverse.copy(this.projectionMatrix).invert();
12713
12714	}
12715
12716	toJSON(meta) {
12717
12718		const data = super.toJSON(meta);
12719
12720		data.object.fov = this.fov;
12721		data.object.zoom = this.zoom;
12722
12723		data.object.near = this.near;
12724		data.object.far = this.far;
12725		data.object.focus = this.focus;
12726
12727		data.object.aspect = this.aspect;
12728
12729		if (this.view !== null) data.object.view = Object.assign({}, this.view);
12730
12731		data.object.filmGauge = this.filmGauge;
12732		data.object.filmOffset = this.filmOffset;
12733
12734		return data;
12735
12736	}
12737
12738}
12739
12740const fov = - 90; // negative fov is not an error
12741const aspect = 1;
12742
12743class CubeCamera extends Object3D {
12744
12745	constructor(near, far, renderTarget) {
12746
12747		super();
12748
12749		this.type = 'CubeCamera';
12750
12751		this.renderTarget = renderTarget;
12752		this.coordinateSystem = null;
12753		this.activeMipmapLevel = 0;
12754
12755		const cameraPX = new PerspectiveCamera(fov, aspect, near, far);
12756		cameraPX.layers = this.layers;
12757		this.add(cameraPX);
12758
12759		const cameraNX = new PerspectiveCamera(fov, aspect, near, far);
12760		cameraNX.layers = this.layers;
12761		this.add(cameraNX);
12762
12763		const cameraPY = new PerspectiveCamera(fov, aspect, near, far);
12764		cameraPY.layers = this.layers;
12765		this.add(cameraPY);
12766
12767		const cameraNY = new PerspectiveCamera(fov, aspect, near, far);
12768		cameraNY.layers = this.layers;
12769		this.add(cameraNY);
12770
12771		const cameraPZ = new PerspectiveCamera(fov, aspect, near, far);
12772		cameraPZ.layers = this.layers;
12773		this.add(cameraPZ);
12774
12775		const cameraNZ = new PerspectiveCamera(fov, aspect, near, far);
12776		cameraNZ.layers = this.layers;
12777		this.add(cameraNZ);
12778
12779	}
12780
12781	updateCoordinateSystem() {
12782
12783		const coordinateSystem = this.coordinateSystem;
12784
12785		const cameras = this.children.concat();
12786
12787		const [cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ] = cameras;
12788
12789		for (const camera of cameras) this.remove(camera);
12790
12791		if (coordinateSystem === WebGLCoordinateSystem) {
12792
12793			cameraPX.up.set(0, 1, 0);
12794			cameraPX.lookAt(1, 0, 0);
12795
12796			cameraNX.up.set(0, 1, 0);
12797			cameraNX.lookAt(- 1, 0, 0);
12798
12799			cameraPY.up.set(0, 0, - 1);
12800			cameraPY.lookAt(0, 1, 0);
12801
12802			cameraNY.up.set(0, 0, 1);
12803			cameraNY.lookAt(0, - 1, 0);
12804
12805			cameraPZ.up.set(0, 1, 0);
12806			cameraPZ.lookAt(0, 0, 1);
12807
12808			cameraNZ.up.set(0, 1, 0);
12809			cameraNZ.lookAt(0, 0, - 1);
12810
12811		} else if (coordinateSystem === WebGPUCoordinateSystem) {
12812
12813			cameraPX.up.set(0, - 1, 0);
12814			cameraPX.lookAt(- 1, 0, 0);
12815
12816			cameraNX.up.set(0, - 1, 0);
12817			cameraNX.lookAt(1, 0, 0);
12818
12819			cameraPY.up.set(0, 0, 1);
12820			cameraPY.lookAt(0, 1, 0);
12821
12822			cameraNY.up.set(0, 0, - 1);
12823			cameraNY.lookAt(0, - 1, 0);
12824
12825			cameraPZ.up.set(0, - 1, 0);
12826			cameraPZ.lookAt(0, 0, 1);
12827
12828			cameraNZ.up.set(0, - 1, 0);
12829			cameraNZ.lookAt(0, 0, - 1);
12830
12831		} else {
12832
12833			throw new Error('THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem);
12834
12835		}
12836
12837		for (const camera of cameras) {
12838
12839			this.add(camera);
12840
12841			camera.updateMatrixWorld();
12842
12843		}
12844
12845	}
12846
12847	update(renderer, scene) {
12848
12849		if (this.parent === null) this.updateMatrixWorld();
12850
12851		const { renderTarget, activeMipmapLevel } = this;
12852
12853		if (this.coordinateSystem !== renderer.coordinateSystem) {
12854
12855			this.coordinateSystem = renderer.coordinateSystem;
12856
12857			this.updateCoordinateSystem();
12858
12859		}
12860
12861		const [cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ] = this.children;
12862
12863		const currentRenderTarget = renderer.getRenderTarget();
12864		const currentActiveCubeFace = renderer.getActiveCubeFace();
12865		const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
12866
12867		const currentXrEnabled = renderer.xr.enabled;
12868
12869		renderer.xr.enabled = false;
12870
12871		const generateMipmaps = renderTarget.texture.generateMipmaps;
12872
12873		renderTarget.texture.generateMipmaps = false;
12874
12875		renderer.setRenderTarget(renderTarget, 0, activeMipmapLevel);
12876		renderer.render(scene, cameraPX);
12877
12878		renderer.setRenderTarget(renderTarget, 1, activeMipmapLevel);
12879		renderer.render(scene, cameraNX);
12880
12881		renderer.setRenderTarget(renderTarget, 2, activeMipmapLevel);
12882		renderer.render(scene, cameraPY);
12883
12884		renderer.setRenderTarget(renderTarget, 3, activeMipmapLevel);
12885		renderer.render(scene, cameraNY);
12886
12887		renderer.setRenderTarget(renderTarget, 4, activeMipmapLevel);
12888		renderer.render(scene, cameraPZ);
12889
12890		// mipmaps are generated during the last call of render()
12891		// at this point, all sides of the cube render target are defined
12892
12893		renderTarget.texture.generateMipmaps = generateMipmaps;
12894
12895		renderer.setRenderTarget(renderTarget, 5, activeMipmapLevel);
12896		renderer.render(scene, cameraNZ);
12897
12898		renderer.setRenderTarget(currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel);
12899
12900		renderer.xr.enabled = currentXrEnabled;
12901
12902		renderTarget.texture.needsPMREMUpdate = true;
12903
12904	}
12905
12906}
12907
12908class CubeTexture extends Texture {
12909
12910	constructor(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace) {
12911
12912		images = images !== undefined ? images : [];
12913		mapping = mapping !== undefined ? mapping : CubeReflectionMapping;
12914
12915		super(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace);
12916
12917		this.isCubeTexture = true;
12918
12919		this.flipY = false;
12920
12921	}
12922
12923	get images() {
12924
12925		return this.image;
12926
12927	}
12928
12929	set images(value) {
12930
12931		this.image = value;
12932
12933	}
12934
12935}
12936
12937class WebGLCubeRenderTarget extends WebGLRenderTarget {
12938
12939	constructor(size = 1, options = {}) {
12940
12941		super(size, size, options);
12942
12943		this.isWebGLCubeRenderTarget = true;
12944
12945		const image = { width: size, height: size, depth: 1 };
12946		const images = [image, image, image, image, image, image];
12947
12948		if (options.encoding !== undefined) {
12949
12950			// @deprecated, r152
12951			warnOnce('THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.');
12952			options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
12953
12954		}
12955
12956		this.texture = new CubeTexture(images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace);
12957
12958		// By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
12959		// in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
12960		// in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
12961
12962		// three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
12963		// and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
12964		// as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
12965
12966		this.texture.isRenderTargetTexture = true;
12967
12968		this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
12969		this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
12970
12971	}
12972
12973	fromEquirectangularTexture(renderer, texture) {
12974
12975		this.texture.type = texture.type;
12976		this.texture.colorSpace = texture.colorSpace;
12977
12978		this.texture.generateMipmaps = texture.generateMipmaps;
12979		this.texture.minFilter = texture.minFilter;
12980		this.texture.magFilter = texture.magFilter;
12981
12982		const shader = {
12983
12984			uniforms: {
12985				tEquirect: { value: null },
12986			},
12987
12988			vertexShader: /* glsl */`
12989
12990				varying vec3 vWorldDirection;
12991
12992				vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
12993
12994					return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
12995
12996				}
12997
12998				void main() {
12999
13000					vWorldDirection = transformDirection( position, modelMatrix );
13001
13002					#include <begin_vertex>
13003					#include <project_vertex>
13004
13005				}
13006			`,
13007
13008			fragmentShader: /* glsl */`
13009
13010				uniform sampler2D tEquirect;
13011
13012				varying vec3 vWorldDirection;
13013
13014				#include <common>
13015
13016				void main() {
13017
13018					vec3 direction = normalize( vWorldDirection );
13019
13020					vec2 sampleUV = equirectUv( direction );
13021
13022					gl_FragColor = texture2D( tEquirect, sampleUV );
13023
13024				}
13025			`
13026		};
13027
13028		const geometry = new BoxGeometry(5, 5, 5);
13029
13030		const material = new ShaderMaterial({
13031
13032			name: 'CubemapFromEquirect',
13033
13034			uniforms: cloneUniforms(shader.uniforms),
13035			vertexShader: shader.vertexShader,
13036			fragmentShader: shader.fragmentShader,
13037			side: BackSide,
13038			blending: NoBlending
13039
13040		});
13041
13042		material.uniforms.tEquirect.value = texture;
13043
13044		const mesh = new Mesh(geometry, material);
13045
13046		const currentMinFilter = texture.minFilter;
13047
13048		// Avoid blurred poles
13049		if (texture.minFilter === LinearMipmapLinearFilter) texture.minFilter = LinearFilter;
13050
13051		const camera = new CubeCamera(1, 10, this);
13052		camera.update(renderer, mesh);
13053
13054		texture.minFilter = currentMinFilter;
13055
13056		mesh.geometry.dispose();
13057		mesh.material.dispose();
13058
13059		return this;
13060
13061	}
13062
13063	clear(renderer, color, depth, stencil) {
13064
13065		const currentRenderTarget = renderer.getRenderTarget();
13066
13067		for (let i = 0; i < 6; i++) {
13068
13069			renderer.setRenderTarget(this, i);
13070
13071			renderer.clear(color, depth, stencil);
13072
13073		}
13074
13075		renderer.setRenderTarget(currentRenderTarget);
13076
13077	}
13078
13079}
13080
13081const _vector1 = /*@__PURE__*/ new Vector3();
13082const _vector2 = /*@__PURE__*/ new Vector3();
13083const _normalMatrix = /*@__PURE__*/ new Matrix3();
13084
13085class Plane {
13086
13087	constructor(normal = new Vector3(1, 0, 0), constant = 0) {
13088
13089		this.isPlane = true;
13090
13091		// normal is assumed to be normalized
13092
13093		this.normal = normal;
13094		this.constant = constant;
13095
13096	}
13097
13098	set(normal, constant) {
13099
13100		this.normal.copy(normal);
13101		this.constant = constant;
13102
13103		return this;
13104
13105	}
13106
13107	setComponents(x, y, z, w) {
13108
13109		this.normal.set(x, y, z);
13110		this.constant = w;
13111
13112		return this;
13113
13114	}
13115
13116	setFromNormalAndCoplanarPoint(normal, point) {
13117
13118		this.normal.copy(normal);
13119		this.constant = - point.dot(this.normal);
13120
13121		return this;
13122
13123	}
13124
13125	setFromCoplanarPoints(a, b, c) {
13126
13127		const normal = _vector1.subVectors(c, b).cross(_vector2.subVectors(a, b)).normalize();
13128
13129		// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
13130
13131		this.setFromNormalAndCoplanarPoint(normal, a);
13132
13133		return this;
13134
13135	}
13136
13137	copy(plane) {
13138
13139		this.normal.copy(plane.normal);
13140		this.constant = plane.constant;
13141
13142		return this;
13143
13144	}
13145
13146	normalize() {
13147
13148		// Note: will lead to a divide by zero if the plane is invalid.
13149
13150		const inverseNormalLength = 1.0 / this.normal.length();
13151		this.normal.multiplyScalar(inverseNormalLength);
13152		this.constant *= inverseNormalLength;
13153
13154		return this;
13155
13156	}
13157
13158	negate() {
13159
13160		this.constant *= - 1;
13161		this.normal.negate();
13162
13163		return this;
13164
13165	}
13166
13167	distanceToPoint(point) {
13168
13169		return this.normal.dot(point) + this.constant;
13170
13171	}
13172
13173	distanceToSphere(sphere) {
13174
13175		return this.distanceToPoint(sphere.center) - sphere.radius;
13176
13177	}
13178
13179	projectPoint(point, target) {
13180
13181		return target.copy(point).addScaledVector(this.normal, - this.distanceToPoint(point));
13182
13183	}
13184
13185	intersectLine(line, target) {
13186
13187		const direction = line.delta(_vector1);
13188
13189		const denominator = this.normal.dot(direction);
13190
13191		if (denominator === 0) {
13192
13193			// line is coplanar, return origin
13194			if (this.distanceToPoint(line.start) === 0) {
13195
13196				return target.copy(line.start);
13197
13198			}
13199
13200			// Unsure if this is the correct method to handle this case.
13201			return null;
13202
13203		}
13204
13205		const t = - (line.start.dot(this.normal) + this.constant) / denominator;
13206
13207		if (t < 0 || t > 1) {
13208
13209			return null;
13210
13211		}
13212
13213		return target.copy(line.start).addScaledVector(direction, t);
13214
13215	}
13216
13217	intersectsLine(line) {
13218
13219		// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
13220
13221		const startSign = this.distanceToPoint(line.start);
13222		const endSign = this.distanceToPoint(line.end);
13223
13224		return (startSign < 0 && endSign > 0) || (endSign < 0 && startSign > 0);
13225
13226	}
13227
13228	intersectsBox(box) {
13229
13230		return box.intersectsPlane(this);
13231
13232	}
13233
13234	intersectsSphere(sphere) {
13235
13236		return sphere.intersectsPlane(this);
13237
13238	}
13239
13240	coplanarPoint(target) {
13241
13242		return target.copy(this.normal).multiplyScalar(- this.constant);
13243
13244	}
13245
13246	applyMatrix4(matrix, optionalNormalMatrix) {
13247
13248		const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix(matrix);
13249
13250		const referencePoint = this.coplanarPoint(_vector1).applyMatrix4(matrix);
13251
13252		const normal = this.normal.applyMatrix3(normalMatrix).normalize();
13253
13254		this.constant = - referencePoint.dot(normal);
13255
13256		return this;
13257
13258	}
13259
13260	translate(offset) {
13261
13262		this.constant -= offset.dot(this.normal);
13263
13264		return this;
13265
13266	}
13267
13268	equals(plane) {
13269
13270		return plane.normal.equals(this.normal) && (plane.constant === this.constant);
13271
13272	}
13273
13274	clone() {
13275
13276		return new this.constructor().copy(this);
13277
13278	}
13279
13280}
13281
13282const _sphere$5 = /*@__PURE__*/ new Sphere();
13283const _vector$7 = /*@__PURE__*/ new Vector3();
13284
13285class Frustum {
13286
13287	constructor(p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane()) {
13288
13289		this.planes = [p0, p1, p2, p3, p4, p5];
13290
13291	}
13292
13293	set(p0, p1, p2, p3, p4, p5) {
13294
13295		const planes = this.planes;
13296
13297		planes[0].copy(p0);
13298		planes[1].copy(p1);
13299		planes[2].copy(p2);
13300		planes[3].copy(p3);
13301		planes[4].copy(p4);
13302		planes[5].copy(p5);
13303
13304		return this;
13305
13306	}
13307
13308	copy(frustum) {
13309
13310		const planes = this.planes;
13311
13312		for (let i = 0; i < 6; i++) {
13313
13314			planes[i].copy(frustum.planes[i]);
13315
13316		}
13317
13318		return this;
13319
13320	}
13321
13322	setFromProjectionMatrix(m, coordinateSystem = WebGLCoordinateSystem) {
13323
13324		const planes = this.planes;
13325		const me = m.elements;
13326		const me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
13327		const me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
13328		const me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
13329		const me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
13330
13331		planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize();
13332		planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize();
13333		planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize();
13334		planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize();
13335		planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize();
13336
13337		if (coordinateSystem === WebGLCoordinateSystem) {
13338
13339			planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize();
13340
13341		} else if (coordinateSystem === WebGPUCoordinateSystem) {
13342
13343			planes[5].setComponents(me2, me6, me10, me14).normalize();
13344
13345		} else {
13346
13347			throw new Error('THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem);
13348
13349		}
13350
13351		return this;
13352
13353	}
13354
13355	intersectsObject(object) {
13356
13357		if (object.boundingSphere !== undefined) {
13358
13359			if (object.boundingSphere === null) object.computeBoundingSphere();
13360
13361			_sphere$5.copy(object.boundingSphere).applyMatrix4(object.matrixWorld);
13362
13363		} else {
13364
13365			const geometry = object.geometry;
13366
13367			if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
13368
13369			_sphere$5.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld);
13370
13371		}
13372
13373		return this.intersectsSphere(_sphere$5);
13374
13375	}
13376
13377	intersectsSprite(sprite) {
13378
13379		_sphere$5.center.set(0, 0, 0);
13380		_sphere$5.radius = 0.7071067811865476;
13381		_sphere$5.applyMatrix4(sprite.matrixWorld);
13382
13383		return this.intersectsSphere(_sphere$5);
13384
13385	}
13386
13387	intersectsSphere(sphere) {
13388
13389		const planes = this.planes;
13390		const center = sphere.center;
13391		const negRadius = - sphere.radius;
13392
13393		for (let i = 0; i < 6; i++) {
13394
13395			const distance = planes[i].distanceToPoint(center);
13396
13397			if (distance < negRadius) {
13398
13399				return false;
13400
13401			}
13402
13403		}
13404
13405		return true;
13406
13407	}
13408
13409	intersectsBox(box) {
13410
13411		const planes = this.planes;
13412
13413		for (let i = 0; i < 6; i++) {
13414
13415			const plane = planes[i];
13416
13417			// corner at max distance
13418
13419			_vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x;
13420			_vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y;
13421			_vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z;
13422
13423			if (plane.distanceToPoint(_vector$7) < 0) {
13424
13425				return false;
13426
13427			}
13428
13429		}
13430
13431		return true;
13432
13433	}
13434
13435	containsPoint(point) {
13436
13437		const planes = this.planes;
13438
13439		for (let i = 0; i < 6; i++) {
13440
13441			if (planes[i].distanceToPoint(point) < 0) {
13442
13443				return false;
13444
13445			}
13446
13447		}
13448
13449		return true;
13450
13451	}
13452
13453	clone() {
13454
13455		return new this.constructor().copy(this);
13456
13457	}
13458
13459}
13460
13461function WebGLAnimation() {
13462
13463	let context = null;
13464	let isAnimating = false;
13465	let animationLoop = null;
13466	let requestId = null;
13467
13468	function onAnimationFrame(time, frame) {
13469
13470		animationLoop(time, frame);
13471
13472		requestId = context.requestAnimationFrame(onAnimationFrame);
13473
13474	}
13475
13476	return {
13477
13478		start: function () {
13479
13480			if (isAnimating === true) return;
13481			if (animationLoop === null) return;
13482
13483			requestId = context.requestAnimationFrame(onAnimationFrame);
13484
13485			isAnimating = true;
13486
13487		},
13488
13489		stop: function () {
13490
13491			context.cancelAnimationFrame(requestId);
13492
13493			isAnimating = false;
13494
13495		},
13496
13497		setAnimationLoop: function (callback) {
13498
13499			animationLoop = callback;
13500
13501		},
13502
13503		setContext: function (value) {
13504
13505			context = value;
13506
13507		}
13508
13509	};
13510
13511}
13512
13513function WebGLAttributes(gl, capabilities) {
13514
13515	const isWebGL2 = capabilities.isWebGL2;
13516
13517	const buffers = new WeakMap();
13518
13519	function createBuffer(attribute, bufferType) {
13520
13521		const array = attribute.array;
13522		const usage = attribute.usage;
13523		const size = array.byteLength;
13524
13525		const buffer = gl.createBuffer();
13526
13527		gl.bindBuffer(bufferType, buffer);
13528		gl.bufferData(bufferType, array, usage);
13529
13530		attribute.onUploadCallback();
13531
13532		let type;
13533
13534		if (array instanceof Float32Array) {
13535
13536			type = gl.FLOAT;
13537
13538		} else if (array instanceof Uint16Array) {
13539
13540			if (attribute.isFloat16BufferAttribute) {
13541
13542				if (isWebGL2) {
13543
13544					type = gl.HALF_FLOAT;
13545
13546				} else {
13547
13548					throw new Error('THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.');
13549
13550				}
13551
13552			} else {
13553
13554				type = gl.UNSIGNED_SHORT;
13555
13556			}
13557
13558		} else if (array instanceof Int16Array) {
13559
13560			type = gl.SHORT;
13561
13562		} else if (array instanceof Uint32Array) {
13563
13564			type = gl.UNSIGNED_INT;
13565
13566		} else if (array instanceof Int32Array) {
13567
13568			type = gl.INT;
13569
13570		} else if (array instanceof Int8Array) {
13571
13572			type = gl.BYTE;
13573
13574		} else if (array instanceof Uint8Array) {
13575
13576			type = gl.UNSIGNED_BYTE;
13577
13578		} else if (array instanceof Uint8ClampedArray) {
13579
13580			type = gl.UNSIGNED_BYTE;
13581
13582		} else {
13583
13584			throw new Error('THREE.WebGLAttributes: Unsupported buffer data format: ' + array);
13585
13586		}
13587
13588		return {
13589			buffer: buffer,
13590			type: type,
13591			bytesPerElement: array.BYTES_PER_ELEMENT,
13592			version: attribute.version,
13593			size: size
13594		};
13595
13596	}
13597
13598	function updateBuffer(buffer, attribute, bufferType) {
13599
13600		const array = attribute.array;
13601		const updateRange = attribute._updateRange; // deprecated
13602		const updateRanges = attribute.updateRanges;
13603
13604		gl.bindBuffer(bufferType, buffer);
13605
13606		if (updateRange.count === - 1 && updateRanges.length === 0) {
13607
13608			// Not using update ranges
13609			gl.bufferSubData(bufferType, 0, array);
13610
13611		}
13612
13613		if (updateRanges.length !== 0) {
13614
13615			for (let i = 0, l = updateRanges.length; i < l; i++) {
13616
13617				const range = updateRanges[i];
13618				if (isWebGL2) {
13619
13620					gl.bufferSubData(bufferType, range.start * array.BYTES_PER_ELEMENT,
13621						array, range.start, range.count);
13622
13623				} else {
13624
13625					gl.bufferSubData(bufferType, range.start * array.BYTES_PER_ELEMENT,
13626						array.subarray(range.start, range.start + range.count));
13627
13628				}
13629
13630			}
13631
13632			attribute.clearUpdateRanges();
13633
13634		}
13635
13636		// deprecated
13637		if (updateRange.count !== - 1) {
13638
13639			if (isWebGL2) {
13640
13641				gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
13642					array, updateRange.offset, updateRange.count);
13643
13644			} else {
13645
13646				gl.bufferSubData(bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
13647					array.subarray(updateRange.offset, updateRange.offset + updateRange.count));
13648
13649			}
13650
13651			updateRange.count = - 1; // reset range
13652
13653		}
13654
13655		attribute.onUploadCallback();
13656
13657	}
13658
13659	//
13660
13661	function get(attribute) {
13662
13663		if (attribute.isInterleavedBufferAttribute) attribute = attribute.data;
13664
13665		return buffers.get(attribute);
13666
13667	}
13668
13669	function remove(attribute) {
13670
13671		if (attribute.isInterleavedBufferAttribute) attribute = attribute.data;
13672
13673		const data = buffers.get(attribute);
13674
13675		if (data) {
13676
13677			gl.deleteBuffer(data.buffer);
13678
13679			buffers.delete(attribute);
13680
13681		}
13682
13683	}
13684
13685	function update(attribute, bufferType) {
13686
13687		if (attribute.isGLBufferAttribute) {
13688
13689			const cached = buffers.get(attribute);
13690
13691			if (!cached || cached.version < attribute.version) {
13692
13693				buffers.set(attribute, {
13694					buffer: attribute.buffer,
13695					type: attribute.type,
13696					bytesPerElement: attribute.elementSize,
13697					version: attribute.version
13698				});
13699
13700			}
13701
13702			return;
13703
13704		}
13705
13706		if (attribute.isInterleavedBufferAttribute) attribute = attribute.data;
13707
13708		const data = buffers.get(attribute);
13709
13710		if (data === undefined) {
13711
13712			buffers.set(attribute, createBuffer(attribute, bufferType));
13713
13714		} else if (data.version < attribute.version) {
13715
13716			if (data.size !== attribute.array.byteLength) {
13717
13718				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.');
13719
13720			}
13721
13722			updateBuffer(data.buffer, attribute, bufferType);
13723
13724			data.version = attribute.version;
13725
13726		}
13727
13728	}
13729
13730	return {
13731
13732		get: get,
13733		remove: remove,
13734		update: update
13735
13736	};
13737
13738}
13739
13740class PlaneGeometry extends BufferGeometry {
13741
13742	constructor(width = 1, height = 1, widthSegments = 1, heightSegments = 1) {
13743
13744		super();
13745
13746		this.type = 'PlaneGeometry';
13747
13748		this.parameters = {
13749			width: width,
13750			height: height,
13751			widthSegments: widthSegments,
13752			heightSegments: heightSegments
13753		};
13754
13755		const width_half = width / 2;
13756		const height_half = height / 2;
13757
13758		const gridX = Math.floor(widthSegments);
13759		const gridY = Math.floor(heightSegments);
13760
13761		const gridX1 = gridX + 1;
13762		const gridY1 = gridY + 1;
13763
13764		const segment_width = width / gridX;
13765		const segment_height = height / gridY;
13766
13767		//
13768
13769		const indices = [];
13770		const vertices = [];
13771		const normals = [];
13772		const uvs = [];
13773
13774		for (let iy = 0; iy < gridY1; iy++) {
13775
13776			const y = iy * segment_height - height_half;
13777
13778			for (let ix = 0; ix < gridX1; ix++) {
13779
13780				const x = ix * segment_width - width_half;
13781
13782				vertices.push(x, - y, 0);
13783
13784				normals.push(0, 0, 1);
13785
13786				uvs.push(ix / gridX);
13787				uvs.push(1 - (iy / gridY));
13788
13789			}
13790
13791		}
13792
13793		for (let iy = 0; iy < gridY; iy++) {
13794
13795			for (let ix = 0; ix < gridX; ix++) {
13796
13797				const a = ix + gridX1 * iy;
13798				const b = ix + gridX1 * (iy + 1);
13799				const c = (ix + 1) + gridX1 * (iy + 1);
13800				const d = (ix + 1) + gridX1 * iy;
13801
13802				indices.push(a, b, d);
13803				indices.push(b, c, d);
13804
13805			}
13806
13807		}
13808
13809		this.setIndex(indices);
13810		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
13811		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
13812		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
13813
13814	}
13815
13816	copy(source) {
13817
13818		super.copy(source);
13819
13820		this.parameters = Object.assign({}, source.parameters);
13821
13822		return this;
13823
13824	}
13825
13826	static fromJSON(data) {
13827
13828		return new PlaneGeometry(data.width, data.height, data.widthSegments, data.heightSegments);
13829
13830	}
13831
13832}
13833
13834var alphahash_fragment = "#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif";
13835
13836var 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";
13837
13838var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif";
13839
13840var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
13841
13842var alphatest_fragment = "#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;\n#endif";
13843
13844var alphatest_pars_fragment = "#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif";
13845
13846var 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
13846( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif";
13847
13848var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
13849
13850var 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";
13851
13852var batching_vertex = "#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif";
13853
13854var begin_vertex = "vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif";
13855
13856var beginnormal_vertex = "vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
13857
13858var 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";
13859
13860var 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 );
13860\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";
13861
13862var 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";
13863
13864var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif";
13865
13866var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
13867
13868var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
13869
13870var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
13871
13872var color_fragment = "#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif";
13873
13874var color_pars_fragment = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif";
13875
13876var color_pars_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
13877
13878var color_vertex = "#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
13879
13880var 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";
13881
13882var 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";
13883
13884var defaultnormal_vertex = "vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );
13884\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";
13885
13886var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
13887
13888var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif";
13889
13890var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
13891
13892var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
13893
13894var colorspace_fragment = "gl_FragColor = linearToOutputTexel( gl_FragColor );";
13895
13896var 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}";
13897
13898var envmap_fragment = "#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif";
13899
13900var envmap_common_pars_fragment = "#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif";
13901
13902var 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";
13903
13904var 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";
13905
13906var 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}
13906 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";
13907
13908var fog_vertex = "#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif";
13909
13910var fog_pars_vertex = "#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif";
13911
13912var 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";
13913
13914var 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";
13915
13916var 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}";
13917
13918var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif";
13919
13920var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
13921
13922var lights_lambert_fragment = "LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;";
13923
13924var 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";
13925
13926var lights_pars_begin = "uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}
13926\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";
13927
13928var 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, 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, 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";
13929
13930var lights_toon_fragment = "ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
13931
13932var 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";
13933
13934var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
13935
13936var 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
13936( 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";
13937
13938var 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;
13938\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif";
13939�
vendor: 15,344 bytes, lines 13939-13940
13939
13940var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n    float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n    float x2 = x * x;\n    float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n    return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3(    0, 1,    0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
13940
13941
13942var 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";
13943
13944var 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";
13945
13946var 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";
13947
13948var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
13949
13950var logdepthbuf_pars_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
13951
13952var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif";
13953
13954var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif";
13955
13956var 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";
13957
13958var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif";
13959
13960var 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";
13961
13962var 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";
13963
13964var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
13965
13966var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
13967
13968var morphcolor_vertex = "#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif";
13969
13970var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif";
13971
13972var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif";
13973
13974var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif";
13975
13976var 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;";
13977
13978var 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 );
13978\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
13979
13980var 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";
13981
13982var 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";
13983
13984var 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";
13985
13986var 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";
13987
13988var clearcoat_normal_fragment_begin = "#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif";
13989
13990var 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";
13991
13992var 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";
13993
13994var iridescence_pars_fragment = "#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif";
13995
13996var 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 );";
13997
13998var 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}";
13999
14000var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
14001
14002var 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;";
14003
14004var dithering_fragment = "#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
14005
14006var 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";
14007
14008var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
14009
14010var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
14011�
vendor: 9,177 bytes, lines 14011-14012
14011
14012var shadowmap_pars_fragment = "#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t  f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif";
14012
14013
14014var 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";
14015
14016var 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";
14017
14018var 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}";
14019
14020var 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";
14021
14022var 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";
14023
14024var 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";
14025
14026var 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";
14027
14028var 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";
14029
14030var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif";
14031
14032var tonemapping_fragment = "#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
14033�
vendor: 2,514 bytes, lines 14033-14034
14033
14034var 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 
14034= LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor *= toneMappingExposure;\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\treturn color;\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
14035
14036var transmission_fragment = "#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif";
14037
14038var transmission_pars_fragment = "#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a *  a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\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";
14039
14040var uv_pars_fragment = "#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;
14040\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";
14041
14042var 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";
14043
14044var 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;
14044\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";
14045
14046var 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";
14047
14048const 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}";
14049
14050const 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}";
14051
14052const 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}";
14053
14054const fragment$g = "#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
14055
14056const 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}";
14057
14058const 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}";
14059
14060const 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#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}";
14061
14062const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}";
14063
14064const 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#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}";
14065
14066const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\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}";
14067
14068const 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}";
14069
14070const 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}";
14071
14072const 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 <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}";
14073
14074const 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\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <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}";
14075
14076const 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 <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}";
14077
14078const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}";
14079
14080const 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 <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}";
14081
14082const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}";
14083
14084const 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 <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>
14084\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
14085
14086const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}";
14087
14088const 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 <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}";
14089
14090const 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\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}";
14091
14092const 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 <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}";
14093
14094const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}";
14095
14096const 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 <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}";
14097
14098const 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;
14098\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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;
14098\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}";
14099
14100const 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 <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}";
14101
14102const 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\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <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}";
14103
14104const 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 <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}";
14105
14106const 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\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\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}";
14107
14108const 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 <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}";
14109
14110const 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}";
14111
14112const 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}";
14113
14114const 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\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\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}";
14115
14116const ShaderChunk = {
14117	alphahash_fragment: alphahash_fragment,
14118	alphahash_pars_fragment: alphahash_pars_fragment,
14119	alphamap_fragment: alphamap_fragment,
14120	alphamap_pars_fragment: alphamap_pars_fragment,
14121	alphatest_fragment: alphatest_fragment,
14122	alphatest_pars_fragment: alphatest_pars_fragment,
14123	aomap_fragment: aomap_fragment,
14124	aomap_pars_fragment: aomap_pars_fragment,
14125	batching_pars_vertex: batching_pars_vertex,
14126	batching_vertex: batching_vertex,
14127	begin_vertex: begin_vertex,
14128	beginnormal_vertex: beginnormal_vertex,
14129	bsdfs: bsdfs,
14130	iridescence_fragment: iridescence_fragment,
14131	bumpmap_pars_fragment: bumpmap_pars_fragment,
14132	clipping_planes_fragment: clipping_planes_fragment,
14133	clipping_planes_pars_fragment: clipping_planes_pars_fragment,
14134	clipping_planes_pars_vertex: clipping_planes_pars_vertex,
14135	clipping_planes_vertex: clipping_planes_vertex,
14136	color_fragment: color_fragment,
14137	color_pars_fragment: color_pars_fragment,
14138	color_pars_vertex: color_pars_vertex,
14139	color_vertex: color_vertex,
14140	common: common,
14141	cube_uv_reflection_fragment: cube_uv_reflection_fragment,
14142	defaultnormal_vertex: defaultnormal_vertex,
vendor: 12,289 bytes, lines 14143-14629
14143	displacementmap_pars_vertex: displacementmap_pars_vertex,
14144	displacementmap_vertex: displacementmap_vertex,
14145	emissivemap_fragment: emissivemap_fragment,
14146	emissivemap_pars_fragment: emissivemap_pars_fragment,
14147	colorspace_fragment: colorspace_fragment,
14148	colorspace_pars_fragment: colorspace_pars_fragment,
14149	envmap_fragment: envmap_fragment,
14150	envmap_common_pars_fragment: envmap_common_pars_fragment,
14151	envmap_pars_fragment: envmap_pars_fragment,
14152	envmap_pars_vertex: envmap_pars_vertex,
14153	envmap_physical_pars_fragment: envmap_physical_pars_fragment,
14154	envmap_vertex: envmap_vertex,
14155	fog_vertex: fog_vertex,
14156	fog_pars_vertex: fog_pars_vertex,
14157	fog_fragment: fog_fragment,
14158	fog_pars_fragment: fog_pars_fragment,
14159	gradientmap_pars_fragment: gradientmap_pars_fragment,
14160	lightmap_fragment: lightmap_fragment,
14161	lightmap_pars_fragment: lightmap_pars_fragment,
14162	lights_lambert_fragment: lights_lambert_fragment,
14163	lights_lambert_pars_fragment: lights_lambert_pars_fragment,
14164	lights_pars_begin: lights_pars_begin,
14165	lights_toon_fragment: lights_toon_fragment,
14166	lights_toon_pars_fragment: lights_toon_pars_fragment,
14167	lights_phong_fragment: lights_phong_fragment,
14168	lights_phong_pars_fragment: lights_phong_pars_fragment,
14169	lights_physical_fragment: lights_physical_fragment,
14170	lights_physical_pars_fragment: lights_physical_pars_fragment,
14171	lights_fragment_begin: lights_fragment_begin,
14172	lights_fragment_maps: lights_fragment_maps,
14173	lights_fragment_end: lights_fragment_end,
14174	logdepthbuf_fragment: logdepthbuf_fragment,
14175	logdepthbuf_pars_fragment: logdepthbuf_pars_fragment,
14176	logdepthbuf_pars_vertex: logdepthbuf_pars_vertex,
14177	logdepthbuf_vertex: logdepthbuf_vertex,
14178	map_fragment: map_fragment,
14179	map_pars_fragment: map_pars_fragment,
14180	map_particle_fragment: map_particle_fragment,
14181	map_particle_pars_fragment: map_particle_pars_fragment,
14182	metalnessmap_fragment: metalnessmap_fragment,
14183	metalnessmap_pars_fragment: metalnessmap_pars_fragment,
14184	morphcolor_vertex: morphcolor_vertex,
14185	morphnormal_vertex: morphnormal_vertex,
14186	morphtarget_pars_vertex: morphtarget_pars_vertex,
14187	morphtarget_vertex: morphtarget_vertex,
14188	normal_fragment_begin: normal_fragment_begin,
14189	normal_fragment_maps: normal_fragment_maps,
14190	normal_pars_fragment: normal_pars_fragment,
14191	normal_pars_vertex: normal_pars_vertex,
14192	normal_vertex: normal_vertex,
14193	normalmap_pars_fragment: normalmap_pars_fragment,
14194	clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
14195	clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
14196	clearcoat_pars_fragment: clearcoat_pars_fragment,
14197	iridescence_pars_fragment: iridescence_pars_fragment,
14198	opaque_fragment: opaque_fragment,
14199	packing: packing,
14200	premultiplied_alpha_fragment: premultiplied_alpha_fragment,
14201	project_vertex: project_vertex,
14202	dithering_fragment: dithering_fragment,
14203	dithering_pars_fragment: dithering_pars_fragment,
14204	roughnessmap_fragment: roughnessmap_fragment,
14205	roughnessmap_pars_fragment: roughnessmap_pars_fragment,
14206	shadowmap_pars_fragment: shadowmap_pars_fragment,
14207	shadowmap_pars_vertex: shadowmap_pars_vertex,
14208	shadowmap_vertex: shadowmap_vertex,
14209	shadowmask_pars_fragment: shadowmask_pars_fragment,
14210	skinbase_vertex: skinbase_vertex,
14211	skinning_pars_vertex: skinning_pars_vertex,
14212	skinning_vertex: skinning_vertex,
14213	skinnormal_vertex: skinnormal_vertex,
14214	specularmap_fragment: specularmap_fragment,
14215	specularmap_pars_fragment: specularmap_pars_fragment,
14216	tonemapping_fragment: tonemapping_fragment,
14217	tonemapping_pars_fragment: tonemapping_pars_fragment,
14218	transmission_fragment: transmission_fragment,
14219	transmission_pars_fragment: transmission_pars_fragment,
14220	uv_pars_fragment: uv_pars_fragment,
14221	uv_pars_vertex: uv_pars_vertex,
14222	uv_vertex: uv_vertex,
14223	worldpos_vertex: worldpos_vertex,
14224
14225	background_vert: vertex$h,
14226	background_frag: fragment$h,
14227	backgroundCube_vert: vertex$g,
14228	backgroundCube_frag: fragment$g,
14229	cube_vert: vertex$f,
14230	cube_frag: fragment$f,
14231	depth_vert: vertex$e,
14232	depth_frag: fragment$e,
14233	distanceRGBA_vert: vertex$d,
14234	distanceRGBA_frag: fragment$d,
14235	equirect_vert: vertex$c,
14236	equirect_frag: fragment$c,
14237	linedashed_vert: vertex$b,
14238	linedashed_frag: fragment$b,
14239	meshbasic_vert: vertex$a,
14240	meshbasic_frag: fragment$a,
14241	meshlambert_vert: vertex$9,
14242	meshlambert_frag: fragment$9,
14243	meshmatcap_vert: vertex$8,
14244	meshmatcap_frag: fragment$8,
14245	meshnormal_vert: vertex$7,
14246	meshnormal_frag: fragment$7,
14247	meshphong_vert: vertex$6,
14248	meshphong_frag: fragment$6,
14249	meshphysical_vert: vertex$5,
14250	meshphysical_frag: fragment$5,
14251	meshtoon_vert: vertex$4,
14252	meshtoon_frag: fragment$4,
14253	points_vert: vertex$3,
14254	points_frag: fragment$3,
14255	shadow_vert: vertex$2,
14256	shadow_frag: fragment$2,
14257	sprite_vert: vertex$1,
14258	sprite_frag: fragment$1
14259};
14260
14261/**
14262 * Uniforms library for shared webgl shaders
14263 */
14264
14265const UniformsLib = {
14266
14267	common: {
14268
14269		diffuse: { value: /*@__PURE__*/ new Color(0xffffff) },
14270		opacity: { value: 1.0 },
14271
14272		map: { value: null },
14273		mapTransform: { value: /*@__PURE__*/ new Matrix3() },
14274
14275		alphaMap: { value: null },
14276		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14277
14278		alphaTest: { value: 0 }
14279
14280	},
14281
14282	specularmap: {
14283
14284		specularMap: { value: null },
14285		specularMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14286
14287	},
14288
14289	envmap: {
14290
14291		envMap: { value: null },
14292		flipEnvMap: { value: - 1 },
14293		reflectivity: { value: 1.0 }, // basic, lambert, phong
14294		ior: { value: 1.5 }, // physical
14295		refractionRatio: { value: 0.98 }, // basic, lambert, phong
14296
14297	},
14298
14299	aomap: {
14300
14301		aoMap: { value: null },
14302		aoMapIntensity: { value: 1 },
14303		aoMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14304
14305	},
14306
14307	lightmap: {
14308
14309		lightMap: { value: null },
14310		lightMapIntensity: { value: 1 },
14311		lightMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14312
14313	},
14314
14315	bumpmap: {
14316
14317		bumpMap: { value: null },
14318		bumpMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14319		bumpScale: { value: 1 }
14320
14321	},
14322
14323	normalmap: {
14324
14325		normalMap: { value: null },
14326		normalMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14327		normalScale: { value: /*@__PURE__*/ new Vector2(1, 1) }
14328
14329	},
14330
14331	displacementmap: {
14332
14333		displacementMap: { value: null },
14334		displacementMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14335		displacementScale: { value: 1 },
14336		displacementBias: { value: 0 }
14337
14338	},
14339
14340	emissivemap: {
14341
14342		emissiveMap: { value: null },
14343		emissiveMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14344
14345	},
14346
14347	metalnessmap: {
14348
14349		metalnessMap: { value: null },
14350		metalnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14351
14352	},
14353
14354	roughnessmap: {
14355
14356		roughnessMap: { value: null },
14357		roughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }
14358
14359	},
14360
14361	gradientmap: {
14362
14363		gradientMap: { value: null }
14364
14365	},
14366
14367	fog: {
14368
14369		fogDensity: { value: 0.00025 },
14370		fogNear: { value: 1 },
14371		fogFar: { value: 2000 },
14372		fogColor: { value: /*@__PURE__*/ new Color(0xffffff) }
14373
14374	},
14375
14376	lights: {
14377
14378		ambientLightColor: { value: [] },
14379
14380		lightProbe: { value: [] },
14381
14382		directionalLights: {
14383			value: [], properties: {
14384				direction: {},
14385				color: {}
14386			}
14387		},
14388
14389		directionalLightShadows: {
14390			value: [], properties: {
14391				shadowBias: {},
14392				shadowNormalBias: {},
14393				shadowRadius: {},
14394				shadowMapSize: {}
14395			}
14396		},
14397
14398		directionalShadowMap: { value: [] },
14399		directionalShadowMatrix: { value: [] },
14400
14401		spotLights: {
14402			value: [], properties: {
14403				color: {},
14404				position: {},
14405				direction: {},
14406				distance: {},
14407				coneCos: {},
14408				penumbraCos: {},
14409				decay: {}
14410			}
14411		},
14412
14413		spotLightShadows: {
14414			value: [], properties: {
14415				shadowBias: {},
14416				shadowNormalBias: {},
14417				shadowRadius: {},
14418				shadowMapSize: {}
14419			}
14420		},
14421
14422		spotLightMap: { value: [] },
14423		spotShadowMap: { value: [] },
14424		spotLightMatrix: { value: [] },
14425
14426		pointLights: {
14427			value: [], properties: {
14428				color: {},
14429				position: {},
14430				decay: {},
14431				distance: {}
14432			}
14433		},
14434
14435		pointLightShadows: {
14436			value: [], properties: {
14437				shadowBias: {},
14438				shadowNormalBias: {},
14439				shadowRadius: {},
14440				shadowMapSize: {},
14441				shadowCameraNear: {},
14442				shadowCameraFar: {}
14443			}
14444		},
14445
14446		pointShadowMap: { value: [] },
14447		pointShadowMatrix: { value: [] },
14448
14449		hemisphereLights: {
14450			value: [], properties: {
14451				direction: {},
14452				skyColor: {},
14453				groundColor: {}
14454			}
14455		},
14456
14457		// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src
14458		rectAreaLights: {
14459			value: [], properties: {
14460				color: {},
14461				position: {},
14462				width: {},
14463				height: {}
14464			}
14465		},
14466
14467		ltc_1: { value: null },
14468		ltc_2: { value: null }
14469
14470	},
14471
14472	points: {
14473
14474		diffuse: { value: /*@__PURE__*/ new Color(0xffffff) },
14475		opacity: { value: 1.0 },
14476		size: { value: 1.0 },
14477		scale: { value: 1.0 },
14478		map: { value: null },
14479		alphaMap: { value: null },
14480		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14481		alphaTest: { value: 0 },
14482		uvTransform: { value: /*@__PURE__*/ new Matrix3() }
14483
14484	},
14485
14486	sprite: {
14487
14488		diffuse: { value: /*@__PURE__*/ new Color(0xffffff) },
14489		opacity: { value: 1.0 },
14490		center: { value: /*@__PURE__*/ new Vector2(0.5, 0.5) },
14491		rotation: { value: 0.0 },
14492		map: { value: null },
14493		mapTransform: { value: /*@__PURE__*/ new Matrix3() },
14494		alphaMap: { value: null },
14495		alphaMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14496		alphaTest: { value: 0 }
14497
14498	}
14499
14500};
14501
14502const ShaderLib = {
14503
14504	basic: {
14505
14506		uniforms: /*@__PURE__*/ mergeUniforms([
14507			UniformsLib.common,
14508			UniformsLib.specularmap,
14509			UniformsLib.envmap,
14510			UniformsLib.aomap,
14511			UniformsLib.lightmap,
14512			UniformsLib.fog
14513		]),
14514
14515		vertexShader: ShaderChunk.meshbasic_vert,
14516		fragmentShader: ShaderChunk.meshbasic_frag
14517
14518	},
14519
14520	lambert: {
14521
14522		uniforms: /*@__PURE__*/ mergeUniforms([
14523			UniformsLib.common,
14524			UniformsLib.specularmap,
14525			UniformsLib.envmap,
14526			UniformsLib.aomap,
14527			UniformsLib.lightmap,
14528			UniformsLib.emissivemap,
14529			UniformsLib.bumpmap,
14530			UniformsLib.normalmap,
14531			UniformsLib.displacementmap,
14532			UniformsLib.fog,
14533			UniformsLib.lights,
14534			{
14535				emissive: { value: /*@__PURE__*/ new Color(0x000000) }
14536			}
14537		]),
14538
14539		vertexShader: ShaderChunk.meshlambert_vert,
14540		fragmentShader: ShaderChunk.meshlambert_frag
14541
14542	},
14543
14544	phong: {
14545
14546		uniforms: /*@__PURE__*/ mergeUniforms([
14547			UniformsLib.common,
14548			UniformsLib.specularmap,
14549			UniformsLib.envmap,
14550			UniformsLib.aomap,
14551			UniformsLib.lightmap,
14552			UniformsLib.emissivemap,
14553			UniformsLib.bumpmap,
14554			UniformsLib.normalmap,
14555			UniformsLib.displacementmap,
14556			UniformsLib.fog,
14557			UniformsLib.lights,
14558			{
14559				emissive: { value: /*@__PURE__*/ new Color(0x000000) },
14560				specular: { value: /*@__PURE__*/ new Color(0x111111) },
14561				shininess: { value: 30 }
14562			}
14563		]),
14564
14565		vertexShader: ShaderChunk.meshphong_vert,
14566		fragmentShader: ShaderChunk.meshphong_frag
14567
14568	},
14569
14570	standard: {
14571
14572		uniforms: /*@__PURE__*/ mergeUniforms([
14573			UniformsLib.common,
14574			UniformsLib.envmap,
14575			UniformsLib.aomap,
14576			UniformsLib.lightmap,
14577			UniformsLib.emissivemap,
14578			UniformsLib.bumpmap,
14579			UniformsLib.normalmap,
14580			UniformsLib.displacementmap,
14581			UniformsLib.roughnessmap,
14582			UniformsLib.metalnessmap,
14583			UniformsLib.fog,
14584			UniformsLib.lights,
14585			{
14586				emissive: { value: /*@__PURE__*/ new Color(0x000000) },
14587				roughness: { value: 1.0 },
14588				metalness: { value: 0.0 },
14589				envMapIntensity: { value: 1 } // temporary
14590			}
14591		]),
14592
14593		vertexShader: ShaderChunk.meshphysical_vert,
14594		fragmentShader: ShaderChunk.meshphysical_frag
14595
14596	},
14597
14598	toon: {
14599
14600		uniforms: /*@__PURE__*/ mergeUniforms([
14601			UniformsLib.common,
14602			UniformsLib.aomap,
14603			UniformsLib.lightmap,
14604			UniformsLib.emissivemap,
14605			UniformsLib.bumpmap,
14606			UniformsLib.normalmap,
14607			UniformsLib.displacementmap,
14608			UniformsLib.gradientmap,
14609			UniformsLib.fog,
14610			UniformsLib.lights,
14611			{
14612				emissive: { value: /*@__PURE__*/ new Color(0x000000) }
14613			}
14614		]),
14615
14616		vertexShader: ShaderChunk.meshtoon_vert,
14617		fragmentShader: ShaderChunk.meshtoon_frag
14618
14619	},
14620
14621	matcap: {
14622
14623		uniforms: /*@__PURE__*/ mergeUniforms([
14624			UniformsLib.common,
14625			UniformsLib.bumpmap,
14626			UniformsLib.normalmap,
14627			UniformsLib.displacementmap,
14628			UniformsLib.fog,
14629			{
vendor: 5,467 bytes, lines 14630-14852
14630				matcap: { value: null }
14631			}
14632		]),
14633
14634		vertexShader: ShaderChunk.meshmatcap_vert,
14635		fragmentShader: ShaderChunk.meshmatcap_frag
14636
14637	},
14638
14639	points: {
14640
14641		uniforms: /*@__PURE__*/ mergeUniforms([
14642			UniformsLib.points,
14643			UniformsLib.fog
14644		]),
14645
14646		vertexShader: ShaderChunk.points_vert,
14647		fragmentShader: ShaderChunk.points_frag
14648
14649	},
14650
14651	dashed: {
14652
14653		uniforms: /*@__PURE__*/ mergeUniforms([
14654			UniformsLib.common,
14655			UniformsLib.fog,
14656			{
14657				scale: { value: 1 },
14658				dashSize: { value: 1 },
14659				totalSize: { value: 2 }
14660			}
14661		]),
14662
14663		vertexShader: ShaderChunk.linedashed_vert,
14664		fragmentShader: ShaderChunk.linedashed_frag
14665
14666	},
14667
14668	depth: {
14669
14670		uniforms: /*@__PURE__*/ mergeUniforms([
14671			UniformsLib.common,
14672			UniformsLib.displacementmap
14673		]),
14674
14675		vertexShader: ShaderChunk.depth_vert,
14676		fragmentShader: ShaderChunk.depth_frag
14677
14678	},
14679
14680	normal: {
14681
14682		uniforms: /*@__PURE__*/ mergeUniforms([
14683			UniformsLib.common,
14684			UniformsLib.bumpmap,
14685			UniformsLib.normalmap,
14686			UniformsLib.displacementmap,
14687			{
14688				opacity: { value: 1.0 }
14689			}
14690		]),
14691
14692		vertexShader: ShaderChunk.meshnormal_vert,
14693		fragmentShader: ShaderChunk.meshnormal_frag
14694
14695	},
14696
14697	sprite: {
14698
14699		uniforms: /*@__PURE__*/ mergeUniforms([
14700			UniformsLib.sprite,
14701			UniformsLib.fog
14702		]),
14703
14704		vertexShader: ShaderChunk.sprite_vert,
14705		fragmentShader: ShaderChunk.sprite_frag
14706
14707	},
14708
14709	background: {
14710
14711		uniforms: {
14712			uvTransform: { value: /*@__PURE__*/ new Matrix3() },
14713			t2D: { value: null },
14714			backgroundIntensity: { value: 1 }
14715		},
14716
14717		vertexShader: ShaderChunk.background_vert,
14718		fragmentShader: ShaderChunk.background_frag
14719
14720	},
14721
14722	backgroundCube: {
14723
14724		uniforms: {
14725			envMap: { value: null },
14726			flipEnvMap: { value: - 1 },
14727			backgroundBlurriness: { value: 0 },
14728			backgroundIntensity: { value: 1 }
14729		},
14730
14731		vertexShader: ShaderChunk.backgroundCube_vert,
14732		fragmentShader: ShaderChunk.backgroundCube_frag
14733
14734	},
14735
14736	cube: {
14737
14738		uniforms: {
14739			tCube: { value: null },
14740			tFlip: { value: - 1 },
14741			opacity: { value: 1.0 }
14742		},
14743
14744		vertexShader: ShaderChunk.cube_vert,
14745		fragmentShader: ShaderChunk.cube_frag
14746
14747	},
14748
14749	equirect: {
14750
14751		uniforms: {
14752			tEquirect: { value: null },
14753		},
14754
14755		vertexShader: ShaderChunk.equirect_vert,
14756		fragmentShader: ShaderChunk.equirect_frag
14757
14758	},
14759
14760	distanceRGBA: {
14761
14762		uniforms: /*@__PURE__*/ mergeUniforms([
14763			UniformsLib.common,
14764			UniformsLib.displacementmap,
14765			{
14766				referencePosition: { value: /*@__PURE__*/ new Vector3() },
14767				nearDistance: { value: 1 },
14768				farDistance: { value: 1000 }
14769			}
14770		]),
14771
14772		vertexShader: ShaderChunk.distanceRGBA_vert,
14773		fragmentShader: ShaderChunk.distanceRGBA_frag
14774
14775	},
14776
14777	shadow: {
14778
14779		uniforms: /*@__PURE__*/ mergeUniforms([
14780			UniformsLib.lights,
14781			UniformsLib.fog,
14782			{
14783				color: { value: /*@__PURE__*/ new Color(0x00000) },
14784				opacity: { value: 1.0 }
14785			},
14786		]),
14787
14788		vertexShader: ShaderChunk.shadow_vert,
14789		fragmentShader: ShaderChunk.shadow_frag
14790
14791	}
14792
14793};
14794
14795ShaderLib.physical = {
14796
14797	uniforms: /*@__PURE__*/ mergeUniforms([
14798		ShaderLib.standard.uniforms,
14799		{
14800			clearcoat: { value: 0 },
14801			clearcoatMap: { value: null },
14802			clearcoatMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14803			clearcoatNormalMap: { value: null },
14804			clearcoatNormalMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14805			clearcoatNormalScale: { value: /*@__PURE__*/ new Vector2(1, 1) },
14806			clearcoatRoughness: { value: 0 },
14807			clearcoatRoughnessMap: { value: null },
14808			clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14809			iridescence: { value: 0 },
14810			iridescenceMap: { value: null },
14811			iridescenceMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14812			iridescenceIOR: { value: 1.3 },
14813			iridescenceThicknessMinimum: { value: 100 },
14814			iridescenceThicknessMaximum: { value: 400 },
14815			iridescenceThicknessMap: { value: null },
14816			iridescenceThicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14817			sheen: { value: 0 },
14818			sheenColor: { value: /*@__PURE__*/ new Color(0x000000) },
14819			sheenColorMap: { value: null },
14820			sheenColorMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14821			sheenRoughness: { value: 1 },
14822			sheenRoughnessMap: { value: null },
14823			sheenRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14824			transmission: { value: 0 },
14825			transmissionMap: { value: null },
14826			transmissionMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14827			transmissionSamplerSize: { value: /*@__PURE__*/ new Vector2() },
14828			transmissionSamplerMap: { value: null },
14829			thickness: { value: 0 },
14830			thicknessMap: { value: null },
14831			thicknessMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14832			attenuationDistance: { value: 0 },
14833			attenuationColor: { value: /*@__PURE__*/ new Color(0x000000) },
14834			specularColor: { value: /*@__PURE__*/ new Color(1, 1, 1) },
14835			specularColorMap: { value: null },
14836			specularColorMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14837			specularIntensity: { value: 1 },
14838			specularIntensityMap: { value: null },
14839			specularIntensityMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14840			anisotropyVector: { value: /*@__PURE__*/ new Vector2() },
14841			anisotropyMap: { value: null },
14842			anisotropyMapTransform: { value: /*@__PURE__*/ new Matrix3() },
14843		}
14844	]),
14845
14846	vertexShader: ShaderChunk.meshphysical_vert,
14847	fragmentShader: ShaderChunk.meshphysical_frag
14848
14849};
14850
14851const _rgb = { r: 0, b: 0, g: 0 };
14852
vendor: 49,453 bytes, lines 14853-16947
14853function WebGLBackground(renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha) {
14854
14855	const clearColor = new Color(0x000000);
14856	let clearAlpha = alpha === true ? 0 : 1;
14857
14858	let planeMesh;
14859	let boxMesh;
14860
14861	let currentBackground = null;
14862	let currentBackgroundVersion = 0;
14863	let currentTonemapping = null;
14864
14865	function render(renderList, scene) {
14866
14867		let forceClear = false;
14868		let background = scene.isScene === true ? scene.background : null;
14869
14870		if (background && background.isTexture) {
14871
14872			const usePMREM = scene.backgroundBlurriness > 0; // use PMREM if the user wants to blur the background
14873			background = (usePMREM ? cubeuvmaps : cubemaps).get(background);
14874
14875		}
14876
14877		if (background === null) {
14878
14879			setClear(clearColor, clearAlpha);
14880
14881		} else if (background && background.isColor) {
14882
14883			setClear(background, 1);
14884			forceClear = true;
14885
14886		}
14887
14888		const environmentBlendMode = renderer.xr.getEnvironmentBlendMode();
14889
14890		if (environmentBlendMode === 'additive') {
14891
14892			state.buffers.color.setClear(0, 0, 0, 1, premultipliedAlpha);
14893
14894		} else if (environmentBlendMode === 'alpha-blend') {
14895
14896			state.buffers.color.setClear(0, 0, 0, 0, premultipliedAlpha);
14897
14898		}
14899
14900		if (renderer.autoClear || forceClear) {
14901
14902			renderer.clear(renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil);
14903
14904		}
14905
14906		if (background && (background.isCubeTexture || background.mapping === CubeUVReflectionMapping)) {
14907
14908			if (boxMesh === undefined) {
14909
14910				boxMesh = new Mesh(
14911					new BoxGeometry(1, 1, 1),
14912					new ShaderMaterial({
14913						name: 'BackgroundCubeMaterial',
14914						uniforms: cloneUniforms(ShaderLib.backgroundCube.uniforms),
14915						vertexShader: ShaderLib.backgroundCube.vertexShader,
14916						fragmentShader: ShaderLib.backgroundCube.fragmentShader,
14917						side: BackSide,
14918						depthTest: false,
14919						depthWrite: false,
14920						fog: false
14921					})
14922				);
14923
14924				boxMesh.geometry.deleteAttribute('normal');
14925				boxMesh.geometry.deleteAttribute('uv');
14926
14927				boxMesh.onBeforeRender = function (renderer, scene, camera) {
14928
14929					this.matrixWorld.copyPosition(camera.matrixWorld);
14930
14931				};
14932
14933				// add "envMap" material property so the renderer can evaluate it like for built-in materials
14934				Object.defineProperty(boxMesh.material, 'envMap', {
14935
14936					get: function () {
14937
14938						return this.uniforms.envMap.value;
14939
14940					}
14941
14942				});
14943
14944				objects.update(boxMesh);
14945
14946			}
14947
14948			boxMesh.material.uniforms.envMap.value = background;
14949			boxMesh.material.uniforms.flipEnvMap.value = (background.isCubeTexture && background.isRenderTargetTexture === false) ? - 1 : 1;
14950			boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
14951			boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14952			boxMesh.material.toneMapped = ColorManagement.getTransfer(background.colorSpace) !== SRGBTransfer;
14953
14954			if (currentBackground !== background ||
14955				currentBackgroundVersion !== background.version ||
14956				currentTonemapping !== renderer.toneMapping) {
14957
14958				boxMesh.material.needsUpdate = true;
14959
14960				currentBackground = background;
14961				currentBackgroundVersion = background.version;
14962				currentTonemapping = renderer.toneMapping;
14963
14964			}
14965
14966			boxMesh.layers.enableAll();
14967
14968			// push to the pre-sorted opaque render list
14969			renderList.unshift(boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null);
14970
14971		} else if (background && background.isTexture) {
14972
14973			if (planeMesh === undefined) {
14974
14975				planeMesh = new Mesh(
14976					new PlaneGeometry(2, 2),
14977					new ShaderMaterial({
14978						name: 'BackgroundMaterial',
14979						uniforms: cloneUniforms(ShaderLib.background.uniforms),
14980						vertexShader: ShaderLib.background.vertexShader,
14981						fragmentShader: ShaderLib.background.fragmentShader,
14982						side: FrontSide,
14983						depthTest: false,
14984						depthWrite: false,
14985						fog: false
14986					})
14987				);
14988
14989				planeMesh.geometry.deleteAttribute('normal');
14990
14991				// add "map" material property so the renderer can evaluate it like for built-in materials
14992				Object.defineProperty(planeMesh.material, 'map', {
14993
14994					get: function () {
14995
14996						return this.uniforms.t2D.value;
14997
14998					}
14999
15000				});
15001
15002				objects.update(planeMesh);
15003
15004			}
15005
15006			planeMesh.material.uniforms.t2D.value = background;
15007			planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
15008			planeMesh.material.toneMapped = ColorManagement.getTransfer(background.colorSpace) !== SRGBTransfer;
15009
15010			if (background.matrixAutoUpdate === true) {
15011
15012				background.updateMatrix();
15013
15014			}
15015
15016			planeMesh.material.uniforms.uvTransform.value.copy(background.matrix);
15017
15018			if (currentBackground !== background ||
15019				currentBackgroundVersion !== background.version ||
15020				currentTonemapping !== renderer.toneMapping) {
15021
15022				planeMesh.material.needsUpdate = true;
15023
15024				currentBackground = background;
15025				currentBackgroundVersion = background.version;
15026				currentTonemapping = renderer.toneMapping;
15027
15028			}
15029
15030			planeMesh.layers.enableAll();
15031
15032			// push to the pre-sorted opaque render list
15033			renderList.unshift(planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null);
15034
15035		}
15036
15037	}
15038
15039	function setClear(color, alpha) {
15040
15041		color.getRGB(_rgb, getUnlitUniformColorSpace(renderer));
15042
15043		state.buffers.color.setClear(_rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha);
15044
15045	}
15046
15047	return {
15048
15049		getClearColor: function () {
15050
15051			return clearColor;
15052
15053		},
15054		setClearColor: function (color, alpha = 1) {
15055
15056			clearColor.set(color);
15057			clearAlpha = alpha;
15058			setClear(clearColor, clearAlpha);
15059
15060		},
15061		getClearAlpha: function () {
15062
15063			return clearAlpha;
15064
15065		},
15066		setClearAlpha: function (alpha) {
15067
15068			clearAlpha = alpha;
15069			setClear(clearColor, clearAlpha);
15070
15071		},
15072		render: render
15073
15074	};
15075
15076}
15077
15078function WebGLBindingStates(gl, extensions, attributes, capabilities) {
15079
15080	const maxVertexAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
15081
15082	const extension = capabilities.isWebGL2 ? null : extensions.get('OES_vertex_array_object');
15083	const vaoAvailable = capabilities.isWebGL2 || extension !== null;
15084
15085	const bindingStates = {};
15086
15087	const defaultState = createBindingState(null);
15088	let currentState = defaultState;
15089	let forceUpdate = false;
15090
15091	function setup(object, material, program, geometry, index) {
15092
15093		let updateBuffers = false;
15094
15095		if (vaoAvailable) {
15096
15097			const state = getBindingState(geometry, program, material);
15098
15099			if (currentState !== state) {
15100
15101				currentState = state;
15102				bindVertexArrayObject(currentState.object);
15103
15104			}
15105
15106			updateBuffers = needsUpdate(object, geometry, program, index);
15107
15108			if (updateBuffers) saveCache(object, geometry, program, index);
15109
15110		} else {
15111
15112			const wireframe = (material.wireframe === true);
15113
15114			if (currentState.geometry !== geometry.id ||
15115				currentState.program !== program.id ||
15116				currentState.wireframe !== wireframe) {
15117
15118				currentState.geometry = geometry.id;
15119				currentState.program = program.id;
15120				currentState.wireframe = wireframe;
15121
15122				updateBuffers = true;
15123
15124			}
15125
15126		}
15127
15128		if (index !== null) {
15129
15130			attributes.update(index, gl.ELEMENT_ARRAY_BUFFER);
15131
15132		}
15133
15134		if (updateBuffers || forceUpdate) {
15135
15136			forceUpdate = false;
15137
15138			setupVertexAttributes(object, material, program, geometry);
15139
15140			if (index !== null) {
15141
15142				gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, attributes.get(index).buffer);
15143
15144			}
15145
15146		}
15147
15148	}
15149
15150	function createVertexArrayObject() {
15151
15152		if (capabilities.isWebGL2) return gl.createVertexArray();
15153
15154		return extension.createVertexArrayOES();
15155
15156	}
15157
15158	function bindVertexArrayObject(vao) {
15159
15160		if (capabilities.isWebGL2) return gl.bindVertexArray(vao);
15161
15162		return extension.bindVertexArrayOES(vao);
15163
15164	}
15165
15166	function deleteVertexArrayObject(vao) {
15167
15168		if (capabilities.isWebGL2) return gl.deleteVertexArray(vao);
15169
15170		return extension.deleteVertexArrayOES(vao);
15171
15172	}
15173
15174	function getBindingState(geometry, program, material) {
15175
15176		const wireframe = (material.wireframe === true);
15177
15178		let programMap = bindingStates[geometry.id];
15179
15180		if (programMap === undefined) {
15181
15182			programMap = {};
15183			bindingStates[geometry.id] = programMap;
15184
15185		}
15186
15187		let stateMap = programMap[program.id];
15188
15189		if (stateMap === undefined) {
15190
15191			stateMap = {};
15192			programMap[program.id] = stateMap;
15193
15194		}
15195
15196		let state = stateMap[wireframe];
15197
15198		if (state === undefined) {
15199
15200			state = createBindingState(createVertexArrayObject());
15201			stateMap[wireframe] = state;
15202
15203		}
15204
15205		return state;
15206
15207	}
15208
15209	function createBindingState(vao) {
15210
15211		const newAttributes = [];
15212		const enabledAttributes = [];
15213		const attributeDivisors = [];
15214
15215		for (let i = 0; i < maxVertexAttributes; i++) {
15216
15217			newAttributes[i] = 0;
15218			enabledAttributes[i] = 0;
15219			attributeDivisors[i] = 0;
15220
15221		}
15222
15223		return {
15224
15225			// for backward compatibility on non-VAO support browser
15226			geometry: null,
15227			program: null,
15228			wireframe: false,
15229
15230			newAttributes: newAttributes,
15231			enabledAttributes: enabledAttributes,
15232			attributeDivisors: attributeDivisors,
15233			object: vao,
15234			attributes: {},
15235			index: null
15236
15237		};
15238
15239	}
15240
15241	function needsUpdate(object, geometry, program, index) {
15242
15243		const cachedAttributes = currentState.attributes;
15244		const geometryAttributes = geometry.attributes;
15245
15246		let attributesNum = 0;
15247
15248		const programAttributes = program.getAttributes();
15249
15250		for (const name in programAttributes) {
15251
15252			const programAttribute = programAttributes[name];
15253
15254			if (programAttribute.location >= 0) {
15255
15256				const cachedAttribute = cachedAttributes[name];
15257				let geometryAttribute = geometryAttributes[name];
15258
15259				if (geometryAttribute === undefined) {
15260
15261					if (name === 'instanceMatrix' && object.instanceMatrix) geometryAttribute = object.instanceMatrix;
15262					if (name === 'instanceColor' && object.instanceColor) geometryAttribute = object.instanceColor;
15263
15264				}
15265
15266				if (cachedAttribute === undefined) return true;
15267
15268				if (cachedAttribute.attribute !== geometryAttribute) return true;
15269
15270				if (geometryAttribute && cachedAttribute.data !== geometryAttribute.data) return true;
15271
15272				attributesNum++;
15273
15274			}
15275
15276		}
15277
15278		if (currentState.attributesNum !== attributesNum) return true;
15279
15280		if (currentState.index !== index) return true;
15281
15282		return false;
15283
15284	}
15285
15286	function saveCache(object, geometry, program, index) {
15287
15288		const cache = {};
15289		const attributes = geometry.attributes;
15290		let attributesNum = 0;
15291
15292		const programAttributes = program.getAttributes();
15293
15294		for (const name in programAttributes) {
15295
15296			const programAttribute = programAttributes[name];
15297
15298			if (programAttribute.location >= 0) {
15299
15300				let attribute = attributes[name];
15301
15302				if (attribute === undefined) {
15303
15304					if (name === 'instanceMatrix' && object.instanceMatrix) attribute = object.instanceMatrix;
15305					if (name === 'instanceColor' && object.instanceColor) attribute = object.instanceColor;
15306
15307				}
15308
15309				const data = {};
15310				data.attribute = attribute;
15311
15312				if (attribute && attribute.data) {
15313
15314					data.data = attribute.data;
15315
15316				}
15317
15318				cache[name] = data;
15319
15320				attributesNum++;
15321
15322			}
15323
15324		}
15325
15326		currentState.attributes = cache;
15327		currentState.attributesNum = attributesNum;
15328
15329		currentState.index = index;
15330
15331	}
15332
15333	function initAttributes() {
15334
15335		const newAttributes = currentState.newAttributes;
15336
15337		for (let i = 0, il = newAttributes.length; i < il; i++) {
15338
15339			newAttributes[i] = 0;
15340
15341		}
15342
15343	}
15344
15345	function enableAttribute(attribute) {
15346
15347		enableAttributeAndDivisor(attribute, 0);
15348
15349	}
15350
15351	function enableAttributeAndDivisor(attribute, meshPerAttribute) {
15352
15353		const newAttributes = currentState.newAttributes;
15354		const enabledAttributes = currentState.enabledAttributes;
15355		const attributeDivisors = currentState.attributeDivisors;
15356
15357		newAttributes[attribute] = 1;
15358
15359		if (enabledAttributes[attribute] === 0) {
15360
15361			gl.enableVertexAttribArray(attribute);
15362			enabledAttributes[attribute] = 1;
15363
15364		}
15365
15366		if (attributeDivisors[attribute] !== meshPerAttribute) {
15367
15368			const extension = capabilities.isWebGL2 ? gl : extensions.get('ANGLE_instanced_arrays');
15369
15370			extension[capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE'](attribute, meshPerAttribute);
15371			attributeDivisors[attribute] = meshPerAttribute;
15372
15373		}
15374
15375	}
15376
15377	function disableUnusedAttributes() {
15378
15379		const newAttributes = currentState.newAttributes;
15380		const enabledAttributes = currentState.enabledAttributes;
15381
15382		for (let i = 0, il = enabledAttributes.length; i < il; i++) {
15383
15384			if (enabledAttributes[i] !== newAttributes[i]) {
15385
15386				gl.disableVertexAttribArray(i);
15387				enabledAttributes[i] = 0;
15388
15389			}
15390
15391		}
15392
15393	}
15394
15395	function vertexAttribPointer(index, size, type, normalized, stride, offset, integer) {
15396
15397		if (integer === true) {
15398
15399			gl.vertexAttribIPointer(index, size, type, stride, offset);
15400
15401		} else {
15402
15403			gl.vertexAttribPointer(index, size, type, normalized, stride, offset);
15404
15405		}
15406
15407	}
15408
15409	function setupVertexAttributes(object, material, program, geometry) {
15410
15411		if (capabilities.isWebGL2 === false && (object.isInstancedMesh || geometry.isInstancedBufferGeometry)) {
15412
15413			if (extensions.get('ANGLE_instanced_arrays') === null) return;
15414
15415		}
15416
15417		initAttributes();
15418
15419		const geometryAttributes = geometry.attributes;
15420
15421		const programAttributes = program.getAttributes();
15422
15423		const materialDefaultAttributeValues = material.defaultAttributeValues;
15424
15425		for (const name in programAttributes) {
15426
15427			const programAttribute = programAttributes[name];
15428
15429			if (programAttribute.location >= 0) {
15430
15431				let geometryAttribute = geometryAttributes[name];
15432
15433				if (geometryAttribute === undefined) {
15434
15435					if (name === 'instanceMatrix' && object.instanceMatrix) geometryAttribute = object.instanceMatrix;
15436					if (name === 'instanceColor' && object.instanceColor) geometryAttribute = object.instanceColor;
15437
15438				}
15439
15440				if (geometryAttribute !== undefined) {
15441
15442					const normalized = geometryAttribute.normalized;
15443					const size = geometryAttribute.itemSize;
15444
15445					const attribute = attributes.get(geometryAttribute);
15446
15447					// TODO Attribute may not be available on context restore
15448
15449					if (attribute === undefined) continue;
15450
15451					const buffer = attribute.buffer;
15452					const type = attribute.type;
15453					const bytesPerElement = attribute.bytesPerElement;
15454
15455					// check for integer attributes (WebGL 2 only)
15456
15457					const integer = (capabilities.isWebGL2 === true && (type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType === IntType));
15458
15459					if (geometryAttribute.isInterleavedBufferAttribute) {
15460
15461						const data = geometryAttribute.data;
15462						const stride = data.stride;
15463						const offset = geometryAttribute.offset;
15464
15465						if (data.isInstancedInterleavedBuffer) {
15466
15467							for (let i = 0; i < programAttribute.locationSize; i++) {
15468
15469								enableAttributeAndDivisor(programAttribute.location + i, data.meshPerAttribute);
15470
15471							}
15472
15473							if (object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined) {
15474
15475								geometry._maxInstanceCount = data.meshPerAttribute * data.count;
15476
15477							}
15478
15479						} else {
15480
15481							for (let i = 0; i < programAttribute.locationSize; i++) {
15482
15483								enableAttribute(programAttribute.location + i);
15484
15485							}
15486
15487						}
15488
15489						gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
15490
15491						for (let i = 0; i < programAttribute.locationSize; i++) {
15492
15493							vertexAttribPointer(
15494								programAttribute.location + i,
15495								size / programAttribute.locationSize,
15496								type,
15497								normalized,
15498								stride * bytesPerElement,
15499								(offset + (size / programAttribute.locationSize) * i) * bytesPerElement,
15500								integer
15501							);
15502
15503						}
15504
15505					} else {
15506
15507						if (geometryAttribute.isInstancedBufferAttribute) {
15508
15509							for (let i = 0; i < programAttribute.locationSize; i++) {
15510
15511								enableAttributeAndDivisor(programAttribute.location + i, geometryAttribute.meshPerAttribute);
15512
15513							}
15514
15515							if (object.isInstancedMesh !== true && geometry._maxInstanceCount === undefined) {
15516
15517								geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
15518
15519							}
15520
15521						} else {
15522
15523							for (let i = 0; i < programAttribute.locationSize; i++) {
15524
15525								enableAttribute(programAttribute.location + i);
15526
15527							}
15528
15529						}
15530
15531						gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
15532
15533						for (let i = 0; i < programAttribute.locationSize; i++) {
15534
15535							vertexAttribPointer(
15536								programAttribute.location + i,
15537								size / programAttribute.locationSize,
15538								type,
15539								normalized,
15540								size * bytesPerElement,
15541								(size / programAttribute.locationSize) * i * bytesPerElement,
15542								integer
15543							);
15544
15545						}
15546
15547					}
15548
15549				} else if (materialDefaultAttributeValues !== undefined) {
15550
15551					const value = materialDefaultAttributeValues[name];
15552
15553					if (value !== undefined) {
15554
15555						switch (value.length) {
15556
15557							case 2:
15558								gl.vertexAttrib2fv(programAttribute.location, value);
15559								break;
15560
15561							case 3:
15562								gl.vertexAttrib3fv(programAttribute.location, value);
15563								break;
15564
15565							case 4:
15566								gl.vertexAttrib4fv(programAttribute.location, value);
15567								break;
15568
15569							default:
15570								gl.vertexAttrib1fv(programAttribute.location, value);
15571
15572						}
15573
15574					}
15575
15576				}
15577
15578			}
15579
15580		}
15581
15582		disableUnusedAttributes();
15583
15584	}
15585
15586	function dispose() {
15587
15588		reset();
15589
15590		for (const geometryId in bindingStates) {
15591
15592			const programMap = bindingStates[geometryId];
15593
15594			for (const programId in programMap) {
15595
15596				const stateMap = programMap[programId];
15597
15598				for (const wireframe in stateMap) {
15599
15600					deleteVertexArrayObject(stateMap[wireframe].object);
15601
15602					delete stateMap[wireframe];
15603
15604				}
15605
15606				delete programMap[programId];
15607
15608			}
15609
15610			delete bindingStates[geometryId];
15611
15612		}
15613
15614	}
15615
15616	function releaseStatesOfGeometry(geometry) {
15617
15618		if (bindingStates[geometry.id] === undefined) return;
15619
15620		const programMap = bindingStates[geometry.id];
15621
15622		for (const programId in programMap) {
15623
15624			const stateMap = programMap[programId];
15625
15626			for (const wireframe in stateMap) {
15627
15628				deleteVertexArrayObject(stateMap[wireframe].object);
15629
15630				delete stateMap[wireframe];
15631
15632			}
15633
15634			delete programMap[programId];
15635
15636		}
15637
15638		delete bindingStates[geometry.id];
15639
15640	}
15641
15642	function releaseStatesOfProgram(program) {
15643
15644		for (const geometryId in bindingStates) {
15645
15646			const programMap = bindingStates[geometryId];
15647
15648			if (programMap[program.id] === undefined) continue;
15649
15650			const stateMap = programMap[program.id];
15651
15652			for (const wireframe in stateMap) {
15653
15654				deleteVertexArrayObject(stateMap[wireframe].object);
15655
15656				delete stateMap[wireframe];
15657
15658			}
15659
15660			delete programMap[program.id];
15661
15662		}
15663
15664	}
15665
15666	function reset() {
15667
15668		resetDefaultState();
15669		forceUpdate = true;
15670
15671		if (currentState === defaultState) return;
15672
15673		currentState = defaultState;
15674		bindVertexArrayObject(currentState.object);
15675
15676	}
15677
15678	// for backward-compatibility
15679
15680	function resetDefaultState() {
15681
15682		defaultState.geometry = null;
15683		defaultState.program = null;
15684		defaultState.wireframe = false;
15685
15686	}
15687
15688	return {
15689
15690		setup: setup,
15691		reset: reset,
15692		resetDefaultState: resetDefaultState,
15693		dispose: dispose,
15694		releaseStatesOfGeometry: releaseStatesOfGeometry,
15695		releaseStatesOfProgram: releaseStatesOfProgram,
15696
15697		initAttributes: initAttributes,
15698		enableAttribute: enableAttribute,
15699		disableUnusedAttributes: disableUnusedAttributes
15700
15701	};
15702
15703}
15704
15705function WebGLBufferRenderer(gl, extensions, info, capabilities) {
15706
15707	const isWebGL2 = capabilities.isWebGL2;
15708
15709	let mode;
15710
15711	function setMode(value) {
15712
15713		mode = value;
15714
15715	}
15716
15717	function render(start, count) {
15718
15719		gl.drawArrays(mode, start, count);
15720
15721		info.update(count, mode, 1);
15722
15723	}
15724
15725	function renderInstances(start, count, primcount) {
15726
15727		if (primcount === 0) return;
15728
15729		let extension, methodName;
15730
15731		if (isWebGL2) {
15732
15733			extension = gl;
15734			methodName = 'drawArraysInstanced';
15735
15736		} else {
15737
15738			extension = extensions.get('ANGLE_instanced_arrays');
15739			methodName = 'drawArraysInstancedANGLE';
15740
15741			if (extension === null) {
15742
15743				console.error('THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
15744				return;
15745
15746			}
15747
15748		}
15749
15750		extension[methodName](mode, start, count, primcount);
15751
15752		info.update(count, mode, primcount);
15753
15754	}
15755
15756	function renderMultiDraw(starts, counts, drawCount) {
15757
15758		if (drawCount === 0) return;
15759
15760		const extension = extensions.get('WEBGL_multi_draw');
15761		if (extension === null) {
15762
15763			for (let i = 0; i < drawCount; i++) {
15764
15765				this.render(starts[i], counts[i]);
15766
15767			}
15768
15769		} else {
15770
15771			extension.multiDrawArraysWEBGL(mode, starts, 0, counts, 0, drawCount);
15772
15773			let elementCount = 0;
15774			for (let i = 0; i < drawCount; i++) {
15775
15776				elementCount += counts[i];
15777
15778			}
15779
15780			info.update(elementCount, mode, 1);
15781
15782		}
15783
15784	}
15785
15786	//
15787
15788	this.setMode = setMode;
15789	this.render = render;
15790	this.renderInstances = renderInstances;
15791	this.renderMultiDraw = renderMultiDraw;
15792
15793}
15794
15795function WebGLCapabilities(gl, extensions, parameters) {
15796
15797	let maxAnisotropy;
15798
15799	function getMaxAnisotropy() {
15800
15801		if (maxAnisotropy !== undefined) return maxAnisotropy;
15802
15803		if (extensions.has('EXT_texture_filter_anisotropic') === true) {
15804
15805			const extension = extensions.get('EXT_texture_filter_anisotropic');
15806
15807			maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
15808
15809		} else {
15810
15811			maxAnisotropy = 0;
15812
15813		}
15814
15815		return maxAnisotropy;
15816
15817	}
15818
15819	function getMaxPrecision(precision) {
15820
15821		if (precision === 'highp') {
15822
15823			if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 &&
15824				gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) {
15825
15826				return 'highp';
15827
15828			}
15829
15830			precision = 'mediump';
15831
15832		}
15833
15834		if (precision === 'mediump') {
15835
15836			if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 &&
15837				gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) {
15838
15839				return 'mediump';
15840
15841			}
15842
15843		}
15844
15845		return 'lowp';
15846
15847	}
15848
15849	const isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl.constructor.name === 'WebGL2RenderingContext';
15850
15851	let precision = parameters.precision !== undefined ? parameters.precision : 'highp';
15852	const maxPrecision = getMaxPrecision(precision);
15853
15854	if (maxPrecision !== precision) {
15855
15856		console.warn('THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.');
15857		precision = maxPrecision;
15858
15859	}
15860
15861	const drawBuffers = isWebGL2 || extensions.has('WEBGL_draw_buffers');
15862
15863	const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
15864
15865	const maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
15866	const maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
15867	const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
15868	const maxCubemapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
15869
15870	const maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
15871	const maxVertexUniforms = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
15872	const maxVaryings = gl.getParameter(gl.MAX_VARYING_VECTORS);
15873	const maxFragmentUniforms = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
15874
15875	const vertexTextures = maxVertexTextures > 0;
15876	const floatFragmentTextures = isWebGL2 || extensions.has('OES_texture_float');
15877	const floatVertexTextures = vertexTextures && floatFragmentTextures;
15878
15879	const maxSamples = isWebGL2 ? gl.getParameter(gl.MAX_SAMPLES) : 0;
15880
15881	return {
15882
15883		isWebGL2: isWebGL2,
15884
15885		drawBuffers: drawBuffers,
15886
15887		getMaxAnisotropy: getMaxAnisotropy,
15888		getMaxPrecision: getMaxPrecision,
15889
15890		precision: precision,
15891		logarithmicDepthBuffer: logarithmicDepthBuffer,
15892
15893		maxTextures: maxTextures,
15894		maxVertexTextures: maxVertexTextures,
15895		maxTextureSize: maxTextureSize,
15896		maxCubemapSize: maxCubemapSize,
15897
15898		maxAttributes: maxAttributes,
15899		maxVertexUniforms: maxVertexUniforms,
15900		maxVaryings: maxVaryings,
15901		maxFragmentUniforms: maxFragmentUniforms,
15902
15903		vertexTextures: vertexTextures,
15904		floatFragmentTextures: floatFragmentTextures,
15905		floatVertexTextures: floatVertexTextures,
15906
15907		maxSamples: maxSamples
15908
15909	};
15910
15911}
15912
15913function WebGLClipping(properties) {
15914
15915	const scope = this;
15916
15917	let globalState = null,
15918		numGlobalPlanes = 0,
15919		localClippingEnabled = false,
15920		renderingShadows = false;
15921
15922	const plane = new Plane(),
15923		viewNormalMatrix = new Matrix3(),
15924
15925		uniform = { value: null, needsUpdate: false };
15926
15927	this.uniform = uniform;
15928	this.numPlanes = 0;
15929	this.numIntersection = 0;
15930
15931	this.init = function (planes, enableLocalClipping) {
15932
15933		const enabled =
15934			planes.length !== 0 ||
15935			enableLocalClipping ||
15936			// enable state of previous frame - the clipping code has to
15937			// run another frame in order to reset the state:
15938			numGlobalPlanes !== 0 ||
15939			localClippingEnabled;
15940
15941		localClippingEnabled = enableLocalClipping;
15942
15943		numGlobalPlanes = planes.length;
15944
15945		return enabled;
15946
15947	};
15948
15949	this.beginShadows = function () {
15950
15951		renderingShadows = true;
15952		projectPlanes(null);
15953
15954	};
15955
15956	this.endShadows = function () {
15957
15958		renderingShadows = false;
15959
15960	};
15961
15962	this.setGlobalState = function (planes, camera) {
15963
15964		globalState = projectPlanes(planes, camera, 0);
15965
15966	};
15967
15968	this.setState = function (material, camera, useCache) {
15969
15970		const planes = material.clippingPlanes,
15971			clipIntersection = material.clipIntersection,
15972			clipShadows = material.clipShadows;
15973
15974		const materialProperties = properties.get(material);
15975
15976		if (!localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && !clipShadows) {
15977
15978			// there's no local clipping
15979
15980			if (renderingShadows) {
15981
15982				// there's no global clipping
15983
15984				projectPlanes(null);
15985
15986			} else {
15987
15988				resetGlobalState();
15989
15990			}
15991
15992		} else {
15993
15994			const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
15995				lGlobal = nGlobal * 4;
15996
15997			let dstArray = materialProperties.clippingState || null;
15998
15999			uniform.value = dstArray; // ensure unique state
16000
16001			dstArray = projectPlanes(planes, camera, lGlobal, useCache);
16002
16003			for (let i = 0; i !== lGlobal; ++i) {
16004
16005				dstArray[i] = globalState[i];
16006
16007			}
16008
16009			materialProperties.clippingState = dstArray;
16010			this.numIntersection = clipIntersection ? this.numPlanes : 0;
16011			this.numPlanes += nGlobal;
16012
16013		}
16014
16015
16016	};
16017
16018	function resetGlobalState() {
16019
16020		if (uniform.value !== globalState) {
16021
16022			uniform.value = globalState;
16023			uniform.needsUpdate = numGlobalPlanes > 0;
16024
16025		}
16026
16027		scope.numPlanes = numGlobalPlanes;
16028		scope.numIntersection = 0;
16029
16030	}
16031
16032	function projectPlanes(planes, camera, dstOffset, skipTransform) {
16033
16034		const nPlanes = planes !== null ? planes.length : 0;
16035		let dstArray = null;
16036
16037		if (nPlanes !== 0) {
16038
16039			dstArray = uniform.value;
16040
16041			if (skipTransform !== true || dstArray === null) {
16042
16043				const flatSize = dstOffset + nPlanes * 4,
16044					viewMatrix = camera.matrixWorldInverse;
16045
16046				viewNormalMatrix.getNormalMatrix(viewMatrix);
16047
16048				if (dstArray === null || dstArray.length < flatSize) {
16049
16050					dstArray = new Float32Array(flatSize);
16051
16052				}
16053
16054				for (let i = 0, i4 = dstOffset; i !== nPlanes; ++i, i4 += 4) {
16055
16056					plane.copy(planes[i]).applyMatrix4(viewMatrix, viewNormalMatrix);
16057
16058					plane.normal.toArray(dstArray, i4);
16059					dstArray[i4 + 3] = plane.constant;
16060
16061				}
16062
16063			}
16064
16065			uniform.value = dstArray;
16066			uniform.needsUpdate = true;
16067
16068		}
16069
16070		scope.numPlanes = nPlanes;
16071		scope.numIntersection = 0;
16072
16073		return dstArray;
16074
16075	}
16076
16077}
16078
16079function WebGLCubeMaps(renderer) {
16080
16081	let cubemaps = new WeakMap();
16082
16083	function mapTextureMapping(texture, mapping) {
16084
16085		if (mapping === EquirectangularReflectionMapping) {
16086
16087			texture.mapping = CubeReflectionMapping;
16088
16089		} else if (mapping === EquirectangularRefractionMapping) {
16090
16091			texture.mapping = CubeRefractionMapping;
16092
16093		}
16094
16095		return texture;
16096
16097	}
16098
16099	function get(texture) {
16100
16101		if (texture && texture.isTexture) {
16102
16103			const mapping = texture.mapping;
16104
16105			if (mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping) {
16106
16107				if (cubemaps.has(texture)) {
16108
16109					const cubemap = cubemaps.get(texture).texture;
16110					return mapTextureMapping(cubemap, texture.mapping);
16111
16112				} else {
16113
16114					const image = texture.image;
16115
16116					if (image && image.height > 0) {
16117
16118						const renderTarget = new WebGLCubeRenderTarget(image.height / 2);
16119						renderTarget.fromEquirectangularTexture(renderer, texture);
16120						cubemaps.set(texture, renderTarget);
16121
16122						texture.addEventListener('dispose', onTextureDispose);
16123
16124						return mapTextureMapping(renderTarget.texture, texture.mapping);
16125
16126					} else {
16127
16128						// image not yet ready. try the conversion next frame
16129
16130						return null;
16131
16132					}
16133
16134				}
16135
16136			}
16137
16138		}
16139
16140		return texture;
16141
16142	}
16143
16144	function onTextureDispose(event) {
16145
16146		const texture = event.target;
16147
16148		texture.removeEventListener('dispose', onTextureDispose);
16149
16150		const cubemap = cubemaps.get(texture);
16151
16152		if (cubemap !== undefined) {
16153
16154			cubemaps.delete(texture);
16155			cubemap.dispose();
16156
16157		}
16158
16159	}
16160
16161	function dispose() {
16162
16163		cubemaps = new WeakMap();
16164
16165	}
16166
16167	return {
16168		get: get,
16169		dispose: dispose
16170	};
16171
16172}
16173
16174class OrthographicCamera extends Camera {
16175
16176	constructor(left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000) {
16177
16178		super();
16179
16180		this.isOrthographicCamera = true;
16181
16182		this.type = 'OrthographicCamera';
16183
16184		this.zoom = 1;
16185		this.view = null;
16186
16187		this.left = left;
16188		this.right = right;
16189		this.top = top;
16190		this.bottom = bottom;
16191
16192		this.near = near;
16193		this.far = far;
16194
16195		this.updateProjectionMatrix();
16196
16197	}
16198
16199	copy(source, recursive) {
16200
16201		super.copy(source, recursive);
16202
16203		this.left = source.left;
16204		this.right = source.right;
16205		this.top = source.top;
16206		this.bottom = source.bottom;
16207		this.near = source.near;
16208		this.far = source.far;
16209
16210		this.zoom = source.zoom;
16211		this.view = source.view === null ? null : Object.assign({}, source.view);
16212
16213		return this;
16214
16215	}
16216
16217	setViewOffset(fullWidth, fullHeight, x, y, width, height) {
16218
16219		if (this.view === null) {
16220
16221			this.view = {
16222				enabled: true,
16223				fullWidth: 1,
16224				fullHeight: 1,
16225				offsetX: 0,
16226				offsetY: 0,
16227				width: 1,
16228				height: 1
16229			};
16230
16231		}
16232
16233		this.view.enabled = true;
16234		this.view.fullWidth = fullWidth;
16235		this.view.fullHeight = fullHeight;
16236		this.view.offsetX = x;
16237		this.view.offsetY = y;
16238		this.view.width = width;
16239		this.view.height = height;
16240
16241		this.updateProjectionMatrix();
16242
16243	}
16244
16245	clearViewOffset() {
16246
16247		if (this.view !== null) {
16248
16249			this.view.enabled = false;
16250
16251		}
16252
16253		this.updateProjectionMatrix();
16254
16255	}
16256
16257	updateProjectionMatrix() {
16258
16259		const dx = (this.right - this.left) / (2 * this.zoom);
16260		const dy = (this.top - this.bottom) / (2 * this.zoom);
16261		const cx = (this.right + this.left) / 2;
16262		const cy = (this.top + this.bottom) / 2;
16263
16264		let left = cx - dx;
16265		let right = cx + dx;
16266		let top = cy + dy;
16267		let bottom = cy - dy;
16268
16269		if (this.view !== null && this.view.enabled) {
16270
16271			const scaleW = (this.right - this.left) / this.view.fullWidth / this.zoom;
16272			const scaleH = (this.top - this.bottom) / this.view.fullHeight / this.zoom;
16273
16274			left += scaleW * this.view.offsetX;
16275			right = left + scaleW * this.view.width;
16276			top -= scaleH * this.view.offsetY;
16277			bottom = top - scaleH * this.view.height;
16278
16279		}
16280
16281		this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far, this.coordinateSystem);
16282
16283		this.projectionMatrixInverse.copy(this.projectionMatrix).invert();
16284
16285	}
16286
16287	toJSON(meta) {
16288
16289		const data = super.toJSON(meta);
16290
16291		data.object.zoom = this.zoom;
16292		data.object.left = this.left;
16293		data.object.right = this.right;
16294		data.object.top = this.top;
16295		data.object.bottom = this.bottom;
16296		data.object.near = this.near;
16297		data.object.far = this.far;
16298
16299		if (this.view !== null) data.object.view = Object.assign({}, this.view);
16300
16301		return data;
16302
16303	}
16304
16305}
16306
16307const LOD_MIN = 4;
16308
16309// The standard deviations (radians) associated with the extra mips. These are
16310// chosen to approximate a Trowbridge-Reitz distribution function times the
16311// geometric shadowing function. These sigma values squared must match the
16312// variance #defines in cube_uv_reflection_fragment.glsl.js.
16313const EXTRA_LOD_SIGMA = [0.125, 0.215, 0.35, 0.446, 0.526, 0.582];
16314
16315// The maximum length of the blur for loop. Smaller sigmas will use fewer
16316// samples and exit early, but not recompile the shader.
16317const MAX_SAMPLES = 20;
16318
16319const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
16320const _clearColor = /*@__PURE__*/ new Color();
16321let _oldTarget = null;
16322let _oldActiveCubeFace = 0;
16323let _oldActiveMipmapLevel = 0;
16324
16325// Golden Ratio
16326const PHI = (1 + Math.sqrt(5)) / 2;
16327const INV_PHI = 1 / PHI;
16328
16329// Vertices of a dodecahedron (except the opposites, which represent the
16330// same axis), used as axis directions evenly spread on a sphere.
16331const _axisDirections = [
16332	/*@__PURE__*/ new Vector3(1, 1, 1),
16333	/*@__PURE__*/ new Vector3(- 1, 1, 1),
16334	/*@__PURE__*/ new Vector3(1, 1, - 1),
16335	/*@__PURE__*/ new Vector3(- 1, 1, - 1),
16336	/*@__PURE__*/ new Vector3(0, PHI, INV_PHI),
16337	/*@__PURE__*/ new Vector3(0, PHI, - INV_PHI),
16338	/*@__PURE__*/ new Vector3(INV_PHI, 0, PHI),
16339	/*@__PURE__*/ new Vector3(- INV_PHI, 0, PHI),
16340	/*@__PURE__*/ new Vector3(PHI, INV_PHI, 0),
16341	/*@__PURE__*/ new Vector3(- PHI, INV_PHI, 0)];
16342
16343/**
16344 * This class generates a Prefiltered, Mipmapped Radiance Environment Map
16345 * (PMREM) from a cubeMap environment texture. This allows different levels of
16346 * blur to be quickly accessed based on material roughness. It is packed into a
16347 * special CubeUV format that allows us to perform custom interpolation so that
16348 * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
16349 * chain, it only goes down to the LOD_MIN level (above), and then creates extra
16350 * even more filtered 'mips' at the same LOD_MIN resolution, associated with
16351 * higher roughness levels. In this way we maintain resolution to smoothly
16352 * interpolate diffuse lighting while limiting sampling computation.
16353 *
16354 * Paper: Fast, Accurate Image-Based Lighting
16355 * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view
16356*/
16357
16358class PMREMGenerator {
16359
16360	constructor(renderer) {
16361
16362		this._renderer = renderer;
16363		this._pingPongRenderTarget = null;
16364
16365		this._lodMax = 0;
16366		this._cubeSize = 0;
16367		this._lodPlanes = [];
16368		this._sizeLods = [];
16369		this._sigmas = [];
16370
16371		this._blurMaterial = null;
16372		this._cubemapMaterial = null;
16373		this._equirectMaterial = null;
16374
16375		this._compileMaterial(this._blurMaterial);
16376
16377	}
16378
16379	/**
16380	 * Generates a PMREM from a supplied Scene, which can be faster than using an
16381	 * image if networking bandwidth is low. Optional sigma specifies a blur radius
16382	 * in radians to be applied to the scene before PMREM generation. Optional near
16383	 * and far planes ensure the scene is rendered in its entirety (the cubeCamera
16384	 * is placed at the origin).
16385	 */
16386	fromScene(scene, sigma = 0, near = 0.1, far = 100) {
16387
16388		_oldTarget = this._renderer.getRenderTarget();
16389		_oldActiveCubeFace = this._renderer.getActiveCubeFace();
16390		_oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
16391
16392		this._setSize(256);
16393
16394		const cubeUVRenderTarget = this._allocateTargets();
16395		cubeUVRenderTarget.depthBuffer = true;
16396
16397		this._sceneToCubeUV(scene, near, far, cubeUVRenderTarget);
16398
16399		if (sigma > 0) {
16400
16401			this._blur(cubeUVRenderTarget, 0, 0, sigma);
16402
16403		}
16404
16405		this._applyPMREM(cubeUVRenderTarget);
16406		this._cleanup(cubeUVRenderTarget);
16407
16408		return cubeUVRenderTarget;
16409
16410	}
16411
16412	/**
16413	 * Generates a PMREM from an equirectangular texture, which can be either LDR
16414	 * or HDR. The ideal input image size is 1k (1024 x 512),
16415	 * as this matches best with the 256 x 256 cubemap output.
16416	 */
16417	fromEquirectangular(equirectangular, renderTarget = null) {
16418
16419		return this._fromTexture(equirectangular, renderTarget);
16420
16421	}
16422
16423	/**
16424	 * Generates a PMREM from an cubemap texture, which can be either LDR
16425	 * or HDR. The ideal input cube size is 256 x 256,
16426	 * as this matches best with the 256 x 256 cubemap output.
16427	 */
16428	fromCubemap(cubemap, renderTarget = null) {
16429
16430		return this._fromTexture(cubemap, renderTarget);
16431
16432	}
16433
16434	/**
16435	 * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during
16436	 * your texture's network fetch for increased concurrency.
16437	 */
16438	compileCubemapShader() {
16439
16440		if (this._cubemapMaterial === null) {
16441
16442			this._cubemapMaterial = _getCubemapMaterial();
16443			this._compileMaterial(this._cubemapMaterial);
16444
16445		}
16446
16447	}
16448
16449	/**
16450	 * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during
16451	 * your texture's network fetch for increased concurrency.
16452	 */
16453	compileEquirectangularShader() {
16454
16455		if (this._equirectMaterial === null) {
16456
16457			this._equirectMaterial = _getEquirectMaterial();
16458			this._compileMaterial(this._equirectMaterial);
16459
16460		}
16461
16462	}
16463
16464	/**
16465	 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
16466	 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
16467	 * one of them will cause any others to also become unusable.
16468	 */
16469	dispose() {
16470
16471		this._dispose();
16472
16473		if (this._cubemapMaterial !== null) this._cubemapMaterial.dispose();
16474		if (this._equirectMaterial !== null) this._equirectMaterial.dispose();
16475
16476	}
16477
16478	// private interface
16479
16480	_setSize(cubeSize) {
16481
16482		this._lodMax = Math.floor(Math.log2(cubeSize));
16483		this._cubeSize = Math.pow(2, this._lodMax);
16484
16485	}
16486
16487	_dispose() {
16488
16489		if (this._blurMaterial !== null) this._blurMaterial.dispose();
16490
16491		if (this._pingPongRenderTarget !== null) this._pingPongRenderTarget.dispose();
16492
16493		for (let i = 0; i < this._lodPlanes.length; i++) {
16494
16495			this._lodPlanes[i].dispose();
16496
16497		}
16498
16499	}
16500
16501	_cleanup(outputTarget) {
16502
16503		this._renderer.setRenderTarget(_oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel);
16504		outputTarget.scissorTest = false;
16505		_setViewport(outputTarget, 0, 0, outputTarget.width, outputTarget.height);
16506
16507	}
16508
16509	_fromTexture(texture, renderTarget) {
16510
16511		if (texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping) {
16512
16513			this._setSize(texture.image.length === 0 ? 16 : (texture.image[0].width || texture.image[0].image.width));
16514
16515		} else { // Equirectangular
16516
16517			this._setSize(texture.image.width / 4);
16518
16519		}
16520
16521		_oldTarget = this._renderer.getRenderTarget();
16522		_oldActiveCubeFace = this._renderer.getActiveCubeFace();
16523		_oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
16524
16525		const cubeUVRenderTarget = renderTarget || this._allocateTargets();
16526		this._textureToCubeUV(texture, cubeUVRenderTarget);
16527		this._applyPMREM(cubeUVRenderTarget);
16528		this._cleanup(cubeUVRenderTarget);
16529
16530		return cubeUVRenderTarget;
16531
16532	}
16533
16534	_allocateTargets() {
16535
16536		const width = 3 * Math.max(this._cubeSize, 16 * 7);
16537		const height = 4 * this._cubeSize;
16538
16539		const params = {
16540			magFilter: LinearFilter,
16541			minFilter: LinearFilter,
16542			generateMipmaps: false,
16543			type: HalfFloatType,
16544			format: RGBAFormat,
16545			colorSpace: LinearSRGBColorSpace,
16546			depthBuffer: false
16547		};
16548
16549		const cubeUVRenderTarget = _createRenderTarget(width, height, params);
16550
16551		if (this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height) {
16552
16553			if (this._pingPongRenderTarget !== null) {
16554
16555				this._dispose();
16556
16557			}
16558
16559			this._pingPongRenderTarget = _createRenderTarget(width, height, params);
16560
16561			const { _lodMax } = this;
16562			({ sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes(_lodMax));
16563
16564			this._blurMaterial = _getBlurShader(_lodMax, width, height);
16565
16566		}
16567
16568		return cubeUVRenderTarget;
16569
16570	}
16571
16572	_compileMaterial(material) {
16573
16574		const tmpMesh = new Mesh(this._lodPlanes[0], material);
16575		this._renderer.compile(tmpMesh, _flatCamera);
16576
16577	}
16578
16579	_sceneToCubeUV(scene, near, far, cubeUVRenderTarget) {
16580
16581		const fov = 90;
16582		const aspect = 1;
16583		const cubeCamera = new PerspectiveCamera(fov, aspect, near, far);
16584		const upSign = [1, - 1, 1, 1, 1, 1];
16585		const forwardSign = [1, 1, 1, - 1, - 1, - 1];
16586		const renderer = this._renderer;
16587
16588		const originalAutoClear = renderer.autoClear;
16589		const toneMapping = renderer.toneMapping;
16590		renderer.getClearColor(_clearColor);
16591
16592		renderer.toneMapping = NoToneMapping;
16593		renderer.autoClear = false;
16594
16595		const backgroundMaterial = new MeshBasicMaterial({
16596			name: 'PMREM.Background',
16597			side: BackSide,
16598			depthWrite: false,
16599			depthTest: false,
16600		});
16601
16602		const backgroundBox = new Mesh(new BoxGeometry(), backgroundMaterial);
16603
16604		let useSolidColor = false;
16605		const background = scene.background;
16606
16607		if (background) {
16608
16609			if (background.isColor) {
16610
16611				backgroundMaterial.color.copy(background);
16612				scene.background = null;
16613				useSolidColor = true;
16614
16615			}
16616
16617		} else {
16618
16619			backgroundMaterial.color.copy(_clearColor);
16620			useSolidColor = true;
16621
16622		}
16623
16624		for (let i = 0; i < 6; i++) {
16625
16626			const col = i % 3;
16627
16628			if (col === 0) {
16629
16630				cubeCamera.up.set(0, upSign[i], 0);
16631				cubeCamera.lookAt(forwardSign[i], 0, 0);
16632
16633			} else if (col === 1) {
16634
16635				cubeCamera.up.set(0, 0, upSign[i]);
16636				cubeCamera.lookAt(0, forwardSign[i], 0);
16637
16638			} else {
16639
16640				cubeCamera.up.set(0, upSign[i], 0);
16641				cubeCamera.lookAt(0, 0, forwardSign[i]);
16642
16643			}
16644
16645			const size = this._cubeSize;
16646
16647			_setViewport(cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size);
16648
16649			renderer.setRenderTarget(cubeUVRenderTarget);
16650
16651			if (useSolidColor) {
16652
16653				renderer.render(backgroundBox, cubeCamera);
16654
16655			}
16656
16657			renderer.render(scene, cubeCamera);
16658
16659		}
16660
16661		backgroundBox.geometry.dispose();
16662		backgroundBox.material.dispose();
16663
16664		renderer.toneMapping = toneMapping;
16665		renderer.autoClear = originalAutoClear;
16666		scene.background = background;
16667
16668	}
16669
16670	_textureToCubeUV(texture, cubeUVRenderTarget) {
16671
16672		const renderer = this._renderer;
16673
16674		const isCubeTexture = (texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping);
16675
16676		if (isCubeTexture) {
16677
16678			if (this._cubemapMaterial === null) {
16679
16680				this._cubemapMaterial = _getCubemapMaterial();
16681
16682			}
16683
16684			this._cubemapMaterial.uniforms.flipEnvMap.value = (texture.isRenderTargetTexture === false) ? - 1 : 1;
16685
16686		} else {
16687
16688			if (this._equirectMaterial === null) {
16689
16690				this._equirectMaterial = _getEquirectMaterial();
16691
16692			}
16693
16694		}
16695
16696		const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
16697		const mesh = new Mesh(this._lodPlanes[0], material);
16698
16699		const uniforms = material.uniforms;
16700
16701		uniforms['envMap'].value = texture;
16702
16703		const size = this._cubeSize;
16704
16705		_setViewport(cubeUVRenderTarget, 0, 0, 3 * size, 2 * size);
16706
16707		renderer.setRenderTarget(cubeUVRenderTarget);
16708		renderer.render(mesh, _flatCamera);
16709
16710	}
16711
16712	_applyPMREM(cubeUVRenderTarget) {
16713
16714		const renderer = this._renderer;
16715		const autoClear = renderer.autoClear;
16716		renderer.autoClear = false;
16717
16718		for (let i = 1; i < this._lodPlanes.length; i++) {
16719
16720			const sigma = Math.sqrt(this._sigmas[i] * this._sigmas[i] - this._sigmas[i - 1] * this._sigmas[i - 1]);
16721
16722			const poleAxis = _axisDirections[(i - 1) % _axisDirections.length];
16723
16724			this._blur(cubeUVRenderTarget, i - 1, i, sigma, poleAxis);
16725
16726		}
16727
16728		renderer.autoClear = autoClear;
16729
16730	}
16731
16732	/**
16733	 * This is a two-pass Gaussian blur for a cubemap. Normally this is done
16734	 * vertically and horizontally, but this breaks down on a cube. Here we apply
16735	 * the blur latitudinally (around the poles), and then longitudinally (towards
16736	 * the poles) to approximate the orthogonally-separable blur. It is least
16737	 * accurate at the poles, but still does a decent job.
16738	 */
16739	_blur(cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis) {
16740
16741		const pingPongRenderTarget = this._pingPongRenderTarget;
16742
16743		this._halfBlur(
16744			cubeUVRenderTarget,
16745			pingPongRenderTarget,
16746			lodIn,
16747			lodOut,
16748			sigma,
16749			'latitudinal',
16750			poleAxis);
16751
16752		this._halfBlur(
16753			pingPongRenderTarget,
16754			cubeUVRenderTarget,
16755			lodOut,
16756			lodOut,
16757			sigma,
16758			'longitudinal',
16759			poleAxis);
16760
16761	}
16762
16763	_halfBlur(targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis) {
16764
16765		const renderer = this._renderer;
16766		const blurMaterial = this._blurMaterial;
16767
16768		if (direction !== 'latitudinal' && direction !== 'longitudinal') {
16769
16770			console.error(
16771				'blur direction must be either latitudinal or longitudinal!');
16772
16773		}
16774
16775		// Number of standard deviations at which to cut off the discrete approximation.
16776		const STANDARD_DEVIATIONS = 3;
16777
16778		const blurMesh = new Mesh(this._lodPlanes[lodOut], blurMaterial);
16779		const blurUniforms = blurMaterial.uniforms;
16780
16781		const pixels = this._sizeLods[lodIn] - 1;
16782		const radiansPerPixel = isFinite(sigmaRadians) ? Math.PI / (2 * pixels) : 2 * Math.PI / (2 * MAX_SAMPLES - 1);
16783		const sigmaPixels = sigmaRadians / radiansPerPixel;
16784		const samples = isFinite(sigmaRadians) ? 1 + Math.floor(STANDARD_DEVIATIONS * sigmaPixels) : MAX_SAMPLES;
16785
16786		if (samples > MAX_SAMPLES) {
16787
16788			console.warn(`sigmaRadians, ${sigmaRadians}, is too large and will clip, as it requested ${samples} samples when the maximum is set to ${MAX_SAMPLES}`);
16789
16790		}
16791
16792		const weights = [];
16793		let sum = 0;
16794
16795		for (let i = 0; i < MAX_SAMPLES; ++i) {
16796
16797			const x = i / sigmaPixels;
16798			const weight = Math.exp(- x * x / 2);
16799			weights.push(weight);
16800
16801			if (i === 0) {
16802
16803				sum += weight;
16804
16805			} else if (i < samples) {
16806
16807				sum += 2 * weight;
16808
16809			}
16810
16811		}
16812
16813		for (let i = 0; i < weights.length; i++) {
16814
16815			weights[i] = weights[i] / sum;
16816
16817		}
16818
16819		blurUniforms['envMap'].value = targetIn.texture;
16820		blurUniforms['samples'].value = samples;
16821		blurUniforms['weights'].value = weights;
16822		blurUniforms['latitudinal'].value = direction === 'latitudinal';
16823
16824		if (poleAxis) {
16825
16826			blurUniforms['poleAxis'].value = poleAxis;
16827
16828		}
16829
16830		const { _lodMax } = this;
16831		blurUniforms['dTheta'].value = radiansPerPixel;
16832		blurUniforms['mipInt'].value = _lodMax - lodIn;
16833
16834		const outputSize = this._sizeLods[lodOut];
16835		const x = 3 * outputSize * (lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0);
16836		const y = 4 * (this._cubeSize - outputSize);
16837
16838		_setViewport(targetOut, x, y, 3 * outputSize, 2 * outputSize);
16839		renderer.setRenderTarget(targetOut);
16840		renderer.render(blurMesh, _flatCamera);
16841
16842	}
16843
16844}
16845
16846
16847
16848function _createPlanes(lodMax) {
16849
16850	const lodPlanes = [];
16851	const sizeLods = [];
16852	const sigmas = [];
16853
16854	let lod = lodMax;
16855
16856	const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
16857
16858	for (let i = 0; i < totalLods; i++) {
16859
16860		const sizeLod = Math.pow(2, lod);
16861		sizeLods.push(sizeLod);
16862		let sigma = 1.0 / sizeLod;
16863
16864		if (i > lodMax - LOD_MIN) {
16865
16866			sigma = EXTRA_LOD_SIGMA[i - lodMax + LOD_MIN - 1];
16867
16868		} else if (i === 0) {
16869
16870			sigma = 0;
16871
16872		}
16873
16874		sigmas.push(sigma);
16875
16876		const texelSize = 1.0 / (sizeLod - 2);
16877		const min = - texelSize;
16878		const max = 1 + texelSize;
16879		const uv1 = [min, min, max, min, max, max, min, min, max, max, min, max];
16880
16881		const cubeFaces = 6;
16882		const vertices = 6;
16883		const positionSize = 3;
16884		const uvSize = 2;
16885		const faceIndexSize = 1;
16886
16887		const position = new Float32Array(positionSize * vertices * cubeFaces);
16888		const uv = new Float32Array(uvSize * vertices * cubeFaces);
16889		const faceIndex = new Float32Array(faceIndexSize * vertices * cubeFaces);
16890
16891		for (let face = 0; face < cubeFaces; face++) {
16892
16893			const x = (face % 3) * 2 / 3 - 1;
16894			const y = face > 2 ? 0 : - 1;
16895			const coordinates = [
16896				x, y, 0,
16897				x + 2 / 3, y, 0,
16898				x + 2 / 3, y + 1, 0,
16899				x, y, 0,
16900				x + 2 / 3, y + 1, 0,
16901				x, y + 1, 0
16902			];
16903			position.set(coordinates, positionSize * vertices * face);
16904			uv.set(uv1, uvSize * vertices * face);
16905			const fill = [face, face, face, face, face, face];
16906			faceIndex.set(fill, faceIndexSize * vertices * face);
16907
16908		}
16909
16910		const planes = new BufferGeometry();
16911		planes.setAttribute('position', new BufferAttribute(position, positionSize));
16912		planes.setAttribute('uv', new BufferAttribute(uv, uvSize));
16913		planes.setAttribute('faceIndex', new BufferAttribute(faceIndex, faceIndexSize));
16914		lodPlanes.push(planes);
16915
16916		if (lod > LOD_MIN) {
16917
16918			lod--;
16919
16920		}
16921
16922	}
16923
16924	return { lodPlanes, sizeLods, sigmas };
16925
16926}
16927
16928function _createRenderTarget(width, height, params) {
16929
16930	const cubeUVRenderTarget = new WebGLRenderTarget(width, height, params);
16931	cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
16932	cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
16933	cubeUVRenderTarget.scissorTest = true;
16934	return cubeUVRenderTarget;
16935
16936}
16937
16938function _setViewport(target, x, y, width, height) {
16939
16940	target.viewport.set(x, y, width, height);
16941	target.scissor.set(x, y, width, height);
16942
16943}
16944
16945function _getBlurShader(lodMax, width, height) {
16946
16947	const weights = new Float32Array(MAX_SAMPLES);
vendor: 3,245 bytes, lines 16948-17107
16948	const poleAxis = new Vector3(0, 1, 0);
16949	const shaderMaterial = new ShaderMaterial({
16950
16951		name: 'SphericalGaussianBlur',
16952
16953		defines: {
16954			'n': MAX_SAMPLES,
16955			'CUBEUV_TEXEL_WIDTH': 1.0 / width,
16956			'CUBEUV_TEXEL_HEIGHT': 1.0 / height,
16957			'CUBEUV_MAX_MIP': `${lodMax}.0`,
16958		},
16959
16960		uniforms: {
16961			'envMap': { value: null },
16962			'samples': { value: 1 },
16963			'weights': { value: weights },
16964			'latitudinal': { value: false },
16965			'dTheta': { value: 0 },
16966			'mipInt': { value: 0 },
16967			'poleAxis': { value: poleAxis }
16968		},
16969
16970		vertexShader: _getCommonVertexShader(),
16971
16972		fragmentShader: /* glsl */`
16973
16974			precision mediump float;
16975			precision mediump int;
16976
16977			varying vec3 vOutputDirection;
16978
16979			uniform sampler2D envMap;
16980			uniform int samples;
16981			uniform float weights[ n ];
16982			uniform bool latitudinal;
16983			uniform float dTheta;
16984			uniform float mipInt;
16985			uniform vec3 poleAxis;
16986
16987			#define ENVMAP_TYPE_CUBE_UV
16988			#include <cube_uv_reflection_fragment>
16989
16990			vec3 getSample( float theta, vec3 axis ) {
16991
16992				float cosTheta = cos( theta );
16993				// Rodrigues' axis-angle rotation
16994				vec3 sampleDirection = vOutputDirection * cosTheta
16995					+ cross( axis, vOutputDirection ) * sin( theta )
16996					+ axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
16997
16998				return bilinearCubeUV( envMap, sampleDirection, mipInt );
16999
17000			}
17001
17002			void main() {
17003
17004				vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
17005
17006				if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
17007
17008					axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
17009
17010				}
17011
17012				axis = normalize( axis );
17013
17014				gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
17015				gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
17016
17017				for ( int i = 1; i < n; i++ ) {
17018
17019					if ( i >= samples ) {
17020
17021						break;
17022
17023					}
17024
17025					float theta = dTheta * float( i );
17026					gl_FragColor.rgb += weights[ i ] * getSample( -1.0 * theta, axis );
17027					gl_FragColor.rgb += weights[ i ] * getSample( theta, axis );
17028
17029				}
17030
17031			}
17032		`,
17033
17034		blending: NoBlending,
17035		depthTest: false,
17036		depthWrite: false
17037
17038	});
17039
17040	return shaderMaterial;
17041
17042}
17043
17044function _getEquirectMaterial() {
17045
17046	return new ShaderMaterial({
17047
17048		name: 'EquirectangularToCubeUV',
17049
17050		uniforms: {
17051			'envMap': { value: null }
17052		},
17053
17054		vertexShader: _getCommonVertexShader(),
17055
17056		fragmentShader: /* glsl */`
17057
17058			precision mediump float;
17059			precision mediump int;
17060
17061			varying vec3 vOutputDirection;
17062
17063			uniform sampler2D envMap;
17064
17065			#include <common>
17066
17067			void main() {
17068
17069				vec3 outputDirection = normalize( vOutputDirection );
17070				vec2 uv = equirectUv( outputDirection );
17071
17072				gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );
17073
17074			}
17075		`,
17076
17077		blending: NoBlending,
17078		depthTest: false,
17079		depthWrite: false
17080
17081	});
17082
17083}
17084
17085function _getCubemapMaterial() {
17086
17087	return new ShaderMaterial({
17088
17089		name: 'CubemapToCubeUV',
17090
17091		uniforms: {
17092			'envMap': { value: null },
17093			'flipEnvMap': { value: - 1 }
17094		},
17095
17096		vertexShader: _getCommonVertexShader(),
17097
17098		fragmentShader: /* glsl */`
17099
17100			precision mediump float;
17101			precision mediump int;
17102
17103			uniform float flipEnvMap;
17104
17105			varying vec3 vOutputDirection;
17106
17107			uniform samplerCube envMap;
17108
17109			void main() {
17110
17111				gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
17112
17113			}
17114		`,
17115
17116		blending: NoBlending,
17117		depthTest: false,
17118		depthWrite: false
17119
17120	});
17121
17122}
17123
17124function _getCommonVertexShader() {
17125
17126	return /* glsl */`
17127
17128		precision mediump float;
17129		precision mediump int;
17130
17131		attribute float faceIndex;
17132
17133		varying vec3 vOutputDirection;
17134
17135		// RH coordinate system; PMREM face-indexing convention
17136		vec3 getDirection( vec2 uv, float face ) {
17137
17138			uv = 2.0 * uv - 1.0;
17139
17140			vec3 direction = vec3( uv, 1.0 );
17141
17142			if ( face == 0.0 ) {
17143
17144				direction = direction.zyx; // ( 1, v, u ) pos x
17145
17146			} else if ( face == 1.0 ) {
17147
17148				direction = direction.xzy;
17149				direction.xz *= -1.0; // ( -u, 1, -v ) pos y
17150
17151			} else if ( face == 2.0 ) {
17152
17153				direction.x *= -1.0; // ( -u, v, 1 ) pos z
17154
17155			} else if ( face == 3.0 ) {
17156
17157				direction = direction.zyx;
17158				direction.xz *= -1.0; // ( -1, v, -u ) neg x
17159
17160			} else if ( face == 4.0 ) {
17161
17162				direction = direction.xzy;
17163				direction.xy *= -1.0; // ( -u, -1, v ) neg y
17164
17165			} else if ( face == 5.0 ) {
17166
17167				direction.z *= -1.0; // ( u, v, -1 ) neg z
17168
17169			}
17170
17171			return direction;
17172
17173		}
17174
17175		void main() {
17176
17177			vOutputDirection = getDirection( uv, faceIndex );
17178			gl_Position = vec4( position, 1.0 );
17179
17180		}
17181	`;
17182
17183}
17184
17185function WebGLCubeUVMaps(renderer) {
17186
17187	let cubeUVmaps = new WeakMap();
17188
17189	let pmremGenerator = null;
17190
17191	function get(texture) {
17192
17193		if (texture && texture.isTexture) {
17194
17195			const mapping = texture.mapping;
17196
17197			const isEquirectMap = (mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping);
17198			const isCubeMap = (mapping === CubeReflectionMapping || mapping === CubeRefractionMapping);
17199
17200			// equirect/cube map to cubeUV conversion
17201
17202			if (isEquirectMap || isCubeMap) {
17203
17204				if (texture.isRenderTargetTexture && texture.needsPMREMUpdate === true) {
17205
17206					texture.needsPMREMUpdate = false;
17207
17208					let renderTarget = cubeUVmaps.get(texture);
17209
17210					if (pmremGenerator === null) pmremGenerator = new PMREMGenerator(renderer);
17211
17212					renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture, renderTarget) : pmremGenerator.fromCubemap(texture, renderTarget);
17213					cubeUVmaps.set(texture, renderTarget);
17214
17215					return renderTarget.texture;
17216
17217				} else {
17218
17219					if (cubeUVmaps.has(texture)) {
17220
17221						return cubeUVmaps.get(texture).texture;
17222
17223					} else {
17224
17225						const image = texture.image;
17226
17227						if ((isEquirectMap && image && image.height > 0) || (isCubeMap && image && isCubeTextureComplete(image))) {
17228
17229							if (pmremGenerator === null) pmremGenerator = new PMREMGenerator(renderer);
17230
17231							const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular(texture) : pmremGenerator.fromCubemap(texture);
17232							cubeUVmaps.set(texture, renderTarget);
17233
17234							texture.addEventListener('dispose', onTextureDispose);
17235
17236							return renderTarget.texture;
17237
17238						} else {
17239
17240							// image not yet ready. try the conversion next frame
17241
17242							return null;
17243
17244						}
17245
17246					}
17247
17248				}
17249
17250			}
17251
17252		}
17253
17254		return texture;
17255
17256	}
17257
17258	function isCubeTextureComplete(image) {
17259
17260		let count = 0;
17261		const length = 6;
17262
17263		for (let i = 0; i < length; i++) {
17264
17265			if (image[i] !== undefined) count++;
17266
17267		}
17268
17269		return count === length;
17270
17271
17272	}
17273
17274	function onTextureDispose(event) {
17275
17276		const texture = event.target;
17277
17278		texture.removeEventListener('dispose', onTextureDispose);
17279
17280		const cubemapUV = cubeUVmaps.get(texture);
17281
17282		if (cubemapUV !== undefined) {
17283
17284			cubeUVmaps.delete(texture);
17285			cubemapUV.dispose();
17286
17287		}
17288
17289	}
17290
17291	function dispose() {
17292
17293		cubeUVmaps = new WeakMap();
17294
17295		if (pmremGenerator !== null) {
17296
17297			pmremGenerator.dispose();
17298			pmremGenerator = null;
17299
17300		}
17301
17302	}
17303
17304	return {
17305		get: get,
17306		dispose: dispose
17307	};
17308
17309}
17310
17311function WebGLExtensions(gl) {
17312
17313	const extensions = {};
17314
17315	function getExtension(name) {
17316
17317		if (extensions[name] !== undefined) {
17318
17319			return extensions[name];
17320
17321		}
17322
17323		let extension;
17324
17325		switch (name) {
17326
17327			case 'WEBGL_depth_texture':
17328				extension = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture');
17329				break;
17330
17331			case 'EXT_texture_filter_anisotropic':
17332				extension = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
17333				break;
17334
17335			case 'WEBGL_compressed_texture_s3tc':
17336				extension = gl.getExtension('WEBGL_compressed_texture_s3tc') || gl.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
17337				break;
17338
17339			case 'WEBGL_compressed_texture_pvrtc':
17340				extension = gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');
17341				break;
17342
17343			default:
17344				extension = gl.getExtension(name);
17345
17346		}
17347
17348		extensions[name] = extension;
17349
17350		return extension;
17351
17352	}
17353
17354	return {
17355
17356		has: function (name) {
17357
17358			return getExtension(name) !== null;
17359
17360		},
17361
17362		init: function (capabilities) {
17363
17364			if (capabilities.isWebGL2) {
17365
17366				getExtension('EXT_color_buffer_float');
17367				getExtension('WEBGL_clip_cull_distance');
17368
17369			} else {
17370
17371				getExtension('WEBGL_depth_texture');
17372				getExtension('OES_texture_float');
17373				getExtension('OES_texture_half_float');
17374				getExtension('OES_texture_half_float_linear');
17375				getExtension('OES_standard_derivatives');
17376				getExtension('OES_element_index_uint');
17377				getExtension('OES_vertex_array_object');
17378				getExtension('ANGLE_instanced_arrays');
17379
17380			}
17381
17382			getExtension('OES_texture_float_linear');
17383			getExtension('EXT_color_buffer_half_float');
17384			getExtension('WEBGL_multisampled_render_to_texture');
17385
17386		},
17387
17388		get: function (name) {
17389
17390			const extension = getExtension(name);
17391
17392			if (extension === null) {
17393
17394				console.warn('THREE.WebGLRenderer: ' + name + ' extension not supported.');
17395
17396			}
17397
17398			return extension;
17399
17400		}
17401
17402	};
17403
17404}
17405
17406function WebGLGeometries(gl, attributes, info, bindingStates) {
17407
17408	const geometries = {};
17409	const wireframeAttributes = new WeakMap();
17410
17411	function onGeometryDispose(event) {
17412
17413		const geometry = event.target;
17414
17415		if (geometry.index !== null) {
17416
17417			attributes.remove(geometry.index);
17418
17419		}
17420
17421		for (const name in geometry.attributes) {
17422
17423			attributes.remove(geometry.attributes[name]);
17424
17425		}
17426
17427		for (const name in geometry.morphAttributes) {
17428
17429			const array = geometry.morphAttributes[name];
17430
17431			for (let i = 0, l = array.length; i < l; i++) {
17432
17433				attributes.remove(array[i]);
17434
17435			}
17436
17437		}
17438
17439		geometry.removeEventListener('dispose', onGeometryDispose);
17440
17441		delete geometries[geometry.id];
17442
17443		const attribute = wireframeAttributes.get(geometry);
17444
17445		if (attribute) {
17446
17447			attributes.remove(attribute);
17448			wireframeAttributes.delete(geometry);
17449
17450		}
17451
17452		bindingStates.releaseStatesOfGeometry(geometry);
17453
17454		if (geometry.isInstancedBufferGeometry === true) {
17455
17456			delete geometry._maxInstanceCount;
17457
17458		}
17459
17460		//
17461
17462		info.memory.geometries--;
17463
17464	}
17465
17466	function get(object, geometry) {
17467
17468		if (geometries[geometry.id] === true) return geometry;
17469
17470		geometry.addEventListener('dispose', onGeometryDispose);
17471
17472		geometries[geometry.id] = true;
17473
17474		info.memory.geometries++;
17475
17476		return geometry;
17477
17478	}
17479
17480	function update(geometry) {
17481
17482		const geometryAttributes = geometry.attributes;
17483
17484		// Updating index buffer in VAO now. See WebGLBindingStates.
17485
17486		for (const name in geometryAttributes) {
17487
17488			attributes.update(geometryAttributes[name], gl.ARRAY_BUFFER);
17489
17490		}
17491
17492		// morph targets
17493
17494		const morphAttributes = geometry.morphAttributes;
17495
17496		for (const name in morphAttributes) {
17497
17498			const array = morphAttributes[name];
17499
17500			for (let i = 0, l = array.length; i < l; i++) {
17501
17502				attributes.update(array[i], gl.ARRAY_BUFFER);
17503
17504			}
17505
17506		}
17507
17508	}
17509
17510	function updateWireframeAttribute(geometry) {
17511
17512		const indices = [];
17513
17514		const geometryIndex = geometry.index;
17515		const geometryPosition = geometry.attributes.position;
17516		let version = 0;
17517
17518		if (geometryIndex !== null) {
17519
17520			const array = geometryIndex.array;
17521			version = geometryIndex.version;
17522
17523			for (let i = 0, l = array.length; i < l; i += 3) {
17524
17525				const a = array[i + 0];
17526				const b = array[i + 1];
vendor: 16,321 bytes, lines 17527-18272
17527				const c = array[i + 2];
17528
17529				indices.push(a, b, b, c, c, a);
17530
17531			}
17532
17533		} else if (geometryPosition !== undefined) {
17534
17535			const array = geometryPosition.array;
17536			version = geometryPosition.version;
17537
17538			for (let i = 0, l = (array.length / 3) - 1; i < l; i += 3) {
17539
17540				const a = i + 0;
17541				const b = i + 1;
17542				const c = i + 2;
17543
17544				indices.push(a, b, b, c, c, a);
17545
17546			}
17547
17548		} else {
17549
17550			return;
17551
17552		}
17553
17554		const attribute = new (arrayNeedsUint32(indices) ? Uint32BufferAttribute : Uint16BufferAttribute)(indices, 1);
17555		attribute.version = version;
17556
17557		// Updating index buffer in VAO now. See WebGLBindingStates
17558
17559		//
17560
17561		const previousAttribute = wireframeAttributes.get(geometry);
17562
17563		if (previousAttribute) attributes.remove(previousAttribute);
17564
17565		//
17566
17567		wireframeAttributes.set(geometry, attribute);
17568
17569	}
17570
17571	function getWireframeAttribute(geometry) {
17572
17573		const currentAttribute = wireframeAttributes.get(geometry);
17574
17575		if (currentAttribute) {
17576
17577			const geometryIndex = geometry.index;
17578
17579			if (geometryIndex !== null) {
17580
17581				// if the attribute is obsolete, create a new one
17582
17583				if (currentAttribute.version < geometryIndex.version) {
17584
17585					updateWireframeAttribute(geometry);
17586
17587				}
17588
17589			}
17590
17591		} else {
17592
17593			updateWireframeAttribute(geometry);
17594
17595		}
17596
17597		return wireframeAttributes.get(geometry);
17598
17599	}
17600
17601	return {
17602
17603		get: get,
17604		update: update,
17605
17606		getWireframeAttribute: getWireframeAttribute
17607
17608	};
17609
17610}
17611
17612function WebGLIndexedBufferRenderer(gl, extensions, info, capabilities) {
17613
17614	const isWebGL2 = capabilities.isWebGL2;
17615
17616	let mode;
17617
17618	function setMode(value) {
17619
17620		mode = value;
17621
17622	}
17623
17624	let type, bytesPerElement;
17625
17626	function setIndex(value) {
17627
17628		type = value.type;
17629		bytesPerElement = value.bytesPerElement;
17630
17631	}
17632
17633	function render(start, count) {
17634
17635		gl.drawElements(mode, count, type, start * bytesPerElement);
17636
17637		info.update(count, mode, 1);
17638
17639	}
17640
17641	function renderInstances(start, count, primcount) {
17642
17643		if (primcount === 0) return;
17644
17645		let extension, methodName;
17646
17647		if (isWebGL2) {
17648
17649			extension = gl;
17650			methodName = 'drawElementsInstanced';
17651
17652		} else {
17653
17654			extension = extensions.get('ANGLE_instanced_arrays');
17655			methodName = 'drawElementsInstancedANGLE';
17656
17657			if (extension === null) {
17658
17659				console.error('THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
17660				return;
17661
17662			}
17663
17664		}
17665
17666		extension[methodName](mode, count, type, start * bytesPerElement, primcount);
17667
17668		info.update(count, mode, primcount);
17669
17670	}
17671
17672	function renderMultiDraw(starts, counts, drawCount) {
17673
17674		if (drawCount === 0) return;
17675
17676		const extension = extensions.get('WEBGL_multi_draw');
17677		if (extension === null) {
17678
17679			for (let i = 0; i < drawCount; i++) {
17680
17681				this.render(starts[i] / bytesPerElement, counts[i]);
17682
17683			}
17684
17685		} else {
17686
17687			extension.multiDrawElementsWEBGL(mode, counts, 0, type, starts, 0, drawCount);
17688
17689			let elementCount = 0;
17690			for (let i = 0; i < drawCount; i++) {
17691
17692				elementCount += counts[i];
17693
17694			}
17695
17696			info.update(elementCount, mode, 1);
17697
17698		}
17699
17700	}
17701
17702	//
17703
17704	this.setMode = setMode;
17705	this.setIndex = setIndex;
17706	this.render = render;
17707	this.renderInstances = renderInstances;
17708	this.renderMultiDraw = renderMultiDraw;
17709
17710}
17711
17712function WebGLInfo(gl) {
17713
17714	const memory = {
17715		geometries: 0,
17716		textures: 0
17717	};
17718
17719	const render = {
17720		frame: 0,
17721		calls: 0,
17722		triangles: 0,
17723		points: 0,
17724		lines: 0
17725	};
17726
17727	function update(count, mode, instanceCount) {
17728
17729		render.calls++;
17730
17731		switch (mode) {
17732
17733			case gl.TRIANGLES:
17734				render.triangles += instanceCount * (count / 3);
17735				break;
17736
17737			case gl.LINES:
17738				render.lines += instanceCount * (count / 2);
17739				break;
17740
17741			case gl.LINE_STRIP:
17742				render.lines += instanceCount * (count - 1);
17743				break;
17744
17745			case gl.LINE_LOOP:
17746				render.lines += instanceCount * count;
17747				break;
17748
17749			case gl.POINTS:
17750				render.points += instanceCount * count;
17751				break;
17752
17753			default:
17754				console.error('THREE.WebGLInfo: Unknown draw mode:', mode);
17755				break;
17756
17757		}
17758
17759	}
17760
17761	function reset() {
17762
17763		render.calls = 0;
17764		render.triangles = 0;
17765		render.points = 0;
17766		render.lines = 0;
17767
17768	}
17769
17770	return {
17771		memory: memory,
17772		render: render,
17773		programs: null,
17774		autoReset: true,
17775		reset: reset,
17776		update: update
17777	};
17778
17779}
17780
17781function numericalSort(a, b) {
17782
17783	return a[0] - b[0];
17784
17785}
17786
17787function absNumericalSort(a, b) {
17788
17789	return Math.abs(b[1]) - Math.abs(a[1]);
17790
17791}
17792
17793function WebGLMorphtargets(gl, capabilities, textures) {
17794
17795	const influencesList = {};
17796	const morphInfluences = new Float32Array(8);
17797	const morphTextures = new WeakMap();
17798	const morph = new Vector4();
17799
17800	const workInfluences = [];
17801
17802	for (let i = 0; i < 8; i++) {
17803
17804		workInfluences[i] = [i, 0];
17805
17806	}
17807
17808	function update(object, geometry, program) {
17809
17810		const objectInfluences = object.morphTargetInfluences;
17811
17812		if (capabilities.isWebGL2 === true) {
17813
17814			// instead of using attributes, the WebGL 2 code path encodes morph targets
17815			// into an array of data textures. Each layer represents a single morph target.
17816
17817			const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
17818			const morphTargetsCount = (morphAttribute !== undefined) ? morphAttribute.length : 0;
17819
17820			let entry = morphTextures.get(geometry);
17821
17822			if (entry === undefined || entry.count !== morphTargetsCount) {
17823
17824				if (entry !== undefined) entry.texture.dispose();
17825
17826				const hasMorphPosition = geometry.morphAttributes.position !== undefined;
17827				const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
17828				const hasMorphColors = geometry.morphAttributes.color !== undefined;
17829
17830				const morphTargets = geometry.morphAttributes.position || [];
17831				const morphNormals = geometry.morphAttributes.normal || [];
17832				const morphColors = geometry.morphAttributes.color || [];
17833
17834				let vertexDataCount = 0;
17835
17836				if (hasMorphPosition === true) vertexDataCount = 1;
17837				if (hasMorphNormals === true) vertexDataCount = 2;
17838				if (hasMorphColors === true) vertexDataCount = 3;
17839
17840				let width = geometry.attributes.position.count * vertexDataCount;
17841				let height = 1;
17842
17843				if (width > capabilities.maxTextureSize) {
17844
17845					height = Math.ceil(width / capabilities.maxTextureSize);
17846					width = capabilities.maxTextureSize;
17847
17848				}
17849
17850				const buffer = new Float32Array(width * height * 4 * morphTargetsCount);
17851
17852				const texture = new DataArrayTexture(buffer, width, height, morphTargetsCount);
17853				texture.type = FloatType;
17854				texture.needsUpdate = true;
17855
17856				// fill buffer
17857
17858				const vertexDataStride = vertexDataCount * 4;
17859
17860				for (let i = 0; i < morphTargetsCount; i++) {
17861
17862					const morphTarget = morphTargets[i];
17863					const morphNormal = morphNormals[i];
17864					const morphColor = morphColors[i];
17865
17866					const offset = width * height * 4 * i;
17867
17868					for (let j = 0; j < morphTarget.count; j++) {
17869
17870						const stride = j * vertexDataStride;
17871
17872						if (hasMorphPosition === true) {
17873
17874							morph.fromBufferAttribute(morphTarget, j);
17875
17876							buffer[offset + stride + 0] = morph.x;
17877							buffer[offset + stride + 1] = morph.y;
17878							buffer[offset + stride + 2] = morph.z;
17879							buffer[offset + stride + 3] = 0;
17880
17881						}
17882
17883						if (hasMorphNormals === true) {
17884
17885							morph.fromBufferAttribute(morphNormal, j);
17886
17887							buffer[offset + stride + 4] = morph.x;
17888							buffer[offset + stride + 5] = morph.y;
17889							buffer[offset + stride + 6] = morph.z;
17890							buffer[offset + stride + 7] = 0;
17891
17892						}
17893
17894						if (hasMorphColors === true) {
17895
17896							morph.fromBufferAttribute(morphColor, j);
17897
17898							buffer[offset + stride + 8] = morph.x;
17899							buffer[offset + stride + 9] = morph.y;
17900							buffer[offset + stride + 10] = morph.z;
17901							buffer[offset + stride + 11] = (morphColor.itemSize === 4) ? morph.w : 1;
17902
17903						}
17904
17905					}
17906
17907				}
17908
17909				entry = {
17910					count: morphTargetsCount,
17911					texture: texture,
17912					size: new Vector2(width, height)
17913				};
17914
17915				morphTextures.set(geometry, entry);
17916
17917				function disposeTexture() {
17918
17919					texture.dispose();
17920
17921					morphTextures.delete(geometry);
17922
17923					geometry.removeEventListener('dispose', disposeTexture);
17924
17925				}
17926
17927				geometry.addEventListener('dispose', disposeTexture);
17928
17929			}
17930
17931			//
17932
17933			let morphInfluencesSum = 0;
17934
17935			for (let i = 0; i < objectInfluences.length; i++) {
17936
17937				morphInfluencesSum += objectInfluences[i];
17938
17939			}
17940
17941			const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
17942
17943			program.getUniforms().setValue(gl, 'morphTargetBaseInfluence', morphBaseInfluence);
17944			program.getUniforms().setValue(gl, 'morphTargetInfluences', objectInfluences);
17945
17946			program.getUniforms().setValue(gl, 'morphTargetsTexture', entry.texture, textures);
17947			program.getUniforms().setValue(gl, 'morphTargetsTextureSize', entry.size);
17948
17949
17950		} else {
17951
17952			// When object doesn't have morph target influences defined, we treat it as a 0-length array
17953			// This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
17954
17955			const length = objectInfluences === undefined ? 0 : objectInfluences.length;
17956
17957			let influences = influencesList[geometry.id];
17958
17959			if (influences === undefined || influences.length !== length) {
17960
17961				// initialise list
17962
17963				influences = [];
17964
17965				for (let i = 0; i < length; i++) {
17966
17967					influences[i] = [i, 0];
17968
17969				}
17970
17971				influencesList[geometry.id] = influences;
17972
17973			}
17974
17975			// Collect influences
17976
17977			for (let i = 0; i < length; i++) {
17978
17979				const influence = influences[i];
17980
17981				influence[0] = i;
17982				influence[1] = objectInfluences[i];
17983
17984			}
17985
17986			influences.sort(absNumericalSort);
17987
17988			for (let i = 0; i < 8; i++) {
17989
17990				if (i < length && influences[i][1]) {
17991
17992					workInfluences[i][0] = influences[i][0];
17993					workInfluences[i][1] = influences[i][1];
17994
17995				} else {
17996
17997					workInfluences[i][0] = Number.MAX_SAFE_INTEGER;
17998					workInfluences[i][1] = 0;
17999
18000				}
18001
18002			}
18003
18004			workInfluences.sort(numericalSort);
18005
18006			const morphTargets = geometry.morphAttributes.position;
18007			const morphNormals = geometry.morphAttributes.normal;
18008
18009			let morphInfluencesSum = 0;
18010
18011			for (let i = 0; i < 8; i++) {
18012
18013				const influence = workInfluences[i];
18014				const index = influence[0];
18015				const value = influence[1];
18016
18017				if (index !== Number.MAX_SAFE_INTEGER && value) {
18018
18019					if (morphTargets && geometry.getAttribute('morphTarget' + i) !== morphTargets[index]) {
18020
18021						geometry.setAttribute('morphTarget' + i, morphTargets[index]);
18022
18023					}
18024
18025					if (morphNormals && geometry.getAttribute('morphNormal' + i) !== morphNormals[index]) {
18026
18027						geometry.setAttribute('morphNormal' + i, morphNormals[index]);
18028
18029					}
18030
18031					morphInfluences[i] = value;
18032					morphInfluencesSum += value;
18033
18034				} else {
18035
18036					if (morphTargets && geometry.hasAttribute('morphTarget' + i) === true) {
18037
18038						geometry.deleteAttribute('morphTarget' + i);
18039
18040					}
18041
18042					if (morphNormals && geometry.hasAttribute('morphNormal' + i) === true) {
18043
18044						geometry.deleteAttribute('morphNormal' + i);
18045
18046					}
18047
18048					morphInfluences[i] = 0;
18049
18050				}
18051
18052			}
18053
18054			// GLSL shader uses formula baseinfluence * base + sum(target * influence)
18055			// This allows us to switch between absolute morphs and relative morphs without changing shader code
18056			// When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
18057			const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
18058
18059			program.getUniforms().setValue(gl, 'morphTargetBaseInfluence', morphBaseInfluence);
18060			program.getUniforms().setValue(gl, 'morphTargetInfluences', morphInfluences);
18061
18062		}
18063
18064	}
18065
18066	return {
18067
18068		update: update
18069
18070	};
18071
18072}
18073
18074function WebGLObjects(gl, geometries, attributes, info) {
18075
18076	let updateMap = new WeakMap();
18077
18078	function update(object) {
18079
18080		const frame = info.render.frame;
18081
18082		const geometry = object.geometry;
18083		const buffergeometry = geometries.get(object, geometry);
18084
18085		// Update once per frame
18086
18087		if (updateMap.get(buffergeometry) !== frame) {
18088
18089			geometries.update(buffergeometry);
18090
18091			updateMap.set(buffergeometry, frame);
18092
18093		}
18094
18095		if (object.isInstancedMesh) {
18096
18097			if (object.hasEventListener('dispose', onInstancedMeshDispose) === false) {
18098
18099				object.addEventListener('dispose', onInstancedMeshDispose);
18100
18101			}
18102
18103			if (updateMap.get(object) !== frame) {
18104
18105				attributes.update(object.instanceMatrix, gl.ARRAY_BUFFER);
18106
18107				if (object.instanceColor !== null) {
18108
18109					attributes.update(object.instanceColor, gl.ARRAY_BUFFER);
18110
18111				}
18112
18113				updateMap.set(object, frame);
18114
18115			}
18116
18117		}
18118
18119		if (object.isSkinnedMesh) {
18120
18121			const skeleton = object.skeleton;
18122
18123			if (updateMap.get(skeleton) !== frame) {
18124
18125				skeleton.update();
18126
18127				updateMap.set(skeleton, frame);
18128
18129			}
18130
18131		}
18132
18133		return buffergeometry;
18134
18135	}
18136
18137	function dispose() {
18138
18139		updateMap = new WeakMap();
18140
18141	}
18142
18143	function onInstancedMeshDispose(event) {
18144
18145		const instancedMesh = event.target;
18146
18147		instancedMesh.removeEventListener('dispose', onInstancedMeshDispose);
18148
18149		attributes.remove(instancedMesh.instanceMatrix);
18150
18151		if (instancedMesh.instanceColor !== null) attributes.remove(instancedMesh.instanceColor);
18152
18153	}
18154
18155	return {
18156
18157		update: update,
18158		dispose: dispose
18159
18160	};
18161
18162}
18163
18164class DepthTexture extends Texture {
18165
18166	constructor(width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format) {
18167
18168		format = format !== undefined ? format : DepthFormat;
18169
18170		if (format !== DepthFormat && format !== DepthStencilFormat) {
18171
18172			throw new Error('DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat');
18173
18174		}
18175
18176		if (type === undefined && format === DepthFormat) type = UnsignedIntType;
18177		if (type === undefined && format === DepthStencilFormat) type = UnsignedInt248Type;
18178
18179		super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
18180
18181		this.isDepthTexture = true;
18182
18183		this.image = { width: width, height: height };
18184
18185		this.magFilter = magFilter !== undefined ? magFilter : NearestFilter;
18186		this.minFilter = minFilter !== undefined ? minFilter : NearestFilter;
18187
18188		this.flipY = false;
18189		this.generateMipmaps = false;
18190
18191		this.compareFunction = null;
18192
18193	}
18194
18195
18196	copy(source) {
18197
18198		super.copy(source);
18199
18200		this.compareFunction = source.compareFunction;
18201
18202		return this;
18203
18204	}
18205
18206	toJSON(meta) {
18207
18208		const data = super.toJSON(meta);
18209
18210		if (this.compareFunction !== null) data.compareFunction = this.compareFunction;
18211
18212		return data;
18213
18214	}
18215
18216}
18217
18218/**
18219 * Uniforms of a program.
18220 * Those form a tree structure with a special top-level container for the root,
18221 * which you get by calling 'new WebGLUniforms( gl, program )'.
18222 *
18223 *
18224 * Properties of inner nodes including the top-level container:
18225 *
18226 * .seq - array of nested uniforms
18227 * .map - nested uniforms by name
18228 *
18229 *
18230 * Methods of all nodes except the top-level container:
18231 *
18232 * .setValue( gl, value, [textures] )
18233 *
18234 * 		uploads a uniform value(s)
18235 *  	the 'textures' parameter is needed for sampler uniforms
18236 *
18237 *
18238 * Static methods of the top-level container (textures factorizations):
18239 *
18240 * .upload( gl, seq, values, textures )
18241 *
18242 * 		sets uniforms in 'seq' to 'values[id].value'
18243 *
18244 * .seqWithValue( seq, values ) : filteredSeq
18245 *
18246 * 		filters 'seq' entries with corresponding entry in values
18247 *
18248 *
18249 * Methods of the top-level container (textures factorizations):
18250 *
18251 * .setValue( gl, name, value, textures )
18252 *
18253 * 		sets uniform with  name 'name' to 'value'
18254 *
18255 * .setOptional( gl, obj, prop )
18256 *
18257 * 		like .set for an optional property of the object
18258 *
18259 */
18260
18261
18262const emptyTexture = /*@__PURE__*/ new Texture();
18263
18264const emptyShadowTexture = /*@__PURE__*/ new DepthTexture(1, 1);
18265emptyShadowTexture.compareFunction = LessEqualCompare;
18266
18267const emptyArrayTexture = /*@__PURE__*/ new DataArrayTexture();
18268const empty3dTexture = /*@__PURE__*/ new Data3DTexture();
18269const emptyCubeTexture = /*@__PURE__*/ new CubeTexture();
18270
18271// --- Utilities ---
18272
vendor: 1,384 bytes, lines 18273-18353
18273// Array Caches (provide typed arrays for temporary by size)
18274
18275const arrayCacheF32 = [];
18276const arrayCacheI32 = [];
18277
18278// Float32Array caches used for uploading Matrix uniforms
18279
18280const mat4array = new Float32Array(16);
18281const mat3array = new Float32Array(9);
18282const mat2array = new Float32Array(4);
18283
18284// Flattening for arrays of vectors and matrices
18285
18286function flatten(array, nBlocks, blockSize) {
18287
18288	const firstElem = array[0];
18289
18290	if (firstElem <= 0 || firstElem > 0) return array;
18291	// unoptimized: ! isNaN( firstElem )
18292	// see http://jacksondunstan.com/articles/983
18293
18294	const n = nBlocks * blockSize;
18295	let r = arrayCacheF32[n];
18296
18297	if (r === undefined) {
18298
18299		r = new Float32Array(n);
18300		arrayCacheF32[n] = r;
18301
18302	}
18303
18304	if (nBlocks !== 0) {
18305
18306		firstElem.toArray(r, 0);
18307
18308		for (let i = 1, offset = 0; i !== nBlocks; ++i) {
18309
18310			offset += blockSize;
18311			array[i].toArray(r, offset);
18312
18313		}
18314
18315	}
18316
18317	return r;
18318
18319}
18320
18321function arraysEqual(a, b) {
18322
18323	if (a.length !== b.length) return false;
18324
18325	for (let i = 0, l = a.length; i < l; i++) {
18326
18327		if (a[i] !== b[i]) return false;
18328
18329	}
18330
18331	return true;
18332
18333}
18334
18335function copyArray(a, b) {
18336
18337	for (let i = 0, l = b.length; i < l; i++) {
18338
18339		a[i] = b[i];
18340
18341	}
18342
18343}
18344
18345// Texture unit allocation
18346
18347function allocTexUnits(textures, n) {
18348
18349	let r = arrayCacheI32[n];
18350
18351	if (r === undefined) {
18352
18353		r = new Int32Array(n);
vendor: 6,498 bytes, lines 18354-18783
18354		arrayCacheI32[n] = r;
18355
18356	}
18357
18358	for (let i = 0; i !== n; ++i) {
18359
18360		r[i] = textures.allocateTextureUnit();
18361
18362	}
18363
18364	return r;
18365
18366}
18367
18368// --- Setters ---
18369
18370// Note: Defining these methods externally, because they come in a bunch
18371// and this way their names minify.
18372
18373// Single scalar
18374
18375function setValueV1f(gl, v) {
18376
18377	const cache = this.cache;
18378
18379	if (cache[0] === v) return;
18380
18381	gl.uniform1f(this.addr, v);
18382
18383	cache[0] = v;
18384
18385}
18386
18387// Single float vector (from flat array or THREE.VectorN)
18388
18389function setValueV2f(gl, v) {
18390
18391	const cache = this.cache;
18392
18393	if (v.x !== undefined) {
18394
18395		if (cache[0] !== v.x || cache[1] !== v.y) {
18396
18397			gl.uniform2f(this.addr, v.x, v.y);
18398
18399			cache[0] = v.x;
18400			cache[1] = v.y;
18401
18402		}
18403
18404	} else {
18405
18406		if (arraysEqual(cache, v)) return;
18407
18408		gl.uniform2fv(this.addr, v);
18409
18410		copyArray(cache, v);
18411
18412	}
18413
18414}
18415
18416function setValueV3f(gl, v) {
18417
18418	const cache = this.cache;
18419
18420	if (v.x !== undefined) {
18421
18422		if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z) {
18423
18424			gl.uniform3f(this.addr, v.x, v.y, v.z);
18425
18426			cache[0] = v.x;
18427			cache[1] = v.y;
18428			cache[2] = v.z;
18429
18430		}
18431
18432	} else if (v.r !== undefined) {
18433
18434		if (cache[0] !== v.r || cache[1] !== v.g || cache[2] !== v.b) {
18435
18436			gl.uniform3f(this.addr, v.r, v.g, v.b);
18437
18438			cache[0] = v.r;
18439			cache[1] = v.g;
18440			cache[2] = v.b;
18441
18442		}
18443
18444	} else {
18445
18446		if (arraysEqual(cache, v)) return;
18447
18448		gl.uniform3fv(this.addr, v);
18449
18450		copyArray(cache, v);
18451
18452	}
18453
18454}
18455
18456function setValueV4f(gl, v) {
18457
18458	const cache = this.cache;
18459
18460	if (v.x !== undefined) {
18461
18462		if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z || cache[3] !== v.w) {
18463
18464			gl.uniform4f(this.addr, v.x, v.y, v.z, v.w);
18465
18466			cache[0] = v.x;
18467			cache[1] = v.y;
18468			cache[2] = v.z;
18469			cache[3] = v.w;
18470
18471		}
18472
18473	} else {
18474
18475		if (arraysEqual(cache, v)) return;
18476
18477		gl.uniform4fv(this.addr, v);
18478
18479		copyArray(cache, v);
18480
18481	}
18482
18483}
18484
18485// Single matrix (from flat array or THREE.MatrixN)
18486
18487function setValueM2(gl, v) {
18488
18489	const cache = this.cache;
18490	const elements = v.elements;
18491
18492	if (elements === undefined) {
18493
18494		if (arraysEqual(cache, v)) return;
18495
18496		gl.uniformMatrix2fv(this.addr, false, v);
18497
18498		copyArray(cache, v);
18499
18500	} else {
18501
18502		if (arraysEqual(cache, elements)) return;
18503
18504		mat2array.set(elements);
18505
18506		gl.uniformMatrix2fv(this.addr, false, mat2array);
18507
18508		copyArray(cache, elements);
18509
18510	}
18511
18512}
18513
18514function setValueM3(gl, v) {
18515
18516	const cache = this.cache;
18517	const elements = v.elements;
18518
18519	if (elements === undefined) {
18520
18521		if (arraysEqual(cache, v)) return;
18522
18523		gl.uniformMatrix3fv(this.addr, false, v);
18524
18525		copyArray(cache, v);
18526
18527	} else {
18528
18529		if (arraysEqual(cache, elements)) return;
18530
18531		mat3array.set(elements);
18532
18533		gl.uniformMatrix3fv(this.addr, false, mat3array);
18534
18535		copyArray(cache, elements);
18536
18537	}
18538
18539}
18540
18541function setValueM4(gl, v) {
18542
18543	const cache = this.cache;
18544	const elements = v.elements;
18545
18546	if (elements === undefined) {
18547
18548		if (arraysEqual(cache, v)) return;
18549
18550		gl.uniformMatrix4fv(this.addr, false, v);
18551
18552		copyArray(cache, v);
18553
18554	} else {
18555
18556		if (arraysEqual(cache, elements)) return;
18557
18558		mat4array.set(elements);
18559
18560		gl.uniformMatrix4fv(this.addr, false, mat4array);
18561
18562		copyArray(cache, elements);
18563
18564	}
18565
18566}
18567
18568// Single integer / boolean
18569
18570function setValueV1i(gl, v) {
18571
18572	const cache = this.cache;
18573
18574	if (cache[0] === v) return;
18575
18576	gl.uniform1i(this.addr, v);
18577
18578	cache[0] = v;
18579
18580}
18581
18582// Single integer / boolean vector (from flat array or THREE.VectorN)
18583
18584function setValueV2i(gl, v) {
18585
18586	const cache = this.cache;
18587
18588	if (v.x !== undefined) {
18589
18590		if (cache[0] !== v.x || cache[1] !== v.y) {
18591
18592			gl.uniform2i(this.addr, v.x, v.y);
18593
18594			cache[0] = v.x;
18595			cache[1] = v.y;
18596
18597		}
18598
18599	} else {
18600
18601		if (arraysEqual(cache, v)) return;
18602
18603		gl.uniform2iv(this.addr, v);
18604
18605		copyArray(cache, v);
18606
18607	}
18608
18609}
18610
18611function setValueV3i(gl, v) {
18612
18613	const cache = this.cache;
18614
18615	if (v.x !== undefined) {
18616
18617		if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z) {
18618
18619			gl.uniform3i(this.addr, v.x, v.y, v.z);
18620
18621			cache[0] = v.x;
18622			cache[1] = v.y;
18623			cache[2] = v.z;
18624
18625		}
18626
18627	} else {
18628
18629		if (arraysEqual(cache, v)) return;
18630
18631		gl.uniform3iv(this.addr, v);
18632
18633		copyArray(cache, v);
18634
18635	}
18636
18637}
18638
18639function setValueV4i(gl, v) {
18640
18641	const cache = this.cache;
18642
18643	if (v.x !== undefined) {
18644
18645		if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z || cache[3] !== v.w) {
18646
18647			gl.uniform4i(this.addr, v.x, v.y, v.z, v.w);
18648
18649			cache[0] = v.x;
18650			cache[1] = v.y;
18651			cache[2] = v.z;
18652			cache[3] = v.w;
18653
18654		}
18655
18656	} else {
18657
18658		if (arraysEqual(cache, v)) return;
18659
18660		gl.uniform4iv(this.addr, v);
18661
18662		copyArray(cache, v);
18663
18664	}
18665
18666}
18667
18668// Single unsigned integer
18669
18670function setValueV1ui(gl, v) {
18671
18672	const cache = this.cache;
18673
18674	if (cache[0] === v) return;
18675
18676	gl.uniform1ui(this.addr, v);
18677
18678	cache[0] = v;
18679
18680}
18681
18682// Single unsigned integer vector (from flat array or THREE.VectorN)
18683
18684function setValueV2ui(gl, v) {
18685
18686	const cache = this.cache;
18687
18688	if (v.x !== undefined) {
18689
18690		if (cache[0] !== v.x || cache[1] !== v.y) {
18691
18692			gl.uniform2ui(this.addr, v.x, v.y);
18693
18694			cache[0] = v.x;
18695			cache[1] = v.y;
18696
18697		}
18698
18699	} else {
18700
18701		if (arraysEqual(cache, v)) return;
18702
18703		gl.uniform2uiv(this.addr, v);
18704
18705		copyArray(cache, v);
18706
18707	}
18708
18709}
18710
18711function setValueV3ui(gl, v) {
18712
18713	const cache = this.cache;
18714
18715	if (v.x !== undefined) {
18716
18717		if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z) {
18718
18719			gl.uniform3ui(this.addr, v.x, v.y, v.z);
18720
18721			cache[0] = v.x;
18722			cache[1] = v.y;
18723			cache[2] = v.z;
18724
18725		}
18726
18727	} else {
18728
18729		if (arraysEqual(cache, v)) return;
18730
18731		gl.uniform3uiv(this.addr, v);
18732
18733		copyArray(cache, v);
18734
18735	}
18736
18737}
18738
18739function setValueV4ui(gl, v) {
18740
18741	const cache = this.cache;
18742
18743	if (v.x !== undefined) {
18744
18745		if (cache[0] !== v.x || cache[1] !== v.y || cache[2] !== v.z || cache[3] !== v.w) {
18746
18747			gl.uniform4ui(this.addr, v.x, v.y, v.z, v.w);
18748
18749			cache[0] = v.x;
18750			cache[1] = v.y;
18751			cache[2] = v.z;
18752			cache[3] = v.w;
18753
18754		}
18755
18756	} else {
18757
18758		if (arraysEqual(cache, v)) return;
18759
18760		gl.uniform4uiv(this.addr, v);
18761
18762		copyArray(cache, v);
18763
18764	}
18765
18766}
18767
18768
18769// Single texture (2D / Cube)
18770
18771function setValueT1(gl, v, textures) {
18772
18773	const cache = this.cache;
18774	const unit = textures.allocateTextureUnit();
18775
18776	if (cache[0] !== unit) {
18777
18778		gl.uniform1i(this.addr, unit);
18779		cache[0] = unit;
18780
18781	}
18782
18783	const emptyTexture2D = (this.type === gl.SAMPLER_2D_SHADOW) ? emptySh
vendor: 7,261 bytes, lines 18783-19146
18783adowTexture : emptyTexture;
18784
18785	textures.setTexture2D(v || emptyTexture2D, unit);
18786
18787}
18788
18789function setValueT3D1(gl, v, textures) {
18790
18791	const cache = this.cache;
18792	const unit = textures.allocateTextureUnit();
18793
18794	if (cache[0] !== unit) {
18795
18796		gl.uniform1i(this.addr, unit);
18797		cache[0] = unit;
18798
18799	}
18800
18801	textures.setTexture3D(v || empty3dTexture, unit);
18802
18803}
18804
18805function setValueT6(gl, v, textures) {
18806
18807	const cache = this.cache;
18808	const unit = textures.allocateTextureUnit();
18809
18810	if (cache[0] !== unit) {
18811
18812		gl.uniform1i(this.addr, unit);
18813		cache[0] = unit;
18814
18815	}
18816
18817	textures.setTextureCube(v || emptyCubeTexture, unit);
18818
18819}
18820
18821function setValueT2DArray1(gl, v, textures) {
18822
18823	const cache = this.cache;
18824	const unit = textures.allocateTextureUnit();
18825
18826	if (cache[0] !== unit) {
18827
18828		gl.uniform1i(this.addr, unit);
18829		cache[0] = unit;
18830
18831	}
18832
18833	textures.setTexture2DArray(v || emptyArrayTexture, unit);
18834
18835}
18836
18837// Helper to pick the right setter for the singular case
18838
18839function getSingularSetter(type) {
18840
18841	switch (type) {
18842
18843		case 0x1406: return setValueV1f; // FLOAT
18844		case 0x8b50: return setValueV2f; // _VEC2
18845		case 0x8b51: return setValueV3f; // _VEC3
18846		case 0x8b52: return setValueV4f; // _VEC4
18847
18848		case 0x8b5a: return setValueM2; // _MAT2
18849		case 0x8b5b: return setValueM3; // _MAT3
18850		case 0x8b5c: return setValueM4; // _MAT4
18851
18852		case 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL
18853		case 0x8b53: case 0x8b57: return setValueV2i; // _VEC2
18854		case 0x8b54: case 0x8b58: return setValueV3i; // _VEC3
18855		case 0x8b55: case 0x8b59: return setValueV4i; // _VEC4
18856
18857		case 0x1405: return setValueV1ui; // UINT
18858		case 0x8dc6: return setValueV2ui; // _VEC2
18859		case 0x8dc7: return setValueV3ui; // _VEC3
18860		case 0x8dc8: return setValueV4ui; // _VEC4
18861
18862		case 0x8b5e: // SAMPLER_2D
18863		case 0x8d66: // SAMPLER_EXTERNAL_OES
18864		case 0x8dca: // INT_SAMPLER_2D
18865		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
18866		case 0x8b62: // SAMPLER_2D_SHADOW
18867			return setValueT1;
18868
18869		case 0x8b5f: // SAMPLER_3D
18870		case 0x8dcb: // INT_SAMPLER_3D
18871		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
18872			return setValueT3D1;
18873
18874		case 0x8b60: // SAMPLER_CUBE
18875		case 0x8dcc: // INT_SAMPLER_CUBE
18876		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
18877		case 0x8dc5: // SAMPLER_CUBE_SHADOW
18878			return setValueT6;
18879
18880		case 0x8dc1: // SAMPLER_2D_ARRAY
18881		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
18882		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
18883		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
18884			return setValueT2DArray1;
18885
18886	}
18887
18888}
18889
18890
18891// Array of scalars
18892
18893function setValueV1fArray(gl, v) {
18894
18895	gl.uniform1fv(this.addr, v);
18896
18897}
18898
18899// Array of vectors (from flat array or array of THREE.VectorN)
18900
18901function setValueV2fArray(gl, v) {
18902
18903	const data = flatten(v, this.size, 2);
18904
18905	gl.uniform2fv(this.addr, data);
18906
18907}
18908
18909function setValueV3fArray(gl, v) {
18910
18911	const data = flatten(v, this.size, 3);
18912
18913	gl.uniform3fv(this.addr, data);
18914
18915}
18916
18917function setValueV4fArray(gl, v) {
18918
18919	const data = flatten(v, this.size, 4);
18920
18921	gl.uniform4fv(this.addr, data);
18922
18923}
18924
18925// Array of matrices (from flat array or array of THREE.MatrixN)
18926
18927function setValueM2Array(gl, v) {
18928
18929	const data = flatten(v, this.size, 4);
18930
18931	gl.uniformMatrix2fv(this.addr, false, data);
18932
18933}
18934
18935function setValueM3Array(gl, v) {
18936
18937	const data = flatten(v, this.size, 9);
18938
18939	gl.uniformMatrix3fv(this.addr, false, data);
18940
18941}
18942
18943function setValueM4Array(gl, v) {
18944
18945	const data = flatten(v, this.size, 16);
18946
18947	gl.uniformMatrix4fv(this.addr, false, data);
18948
18949}
18950
18951// Array of integer / boolean
18952
18953function setValueV1iArray(gl, v) {
18954
18955	gl.uniform1iv(this.addr, v);
18956
18957}
18958
18959// Array of integer / boolean vectors (from flat array)
18960
18961function setValueV2iArray(gl, v) {
18962
18963	gl.uniform2iv(this.addr, v);
18964
18965}
18966
18967function setValueV3iArray(gl, v) {
18968
18969	gl.uniform3iv(this.addr, v);
18970
18971}
18972
18973function setValueV4iArray(gl, v) {
18974
18975	gl.uniform4iv(this.addr, v);
18976
18977}
18978
18979// Array of unsigned integer
18980
18981function setValueV1uiArray(gl, v) {
18982
18983	gl.uniform1uiv(this.addr, v);
18984
18985}
18986
18987// Array of unsigned integer vectors (from flat array)
18988
18989function setValueV2uiArray(gl, v) {
18990
18991	gl.uniform2uiv(this.addr, v);
18992
18993}
18994
18995function setValueV3uiArray(gl, v) {
18996
18997	gl.uniform3uiv(this.addr, v);
18998
18999}
19000
19001function setValueV4uiArray(gl, v) {
19002
19003	gl.uniform4uiv(this.addr, v);
19004
19005}
19006
19007
19008// Array of textures (2D / 3D / Cube / 2DArray)
19009
19010function setValueT1Array(gl, v, textures) {
19011
19012	const cache = this.cache;
19013
19014	const n = v.length;
19015
19016	const units = allocTexUnits(textures, n);
19017
19018	if (!arraysEqual(cache, units)) {
19019
19020		gl.uniform1iv(this.addr, units);
19021
19022		copyArray(cache, units);
19023
19024	}
19025
19026	for (let i = 0; i !== n; ++i) {
19027
19028		textures.setTexture2D(v[i] || emptyTexture, units[i]);
19029
19030	}
19031
19032}
19033
19034function setValueT3DArray(gl, v, textures) {
19035
19036	const cache = this.cache;
19037
19038	const n = v.length;
19039
19040	const units = allocTexUnits(textures, n);
19041
19042	if (!arraysEqual(cache, units)) {
19043
19044		gl.uniform1iv(this.addr, units);
19045
19046		copyArray(cache, units);
19047
19048	}
19049
19050	for (let i = 0; i !== n; ++i) {
19051
19052		textures.setTexture3D(v[i] || empty3dTexture, units[i]);
19053
19054	}
19055
19056}
19057
19058function setValueT6Array(gl, v, textures) {
19059
19060	const cache = this.cache;
19061
19062	const n = v.length;
19063
19064	const units = allocTexUnits(textures, n);
19065
19066	if (!arraysEqual(cache, units)) {
19067
19068		gl.uniform1iv(this.addr, units);
19069
19070		copyArray(cache, units);
19071
19072	}
19073
19074	for (let i = 0; i !== n; ++i) {
19075
19076		textures.setTextureCube(v[i] || emptyCubeTexture, units[i]);
19077
19078	}
19079
19080}
19081
19082function setValueT2DArrayArray(gl, v, textures) {
19083
19084	const cache = this.cache;
19085
19086	const n = v.length;
19087
19088	const units = allocTexUnits(textures, n);
19089
19090	if (!arraysEqual(cache, units)) {
19091
19092		gl.uniform1iv(this.addr, units);
19093
19094		copyArray(cache, units);
19095
19096	}
19097
19098	for (let i = 0; i !== n; ++i) {
19099
19100		textures.setTexture2DArray(v[i] || emptyArrayTexture, units[i]);
19101
19102	}
19103
19104}
19105
19106
19107// Helper to pick the right setter for a pure (bottom-level) array
19108
19109function getPureArraySetter(type) {
19110
19111	switch (type) {
19112
19113		case 0x1406: return setValueV1fArray; // FLOAT
19114		case 0x8b50: return setValueV2fArray; // _VEC2
19115		case 0x8b51: return setValueV3fArray; // _VEC3
19116		case 0x8b52: return setValueV4fArray; // _VEC4
19117
19118		case 0x8b5a: return setValueM2Array; // _MAT2
19119		case 0x8b5b: return setValueM3Array; // _MAT3
19120		case 0x8b5c: return setValueM4Array; // _MAT4
19121
19122		case 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL
19123		case 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2
19124		case 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3
19125		case 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4
19126
19127		case 0x1405: return setValueV1uiArray; // UINT
19128		case 0x8dc6: return setValueV2uiArray; // _VEC2
19129		case 0x8dc7: return setValueV3uiArray; // _VEC3
19130		case 0x8dc8: return setValueV4uiArray; // _VEC4
19131
19132		case 0x8b5e: // SAMPLER_2D
19133		case 0x8d66: // SAMPLER_EXTERNAL_OES
19134		case 0x8dca: // INT_SAMPLER_2D
19135		case 0x8dd2: // UNSIGNED_INT_SAMPLER_2D
19136		case 0x8b62: // SAMPLER_2D_SHADOW
19137			return setValueT1Array;
19138
19139		case 0x8b5f: // SAMPLER_3D
19140		case 0x8dcb: // INT_SAMPLER_3D
19141		case 0x8dd3: // UNSIGNED_INT_SAMPLER_3D
19142			return setValueT3DArray;
19143
19144		case 0x8b60: // SAMPLER_CUBE
19145		case 0x8dcc: // INT_SAMPLER_CUBE
19146		case 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE
vendor: 59,264 bytes, lines 19147-21260
19147		case 0x8dc5: // SAMPLER_CUBE_SHADOW
19148			return setValueT6Array;
19149
19150		case 0x8dc1: // SAMPLER_2D_ARRAY
19151		case 0x8dcf: // INT_SAMPLER_2D_ARRAY
19152		case 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY
19153		case 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW
19154			return setValueT2DArrayArray;
19155
19156	}
19157
19158}
19159
19160// --- Uniform Classes ---
19161
19162class SingleUniform {
19163
19164	constructor(id, activeInfo, addr) {
19165
19166		this.id = id;
19167		this.addr = addr;
19168		this.cache = [];
19169		this.type = activeInfo.type;
19170		this.setValue = getSingularSetter(activeInfo.type);
19171
19172		// this.path = activeInfo.name; // DEBUG
19173
19174	}
19175
19176}
19177
19178class PureArrayUniform {
19179
19180	constructor(id, activeInfo, addr) {
19181
19182		this.id = id;
19183		this.addr = addr;
19184		this.cache = [];
19185		this.type = activeInfo.type;
19186		this.size = activeInfo.size;
19187		this.setValue = getPureArraySetter(activeInfo.type);
19188
19189		// this.path = activeInfo.name; // DEBUG
19190
19191	}
19192
19193}
19194
19195class StructuredUniform {
19196
19197	constructor(id) {
19198
19199		this.id = id;
19200
19201		this.seq = [];
19202		this.map = {};
19203
19204	}
19205
19206	setValue(gl, value, textures) {
19207
19208		const seq = this.seq;
19209
19210		for (let i = 0, n = seq.length; i !== n; ++i) {
19211
19212			const u = seq[i];
19213			u.setValue(gl, value[u.id], textures);
19214
19215		}
19216
19217	}
19218
19219}
19220
19221// --- Top-level ---
19222
19223// Parser - builds up the property tree from the path strings
19224
19225const RePathPart = /(\w+)(\])?(\[|\.)?/g;
19226
19227// extracts
19228// 	- the identifier (member name or array index)
19229//  - followed by an optional right bracket (found when array index)
19230//  - followed by an optional left bracket or dot (type of subscript)
19231//
19232// Note: These portions can be read in a non-overlapping fashion and
19233// allow straightforward parsing of the hierarchy that WebGL encodes
19234// in the uniform names.
19235
19236function addUniform(container, uniformObject) {
19237
19238	container.seq.push(uniformObject);
19239	container.map[uniformObject.id] = uniformObject;
19240
19241}
19242
19243function parseUniform(activeInfo, addr, container) {
19244
19245	const path = activeInfo.name,
19246		pathLength = path.length;
19247
19248	// reset RegExp object, because of the early exit of a previous run
19249	RePathPart.lastIndex = 0;
19250
19251	while (true) {
19252
19253		const match = RePathPart.exec(path),
19254			matchEnd = RePathPart.lastIndex;
19255
19256		let id = match[1];
19257		const idIsIndex = match[2] === ']',
19258			subscript = match[3];
19259
19260		if (idIsIndex) id = id | 0; // convert to integer
19261
19262		if (subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength) {
19263
19264			// bare name or "pure" bottom-level array "[0]" suffix
19265
19266			addUniform(container, subscript === undefined ?
19267				new SingleUniform(id, activeInfo, addr) :
19268				new PureArrayUniform(id, activeInfo, addr));
19269
19270			break;
19271
19272		} else {
19273
19274			// step into inner node / create it in case it doesn't exist
19275
19276			const map = container.map;
19277			let next = map[id];
19278
19279			if (next === undefined) {
19280
19281				next = new StructuredUniform(id);
19282				addUniform(container, next);
19283
19284			}
19285
19286			container = next;
19287
19288		}
19289
19290	}
19291
19292}
19293
19294// Root Container
19295
19296class WebGLUniforms {
19297
19298	constructor(gl, program) {
19299
19300		this.seq = [];
19301		this.map = {};
19302
19303		const n = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
19304
19305		for (let i = 0; i < n; ++i) {
19306
19307			const info = gl.getActiveUniform(program, i),
19308				addr = gl.getUniformLocation(program, info.name);
19309
19310			parseUniform(info, addr, this);
19311
19312		}
19313
19314	}
19315
19316	setValue(gl, name, value, textures) {
19317
19318		const u = this.map[name];
19319
19320		if (u !== undefined) u.setValue(gl, value, textures);
19321
19322	}
19323
19324	setOptional(gl, object, name) {
19325
19326		const v = object[name];
19327
19328		if (v !== undefined) this.setValue(gl, name, v);
19329
19330	}
19331
19332	static upload(gl, seq, values, textures) {
19333
19334		for (let i = 0, n = seq.length; i !== n; ++i) {
19335
19336			const u = seq[i],
19337				v = values[u.id];
19338
19339			if (v.needsUpdate !== false) {
19340
19341				// note: always updating when .needsUpdate is undefined
19342				u.setValue(gl, v.value, textures);
19343
19344			}
19345
19346		}
19347
19348	}
19349
19350	static seqWithValue(seq, values) {
19351
19352		const r = [];
19353
19354		for (let i = 0, n = seq.length; i !== n; ++i) {
19355
19356			const u = seq[i];
19357			if (u.id in values) r.push(u);
19358
19359		}
19360
19361		return r;
19362
19363	}
19364
19365}
19366
19367function WebGLShader(gl, type, string) {
19368
19369	const shader = gl.createShader(type);
19370
19371	gl.shaderSource(shader, string);
19372	gl.compileShader(shader);
19373
19374	return shader;
19375
19376}
19377
19378// From https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/
19379const COMPLETION_STATUS_KHR = 0x91B1;
19380
19381let programIdCount = 0;
19382
19383function handleSource(string, errorLine) {
19384
19385	const lines = string.split('\n');
19386	const lines2 = [];
19387
19388	const from = Math.max(errorLine - 6, 0);
19389	const to = Math.min(errorLine + 6, lines.length);
19390
19391	for (let i = from; i < to; i++) {
19392
19393		const line = i + 1;
19394		lines2.push(`${line === errorLine ? '>' : ' '} ${line}: ${lines[i]}`);
19395
19396	}
19397
19398	return lines2.join('\n');
19399
19400}
19401
19402function getEncodingComponents(colorSpace) {
19403
19404	const workingPrimaries = ColorManagement.getPrimaries(ColorManagement.workingColorSpace);
19405	const encodingPrimaries = ColorManagement.getPrimaries(colorSpace);
19406
19407	let gamutMapping;
19408
19409	if (workingPrimaries === encodingPrimaries) {
19410
19411		gamutMapping = '';
19412
19413	} else if (workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries) {
19414
19415		gamutMapping = 'LinearDisplayP3ToLinearSRGB';
19416
19417	} else if (workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries) {
19418
19419		gamutMapping = 'LinearSRGBToLinearDisplayP3';
19420
19421	}
19422
19423	switch (colorSpace) {
19424
19425		case LinearSRGBColorSpace:
19426		case LinearDisplayP3ColorSpace:
19427			return [gamutMapping, 'LinearTransferOETF'];
19428
19429		case SRGBColorSpace:
19430		case DisplayP3ColorSpace:
19431			return [gamutMapping, 'sRGBTransferOETF'];
19432
19433		default:
19434			console.warn('THREE.WebGLProgram: Unsupported color space:', colorSpace);
19435			return [gamutMapping, 'LinearTransferOETF'];
19436
19437	}
19438
19439}
19440
19441function getShaderErrors(gl, shader, type) {
19442
19443	const status = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
19444	const errors = gl.getShaderInfoLog(shader).trim();
19445
19446	if (status && errors === '') return '';
19447
19448	const errorMatches = /ERROR: 0:(\d+)/.exec(errors);
19449	if (errorMatches) {
19450
19451		// --enable-privileged-webgl-extension
19452		// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );
19453
19454		const errorLine = parseInt(errorMatches[1]);
19455		return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource(gl.getShaderSource(shader), errorLine);
19456
19457	} else {
19458
19459		return errors;
19460
19461	}
19462
19463}
19464
19465function getTexelEncodingFunction(functionName, colorSpace) {
19466
19467	const components = getEncodingComponents(colorSpace);
19468	return `vec4 ${functionName}( vec4 value ) { return ${components[0]}( ${components[1]}( value ) ); }`;
19469
19470}
19471
19472function getToneMappingFunction(functionName, toneMapping) {
19473
19474	let toneMappingName;
19475
19476	switch (toneMapping) {
19477
19478		case LinearToneMapping:
19479			toneMappingName = 'Linear';
19480			break;
19481
19482		case ReinhardToneMapping:
19483			toneMappingName = 'Reinhard';
19484			break;
19485
19486		case CineonToneMapping:
19487			toneMappingName = 'OptimizedCineon';
19488			break;
19489
19490		case ACESFilmicToneMapping:
19491			toneMappingName = 'ACESFilmic';
19492			break;
19493
19494		case AgXToneMapping:
19495			toneMappingName = 'AgX';
19496			break;
19497
19498		case CustomToneMapping:
19499			toneMappingName = 'Custom';
19500			break;
19501
19502		default:
19503			console.warn('THREE.WebGLProgram: Unsupported toneMapping:', toneMapping);
19504			toneMappingName = 'Linear';
19505
19506	}
19507
19508	return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';
19509
19510}
19511
19512function generateExtensions(parameters) {
19513
19514	const chunks = [
19515		(parameters.extensionDerivatives || !!parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.normalMapTangentSpace || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical') ? '#extension GL_OES_standard_derivatives : enable' : '',
19516		(parameters.extensionFragDepth || parameters.logarithmicDepthBuffer) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',
19517		(parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers) ? '#extension GL_EXT_draw_buffers : require' : '',
19518		(parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''
19519	];
19520
19521	return chunks.filter(filterEmptyLine).join('\n');
19522
19523}
19524
19525function generateVertexExtensions(parameters) {
19526
19527	const chunks = [
19528		parameters.extensionClipCullDistance ? '#extension GL_ANGLE_clip_cull_distance : require' : ''
19529	];
19530
19531	return chunks.filter(filterEmptyLine).join('\n');
19532
19533}
19534
19535function generateDefines(defines) {
19536
19537	const chunks = [];
19538
19539	for (const name in defines) {
19540
19541		const value = defines[name];
19542
19543		if (value === false) continue;
19544
19545		chunks.push('#define ' + name + ' ' + value);
19546
19547	}
19548
19549	return chunks.join('\n');
19550
19551}
19552
19553function fetchAttributeLocations(gl, program) {
19554
19555	const attributes = {};
19556
19557	const n = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
19558
19559	for (let i = 0; i < n; i++) {
19560
19561		const info = gl.getActiveAttrib(program, i);
19562		const name = info.name;
19563
19564		let locationSize = 1;
19565		if (info.type === gl.FLOAT_MAT2) locationSize = 2;
19566		if (info.type === gl.FLOAT_MAT3) locationSize = 3;
19567		if (info.type === gl.FLOAT_MAT4) locationSize = 4;
19568
19569		// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );
19570
19571		attributes[name] = {
19572			type: info.type,
19573			location: gl.getAttribLocation(program, name),
19574			locationSize: locationSize
19575		};
19576
19577	}
19578
19579	return attributes;
19580
19581}
19582
19583function filterEmptyLine(string) {
19584
19585	return string !== '';
19586
19587}
19588
19589function replaceLightNums(string, parameters) {
19590
19591	const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps;
19592
19593	return string
19594		.replace(/NUM_DIR_LIGHTS/g, parameters.numDirLights)
19595		.replace(/NUM_SPOT_LIGHTS/g, parameters.numSpotLights)
19596		.replace(/NUM_SPOT_LIGHT_MAPS/g, parameters.numSpotLightMaps)
19597		.replace(/NUM_SPOT_LIGHT_COORDS/g, numSpotLightCoords)
19598		.replace(/NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights)
19599		.replace(/NUM_POINT_LIGHTS/g, parameters.numPointLights)
19600		.replace(/NUM_HEMI_LIGHTS/g, parameters.numHemiLights)
19601		.replace(/NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows)
19602		.replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g, parameters.numSpotLightShadowsWithMaps)
19603		.replace(/NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows)
19604		.replace(/NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows);
19605
19606}
19607
19608function replaceClippingPlaneNums(string, parameters) {
19609
19610	return string
19611		.replace(/NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes)
19612		.replace(/UNION_CLIPPING_PLANES/g, (parameters.numClippingPlanes - parameters.numClipIntersection));
19613
19614}
19615
19616// Resolve Includes
19617
19618const includePattern = /^[ \t]*#include +<([\w\d./]+)>/gm;
19619
19620function resolveIncludes(string) {
19621
19622	return string.replace(includePattern, includeReplacer);
19623
19624}
19625
19626const shaderChunkMap = new Map([
19627	['encodings_fragment', 'colorspace_fragment'], // @deprecated, r154
19628	['encodings_pars_fragment', 'colorspace_pars_fragment'], // @deprecated, r154
19629	['output_fragment', 'opaque_fragment'], // @deprecated, r154
19630]);
19631
19632function includeReplacer(match, include) {
19633
19634	let string = ShaderChunk[include];
19635
19636	if (string === undefined) {
19637
19638		const newInclude = shaderChunkMap.get(include);
19639
19640		if (newInclude !== undefined) {
19641
19642			string = ShaderChunk[newInclude];
19643			console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.', include, newInclude);
19644
19645		} else {
19646
19647			throw new Error('Can not resolve #include <' + include + '>');
19648
19649		}
19650
19651	}
19652
19653	return resolveIncludes(string);
19654
19655}
19656
19657// Unroll Loops
19658
19659const 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;
19660
19661function unrollLoops(string) {
19662
19663	return string.replace(unrollLoopPattern, loopReplacer);
19664
19665}
19666
19667function loopReplacer(match, start, end, snippet) {
19668
19669	let string = '';
19670
19671	for (let i = parseInt(start); i < parseInt(end); i++) {
19672
19673		string += snippet
19674			.replace(/\[\s*i\s*\]/g, '[ ' + i + ' ]')
19675			.replace(/UNROLLED_LOOP_INDEX/g, i);
19676
19677	}
19678
19679	return string;
19680
19681}
19682
19683//
19684
19685function generatePrecision(parameters) {
19686
19687	let precisionstring = 'precision ' + parameters.precision + ' float;\nprecision ' + parameters.precision + ' int;';
19688
19689	if (parameters.precision === 'highp') {
19690
19691		precisionstring += '\n#define HIGH_PRECISION';
19692
19693	} else if (parameters.precision === 'mediump') {
19694
19695		precisionstring += '\n#define MEDIUM_PRECISION';
19696
19697	} else if (parameters.precision === 'lowp') {
19698
19699		precisionstring += '\n#define LOW_PRECISION';
19700
19701	}
19702
19703	return precisionstring;
19704
19705}
19706
19707function generateShadowMapTypeDefine(parameters) {
19708
19709	let shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
19710
19711	if (parameters.shadowMapType === PCFShadowMap) {
19712
19713		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
19714
19715	} else if (parameters.shadowMapType === PCFSoftShadowMap) {
19716
19717		shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
19718
19719	} else if (parameters.shadowMapType === VSMShadowMap) {
19720
19721		shadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';
19722
19723	}
19724
19725	return shadowMapTypeDefine;
19726
19727}
19728
19729function generateEnvMapTypeDefine(parameters) {
19730
19731	let envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
19732
19733	if (parameters.envMap) {
19734
19735		switch (parameters.envMapMode) {
19736
19737			case CubeReflectionMapping:
19738			case CubeRefractionMapping:
19739				envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
19740				break;
19741
19742			case CubeUVReflectionMapping:
19743				envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
19744				break;
19745
19746		}
19747
19748	}
19749
19750	return envMapTypeDefine;
19751
19752}
19753
19754function generateEnvMapModeDefine(parameters) {
19755
19756	let envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
19757
19758	if (parameters.envMap) {
19759
19760		switch (parameters.envMapMode) {
19761
19762			case CubeRefractionMapping:
19763
19764				envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
19765				break;
19766
19767		}
19768
19769	}
19770
19771	return envMapModeDefine;
19772
19773}
19774
19775function generateEnvMapBlendingDefine(parameters) {
19776
19777	let envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';
19778
19779	if (parameters.envMap) {
19780
19781		switch (parameters.combine) {
19782
19783			case MultiplyOperation:
19784				envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
19785				break;
19786
19787			case MixOperation:
19788				envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
19789				break;
19790
19791			case AddOperation:
19792				envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
19793				break;
19794
19795		}
19796
19797	}
19798
19799	return envMapBlendingDefine;
19800
19801}
19802
19803function generateCubeUVSize(parameters) {
19804
19805	const imageHeight = parameters.envMapCubeUVHeight;
19806
19807	if (imageHeight === null) return null;
19808
19809	const maxMip = Math.log2(imageHeight) - 2;
19810
19811	const texelHeight = 1.0 / imageHeight;
19812
19813	const texelWidth = 1.0 / (3 * Math.max(Math.pow(2, maxMip), 7 * 16));
19814
19815	return { texelWidth, texelHeight, maxMip };
19816
19817}
19818
19819function WebGLProgram(renderer, cacheKey, parameters, bindingStates) {
19820
19821	// TODO Send this event to Three.js DevTools
19822	// console.log( 'WebGLProgram', cacheKey );
19823
19824	const gl = renderer.getContext();
19825
19826	const defines = parameters.defines;
19827
19828	let vertexShader = parameters.vertexShader;
19829	let fragmentShader = parameters.fragmentShader;
19830
19831	const shadowMapTypeDefine = generateShadowMapTypeDefine(parameters);
19832	const envMapTypeDefine = generateEnvMapTypeDefine(parameters);
19833	const envMapModeDefine = generateEnvMapModeDefine(parameters);
19834	const envMapBlendingDefine = generateEnvMapBlendingDefine(parameters);
19835	const envMapCubeUVSize = generateCubeUVSize(parameters);
19836
19837	const customExtensions = parameters.isWebGL2 ? '' : generateExtensions(parameters);
19838
19839	const customVertexExtensions = generateVertexExtensions(parameters);
19840
19841	const customDefines = generateDefines(defines);
19842
19843	const program = gl.createProgram();
19844
19845	let prefixVertex, prefixFragment;
19846	let versionString = parameters.glslVersion ? '#version ' + parameters.glslVersion + '\n' : '';
19847
19848	if (parameters.isRawShaderMaterial) {
19849
19850		prefixVertex = [
19851
19852			'#define SHADER_TYPE ' + parameters.shaderType,
19853			'#define SHADER_NAME ' + parameters.shaderName,
19854
19855			customDefines
19856
19857		].filter(filterEmptyLine).join('\n');
19858
19859		if (prefixVertex.length > 0) {
19860
19861			prefixVertex += '\n';
19862
19863		}
19864
19865		prefixFragment = [
19866
19867			customExtensions,
19868
19869			'#define SHADER_TYPE ' + parameters.shaderType,
19870			'#define SHADER_NAME ' + parameters.shaderName,
19871
19872			customDefines
19873
19874		].filter(filterEmptyLine).join('\n');
19875
19876		if (prefixFragment.length > 0) {
19877
19878			prefixFragment += '\n';
19879
19880		}
19881
19882	} else {
19883
19884		prefixVertex = [
19885
19886			generatePrecision(parameters),
19887
19888			'#define SHADER_TYPE ' + parameters.shaderType,
19889			'#define SHADER_NAME ' + parameters.shaderName,
19890
19891			customDefines,
19892
19893			parameters.extensionClipCullDistance ? '#define USE_CLIP_DISTANCE' : '',
19894			parameters.batching ? '#define USE_BATCHING' : '',
19895			parameters.instancing ? '#define USE_INSTANCING' : '',
19896			parameters.instancingColor ? '#define USE_INSTANCING_COLOR' : '',
19897
19898			parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
19899			parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
19900
19901			parameters.map ? '#define USE_MAP' : '',
19902			parameters.envMap ? '#define USE_ENVMAP' : '',
19903			parameters.envMap ? '#define ' + envMapModeDefine : '',
19904			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
19905			parameters.aoMap ? '#define USE_AOMAP' : '',
19906			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
19907			parameters.normalMap ? '#define USE_NORMALMAP' : '',
19908			parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '',
19909			parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '',
19910			parameters.displacementMap ? '#define USE_DISPLACEMENTMAP' : '',
19911			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
19912
19913			parameters.anisotropy ? '#define USE_ANISOTROPY' : '',
19914			parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '',
19915
19916			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
19917			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
19918			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
19919
19920			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
19921			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
19922
19923			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
19924			parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '',
19925			parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '',
19926
19927			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
19928			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
19929			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
19930			parameters.alphaHash ? '#define USE_ALPHAHASH' : '',
19931
19932			parameters.transmission ? '#define USE_TRANSMISSION' : '',
19933			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
19934			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
19935
19936			parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '',
19937			parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '',
19938
19939			//
19940
19941			parameters.mapUv ? '#define MAP_UV ' + parameters.mapUv : '',
19942			parameters.alphaMapUv ? '#define ALPHAMAP_UV ' + parameters.alphaMapUv : '',
19943			parameters.lightMapUv ? '#define LIGHTMAP_UV ' + parameters.lightMapUv : '',
19944			parameters.aoMapUv ? '#define AOMAP_UV ' + parameters.aoMapUv : '',
19945			parameters.emissiveMapUv ? '#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv : '',
19946			parameters.bumpMapUv ? '#define BUMPMAP_UV ' + parameters.bumpMapUv : '',
19947			parameters.normalMapUv ? '#define NORMALMAP_UV ' + parameters.normalMapUv : '',
19948			parameters.displacementMapUv ? '#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv : '',
19949
19950			parameters.metalnessMapUv ? '#define METALNESSMAP_UV ' + parameters.metalnessMapUv : '',
19951			parameters.roughnessMapUv ? '#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv : '',
19952
19953			parameters.anisotropyMapUv ? '#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv : '',
19954
19955			parameters.clearcoatMapUv ? '#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv : '',
19956			parameters.clearcoatNormalMapUv ? '#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv : '',
19957			parameters.clearcoatRoughnessMapUv ? '#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv : '',
19958
19959			parameters.iridescenceMapUv ? '#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv : '',
19960			parameters.iridescenceThicknessMapUv ? '#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv : '',
19961
19962			parameters.sheenColorMapUv ? '#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv : '',
19963			parameters.sheenRoughnessMapUv ? '#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv : '',
19964
19965			parameters.specularMapUv ? '#define SPECULARMAP_UV ' + parameters.specularMapUv : '',
19966			parameters.specularColorMapUv ? '#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv : '',
19967			parameters.specularIntensityMapUv ? '#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv : '',
19968
19969			parameters.transmissionMapUv ? '#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv : '',
19970			parameters.thicknessMapUv ? '#define THICKNESSMAP_UV ' + parameters.thicknessMapUv : '',
19971
19972			//
19973
19974			parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
19975			parameters.vertexColors ? '#define USE_COLOR' : '',
19976			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
19977			parameters.vertexUv1s ? '#define USE_UV1' : '',
19978			parameters.vertexUv2s ? '#define USE_UV2' : '',
19979			parameters.vertexUv3s ? '#define USE_UV3' : '',
19980
19981			parameters.pointsUvs ? '#define USE_POINTS_UV' : '',
19982
19983			parameters.flatShading ? '#define FLAT_SHADED' : '',
19984
19985			parameters.skinning ? '#define USE_SKINNING' : '',
19986
19987			parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
19988			parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
19989			(parameters.morphColors && parameters.isWebGL2) ? '#define USE_MORPHCOLORS' : '',
19990			(parameters.morphTargetsCount > 0 && parameters.isWebGL2) ? '#define MORPHTARGETS_TEXTURE' : '',
19991			(parameters.morphTargetsCount > 0 && parameters.isWebGL2) ? '#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride : '',
19992			(parameters.morphTargetsCount > 0 && parameters.isWebGL2) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '',
19993			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
19994			parameters.flipSided ? '#define FLIP_SIDED' : '',
19995
19996			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
19997			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
19998
19999			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
20000
20001			parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
20002
20003			parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '',
20004
20005			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
20006			(parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth) ? '#define USE_LOGDEPTHBUF_EXT' : '',
20007
20008			'uniform mat4 modelMatrix;',
20009			'uniform mat4 modelViewMatrix;',
20010			'uniform mat4 projectionMatrix;',
20011			'uniform mat4 viewMatrix;',
20012			'uniform mat3 normalMatrix;',
20013			'uniform vec3 cameraPosition;',
20014			'uniform bool isOrthographic;',
20015
20016			'#ifdef USE_INSTANCING',
20017
20018			'	attribute mat4 instanceMatrix;',
20019
20020			'#endif',
20021
20022			'#ifdef USE_INSTANCING_COLOR',
20023
20024			'	attribute vec3 instanceColor;',
20025
20026			'#endif',
20027
20028			'attribute vec3 position;',
20029			'attribute vec3 normal;',
20030			'attribute vec2 uv;',
20031
20032			'#ifdef USE_UV1',
20033
20034			'	attribute vec2 uv1;',
20035
20036			'#endif',
20037
20038			'#ifdef USE_UV2',
20039
20040			'	attribute vec2 uv2;',
20041
20042			'#endif',
20043
20044			'#ifdef USE_UV3',
20045
20046			'	attribute vec2 uv3;',
20047
20048			'#endif',
20049
20050			'#ifdef USE_TANGENT',
20051
20052			'	attribute vec4 tangent;',
20053
20054			'#endif',
20055
20056			'#if defined( USE_COLOR_ALPHA )',
20057
20058			'	attribute vec4 color;',
20059
20060			'#elif defined( USE_COLOR )',
20061
20062			'	attribute vec3 color;',
20063
20064			'#endif',
20065
20066			'#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )',
20067
20068			'	attribute vec3 morphTarget0;',
20069			'	attribute vec3 morphTarget1;',
20070			'	attribute vec3 morphTarget2;',
20071			'	attribute vec3 morphTarget3;',
20072
20073			'	#ifdef USE_MORPHNORMALS',
20074
20075			'		attribute vec3 morphNormal0;',
20076			'		attribute vec3 morphNormal1;',
20077			'		attribute vec3 morphNormal2;',
20078			'		attribute vec3 morphNormal3;',
20079
20080			'	#else',
20081
20082			'		attribute vec3 morphTarget4;',
20083			'		attribute vec3 morphTarget5;',
20084			'		attribute vec3 morphTarget6;',
20085			'		attribute vec3 morphTarget7;',
20086
20087			'	#endif',
20088
20089			'#endif',
20090
20091			'#ifdef USE_SKINNING',
20092
20093			'	attribute vec4 skinIndex;',
20094			'	attribute vec4 skinWeight;',
20095
20096			'#endif',
20097
20098			'\n'
20099
20100		].filter(filterEmptyLine).join('\n');
20101
20102		prefixFragment = [
20103
20104			customExtensions,
20105
20106			generatePrecision(parameters),
20107
20108			'#define SHADER_TYPE ' + parameters.shaderType,
20109			'#define SHADER_NAME ' + parameters.shaderName,
20110
20111			customDefines,
20112
20113			parameters.useFog && parameters.fog ? '#define USE_FOG' : '',
20114			parameters.useFog && parameters.fogExp2 ? '#define FOG_EXP2' : '',
20115
20116			parameters.map ? '#define USE_MAP' : '',
20117			parameters.matcap ? '#define USE_MATCAP' : '',
20118			parameters.envMap ? '#define USE_ENVMAP' : '',
20119			parameters.envMap ? '#define ' + envMapTypeDefine : '',
20120			parameters.envMap ? '#define ' + envMapModeDefine : '',
20121			parameters.envMap ? '#define ' + envMapBlendingDefine : '',
20122			envMapCubeUVSize ? '#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth : '',
20123			envMapCubeUVSize ? '#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight : '',
20124			envMapCubeUVSize ? '#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip + '.0' : '',
20125			parameters.lightMap ? '#define USE_LIGHTMAP' : '',
20126			parameters.aoMap ? '#define USE_AOMAP' : '',
20127			parameters.bumpMap ? '#define USE_BUMPMAP' : '',
20128			parameters.normalMap ? '#define USE_NORMALMAP' : '',
20129			parameters.normalMapObjectSpace ? '#define USE_NORMALMAP_OBJECTSPACE' : '',
20130			parameters.normalMapTangentSpace ? '#define USE_NORMALMAP_TANGENTSPACE' : '',
20131			parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',
20132
20133			parameters.anisotropy ? '#define USE_ANISOTROPY' : '',
20134			parameters.anisotropyMap ? '#define USE_ANISOTROPYMAP' : '',
20135
20136			parameters.clearcoat ? '#define USE_CLEARCOAT' : '',
20137			parameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',
20138			parameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',
20139			parameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',
20140
20141			parameters.iridescence ? '#define USE_IRIDESCENCE' : '',
20142			parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '',
20143			parameters.iridescenceThicknessMap ? '#define USE_IRIDESCENCE_THICKNESSMAP' : '',
20144
20145			parameters.specularMap ? '#define USE_SPECULARMAP' : '',
20146			parameters.specularColorMap ? '#define USE_SPECULAR_COLORMAP' : '',
20147			parameters.specularIntensityMap ? '#define USE_SPECULAR_INTENSITYMAP' : '',
20148
20149			parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',
20150			parameters.metalnessMap ? '#define USE_METALNESSMAP' : '',
20151
20152			parameters.alphaMap ? '#define USE_ALPHAMAP' : '',
20153			parameters.alphaTest ? '#define USE_ALPHATEST' : '',
20154			parameters.alphaHash ? '#define USE_ALPHAHASH' : '',
20155
20156			parameters.sheen ? '#define USE_SHEEN' : '',
20157			parameters.sheenColorMap ? '#define USE_SHEEN_COLORMAP' : '',
20158			parameters.sheenRoughnessMap ? '#define USE_SHEEN_ROUGHNESSMAP' : '',
20159
20160			parameters.transmission ? '#define USE_TRANSMISSION' : '',
20161			parameters.transmissionMap ? '#define USE_TRANSMISSIONMAP' : '',
20162			parameters.thicknessMap ? '#define USE_THICKNESSMAP' : '',
20163
20164			parameters.vertexTangents && parameters.flatShading === false ? '#define USE_TANGENT' : '',
20165			parameters.vertexColors || parameters.instancingColor ? '#define USE_COLOR' : '',
20166			parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',
20167			parameters.vertexUv1s ? '#define USE_UV1' : '',
20168			parameters.vertexUv2s ? '#define USE_UV2' : '',
20169			parameters.vertexUv3s ? '#define USE_UV3' : '',
20170
20171			parameters.pointsUvs ? '#define USE_POINTS_UV' : '',
20172
20173			parameters.gradientMap ? '#define USE_GRADIENTMAP' : '',
20174
20175			parameters.flatShading ? '#define FLAT_SHADED' : '',
20176
20177			parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
20178			parameters.flipSided ? '#define FLIP_SIDED' : '',
20179
20180			parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',
20181			parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',
20182
20183			parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',
20184
20185			parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '',
20186
20187			parameters.useLegacyLights ? '#define LEGACY_LIGHTS' : '',
20188
20189			parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '',
20190
20191			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
20192			(parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth) ? '#define USE_LOGDEPTHBUF_EXT' : '',
20193
20194			'uniform mat4 viewMatrix;',
20195			'uniform vec3 cameraPosition;',
20196			'uniform bool isOrthographic;',
20197
20198			(parameters.toneMapping !== NoToneMapping) ? '#define TONE_MAPPING' : '',
20199			(parameters.toneMapping !== NoToneMapping) ? ShaderChunk['tonemapping_pars_fragment'] : '', // this code is required here because it is used by the toneMapping() function defined below
20200			(parameters.toneMapping !== NoToneMapping) ? getToneMappingFunction('toneMapping', parameters.toneMapping) : '',
20201
20202			parameters.dithering ? '#define DITHERING' : '',
20203			parameters.opaque ? '#define OPAQUE' : '',
20204
20205			ShaderChunk['colorspace_pars_fragment'], // this code is required here because it is used by the various encoding/decoding function defined below
20206			getTexelEncodingFunction('linearToOutputTexel', parameters.outputColorSpace),
20207
20208			parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',
20209
20210			'\n'
20211
20212		].filter(filterEmptyLine).join('\n');
20213
20214	}
20215
20216	vertexShader = resolveIncludes(vertexShader);
20217	vertexShader = replaceLightNums(vertexShader, parameters);
20218	vertexShader = replaceClippingPlaneNums(vertexShader, parameters);
20219
20220	fragmentShader = resolveIncludes(fragmentShader);
20221	fragmentShader = replaceLightNums(fragmentShader, parameters);
20222	fragmentShader = replaceClippingPlaneNums(fragmentShader, parameters);
20223
20224	vertexShader = unrollLoops(vertexShader);
20225	fragmentShader = unrollLoops(fragmentShader);
20226
20227	if (parameters.isWebGL2 && parameters.isRawShaderMaterial !== true) {
20228
20229		// GLSL 3.0 conversion for built-in materials and ShaderMaterial
20230
20231		versionString = '#version 300 es\n';
20232
20233		prefixVertex = [
20234			customVertexExtensions,
20235			'precision mediump sampler2DArray;',
20236			'#define attribute in',
20237			'#define varying out',
20238			'#define texture2D texture'
20239		].join('\n') + '\n' + prefixVertex;
20240
20241		prefixFragment = [
20242			'precision mediump sampler2DArray;',
20243			'#define varying in',
20244			(parameters.glslVersion === GLSL3) ? '' : 'layout(location = 0) out highp vec4 pc_fragColor;',
20245			(parameters.glslVersion === GLSL3) ? '' : '#define gl_FragColor pc_fragColor',
20246			'#define gl_FragDepthEXT gl_FragDepth',
20247			'#define texture2D texture',
20248			'#define textureCube texture',
20249			'#define texture2DProj textureProj',
20250			'#define texture2DLodEXT textureLod',
20251			'#define texture2DProjLodEXT textureProjLod',
20252			'#define textureCubeLodEXT textureLod',
20253			'#define texture2DGradEXT textureGrad',
20254			'#define texture2DProjGradEXT textureProjGrad',
20255			'#define textureCubeGradEXT textureGrad'
20256		].join('\n') + '\n' + prefixFragment;
20257
20258	}
20259
20260	const vertexGlsl = versionString + prefixVertex + vertexShader;
20261	const fragmentGlsl = versionString + prefixFragment + fragmentShader;
20262
20263	// console.log( '*VERTEX*', vertexGlsl );
20264	// console.log( '*FRAGMENT*', fragmentGlsl );
20265
20266	const glVertexShader = WebGLShader(gl, gl.VERTEX_SHADER, vertexGlsl);
20267	const glFragmentShader = WebGLShader(gl, gl.FRAGMENT_SHADER, fragmentGlsl);
20268
20269	gl.attachShader(program, glVertexShader);
20270	gl.attachShader(program, glFragmentShader);
20271
20272	// Force a particular attribute to index 0.
20273
20274	if (parameters.index0AttributeName !== undefined) {
20275
20276		gl.bindAttribLocation(program, 0, parameters.index0AttributeName);
20277
20278	} else if (parameters.morphTargets === true) {
20279
20280		// programs with morphTargets displace position out of attribute 0
20281		gl.bindAttribLocation(program, 0, 'position');
20282
20283	}
20284
20285	gl.linkProgram(program);
20286
20287	function onFirstUse(self) {
20288
20289		// check for link errors
20290		if (renderer.debug.checkShaderErrors) {
20291
20292			const programLog = gl.getProgramInfoLog(program).trim();
20293			const vertexLog = gl.getShaderInfoLog(glVertexShader).trim();
20294			const fragmentLog = gl.getShaderInfoLog(glFragmentShader).trim();
20295
20296			let runnable = true;
20297			let haveDiagnostics = true;
20298
20299			if (gl.getProgramParameter(program, gl.LINK_STATUS) === false) {
20300
20301				runnable = false;
20302
20303				if (typeof renderer.debug.onShaderError === 'function') {
20304
20305					renderer.debug.onShaderError(gl, program, glVertexShader, glFragmentShader);
20306
20307				} else {
20308
20309					// default error reporting
20310
20311					const vertexErrors = getShaderErrors(gl, glVertexShader, 'vertex');
20312					const fragmentErrors = getShaderErrors(gl, glFragmentShader, 'fragment');
20313
20314					console.error(
20315						'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' +
20316						'VALIDATE_STATUS ' + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + '\n\n' +
20317						'Program Info Log: ' + programLog + '\n' +
20318						vertexErrors + '\n' +
20319						fragmentErrors
20320					);
20321
20322				}
20323
20324			} else if (programLog !== '') {
20325
20326				console.warn('THREE.WebGLProgram: Program Info Log:', programLog);
20327
20328			} else if (vertexLog === '' || fragmentLog === '') {
20329
20330				haveDiagnostics = false;
20331
20332			}
20333
20334			if (haveDiagnostics) {
20335
20336				self.diagnostics = {
20337
20338					runnable: runnable,
20339
20340					programLog: programLog,
20341
20342					vertexShader: {
20343
20344						log: vertexLog,
20345						prefix: prefixVertex
20346
20347					},
20348
20349					fragmentShader: {
20350
20351						log: fragmentLog,
20352						prefix: prefixFragment
20353
20354					}
20355
20356				};
20357
20358			}
20359
20360		}
20361
20362		// Clean up
20363
20364		// Crashes in iOS9 and iOS10. #18402
20365		// gl.detachShader( program, glVertexShader );
20366		// gl.detachShader( program, glFragmentShader );
20367
20368		gl.deleteShader(glVertexShader);
20369		gl.deleteShader(glFragmentShader);
20370
20371		cachedUniforms = new WebGLUniforms(gl, program);
20372		cachedAttributes = fetchAttributeLocations(gl, program);
20373
20374	}
20375
20376	// set up caching for uniform locations
20377
20378	let cachedUniforms;
20379
20380	this.getUniforms = function () {
20381
20382		if (cachedUniforms === undefined) {
20383
20384			// Populates cachedUniforms and cachedAttributes
20385			onFirstUse(this);
20386
20387		}
20388
20389		return cachedUniforms;
20390
20391	};
20392
20393	// set up caching for attribute locations
20394
20395	let cachedAttributes;
20396
20397	this.getAttributes = function () {
20398
20399		if (cachedAttributes === undefined) {
20400
20401			// Populates cachedAttributes and cachedUniforms
20402			onFirstUse(this);
20403
20404		}
20405
20406		return cachedAttributes;
20407
20408	};
20409
20410	// indicate when the program is ready to be used. if the KHR_parallel_shader_compile extension isn't supported,
20411	// flag the program as ready immediately. It may cause a stall when it's first used.
20412
20413	let programReady = (parameters.rendererExtensionParallelShaderCompile === false);
20414
20415	this.isReady = function () {
20416
20417		if (programReady === false) {
20418
20419			programReady = gl.getProgramParameter(program, COMPLETION_STATUS_KHR);
20420
20421		}
20422
20423		return programReady;
20424
20425	};
20426
20427	// free resource
20428
20429	this.destroy = function () {
20430
20431		bindingStates.releaseStatesOfProgram(this);
20432
20433		gl.deleteProgram(program);
20434		this.program = undefined;
20435
20436	};
20437
20438	//
20439
20440	this.type = parameters.shaderType;
20441	this.name = parameters.shaderName;
20442	this.id = programIdCount++;
20443	this.cacheKey = cacheKey;
20444	this.usedTimes = 1;
20445	this.program = program;
20446	this.vertexShader = glVertexShader;
20447	this.fragmentShader = glFragmentShader;
20448
20449	return this;
20450
20451}
20452
20453let _id$1 = 0;
20454
20455class WebGLShaderCache {
20456
20457	constructor() {
20458
20459		this.shaderCache = new Map();
20460		this.materialCache = new Map();
20461
20462	}
20463
20464	update(material) {
20465
20466		const vertexShader = material.vertexShader;
20467		const fragmentShader = material.fragmentShader;
20468
20469		const vertexShaderStage = this._getShaderStage(vertexShader);
20470		const fragmentShaderStage = this._getShaderStage(fragmentShader);
20471
20472		const materialShaders = this._getShaderCacheForMaterial(material);
20473
20474		if (materialShaders.has(vertexShaderStage) === false) {
20475
20476			materialShaders.add(vertexShaderStage);
20477			vertexShaderStage.usedTimes++;
20478
20479		}
20480
20481		if (materialShaders.has(fragmentShaderStage) === false) {
20482
20483			materialShaders.add(fragmentShaderStage);
20484			fragmentShaderStage.usedTimes++;
20485
20486		}
20487
20488		return this;
20489
20490	}
20491
20492	remove(material) {
20493
20494		const materialShaders = this.materialCache.get(material);
20495
20496		for (const shaderStage of materialShaders) {
20497
20498			shaderStage.usedTimes--;
20499
20500			if (shaderStage.usedTimes === 0) this.shaderCache.delete(shaderStage.code);
20501
20502		}
20503
20504		this.materialCache.delete(material);
20505
20506		return this;
20507
20508	}
20509
20510	getVertexShaderID(material) {
20511
20512		return this._getShaderStage(material.vertexShader).id;
20513
20514	}
20515
20516	getFragmentShaderID(material) {
20517
20518		return this._getShaderStage(material.fragmentShader).id;
20519
20520	}
20521
20522	dispose() {
20523
20524		this.shaderCache.clear();
20525		this.materialCache.clear();
20526
20527	}
20528
20529	_getShaderCacheForMaterial(material) {
20530
20531		const cache = this.materialCache;
20532		let set = cache.get(material);
20533
20534		if (set === undefined) {
20535
20536			set = new Set();
20537			cache.set(material, set);
20538
20539		}
20540
20541		return set;
20542
20543	}
20544
20545	_getShaderStage(code) {
20546
20547		const cache = this.shaderCache;
20548		let stage = cache.get(code);
20549
20550		if (stage === undefined) {
20551
20552			stage = new WebGLShaderStage(code);
20553			cache.set(code, stage);
20554
20555		}
20556
20557		return stage;
20558
20559	}
20560
20561}
20562
20563class WebGLShaderStage {
20564
20565	constructor(code) {
20566
20567		this.id = _id$1++;
20568
20569		this.code = code;
20570		this.usedTimes = 0;
20571
20572	}
20573
20574}
20575
20576function WebGLPrograms(renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping) {
20577
20578	const _programLayers = new Layers();
20579	const _customShaders = new WebGLShaderCache();
20580	const programs = [];
20581
20582	const IS_WEBGL2 = capabilities.isWebGL2;
20583	const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
20584	const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures;
20585
20586	let precision = capabilities.precision;
20587
20588	const shaderIDs = {
20589		MeshDepthMaterial: 'depth',
20590		MeshDistanceMaterial: 'distanceRGBA',
20591		MeshNormalMaterial: 'normal',
20592		MeshBasicMaterial: 'basic',
20593		MeshLambertMaterial: 'lambert',
20594		MeshPhongMaterial: 'phong',
20595		MeshToonMaterial: 'toon',
20596		MeshStandardMaterial: 'physical',
20597		MeshPhysicalMaterial: 'physical',
20598		MeshMatcapMaterial: 'matcap',
20599		LineBasicMaterial: 'basic',
20600		LineDashedMaterial: 'dashed',
20601		PointsMaterial: 'points',
20602		ShadowMaterial: 'shadow',
20603		SpriteMaterial: 'sprite'
20604	};
20605
20606	function getChannel(value) {
20607
20608		if (value === 0) return 'uv';
20609
20610		return `uv${value}`;
20611
20612	}
20613
20614	function getParameters(material, lights, shadows, scene, object) {
20615
20616		const fog = scene.fog;
20617		const geometry = object.geometry;
20618		const environment = material.isMeshStandardMaterial ? scene.environment : null;
20619
20620		const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment);
20621		const envMapCubeUVHeight = (!!envMap) && (envMap.mapping === CubeUVReflectionMapping) ? envMap.image.height : null;
20622
20623		const shaderID = shaderIDs[material.type];
20624
20625		// heuristics to create shader parameters according to lights in the scene
20626		// (not to blow over maxLights budget)
20627
20628		if (material.precision !== null) {
20629
20630			precision = capabilities.getMaxPrecision(material.precision);
20631
20632			if (precision !== material.precision) {
20633
20634				console.warn('THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.');
20635
20636			}
20637
20638		}
20639
20640		//
20641
20642		const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
20643		const morphTargetsCount = (morphAttribute !== undefined) ? morphAttribute.length : 0;
20644
20645		let morphTextureStride = 0;
20646
20647		if (geometry.morphAttributes.position !== undefined) morphTextureStride = 1;
20648		if (geometry.morphAttributes.normal !== undefined) morphTextureStride = 2;
20649		if (geometry.morphAttributes.color !== undefined) morphTextureStride = 3;
20650
20651		//
20652
20653		let vertexShader, fragmentShader;
20654		let customVertexShaderID, customFragmentShaderID;
20655
20656		if (shaderID) {
20657
20658			const shader = ShaderLib[shaderID];
20659
20660			vertexShader = shader.vertexShader;
20661			fragmentShader = shader.fragmentShader;
20662
20663		} else {
20664
20665			vertexShader = material.vertexShader;
20666			fragmentShader = material.fragmentShader;
20667
20668			_customShaders.update(material);
20669
20670			customVertexShaderID = _customShaders.getVertexShaderID(material);
20671			customFragmentShaderID = _customShaders.getFragmentShaderID(material);
20672
20673		}
20674
20675		const currentRenderTarget = renderer.getRenderTarget();
20676
20677		const IS_INSTANCEDMESH = object.isInstancedMesh === true;
20678		const IS_BATCHEDMESH = object.isBatchedMesh === true;
20679
20680		const HAS_MAP = !!material.map;
20681		const HAS_MATCAP = !!material.matcap;
20682		const HAS_ENVMAP = !!envMap;
20683		const HAS_AOMAP = !!material.aoMap;
20684		const HAS_LIGHTMAP = !!material.lightMap;
20685		const HAS_BUMPMAP = !!material.bumpMap;
20686		const HAS_NORMALMAP = !!material.normalMap;
20687		const HAS_DISPLACEMENTMAP = !!material.displacementMap;
20688		const HAS_EMISSIVEMAP = !!material.emissiveMap;
20689
20690		const HAS_METALNESSMAP = !!material.metalnessMap;
20691		const HAS_ROUGHNESSMAP = !!material.roughnessMap;
20692
20693		const HAS_ANISOTROPY = material.anisotropy > 0;
20694		const HAS_CLEARCOAT = material.clearcoat > 0;
20695		const HAS_IRIDESCENCE = material.iridescence > 0;
20696		const HAS_SHEEN = material.sheen > 0;
20697		const HAS_TRANSMISSION = material.transmission > 0;
20698
20699		const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !!material.anisotropyMap;
20700
20701		const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !!material.clearcoatMap;
20702		const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !!material.clearcoatNormalMap;
20703		const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !!material.clearcoatRoughnessMap;
20704
20705		const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !!material.iridescenceMap;
20706		const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !!material.iridescenceThicknessMap;
20707
20708		const HAS_SHEEN_COLORMAP = HAS_SHEEN && !!material.sheenColorMap;
20709		const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !!material.sheenRoughnessMap;
20710
20711		const HAS_SPECULARMAP = !!material.specularMap;
20712		const HAS_SPECULAR_COLORMAP = !!material.specularColorMap;
20713		const HAS_SPECULAR_INTENSITYMAP = !!material.specularIntensityMap;
20714
20715		const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !!material.transmissionMap;
20716		const HAS_THICKNESSMAP = HAS_TRANSMISSION && !!material.thicknessMap;
20717
20718		const HAS_GRADIENTMAP = !!material.gradientMap;
20719
20720		const HAS_ALPHAMAP = !!material.alphaMap;
20721
20722		const HAS_ALPHATEST = material.alphaTest > 0;
20723
20724		const HAS_ALPHAHASH = !!material.alphaHash;
20725
20726		const HAS_EXTENSIONS = !!material.extensions;
20727
20728		const HAS_ATTRIBUTE_UV1 = !!geometry.attributes.uv1;
20729		const HAS_ATTRIBUTE_UV2 = !!geometry.attributes.uv2;
20730		const HAS_ATTRIBUTE_UV3 = !!geometry.attributes.uv3;
20731
20732		let toneMapping = NoToneMapping;
20733
20734		if (material.toneMapped) {
20735
20736			if (currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true) {
20737
20738				toneMapping = renderer.toneMapping;
20739
20740			}
20741
20742		}
20743
20744		const parameters = {
20745
20746			isWebGL2: IS_WEBGL2,
20747
20748			shaderID: shaderID,
20749			shaderType: material.type,
20750			shaderName: material.name,
20751
20752			vertexShader: vertexShader,
20753			fragmentShader: fragmentShader,
20754			defines: material.defines,
20755
20756			customVertexShaderID: customVertexShaderID,
20757			customFragmentShaderID: customFragmentShaderID,
20758
20759			isRawShaderMaterial: material.isRawShaderMaterial === true,
20760			glslVersion: material.glslVersion,
20761
20762			precision: precision,
20763
20764			batching: IS_BATCHEDMESH,
20765			instancing: IS_INSTANCEDMESH,
20766			instancingColor: IS_INSTANCEDMESH && object.instanceColor !== null,
20767
20768			supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES,
20769			outputColorSpace: (currentRenderTarget === null) ? renderer.outputColorSpace : (currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace),
20770
20771			map: HAS_MAP,
20772			matcap: HAS_MATCAP,
20773			envMap: HAS_ENVMAP,
20774			envMapMode: HAS_ENVMAP && envMap.mapping,
20775			envMapCubeUVHeight: envMapCubeUVHeight,
20776			aoMap: HAS_AOMAP,
20777			lightMap: HAS_LIGHTMAP,
20778			bumpMap: HAS_BUMPMAP,
20779			normalMap: HAS_NORMALMAP,
20780			displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP,
20781			emissiveMap: HAS_EMISSIVEMAP,
20782
20783			normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap,
20784			normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap,
20785
20786			metalnessMap: HAS_METALNESSMAP,
20787			roughnessMap: HAS_ROUGHNESSMAP,
20788
20789			anisotropy: HAS_ANISOTROPY,
20790			anisotropyMap: HAS_ANISOTROPYMAP,
20791
20792			clearcoat: HAS_CLEARCOAT,
20793			clearcoatMap: HAS_CLEARCOATMAP,
20794			clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP,
20795			clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP,
20796
20797			iridescence: HAS_IRIDESCENCE,
20798			iridescenceMap: HAS_IRIDESCENCEMAP,
20799			iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP,
20800
20801			sheen: HAS_SHEEN,
20802			sheenColorMap: HAS_SHEEN_COLORMAP,
20803			sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP,
20804
20805			specularMap: HAS_SPECULARMAP,
20806			specularColorMap: HAS_SPECULAR_COLORMAP,
20807			specularIntensityMap: HAS_SPECULAR_INTENSITYMAP,
20808
20809			transmission: HAS_TRANSMISSION,
20810			transmissionMap: HAS_TRANSMISSIONMAP,
20811			thicknessMap: HAS_THICKNESSMAP,
20812
20813			gradientMap: HAS_GRADIENTMAP,
20814
20815			opaque: material.transparent === false && material.blending === NormalBlending,
20816
20817			alphaMap: HAS_ALPHAMAP,
20818			alphaTest: HAS_ALPHATEST,
20819			alphaHash: HAS_ALPHAHASH,
20820
20821			combine: material.combine,
20822
20823			//
20824
20825			mapUv: HAS_MAP && getChannel(material.map.channel),
20826			aoMapUv: HAS_AOMAP && getChannel(material.aoMap.channel),
20827			lightMapUv: HAS_LIGHTMAP && getChannel(material.lightMap.channel),
20828			bumpMapUv: HAS_BUMPMAP && getChannel(material.bumpMap.channel),
20829			normalMapUv: HAS_NORMALMAP && getChannel(material.normalMap.channel),
20830			displacementMapUv: HAS_DISPLACEMENTMAP && getChannel(material.displacementMap.channel),
20831			emissiveMapUv: HAS_EMISSIVEMAP && getChannel(material.emissiveMap.channel),
20832
20833			metalnessMapUv: HAS_METALNESSMAP && getChannel(material.metalnessMap.channel),
20834			roughnessMapUv: HAS_ROUGHNESSMAP && getChannel(material.roughnessMap.channel),
20835
20836			anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel(material.anisotropyMap.channel),
20837
20838			clearcoatMapUv: HAS_CLEARCOATMAP && getChannel(material.clearcoatMap.channel),
20839			clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel(material.clearcoatNormalMap.channel),
20840			clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel(material.clearcoatRoughnessMap.channel),
20841
20842			iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel(material.iridescenceMap.channel),
20843			iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel(material.iridescenceThicknessMap.channel),
20844
20845			sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel(material.sheenColorMap.channel),
20846			sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel(material.sheenRoughnessMap.channel),
20847
20848			specularMapUv: HAS_SPECULARMAP && getChannel(material.specularMap.channel),
20849			specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel(material.specularColorMap.channel),
20850			specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel(material.specularIntensityMap.channel),
20851
20852			transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel(material.transmissionMap.channel),
20853			thicknessMapUv: HAS_THICKNESSMAP && getChannel(material.thicknessMap.channel),
20854
20855			alphaMapUv: HAS_ALPHAMAP && getChannel(material.alphaMap.channel),
20856
20857			//
20858
20859			vertexTangents: !!geometry.attributes.tangent && (HAS_NORMALMAP || HAS_ANISOTROPY),
20860			vertexColors: material.vertexColors,
20861			vertexAlphas: material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4,
20862			vertexUv1s: HAS_ATTRIBUTE_UV1,
20863			vertexUv2s: HAS_ATTRIBUTE_UV2,
20864			vertexUv3s: HAS_ATTRIBUTE_UV3,
20865
20866			pointsUvs: object.isPoints === true && !!geometry.attributes.uv && (HAS_MAP || HAS_ALPHAMAP),
20867
20868			fog: !!fog,
20869			useFog: material.fog === true,
20870			fogExp2: (fog && fog.isFogExp2),
20871
20872			flatShading: material.flatShading === true,
20873
20874			sizeAttenuation: material.sizeAttenuation === true,
20875			logarithmicDepthBuffer: logarithmicDepthBuffer,
20876
20877			skinning: object.isSkinnedMesh === true,
20878
20879			morphTargets: geometry.morphAttributes.position !== undefined,
20880			morphNormals: geometry.morphAttributes.normal !== undefined,
20881			morphColors: geometry.morphAttributes.color !== undefined,
20882			morphTargetsCount: morphTargetsCount,
20883			morphTextureStride: morphTextureStride,
20884
20885			numDirLights: lights.directional.length,
20886			numPointLights: lights.point.length,
20887			numSpotLights: lights.spot.length,
20888			numSpotLightMaps: lights.spotLightMap.length,
20889			numRectAreaLights: lights.rectArea.length,
20890			numHemiLights: lights.hemi.length,
20891
20892			numDirLightShadows: lights.directionalShadowMap.length,
20893			numPointLightShadows: lights.pointShadowMap.length,
20894			numSpotLightShadows: lights.spotShadowMap.length,
20895			numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps,
20896
20897			numLightProbes: lights.numLightProbes,
20898
20899			numClippingPlanes: clipping.numPlanes,
20900			numClipIntersection: clipping.numIntersection,
20901
20902			dithering: material.dithering,
20903
20904			shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
20905			shadowMapType: renderer.shadowMap.type,
20906
20907			toneMapping: toneMapping,
20908			useLegacyLights: renderer._useLegacyLights,
20909
20910			decodeVideoTexture: HAS_MAP && (material.map.isVideoTexture === true) && (ColorManagement.getTransfer(material.map.colorSpace) === SRGBTransfer),
20911
20912			premultipliedAlpha: material.premultipliedAlpha,
20913
20914			doubleSided: material.side === DoubleSide,
20915			flipSided: material.side === BackSide,
20916
20917			useDepthPacking: material.depthPacking >= 0,
20918			depthPacking: material.depthPacking || 0,
20919
20920			index0AttributeName: material.index0AttributeName,
20921
20922			extensionDerivatives: HAS_EXTENSIONS && material.extensions.derivatives === true,
20923			extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true,
20924			extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true,
20925			extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true,
20926			extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance && extensions.has('WEBGL_clip_cull_distance'),
20927
20928			rendererExtensionFragDepth: IS_WEBGL2 || extensions.has('EXT_frag_depth'),
20929			rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has('WEBGL_draw_buffers'),
20930			rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has('EXT_shader_texture_lod'),
20931			rendererExtensionParallelShaderCompile: extensions.has('KHR_parallel_shader_compile'),
20932
20933			customProgramCacheKey: material.customProgramCacheKey()
20934
20935		};
20936
20937		return parameters;
20938
20939	}
20940
20941	function getProgramCacheKey(parameters) {
20942
20943		const array = [];
20944
20945		if (parameters.shaderID) {
20946
20947			array.push(parameters.shaderID);
20948
20949		} else {
20950
20951			array.push(parameters.customVertexShaderID);
20952			array.push(parameters.customFragmentShaderID);
20953
20954		}
20955
20956		if (parameters.defines !== undefined) {
20957
20958			for (const name in parameters.defines) {
20959
20960				array.push(name);
20961				array.push(parameters.defines[name]);
20962
20963			}
20964
20965		}
20966
20967		if (parameters.isRawShaderMaterial === false) {
20968
20969			getProgramCacheKeyParameters(array, parameters);
20970			getProgramCacheKeyBooleans(array, parameters);
20971			array.push(renderer.outputColorSpace);
20972
20973		}
20974
20975		array.push(parameters.customProgramCacheKey);
20976
20977		return array.join();
20978
20979	}
20980
20981	function getProgramCacheKeyParameters(array, parameters) {
20982
20983		array.push(parameters.precision);
20984		array.push(parameters.outputColorSpace);
20985		array.push(parameters.envMapMode);
20986		array.push(parameters.envMapCubeUVHeight);
20987		array.push(parameters.mapUv);
20988		array.push(parameters.alphaMapUv);
20989		array.push(parameters.lightMapUv);
20990		array.push(parameters.aoMapUv);
20991		array.push(parameters.bumpMapUv);
20992		array.push(parameters.normalMapUv);
20993		array.push(parameters.displacementMapUv);
20994		array.push(parameters.emissiveMapUv);
20995		array.push(parameters.metalnessMapUv);
20996		array.push(parameters.roughnessMapUv);
20997		array.push(parameters.anisotropyMapUv);
20998		array.push(parameters.clearcoatMapUv);
20999		array.push(parameters.clearcoatNormalMapUv);
21000		array.push(parameters.clearcoatRoughnessMapUv);
21001		array.push(parameters.iridescenceMapUv);
21002		array.push(parameters.iridescenceThicknessMapUv);
21003		array.push(parameters.sheenColorMapUv);
21004		array.push(parameters.sheenRoughnessMapUv);
21005		array.push(parameters.specularMapUv);
21006		array.push(parameters.specularColorMapUv);
21007		array.push(parameters.specularIntensityMapUv);
21008		array.push(parameters.transmissionMapUv);
21009		array.push(parameters.thicknessMapUv);
21010		array.push(parameters.combine);
21011		array.push(parameters.fogExp2);
21012		array.push(parameters.sizeAttenuation);
21013		array.push(parameters.morphTargetsCount);
21014		array.push(parameters.morphAttributeCount);
21015		array.push(parameters.numDirLights);
21016		array.push(parameters.numPointLights);
21017		array.push(parameters.numSpotLights);
21018		array.push(parameters.numSpotLightMaps);
21019		array.push(parameters.numHemiLights);
21020		array.push(parameters.numRectAreaLights);
21021		array.push(parameters.numDirLightShadows);
21022		array.push(parameters.numPointLightShadows);
21023		array.push(parameters.numSpotLightShadows);
21024		array.push(parameters.numSpotLightShadowsWithMaps);
21025		array.push(parameters.numLightProbes);
21026		array.push(parameters.shadowMapType);
21027		array.push(parameters.toneMapping);
21028		array.push(parameters.numClippingPlanes);
21029		array.push(parameters.numClipIntersection);
21030		array.push(parameters.depthPacking);
21031
21032	}
21033
21034	function getProgramCacheKeyBooleans(array, parameters) {
21035
21036		_programLayers.disableAll();
21037
21038		if (parameters.isWebGL2)
21039			_programLayers.enable(0);
21040		if (parameters.supportsVertexTextures)
21041			_programLayers.enable(1);
21042		if (parameters.instancing)
21043			_programLayers.enable(2);
21044		if (parameters.instancingColor)
21045			_programLayers.enable(3);
21046		if (parameters.matcap)
21047			_programLayers.enable(4);
21048		if (parameters.envMap)
21049			_programLayers.enable(5);
21050		if (parameters.normalMapObjectSpace)
21051			_programLayers.enable(6);
21052		if (parameters.normalMapTangentSpace)
21053			_programLayers.enable(7);
21054		if (parameters.clearcoat)
21055			_programLayers.enable(8);
21056		if (parameters.iridescence)
21057			_programLayers.enable(9);
21058		if (parameters.alphaTest)
21059			_programLayers.enable(10);
21060		if (parameters.vertexColors)
21061			_programLayers.enable(11);
21062		if (parameters.vertexAlphas)
21063			_programLayers.enable(12);
21064		if (parameters.vertexUv1s)
21065			_programLayers.enable(13);
21066		if (parameters.vertexUv2s)
21067			_programLayers.enable(14);
21068		if (parameters.vertexUv3s)
21069			_programLayers.enable(15);
21070		if (parameters.vertexTangents)
21071			_programLayers.enable(16);
21072		if (parameters.anisotropy)
21073			_programLayers.enable(17);
21074		if (parameters.alphaHash)
21075			_programLayers.enable(18);
21076		if (parameters.batching)
21077			_programLayers.enable(19);
21078
21079		array.push(_programLayers.mask);
21080		_programLayers.disableAll();
21081
21082		if (parameters.fog)
21083			_programLayers.enable(0);
21084		if (parameters.useFog)
21085			_programLayers.enable(1);
21086		if (parameters.flatShading)
21087			_programLayers.enable(2);
21088		if (parameters.logarithmicDepthBuffer)
21089			_programLayers.enable(3);
21090		if (parameters.skinning)
21091			_programLayers.enable(4);
21092		if (parameters.morphTargets)
21093			_programLayers.enable(5);
21094		if (parameters.morphNormals)
21095			_programLayers.enable(6);
21096		if (parameters.morphColors)
21097			_programLayers.enable(7);
21098		if (parameters.premultipliedAlpha)
21099			_programLayers.enable(8);
21100		if (parameters.shadowMapEnabled)
21101			_programLayers.enable(9);
21102		if (parameters.useLegacyLights)
21103			_programLayers.enable(10);
21104		if (parameters.doubleSided)
21105			_programLayers.enable(11);
21106		if (parameters.flipSided)
21107			_programLayers.enable(12);
21108		if (parameters.useDepthPacking)
21109			_programLayers.enable(13);
21110		if (parameters.dithering)
21111			_programLayers.enable(14);
21112		if (parameters.transmission)
21113			_programLayers.enable(15);
21114		if (parameters.sheen)
21115			_programLayers.enable(16);
21116		if (parameters.opaque)
21117			_programLayers.enable(17);
21118		if (parameters.pointsUvs)
21119			_programLayers.enable(18);
21120		if (parameters.decodeVideoTexture)
21121			_programLayers.enable(19);
21122
21123		array.push(_programLayers.mask);
21124
21125	}
21126
21127	function getUniforms(material) {
21128
21129		const shaderID = shaderIDs[material.type];
21130		let uniforms;
21131
21132		if (shaderID) {
21133
21134			const shader = ShaderLib[shaderID];
21135			uniforms = UniformsUtils.clone(shader.uniforms);
21136
21137		} else {
21138
21139			uniforms = material.uniforms;
21140
21141		}
21142
21143		return uniforms;
21144
21145	}
21146
21147	function acquireProgram(parameters, cacheKey) {
21148
21149		let program;
21150
21151		// Check if code has been already compiled
21152		for (let p = 0, pl = programs.length; p < pl; p++) {
21153
21154			const preexistingProgram = programs[p];
21155
21156			if (preexistingProgram.cacheKey === cacheKey) {
21157
21158				program = preexistingProgram;
21159				++program.usedTimes;
21160
21161				break;
21162
21163			}
21164
21165		}
21166
21167		if (program === undefined) {
21168
21169			program = new WebGLProgram(renderer, cacheKey, parameters, bindingStates);
21170			programs.push(program);
21171
21172		}
21173
21174		return program;
21175
21176	}
21177
21178	function releaseProgram(program) {
21179
21180		if (--program.usedTimes === 0) {
21181
21182			// Remove from unordered set
21183			const i = programs.indexOf(program);
21184			programs[i] = programs[programs.length - 1];
21185			programs.pop();
21186
21187			// Free WebGL resources
21188			program.destroy();
21189
21190		}
21191
21192	}
21193
21194	function releaseShaderCache(material) {
21195
21196		_customShaders.remove(material);
21197
21198	}
21199
21200	function dispose() {
21201
21202		_customShaders.dispose();
21203
21204	}
21205
21206	return {
21207		getParameters: getParameters,
21208		getProgramCacheKey: getProgramCacheKey,
21209		getUniforms: getUniforms,
21210		acquireProgram: acquireProgram,
21211		releaseProgram: releaseProgram,
21212		releaseShaderCache: releaseShaderCache,
21213		// Exposed for resource monitoring & error feedback via renderer.info:
21214		programs: programs,
21215		dispose: dispose
21216	};
21217
21218}
21219
21220function WebGLProperties() {
21221
21222	let properties = new WeakMap();
21223
21224	function get(object) {
21225
21226		let map = properties.get(object);
21227
21228		if (map === undefined) {
21229
21230			map = {};
21231			properties.set(object, map);
21232
21233		}
21234
21235		return map;
21236
21237	}
21238
21239	function remove(object) {
21240
21241		properties.delete(object);
21242
21243	}
21244
21245	function update(object, key, value) {
21246
21247		properties.get(object)[key] = value;
21248
21249	}
21250
21251	function dispose() {
21252
21253		properties = new WeakMap();
21254
21255	}
21256
21257	return {
21258		get: get,
21259		remove: remove,
21260		update: update,
vendor: 4,151 bytes, lines 21261-21496
21261		dispose: dispose
21262	};
21263
21264}
21265
21266function painterSortStable(a, b) {
21267
21268	if (a.groupOrder !== b.groupOrder) {
21269
21270		return a.groupOrder - b.groupOrder;
21271
21272	} else if (a.renderOrder !== b.renderOrder) {
21273
21274		return a.renderOrder - b.renderOrder;
21275
21276	} else if (a.material.id !== b.material.id) {
21277
21278		return a.material.id - b.material.id;
21279
21280	} else if (a.z !== b.z) {
21281
21282		return a.z - b.z;
21283
21284	} else {
21285
21286		return a.id - b.id;
21287
21288	}
21289
21290}
21291
21292function reversePainterSortStable(a, b) {
21293
21294	if (a.groupOrder !== b.groupOrder) {
21295
21296		return a.groupOrder - b.groupOrder;
21297
21298	} else if (a.renderOrder !== b.renderOrder) {
21299
21300		return a.renderOrder - b.renderOrder;
21301
21302	} else if (a.z !== b.z) {
21303
21304		return b.z - a.z;
21305
21306	} else {
21307
21308		return a.id - b.id;
21309
21310	}
21311
21312}
21313
21314
21315function WebGLRenderList() {
21316
21317	const renderItems = [];
21318	let renderItemsIndex = 0;
21319
21320	const opaque = [];
21321	const transmissive = [];
21322	const transparent = [];
21323
21324	function init() {
21325
21326		renderItemsIndex = 0;
21327
21328		opaque.length = 0;
21329		transmissive.length = 0;
21330		transparent.length = 0;
21331
21332	}
21333
21334	function getNextRenderItem(object, geometry, material, groupOrder, z, group) {
21335
21336		let renderItem = renderItems[renderItemsIndex];
21337
21338		if (renderItem === undefined) {
21339
21340			renderItem = {
21341				id: object.id,
21342				object: object,
21343				geometry: geometry,
21344				material: material,
21345				groupOrder: groupOrder,
21346				renderOrder: object.renderOrder,
21347				z: z,
21348				group: group
21349			};
21350
21351			renderItems[renderItemsIndex] = renderItem;
21352
21353		} else {
21354
21355			renderItem.id = object.id;
21356			renderItem.object = object;
21357			renderItem.geometry = geometry;
21358			renderItem.material = material;
21359			renderItem.groupOrder = groupOrder;
21360			renderItem.renderOrder = object.renderOrder;
21361			renderItem.z = z;
21362			renderItem.group = group;
21363
21364		}
21365
21366		renderItemsIndex++;
21367
21368		return renderItem;
21369
21370	}
21371
21372	function push(object, geometry, material, groupOrder, z, group) {
21373
21374		const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group);
21375
21376		if (material.transmission > 0.0) {
21377
21378			transmissive.push(renderItem);
21379
21380		} else if (material.transparent === true) {
21381
21382			transparent.push(renderItem);
21383
21384		} else {
21385
21386			opaque.push(renderItem);
21387
21388		}
21389
21390	}
21391
21392	function unshift(object, geometry, material, groupOrder, z, group) {
21393
21394		const renderItem = getNextRenderItem(object, geometry, material, groupOrder, z, group);
21395
21396		if (material.transmission > 0.0) {
21397
21398			transmissive.unshift(renderItem);
21399
21400		} else if (material.transparent === true) {
21401
21402			transparent.unshift(renderItem);
21403
21404		} else {
21405
21406			opaque.unshift(renderItem);
21407
21408		}
21409
21410	}
21411
21412	function sort(customOpaqueSort, customTransparentSort) {
21413
21414		if (opaque.length > 1) opaque.sort(customOpaqueSort || painterSortStable);
21415		if (transmissive.length > 1) transmissive.sort(customTransparentSort || reversePainterSortStable);
21416		if (transparent.length > 1) transparent.sort(customTransparentSort || reversePainterSortStable);
21417
21418	}
21419
21420	function finish() {
21421
21422		// Clear references from inactive renderItems in the list
21423
21424		for (let i = renderItemsIndex, il = renderItems.length; i < il; i++) {
21425
21426			const renderItem = renderItems[i];
21427
21428			if (renderItem.id === null) break;
21429
21430			renderItem.id = null;
21431			renderItem.object = null;
21432			renderItem.geometry = null;
21433			renderItem.material = null;
21434			renderItem.group = null;
21435
21436		}
21437
21438	}
21439
21440	return {
21441
21442		opaque: opaque,
21443		transmissive: transmissive,
21444		transparent: transparent,
21445
21446		init: init,
21447		push: push,
21448		unshift: unshift,
21449		finish: finish,
21450
21451		sort: sort
21452	};
21453
21454}
21455
21456function WebGLRenderLists() {
21457
21458	let lists = new WeakMap();
21459
21460	function get(scene, renderCallDepth) {
21461
21462		const listArray = lists.get(scene);
21463		let list;
21464
21465		if (listArray === undefined) {
21466
21467			list = new WebGLRenderList();
21468			lists.set(scene, [list]);
21469
21470		} else {
21471
21472			if (renderCallDepth >= listArray.length) {
21473
21474				list = new WebGLRenderList();
21475				listArray.push(list);
21476
21477			} else {
21478
21479				list = listArray[renderCallDepth];
21480
21481			}
21482
21483		}
21484
21485		return list;
21486
21487	}
21488
21489	function dispose() {
21490
21491		lists = new WeakMap();
21492
21493	}
21494
21495	return {
21496		get: get,
vendor: 17,259 bytes, lines 21497-22279
21497		dispose: dispose
21498	};
21499
21500}
21501
21502function UniformsCache() {
21503
21504	const lights = {};
21505
21506	return {
21507
21508		get: function (light) {
21509
21510			if (lights[light.id] !== undefined) {
21511
21512				return lights[light.id];
21513
21514			}
21515
21516			let uniforms;
21517
21518			switch (light.type) {
21519
21520				case 'DirectionalLight':
21521					uniforms = {
21522						direction: new Vector3(),
21523						color: new Color()
21524					};
21525					break;
21526
21527				case 'SpotLight':
21528					uniforms = {
21529						position: new Vector3(),
21530						direction: new Vector3(),
21531						color: new Color(),
21532						distance: 0,
21533						coneCos: 0,
21534						penumbraCos: 0,
21535						decay: 0
21536					};
21537					break;
21538
21539				case 'PointLight':
21540					uniforms = {
21541						position: new Vector3(),
21542						color: new Color(),
21543						distance: 0,
21544						decay: 0
21545					};
21546					break;
21547
21548				case 'HemisphereLight':
21549					uniforms = {
21550						direction: new Vector3(),
21551						skyColor: new Color(),
21552						groundColor: new Color()
21553					};
21554					break;
21555
21556				case 'RectAreaLight':
21557					uniforms = {
21558						color: new Color(),
21559						position: new Vector3(),
21560						halfWidth: new Vector3(),
21561						halfHeight: new Vector3()
21562					};
21563					break;
21564
21565			}
21566
21567			lights[light.id] = uniforms;
21568
21569			return uniforms;
21570
21571		}
21572
21573	};
21574
21575}
21576
21577function ShadowUniformsCache() {
21578
21579	const lights = {};
21580
21581	return {
21582
21583		get: function (light) {
21584
21585			if (lights[light.id] !== undefined) {
21586
21587				return lights[light.id];
21588
21589			}
21590
21591			let uniforms;
21592
21593			switch (light.type) {
21594
21595				case 'DirectionalLight':
21596					uniforms = {
21597						shadowBias: 0,
21598						shadowNormalBias: 0,
21599						shadowRadius: 1,
21600						shadowMapSize: new Vector2()
21601					};
21602					break;
21603
21604				case 'SpotLight':
21605					uniforms = {
21606						shadowBias: 0,
21607						shadowNormalBias: 0,
21608						shadowRadius: 1,
21609						shadowMapSize: new Vector2()
21610					};
21611					break;
21612
21613				case 'PointLight':
21614					uniforms = {
21615						shadowBias: 0,
21616						shadowNormalBias: 0,
21617						shadowRadius: 1,
21618						shadowMapSize: new Vector2(),
21619						shadowCameraNear: 1,
21620						shadowCameraFar: 1000
21621					};
21622					break;
21623
21624				// TODO (abelnation): set RectAreaLight shadow uniforms
21625
21626			}
21627
21628			lights[light.id] = uniforms;
21629
21630			return uniforms;
21631
21632		}
21633
21634	};
21635
21636}
21637
21638
21639
21640let nextVersion = 0;
21641
21642function shadowCastingAndTexturingLightsFirst(lightA, lightB) {
21643
21644	return (lightB.castShadow ? 2 : 0) - (lightA.castShadow ? 2 : 0) + (lightB.map ? 1 : 0) - (lightA.map ? 1 : 0);
21645
21646}
21647
21648function WebGLLights(extensions, capabilities) {
21649
21650	const cache = new UniformsCache();
21651
21652	const shadowCache = ShadowUniformsCache();
21653
21654	const state = {
21655
21656		version: 0,
21657
21658		hash: {
21659			directionalLength: - 1,
21660			pointLength: - 1,
21661			spotLength: - 1,
21662			rectAreaLength: - 1,
21663			hemiLength: - 1,
21664
21665			numDirectionalShadows: - 1,
21666			numPointShadows: - 1,
21667			numSpotShadows: - 1,
21668			numSpotMaps: - 1,
21669
21670			numLightProbes: - 1
21671		},
21672
21673		ambient: [0, 0, 0],
21674		probe: [],
21675		directional: [],
21676		directionalShadow: [],
21677		directionalShadowMap: [],
21678		directionalShadowMatrix: [],
21679		spot: [],
21680		spotLightMap: [],
21681		spotShadow: [],
21682		spotShadowMap: [],
21683		spotLightMatrix: [],
21684		rectArea: [],
21685		rectAreaLTC1: null,
21686		rectAreaLTC2: null,
21687		point: [],
21688		pointShadow: [],
21689		pointShadowMap: [],
21690		pointShadowMatrix: [],
21691		hemi: [],
21692		numSpotLightShadowsWithMaps: 0,
21693		numLightProbes: 0
21694
21695	};
21696
21697	for (let i = 0; i < 9; i++) state.probe.push(new Vector3());
21698
21699	const vector3 = new Vector3();
21700	const matrix4 = new Matrix4();
21701	const matrix42 = new Matrix4();
21702
21703	function setup(lights, useLegacyLights) {
21704
21705		let r = 0, g = 0, b = 0;
21706
21707		for (let i = 0; i < 9; i++) state.probe[i].set(0, 0, 0);
21708
21709		let directionalLength = 0;
21710		let pointLength = 0;
21711		let spotLength = 0;
21712		let rectAreaLength = 0;
21713		let hemiLength = 0;
21714
21715		let numDirectionalShadows = 0;
21716		let numPointShadows = 0;
21717		let numSpotShadows = 0;
21718		let numSpotMaps = 0;
21719		let numSpotShadowsWithMaps = 0;
21720
21721		let numLightProbes = 0;
21722
21723		// ordering : [shadow casting + map texturing, map texturing, shadow casting, none ]
21724		lights.sort(shadowCastingAndTexturingLightsFirst);
21725
21726		// artist-friendly light intensity scaling factor
21727		const scaleFactor = (useLegacyLights === true) ? Math.PI : 1;
21728
21729		for (let i = 0, l = lights.length; i < l; i++) {
21730
21731			const light = lights[i];
21732
21733			const color = light.color;
21734			const intensity = light.intensity;
21735			const distance = light.distance;
21736
21737			const shadowMap = (light.shadow && light.shadow.map) ? light.shadow.map.texture : null;
21738
21739			if (light.isAmbientLight) {
21740
21741				r += color.r * intensity * scaleFactor;
21742				g += color.g * intensity * scaleFactor;
21743				b += color.b * intensity * scaleFactor;
21744
21745			} else if (light.isLightProbe) {
21746
21747				for (let j = 0; j < 9; j++) {
21748
21749					state.probe[j].addScaledVector(light.sh.coefficients[j], intensity);
21750
21751				}
21752
21753				numLightProbes++;
21754
21755			} else if (light.isDirectionalLight) {
21756
21757				const uniforms = cache.get(light);
21758
21759				uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor);
21760
21761				if (light.castShadow) {
21762
21763					const shadow = light.shadow;
21764
21765					const shadowUniforms = shadowCache.get(light);
21766
21767					shadowUniforms.shadowBias = shadow.bias;
21768					shadowUniforms.shadowNormalBias = shadow.normalBias;
21769					shadowUniforms.shadowRadius = shadow.radius;
21770					shadowUniforms.shadowMapSize = shadow.mapSize;
21771
21772					state.directionalShadow[directionalLength] = shadowUniforms;
21773					state.directionalShadowMap[directionalLength] = shadowMap;
21774					state.directionalShadowMatrix[directionalLength] = light.shadow.matrix;
21775
21776					numDirectionalShadows++;
21777
21778				}
21779
21780				state.directional[directionalLength] = uniforms;
21781
21782				directionalLength++;
21783
21784			} else if (light.isSpotLight) {
21785
21786				const uniforms = cache.get(light);
21787
21788				uniforms.position.setFromMatrixPosition(light.matrixWorld);
21789
21790				uniforms.color.copy(color).multiplyScalar(intensity * scaleFactor);
21791				uniforms.distance = distance;
21792
21793				uniforms.coneCos = Math.cos(light.angle);
21794				uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra));
21795				uniforms.decay = light.decay;
21796
21797				state.spot[spotLength] = uniforms;
21798
21799				const shadow = light.shadow;
21800
21801				if (light.map) {
21802
21803					state.spotLightMap[numSpotMaps] = light.map;
21804					numSpotMaps++;
21805
21806					// make sure the lightMatrix is up to date
21807					// TODO : do it if required only
21808					shadow.updateMatrices(light);
21809
21810					if (light.castShadow) numSpotShadowsWithMaps++;
21811
21812				}
21813
21814				state.spotLightMatrix[spotLength] = shadow.matrix;
21815
21816				if (light.castShadow) {
21817
21818					const shadowUniforms = shadowCache.get(light);
21819
21820					shadowUniforms.shadowBias = shadow.bias;
21821					shadowUniforms.shadowNormalBias = shadow.normalBias;
21822					shadowUniforms.shadowRadius = shadow.radius;
21823					shadowUniforms.shadowMapSize = shadow.mapSize;
21824
21825					state.spotShadow[spotLength] = shadowUniforms;
21826					state.spotShadowMap[spotLength] = shadowMap;
21827
21828					numSpotShadows++;
21829
21830				}
21831
21832				spotLength++;
21833
21834			} else if (light.isRectAreaLight) {
21835
21836				const uniforms = cache.get(light);
21837
21838				uniforms.color.copy(color).multiplyScalar(intensity);
21839
21840				uniforms.halfWidth.set(light.width * 0.5, 0.0, 0.0);
21841				uniforms.halfHeight.set(0.0, light.height * 0.5, 0.0);
21842
21843				state.rectArea[rectAreaLength] = uniforms;
21844
21845				rectAreaLength++;
21846
21847			} else if (light.isPointLight) {
21848
21849				const uniforms = cache.get(light);
21850
21851				uniforms.color.copy(light.color).multiplyScalar(light.intensity * scaleFactor);
21852				uniforms.distance = light.distance;
21853				uniforms.decay = light.decay;
21854
21855				if (light.castShadow) {
21856
21857					const shadow = light.shadow;
21858
21859					const shadowUniforms = shadowCache.get(light);
21860
21861					shadowUniforms.shadowBias = shadow.bias;
21862					shadowUniforms.shadowNormalBias = shadow.normalBias;
21863					shadowUniforms.shadowRadius = shadow.radius;
21864					shadowUniforms.shadowMapSize = shadow.mapSize;
21865					shadowUniforms.shadowCameraNear = shadow.camera.near;
21866					shadowUniforms.shadowCameraFar = shadow.camera.far;
21867
21868					state.pointShadow[pointLength] = shadowUniforms;
21869					state.pointShadowMap[pointLength] = shadowMap;
21870					state.pointShadowMatrix[pointLength] = light.shadow.matrix;
21871
21872					numPointShadows++;
21873
21874				}
21875
21876				state.point[pointLength] = uniforms;
21877
21878				pointLength++;
21879
21880			} else if (light.isHemisphereLight) {
21881
21882				const uniforms = cache.get(light);
21883
21884				uniforms.skyColor.copy(light.color).multiplyScalar(intensity * scaleFactor);
21885				uniforms.groundColor.copy(light.groundColor).multiplyScalar(intensity * scaleFactor);
21886
21887				state.hemi[hemiLength] = uniforms;
21888
21889				hemiLength++;
21890
21891			}
21892
21893		}
21894
21895		if (rectAreaLength > 0) {
21896
21897			if (capabilities.isWebGL2) {
21898
21899				// WebGL 2
21900
21901				if (extensions.has('OES_texture_float_linear') === true) {
21902
21903					state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
21904					state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
21905
21906				} else {
21907
21908					state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
21909					state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
21910
21911				}
21912
21913			} else {
21914
21915				// WebGL 1
21916
21917				if (extensions.has('OES_texture_float_linear') === true) {
21918
21919					state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
21920					state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
21921
21922				} else if (extensions.has('OES_texture_half_float_linear') === true) {
21923
21924					state.rectAreaLTC1 = UniformsLib.LTC_HALF_1;
21925					state.rectAreaLTC2 = UniformsLib.LTC_HALF_2;
21926
21927				} else {
21928
21929					console.error('THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.');
21930
21931				}
21932
21933			}
21934
21935		}
21936
21937		state.ambient[0] = r;
21938		state.ambient[1] = g;
21939		state.ambient[2] = b;
21940
21941		const hash = state.hash;
21942
21943		if (hash.directionalLength !== directionalLength ||
21944			hash.pointLength !== pointLength ||
21945			hash.spotLength !== spotLength ||
21946			hash.rectAreaLength !== rectAreaLength ||
21947			hash.hemiLength !== hemiLength ||
21948			hash.numDirectionalShadows !== numDirectionalShadows ||
21949			hash.numPointShadows !== numPointShadows ||
21950			hash.numSpotShadows !== numSpotShadows ||
21951			hash.numSpotMaps !== numSpotMaps ||
21952			hash.numLightProbes !== numLightProbes) {
21953
21954			state.directional.length = directionalLength;
21955			state.spot.length = spotLength;
21956			state.rectArea.length = rectAreaLength;
21957			state.point.length = pointLength;
21958			state.hemi.length = hemiLength;
21959
21960			state.directionalShadow.length = numDirectionalShadows;
21961			state.directionalShadowMap.length = numDirectionalShadows;
21962			state.pointShadow.length = numPointShadows;
21963			state.pointShadowMap.length = numPointShadows;
21964			state.spotShadow.length = numSpotShadows;
21965			state.spotShadowMap.length = numSpotShadows;
21966			state.directionalShadowMatrix.length = numDirectionalShadows;
21967			state.pointShadowMatrix.length = numPointShadows;
21968			state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps;
21969			state.spotLightMap.length = numSpotMaps;
21970			state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps;
21971			state.numLightProbes = numLightProbes;
21972
21973			hash.directionalLength = directionalLength;
21974			hash.pointLength = pointLength;
21975			hash.spotLength = spotLength;
21976			hash.rectAreaLength = rectAreaLength;
21977			hash.hemiLength = hemiLength;
21978
21979			hash.numDirectionalShadows = numDirectionalShadows;
21980			hash.numPointShadows = numPointShadows;
21981			hash.numSpotShadows = numSpotShadows;
21982			hash.numSpotMaps = numSpotMaps;
21983
21984			hash.numLightProbes = numLightProbes;
21985
21986			state.version = nextVersion++;
21987
21988		}
21989
21990	}
21991
21992	function setupView(lights, camera) {
21993
21994		let directionalLength = 0;
21995		let pointLength = 0;
21996		let spotLength = 0;
21997		let rectAreaLength = 0;
21998		let hemiLength = 0;
21999
22000		const viewMatrix = camera.matrixWorldInverse;
22001
22002		for (let i = 0, l = lights.length; i < l; i++) {
22003
22004			const light = lights[i];
22005
22006			if (light.isDirectionalLight) {
22007
22008				const uniforms = state.directional[directionalLength];
22009
22010				uniforms.direction.setFromMatrixPosition(light.matrixWorld);
22011				vector3.setFromMatrixPosition(light.target.matrixWorld);
22012				uniforms.direction.sub(vector3);
22013				uniforms.direction.transformDirection(viewMatrix);
22014
22015				directionalLength++;
22016
22017			} else if (light.isSpotLight) {
22018
22019				const uniforms = state.spot[spotLength];
22020
22021				uniforms.position.setFromMatrixPosition(light.matrixWorld);
22022				uniforms.position.applyMatrix4(viewMatrix);
22023
22024				uniforms.direction.setFromMatrixPosition(light.matrixWorld);
22025				vector3.setFromMatrixPosition(light.target.matrixWorld);
22026				uniforms.direction.sub(vector3);
22027				uniforms.direction.transformDirection(viewMatrix);
22028
22029				spotLength++;
22030
22031			} else if (light.isRectAreaLight) {
22032
22033				const uniforms = state.rectArea[rectAreaLength];
22034
22035				uniforms.position.setFromMatrixPosition(light.matrixWorld);
22036				uniforms.position.applyMatrix4(viewMatrix);
22037
22038				// extract local rotation of light to derive width/height half vectors
22039				matrix42.identity();
22040				matrix4.copy(light.matrixWorld);
22041				matrix4.premultiply(viewMatrix);
22042				matrix42.extractRotation(matrix4);
22043
22044				uniforms.halfWidth.set(light.width * 0.5, 0.0, 0.0);
22045				uniforms.halfHeight.set(0.0, light.height * 0.5, 0.0);
22046
22047				uniforms.halfWidth.applyMatrix4(matrix42);
22048				uniforms.halfHeight.applyMatrix4(matrix42);
22049
22050				rectAreaLength++;
22051
22052			} else if (light.isPointLight) {
22053
22054				const uniforms = state.point[pointLength];
22055
22056				uniforms.position.setFromMatrixPosition(light.matrixWorld);
22057				uniforms.position.applyMatrix4(viewMatrix);
22058
22059				pointLength++;
22060
22061			} else if (light.isHemisphereLight) {
22062
22063				const uniforms = state.hemi[hemiLength];
22064
22065				uniforms.direction.setFromMatrixPosition(light.matrixWorld);
22066				uniforms.direction.transformDirection(viewMatrix);
22067
22068				hemiLength++;
22069
22070			}
22071
22072		}
22073
22074	}
22075
22076	return {
22077		setup: setup,
22078		setupView: setupView,
22079		state: state
22080	};
22081
22082}
22083
22084function WebGLRenderState(extensions, capabilities) {
22085
22086	const lights = new WebGLLights(extensions, capabilities);
22087
22088	const lightsArray = [];
22089	const shadowsArray = [];
22090
22091	function init() {
22092
22093		lightsArray.length = 0;
22094		shadowsArray.length = 0;
22095
22096	}
22097
22098	function pushLight(light) {
22099
22100		lightsArray.push(light);
22101
22102	}
22103
22104	function pushShadow(shadowLight) {
22105
22106		shadowsArray.push(shadowLight);
22107
22108	}
22109
22110	function setupLights(useLegacyLights) {
22111
22112		lights.setup(lightsArray, useLegacyLights);
22113
22114	}
22115
22116	function setupLightsView(camera) {
22117
22118		lights.setupView(lightsArray, camera);
22119
22120	}
22121
22122	const state = {
22123		lightsArray: lightsArray,
22124		shadowsArray: shadowsArray,
22125
22126		lights: lights
22127	};
22128
22129	return {
22130		init: init,
22131		state: state,
22132		setupLights: setupLights,
22133		setupLightsView: setupLightsView,
22134
22135		pushLight: pushLight,
22136		pushShadow: pushShadow
22137	};
22138
22139}
22140
22141function WebGLRenderStates(extensions, capabilities) {
22142
22143	let renderStates = new WeakMap();
22144
22145	function get(scene, renderCallDepth = 0) {
22146
22147		const renderStateArray = renderStates.get(scene);
22148		let renderState;
22149
22150		if (renderStateArray === undefined) {
22151
22152			renderState = new WebGLRenderState(extensions, capabilities);
22153			renderStates.set(scene, [renderState]);
22154
22155		} else {
22156
22157			if (renderCallDepth >= renderStateArray.length) {
22158
22159				renderState = new WebGLRenderState(extensions, capabilities);
22160				renderStateArray.push(renderState);
22161
22162			} else {
22163
22164				renderState = renderStateArray[renderCallDepth];
22165
22166			}
22167
22168		}
22169
22170		return renderState;
22171
22172	}
22173
22174	function dispose() {
22175
22176		renderStates = new WeakMap();
22177
22178	}
22179
22180	return {
22181		get: get,
22182		dispose: dispose
22183	};
22184
22185}
22186
22187class MeshDepthMaterial extends Material {
22188
22189	constructor(parameters) {
22190
22191		super();
22192
22193		this.isMeshDepthMaterial = true;
22194
22195		this.type = 'MeshDepthMaterial';
22196
22197		this.depthPacking = BasicDepthPacking;
22198
22199		this.map = null;
22200
22201		this.alphaMap = null;
22202
22203		this.displacementMap = null;
22204		this.displacementScale = 1;
22205		this.displacementBias = 0;
22206
22207		this.wireframe = false;
22208		this.wireframeLinewidth = 1;
22209
22210		this.setValues(parameters);
22211
22212	}
22213
22214	copy(source) {
22215
22216		super.copy(source);
22217
22218		this.depthPacking = source.depthPacking;
22219
22220		this.map = source.map;
22221
22222		this.alphaMap = source.alphaMap;
22223
22224		this.displacementMap = source.displacementMap;
22225		this.displacementScale = source.displacementScale;
22226		this.displacementBias = source.displacementBias;
22227
22228		this.wireframe = source.wireframe;
22229		this.wireframeLinewidth = source.wireframeLinewidth;
22230
22231		return this;
22232
22233	}
22234
22235}
22236
22237class MeshDistanceMaterial extends Material {
22238
22239	constructor(parameters) {
22240
22241		super();
22242
22243		this.isMeshDistanceMaterial = true;
22244
22245		this.type = 'MeshDistanceMaterial';
22246
22247		this.map = null;
22248
22249		this.alphaMap = null;
22250
22251		this.displacementMap = null;
22252		this.displacementScale = 1;
22253		this.displacementBias = 0;
22254
22255		this.setValues(parameters);
22256
22257	}
22258
22259	copy(source) {
22260
22261		super.copy(source);
22262
22263		this.map = source.map;
22264
22265		this.alphaMap = source.alphaMap;
22266
22267		this.displacementMap = source.displacementMap;
22268		this.displacementScale = source.displacementScale;
22269		this.displacementBias = source.displacementBias;
22270
22271		return this;
22272
22273	}
22274
22275}
22276
22277const vertex = "void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
22278
22279const fragment = "uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>
22279\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}";
22280
22281function WebGLShadowMap(_renderer, _objects, _capabilities) {
22282
22283	let _frustum = new Frustum();
22284
22285	const _shadowMapSize = new Vector2(),
22286		_viewportSize = new Vector2(),
22287
22288		_viewport = new Vector4(),
22289
22290		_depthMaterial = new MeshDepthMaterial({ depthPacking: RGBADepthPacking }),
22291		_distanceMaterial = new MeshDistanceMaterial(),
22292
22293		_materialCache = {},
22294
22295		_maxTextureSize = _capabilities.maxTextureSize;
22296
22297	const shadowSide = { [FrontSide]: BackSide, [BackSide]: FrontSide, [DoubleSide]: DoubleSide };
22298
22299	const shadowMaterialVertical = new ShaderMaterial({
22300		defines: {
22301			VSM_SAMPLES: 8
22302		},
22303		uniforms: {
22304			shadow_pass: { value: null },
22305			resolution: { value: new Vector2() },
22306			radius: { value: 4.0 }
22307		},
22308
22309		vertexShader: vertex,
22310		fragmentShader: fragment
22311
22312	});
22313
22314	const shadowMaterialHorizontal = shadowMaterialVertical.clone();
22315	shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
22316
22317	const fullScreenTri = new BufferGeometry();
22318	fullScreenTri.setAttribute(
22319		'position',
22320		new BufferAttribute(
22321			new Float32Array([- 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5]),
22322			3
22323		)
22324	);
22325
22326	const fullScreenMesh = new Mesh(fullScreenTri, shadowMaterialVertical);
22327
22328	const scope = this;
22329
22330	this.enabled = false;
22331
22332	this.autoUpdate = true;
22333	this.needsUpdate = false;
22334
22335	this.type = PCFShadowMap;
22336	let _previousType = this.type;
22337
22338	this.render = function (lights, scene, camera) {
22339
22340		if (scope.enabled === false) return;
22341		if (scope.autoUpdate === false && scope.needsUpdate === false) return;
22342
22343		if (lights.length === 0) return;
22344
22345		const currentRenderTarget = _renderer.getRenderTarget();
22346		const activeCubeFace = _renderer.getActiveCubeFace();
22347		const activeMipmapLevel = _renderer.getActiveMipmapLevel();
22348
22349		const _state = _renderer.state;
22350
22351		// Set GL state for depth map.
22352		_state.setBlending(NoBlending);
22353		_state.buffers.color.setClear(1, 1, 1, 1);
22354		_state.buffers.depth.setTest(true);
22355		_state.setScissorTest(false);
22356
22357		// check for shadow map type changes
22358
22359		const toVSM = (_previousType !== VSMShadowMap && this.type === VSMShadowMap);
22360		const fromVSM = (_previousType === VSMShadowMap && this.type !== VSMShadowMap);
22361
22362		// render depth map
22363
22364		for (let i = 0, il = lights.length; i < il; i++) {
22365
22366			const light = lights[i];
22367			const shadow = light.shadow;
22368
22369			if (shadow === undefined) {
22370
22371				console.warn('THREE.WebGLShadowMap:', light, 'has no shadow.');
22372				continue;
22373
22374			}
22375
22376			if (shadow.autoUpdate === false && shadow.needsUpdate === false) continue;
22377
22378			_shadowMapSize.copy(shadow.mapSize);
22379
22380			const shadowFrameExtents = shadow.getFrameExtents();
22381
22382			_shadowMapSize.multiply(shadowFrameExtents);
22383
22384			_viewportSize.copy(shadow.mapSize);
22385
22386			if (_shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize) {
22387
22388				if (_shadowMapSize.x > _maxTextureSize) {
22389
22390					_viewportSize.x = Math.floor(_maxTextureSize / shadowFrameExtents.x);
22391					_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
22392					shadow.mapSize.x = _viewportSize.x;
22393
22394				}
22395
22396				if (_shadowMapSize.y > _maxTextureSize) {
22397
22398					_viewportSize.y = Math.floor(_maxTextureSize / shadowFrameExtents.y);
22399					_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
22400					shadow.mapSize.y = _viewportSize.y;
22401
22402				}
22403
22404			}
22405
22406			if (shadow.map === null || toVSM === true || fromVSM === true) {
22407
22408				const pars = (this.type !== VSMShadowMap) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {};
22409
22410				if (shadow.map !== null) {
22411
22412					shadow.map.dispose();
22413
22414				}
22415
22416				shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
22417				shadow.map.texture.name = light.name + '.shadowMap';
22418
22419				shadow.camera.updateProjectionMatrix();
22420
22421			}
22422
22423			_renderer.setRenderTarget(shadow.map);
22424			_renderer.clear();
22425
22426			const viewportCount = shadow.getViewportCount();
22427
vendor: 2,558 bytes, lines 22428-22522
22428			for (let vp = 0; vp < viewportCount; vp++) {
22429
22430				const viewport = shadow.getViewport(vp);
22431
22432				_viewport.set(
22433					_viewportSize.x * viewport.x,
22434					_viewportSize.y * viewport.y,
22435					_viewportSize.x * viewport.z,
22436					_viewportSize.y * viewport.w
22437				);
22438
22439				_state.viewport(_viewport);
22440
22441				shadow.updateMatrices(light, vp);
22442
22443				_frustum = shadow.getFrustum();
22444
22445				renderObject(scene, camera, shadow.camera, light, this.type);
22446
22447			}
22448
22449			// do blur pass for VSM
22450
22451			if (shadow.isPointLightShadow !== true && this.type === VSMShadowMap) {
22452
22453				VSMPass(shadow, camera);
22454
22455			}
22456
22457			shadow.needsUpdate = false;
22458
22459		}
22460
22461		_previousType = this.type;
22462
22463		scope.needsUpdate = false;
22464
22465		_renderer.setRenderTarget(currentRenderTarget, activeCubeFace, activeMipmapLevel);
22466
22467	};
22468
22469	function VSMPass(shadow, camera) {
22470
22471		const geometry = _objects.update(fullScreenMesh);
22472
22473		if (shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples) {
22474
22475			shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
22476			shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
22477
22478			shadowMaterialVertical.needsUpdate = true;
22479			shadowMaterialHorizontal.needsUpdate = true;
22480
22481		}
22482
22483		if (shadow.mapPass === null) {
22484
22485			shadow.mapPass = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y);
22486
22487		}
22488
22489		// vertical pass
22490
22491		shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
22492		shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
22493		shadowMaterialVertical.uniforms.radius.value = shadow.radius;
22494		_renderer.setRenderTarget(shadow.mapPass);
22495		_renderer.clear();
22496		_renderer.renderBufferDirect(camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null);
22497
22498		// horizontal pass
22499
22500		shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
22501		shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
22502		shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
22503		_renderer.setRenderTarget(shadow.map);
22504		_renderer.clear();
22505		_renderer.renderBufferDirect(camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null);
22506
22507	}
22508
22509	function getDepthMaterial(object, material, light, type) {
22510
22511		let result = null;
22512
22513		const customMaterial = (light.isPointLight === true) ? object.customDistanceMaterial : object.customDepthMaterial;
22514
22515		if (customMaterial !== undefined) {
22516
22517			result = customMaterial;
22518
22519		} else {
22520
22521			result = (light.isPointLight === true) ? _distanceMaterial : _depthMaterial;
22522
vendor: 123,361 bytes, lines 22523-27444
22523			if ((_renderer.localClippingEnabled && material.clipShadows === true && Array.isArray(material.clippingPlanes) && material.clippingPlanes.length !== 0) ||
22524				(material.displacementMap && material.displacementScale !== 0) ||
22525				(material.alphaMap && material.alphaTest > 0) ||
22526				(material.map && material.alphaTest > 0)) {
22527
22528				// in this case we need a unique material instance reflecting the
22529				// appropriate state
22530
22531				const keyA = result.uuid, keyB = material.uuid;
22532
22533				let materialsForVariant = _materialCache[keyA];
22534
22535				if (materialsForVariant === undefined) {
22536
22537					materialsForVariant = {};
22538					_materialCache[keyA] = materialsForVariant;
22539
22540				}
22541
22542				let cachedMaterial = materialsForVariant[keyB];
22543
22544				if (cachedMaterial === undefined) {
22545
22546					cachedMaterial = result.clone();
22547					materialsForVariant[keyB] = cachedMaterial;
22548					material.addEventListener('dispose', onMaterialDispose);
22549
22550				}
22551
22552				result = cachedMaterial;
22553
22554			}
22555
22556		}
22557
22558		result.visible = material.visible;
22559		result.wireframe = material.wireframe;
22560
22561		if (type === VSMShadowMap) {
22562
22563			result.side = (material.shadowSide !== null) ? material.shadowSide : material.side;
22564
22565		} else {
22566
22567			result.side = (material.shadowSide !== null) ? material.shadowSide : shadowSide[material.side];
22568
22569		}
22570
22571		result.alphaMap = material.alphaMap;
22572		result.alphaTest = material.alphaTest;
22573		result.map = material.map;
22574
22575		result.clipShadows = material.clipShadows;
22576		result.clippingPlanes = material.clippingPlanes;
22577		result.clipIntersection = material.clipIntersection;
22578
22579		result.displacementMap = material.displacementMap;
22580		result.displacementScale = material.displacementScale;
22581		result.displacementBias = material.displacementBias;
22582
22583		result.wireframeLinewidth = material.wireframeLinewidth;
22584		result.linewidth = material.linewidth;
22585
22586		if (light.isPointLight === true && result.isMeshDistanceMaterial === true) {
22587
22588			const materialProperties = _renderer.properties.get(result);
22589			materialProperties.light = light;
22590
22591		}
22592
22593		return result;
22594
22595	}
22596
22597	function renderObject(object, camera, shadowCamera, light, type) {
22598
22599		if (object.visible === false) return;
22600
22601		const visible = object.layers.test(camera.layers);
22602
22603		if (visible && (object.isMesh || object.isLine || object.isPoints)) {
22604
22605			if ((object.castShadow || (object.receiveShadow && type === VSMShadowMap)) && (!object.frustumCulled || _frustum.intersectsObject(object))) {
22606
22607				object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld);
22608
22609				const geometry = _objects.update(object);
22610				const material = object.material;
22611
22612				if (Array.isArray(material)) {
22613
22614					const groups = geometry.groups;
22615
22616					for (let k = 0, kl = groups.length; k < kl; k++) {
22617
22618						const group = groups[k];
22619						const groupMaterial = material[group.materialIndex];
22620
22621						if (groupMaterial && groupMaterial.visible) {
22622
22623							const depthMaterial = getDepthMaterial(object, groupMaterial, light, type);
22624
22625							object.onBeforeShadow(_renderer, object, camera, shadowCamera, geometry, depthMaterial, group);
22626
22627							_renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group);
22628
22629							object.onAfterShadow(_renderer, object, camera, shadowCamera, geometry, depthMaterial, group);
22630
22631						}
22632
22633					}
22634
22635				} else if (material.visible) {
22636
22637					const depthMaterial = getDepthMaterial(object, material, light, type);
22638
22639					object.onBeforeShadow(_renderer, object, camera, shadowCamera, geometry, depthMaterial, null);
22640
22641					_renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null);
22642
22643					object.onAfterShadow(_renderer, object, camera, shadowCamera, geometry, depthMaterial, null);
22644
22645				}
22646
22647			}
22648
22649		}
22650
22651		const children = object.children;
22652
22653		for (let i = 0, l = children.length; i < l; i++) {
22654
22655			renderObject(children[i], camera, shadowCamera, light, type);
22656
22657		}
22658
22659	}
22660
22661	function onMaterialDispose(event) {
22662
22663		const material = event.target;
22664
22665		material.removeEventListener('dispose', onMaterialDispose);
22666
22667		// make sure to remove the unique distance/depth materials used for shadow map rendering
22668
22669		for (const id in _materialCache) {
22670
22671			const cache = _materialCache[id];
22672
22673			const uuid = event.target.uuid;
22674
22675			if (uuid in cache) {
22676
22677				const shadowMaterial = cache[uuid];
22678				shadowMaterial.dispose();
22679				delete cache[uuid];
22680
22681			}
22682
22683		}
22684
22685	}
22686
22687}
22688
22689function WebGLState(gl, extensions, capabilities) {
22690
22691	const isWebGL2 = capabilities.isWebGL2;
22692
22693	function ColorBuffer() {
22694
22695		let locked = false;
22696
22697		const color = new Vector4();
22698		let currentColorMask = null;
22699		const currentColorClear = new Vector4(0, 0, 0, 0);
22700
22701		return {
22702
22703			setMask: function (colorMask) {
22704
22705				if (currentColorMask !== colorMask && !locked) {
22706
22707					gl.colorMask(colorMask, colorMask, colorMask, colorMask);
22708					currentColorMask = colorMask;
22709
22710				}
22711
22712			},
22713
22714			setLocked: function (lock) {
22715
22716				locked = lock;
22717
22718			},
22719
22720			setClear: function (r, g, b, a, premultipliedAlpha) {
22721
22722				if (premultipliedAlpha === true) {
22723
22724					r *= a; g *= a; b *= a;
22725
22726				}
22727
22728				color.set(r, g, b, a);
22729
22730				if (currentColorClear.equals(color) === false) {
22731
22732					gl.clearColor(r, g, b, a);
22733					currentColorClear.copy(color);
22734
22735				}
22736
22737			},
22738
22739			reset: function () {
22740
22741				locked = false;
22742
22743				currentColorMask = null;
22744				currentColorClear.set(- 1, 0, 0, 0); // set to invalid state
22745
22746			}
22747
22748		};
22749
22750	}
22751
22752	function DepthBuffer() {
22753
22754		let locked = false;
22755
22756		let currentDepthMask = null;
22757		let currentDepthFunc = null;
22758		let currentDepthClear = null;
22759
22760		return {
22761
22762			setTest: function (depthTest) {
22763
22764				if (depthTest) {
22765
22766					enable(gl.DEPTH_TEST);
22767
22768				} else {
22769
22770					disable(gl.DEPTH_TEST);
22771
22772				}
22773
22774			},
22775
22776			setMask: function (depthMask) {
22777
22778				if (currentDepthMask !== depthMask && !locked) {
22779
22780					gl.depthMask(depthMask);
22781					currentDepthMask = depthMask;
22782
22783				}
22784
22785			},
22786
22787			setFunc: function (depthFunc) {
22788
22789				if (currentDepthFunc !== depthFunc) {
22790
22791					switch (depthFunc) {
22792
22793						case NeverDepth:
22794
22795							gl.depthFunc(gl.NEVER);
22796							break;
22797
22798						case AlwaysDepth:
22799
22800							gl.depthFunc(gl.ALWAYS);
22801							break;
22802
22803						case LessDepth:
22804
22805							gl.depthFunc(gl.LESS);
22806							break;
22807
22808						case LessEqualDepth:
22809
22810							gl.depthFunc(gl.LEQUAL);
22811							break;
22812
22813						case EqualDepth:
22814
22815							gl.depthFunc(gl.EQUAL);
22816							break;
22817
22818						case GreaterEqualDepth:
22819
22820							gl.depthFunc(gl.GEQUAL);
22821							break;
22822
22823						case GreaterDepth:
22824
22825							gl.depthFunc(gl.GREATER);
22826							break;
22827
22828						case NotEqualDepth:
22829
22830							gl.depthFunc(gl.NOTEQUAL);
22831							break;
22832
22833						default:
22834
22835							gl.depthFunc(gl.LEQUAL);
22836
22837					}
22838
22839					currentDepthFunc = depthFunc;
22840
22841				}
22842
22843			},
22844
22845			setLocked: function (lock) {
22846
22847				locked = lock;
22848
22849			},
22850
22851			setClear: function (depth) {
22852
22853				if (currentDepthClear !== depth) {
22854
22855					gl.clearDepth(depth);
22856					currentDepthClear = depth;
22857
22858				}
22859
22860			},
22861
22862			reset: function () {
22863
22864				locked = false;
22865
22866				currentDepthMask = null;
22867				currentDepthFunc = null;
22868				currentDepthClear = null;
22869
22870			}
22871
22872		};
22873
22874	}
22875
22876	function StencilBuffer() {
22877
22878		let locked = false;
22879
22880		let currentStencilMask = null;
22881		let currentStencilFunc = null;
22882		let currentStencilRef = null;
22883		let currentStencilFuncMask = null;
22884		let currentStencilFail = null;
22885		let currentStencilZFail = null;
22886		let currentStencilZPass = null;
22887		let currentStencilClear = null;
22888
22889		return {
22890
22891			setTest: function (stencilTest) {
22892
22893				if (!locked) {
22894
22895					if (stencilTest) {
22896
22897						enable(gl.STENCIL_TEST);
22898
22899					} else {
22900
22901						disable(gl.STENCIL_TEST);
22902
22903					}
22904
22905				}
22906
22907			},
22908
22909			setMask: function (stencilMask) {
22910
22911				if (currentStencilMask !== stencilMask && !locked) {
22912
22913					gl.stencilMask(stencilMask);
22914					currentStencilMask = stencilMask;
22915
22916				}
22917
22918			},
22919
22920			setFunc: function (stencilFunc, stencilRef, stencilMask) {
22921
22922				if (currentStencilFunc !== stencilFunc ||
22923					currentStencilRef !== stencilRef ||
22924					currentStencilFuncMask !== stencilMask) {
22925
22926					gl.stencilFunc(stencilFunc, stencilRef, stencilMask);
22927
22928					currentStencilFunc = stencilFunc;
22929					currentStencilRef = stencilRef;
22930					currentStencilFuncMask = stencilMask;
22931
22932				}
22933
22934			},
22935
22936			setOp: function (stencilFail, stencilZFail, stencilZPass) {
22937
22938				if (currentStencilFail !== stencilFail ||
22939					currentStencilZFail !== stencilZFail ||
22940					currentStencilZPass !== stencilZPass) {
22941
22942					gl.stencilOp(stencilFail, stencilZFail, stencilZPass);
22943
22944					currentStencilFail = stencilFail;
22945					currentStencilZFail = stencilZFail;
22946					currentStencilZPass = stencilZPass;
22947
22948				}
22949
22950			},
22951
22952			setLocked: function (lock) {
22953
22954				locked = lock;
22955
22956			},
22957
22958			setClear: function (stencil) {
22959
22960				if (currentStencilClear !== stencil) {
22961
22962					gl.clearStencil(stencil);
22963					currentStencilClear = stencil;
22964
22965				}
22966
22967			},
22968
22969			reset: function () {
22970
22971				locked = false;
22972
22973				currentStencilMask = null;
22974				currentStencilFunc = null;
22975				currentStencilRef = null;
22976				currentStencilFuncMask = null;
22977				currentStencilFail = null;
22978				currentStencilZFail = null;
22979				currentStencilZPass = null;
22980				currentStencilClear = null;
22981
22982			}
22983
22984		};
22985
22986	}
22987
22988	//
22989
22990	const colorBuffer = new ColorBuffer();
22991	const depthBuffer = new DepthBuffer();
22992	const stencilBuffer = new StencilBuffer();
22993
22994	const uboBindings = new WeakMap();
22995	const uboProgramMap = new WeakMap();
22996
22997	let enabledCapabilities = {};
22998
22999	let currentBoundFramebuffers = {};
23000	let currentDrawbuffers = new WeakMap();
23001	let defaultDrawbuffers = [];
23002
23003	let currentProgram = null;
23004
23005	let currentBlendingEnabled = false;
23006	let currentBlending = null;
23007	let currentBlendEquation = null;
23008	let currentBlendSrc = null;
23009	let currentBlendDst = null;
23010	let currentBlendEquationAlpha = null;
23011	let currentBlendSrcAlpha = null;
23012	let currentBlendDstAlpha = null;
23013	let currentBlendColor = new Color(0, 0, 0);
23014	let currentBlendAlpha = 0;
23015	let currentPremultipledAlpha = false;
23016
23017	let currentFlipSided = null;
23018	let currentCullFace = null;
23019
23020	let currentLineWidth = null;
23021
23022	let currentPolygonOffsetFactor = null;
23023	let currentPolygonOffsetUnits = null;
23024
23025	const maxTextures = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);
23026
23027	let lineWidthAvailable = false;
23028	let version = 0;
23029	const glVersion = gl.getParameter(gl.VERSION);
23030
23031	if (glVersion.indexOf('WebGL') !== - 1) {
23032
23033		version = parseFloat(/^WebGL (\d)/.exec(glVersion)[1]);
23034		lineWidthAvailable = (version >= 1.0);
23035
23036	} else if (glVersion.indexOf('OpenGL ES') !== - 1) {
23037
23038		version = parseFloat(/^OpenGL ES (\d)/.exec(glVersion)[1]);
23039		lineWidthAvailable = (version >= 2.0);
23040
23041	}
23042
23043	let currentTextureSlot = null;
23044	let currentBoundTextures = {};
23045
23046	const scissorParam = gl.getParameter(gl.SCISSOR_BOX);
23047	const viewportParam = gl.getParameter(gl.VIEWPORT);
23048
23049	const currentScissor = new Vector4().fromArray(scissorParam);
23050	const currentViewport = new Vector4().fromArray(viewportParam);
23051
23052	function createTexture(type, target, count, dimensions) {
23053
23054		const data = new Uint8Array(4); // 4 is required to match default unpack alignment of 4.
23055		const texture = gl.createTexture();
23056
23057		gl.bindTexture(type, texture);
23058		gl.texParameteri(type, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
23059		gl.texParameteri(type, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
23060
23061		for (let i = 0; i < count; i++) {
23062
23063			if (isWebGL2 && (type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY)) {
23064
23065				gl.texImage3D(target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
23066
23067			} else {
23068
23069				gl.texImage2D(target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
23070
23071			}
23072
23073		}
23074
23075		return texture;
23076
23077	}
23078
23079	const emptyTextures = {};
23080	emptyTextures[gl.TEXTURE_2D] = createTexture(gl.TEXTURE_2D, gl.TEXTURE_2D, 1);
23081	emptyTextures[gl.TEXTURE_CUBE_MAP] = createTexture(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6);
23082
23083	if (isWebGL2) {
23084
23085		emptyTextures[gl.TEXTURE_2D_ARRAY] = createTexture(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1);
23086		emptyTextures[gl.TEXTURE_3D] = createTexture(gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1);
23087
23088	}
23089
23090	// init
23091
23092	colorBuffer.setClear(0, 0, 0, 1);
23093	depthBuffer.setClear(1);
23094	stencilBuffer.setClear(0);
23095
23096	enable(gl.DEPTH_TEST);
23097	depthBuffer.setFunc(LessEqualDepth);
23098
23099	setFlipSided(false);
23100	setCullFace(CullFaceBack);
23101	enable(gl.CULL_FACE);
23102
23103	setBlending(NoBlending);
23104
23105	//
23106
23107	function enable(id) {
23108
23109		if (enabledCapabilities[id] !== true) {
23110
23111			gl.enable(id);
23112			enabledCapabilities[id] = true;
23113
23114		}
23115
23116	}
23117
23118	function disable(id) {
23119
23120		if (enabledCapabilities[id] !== false) {
23121
23122			gl.disable(id);
23123			enabledCapabilities[id] = false;
23124
23125		}
23126
23127	}
23128
23129	function bindFramebuffer(target, framebuffer) {
23130
23131		if (currentBoundFramebuffers[target] !== framebuffer) {
23132
23133			gl.bindFramebuffer(target, framebuffer);
23134
23135			currentBoundFramebuffers[target] = framebuffer;
23136
23137			if (isWebGL2) {
23138
23139				// gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER
23140
23141				if (target === gl.DRAW_FRAMEBUFFER) {
23142
23143					currentBoundFramebuffers[gl.FRAMEBUFFER] = framebuffer;
23144
23145				}
23146
23147				if (target === gl.FRAMEBUFFER) {
23148
23149					currentBoundFramebuffers[gl.DRAW_FRAMEBUFFER] = framebuffer;
23150
23151				}
23152
23153			}
23154
23155			return true;
23156
23157		}
23158
23159		return false;
23160
23161	}
23162
23163	function drawBuffers(renderTarget, framebuffer) {
23164
23165		let drawBuffers = defaultDrawbuffers;
23166
23167		let needsUpdate = false;
23168
23169		if (renderTarget) {
23170
23171			drawBuffers = currentDrawbuffers.get(framebuffer);
23172
23173			if (drawBuffers === undefined) {
23174
23175				drawBuffers = [];
23176				currentDrawbuffers.set(framebuffer, drawBuffers);
23177
23178			}
23179
23180			if (renderTarget.isWebGLMultipleRenderTargets) {
23181
23182				const textures = renderTarget.texture;
23183
23184				if (drawBuffers.length !== textures.length || drawBuffers[0] !== gl.COLOR_ATTACHMENT0) {
23185
23186					for (let i = 0, il = textures.length; i < il; i++) {
23187
23188						drawBuffers[i] = gl.COLOR_ATTACHMENT0 + i;
23189
23190					}
23191
23192					drawBuffers.length = textures.length;
23193
23194					needsUpdate = true;
23195
23196				}
23197
23198			} else {
23199
23200				if (drawBuffers[0] !== gl.COLOR_ATTACHMENT0) {
23201
23202					drawBuffers[0] = gl.COLOR_ATTACHMENT0;
23203
23204					needsUpdate = true;
23205
23206				}
23207
23208			}
23209
23210		} else {
23211
23212			if (drawBuffers[0] !== gl.BACK) {
23213
23214				drawBuffers[0] = gl.BACK;
23215
23216				needsUpdate = true;
23217
23218			}
23219
23220		}
23221
23222		if (needsUpdate) {
23223
23224			if (capabilities.isWebGL2) {
23225
23226				gl.drawBuffers(drawBuffers);
23227
23228			} else {
23229
23230				extensions.get('WEBGL_draw_buffers').drawBuffersWEBGL(drawBuffers);
23231
23232			}
23233
23234		}
23235
23236
23237	}
23238
23239	function useProgram(program) {
23240
23241		if (currentProgram !== program) {
23242
23243			gl.useProgram(program);
23244
23245			currentProgram = program;
23246
23247			return true;
23248
23249		}
23250
23251		return false;
23252
23253	}
23254
23255	const equationToGL = {
23256		[AddEquation]: gl.FUNC_ADD,
23257		[SubtractEquation]: gl.FUNC_SUBTRACT,
23258		[ReverseSubtractEquation]: gl.FUNC_REVERSE_SUBTRACT
23259	};
23260
23261	if (isWebGL2) {
23262
23263		equationToGL[MinEquation] = gl.MIN;
23264		equationToGL[MaxEquation] = gl.MAX;
23265
23266	} else {
23267
23268		const extension = extensions.get('EXT_blend_minmax');
23269
23270		if (extension !== null) {
23271
23272			equationToGL[MinEquation] = extension.MIN_EXT;
23273			equationToGL[MaxEquation] = extension.MAX_EXT;
23274
23275		}
23276
23277	}
23278
23279	const factorToGL = {
23280		[ZeroFactor]: gl.ZERO,
23281		[OneFactor]: gl.ONE,
23282		[SrcColorFactor]: gl.SRC_COLOR,
23283		[SrcAlphaFactor]: gl.SRC_ALPHA,
23284		[SrcAlphaSaturateFactor]: gl.SRC_ALPHA_SATURATE,
23285		[DstColorFactor]: gl.DST_COLOR,
23286		[DstAlphaFactor]: gl.DST_ALPHA,
23287		[OneMinusSrcColorFactor]: gl.ONE_MINUS_SRC_COLOR,
23288		[OneMinusSrcAlphaFactor]: gl.ONE_MINUS_SRC_ALPHA,
23289		[OneMinusDstColorFactor]: gl.ONE_MINUS_DST_COLOR,
23290		[OneMinusDstAlphaFactor]: gl.ONE_MINUS_DST_ALPHA,
23291		[ConstantColorFactor]: gl.CONSTANT_COLOR,
23292		[OneMinusConstantColorFactor]: gl.ONE_MINUS_CONSTANT_COLOR,
23293		[ConstantAlphaFactor]: gl.CONSTANT_ALPHA,
23294		[OneMinusConstantAlphaFactor]: gl.ONE_MINUS_CONSTANT_ALPHA
23295	};
23296
23297	function setBlending(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha) {
23298
23299		if (blending === NoBlending) {
23300
23301			if (currentBlendingEnabled === true) {
23302
23303				disable(gl.BLEND);
23304				currentBlendingEnabled = false;
23305
23306			}
23307
23308			return;
23309
23310		}
23311
23312		if (currentBlendingEnabled === false) {
23313
23314			enable(gl.BLEND);
23315			currentBlendingEnabled = true;
23316
23317		}
23318
23319		if (blending !== CustomBlending) {
23320
23321			if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) {
23322
23323				if (currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation) {
23324
23325					gl.blendEquation(gl.FUNC_ADD);
23326
23327					currentBlendEquation = AddEquation;
23328					currentBlendEquationAlpha = AddEquation;
23329
23330				}
23331
23332				if (premultipliedAlpha) {
23333
23334					switch (blending) {
23335
23336						case NormalBlending:
23337							gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
23338							break;
23339
23340						case AdditiveBlending:
23341							gl.blendFunc(gl.ONE, gl.ONE);
23342							break;
23343
23344						case SubtractiveBlending:
23345							gl.blendFuncSeparate(gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE);
23346							break;
23347
23348						case MultiplyBlending:
23349							gl.blendFuncSeparate(gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA);
23350							break;
23351
23352						default:
23353							console.error('THREE.WebGLState: Invalid blending: ', blending);
23354							break;
23355
23356					}
23357
23358				} else {
23359
23360					switch (blending) {
23361
23362						case NormalBlending:
23363							gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
23364							break;
23365
23366						case AdditiveBlending:
23367							gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
23368							break;
23369
23370						case SubtractiveBlending:
23371							gl.blendFuncSeparate(gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE);
23372							break;
23373
23374						case MultiplyBlending:
23375							gl.blendFunc(gl.ZERO, gl.SRC_COLOR);
23376							break;
23377
23378						default:
23379							console.error('THREE.WebGLState: Invalid blending: ', blending);
23380							break;
23381
23382					}
23383
23384				}
23385
23386				currentBlendSrc = null;
23387				currentBlendDst = null;
23388				currentBlendSrcAlpha = null;
23389				currentBlendDstAlpha = null;
23390				currentBlendColor.set(0, 0, 0);
23391				currentBlendAlpha = 0;
23392
23393				currentBlending = blending;
23394				currentPremultipledAlpha = premultipliedAlpha;
23395
23396			}
23397
23398			return;
23399
23400		}
23401
23402		// custom blending
23403
23404		blendEquationAlpha = blendEquationAlpha || blendEquation;
23405		blendSrcAlpha = blendSrcAlpha || blendSrc;
23406		blendDstAlpha = blendDstAlpha || blendDst;
23407
23408		if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) {
23409
23410			gl.blendEquationSeparate(equationToGL[blendEquation], equationToGL[blendEquationAlpha]);
23411
23412			currentBlendEquation = blendEquation;
23413			currentBlendEquationAlpha = blendEquationAlpha;
23414
23415		}
23416
23417		if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) {
23418
23419			gl.blendFuncSeparate(factorToGL[blendSrc], factorToGL[blendDst], factorToGL[blendSrcAlpha], factorToGL[blendDstAlpha]);
23420
23421			currentBlendSrc = blendSrc;
23422			currentBlendDst = blendDst;
23423			currentBlendSrcAlpha = blendSrcAlpha;
23424			currentBlendDstAlpha = blendDstAlpha;
23425
23426		}
23427
23428		if (blendColor.equals(currentBlendColor) === false || blendAlpha !== currentBlendAlpha) {
23429
23430			gl.blendColor(blendColor.r, blendColor.g, blendColor.b, blendAlpha);
23431
23432			currentBlendColor.copy(blendColor);
23433			currentBlendAlpha = blendAlpha;
23434
23435		}
23436
23437		currentBlending = blending;
23438		currentPremultipledAlpha = false;
23439
23440	}
23441
23442	function setMaterial(material, frontFaceCW) {
23443
23444		material.side === DoubleSide
23445			? disable(gl.CULL_FACE)
23446			: enable(gl.CULL_FACE);
23447
23448		let flipSided = (material.side === BackSide);
23449		if (frontFaceCW) flipSided = !flipSided;
23450
23451		setFlipSided(flipSided);
23452
23453		(material.blending === NormalBlending && material.transparent === false)
23454			? setBlending(NoBlending)
23455			: setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha);
23456
23457		depthBuffer.setFunc(material.depthFunc);
23458		depthBuffer.setTest(material.depthTest);
23459		depthBuffer.setMask(material.depthWrite);
23460		colorBuffer.setMask(material.colorWrite);
23461
23462		const stencilWrite = material.stencilWrite;
23463		stencilBuffer.setTest(stencilWrite);
23464		if (stencilWrite) {
23465
23466			stencilBuffer.setMask(material.stencilWriteMask);
23467			stencilBuffer.setFunc(material.stencilFunc, material.stencilRef, material.stencilFuncMask);
23468			stencilBuffer.setOp(material.stencilFail, material.stencilZFail, material.stencilZPass);
23469
23470		}
23471
23472		setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits);
23473
23474		material.alphaToCoverage === true
23475			? enable(gl.SAMPLE_ALPHA_TO_COVERAGE)
23476			: disable(gl.SAMPLE_ALPHA_TO_COVERAGE);
23477
23478	}
23479
23480	//
23481
23482	function setFlipSided(flipSided) {
23483
23484		if (currentFlipSided !== flipSided) {
23485
23486			if (flipSided) {
23487
23488				gl.frontFace(gl.CW);
23489
23490			} else {
23491
23492				gl.frontFace(gl.CCW);
23493
23494			}
23495
23496			currentFlipSided = flipSided;
23497
23498		}
23499
23500	}
23501
23502	function setCullFace(cullFace) {
23503
23504		if (cullFace !== CullFaceNone) {
23505
23506			enable(gl.CULL_FACE);
23507
23508			if (cullFace !== currentCullFace) {
23509
23510				if (cullFace === CullFaceBack) {
23511
23512					gl.cullFace(gl.BACK);
23513
23514				} else if (cullFace === CullFaceFront) {
23515
23516					gl.cullFace(gl.FRONT);
23517
23518				} else {
23519
23520					gl.cullFace(gl.FRONT_AND_BACK);
23521
23522				}
23523
23524			}
23525
23526		} else {
23527
23528			disable(gl.CULL_FACE);
23529
23530		}
23531
23532		currentCullFace = cullFace;
23533
23534	}
23535
23536	function setLineWidth(width) {
23537
23538		if (width !== currentLineWidth) {
23539
23540			if (lineWidthAvailable) gl.lineWidth(width);
23541
23542			currentLineWidth = width;
23543
23544		}
23545
23546	}
23547
23548	function setPolygonOffset(polygonOffset, factor, units) {
23549
23550		if (polygonOffset) {
23551
23552			enable(gl.POLYGON_OFFSET_FILL);
23553
23554			if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) {
23555
23556				gl.polygonOffset(factor, units);
23557
23558				currentPolygonOffsetFactor = factor;
23559				currentPolygonOffsetUnits = units;
23560
23561			}
23562
23563		} else {
23564
23565			disable(gl.POLYGON_OFFSET_FILL);
23566
23567		}
23568
23569	}
23570
23571	function setScissorTest(scissorTest) {
23572
23573		if (scissorTest) {
23574
23575			enable(gl.SCISSOR_TEST);
23576
23577		} else {
23578
23579			disable(gl.SCISSOR_TEST);
23580
23581		}
23582
23583	}
23584
23585	// texture
23586
23587	function activeTexture(webglSlot) {
23588
23589		if (webglSlot === undefined) webglSlot = gl.TEXTURE0 + maxTextures - 1;
23590
23591		if (currentTextureSlot !== webglSlot) {
23592
23593			gl.activeTexture(webglSlot);
23594			currentTextureSlot = webglSlot;
23595
23596		}
23597
23598	}
23599
23600	function bindTexture(webglType, webglTexture, webglSlot) {
23601
23602		if (webglSlot === undefined) {
23603
23604			if (currentTextureSlot === null) {
23605
23606				webglSlot = gl.TEXTURE0 + maxTextures - 1;
23607
23608			} else {
23609
23610				webglSlot = currentTextureSlot;
23611
23612			}
23613
23614		}
23615
23616		let boundTexture = currentBoundTextures[webglSlot];
23617
23618		if (boundTexture === undefined) {
23619
23620			boundTexture = { type: undefined, texture: undefined };
23621			currentBoundTextures[webglSlot] = boundTexture;
23622
23623		}
23624
23625		if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) {
23626
23627			if (currentTextureSlot !== webglSlot) {
23628
23629				gl.activeTexture(webglSlot);
23630				currentTextureSlot = webglSlot;
23631
23632			}
23633
23634			gl.bindTexture(webglType, webglTexture || emptyTextures[webglType]);
23635
23636			boundTexture.type = webglType;
23637			boundTexture.texture = webglTexture;
23638
23639		}
23640
23641	}
23642
23643	function unbindTexture() {
23644
23645		const boundTexture = currentBoundTextures[currentTextureSlot];
23646
23647		if (boundTexture !== undefined && boundTexture.type !== undefined) {
23648
23649			gl.bindTexture(boundTexture.type, null);
23650
23651			boundTexture.type = undefined;
23652			boundTexture.texture = undefined;
23653
23654		}
23655
23656	}
23657
23658	function compressedTexImage2D() {
23659
23660		try {
23661
23662			gl.compressedTexImage2D.apply(gl, arguments);
23663
23664		} catch (error) {
23665
23666			console.error('THREE.WebGLState:', error);
23667
23668		}
23669
23670	}
23671
23672	function compressedTexImage3D() {
23673
23674		try {
23675
23676			gl.compressedTexImage3D.apply(gl, arguments);
23677
23678		} catch (error) {
23679
23680			console.error('THREE.WebGLState:', error);
23681
23682		}
23683
23684	}
23685
23686	function texSubImage2D() {
23687
23688		try {
23689
23690			gl.texSubImage2D.apply(gl, arguments);
23691
23692		} catch (error) {
23693
23694			console.error('THREE.WebGLState:', error);
23695
23696		}
23697
23698	}
23699
23700	function texSubImage3D() {
23701
23702		try {
23703
23704			gl.texSubImage3D.apply(gl, arguments);
23705
23706		} catch (error) {
23707
23708			console.error('THREE.WebGLState:', error);
23709
23710		}
23711
23712	}
23713
23714	function compressedTexSubImage2D() {
23715
23716		try {
23717
23718			gl.compressedTexSubImage2D.apply(gl, arguments);
23719
23720		} catch (error) {
23721
23722			console.error('THREE.WebGLState:', error);
23723
23724		}
23725
23726	}
23727
23728	function compressedTexSubImage3D() {
23729
23730		try {
23731
23732			gl.compressedTexSubImage3D.apply(gl, arguments);
23733
23734		} catch (error) {
23735
23736			console.error('THREE.WebGLState:', error);
23737
23738		}
23739
23740	}
23741
23742	function texStorage2D() {
23743
23744		try {
23745
23746			gl.texStorage2D.apply(gl, arguments);
23747
23748		} catch (error) {
23749
23750			console.error('THREE.WebGLState:', error);
23751
23752		}
23753
23754	}
23755
23756	function texStorage3D() {
23757
23758		try {
23759
23760			gl.texStorage3D.apply(gl, arguments);
23761
23762		} catch (error) {
23763
23764			console.error('THREE.WebGLState:', error);
23765
23766		}
23767
23768	}
23769
23770	function texImage2D() {
23771
23772		try {
23773
23774			gl.texImage2D.apply(gl, arguments);
23775
23776		} catch (error) {
23777
23778			console.error('THREE.WebGLState:', error);
23779
23780		}
23781
23782	}
23783
23784	function texImage3D() {
23785
23786		try {
23787
23788			gl.texImage3D.apply(gl, arguments);
23789
23790		} catch (error) {
23791
23792			console.error('THREE.WebGLState:', error);
23793
23794		}
23795
23796	}
23797
23798	//
23799
23800	function scissor(scissor) {
23801
23802		if (currentScissor.equals(scissor) === false) {
23803
23804			gl.scissor(scissor.x, scissor.y, scissor.z, scissor.w);
23805			currentScissor.copy(scissor);
23806
23807		}
23808
23809	}
23810
23811	function viewport(viewport) {
23812
23813		if (currentViewport.equals(viewport) === false) {
23814
23815			gl.viewport(viewport.x, viewport.y, viewport.z, viewport.w);
23816			currentViewport.copy(viewport);
23817
23818		}
23819
23820	}
23821
23822	function updateUBOMapping(uniformsGroup, program) {
23823
23824		let mapping = uboProgramMap.get(program);
23825
23826		if (mapping === undefined) {
23827
23828			mapping = new WeakMap();
23829
23830			uboProgramMap.set(program, mapping);
23831
23832		}
23833
23834		let blockIndex = mapping.get(uniformsGroup);
23835
23836		if (blockIndex === undefined) {
23837
23838			blockIndex = gl.getUniformBlockIndex(program, uniformsGroup.name);
23839
23840			mapping.set(uniformsGroup, blockIndex);
23841
23842		}
23843
23844	}
23845
23846	function uniformBlockBinding(uniformsGroup, program) {
23847
23848		const mapping = uboProgramMap.get(program);
23849		const blockIndex = mapping.get(uniformsGroup);
23850
23851		if (uboBindings.get(program) !== blockIndex) {
23852
23853			// bind shader specific block index to global block point
23854			gl.uniformBlockBinding(program, blockIndex, uniformsGroup.__bindingPointIndex);
23855
23856			uboBindings.set(program, blockIndex);
23857
23858		}
23859
23860	}
23861
23862	//
23863
23864	function reset() {
23865
23866		// reset state
23867
23868		gl.disable(gl.BLEND);
23869		gl.disable(gl.CULL_FACE);
23870		gl.disable(gl.DEPTH_TEST);
23871		gl.disable(gl.POLYGON_OFFSET_FILL);
23872		gl.disable(gl.SCISSOR_TEST);
23873		gl.disable(gl.STENCIL_TEST);
23874		gl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE);
23875
23876		gl.blendEquation(gl.FUNC_ADD);
23877		gl.blendFunc(gl.ONE, gl.ZERO);
23878		gl.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ZERO);
23879		gl.blendColor(0, 0, 0, 0);
23880
23881		gl.colorMask(true, true, true, true);
23882		gl.clearColor(0, 0, 0, 0);
23883
23884		gl.depthMask(true);
23885		gl.depthFunc(gl.LESS);
23886		gl.clearDepth(1);
23887
23888		gl.stencilMask(0xffffffff);
23889		gl.stencilFunc(gl.ALWAYS, 0, 0xffffffff);
23890		gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
23891		gl.clearStencil(0);
23892
23893		gl.cullFace(gl.BACK);
23894		gl.frontFace(gl.CCW);
23895
23896		gl.polygonOffset(0, 0);
23897
23898		gl.activeTexture(gl.TEXTURE0);
23899
23900		gl.bindFramebuffer(gl.FRAMEBUFFER, null);
23901
23902		if (isWebGL2 === true) {
23903
23904			gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
23905			gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
23906
23907		}
23908
23909		gl.useProgram(null);
23910
23911		gl.lineWidth(1);
23912
23913		gl.scissor(0, 0, gl.canvas.width, gl.canvas.height);
23914		gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
23915
23916		// reset internals
23917
23918		enabledCapabilities = {};
23919
23920		currentTextureSlot = null;
23921		currentBoundTextures = {};
23922
23923		currentBoundFramebuffers = {};
23924		currentDrawbuffers = new WeakMap();
23925		defaultDrawbuffers = [];
23926
23927		currentProgram = null;
23928
23929		currentBlendingEnabled = false;
23930		currentBlending = null;
23931		currentBlendEquation = null;
23932		currentBlendSrc = null;
23933		currentBlendDst = null;
23934		currentBlendEquationAlpha = null;
23935		currentBlendSrcAlpha = null;
23936		currentBlendDstAlpha = null;
23937		currentBlendColor = new Color(0, 0, 0);
23938		currentBlendAlpha = 0;
23939		currentPremultipledAlpha = false;
23940
23941		currentFlipSided = null;
23942		currentCullFace = null;
23943
23944		currentLineWidth = null;
23945
23946		currentPolygonOffsetFactor = null;
23947		currentPolygonOffsetUnits = null;
23948
23949		currentScissor.set(0, 0, gl.canvas.width, gl.canvas.height);
23950		currentViewport.set(0, 0, gl.canvas.width, gl.canvas.height);
23951
23952		colorBuffer.reset();
23953		depthBuffer.reset();
23954		stencilBuffer.reset();
23955
23956	}
23957
23958	return {
23959
23960		buffers: {
23961			color: colorBuffer,
23962			depth: depthBuffer,
23963			stencil: stencilBuffer
23964		},
23965
23966		enable: enable,
23967		disable: disable,
23968
23969		bindFramebuffer: bindFramebuffer,
23970		drawBuffers: drawBuffers,
23971
23972		useProgram: useProgram,
23973
23974		setBlending: setBlending,
23975		setMaterial: setMaterial,
23976
23977		setFlipSided: setFlipSided,
23978		setCullFace: setCullFace,
23979
23980		setLineWidth: setLineWidth,
23981		setPolygonOffset: setPolygonOffset,
23982
23983		setScissorTest: setScissorTest,
23984
23985		activeTexture: activeTexture,
23986		bindTexture: bindTexture,
23987		unbindTexture: unbindTexture,
23988		compressedTexImage2D: compressedTexImage2D,
23989		compressedTexImage3D: compressedTexImage3D,
23990		texImage2D: texImage2D,
23991		texImage3D: texImage3D,
23992
23993		updateUBOMapping: updateUBOMapping,
23994		uniformBlockBinding: uniformBlockBinding,
23995
23996		texStorage2D: texStorage2D,
23997		texStorage3D: texStorage3D,
23998		texSubImage2D: texSubImage2D,
23999		texSubImage3D: texSubImage3D,
24000		compressedTexSubImage2D: compressedTexSubImage2D,
24001		compressedTexSubImage3D: compressedTexSubImage3D,
24002
24003		scissor: scissor,
24004		viewport: viewport,
24005
24006		reset: reset
24007
24008	};
24009
24010}
24011
24012function WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info) {
24013
24014	const isWebGL2 = capabilities.isWebGL2;
24015	const multisampledRTTExt = extensions.has('WEBGL_multisampled_render_to_texture') ? extensions.get('WEBGL_multisampled_render_to_texture') : null;
24016	const supportsInvalidateFramebuffer = typeof navigator === 'undefined' ? false : /OculusBrowser/g.test(navigator.userAgent);
24017
24018	const _videoTextures = new WeakMap();
24019	let _canvas;
24020
24021	const _sources = new WeakMap(); // maps WebglTexture objects to instances of Source
24022
24023	// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,
24024	// also OffscreenCanvas.getContext("webgl"), but not OffscreenCanvas.getContext("2d")!
24025	// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).
24026
24027	let useOffscreenCanvas = false;
24028
24029	try {
24030
24031		useOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'
24032			// eslint-disable-next-line compat/compat
24033			&& (new OffscreenCanvas(1, 1).getContext('2d')) !== null;
24034
24035	} catch (err) {
24036
24037		// Ignore any errors
24038
24039	}
24040
24041	function createCanvas(width, height) {
24042
24043		// Use OffscreenCanvas when available. Specially needed in web workers
24044
24045		return useOffscreenCanvas ?
24046			// eslint-disable-next-line compat/compat
24047			new OffscreenCanvas(width, height) : createElementNS('canvas');
24048
24049	}
24050
24051	function resizeImage(image, needsPowerOfTwo, needsNewCanvas, maxSize) {
24052
24053		let scale = 1;
24054
24055		// handle case if texture exceeds max size
24056
24057		if (image.width > maxSize || image.height > maxSize) {
24058
24059			scale = maxSize / Math.max(image.width, image.height);
24060
24061		}
24062
24063		// only perform resize if necessary
24064
24065		if (scale < 1 || needsPowerOfTwo === true) {
24066
24067			// only perform resize for certain image types
24068
24069			if ((typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement) ||
24070				(typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement) ||
24071				(typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap)) {
24072
24073				const floor = needsPowerOfTwo ? floorPowerOfTwo : Math.floor;
24074
24075				const width = floor(scale * image.width);
24076				const height = floor(scale * image.height);
24077
24078				if (_canvas === undefined) _canvas = createCanvas(width, height);
24079
24080				// cube textures can't reuse the same canvas
24081
24082				const canvas = needsNewCanvas ? createCanvas(width, height) : _canvas;
24083
24084				canvas.width = width;
24085				canvas.height = height;
24086
24087				const context = canvas.getContext('2d');
24088				context.drawImage(image, 0, 0, width, height);
24089
24090				console.warn('THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').');
24091
24092				return canvas;
24093
24094			} else {
24095
24096				if ('data' in image) {
24097
24098					console.warn('THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').');
24099
24100				}
24101
24102				return image;
24103
24104			}
24105
24106		}
24107
24108		return image;
24109
24110	}
24111
24112	function isPowerOfTwo$1(image) {
24113
24114		return isPowerOfTwo(image.width) && isPowerOfTwo(image.height);
24115
24116	}
24117
24118	function textureNeedsPowerOfTwo(texture) {
24119
24120		if (isWebGL2) return false;
24121
24122		return (texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping) ||
24123			(texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter);
24124
24125	}
24126
24127	function textureNeedsGenerateMipmaps(texture, supportsMips) {
24128
24129		return texture.generateMipmaps && supportsMips &&
24130			texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;
24131
24132	}
24133
24134	function generateMipmap(target) {
24135
24136		_gl.generateMipmap(target);
24137
24138	}
24139
24140	function getInternalFormat(internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false) {
24141
24142		if (isWebGL2 === false) return glFormat;
24143
24144		if (internalFormatName !== null) {
24145
24146			if (_gl[internalFormatName] !== undefined) return _gl[internalFormatName];
24147
24148			console.warn('THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'');
24149
24150		}
24151
24152		let internalFormat = glFormat;
24153
24154		if (glFormat === _gl.RED) {
24155
24156			if (glType === _gl.FLOAT) internalFormat = _gl.R32F;
24157			if (glType === _gl.HALF_FLOAT) internalFormat = _gl.R16F;
24158			if (glType === _gl.UNSIGNED_BYTE) internalFormat = _gl.R8;
24159
24160		}
24161
24162		if (glFormat === _gl.RED_INTEGER) {
24163
24164			if (glType === _gl.UNSIGNED_BYTE) internalFormat = _gl.R8UI;
24165			if (glType === _gl.UNSIGNED_SHORT) internalFormat = _gl.R16UI;
24166			if (glType === _gl.UNSIGNED_INT) internalFormat = _gl.R32UI;
24167			if (glType === _gl.BYTE) internalFormat = _gl.R8I;
24168			if (glType === _gl.SHORT) internalFormat = _gl.R16I;
24169			if (glType === _gl.INT) internalFormat = _gl.R32I;
24170
24171		}
24172
24173		if (glFormat === _gl.RG) {
24174
24175			if (glType === _gl.FLOAT) internalFormat = _gl.RG32F;
24176			if (glType === _gl.HALF_FLOAT) internalFormat = _gl.RG16F;
24177			if (glType === _gl.UNSIGNED_BYTE) internalFormat = _gl.RG8;
24178
24179		}
24180
24181		if (glFormat === _gl.RGBA) {
24182
24183			const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer(colorSpace);
24184
24185			if (glType === _gl.FLOAT) internalFormat = _gl.RGBA32F;
24186			if (glType === _gl.HALF_FLOAT) internalFormat = _gl.RGBA16F;
24187			if (glType === _gl.UNSIGNED_BYTE) internalFormat = (transfer === SRGBTransfer) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8;
24188			if (glType === _gl.UNSIGNED_SHORT_4_4_4_4) internalFormat = _gl.RGBA4;
24189			if (glType === _gl.UNSIGNED_SHORT_5_5_5_1) internalFormat = _gl.RGB5_A1;
24190
24191		}
24192
24193		if (internalFormat === _gl.R16F || internalFormat === _gl.R32F ||
24194			internalFormat === _gl.RG16F || internalFormat === _gl.RG32F ||
24195			internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F) {
24196
24197			extensions.get('EXT_color_buffer_float');
24198
24199		}
24200
24201		return internalFormat;
24202
24203	}
24204
24205	function getMipLevels(texture, image, supportsMips) {
24206
24207		if (textureNeedsGenerateMipmaps(texture, supportsMips) === true || (texture.isFramebufferTexture && texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter)) {
24208
24209			return Math.log2(Math.max(image.width, image.height)) + 1;
24210
24211		} else if (texture.mipmaps !== undefined && texture.mipmaps.length > 0) {
24212
24213			// user-defined mipmaps
24214
24215			return texture.mipmaps.length;
24216
24217		} else if (texture.isCompressedTexture && Array.isArray(texture.image)) {
24218
24219			return image.mipmaps.length;
24220
24221		} else {
24222
24223			// texture without mipmaps (only base level)
24224
24225			return 1;
24226
24227		}
24228
24229	}
24230
24231	// Fallback filters for non-power-of-2 textures
24232
24233	function filterFallback(f) {
24234
24235		if (f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter) {
24236
24237			return _gl.NEAREST;
24238
24239		}
24240
24241		return _gl.LINEAR;
24242
24243	}
24244
24245	//
24246
24247	function onTextureDispose(event) {
24248
24249		const texture = event.target;
24250
24251		texture.removeEventListener('dispose', onTextureDispose);
24252
24253		deallocateTexture(texture);
24254
24255		if (texture.isVideoTexture) {
24256
24257			_videoTextures.delete(texture);
24258
24259		}
24260
24261	}
24262
24263	function onRenderTargetDispose(event) {
24264
24265		const renderTarget = event.target;
24266
24267		renderTarget.removeEventListener('dispose', onRenderTargetDispose);
24268
24269		deallocateRenderTarget(renderTarget);
24270
24271	}
24272
24273	//
24274
24275	function deallocateTexture(texture) {
24276
24277		const textureProperties = properties.get(texture);
24278
24279		if (textureProperties.__webglInit === undefined) return;
24280
24281		// check if it's necessary to remove the WebGLTexture object
24282
24283		const source = texture.source;
24284		const webglTextures = _sources.get(source);
24285
24286		if (webglTextures) {
24287
24288			const webglTexture = webglTextures[textureProperties.__cacheKey];
24289			webglTexture.usedTimes--;
24290
24291			// the WebGLTexture object is not used anymore, remove it
24292
24293			if (webglTexture.usedTimes === 0) {
24294
24295				deleteTexture(texture);
24296
24297			}
24298
24299			// remove the weak map entry if no WebGLTexture uses the source anymore
24300
24301			if (Object.keys(webglTextures).length === 0) {
24302
24303				_sources.delete(source);
24304
24305			}
24306
24307		}
24308
24309		properties.remove(texture);
24310
24311	}
24312
24313	function deleteTexture(texture) {
24314
24315		const textureProperties = properties.get(texture);
24316		_gl.deleteTexture(textureProperties.__webglTexture);
24317
24318		const source = texture.source;
24319		const webglTextures = _sources.get(source);
24320		delete webglTextures[textureProperties.__cacheKey];
24321
24322		info.memory.textures--;
24323
24324	}
24325
24326	function deallocateRenderTarget(renderTarget) {
24327
24328		const texture = renderTarget.texture;
24329
24330		const renderTargetProperties = properties.get(renderTarget);
24331		const textureProperties = properties.get(texture);
24332
24333		if (textureProperties.__webglTexture !== undefined) {
24334
24335			_gl.deleteTexture(textureProperties.__webglTexture);
24336
24337			info.memory.textures--;
24338
24339		}
24340
24341		if (renderTarget.depthTexture) {
24342
24343			renderTarget.depthTexture.dispose();
24344
24345		}
24346
24347		if (renderTarget.isWebGLCubeRenderTarget) {
24348
24349			for (let i = 0; i < 6; i++) {
24350
24351				if (Array.isArray(renderTargetProperties.__webglFramebuffer[i])) {
24352
24353					for (let level = 0; level < renderTargetProperties.__webglFramebuffer[i].length; level++) _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i][level]);
24354
24355				} else {
24356
24357					_gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i]);
24358
24359				}
24360
24361				if (renderTargetProperties.__webglDepthbuffer) _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[i]);
24362
24363			}
24364
24365		} else {
24366
24367			if (Array.isArray(renderTargetProperties.__webglFramebuffer)) {
24368
24369				for (let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level++) _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[level]);
24370
24371			} else {
24372
24373				_gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer);
24374
24375			}
24376
24377			if (renderTargetProperties.__webglDepthbuffer) _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer);
24378			if (renderTargetProperties.__webglMultisampledFramebuffer) _gl.deleteFramebuffer(renderTargetProperties.__webglMultisampledFramebuffer);
24379
24380			if (renderTargetProperties.__webglColorRenderbuffer) {
24381
24382				for (let i = 0; i < renderTargetProperties.__webglColorRenderbuffer.length; i++) {
24383
24384					if (renderTargetProperties.__webglColorRenderbuffer[i]) _gl.deleteRenderbuffer(renderTargetProperties.__webglColorRenderbuffer[i]);
24385
24386				}
24387
24388			}
24389
24390			if (renderTargetProperties.__webglDepthRenderbuffer) _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthRenderbuffer);
24391
24392		}
24393
24394		if (renderTarget.isWebGLMultipleRenderTargets) {
24395
24396			for (let i = 0, il = texture.length; i < il; i++) {
24397
24398				const attachmentProperties = properties.get(texture[i]);
24399
24400				if (attachmentProperties.__webglTexture) {
24401
24402					_gl.deleteTexture(attachmentProperties.__webglTexture);
24403
24404					info.memory.textures--;
24405
24406				}
24407
24408				properties.remove(texture[i]);
24409
24410			}
24411
24412		}
24413
24414		properties.remove(texture);
24415		properties.remove(renderTarget);
24416
24417	}
24418
24419	//
24420
24421	let textureUnits = 0;
24422
24423	function resetTextureUnits() {
24424
24425		textureUnits = 0;
24426
24427	}
24428
24429	function allocateTextureUnit() {
24430
24431		const textureUnit = textureUnits;
24432
24433		if (textureUnit >= capabilities.maxTextures) {
24434
24435			console.warn('THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures);
24436
24437		}
24438
24439		textureUnits += 1;
24440
24441		return textureUnit;
24442
24443	}
24444
24445	function getTextureCacheKey(texture) {
24446
24447		const array = [];
24448
24449		array.push(texture.wrapS);
24450		array.push(texture.wrapT);
24451		array.push(texture.wrapR || 0);
24452		array.push(texture.magFilter);
24453		array.push(texture.minFilter);
24454		array.push(texture.anisotropy);
24455		array.push(texture.internalFormat);
24456		array.push(texture.format);
24457		array.push(texture.type);
24458		array.push(texture.generateMipmaps);
24459		array.push(texture.premultiplyAlpha);
24460		array.push(texture.flipY);
24461		array.push(texture.unpackAlignment);
24462		array.push(texture.colorSpace);
24463
24464		return array.join();
24465
24466	}
24467
24468	//
24469
24470	function setTexture2D(texture, slot) {
24471
24472		const textureProperties = properties.get(texture);
24473
24474		if (texture.isVideoTexture) updateVideoTexture(texture);
24475
24476		if (texture.isRenderTargetTexture === false && texture.version > 0 && textureProperties.__version !== texture.version) {
24477
24478			const image = texture.image;
24479
24480			if (image === null) {
24481
24482				console.warn('THREE.WebGLRenderer: Texture marked for update but no image data found.');
24483
24484			} else if (image.complete === false) {
24485
24486				console.warn('THREE.WebGLRenderer: Texture marked for update but image is incomplete');
24487
24488			} else {
24489
24490				uploadTexture(textureProperties, texture, slot);
24491				return;
24492
24493			}
24494
24495		}
24496
24497		state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot);
24498
24499	}
24500
24501	function setTexture2DArray(texture, slot) {
24502
24503		const textureProperties = properties.get(texture);
24504
24505		if (texture.version > 0 && textureProperties.__version !== texture.version) {
24506
24507			uploadTexture(textureProperties, texture, slot);
24508			return;
24509
24510		}
24511
24512		state.bindTexture(_gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot);
24513
24514	}
24515
24516	function setTexture3D(texture, slot) {
24517
24518		const textureProperties = properties.get(texture);
24519
24520		if (texture.version > 0 && textureProperties.__version !== texture.version) {
24521
24522			uploadTexture(textureProperties, texture, slot);
24523			return;
24524
24525		}
24526
24527		state.bindTexture(_gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot);
24528
24529	}
24530
24531	function setTextureCube(texture, slot) {
24532
24533		const textureProperties = properties.get(texture);
24534
24535		if (texture.version > 0 && textureProperties.__version !== texture.version) {
24536
24537			uploadCubeTexture(textureProperties, texture, slot);
24538			return;
24539
24540		}
24541
24542		state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot);
24543
24544	}
24545
24546	const wrappingToGL = {
24547		[RepeatWrapping]: _gl.REPEAT,
24548		[ClampToEdgeWrapping]: _gl.CLAMP_TO_EDGE,
24549		[MirroredRepeatWrapping]: _gl.MIRRORED_REPEAT
24550	};
24551
24552	const filterToGL = {
24553		[NearestFilter]: _gl.NEAREST,
24554		[NearestMipmapNearestFilter]: _gl.NEAREST_MIPMAP_NEAREST,
24555		[NearestMipmapLinearFilter]: _gl.NEAREST_MIPMAP_LINEAR,
24556
24557		[LinearFilter]: _gl.LINEAR,
24558		[LinearMipmapNearestFilter]: _gl.LINEAR_MIPMAP_NEAREST,
24559		[LinearMipmapLinearFilter]: _gl.LINEAR_MIPMAP_LINEAR
24560	};
24561
24562	const compareToGL = {
24563		[NeverCompare]: _gl.NEVER,
24564		[AlwaysCompare]: _gl.ALWAYS,
24565		[LessCompare]: _gl.LESS,
24566		[LessEqualCompare]: _gl.LEQUAL,
24567		[EqualCompare]: _gl.EQUAL,
24568		[GreaterEqualCompare]: _gl.GEQUAL,
24569		[GreaterCompare]: _gl.GREATER,
24570		[NotEqualCompare]: _gl.NOTEQUAL
24571	};
24572
24573	function setTextureParameters(textureType, texture, supportsMips) {
24574
24575		if (supportsMips) {
24576
24577			_gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[texture.wrapS]);
24578			_gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[texture.wrapT]);
24579
24580			if (textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) {
24581
24582				_gl.texParameteri(textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[texture.wrapR]);
24583
24584			}
24585
24586			_gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[texture.magFilter]);
24587			_gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[texture.minFilter]);
24588
24589		} else {
24590
24591			_gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE);
24592			_gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE);
24593
24594			if (textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY) {
24595
24596				_gl.texParameteri(textureType, _gl.TEXTURE_WRAP_R, _gl.CLAMP_TO_EDGE);
24597
24598			}
24599
24600			if (texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping) {
24601
24602				console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.');
24603
24604			}
24605
24606			_gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, filterFallback(texture.magFilter));
24607			_gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, filterFallback(texture.minFilter));
24608
24609			if (texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter) {
24610
24611				console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.');
24612
24613			}
24614
24615		}
24616
24617		if (texture.compareFunction) {
24618
24619			_gl.texParameteri(textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE);
24620			_gl.texParameteri(textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[texture.compareFunction]);
24621
24622		}
24623
24624		if (extensions.has('EXT_texture_filter_anisotropic') === true) {
24625
24626			const extension = extensions.get('EXT_texture_filter_anisotropic');
24627
24628			if (texture.magFilter === NearestFilter) return;
24629			if (texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter) return;
24630			if (texture.type === FloatType && extensions.has('OES_texture_float_linear') === false) return; // verify extension for WebGL 1 and WebGL 2
24631			if (isWebGL2 === false && (texture.type === HalfFloatType && extensions.has('OES_texture_half_float_linear') === false)) return; // verify extension for WebGL 1 only
24632
24633			if (texture.anisotropy > 1 || properties.get(texture).__currentAnisotropy) {
24634
24635				_gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropy, capabilities.getMaxAnisotropy()));
24636				properties.get(texture).__currentAnisotropy = texture.anisotropy;
24637
24638			}
24639
24640		}
24641
24642	}
24643
24644	function initTexture(textureProperties, texture) {
24645
24646		let forceUpload = false;
24647
24648		if (textureProperties.__webglInit === undefined) {
24649
24650			textureProperties.__webglInit = true;
24651
24652			texture.addEventListener('dispose', onTextureDispose);
24653
24654		}
24655
24656		// create Source <-> WebGLTextures mapping if necessary
24657
24658		const source = texture.source;
24659		let webglTextures = _sources.get(source);
24660
24661		if (webglTextures === undefined) {
24662
24663			webglTextures = {};
24664			_sources.set(source, webglTextures);
24665
24666		}
24667
24668		// check if there is already a WebGLTexture object for the given texture parameters
24669
24670		const textureCacheKey = getTextureCacheKey(texture);
24671
24672		if (textureCacheKey !== textureProperties.__cacheKey) {
24673
24674			// if not, create a new instance of WebGLTexture
24675
24676			if (webglTextures[textureCacheKey] === undefined) {
24677
24678				// create new entry
24679
24680				webglTextures[textureCacheKey] = {
24681					texture: _gl.createTexture(),
24682					usedTimes: 0
24683				};
24684
24685				info.memory.textures++;
24686
24687				// when a new instance of WebGLTexture was created, a texture upload is required
24688				// even if the image contents are identical
24689
24690				forceUpload = true;
24691
24692			}
24693
24694			webglTextures[textureCacheKey].usedTimes++;
24695
24696			// every time the texture cache key changes, it's necessary to check if an instance of
24697			// WebGLTexture can be deleted in order to avoid a memory leak.
24698
24699			const webglTexture = webglTextures[textureProperties.__cacheKey];
24700
24701			if (webglTexture !== undefined) {
24702
24703				webglTextures[textureProperties.__cacheKey].usedTimes--;
24704
24705				if (webglTexture.usedTimes === 0) {
24706
24707					deleteTexture(texture);
24708
24709				}
24710
24711			}
24712
24713			// store references to cache key and WebGLTexture object
24714
24715			textureProperties.__cacheKey = textureCacheKey;
24716			textureProperties.__webglTexture = webglTextures[textureCacheKey].texture;
24717
24718		}
24719
24720		return forceUpload;
24721
24722	}
24723
24724	function uploadTexture(textureProperties, texture, slot) {
24725
24726		let textureType = _gl.TEXTURE_2D;
24727
24728		if (texture.isDataArrayTexture || texture.isCompressedArrayTexture) textureType = _gl.TEXTURE_2D_ARRAY;
24729		if (texture.isData3DTexture) textureType = _gl.TEXTURE_3D;
24730
24731		const forceUpload = initTexture(textureProperties, texture);
24732		const source = texture.source;
24733
24734		state.bindTexture(textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot);
24735
24736		const sourceProperties = properties.get(source);
24737
24738		if (source.version !== sourceProperties.__version || forceUpload === true) {
24739
24740			state.activeTexture(_gl.TEXTURE0 + slot);
24741
24742			const workingPrimaries = ColorManagement.getPrimaries(ColorManagement.workingColorSpace);
24743			const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries(texture.colorSpace);
24744			const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
24745
24746			_gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
24747			_gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
24748			_gl.pixelStorei(_gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
24749			_gl.pixelStorei(_gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion);
24750
24751			const needsPowerOfTwo = textureNeedsPowerOfTwo(texture) && isPowerOfTwo$1(texture.image) === false;
24752			let image = resizeImage(texture.image, needsPowerOfTwo, false, capabilities.maxTextureSize);
24753			image = verifyColorSpace(texture, image);
24754
24755			const supportsMips = isPowerOfTwo$1(image) || isWebGL2,
24756				glFormat = utils.convert(texture.format, texture.colorSpace);
24757
24758			let glType = utils.convert(texture.type),
24759				glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture);
24760
24761			setTextureParameters(textureType, texture, supportsMips);
24762
24763			let mipmap;
24764			const mipmaps = texture.mipmaps;
24765
24766			const useTexStorage = (isWebGL2 && texture.isVideoTexture !== true && glInternalFormat !== RGB_ETC1_Format);
24767			const allocateMemory = (sourceProperties.__version === undefined) || (forceUpload === true);
24768			const levels = getMipLevels(texture, image, supportsMips);
24769
24770			if (texture.isDepthTexture) {
24771
24772				// populate depth texture with dummy data
24773
24774				glInternalFormat = _gl.DEPTH_COMPONENT;
24775
24776				if (isWebGL2) {
24777
24778					if (texture.type === FloatType) {
24779
24780						glInternalFormat = _gl.DEPTH_COMPONENT32F;
24781
24782					} else if (texture.type === UnsignedIntType) {
24783
24784						glInternalFormat = _gl.DEPTH_COMPONENT24;
24785
24786					} else if (texture.type === UnsignedInt248Type) {
24787
24788						glInternalFormat = _gl.DEPTH24_STENCIL8;
24789
24790					} else {
24791
24792						glInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D
24793
24794					}
24795
24796				} else {
24797
24798					if (texture.type === FloatType) {
24799
24800						console.error('WebGLRenderer: Floating point depth texture requires WebGL2.');
24801
24802					}
24803
24804				}
24805
24806				// validation checks for WebGL 1
24807
24808				if (texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT) {
24809
24810					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
24811					// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
24812					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
24813					if (texture.type !== UnsignedShortType && texture.type !== UnsignedIntType) {
24814
24815						console.warn('THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.');
24816
24817						texture.type = UnsignedIntType;
24818						glType = utils.convert(texture.type);
24819
24820					}
24821
24822				}
24823
24824				if (texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT) {
24825
24826					// Depth stencil textures need the DEPTH_STENCIL internal format
24827					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
24828					glInternalFormat = _gl.DEPTH_STENCIL;
24829
24830					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
24831					// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
24832					// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
24833					if (texture.type !== UnsignedInt248Type) {
24834
24835						console.warn('THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.');
24836
24837						texture.type = UnsignedInt248Type;
24838						glType = utils.convert(texture.type);
24839
24840					}
24841
24842				}
24843
24844				//
24845
24846				if (allocateMemory) {
24847
24848					if (useTexStorage) {
24849
24850						state.texStorage2D(_gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height);
24851
24852					} else {
24853
24854						state.texImage2D(_gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null);
24855
24856					}
24857
24858				}
24859
24860			} else if (texture.isDataTexture) {
24861
24862				// use manually created mipmaps if available
24863				// if there are no manual mipmaps
24864				// set 0 level mipmap and then use GL to generate other mipmap levels
24865
24866				if (mipmaps.length > 0 && supportsMips) {
24867
24868					if (useTexStorage && allocateMemory) {
24869
24870						state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height);
24871
24872					}
24873
24874					for (let i = 0, il = mipmaps.length; i < il; i++) {
24875
24876						mipmap = mipmaps[i];
24877
24878						if (useTexStorage) {
24879
24880							state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data);
24881
24882						} else {
24883
24884							state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
24885
24886						}
24887
24888					}
24889
24890					texture.generateMipmaps = false;
24891
24892				} else {
24893
24894					if (useTexStorage) {
24895
24896						if (allocateMemory) {
24897
24898							state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height);
24899
24900						}
24901
24902						state.texSubImage2D(_gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data);
24903
24904					} else {
24905
24906						state.texImage2D(_gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data);
24907
24908					}
24909
24910				}
24911
24912			} else if (texture.isCompressedTexture) {
24913
24914				if (texture.isCompressedArrayTexture) {
24915
24916					if (useTexStorage && allocateMemory) {
24917
24918						state.texStorage3D(_gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height, image.depth);
24919
24920					}
24921
24922					for (let i = 0, il = mipmaps.length; i < il; i++) {
24923
24924						mipmap = mipmaps[i];
24925
24926						if (texture.format !== RGBAFormat) {
24927
24928							if (glFormat !== null) {
24929
24930								if (useTexStorage) {
24931
24932									state.compressedTexSubImage3D(_gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0);
24933
24934								} else {
24935
24936									state.compressedTexImage3D(_gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0);
24937
24938								}
24939
24940							} else {
24941
24942								console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()');
24943
24944							}
24945
24946						} else {
24947
24948							if (useTexStorage) {
24949
24950								state.texSubImage3D(_gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data);
24951
24952							} else {
24953
24954								state.texImage3D(_gl.TEXTURE_2D_ARRAY, i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data);
24955
24956							}
24957
24958						}
24959
24960					}
24961
24962				} else {
24963
24964					if (useTexStorage && allocateMemory) {
24965
24966						state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height);
24967
24968					}
24969
24970					for (let i = 0, il = mipmaps.length; i < il; i++) {
24971
24972						mipmap = mipmaps[i];
24973
24974						if (texture.format !== RGBAFormat) {
24975
24976							if (glFormat !== null) {
24977
24978								if (useTexStorage) {
24979
24980									state.compressedTexSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data);
24981
24982								} else {
24983
24984									state.compressedTexImage2D(_gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data);
24985
24986								}
24987
24988							} else {
24989
24990								console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()');
24991
24992							}
24993
24994						} else {
24995
24996							if (useTexStorage) {
24997
24998								state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data);
24999
25000							} else {
25001
25002								state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
25003
25004							}
25005
25006						}
25007
25008					}
25009
25010				}
25011
25012			} else if (texture.isDataArrayTexture) {
25013
25014				if (useTexStorage) {
25015
25016					if (allocateMemory) {
25017
25018						state.texStorage3D(_gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth);
25019
25020					}
25021
25022					state.texSubImage3D(_gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data);
25023
25024				} else {
25025
25026					state.texImage3D(_gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data);
25027
25028				}
25029
25030			} else if (texture.isData3DTexture) {
25031
25032				if (useTexStorage) {
25033
25034					if (allocateMemory) {
25035
25036						state.texStorage3D(_gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth);
25037
25038					}
25039
25040					state.texSubImage3D(_gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data);
25041
25042				} else {
25043
25044					state.texImage3D(_gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data);
25045
25046				}
25047
25048			} else if (texture.isFramebufferTexture) {
25049
25050				if (allocateMemory) {
25051
25052					if (useTexStorage) {
25053
25054						state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height);
25055
25056					} else {
25057
25058						let width = image.width, height = image.height;
25059
25060						for (let i = 0; i < levels; i++) {
25061
25062							state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null);
25063
25064							width >>= 1;
25065							height >>= 1;
25066
25067						}
25068
25069					}
25070
25071				}
25072
25073			} else {
25074
25075				// regular Texture (image, video, canvas)
25076
25077				// use manually created mipmaps if available
25078				// if there are no manual mipmaps
25079				// set 0 level mipmap and then use GL to generate other mipmap levels
25080
25081				if (mipmaps.length > 0 && supportsMips) {
25082
25083					if (useTexStorage && allocateMemory) {
25084
25085						state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[0].width, mipmaps[0].height);
25086
25087					}
25088
25089					for (let i = 0, il = mipmaps.length; i < il; i++) {
25090
25091						mipmap = mipmaps[i];
25092
25093						if (useTexStorage) {
25094
25095							state.texSubImage2D(_gl.TEXTURE_2D, i, 0, 0, glFormat, glType, mipmap);
25096
25097						} else {
25098
25099							state.texImage2D(_gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap);
25100
25101						}
25102
25103					}
25104
25105					texture.generateMipmaps = false;
25106
25107				} else {
25108
25109					if (useTexStorage) {
25110
25111						if (allocateMemory) {
25112
25113							state.texStorage2D(_gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height);
25114
25115						}
25116
25117						state.texSubImage2D(_gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image);
25118
25119					} else {
25120
25121						state.texImage2D(_gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image);
25122
25123					}
25124
25125				}
25126
25127			}
25128
25129			if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
25130
25131				generateMipmap(textureType);
25132
25133			}
25134
25135			sourceProperties.__version = source.version;
25136
25137			if (texture.onUpdate) texture.onUpdate(texture);
25138
25139		}
25140
25141		textureProperties.__version = texture.version;
25142
25143	}
25144
25145	function uploadCubeTexture(textureProperties, texture, slot) {
25146
25147		if (texture.image.length !== 6) return;
25148
25149		const forceUpload = initTexture(textureProperties, texture);
25150		const source = texture.source;
25151
25152		state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot);
25153
25154		const sourceProperties = properties.get(source);
25155
25156		if (source.version !== sourceProperties.__version || forceUpload === true) {
25157
25158			state.activeTexture(_gl.TEXTURE0 + slot);
25159
25160			const workingPrimaries = ColorManagement.getPrimaries(ColorManagement.workingColorSpace);
25161			const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries(texture.colorSpace);
25162			const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
25163
25164			_gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
25165			_gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
25166			_gl.pixelStorei(_gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
25167			_gl.pixelStorei(_gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion);
25168
25169			const isCompressed = (texture.isCompressedTexture || texture.image[0].isCompressedTexture);
25170			const isDataTexture = (texture.image[0] && texture.image[0].isDataTexture);
25171
25172			const cubeImage = [];
25173
25174			for (let i = 0; i < 6; i++) {
25175
25176				if (!isCompressed && !isDataTexture) {
25177
25178					cubeImage[i] = resizeImage(texture.image[i], false, true, capabilities.maxCubemapSize);
25179
25180				} else {
25181
25182					cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i];
25183
25184				}
25185
25186				cubeImage[i] = verifyColorSpace(texture, cubeImage[i]);
25187
25188			}
25189
25190			const image = cubeImage[0],
25191				supportsMips = isPowerOfTwo$1(image) || isWebGL2,
25192				glFormat = utils.convert(texture.format, texture.colorSpace),
25193				glType = utils.convert(texture.type),
25194				glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.colorSpace);
25195
25196			const useTexStorage = (isWebGL2 && texture.isVideoTexture !== true);
25197			const allocateMemory = (sourceProperties.__version === undefined) || (forceUpload === true);
25198			let levels = getMipLevels(texture, image, supportsMips);
25199
25200			setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, supportsMips);
25201
25202			let mipmaps;
25203
25204			if (isCompressed) {
25205
25206				if (useTexStorage && allocateMemory) {
25207
25208					state.texStorage2D(_gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height);
25209
25210				}
25211
25212				for (let i = 0; i < 6; i++) {
25213
25214					mipmaps = cubeImage[i].mipmaps;
25215
25216					for (let j = 0; j < mipmaps.length; j++) {
25217
25218						const mipmap = mipmaps[j];
25219
25220						if (texture.format !== RGBAFormat) {
25221
25222							if (glFormat !== null) {
25223
25224								if (useTexStorage) {
25225
25226									state.compressedTexSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data);
25227
25228								} else {
25229
25230									state.compressedTexImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data);
25231
25232								}
25233
25234							} else {
25235
25236								console.warn('THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()');
25237
25238							}
25239
25240						} else {
25241
25242							if (useTexStorage) {
25243
25244								state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data);
25245
25246							} else {
25247
25248								state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
25249
25250							}
25251
25252						}
25253
25254					}
25255
25256				}
25257
25258			} else {
25259
25260				mipmaps = texture.mipmaps;
25261
25262				if (useTexStorage && allocateMemory) {
25263
25264					// TODO: Uniformly handle mipmap definitions
25265					// Normal textures and compressed cube textures define base level + mips with their mipmap array
25266					// Uncompressed cube textures use their mipmap array only for mips (no base level)
25267
25268					if (mipmaps.length > 0) levels++;
25269
25270					state.texStorage2D(_gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[0].width, cubeImage[0].height);
25271
25272				}
25273
25274				for (let i = 0; i < 6; i++) {
25275
25276					if (isDataTexture) {
25277
25278						if (useTexStorage) {
25279
25280							state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, cubeImage[i].width, cubeImage[i].height, glFormat, glType, cubeImage[i].data);
25281
25282						} else {
25283
25284							state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[i].width, cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data);
25285
25286						}
25287
25288						for (let j = 0; j < mipmaps.length; j++) {
25289
25290							const mipmap = mipmaps[j];
25291							const mipmapImage = mipmap.image[i].image;
25292
25293							if (useTexStorage) {
25294
25295								state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data);
25296
25297							} else {
25298
25299								state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data);
25300
25301							}
25302
25303						}
25304
25305					} else {
25306
25307						if (useTexStorage) {
25308
25309							state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, glFormat, glType, cubeImage[i]);
25310
25311						} else {
25312
25313							state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[i]);
25314
25315						}
25316
25317						for (let j = 0; j < mipmaps.length; j++) {
25318
25319							const mipmap = mipmaps[j];
25320
25321							if (useTexStorage) {
25322
25323								state.texSubImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, 0, 0, glFormat, glType, mipmap.image[i]);
25324
25325							} else {
25326
25327								state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[i]);
25328
25329							}
25330
25331						}
25332
25333					}
25334
25335				}
25336
25337			}
25338
25339			if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
25340
25341				// We assume images for cube map have the same size.
25342				generateMipmap(_gl.TEXTURE_CUBE_MAP);
25343
25344			}
25345
25346			sourceProperties.__version = source.version;
25347
25348			if (texture.onUpdate) texture.onUpdate(texture);
25349
25350		}
25351
25352		textureProperties.__version = texture.version;
25353
25354	}
25355
25356	// Render targets
25357
25358	// Setup storage for target texture and bind it to correct framebuffer
25359	function setupFrameBufferTexture(framebuffer, renderTarget, texture, attachment, textureTarget, level) {
25360
25361		const glFormat = utils.convert(texture.format, texture.colorSpace);
25362		const glType = utils.convert(texture.type);
25363		const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.colorSpace);
25364		const renderTargetProperties = properties.get(renderTarget);
25365
25366		if (!renderTargetProperties.__hasExternalTextures) {
25367
25368			const width = Math.max(1, renderTarget.width >> level);
25369			const height = Math.max(1, renderTarget.height >> level);
25370
25371			if (textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY) {
25372
25373				state.texImage3D(textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null);
25374
25375			} else {
25376
25377				state.texImage2D(textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null);
25378
25379			}
25380
25381		}
25382
25383		state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
25384
25385		if (useMultisampledRTT(renderTarget)) {
25386
25387			multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, 0, getRenderTargetSamples(renderTarget));
25388
25389		} else if (textureTarget === _gl.TEXTURE_2D || (textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z)) { // see #24753
25390
25391			_gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(texture).__webglTexture, level);
25392
25393		}
25394
25395		state.bindFramebuffer(_gl.FRAMEBUFFER, null);
25396
25397	}
25398
25399
25400	// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
25401	function setupRenderBufferStorage(renderbuffer, renderTarget, isMultisample) {
25402
25403		_gl.bindRenderbuffer(_gl.RENDERBUFFER, renderbuffer);
25404
25405		if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) {
25406
25407			let glInternalFormat = (isWebGL2 === true) ? _gl.DEPTH_COMPONENT24 : _gl.DEPTH_COMPONENT16;
25408
25409			if (isMultisample || useMultisampledRTT(renderTarget)) {
25410
25411				const depthTexture = renderTarget.depthTexture;
25412
25413				if (depthTexture && depthTexture.isDepthTexture) {
25414
25415					if (depthTexture.type === FloatType) {
25416
25417						glInternalFormat = _gl.DEPTH_COMPONENT32F;
25418
25419					} else if (depthTexture.type === UnsignedIntType) {
25420
25421						glInternalFormat = _gl.DEPTH_COMPONENT24;
25422
25423					}
25424
25425				}
25426
25427				const samples = getRenderTargetSamples(renderTarget);
25428
25429				if (useMultisampledRTT(renderTarget)) {
25430
25431					multisampledRTTExt.renderbufferStorageMultisampleEXT(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height);
25432
25433				} else {
25434
25435					_gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height);
25436
25437				}
25438
25439			} else {
25440
25441				_gl.renderbufferStorage(_gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height);
25442
25443			}
25444
25445			_gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer);
25446
25447		} else if (renderTarget.depthBuffer && renderTarget.stencilBuffer) {
25448
25449			const samples = getRenderTargetSamples(renderTarget);
25450
25451			if (isMultisample && useMultisampledRTT(renderTarget) === false) {
25452
25453				_gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height);
25454
25455			} else if (useMultisampledRTT(renderTarget)) {
25456
25457				multisampledRTTExt.renderbufferStorageMultisampleEXT(_gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height);
25458
25459			} else {
25460
25461				_gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height);
25462
25463			}
25464
25465
25466			_gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer);
25467
25468		} else {
25469
25470			const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture];
25471
25472			for (let i = 0; i < textures.length; i++) {
25473
25474				const texture = textures[i];
25475
25476				const glFormat = utils.convert(texture.format, texture.colorSpace);
25477				const glType = utils.convert(texture.type);
25478				const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.colorSpace);
25479				const samples = getRenderTargetSamples(renderTarget);
25480
25481				if (isMultisample && useMultisampledRTT(renderTarget) === false) {
25482
25483					_gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height);
25484
25485				} else if (useMultisampledRTT(renderTarget)) {
25486
25487					multisampledRTTExt.renderbufferStorageMultisampleEXT(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height);
25488
25489				} else {
25490
25491					_gl.renderbufferStorage(_gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height);
25492
25493				}
25494
25495			}
25496
25497		}
25498
25499		_gl.bindRenderbuffer(_gl.RENDERBUFFER, null);
25500
25501	}
25502
25503	// Setup resources for a Depth Texture for a FBO (needs an extension)
25504	function setupDepthTexture(framebuffer, renderTarget) {
25505
25506		const isCube = (renderTarget && renderTarget.isWebGLCubeRenderTarget);
25507		if (isCube) throw new Error('Depth Texture with cube render targets is not supported');
25508
25509		state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
25510
25511		if (!(renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture)) {
25512
25513			throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture');
25514
25515		}
25516
25517		// upload an empty depth texture with framebuffer size
25518		if (!properties.get(renderTarget.depthTexture).__webglTexture ||
25519			renderTarget.depthTexture.image.width !== renderTarget.width ||
25520			renderTarget.depthTexture.image.height !== renderTarget.height) {
25521
25522			renderTarget.depthTexture.image.width = renderTarget.width;
25523			renderTarget.depthTexture.image.height = renderTarget.height;
25524			renderTarget.depthTexture.needsUpdate = true;
25525
25526		}
25527
25528		setTexture2D(renderTarget.depthTexture, 0);
25529
25530		const webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture;
25531		const samples = getRenderTargetSamples(renderTarget);
25532
25533		if (renderTarget.depthTexture.format === DepthFormat) {
25534
25535			if (useMultisampledRTT(renderTarget)) {
25536
25537				multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples);
25538
25539			} else {
25540
25541				_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0);
25542
25543			}
25544
25545		} else if (renderTarget.depthTexture.format === DepthStencilFormat) {
25546
25547			if (useMultisampledRTT(renderTarget)) {
25548
25549				multisampledRTTExt.framebufferTexture2DMultisampleEXT(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples);
25550
25551			} else {
25552
25553				_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0);
25554
25555			}
25556
25557		} else {
25558
25559			throw new Error('Unknown depthTexture format');
25560
25561		}
25562
25563	}
25564
25565	// Setup GL resources for a non-texture depth buffer
25566	function setupDepthRenderbuffer(renderTarget) {
25567
25568		const renderTargetProperties = properties.get(renderTarget);
25569		const isCube = (renderTarget.isWebGLCubeRenderTarget === true);
25570
25571		if (renderTarget.depthTexture && !renderTargetProperties.__autoAllocateDepthBuffer) {
25572
25573			if (isCube) throw new Error('target.depthTexture not supported in Cube render targets');
25574
25575			setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget);
25576
25577		} else {
25578
25579			if (isCube) {
25580
25581				renderTargetProperties.__webglDepthbuffer = [];
25582
25583				for (let i = 0; i < 6; i++) {
25584
25585					state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[i]);
25586					renderTargetProperties.__webglDepthbuffer[i] = _gl.createRenderbuffer();
25587					setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[i], renderTarget, false);
25588
25589				}
25590
25591			} else {
25592
25593				state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer);
25594				renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
25595				setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer, renderTarget, false);
25596
25597			}
25598
25599		}
25600
25601		state.bindFramebuffer(_gl.FRAMEBUFFER, null);
25602
25603	}
25604
25605	// rebind framebuffer with external textures
25606	function rebindTextures(renderTarget, colorTexture, depthTexture) {
25607
25608		const renderTargetProperties = properties.get(renderTarget);
25609
25610		if (colorTexture !== undefined) {
25611
25612			setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0);
25613
25614		}
25615
25616		if (depthTexture !== undefined) {
25617
25618			setupDepthRenderbuffer(renderTarget);
25619
25620		}
25621
25622	}
25623
25624	// Set up GL resources for the render target
25625	function setupRenderTarget(renderTarget) {
25626
25627		const texture = renderTarget.texture;
25628
25629		const renderTargetProperties = properties.get(renderTarget);
25630		const textureProperties = properties.get(texture);
25631
25632		renderTarget.addEventListener('dispose', onRenderTargetDispose);
25633
25634		if (renderTarget.isWebGLMultipleRenderTargets !== true) {
25635
25636			if (textureProperties.__webglTexture === undefined) {
25637
25638				textureProperties.__webglTexture = _gl.createTexture();
25639
25640			}
25641
25642			textureProperties.__version = texture.version;
25643			info.memory.textures++;
25644
25645		}
25646
25647		const isCube = (renderTarget.isWebGLCubeRenderTarget === true);
25648		const isMultipleRenderTargets = (renderTarget.isWebGLMultipleRenderTargets === true);
25649		const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2;
25650
25651		// Setup framebuffer
25652
25653		if (isCube) {
25654
25655			renderTargetProperties.__webglFramebuffer = [];
25656
25657			for (let i = 0; i < 6; i++) {
25658
25659				if (isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0) {
25660
25661					renderTargetProperties.__webglFramebuffer[i] = [];
25662
25663					for (let level = 0; level < texture.mipmaps.length; level++) {
25664
25665						renderTargetProperties.__webglFramebuffer[i][level] = _gl.createFramebuffer();
25666
25667					}
25668
25669				} else {
25670
25671					renderTargetProperties.__webglFramebuffer[i] = _gl.createFramebuffer();
25672
25673				}
25674
25675			}
25676
25677		} else {
25678
25679			if (isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0) {
25680
25681				renderTargetProperties.__webglFramebuffer = [];
25682
25683				for (let level = 0; level < texture.mipmaps.length; level++) {
25684
25685					renderTargetProperties.__webglFramebuffer[level] = _gl.createFramebuffer();
25686
25687				}
25688
25689			} else {
25690
25691				renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
25692
25693			}
25694
25695			if (isMultipleRenderTargets) {
25696
25697				if (capabilities.drawBuffers) {
25698
25699					const textures = renderTarget.texture;
25700
25701					for (let i = 0, il = textures.length; i < il; i++) {
25702
25703						const attachmentProperties = properties.get(textures[i]);
25704
25705						if (attachmentProperties.__webglTexture === undefined) {
25706
25707							attachmentProperties.__webglTexture = _gl.createTexture();
25708
25709							info.memory.textures++;
25710
25711						}
25712
25713					}
25714
25715				} else {
25716
25717					console.warn('THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.');
25718
25719				}
25720
25721			}
25722
25723			if ((isWebGL2 && renderTarget.samples > 0) && useMultisampledRTT(renderTarget) === false) {
25724
25725				const textures = isMultipleRenderTargets ? texture : [texture];
25726
25727				renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
25728				renderTargetProperties.__webglColorRenderbuffer = [];
25729
25730				state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer);
25731
25732				for (let i = 0; i < textures.length; i++) {
25733
25734					const texture = textures[i];
25735					renderTargetProperties.__webglColorRenderbuffer[i] = _gl.createRenderbuffer();
25736
25737					_gl.bindRenderbuffer(_gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]);
25738
25739					const glFormat = utils.convert(texture.format, texture.colorSpace);
25740					const glType = utils.convert(texture.type);
25741					const glInternalFormat = getInternalFormat(texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget === true);
25742					const samples = getRenderTargetSamples(renderTarget);
25743					_gl.renderbufferStorageMultisample(_gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height);
25744
25745					_gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]);
25746
25747				}
25748
25749				_gl.bindRenderbuffer(_gl.RENDERBUFFER, null);
25750
25751				if (renderTarget.depthBuffer) {
25752
25753					renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
25754					setupRenderBufferStorage(renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true);
25755
25756				}
25757
25758				state.bindFramebuffer(_gl.FRAMEBUFFER, null);
25759
25760			}
25761
25762		}
25763
25764		// Setup color buffer
25765
25766		if (isCube) {
25767
25768			state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture);
25769			setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, supportsMips);
25770
25771			for (let i = 0; i < 6; i++) {
25772
25773				if (isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0) {
25774
25775					for (let level = 0; level < texture.mipmaps.length; level++) {
25776
25777						setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i][level], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level);
25778
25779					}
25780
25781				} else {
25782
25783					setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0);
25784
25785				}
25786
25787			}
25788
25789			if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
25790
25791				generateMipmap(_gl.TEXTURE_CUBE_MAP);
25792
25793			}
25794
25795			state.unbindTexture();
25796
25797		} else if (isMultipleRenderTargets) {
25798
25799			const textures = renderTarget.texture;
25800
25801			for (let i = 0, il = textures.length; i < il; i++) {
25802
25803				const attachment = textures[i];
25804				const attachmentProperties = properties.get(attachment);
25805
25806				state.bindTexture(_gl.TEXTURE_2D, attachmentProperties.__webglTexture);
25807				setTextureParameters(_gl.TEXTURE_2D, attachment, supportsMips);
25808				setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0);
25809
25810				if (textureNeedsGenerateMipmaps(attachment, supportsMips)) {
25811
25812					generateMipmap(_gl.TEXTURE_2D);
25813
25814				}
25815
25816			}
25817
25818			state.unbindTexture();
25819
25820		} else {
25821
25822			let glTextureType = _gl.TEXTURE_2D;
25823
25824			if (renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget) {
25825
25826				if (isWebGL2) {
25827
25828					glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY;
25829
25830				} else {
25831
25832					console.error('THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2.');
25833
25834				}
25835
25836			}
25837
25838			state.bindTexture(glTextureType, textureProperties.__webglTexture);
25839			setTextureParameters(glTextureType, texture, supportsMips);
25840
25841			if (isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0) {
25842
25843				for (let level = 0; level < texture.mipmaps.length; level++) {
25844
25845					setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[level], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level);
25846
25847				}
25848
25849			} else {
25850
25851				setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0);
25852
25853			}
25854
25855			if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
25856
25857				generateMipmap(glTextureType);
25858
25859			}
25860
25861			state.unbindTexture();
25862
25863		}
25864
25865		// Setup depth and stencil buffers
25866
25867		if (renderTarget.depthBuffer) {
25868
25869			setupDepthRenderbuffer(renderTarget);
25870
25871		}
25872
25873	}
25874
25875	function updateRenderTargetMipmap(renderTarget) {
25876
25877		const supportsMips = isPowerOfTwo$1(renderTarget) || isWebGL2;
25878
25879		const textures = renderTarget.isWebGLMultipleRenderTargets === true ? renderTarget.texture : [renderTarget.texture];
25880
25881		for (let i = 0, il = textures.length; i < il; i++) {
25882
25883			const texture = textures[i];
25884
25885			if (textureNeedsGenerateMipmaps(texture, supportsMips)) {
25886
25887				const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
25888				const webglTexture = properties.get(texture).__webglTexture;
25889
25890				state.bindTexture(target, webglTexture);
25891				generateMipmap(target);
25892				state.unbindTexture();
25893
25894			}
25895
25896		}
25897
25898	}
25899
25900	function updateMultisampleRenderTarget(renderTarget) {
25901
25902		if ((isWebGL2 && renderTarget.samples > 0) && useMultisampledRTT(renderTarget) === false) {
25903
25904			const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [renderTarget.texture];
25905			const width = renderTarget.width;
25906			const height = renderTarget.height;
25907			let mask = _gl.COLOR_BUFFER_BIT;
25908			const invalidationArray = [];
25909			const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT;
25910			const renderTargetProperties = properties.get(renderTarget);
25911			const isMultipleRenderTargets = (renderTarget.isWebGLMultipleRenderTargets === true);
25912
25913			// If MRT we need to remove FBO attachments
25914			if (isMultipleRenderTargets) {
25915
25916				for (let i = 0; i < textures.length; i++) {
25917
25918					state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer);
25919					_gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null);
25920
25921					state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer);
25922					_gl.framebufferTexture2D(_gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0);
25923
25924				}
25925
25926			}
25927
25928			state.bindFramebuffer(_gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer);
25929			state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer);
25930
25931			for (let i = 0; i < textures.length; i++) {
25932
25933				invalidationArray.push(_gl.COLOR_ATTACHMENT0 + i);
25934
25935				if (renderTarget.depthBuffer) {
25936
25937					invalidationArray.push(depthStyle);
25938
25939				}
25940
25941				const ignoreDepthValues = (renderTargetProperties.__ignoreDepthValues !== undefined) ? renderTargetProperties.__ignoreDepthValues : false;
25942
25943				if (ignoreDepthValues === false) {
25944
25945					if (renderTarget.depthBuffer) mask |= _gl.DEPTH_BUFFER_BIT;
25946					if (renderTarget.stencilBuffer) mask |= _gl.STENCIL_BUFFER_BIT;
25947
25948				}
25949
25950				if (isMultipleRenderTargets) {
25951
25952					_gl.framebufferRenderbuffer(_gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]);
25953
25954				}
25955
25956				if (ignoreDepthValues === true) {
25957
25958					_gl.invalidateFramebuffer(_gl.READ_FRAMEBUFFER, [depthStyle]);
25959					_gl.invalidateFramebuffer(_gl.DRAW_FRAMEBUFFER, [depthStyle]);
25960
25961				}
25962
25963				if (isMultipleRenderTargets) {
25964
25965					const webglTexture = properties.get(textures[i]).__webglTexture;
25966					_gl.framebufferTexture2D(_gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0);
25967
25968				}
25969
25970				_gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST);
25971
25972				if (supportsInvalidateFramebuffer) {
25973
25974					_gl.invalidateFramebuffer(_gl.READ_FRAMEBUFFER, invalidationArray);
25975
25976				}
25977
25978
25979			}
25980
25981			state.bindFramebuffer(_gl.READ_FRAMEBUFFER, null);
25982			state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, null);
25983
25984			// If MRT since pre-blit we removed the FBO we need to reconstruct the attachments
25985			if (isMultipleRenderTargets) {
25986
25987				for (let i = 0; i < textures.length; i++) {
25988
25989					state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer);
25990					_gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[i]);
25991
25992					const webglTexture = properties.get(textures[i]).__webglTexture;
25993
25994					state.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer);
25995					_gl.framebufferTexture2D(_gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0);
25996
25997				}
25998
25999			}
26000
26001			state.bindFramebuffer(_gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer);
26002
26003		}
26004
26005	}
26006
26007	function getRenderTargetSamples(renderTarget) {
26008
26009		return Math.min(capabilities.maxSamples, renderTarget.samples);
26010
26011	}
26012
26013	function useMultisampledRTT(renderTarget) {
26014
26015		const renderTargetProperties = properties.get(renderTarget);
26016
26017		return isWebGL2 && renderTarget.samples > 0 && extensions.has('WEBGL_multisampled_render_to_texture') === true && renderTargetProperties.__useRenderToTexture !== false;
26018
26019	}
26020
26021	function updateVideoTexture(texture) {
26022
26023		const frame = info.render.frame;
26024
26025		// Check the last frame we updated the VideoTexture
26026
26027		if (_videoTextures.get(texture) !== frame) {
26028
26029			_videoTextures.set(texture, frame);
26030			texture.update();
26031
26032		}
26033
26034	}
26035
26036	function verifyColorSpace(texture, image) {
26037
26038		const colorSpace = texture.colorSpace;
26039		const format = texture.format;
26040		const type = texture.type;
26041
26042		if (texture.isCompressedTexture === true || texture.isVideoTexture === true || texture.format === _SRGBAFormat) return image;
26043
26044		if (colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace) {
26045
26046			// sRGB
26047
26048			if (ColorManagement.getTransfer(colorSpace) === SRGBTransfer) {
26049
26050				if (isWebGL2 === false) {
26051
26052					// in WebGL 1, try to use EXT_sRGB extension and unsized formats
26053
26054					if (extensions.has('EXT_sRGB') === true && format === RGBAFormat) {
26055
26056						texture.format = _SRGBAFormat;
26057
26058						// it's not possible to generate mips in WebGL 1 with this extension
26059
26060						texture.minFilter = LinearFilter;
26061						texture.generateMipmaps = false;
26062
26063					} else {
26064
26065						// slow fallback (CPU decode)
26066
26067						image = ImageUtils.sRGBToLinear(image);
26068
26069					}
26070
26071				} else {
26072
26073					// in WebGL 2 uncompressed textures can only be sRGB encoded if they have the RGBA8 format
26074
26075					if (format !== RGBAFormat || type !== UnsignedByteType) {
26076
26077						console.warn('THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.');
26078
26079					}
26080
26081				}
26082
26083			} else {
26084
26085				console.error('THREE.WebGLTextures: Unsupported texture color space:', colorSpace);
26086
26087			}
26088
26089		}
26090
26091		return image;
26092
26093	}
26094
26095	//
26096
26097	this.allocateTextureUnit = allocateTextureUnit;
26098	this.resetTextureUnits = resetTextureUnits;
26099
26100	this.setTexture2D = setTexture2D;
26101	this.setTexture2DArray = setTexture2DArray;
26102	this.setTexture3D = setTexture3D;
26103	this.setTextureCube = setTextureCube;
26104	this.rebindTextures = rebindTextures;
26105	this.setupRenderTarget = setupRenderTarget;
26106	this.updateRenderTargetMipmap = updateRenderTargetMipmap;
26107	this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
26108	this.setupDepthRenderbuffer = setupDepthRenderbuffer;
26109	this.setupFrameBufferTexture = setupFrameBufferTexture;
26110	this.useMultisampledRTT = useMultisampledRTT;
26111
26112}
26113
26114function WebGLUtils(gl, extensions, capabilities) {
26115
26116	const isWebGL2 = capabilities.isWebGL2;
26117
26118	function convert(p, colorSpace = NoColorSpace) {
26119
26120		let extension;
26121
26122		const transfer = ColorManagement.getTransfer(colorSpace);
26123
26124		if (p === UnsignedByteType) return gl.UNSIGNED_BYTE;
26125		if (p === UnsignedShort4444Type) return gl.UNSIGNED_SHORT_4_4_4_4;
26126		if (p === UnsignedShort5551Type) return gl.UNSIGNED_SHORT_5_5_5_1;
26127
26128		if (p === ByteType) return gl.BYTE;
26129		if (p === ShortType) return gl.SHORT;
26130		if (p === UnsignedShortType) return gl.UNSIGNED_SHORT;
26131		if (p === IntType) return gl.INT;
26132		if (p === UnsignedIntType) return gl.UNSIGNED_INT;
26133		if (p === FloatType) return gl.FLOAT;
26134
26135		if (p === HalfFloatType) {
26136
26137			if (isWebGL2) return gl.HALF_FLOAT;
26138
26139			extension = extensions.get('OES_texture_half_float');
26140
26141			if (extension !== null) {
26142
26143				return extension.HALF_FLOAT_OES;
26144
26145			} else {
26146
26147				return null;
26148
26149			}
26150
26151		}
26152
26153		if (p === AlphaFormat) return gl.ALPHA;
26154		if (p === RGBAFormat) return gl.RGBA;
26155		if (p === LuminanceFormat) return gl.LUMINANCE;
26156		if (p === LuminanceAlphaFormat) return gl.LUMINANCE_ALPHA;
26157		if (p === DepthFormat) return gl.DEPTH_COMPONENT;
26158		if (p === DepthStencilFormat) return gl.DEPTH_STENCIL;
26159
26160		// WebGL 1 sRGB fallback
26161
26162		if (p === _SRGBAFormat) {
26163
26164			extension = extensions.get('EXT_sRGB');
26165
26166			if (extension !== null) {
26167
26168				return extension.SRGB_ALPHA_EXT;
26169
26170			} else {
26171
26172				return null;
26173
26174			}
26175
26176		}
26177
26178		// WebGL2 formats.
26179
26180		if (p === RedFormat) return gl.RED;
26181		if (p === RedIntegerFormat) return gl.RED_INTEGER;
26182		if (p === RGFormat) return gl.RG;
26183		if (p === RGIntegerFormat) return gl.RG_INTEGER;
26184		if (p === RGBAIntegerFormat) return gl.RGBA_INTEGER;
26185
26186		// S3TC
26187
26188		if (p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format) {
26189
26190			if (transfer === SRGBTransfer) {
26191
26192				extension = extensions.get('WEBGL_compressed_texture_s3tc_srgb');
26193
26194				if (extension !== null) {
26195
26196					if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT;
26197					if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
26198					if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
26199					if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
26200
26201				} else {
26202
26203					return null;
26204
26205				}
26206
26207			} else {
26208
26209				extension = extensions.get('WEBGL_compressed_texture_s3tc');
26210
26211				if (extension !== null) {
26212
26213					if (p === RGB_S3TC_DXT1_Format) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
26214					if (p === RGBA_S3TC_DXT1_Format) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
26215					if (p === RGBA_S3TC_DXT3_Format) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
26216					if (p === RGBA_S3TC_DXT5_Format) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
26217
26218				} else {
26219
26220					return null;
26221
26222				}
26223
26224			}
26225
26226		}
26227
26228		// PVRTC
26229
26230		if (p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format) {
26231
26232			extension = extensions.get('WEBGL_compressed_texture_pvrtc');
26233
26234			if (extension !== null) {
26235
26236				if (p === RGB_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
26237				if (p === RGB_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
26238				if (p === RGBA_PVRTC_4BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
26239				if (p === RGBA_PVRTC_2BPPV1_Format) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
26240
26241			} else {
26242
26243				return null;
26244
26245			}
26246
26247		}
26248
26249		// ETC1
26250
26251		if (p === RGB_ETC1_Format) {
26252
26253			extension = extensions.get('WEBGL_compressed_texture_etc1');
26254
26255			if (extension !== null) {
26256
26257				return extension.COMPRESSED_RGB_ETC1_WEBGL;
26258
26259			} else {
26260
26261				return null;
26262
26263			}
26264
26265		}
26266
26267		// ETC2
26268
26269		if (p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format) {
26270
26271			extension = extensions.get('WEBGL_compressed_texture_etc');
26272
26273			if (extension !== null) {
26274
26275				if (p === RGB_ETC2_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
26276				if (p === RGBA_ETC2_EAC_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
26277
26278			} else {
26279
26280				return null;
26281
26282			}
26283
26284		}
26285
26286		// ASTC
26287
26288		if (p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||
26289			p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||
26290			p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||
26291			p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||
26292			p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format) {
26293
26294			extension = extensions.get('WEBGL_compressed_texture_astc');
26295
26296			if (extension !== null) {
26297
26298				if (p === RGBA_ASTC_4x4_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
26299				if (p === RGBA_ASTC_5x4_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
26300				if (p === RGBA_ASTC_5x5_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR;
26301				if (p === RGBA_ASTC_6x5_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR;
26302				if (p === RGBA_ASTC_6x6_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR;
26303				if (p === RGBA_ASTC_8x5_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR;
26304				if (p === RGBA_ASTC_8x6_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR;
26305				if (p === RGBA_ASTC_8x8_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR;
26306				if (p === RGBA_ASTC_10x5_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR;
26307				if (p === RGBA_ASTC_10x6_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR;
26308				if (p === RGBA_ASTC_10x8_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR;
26309				if (p === RGBA_ASTC_10x10_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR;
26310				if (p === RGBA_ASTC_12x10_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR;
26311				if (p === RGBA_ASTC_12x12_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR;
26312
26313			} else {
26314
26315				return null;
26316
26317			}
26318
26319		}
26320
26321		// BPTC
26322
26323		if (p === RGBA_BPTC_Format || p === RGB_BPTC_SIGNED_Format || p === RGB_BPTC_UNSIGNED_Format) {
26324
26325			extension = extensions.get('EXT_texture_compression_bptc');
26326
26327			if (extension !== null) {
26328
26329				if (p === RGBA_BPTC_Format) return (transfer === SRGBTransfer) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
26330				if (p === RGB_BPTC_SIGNED_Format) return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;
26331				if (p === RGB_BPTC_UNSIGNED_Format) return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
26332
26333			} else {
26334
26335				return null;
26336
26337			}
26338
26339		}
26340
26341		// RGTC
26342
26343		if (p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format) {
26344
26345			extension = extensions.get('EXT_texture_compression_rgtc');
26346
26347			if (extension !== null) {
26348
26349				if (p === RGBA_BPTC_Format) return extension.COMPRESSED_RED_RGTC1_EXT;
26350				if (p === SIGNED_RED_RGTC1_Format) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT;
26351				if (p === RED_GREEN_RGTC2_Format) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT;
26352				if (p === SIGNED_RED_GREEN_RGTC2_Format) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
26353
26354			} else {
26355
26356				return null;
26357
26358			}
26359
26360		}
26361
26362		//
26363
26364		if (p === UnsignedInt248Type) {
26365
26366			if (isWebGL2) return gl.UNSIGNED_INT_24_8;
26367
26368			extension = extensions.get('WEBGL_depth_texture');
26369
26370			if (extension !== null) {
26371
26372				return extension.UNSIGNED_INT_24_8_WEBGL;
26373
26374			} else {
26375
26376				return null;
26377
26378			}
26379
26380		}
26381
26382		// if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats)
26383
26384		return (gl[p] !== undefined) ? gl[p] : null;
26385
26386	}
26387
26388	return { convert: convert };
26389
26390}
26391
26392class ArrayCamera extends PerspectiveCamera {
26393
26394	constructor(array = []) {
26395
26396		super();
26397
26398		this.isArrayCamera = true;
26399
26400		this.cameras = array;
26401
26402	}
26403
26404}
26405
26406class Group extends Object3D {
26407
26408	constructor() {
26409
26410		super();
26411
26412		this.isGroup = true;
26413
26414		this.type = 'Group';
26415
26416	}
26417
26418}
26419
26420const _moveEvent = { type: 'move' };
26421
26422class WebXRController {
26423
26424	constructor() {
26425
26426		this._targetRay = null;
26427		this._grip = null;
26428		this._hand = null;
26429
26430	}
26431
26432	getHandSpace() {
26433
26434		if (this._hand === null) {
26435
26436			this._hand = new Group();
26437			this._hand.matrixAutoUpdate = false;
26438			this._hand.visible = false;
26439
26440			this._hand.joints = {};
26441			this._hand.inputState = { pinching: false };
26442
26443		}
26444
26445		return this._hand;
26446
26447	}
26448
26449	getTargetRaySpace() {
26450
26451		if (this._targetRay === null) {
26452
26453			this._targetRay = new Group();
26454			this._targetRay.matrixAutoUpdate = false;
26455			this._targetRay.visible = false;
26456			this._targetRay.hasLinearVelocity = false;
26457			this._targetRay.linearVelocity = new Vector3();
26458			this._targetRay.hasAngularVelocity = false;
26459			this._targetRay.angularVelocity = new Vector3();
26460
26461		}
26462
26463		return this._targetRay;
26464
26465	}
26466
26467	getGripSpace() {
26468
26469		if (this._grip === null) {
26470
26471			this._grip = new Group();
26472			this._grip.matrixAutoUpdate = false;
26473			this._grip.visible = false;
26474			this._grip.hasLinearVelocity = false;
26475			this._grip.linearVelocity = new Vector3();
26476			this._grip.hasAngularVelocity = false;
26477			this._grip.angularVelocity = new Vector3();
26478
26479		}
26480
26481		return this._grip;
26482
26483	}
26484
26485	dispatchEvent(event) {
26486
26487		if (this._targetRay !== null) {
26488
26489			this._targetRay.dispatchEvent(event);
26490
26491		}
26492
26493		if (this._grip !== null) {
26494
26495			this._grip.dispatchEvent(event);
26496
26497		}
26498
26499		if (this._hand !== null) {
26500
26501			this._hand.dispatchEvent(event);
26502
26503		}
26504
26505		return this;
26506
26507	}
26508
26509	connect(inputSource) {
26510
26511		if (inputSource && inputSource.hand) {
26512
26513			const hand = this._hand;
26514
26515			if (hand) {
26516
26517				for (const inputjoint of inputSource.hand.values()) {
26518
26519					// Initialize hand with joints when connected
26520					this._getHandJoint(hand, inputjoint);
26521
26522				}
26523
26524			}
26525
26526		}
26527
26528		this.dispatchEvent({ type: 'connected', data: inputSource });
26529
26530		return this;
26531
26532	}
26533
26534	disconnect(inputSource) {
26535
26536		this.dispatchEvent({ type: 'disconnected', data: inputSource });
26537
26538		if (this._targetRay !== null) {
26539
26540			this._targetRay.visible = false;
26541
26542		}
26543
26544		if (this._grip !== null) {
26545
26546			this._grip.visible = false;
26547
26548		}
26549
26550		if (this._hand !== null) {
26551
26552			this._hand.visible = false;
26553
26554		}
26555
26556		return this;
26557
26558	}
26559
26560	update(inputSource, frame, referenceSpace) {
26561
26562		let inputPose = null;
26563		let gripPose = null;
26564		let handPose = null;
26565
26566		const targetRay = this._targetRay;
26567		const grip = this._grip;
26568		const hand = this._hand;
26569
26570		if (inputSource && frame.session.visibilityState !== 'visible-blurred') {
26571
26572			if (hand && inputSource.hand) {
26573
26574				handPose = true;
26575
26576				for (const inputjoint of inputSource.hand.values()) {
26577
26578					// Update the joints groups with the XRJoint poses
26579					const jointPose = frame.getJointPose(inputjoint, referenceSpace);
26580
26581					// The transform of this joint will be updated with the joint pose on each frame
26582					const joint = this._getHandJoint(hand, inputjoint);
26583
26584					if (jointPose !== null) {
26585
26586						joint.matrix.fromArray(jointPose.transform.matrix);
26587						joint.matrix.decompose(joint.position, joint.rotation, joint.scale);
26588						joint.matrixWorldNeedsUpdate = true;
26589						joint.jointRadius = jointPose.radius;
26590
26591					}
26592
26593					joint.visible = jointPose !== null;
26594
26595				}
26596
26597				// Custom events
26598
26599				// Check pinchz
26600				const indexTip = hand.joints['index-finger-tip'];
26601				const thumbTip = hand.joints['thumb-tip'];
26602				const distance = indexTip.position.distanceTo(thumbTip.position);
26603
26604				const distanceToPinch = 0.02;
26605				const threshold = 0.005;
26606
26607				if (hand.inputState.pinching && distance > distanceToPinch + threshold) {
26608
26609					hand.inputState.pinching = false;
26610					this.dispatchEvent({
26611						type: 'pinchend',
26612						handedness: inputSource.handedness,
26613						target: this
26614					});
26615
26616				} else if (!hand.inputState.pinching && distance <= distanceToPinch - threshold) {
26617
26618					hand.inputState.pinching = true;
26619					this.dispatchEvent({
26620						type: 'pinchstart',
26621						handedness: inputSource.handedness,
26622						target: this
26623					});
26624
26625				}
26626
26627			} else {
26628
26629				if (grip !== null && inputSource.gripSpace) {
26630
26631					gripPose = frame.getPose(inputSource.gripSpace, referenceSpace);
26632
26633					if (gripPose !== null) {
26634
26635						grip.matrix.fromArray(gripPose.transform.matrix);
26636						grip.matrix.decompose(grip.position, grip.rotation, grip.scale);
26637						grip.matrixWorldNeedsUpdate = true;
26638
26639						if (gripPose.linearVelocity) {
26640
26641							grip.hasLinearVelocity = true;
26642							grip.linearVelocity.copy(gripPose.linearVelocity);
26643
26644						} else {
26645
26646							grip.hasLinearVelocity = false;
26647
26648						}
26649
26650						if (gripPose.angularVelocity) {
26651
26652							grip.hasAngularVelocity = true;
26653							grip.angularVelocity.copy(gripPose.angularVelocity);
26654
26655						} else {
26656
26657							grip.hasAngularVelocity = false;
26658
26659						}
26660
26661					}
26662
26663				}
26664
26665			}
26666
26667			if (targetRay !== null) {
26668
26669				inputPose = frame.getPose(inputSource.targetRaySpace, referenceSpace);
26670
26671				// Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it
26672				if (inputPose === null && gripPose !== null) {
26673
26674					inputPose = gripPose;
26675
26676				}
26677
26678				if (inputPose !== null) {
26679
26680					targetRay.matrix.fromArray(inputPose.transform.matrix);
26681					targetRay.matrix.decompose(targetRay.position, targetRay.rotation, targetRay.scale);
26682					targetRay.matrixWorldNeedsUpdate = true;
26683
26684					if (inputPose.linearVelocity) {
26685
26686						targetRay.hasLinearVelocity = true;
26687						targetRay.linearVelocity.copy(inputPose.linearVelocity);
26688
26689					} else {
26690
26691						targetRay.hasLinearVelocity = false;
26692
26693					}
26694
26695					if (inputPose.angularVelocity) {
26696
26697						targetRay.hasAngularVelocity = true;
26698						targetRay.angularVelocity.copy(inputPose.angularVelocity);
26699
26700					} else {
26701
26702						targetRay.hasAngularVelocity = false;
26703
26704					}
26705
26706					this.dispatchEvent(_moveEvent);
26707
26708				}
26709
26710			}
26711
26712
26713		}
26714
26715		if (targetRay !== null) {
26716
26717			targetRay.visible = (inputPose !== null);
26718
26719		}
26720
26721		if (grip !== null) {
26722
26723			grip.visible = (gripPose !== null);
26724
26725		}
26726
26727		if (hand !== null) {
26728
26729			hand.visible = (handPose !== null);
26730
26731		}
26732
26733		return this;
26734
26735	}
26736
26737	// private method
26738
26739	_getHandJoint(hand, inputjoint) {
26740
26741		if (hand.joints[inputjoint.jointName] === undefined) {
26742
26743			const joint = new Group();
26744			joint.matrixAutoUpdate = false;
26745			joint.visible = false;
26746			hand.joints[inputjoint.jointName] = joint;
26747
26748			hand.add(joint);
26749
26750		}
26751
26752		return hand.joints[inputjoint.jointName];
26753
26754	}
26755
26756}
26757
26758class WebXRManager extends EventDispatcher {
26759
26760	constructor(renderer, gl) {
26761
26762		super();
26763
26764		const scope = this;
26765
26766		let session = null;
26767
26768		let framebufferScaleFactor = 1.0;
26769
26770		let referenceSpace = null;
26771		let referenceSpaceType = 'local-floor';
26772		// Set default foveation to maximum.
26773		let foveation = 1.0;
26774		let customReferenceSpace = null;
26775
26776		let pose = null;
26777		let glBinding = null;
26778		let glProjLayer = null;
26779		let glBaseLayer = null;
26780		let xrFrame = null;
26781		const attributes = gl.getContextAttributes();
26782		let initialRenderTarget = null;
26783		let newRenderTarget = null;
26784
26785		const controllers = [];
26786		const controllerInputSources = [];
26787
26788		const currentSize = new Vector2();
26789		let currentPixelRatio = null;
26790
26791		//
26792
26793		const cameraL = new PerspectiveCamera();
26794		cameraL.layers.enable(1);
26795		cameraL.viewport = new Vector4();
26796
26797		const cameraR = new PerspectiveCamera();
26798		cameraR.layers.enable(2);
26799		cameraR.viewport = new Vector4();
26800
26801		const cameras = [cameraL, cameraR];
26802
26803		const cameraXR = new ArrayCamera();
26804		cameraXR.layers.enable(1);
26805		cameraXR.layers.enable(2);
26806
26807		let _currentDepthNear = null;
26808		let _currentDepthFar = null;
26809
26810		//
26811
26812		this.cameraAutoUpdate = true;
26813		this.enabled = false;
26814
26815		this.isPresenting = false;
26816
26817		this.getController = function (index) {
26818
26819			let controller = controllers[index];
26820
26821			if (controller === undefined) {
26822
26823				controller = new WebXRController();
26824				controllers[index] = controller;
26825
26826			}
26827
26828			return controller.getTargetRaySpace();
26829
26830		};
26831
26832		this.getControllerGrip = function (index) {
26833
26834			let controller = controllers[index];
26835
26836			if (controller === undefined) {
26837
26838				controller = new WebXRController();
26839				controllers[index] = controller;
26840
26841			}
26842
26843			return controller.getGripSpace();
26844
26845		};
26846
26847		this.getHand = function (index) {
26848
26849			let controller = controllers[index];
26850
26851			if (controller === undefined) {
26852
26853				controller = new WebXRController();
26854				controllers[index] = controller;
26855
26856			}
26857
26858			return controller.getHandSpace();
26859
26860		};
26861
26862		//
26863
26864		function onSessionEvent(event) {
26865
26866			const controllerIndex = controllerInputSources.indexOf(event.inputSource);
26867
26868			if (controllerIndex === - 1) {
26869
26870				return;
26871
26872			}
26873
26874			const controller = controllers[controllerIndex];
26875
26876			if (controller !== undefined) {
26877
26878				controller.update(event.inputSource, event.frame, customReferenceSpace || referenceSpace);
26879				controller.dispatchEvent({ type: event.type, data: event.inputSource });
26880
26881			}
26882
26883		}
26884
26885		function onSessionEnd() {
26886
26887			session.removeEventListener('select', onSessionEvent);
26888			session.removeEventListener('selectstart', onSessionEvent);
26889			session.removeEventListener('selectend', onSessionEvent);
26890			session.removeEventListener('squeeze', onSessionEvent);
26891			session.removeEventListener('squeezestart', onSessionEvent);
26892			session.removeEventListener('squeezeend', onSessionEvent);
26893			session.removeEventListener('end', onSessionEnd);
26894			session.removeEventListener('inputsourceschange', onInputSourcesChange);
26895
26896			for (let i = 0; i < controllers.length; i++) {
26897
26898				const inputSource = controllerInputSources[i];
26899
26900				if (inputSource === null) continue;
26901
26902				controllerInputSources[i] = null;
26903
26904				controllers[i].disconnect(inputSource);
26905
26906			}
26907
26908			_currentDepthNear = null;
26909			_currentDepthFar = null;
26910
26911			// restore framebuffer/rendering state
26912
26913			renderer.setRenderTarget(initialRenderTarget);
26914
26915			glBaseLayer = null;
26916			glProjLayer = null;
26917			glBinding = null;
26918			session = null;
26919			newRenderTarget = null;
26920
26921			//
26922
26923			animation.stop();
26924
26925			scope.isPresenting = false;
26926
26927			renderer.setPixelRatio(currentPixelRatio);
26928			renderer.setSize(currentSize.width, currentSize.height, false);
26929
26930			scope.dispatchEvent({ type: 'sessionend' });
26931
26932		}
26933
26934		this.setFramebufferScaleFactor = function (value) {
26935
26936			framebufferScaleFactor = value;
26937
26938			if (scope.isPresenting === true) {
26939
26940				console.warn('THREE.WebXRManager: Cannot change framebuffer scale while presenting.');
26941
26942			}
26943
26944		};
26945
26946		this.setReferenceSpaceType = function (value) {
26947
26948			referenceSpaceType = value;
26949
26950			if (scope.isPresenting === true) {
26951
26952				console.warn('THREE.WebXRManager: Cannot change reference space type while presenting.');
26953
26954			}
26955
26956		};
26957
26958		this.getReferenceSpace = function () {
26959
26960			return customReferenceSpace || referenceSpace;
26961
26962		};
26963
26964		this.setReferenceSpace = function (space) {
26965
26966			customReferenceSpace = space;
26967
26968		};
26969
26970		this.getBaseLayer = function () {
26971
26972			return glProjLayer !== null ? glProjLayer : glBaseLayer;
26973
26974		};
26975
26976		this.getBinding = function () {
26977
26978			return glBinding;
26979
26980		};
26981
26982		this.getFrame = function () {
26983
26984			return xrFrame;
26985
26986		};
26987
26988		this.getSession = function () {
26989
26990			return session;
26991
26992		};
26993
26994		this.setSession = async function (value) {
26995
26996			session = value;
26997
26998			if (session !== null) {
26999
27000				initialRenderTarget = renderer.getRenderTarget();
27001
27002				session.addEventListener('select', onSessionEvent);
27003				session.addEventListener('selectstart', onSessionEvent);
27004				session.addEventListener('selectend', onSessionEvent);
27005				session.addEventListener('squeeze', onSessionEvent);
27006				session.addEventListener('squeezestart', onSessionEvent);
27007				session.addEventListener('squeezeend', onSessionEvent);
27008				session.addEventListener('end', onSessionEnd);
27009				session.addEventListener('inputsourceschange', onInputSourcesChange);
27010
27011				if (attributes.xrCompatible !== true) {
27012
27013					await gl.makeXRCompatible();
27014
27015				}
27016
27017				currentPixelRatio = renderer.getPixelRatio();
27018				renderer.getSize(currentSize);
27019
27020				if ((session.renderState.layers === undefined) || (renderer.capabilities.isWebGL2 === false)) {
27021
27022					const layerInit = {
27023						antialias: (session.renderState.layers === undefined) ? attributes.antialias : true,
27024						alpha: true,
27025						depth: attributes.depth,
27026						stencil: attributes.stencil,
27027						framebufferScaleFactor: framebufferScaleFactor
27028					};
27029
27030					glBaseLayer = new XRWebGLLayer(session, gl, layerInit);
27031
27032					session.updateRenderState({ baseLayer: glBaseLayer });
27033
27034					renderer.setPixelRatio(1);
27035					renderer.setSize(glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight, false);
27036
27037					newRenderTarget = new WebGLRenderTarget(
27038						glBaseLayer.framebufferWidth,
27039						glBaseLayer.framebufferHeight,
27040						{
27041							format: RGBAFormat,
27042							type: UnsignedByteType,
27043							colorSpace: renderer.outputColorSpace,
27044							stencilBuffer: attributes.stencil
27045						}
27046					);
27047
27048				} else {
27049
27050					let depthFormat = null;
27051					let depthType = null;
27052					let glDepthFormat = null;
27053
27054					if (attributes.depth) {
27055
27056						glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
27057						depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat;
27058						depthType = attributes.stencil ? UnsignedInt248Type : UnsignedIntType;
27059
27060					}
27061
27062					const projectionlayerInit = {
27063						colorFormat: gl.RGBA8,
27064						depthFormat: glDepthFormat,
27065						scaleFactor: framebufferScaleFactor
27066					};
27067
27068					glBinding = new XRWebGLBinding(session, gl);
27069
27070					glProjLayer = glBinding.createProjectionLayer(projectionlayerInit);
27071
27072					session.updateRenderState({ layers: [glProjLayer] });
27073
27074					renderer.setPixelRatio(1);
27075					renderer.setSize(glProjLayer.textureWidth, glProjLayer.textureHeight, false);
27076
27077					newRenderTarget = new WebGLRenderTarget(
27078						glProjLayer.textureWidth,
27079						glProjLayer.textureHeight,
27080						{
27081							format: RGBAFormat,
27082							type: UnsignedByteType,
27083							depthTexture: new DepthTexture(glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat),
27084							stencilBuffer: attributes.stencil,
27085							colorSpace: renderer.outputColorSpace,
27086							samples: attributes.antialias ? 4 : 0
27087						});
27088
27089					const renderTargetProperties = renderer.properties.get(newRenderTarget);
27090					renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues;
27091
27092				}
27093
27094				newRenderTarget.isXRRenderTarget = true; // TODO Remove this when possible, see #23278
27095
27096				this.setFoveation(foveation);
27097
27098				customReferenceSpace = null;
27099				referenceSpace = await session.requestReferenceSpace(referenceSpaceType);
27100
27101				animation.setContext(session);
27102				animation.start();
27103
27104				scope.isPresenting = true;
27105
27106				scope.dispatchEvent({ type: 'sessionstart' });
27107
27108			}
27109
27110		};
27111
27112		this.getEnvironmentBlendMode = function () {
27113
27114			if (session !== null) {
27115
27116				return session.environmentBlendMode;
27117
27118			}
27119
27120		};
27121
27122		function onInputSourcesChange(event) {
27123
27124			// Notify disconnected
27125
27126			for (let i = 0; i < event.removed.length; i++) {
27127
27128				const inputSource = event.removed[i];
27129				const index = controllerInputSources.indexOf(inputSource);
27130
27131				if (index >= 0) {
27132
27133					controllerInputSources[index] = null;
27134					controllers[index].disconnect(inputSource);
27135
27136				}
27137
27138			}
27139
27140			// Notify connected
27141
27142			for (let i = 0; i < event.added.length; i++) {
27143
27144				const inputSource = event.added[i];
27145
27146				let controllerIndex = controllerInputSources.indexOf(inputSource);
27147
27148				if (controllerIndex === - 1) {
27149
27150					// Assign input source a controller that currently has no input source
27151
27152					for (let i = 0; i < controllers.length; i++) {
27153
27154						if (i >= controllerInputSources.length) {
27155
27156							controllerInputSources.push(inputSource);
27157							controllerIndex = i;
27158							break;
27159
27160						} else if (controllerInputSources[i] === null) {
27161
27162							controllerInputSources[i] = inputSource;
27163							controllerIndex = i;
27164							break;
27165
27166						}
27167
27168					}
27169
27170					// If all controllers do currently receive input we ignore new ones
27171
27172					if (controllerIndex === - 1) break;
27173
27174				}
27175
27176				const controller = controllers[controllerIndex];
27177
27178				if (controller) {
27179
27180					controller.connect(inputSource);
27181
27182				}
27183
27184			}
27185
27186		}
27187
27188		//
27189
27190		const cameraLPos = new Vector3();
27191		const cameraRPos = new Vector3();
27192
27193		/**
27194		 * Assumes 2 cameras that are parallel and share an X-axis, and that
27195		 * the cameras' projection and world matrices have already been set.
27196		 * And that near and far planes are identical for both cameras.
27197		 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
27198		 */
27199		function setProjectionFromUnion(camera, cameraL, cameraR) {
27200
27201			cameraLPos.setFromMatrixPosition(cameraL.matrixWorld);
27202			cameraRPos.setFromMatrixPosition(cameraR.matrixWorld);
27203
27204			const ipd = cameraLPos.distanceTo(cameraRPos);
27205
27206			const projL = cameraL.projectionMatrix.elements;
27207			const projR = cameraR.projectionMatrix.elements;
27208
27209			// VR systems will have identical far and near planes, and
27210			// most likely identical top and bottom frustum extents.
27211			// Use the left camera for these values.
27212			const near = projL[14] / (projL[10] - 1);
27213			const far = projL[14] / (projL[10] + 1);
27214			const topFov = (projL[9] + 1) / projL[5];
27215			const bottomFov = (projL[9] - 1) / projL[5];
27216
27217			const leftFov = (projL[8] - 1) / projL[0];
27218			const rightFov = (projR[8] + 1) / projR[0];
27219			const left = near * leftFov;
27220			const right = near * rightFov;
27221
27222			// Calculate the new camera's position offset from the
27223			// left camera. xOffset should be roughly half `ipd`.
27224			const zOffset = ipd / (- leftFov + rightFov);
27225			const xOffset = zOffset * - leftFov;
27226
27227			// TODO: Better way to apply this offset?
27228			cameraL.matrixWorld.decompose(camera.position, camera.quaternion, camera.scale);
27229			camera.translateX(xOffset);
27230			camera.translateZ(zOffset);
27231			camera.matrixWorld.compose(camera.position, camera.quaternion, camera.scale);
27232			camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
27233
27234			// Find the union of the frustum values of the cameras and scale
27235			// the values so that the near plane's position does not change in world space,
27236			// although must now be relative to the new union camera.
27237			const near2 = near + zOffset;
27238			const far2 = far + zOffset;
27239			const left2 = left - xOffset;
27240			const right2 = right + (ipd - xOffset);
27241			const top2 = topFov * far / far2 * near2;
27242			const bottom2 = bottomFov * far / far2 * near2;
27243
27244			camera.projectionMatrix.makePerspective(left2, right2, top2, bottom2, near2, far2);
27245			camera.projectionMatrixInverse.copy(camera.projectionMatrix).invert();
27246
27247		}
27248
27249		function updateCamera(camera, parent) {
27250
27251			if (parent === null) {
27252
27253				camera.matrixWorld.copy(camera.matrix);
27254
27255			} else {
27256
27257				camera.matrixWorld.multiplyMatrices(parent.matrixWorld, camera.matrix);
27258
27259			}
27260
27261			camera.matrixWorldInverse.copy(camera.matrixWorld).invert();
27262
27263		}
27264
27265		this.updateCamera = function (camera) {
27266
27267			if (session === null) return;
27268
27269			cameraXR.near = cameraR.near = cameraL.near = camera.near;
27270			cameraXR.far = cameraR.far = cameraL.far = camera.far;
27271
27272			if (_currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far) {
27273
27274				// Note that the new renderState won't apply until the next frame. See #18320
27275
27276				session.updateRenderState({
27277					depthNear: cameraXR.near,
27278					depthFar: cameraXR.far
27279				});
27280
27281				_currentDepthNear = cameraXR.near;
27282				_currentDepthFar = cameraXR.far;
27283
27284			}
27285
27286			const parent = camera.parent;
27287			const cameras = cameraXR.cameras;
27288
27289			updateCamera(cameraXR, parent);
27290
27291			for (let i = 0; i < cameras.length; i++) {
27292
27293				updateCamera(cameras[i], parent);
27294
27295			}
27296
27297			// update projection matrix for proper view frustum culling
27298
27299			if (cameras.length === 2) {
27300
27301				setProjectionFromUnion(cameraXR, cameraL, cameraR);
27302
27303			} else {
27304
27305				// assume single camera setup (AR)
27306
27307				cameraXR.projectionMatrix.copy(cameraL.projectionMatrix);
27308
27309			}
27310
27311			// update user camera and its children
27312
27313			updateUserCamera(camera, cameraXR, parent);
27314
27315		};
27316
27317		function updateUserCamera(camera, cameraXR, parent) {
27318
27319			if (parent === null) {
27320
27321				camera.matrix.copy(cameraXR.matrixWorld);
27322
27323			} else {
27324
27325				camera.matrix.copy(parent.matrixWorld);
27326				camera.matrix.invert();
27327				camera.matrix.multiply(cameraXR.matrixWorld);
27328
27329			}
27330
27331			camera.matrix.decompose(camera.position, camera.quaternion, camera.scale);
27332			camera.updateMatrixWorld(true);
27333
27334			camera.projectionMatrix.copy(cameraXR.projectionMatrix);
27335			camera.projectionMatrixInverse.copy(cameraXR.projectionMatrixInverse);
27336
27337			if (camera.isPerspectiveCamera) {
27338
27339				camera.fov = RAD2DEG * 2 * Math.atan(1 / camera.projectionMatrix.elements[5]);
27340				camera.zoom = 1;
27341
27342			}
27343
27344		}
27345
27346		this.getCamera = function () {
27347
27348			return cameraXR;
27349
27350		};
27351
27352		this.getFoveation = function () {
27353
27354			if (glProjLayer === null && glBaseLayer === null) {
27355
27356				return undefined;
27357
27358			}
27359
27360			return foveation;
27361
27362		};
27363
27364		this.setFoveation = function (value) {
27365
27366			// 0 = no foveation = full resolution
27367			// 1 = maximum foveation = the edges render at lower resolution
27368
27369			foveation = value;
27370
27371			if (glProjLayer !== null) {
27372
27373				glProjLayer.fixedFoveation = value;
27374
27375			}
27376
27377			if (glBaseLayer !== null && glBaseLayer.fixedFoveation !== undefined) {
27378
27379				glBaseLayer.fixedFoveation = value;
27380
27381			}
27382
27383		};
27384
27385		// Animation Loop
27386
27387		let onAnimationFrameCallback = null;
27388
27389		function onAnimationFrame(time, frame) {
27390
27391			pose = frame.getViewerPose(customReferenceSpace || referenceSpace);
27392			xrFrame = frame;
27393
27394			if (pose !== null) {
27395
27396				const views = pose.views;
27397
27398				if (glBaseLayer !== null) {
27399
27400					renderer.setRenderTargetFramebuffer(newRenderTarget, glBaseLayer.framebuffer);
27401					renderer.setRenderTarget(newRenderTarget);
27402
27403				}
27404
27405				let cameraXRNeedsUpdate = false;
27406
27407				// check if it's necessary to rebuild cameraXR's camera list
27408
27409				if (views.length !== cameraXR.cameras.length) {
27410
27411					cameraXR.cameras.length = 0;
27412					cameraXRNeedsUpdate = true;
27413
27414				}
27415
27416				for (let i = 0; i < views.length; i++) {
27417
27418					const view = views[i];
27419
27420					let viewport = null;
27421
27422					if (glBaseLayer !== null) {
27423
27424						viewport = glBaseLayer.getViewport(view);
27425
27426					} else {
27427
27428						const glSubImage = glBinding.getViewSubImage(glProjLayer, view);
27429						viewport = glSubImage.viewport;
27430
27431						// For side-by-side projection, we only produce a single texture for both eyes.
27432						if (i === 0) {
27433
27434							renderer.setRenderTargetTextures(
27435								newRenderTarget,
27436								glSubImage.colorTexture,
27437								glProjLayer.ignoreDepthValues ? undefined : glSubImage.depthStencilTexture);
27438
27439							renderer.setRenderTarget(newRenderTarget);
27440
27441						}
27442
27443					}
27444
vendor: 6,300 bytes, lines 27445-27730
27445					let camera = cameras[i];
27446
27447					if (camera === undefined) {
27448
27449						camera = new PerspectiveCamera();
27450						camera.layers.enable(i);
27451						camera.viewport = new Vector4();
27452						cameras[i] = camera;
27453
27454					}
27455
27456					camera.matrix.fromArray(view.transform.matrix);
27457					camera.matrix.decompose(camera.position, camera.quaternion, camera.scale);
27458					camera.projectionMatrix.fromArray(view.projectionMatrix);
27459					camera.projectionMatrixInverse.copy(camera.projectionMatrix).invert();
27460					camera.viewport.set(viewport.x, viewport.y, viewport.width, viewport.height);
27461
27462					if (i === 0) {
27463
27464						cameraXR.matrix.copy(camera.matrix);
27465						cameraXR.matrix.decompose(cameraXR.position, cameraXR.quaternion, cameraXR.scale);
27466
27467					}
27468
27469					if (cameraXRNeedsUpdate === true) {
27470
27471						cameraXR.cameras.push(camera);
27472
27473					}
27474
27475				}
27476
27477			}
27478
27479			//
27480
27481			for (let i = 0; i < controllers.length; i++) {
27482
27483				const inputSource = controllerInputSources[i];
27484				const controller = controllers[i];
27485
27486				if (inputSource !== null && controller !== undefined) {
27487
27488					controller.update(inputSource, frame, customReferenceSpace || referenceSpace);
27489
27490				}
27491
27492			}
27493
27494			if (onAnimationFrameCallback) onAnimationFrameCallback(time, frame);
27495
27496			if (frame.detectedPlanes) {
27497
27498				scope.dispatchEvent({ type: 'planesdetected', data: frame });
27499
27500			}
27501
27502			xrFrame = null;
27503
27504		}
27505
27506		const animation = new WebGLAnimation();
27507
27508		animation.setAnimationLoop(onAnimationFrame);
27509
27510		this.setAnimationLoop = function (callback) {
27511
27512			onAnimationFrameCallback = callback;
27513
27514		};
27515
27516		this.dispose = function () { };
27517
27518	}
27519
27520}
27521
27522function WebGLMaterials(renderer, properties) {
27523
27524	function refreshTransformUniform(map, uniform) {
27525
27526		if (map.matrixAutoUpdate === true) {
27527
27528			map.updateMatrix();
27529
27530		}
27531
27532		uniform.value.copy(map.matrix);
27533
27534	}
27535
27536	function refreshFogUniforms(uniforms, fog) {
27537
27538		fog.color.getRGB(uniforms.fogColor.value, getUnlitUniformColorSpace(renderer));
27539
27540		if (fog.isFog) {
27541
27542			uniforms.fogNear.value = fog.near;
27543			uniforms.fogFar.value = fog.far;
27544
27545		} else if (fog.isFogExp2) {
27546
27547			uniforms.fogDensity.value = fog.density;
27548
27549		}
27550
27551	}
27552
27553	function refreshMaterialUniforms(uniforms, material, pixelRatio, height, transmissionRenderTarget) {
27554
27555		if (material.isMeshBasicMaterial) {
27556
27557			refreshUniformsCommon(uniforms, material);
27558
27559		} else if (material.isMeshLambertMaterial) {
27560
27561			refreshUniformsCommon(uniforms, material);
27562
27563		} else if (material.isMeshToonMaterial) {
27564
27565			refreshUniformsCommon(uniforms, material);
27566			refreshUniformsToon(uniforms, material);
27567
27568		} else if (material.isMeshPhongMaterial) {
27569
27570			refreshUniformsCommon(uniforms, material);
27571			refreshUniformsPhong(uniforms, material);
27572
27573		} else if (material.isMeshStandardMaterial) {
27574
27575			refreshUniformsCommon(uniforms, material);
27576			refreshUniformsStandard(uniforms, material);
27577
27578			if (material.isMeshPhysicalMaterial) {
27579
27580				refreshUniformsPhysical(uniforms, material, transmissionRenderTarget);
27581
27582			}
27583
27584		} else if (material.isMeshMatcapMaterial) {
27585
27586			refreshUniformsCommon(uniforms, material);
27587			refreshUniformsMatcap(uniforms, material);
27588
27589		} else if (material.isMeshDepthMaterial) {
27590
27591			refreshUniformsCommon(uniforms, material);
27592
27593		} else if (material.isMeshDistanceMaterial) {
27594
27595			refreshUniformsCommon(uniforms, material);
27596			refreshUniformsDistance(uniforms, material);
27597
27598		} else if (material.isMeshNormalMaterial) {
27599
27600			refreshUniformsCommon(uniforms, material);
27601
27602		} else if (material.isLineBasicMaterial) {
27603
27604			refreshUniformsLine(uniforms, material);
27605
27606			if (material.isLineDashedMaterial) {
27607
27608				refreshUniformsDash(uniforms, material);
27609
27610			}
27611
27612		} else if (material.isPointsMaterial) {
27613
27614			refreshUniformsPoints(uniforms, material, pixelRatio, height);
27615
27616		} else if (material.isSpriteMaterial) {
27617
27618			refreshUniformsSprites(uniforms, material);
27619
27620		} else if (material.isShadowMaterial) {
27621
27622			uniforms.color.value.copy(material.color);
27623			uniforms.opacity.value = material.opacity;
27624
27625		} else if (material.isShaderMaterial) {
27626
27627			material.uniformsNeedUpdate = false; // #15581
27628
27629		}
27630
27631	}
27632
27633	function refreshUniformsCommon(uniforms, material) {
27634
27635		uniforms.opacity.value = material.opacity;
27636
27637		if (material.color) {
27638
27639			uniforms.diffuse.value.copy(material.color);
27640
27641		}
27642
27643		if (material.emissive) {
27644
27645			uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity);
27646
27647		}
27648
27649		if (material.map) {
27650
27651			uniforms.map.value = material.map;
27652
27653			refreshTransformUniform(material.map, uniforms.mapTransform);
27654
27655		}
27656
27657		if (material.alphaMap) {
27658
27659			uniforms.alphaMap.value = material.alphaMap;
27660
27661			refreshTransformUniform(material.alphaMap, uniforms.alphaMapTransform);
27662
27663		}
27664
27665		if (material.bumpMap) {
27666
27667			uniforms.bumpMap.value = material.bumpMap;
27668
27669			refreshTransformUniform(material.bumpMap, uniforms.bumpMapTransform);
27670
27671			uniforms.bumpScale.value = material.bumpScale;
27672
27673			if (material.side === BackSide) {
27674
27675				uniforms.bumpScale.value *= - 1;
27676
27677			}
27678
27679		}
27680
27681		if (material.normalMap) {
27682
27683			uniforms.normalMap.value = material.normalMap;
27684
27685			refreshTransformUniform(material.normalMap, uniforms.normalMapTransform);
27686
27687			uniforms.normalScale.value.copy(material.normalScale);
27688
27689			if (material.side === BackSide) {
27690
27691				uniforms.normalScale.value.negate();
27692
27693			}
27694
27695		}
27696
27697		if (material.displacementMap) {
27698
27699			uniforms.displacementMap.value = material.displacementMap;
27700
27701			refreshTransformUniform(material.displacementMap, uniforms.displacementMapTransform);
27702
27703			uniforms.displacementScale.value = material.displacementScale;
27704			uniforms.displacementBias.value = material.displacementBias;
27705
27706		}
27707
27708		if (material.emissiveMap) {
27709
27710			uniforms.emissiveMap.value = material.emissiveMap;
27711
27712			refreshTransformUniform(material.emissiveMap, uniforms.emissiveMapTransform);
27713
27714		}
27715
27716		if (material.specularMap) {
27717
27718			uniforms.specularMap.value = material.specularMap;
27719
27720			refreshTransformUniform(material.specularMap, uniforms.specularMapTransform);
27721
27722		}
27723
27724		if (material.alphaTest > 0) {
27725
27726			uniforms.alphaTest.value = material.alphaTest;
27727
27728		}
27729
27730		const envMap = properties.get(material).envMap;
vendor: 85,181 bytes, lines 27731-31041
27731
27732		if (envMap) {
27733
27734			uniforms.envMap.value = envMap;
27735
27736			uniforms.flipEnvMap.value = (envMap.isCubeTexture && envMap.isRenderTargetTexture === false) ? - 1 : 1;
27737
27738			uniforms.reflectivity.value = material.reflectivity;
27739			uniforms.ior.value = material.ior;
27740			uniforms.refractionRatio.value = material.refractionRatio;
27741
27742		}
27743
27744		if (material.lightMap) {
27745
27746			uniforms.lightMap.value = material.lightMap;
27747
27748			// artist-friendly light intensity scaling factor
27749			const scaleFactor = (renderer._useLegacyLights === true) ? Math.PI : 1;
27750
27751			uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor;
27752
27753			refreshTransformUniform(material.lightMap, uniforms.lightMapTransform);
27754
27755		}
27756
27757		if (material.aoMap) {
27758
27759			uniforms.aoMap.value = material.aoMap;
27760			uniforms.aoMapIntensity.value = material.aoMapIntensity;
27761
27762			refreshTransformUniform(material.aoMap, uniforms.aoMapTransform);
27763
27764		}
27765
27766	}
27767
27768	function refreshUniformsLine(uniforms, material) {
27769
27770		uniforms.diffuse.value.copy(material.color);
27771		uniforms.opacity.value = material.opacity;
27772
27773		if (material.map) {
27774
27775			uniforms.map.value = material.map;
27776
27777			refreshTransformUniform(material.map, uniforms.mapTransform);
27778
27779		}
27780
27781	}
27782
27783	function refreshUniformsDash(uniforms, material) {
27784
27785		uniforms.dashSize.value = material.dashSize;
27786		uniforms.totalSize.value = material.dashSize + material.gapSize;
27787		uniforms.scale.value = material.scale;
27788
27789	}
27790
27791	function refreshUniformsPoints(uniforms, material, pixelRatio, height) {
27792
27793		uniforms.diffuse.value.copy(material.color);
27794		uniforms.opacity.value = material.opacity;
27795		uniforms.size.value = material.size * pixelRatio;
27796		uniforms.scale.value = height * 0.5;
27797
27798		if (material.map) {
27799
27800			uniforms.map.value = material.map;
27801
27802			refreshTransformUniform(material.map, uniforms.uvTransform);
27803
27804		}
27805
27806		if (material.alphaMap) {
27807
27808			uniforms.alphaMap.value = material.alphaMap;
27809
27810			refreshTransformUniform(material.alphaMap, uniforms.alphaMapTransform);
27811
27812		}
27813
27814		if (material.alphaTest > 0) {
27815
27816			uniforms.alphaTest.value = material.alphaTest;
27817
27818		}
27819
27820	}
27821
27822	function refreshUniformsSprites(uniforms, material) {
27823
27824		uniforms.diffuse.value.copy(material.color);
27825		uniforms.opacity.value = material.opacity;
27826		uniforms.rotation.value = material.rotation;
27827
27828		if (material.map) {
27829
27830			uniforms.map.value = material.map;
27831
27832			refreshTransformUniform(material.map, uniforms.mapTransform);
27833
27834		}
27835
27836		if (material.alphaMap) {
27837
27838			uniforms.alphaMap.value = material.alphaMap;
27839
27840			refreshTransformUniform(material.alphaMap, uniforms.alphaMapTransform);
27841
27842		}
27843
27844		if (material.alphaTest > 0) {
27845
27846			uniforms.alphaTest.value = material.alphaTest;
27847
27848		}
27849
27850	}
27851
27852	function refreshUniformsPhong(uniforms, material) {
27853
27854		uniforms.specular.value.copy(material.specular);
27855		uniforms.shininess.value = Math.max(material.shininess, 1e-4); // to prevent pow( 0.0, 0.0 )
27856
27857	}
27858
27859	function refreshUniformsToon(uniforms, material) {
27860
27861		if (material.gradientMap) {
27862
27863			uniforms.gradientMap.value = material.gradientMap;
27864
27865		}
27866
27867	}
27868
27869	function refreshUniformsStandard(uniforms, material) {
27870
27871		uniforms.metalness.value = material.metalness;
27872
27873		if (material.metalnessMap) {
27874
27875			uniforms.metalnessMap.value = material.metalnessMap;
27876
27877			refreshTransformUniform(material.metalnessMap, uniforms.metalnessMapTransform);
27878
27879		}
27880
27881		uniforms.roughness.value = material.roughness;
27882
27883		if (material.roughnessMap) {
27884
27885			uniforms.roughnessMap.value = material.roughnessMap;
27886
27887			refreshTransformUniform(material.roughnessMap, uniforms.roughnessMapTransform);
27888
27889		}
27890
27891		const envMap = properties.get(material).envMap;
27892
27893		if (envMap) {
27894
27895			//uniforms.envMap.value = material.envMap; // part of uniforms common
27896			uniforms.envMapIntensity.value = material.envMapIntensity;
27897
27898		}
27899
27900	}
27901
27902	function refreshUniformsPhysical(uniforms, material, transmissionRenderTarget) {
27903
27904		uniforms.ior.value = material.ior; // also part of uniforms common
27905
27906		if (material.sheen > 0) {
27907
27908			uniforms.sheenColor.value.copy(material.sheenColor).multiplyScalar(material.sheen);
27909
27910			uniforms.sheenRoughness.value = material.sheenRoughness;
27911
27912			if (material.sheenColorMap) {
27913
27914				uniforms.sheenColorMap.value = material.sheenColorMap;
27915
27916				refreshTransformUniform(material.sheenColorMap, uniforms.sheenColorMapTransform);
27917
27918			}
27919
27920			if (material.sheenRoughnessMap) {
27921
27922				uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap;
27923
27924				refreshTransformUniform(material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform);
27925
27926			}
27927
27928		}
27929
27930		if (material.clearcoat > 0) {
27931
27932			uniforms.clearcoat.value = material.clearcoat;
27933			uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
27934
27935			if (material.clearcoatMap) {
27936
27937				uniforms.clearcoatMap.value = material.clearcoatMap;
27938
27939				refreshTransformUniform(material.clearcoatMap, uniforms.clearcoatMapTransform);
27940
27941			}
27942
27943			if (material.clearcoatRoughnessMap) {
27944
27945				uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
27946
27947				refreshTransformUniform(material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform);
27948
27949			}
27950
27951			if (material.clearcoatNormalMap) {
27952
27953				uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
27954
27955				refreshTransformUniform(material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform);
27956
27957				uniforms.clearcoatNormalScale.value.copy(material.clearcoatNormalScale);
27958
27959				if (material.side === BackSide) {
27960
27961					uniforms.clearcoatNormalScale.value.negate();
27962
27963				}
27964
27965			}
27966
27967		}
27968
27969		if (material.iridescence > 0) {
27970
27971			uniforms.iridescence.value = material.iridescence;
27972			uniforms.iridescenceIOR.value = material.iridescenceIOR;
27973			uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[0];
27974			uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[1];
27975
27976			if (material.iridescenceMap) {
27977
27978				uniforms.iridescenceMap.value = material.iridescenceMap;
27979
27980				refreshTransformUniform(material.iridescenceMap, uniforms.iridescenceMapTransform);
27981
27982			}
27983
27984			if (material.iridescenceThicknessMap) {
27985
27986				uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap;
27987
27988				refreshTransformUniform(material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform);
27989
27990			}
27991
27992		}
27993
27994		if (material.transmission > 0) {
27995
27996			uniforms.transmission.value = material.transmission;
27997			uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
27998			uniforms.transmissionSamplerSize.value.set(transmissionRenderTarget.width, transmissionRenderTarget.height);
27999
28000			if (material.transmissionMap) {
28001
28002				uniforms.transmissionMap.value = material.transmissionMap;
28003
28004				refreshTransformUniform(material.transmissionMap, uniforms.transmissionMapTransform);
28005
28006			}
28007
28008			uniforms.thickness.value = material.thickness;
28009
28010			if (material.thicknessMap) {
28011
28012				uniforms.thicknessMap.value = material.thicknessMap;
28013
28014				refreshTransformUniform(material.thicknessMap, uniforms.thicknessMapTransform);
28015
28016			}
28017
28018			uniforms.attenuationDistance.value = material.attenuationDistance;
28019			uniforms.attenuationColor.value.copy(material.attenuationColor);
28020
28021		}
28022
28023		if (material.anisotropy > 0) {
28024
28025			uniforms.anisotropyVector.value.set(material.anisotropy * Math.cos(material.anisotropyRotation), material.anisotropy * Math.sin(material.anisotropyRotation));
28026
28027			if (material.anisotropyMap) {
28028
28029				uniforms.anisotropyMap.value = material.anisotropyMap;
28030
28031				refreshTransformUniform(material.anisotropyMap, uniforms.anisotropyMapTransform);
28032
28033			}
28034
28035		}
28036
28037		uniforms.specularIntensity.value = material.specularIntensity;
28038		uniforms.specularColor.value.copy(material.specularColor);
28039
28040		if (material.specularColorMap) {
28041
28042			uniforms.specularColorMap.value = material.specularColorMap;
28043
28044			refreshTransformUniform(material.specularColorMap, uniforms.specularColorMapTransform);
28045
28046		}
28047
28048		if (material.specularIntensityMap) {
28049
28050			uniforms.specularIntensityMap.value = material.specularIntensityMap;
28051
28052			refreshTransformUniform(material.specularIntensityMap, uniforms.specularIntensityMapTransform);
28053
28054		}
28055
28056	}
28057
28058	function refreshUniformsMatcap(uniforms, material) {
28059
28060		if (material.matcap) {
28061
28062			uniforms.matcap.value = material.matcap;
28063
28064		}
28065
28066	}
28067
28068	function refreshUniformsDistance(uniforms, material) {
28069
28070		const light = properties.get(material).light;
28071
28072		uniforms.referencePosition.value.setFromMatrixPosition(light.matrixWorld);
28073		uniforms.nearDistance.value = light.shadow.camera.near;
28074		uniforms.farDistance.value = light.shadow.camera.far;
28075
28076	}
28077
28078	return {
28079		refreshFogUniforms: refreshFogUniforms,
28080		refreshMaterialUniforms: refreshMaterialUniforms
28081	};
28082
28083}
28084
28085function WebGLUniformsGroups(gl, info, capabilities, state) {
28086
28087	let buffers = {};
28088	let updateList = {};
28089	let allocatedBindingPoints = [];
28090
28091	const maxBindingPoints = (capabilities.isWebGL2) ? gl.getParameter(gl.MAX_UNIFORM_BUFFER_BINDINGS) : 0; // binding points are global whereas block indices are per shader program
28092
28093	function bind(uniformsGroup, program) {
28094
28095		const webglProgram = program.program;
28096		state.uniformBlockBinding(uniformsGroup, webglProgram);
28097
28098	}
28099
28100	function update(uniformsGroup, program) {
28101
28102		let buffer = buffers[uniformsGroup.id];
28103
28104		if (buffer === undefined) {
28105
28106			prepareUniformsGroup(uniformsGroup);
28107
28108			buffer = createBuffer(uniformsGroup);
28109			buffers[uniformsGroup.id] = buffer;
28110
28111			uniformsGroup.addEventListener('dispose', onUniformsGroupsDispose);
28112
28113		}
28114
28115		// ensure to update the binding points/block indices mapping for this program
28116
28117		const webglProgram = program.program;
28118		state.updateUBOMapping(uniformsGroup, webglProgram);
28119
28120		// update UBO once per frame
28121
28122		const frame = info.render.frame;
28123
28124		if (updateList[uniformsGroup.id] !== frame) {
28125
28126			updateBufferData(uniformsGroup);
28127
28128			updateList[uniformsGroup.id] = frame;
28129
28130		}
28131
28132	}
28133
28134	function createBuffer(uniformsGroup) {
28135
28136		// the setup of an UBO is independent of a particular shader program but global
28137
28138		const bindingPointIndex = allocateBindingPointIndex();
28139		uniformsGroup.__bindingPointIndex = bindingPointIndex;
28140
28141		const buffer = gl.createBuffer();
28142		const size = uniformsGroup.__size;
28143		const usage = uniformsGroup.usage;
28144
28145		gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
28146		gl.bufferData(gl.UNIFORM_BUFFER, size, usage);
28147		gl.bindBuffer(gl.UNIFORM_BUFFER, null);
28148		gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPointIndex, buffer);
28149
28150		return buffer;
28151
28152	}
28153
28154	function allocateBindingPointIndex() {
28155
28156		for (let i = 0; i < maxBindingPoints; i++) {
28157
28158			if (allocatedBindingPoints.indexOf(i) === - 1) {
28159
28160				allocatedBindingPoints.push(i);
28161				return i;
28162
28163			}
28164
28165		}
28166
28167		console.error('THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.');
28168
28169		return 0;
28170
28171	}
28172
28173	function updateBufferData(uniformsGroup) {
28174
28175		const buffer = buffers[uniformsGroup.id];
28176		const uniforms = uniformsGroup.uniforms;
28177		const cache = uniformsGroup.__cache;
28178
28179		gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
28180
28181		for (let i = 0, il = uniforms.length; i < il; i++) {
28182
28183			const uniformArray = Array.isArray(uniforms[i]) ? uniforms[i] : [uniforms[i]];
28184
28185			for (let j = 0, jl = uniformArray.length; j < jl; j++) {
28186
28187				const uniform = uniformArray[j];
28188
28189				if (hasUniformChanged(uniform, i, j, cache) === true) {
28190
28191					const offset = uniform.__offset;
28192
28193					const values = Array.isArray(uniform.value) ? uniform.value : [uniform.value];
28194
28195					let arrayOffset = 0;
28196
28197					for (let k = 0; k < values.length; k++) {
28198
28199						const value = values[k];
28200
28201						const info = getUniformSize(value);
28202
28203						// TODO add integer and struct support
28204						if (typeof value === 'number' || typeof value === 'boolean') {
28205
28206							uniform.__data[0] = value;
28207							gl.bufferSubData(gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data);
28208
28209						} else if (value.isMatrix3) {
28210
28211							// manually converting 3x3 to 3x4
28212
28213							uniform.__data[0] = value.elements[0];
28214							uniform.__data[1] = value.elements[1];
28215							uniform.__data[2] = value.elements[2];
28216							uniform.__data[3] = 0;
28217							uniform.__data[4] = value.elements[3];
28218							uniform.__data[5] = value.elements[4];
28219							uniform.__data[6] = value.elements[5];
28220							uniform.__data[7] = 0;
28221							uniform.__data[8] = value.elements[6];
28222							uniform.__data[9] = value.elements[7];
28223							uniform.__data[10] = value.elements[8];
28224							uniform.__data[11] = 0;
28225
28226						} else {
28227
28228							value.toArray(uniform.__data, arrayOffset);
28229
28230							arrayOffset += info.storage / Float32Array.BYTES_PER_ELEMENT;
28231
28232						}
28233
28234					}
28235
28236					gl.bufferSubData(gl.UNIFORM_BUFFER, offset, uniform.__data);
28237
28238				}
28239
28240			}
28241
28242		}
28243
28244		gl.bindBuffer(gl.UNIFORM_BUFFER, null);
28245
28246	}
28247
28248	function hasUniformChanged(uniform, index, indexArray, cache) {
28249
28250		const value = uniform.value;
28251		const indexString = index + '_' + indexArray;
28252
28253		if (cache[indexString] === undefined) {
28254
28255			// cache entry does not exist so far
28256
28257			if (typeof value === 'number' || typeof value === 'boolean') {
28258
28259				cache[indexString] = value;
28260
28261			} else {
28262
28263				cache[indexString] = value.clone();
28264
28265			}
28266
28267			return true;
28268
28269		} else {
28270
28271			const cachedObject = cache[indexString];
28272
28273			// compare current value with cached entry
28274
28275			if (typeof value === 'number' || typeof value === 'boolean') {
28276
28277				if (cachedObject !== value) {
28278
28279					cache[indexString] = value;
28280					return true;
28281
28282				}
28283
28284			} else {
28285
28286				if (cachedObject.equals(value) === false) {
28287
28288					cachedObject.copy(value);
28289					return true;
28290
28291				}
28292
28293			}
28294
28295		}
28296
28297		return false;
28298
28299	}
28300
28301	function prepareUniformsGroup(uniformsGroup) {
28302
28303		// determine total buffer size according to the STD140 layout
28304		// Hint: STD140 is the only supported layout in WebGL 2
28305
28306		const uniforms = uniformsGroup.uniforms;
28307
28308		let offset = 0; // global buffer offset in bytes
28309		const chunkSize = 16; // size of a chunk in bytes
28310
28311		for (let i = 0, l = uniforms.length; i < l; i++) {
28312
28313			const uniformArray = Array.isArray(uniforms[i]) ? uniforms[i] : [uniforms[i]];
28314
28315			for (let j = 0, jl = uniformArray.length; j < jl; j++) {
28316
28317				const uniform = uniformArray[j];
28318
28319				const values = Array.isArray(uniform.value) ? uniform.value : [uniform.value];
28320
28321				for (let k = 0, kl = values.length; k < kl; k++) {
28322
28323					const value = values[k];
28324
28325					const info = getUniformSize(value);
28326
28327					// Calculate the chunk offset
28328					const chunkOffsetUniform = offset % chunkSize;
28329
28330					// Check for chunk overflow
28331					if (chunkOffsetUniform !== 0 && (chunkSize - chunkOffsetUniform) < info.boundary) {
28332
28333						// Add padding and adjust offset
28334						offset += (chunkSize - chunkOffsetUniform);
28335
28336					}
28337
28338					// the following two properties will be used for partial buffer updates
28339
28340					uniform.__data = new Float32Array(info.storage / Float32Array.BYTES_PER_ELEMENT);
28341					uniform.__offset = offset;
28342
28343
28344					// Update the global offset
28345					offset += info.storage;
28346
28347
28348				}
28349
28350			}
28351
28352		}
28353
28354		// ensure correct final padding
28355
28356		const chunkOffset = offset % chunkSize;
28357
28358		if (chunkOffset > 0) offset += (chunkSize - chunkOffset);
28359
28360		//
28361
28362		uniformsGroup.__size = offset;
28363		uniformsGroup.__cache = {};
28364
28365		return this;
28366
28367	}
28368
28369	function getUniformSize(value) {
28370
28371		const info = {
28372			boundary: 0, // bytes
28373			storage: 0 // bytes
28374		};
28375
28376		// determine sizes according to STD140
28377
28378		if (typeof value === 'number' || typeof value === 'boolean') {
28379
28380			// float/int/bool
28381
28382			info.boundary = 4;
28383			info.storage = 4;
28384
28385		} else if (value.isVector2) {
28386
28387			// vec2
28388
28389			info.boundary = 8;
28390			info.storage = 8;
28391
28392		} else if (value.isVector3 || value.isColor) {
28393
28394			// vec3
28395
28396			info.boundary = 16;
28397			info.storage = 12; // evil: vec3 must start on a 16-byte boundary but it only consumes 12 bytes
28398
28399		} else if (value.isVector4) {
28400
28401			// vec4
28402
28403			info.boundary = 16;
28404			info.storage = 16;
28405
28406		} else if (value.isMatrix3) {
28407
28408			// mat3 (in STD140 a 3x3 matrix is represented as 3x4)
28409
28410			info.boundary = 48;
28411			info.storage = 48;
28412
28413		} else if (value.isMatrix4) {
28414
28415			// mat4
28416
28417			info.boundary = 64;
28418			info.storage = 64;
28419
28420		} else if (value.isTexture) {
28421
28422			console.warn('THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.');
28423
28424		} else {
28425
28426			console.warn('THREE.WebGLRenderer: Unsupported uniform value type.', value);
28427
28428		}
28429
28430		return info;
28431
28432	}
28433
28434	function onUniformsGroupsDispose(event) {
28435
28436		const uniformsGroup = event.target;
28437
28438		uniformsGroup.removeEventListener('dispose', onUniformsGroupsDispose);
28439
28440		const index = allocatedBindingPoints.indexOf(uniformsGroup.__bindingPointIndex);
28441		allocatedBindingPoints.splice(index, 1);
28442
28443		gl.deleteBuffer(buffers[uniformsGroup.id]);
28444
28445		delete buffers[uniformsGroup.id];
28446		delete updateList[uniformsGroup.id];
28447
28448	}
28449
28450	function dispose() {
28451
28452		for (const id in buffers) {
28453
28454			gl.deleteBuffer(buffers[id]);
28455
28456		}
28457
28458		allocatedBindingPoints = [];
28459		buffers = {};
28460		updateList = {};
28461
28462	}
28463
28464	return {
28465
28466		bind: bind,
28467		update: update,
28468
28469		dispose: dispose
28470
28471	};
28472
28473}
28474
28475class WebGLRenderer {
28476
28477	constructor(parameters = {}) {
28478
28479		const {
28480			canvas = createCanvasElement(),
28481			context = null,
28482			depth = true,
28483			stencil = true,
28484			alpha = false,
28485			antialias = false,
28486			premultipliedAlpha = true,
28487			preserveDrawingBuffer = false,
28488			powerPreference = 'default',
28489			failIfMajorPerformanceCaveat = false,
28490		} = parameters;
28491
28492		this.isWebGLRenderer = true;
28493
28494		let _alpha;
28495
28496		if (context !== null) {
28497
28498			_alpha = context.getContextAttributes().alpha;
28499
28500		} else {
28501
28502			_alpha = alpha;
28503
28504		}
28505
28506		const uintClearColor = new Uint32Array(4);
28507		const intClearColor = new Int32Array(4);
28508
28509		let currentRenderList = null;
28510		let currentRenderState = null;
28511
28512		// render() can be called from within a callback triggered by another render.
28513		// We track this so that the nested render call gets its list and state isolated from the parent render call.
28514
28515		const renderListStack = [];
28516		const renderStateStack = [];
28517
28518		// public properties
28519
28520		this.domElement = canvas;
28521
28522		// Debug configuration container
28523		this.debug = {
28524
28525			/**
28526			 * Enables error checking and reporting when shader programs are being compiled
28527			 * @type {boolean}
28528			 */
28529			checkShaderErrors: true,
28530			/**
28531			 * Callback for custom error reporting.
28532			 * @type {?Function}
28533			 */
28534			onShaderError: null
28535		};
28536
28537		// clearing
28538
28539		this.autoClear = true;
28540		this.autoClearColor = true;
28541		this.autoClearDepth = true;
28542		this.autoClearStencil = true;
28543
28544		// scene graph
28545
28546		this.sortObjects = true;
28547
28548		// user-defined clipping
28549
28550		this.clippingPlanes = [];
28551		this.localClippingEnabled = false;
28552
28553		// physically based shading
28554
28555		this._outputColorSpace = SRGBColorSpace;
28556
28557		// physical lights
28558
28559		this._useLegacyLights = false;
28560
28561		// tone mapping
28562
28563		this.toneMapping = NoToneMapping;
28564		this.toneMappingExposure = 1.0;
28565
28566		// internal properties
28567
28568		const _this = this;
28569
28570		let _isContextLost = false;
28571
28572		// internal state cache
28573
28574		let _currentActiveCubeFace = 0;
28575		let _currentActiveMipmapLevel = 0;
28576		let _currentRenderTarget = null;
28577		let _currentMaterialId = - 1;
28578
28579		let _currentCamera = null;
28580
28581		const _currentViewport = new Vector4();
28582		const _currentScissor = new Vector4();
28583		let _currentScissorTest = null;
28584
28585		const _currentClearColor = new Color(0x000000);
28586		let _currentClearAlpha = 0;
28587
28588		//
28589
28590		let _width = canvas.width;
28591		let _height = canvas.height;
28592
28593		let _pixelRatio = 1;
28594		let _opaqueSort = null;
28595		let _transparentSort = null;
28596
28597		const _viewport = new Vector4(0, 0, _width, _height);
28598		const _scissor = new Vector4(0, 0, _width, _height);
28599		let _scissorTest = false;
28600
28601		// frustum
28602
28603		const _frustum = new Frustum();
28604
28605		// clipping
28606
28607		let _clippingEnabled = false;
28608		let _localClippingEnabled = false;
28609
28610		// transmission
28611
28612		let _transmissionRenderTarget = null;
28613
28614		// camera matrices cache
28615
28616		const _projScreenMatrix = new Matrix4();
28617
28618		const _vector2 = new Vector2();
28619		const _vector3 = new Vector3();
28620
28621		const _emptyScene = { background: null, fog: null, environment: null, overrideMaterial: null, isScene: true };
28622
28623		function getTargetPixelRatio() {
28624
28625			return _currentRenderTarget === null ? _pixelRatio : 1;
28626
28627		}
28628
28629		// initialize
28630
28631		let _gl = context;
28632
28633		function getContext(contextNames, contextAttributes) {
28634
28635			for (let i = 0; i < contextNames.length; i++) {
28636
28637				const contextName = contextNames[i];
28638				const context = canvas.getContext(contextName, contextAttributes);
28639				if (context !== null) return context;
28640
28641			}
28642
28643			return null;
28644
28645		}
28646
28647		try {
28648
28649			const contextAttributes = {
28650				alpha: true,
28651				depth,
28652				stencil,
28653				antialias,
28654				premultipliedAlpha,
28655				preserveDrawingBuffer,
28656				powerPreference,
28657				failIfMajorPerformanceCaveat,
28658			};
28659
28660			// OffscreenCanvas does not have setAttribute, see #22811
28661			if ('setAttribute' in canvas) canvas.setAttribute('data-engine', `three.js r${REVISION}`);
28662
28663			// event listeners must be registered before WebGL context is created, see #12753
28664			canvas.addEventListener('webglcontextlost', onContextLost, false);
28665			canvas.addEventListener('webglcontextrestored', onContextRestore, false);
28666			canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false);
28667
28668			if (_gl === null) {
28669
28670				const contextNames = ['webgl2', 'webgl', 'experimental-webgl'];
28671
28672				if (_this.isWebGL1Renderer === true) {
28673
28674					contextNames.shift();
28675
28676				}
28677
28678				_gl = getContext(contextNames, contextAttributes);
28679
28680				if (_gl === null) {
28681
28682					if (getContext(contextNames)) {
28683
28684						throw new Error('Error creating WebGL context with your selected attributes.');
28685
28686					} else {
28687
28688						throw new Error('Error creating WebGL context.');
28689
28690					}
28691
28692				}
28693
28694			}
28695
28696			if (typeof WebGLRenderingContext !== 'undefined' && _gl instanceof WebGLRenderingContext) { // @deprecated, r153
28697
28698				console.warn('THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.');
28699
28700			}
28701
28702			// Some experimental-webgl implementations do not have getShaderPrecisionFormat
28703
28704			if (_gl.getShaderPrecisionFormat === undefined) {
28705
28706				_gl.getShaderPrecisionFormat = function () {
28707
28708					return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };
28709
28710				};
28711
28712			}
28713
28714		} catch (error) {
28715
28716			console.error('THREE.WebGLRenderer: ' + error.message);
28717			throw error;
28718
28719		}
28720
28721		let extensions, capabilities, state, info;
28722		let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
28723		let programCache, materials, renderLists, renderStates, clipping, shadowMap;
28724
28725		let background, morphtargets, bufferRenderer, indexedBufferRenderer;
28726
28727		let utils, bindingStates, uniformsGroups;
28728
28729		function initGLContext() {
28730
28731			extensions = new WebGLExtensions(_gl);
28732
28733			capabilities = new WebGLCapabilities(_gl, extensions, parameters);
28734
28735			extensions.init(capabilities);
28736
28737			utils = new WebGLUtils(_gl, extensions, capabilities);
28738
28739			state = new WebGLState(_gl, extensions, capabilities);
28740
28741			info = new WebGLInfo(_gl);
28742			properties = new WebGLProperties();
28743			textures = new WebGLTextures(_gl, extensions, state, properties, capabilities, utils, info);
28744			cubemaps = new WebGLCubeMaps(_this);
28745			cubeuvmaps = new WebGLCubeUVMaps(_this);
28746			attributes = new WebGLAttributes(_gl, capabilities);
28747			bindingStates = new WebGLBindingStates(_gl, extensions, attributes, capabilities);
28748			geometries = new WebGLGeometries(_gl, attributes, info, bindingStates);
28749			objects = new WebGLObjects(_gl, geometries, attributes, info);
28750			morphtargets = new WebGLMorphtargets(_gl, capabilities, textures);
28751			clipping = new WebGLClipping(properties);
28752			programCache = new WebGLPrograms(_this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping);
28753			materials = new WebGLMaterials(_this, properties);
28754			renderLists = new WebGLRenderLists();
28755			renderStates = new WebGLRenderStates(extensions, capabilities);
28756			background = new WebGLBackground(_this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha);
28757			shadowMap = new WebGLShadowMap(_this, objects, capabilities);
28758			uniformsGroups = new WebGLUniformsGroups(_gl, info, capabilities, state);
28759
28760			bufferRenderer = new WebGLBufferRenderer(_gl, extensions, info, capabilities);
28761			indexedBufferRenderer = new WebGLIndexedBufferRenderer(_gl, extensions, info, capabilities);
28762
28763			info.programs = programCache.programs;
28764
28765			_this.capabilities = capabilities;
28766			_this.extensions = extensions;
28767			_this.properties = properties;
28768			_this.renderLists = renderLists;
28769			_this.shadowMap = shadowMap;
28770			_this.state = state;
28771			_this.info = info;
28772
28773		}
28774
28775		initGLContext();
28776
28777		// xr
28778
28779		const xr = new WebXRManager(_this, _gl);
28780
28781		this.xr = xr;
28782
28783		// API
28784
28785		this.getContext = function () {
28786
28787			return _gl;
28788
28789		};
28790
28791		this.getContextAttributes = function () {
28792
28793			return _gl.getContextAttributes();
28794
28795		};
28796
28797		this.forceContextLoss = function () {
28798
28799			const extension = extensions.get('WEBGL_lose_context');
28800			if (extension) extension.loseContext();
28801
28802		};
28803
28804		this.forceContextRestore = function () {
28805
28806			const extension = extensions.get('WEBGL_lose_context');
28807			if (extension) extension.restoreContext();
28808
28809		};
28810
28811		this.getPixelRatio = function () {
28812
28813			return _pixelRatio;
28814
28815		};
28816
28817		this.setPixelRatio = function (value) {
28818
28819			if (value === undefined) return;
28820
28821			_pixelRatio = value;
28822
28823			this.setSize(_width, _height, false);
28824
28825		};
28826
28827		this.getSize = function (target) {
28828
28829			return target.set(_width, _height);
28830
28831		};
28832
28833		this.setSize = function (width, height, updateStyle = true) {
28834
28835			if (xr.isPresenting) {
28836
28837				console.warn('THREE.WebGLRenderer: Can\'t change size while VR device is presenting.');
28838				return;
28839
28840			}
28841
28842			_width = width;
28843			_height = height;
28844
28845			canvas.width = Math.floor(width * _pixelRatio);
28846			canvas.height = Math.floor(height * _pixelRatio);
28847
28848			if (updateStyle === true) {
28849
28850				canvas.style.width = width + 'px';
28851				canvas.style.height = height + 'px';
28852
28853			}
28854
28855			this.setViewport(0, 0, width, height);
28856
28857		};
28858
28859		this.getDrawingBufferSize = function (target) {
28860
28861			return target.set(_width * _pixelRatio, _height * _pixelRatio).floor();
28862
28863		};
28864
28865		this.setDrawingBufferSize = function (width, height, pixelRatio) {
28866
28867			_width = width;
28868			_height = height;
28869
28870			_pixelRatio = pixelRatio;
28871
28872			canvas.width = Math.floor(width * pixelRatio);
28873			canvas.height = Math.floor(height * pixelRatio);
28874
28875			this.setViewport(0, 0, width, height);
28876
28877		};
28878
28879		this.getCurrentViewport = function (target) {
28880
28881			return target.copy(_currentViewport);
28882
28883		};
28884
28885		this.getViewport = function (target) {
28886
28887			return target.copy(_viewport);
28888
28889		};
28890
28891		this.setViewport = function (x, y, width, height) {
28892
28893			if (x.isVector4) {
28894
28895				_viewport.set(x.x, x.y, x.z, x.w);
28896
28897			} else {
28898
28899				_viewport.set(x, y, width, height);
28900
28901			}
28902
28903			state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor());
28904
28905		};
28906
28907		this.getScissor = function (target) {
28908
28909			return target.copy(_scissor);
28910
28911		};
28912
28913		this.setScissor = function (x, y, width, height) {
28914
28915			if (x.isVector4) {
28916
28917				_scissor.set(x.x, x.y, x.z, x.w);
28918
28919			} else {
28920
28921				_scissor.set(x, y, width, height);
28922
28923			}
28924
28925			state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor());
28926
28927		};
28928
28929		this.getScissorTest = function () {
28930
28931			return _scissorTest;
28932
28933		};
28934
28935		this.setScissorTest = function (boolean) {
28936
28937			state.setScissorTest(_scissorTest = boolean);
28938
28939		};
28940
28941		this.setOpaqueSort = function (method) {
28942
28943			_opaqueSort = method;
28944
28945		};
28946
28947		this.setTransparentSort = function (method) {
28948
28949			_transparentSort = method;
28950
28951		};
28952
28953		// Clearing
28954
28955		this.getClearColor = function (target) {
28956
28957			return target.copy(background.getClearColor());
28958
28959		};
28960
28961		this.setClearColor = function () {
28962
28963			background.setClearColor.apply(background, arguments);
28964
28965		};
28966
28967		this.getClearAlpha = function () {
28968
28969			return background.getClearAlpha();
28970
28971		};
28972
28973		this.setClearAlpha = function () {
28974
28975			background.setClearAlpha.apply(background, arguments);
28976
28977		};
28978
28979		this.clear = function (color = true, depth = true, stencil = true) {
28980
28981			let bits = 0;
28982
28983			if (color) {
28984
28985				// check if we're trying to clear an integer target
28986				let isIntegerFormat = false;
28987				if (_currentRenderTarget !== null) {
28988
28989					const targetFormat = _currentRenderTarget.texture.format;
28990					isIntegerFormat = targetFormat === RGBAIntegerFormat ||
28991						targetFormat === RGIntegerFormat ||
28992						targetFormat === RedIntegerFormat;
28993
28994				}
28995
28996				// use the appropriate clear functions to clear the target if it's a signed
28997				// or unsigned integer target
28998				if (isIntegerFormat) {
28999
29000					const targetType = _currentRenderTarget.texture.type;
29001					const isUnsignedType = targetType === UnsignedByteType ||
29002						targetType === UnsignedIntType ||
29003						targetType === UnsignedShortType ||
29004						targetType === UnsignedInt248Type ||
29005						targetType === UnsignedShort4444Type ||
29006						targetType === UnsignedShort5551Type;
29007
29008					const clearColor = background.getClearColor();
29009					const a = background.getClearAlpha();
29010					const r = clearColor.r;
29011					const g = clearColor.g;
29012					const b = clearColor.b;
29013
29014					if (isUnsignedType) {
29015
29016						uintClearColor[0] = r;
29017						uintClearColor[1] = g;
29018						uintClearColor[2] = b;
29019						uintClearColor[3] = a;
29020						_gl.clearBufferuiv(_gl.COLOR, 0, uintClearColor);
29021
29022					} else {
29023
29024						intClearColor[0] = r;
29025						intClearColor[1] = g;
29026						intClearColor[2] = b;
29027						intClearColor[3] = a;
29028						_gl.clearBufferiv(_gl.COLOR, 0, intClearColor);
29029
29030					}
29031
29032				} else {
29033
29034					bits |= _gl.COLOR_BUFFER_BIT;
29035
29036				}
29037
29038			}
29039
29040			if (depth) bits |= _gl.DEPTH_BUFFER_BIT;
29041			if (stencil) {
29042
29043				bits |= _gl.STENCIL_BUFFER_BIT;
29044				this.state.buffers.stencil.setMask(0xffffffff);
29045
29046			}
29047
29048			_gl.clear(bits);
29049
29050		};
29051
29052		this.clearColor = function () {
29053
29054			this.clear(true, false, false);
29055
29056		};
29057
29058		this.clearDepth = function () {
29059
29060			this.clear(false, true, false);
29061
29062		};
29063
29064		this.clearStencil = function () {
29065
29066			this.clear(false, false, true);
29067
29068		};
29069
29070		//
29071
29072		this.dispose = function () {
29073
29074			canvas.removeEventListener('webglcontextlost', onContextLost, false);
29075			canvas.removeEventListener('webglcontextrestored', onContextRestore, false);
29076			canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false);
29077
29078			renderLists.dispose();
29079			renderStates.dispose();
29080			properties.dispose();
29081			cubemaps.dispose();
29082			cubeuvmaps.dispose();
29083			objects.dispose();
29084			bindingStates.dispose();
29085			uniformsGroups.dispose();
29086			programCache.dispose();
29087
29088			xr.dispose();
29089
29090			xr.removeEventListener('sessionstart', onXRSessionStart);
29091			xr.removeEventListener('sessionend', onXRSessionEnd);
29092
29093			if (_transmissionRenderTarget) {
29094
29095				_transmissionRenderTarget.dispose();
29096				_transmissionRenderTarget = null;
29097
29098			}
29099
29100			animation.stop();
29101
29102		};
29103
29104		// Events
29105
29106		function onContextLost(event) {
29107
29108			event.preventDefault();
29109
29110			console.log('THREE.WebGLRenderer: Context Lost.');
29111
29112			_isContextLost = true;
29113
29114		}
29115
29116		function onContextRestore( /* event */) {
29117
29118			console.log('THREE.WebGLRenderer: Context Restored.');
29119
29120			_isContextLost = false;
29121
29122			const infoAutoReset = info.autoReset;
29123			const shadowMapEnabled = shadowMap.enabled;
29124			const shadowMapAutoUpdate = shadowMap.autoUpdate;
29125			const shadowMapNeedsUpdate = shadowMap.needsUpdate;
29126			const shadowMapType = shadowMap.type;
29127
29128			initGLContext();
29129
29130			info.autoReset = infoAutoReset;
29131			shadowMap.enabled = shadowMapEnabled;
29132			shadowMap.autoUpdate = shadowMapAutoUpdate;
29133			shadowMap.needsUpdate = shadowMapNeedsUpdate;
29134			shadowMap.type = shadowMapType;
29135
29136		}
29137
29138		function onContextCreationError(event) {
29139
29140			console.error('THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage);
29141
29142		}
29143
29144		function onMaterialDispose(event) {
29145
29146			const material = event.target;
29147
29148			material.removeEventListener('dispose', onMaterialDispose);
29149
29150			deallocateMaterial(material);
29151
29152		}
29153
29154		// Buffer deallocation
29155
29156		function deallocateMaterial(material) {
29157
29158			releaseMaterialProgramReferences(material);
29159
29160			properties.remove(material);
29161
29162		}
29163
29164
29165		function releaseMaterialProgramReferences(material) {
29166
29167			const programs = properties.get(material).programs;
29168
29169			if (programs !== undefined) {
29170
29171				programs.forEach(function (program) {
29172
29173					programCache.releaseProgram(program);
29174
29175				});
29176
29177				if (material.isShaderMaterial) {
29178
29179					programCache.releaseShaderCache(material);
29180
29181				}
29182
29183			}
29184
29185		}
29186
29187		// Buffer rendering
29188
29189		this.renderBufferDirect = function (camera, scene, geometry, material, object, group) {
29190
29191			if (scene === null) scene = _emptyScene; // renderBufferDirect second parameter used to be fog (could be null)
29192
29193			const frontFaceCW = (object.isMesh && object.matrixWorld.determinant() < 0);
29194
29195			const program = setProgram(camera, scene, geometry, material, object);
29196
29197			state.setMaterial(material, frontFaceCW);
29198
29199			//
29200
29201			let index = geometry.index;
29202			let rangeFactor = 1;
29203
29204			if (material.wireframe === true) {
29205
29206				index = geometries.getWireframeAttribute(geometry);
29207
29208				if (index === undefined) return;
29209
29210				rangeFactor = 2;
29211
29212			}
29213
29214			//
29215
29216			const drawRange = geometry.drawRange;
29217			const position = geometry.attributes.position;
29218
29219			let drawStart = drawRange.start * rangeFactor;
29220			let drawEnd = (drawRange.start + drawRange.count) * rangeFactor;
29221
29222			if (group !== null) {
29223
29224				drawStart = Math.max(drawStart, group.start * rangeFactor);
29225				drawEnd = Math.min(drawEnd, (group.start + group.count) * rangeFactor);
29226
29227			}
29228
29229			if (index !== null) {
29230
29231				drawStart = Math.max(drawStart, 0);
29232				drawEnd = Math.min(drawEnd, index.count);
29233
29234			} else if (position !== undefined && position !== null) {
29235
29236				drawStart = Math.max(drawStart, 0);
29237				drawEnd = Math.min(drawEnd, position.count);
29238
29239			}
29240
29241			const drawCount = drawEnd - drawStart;
29242
29243			if (drawCount < 0 || drawCount === Infinity) return;
29244
29245			//
29246
29247			bindingStates.setup(object, material, program, geometry, index);
29248
29249			let attribute;
29250			let renderer = bufferRenderer;
29251
29252			if (index !== null) {
29253
29254				attribute = attributes.get(index);
29255
29256				renderer = indexedBufferRenderer;
29257				renderer.setIndex(attribute);
29258
29259			}
29260
29261			//
29262
29263			if (object.isMesh) {
29264
29265				if (material.wireframe === true) {
29266
29267					state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio());
29268					renderer.setMode(_gl.LINES);
29269
29270				} else {
29271
29272					renderer.setMode(_gl.TRIANGLES);
29273
29274				}
29275
29276			} else if (object.isLine) {
29277
29278				let lineWidth = material.linewidth;
29279
29280				if (lineWidth === undefined) lineWidth = 1; // Not using Line*Material
29281
29282				state.setLineWidth(lineWidth * getTargetPixelRatio());
29283
29284				if (object.isLineSegments) {
29285
29286					renderer.setMode(_gl.LINES);
29287
29288				} else if (object.isLineLoop) {
29289
29290					renderer.setMode(_gl.LINE_LOOP);
29291
29292				} else {
29293
29294					renderer.setMode(_gl.LINE_STRIP);
29295
29296				}
29297
29298			} else if (object.isPoints) {
29299
29300				renderer.setMode(_gl.POINTS);
29301
29302			} else if (object.isSprite) {
29303
29304				renderer.setMode(_gl.TRIANGLES);
29305
29306			}
29307
29308			if (object.isBatchedMesh) {
29309
29310				renderer.renderMultiDraw(object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount);
29311
29312			} else if (object.isInstancedMesh) {
29313
29314				renderer.renderInstances(drawStart, drawCount, object.count);
29315
29316			} else if (geometry.isInstancedBufferGeometry) {
29317
29318				const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity;
29319				const instanceCount = Math.min(geometry.instanceCount, maxInstanceCount);
29320
29321				renderer.renderInstances(drawStart, drawCount, instanceCount);
29322
29323			} else {
29324
29325				renderer.render(drawStart, drawCount);
29326
29327			}
29328
29329		};
29330
29331		// Compile
29332
29333		function prepareMaterial(material, scene, object) {
29334
29335			if (material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false) {
29336
29337				material.side = BackSide;
29338				material.needsUpdate = true;
29339				getProgram(material, scene, object);
29340
29341				material.side = FrontSide;
29342				material.needsUpdate = true;
29343				getProgram(material, scene, object);
29344
29345				material.side = DoubleSide;
29346
29347			} else {
29348
29349				getProgram(material, scene, object);
29350
29351			}
29352
29353		}
29354
29355		this.compile = function (scene, camera, targetScene = null) {
29356
29357			if (targetScene === null) targetScene = scene;
29358
29359			currentRenderState = renderStates.get(targetScene);
29360			currentRenderState.init();
29361
29362			renderStateStack.push(currentRenderState);
29363
29364			// gather lights from both the target scene and the new object that will be added to the scene.
29365
29366			targetScene.traverseVisible(function (object) {
29367
29368				if (object.isLight && object.layers.test(camera.layers)) {
29369
29370					currentRenderState.pushLight(object);
29371
29372					if (object.castShadow) {
29373
29374						currentRenderState.pushShadow(object);
29375
29376					}
29377
29378				}
29379
29380			});
29381
29382			if (scene !== targetScene) {
29383
29384				scene.traverseVisible(function (object) {
29385
29386					if (object.isLight && object.layers.test(camera.layers)) {
29387
29388						currentRenderState.pushLight(object);
29389
29390						if (object.castShadow) {
29391
29392							currentRenderState.pushShadow(object);
29393
29394						}
29395
29396					}
29397
29398				});
29399
29400			}
29401
29402			currentRenderState.setupLights(_this._useLegacyLights);
29403
29404			// Only initialize materials in the new scene, not the targetScene.
29405
29406			const materials = new Set();
29407
29408			scene.traverse(function (object) {
29409
29410				const material = object.material;
29411
29412				if (material) {
29413
29414					if (Array.isArray(material)) {
29415
29416						for (let i = 0; i < material.length; i++) {
29417
29418							const material2 = material[i];
29419
29420							prepareMaterial(material2, targetScene, object);
29421							materials.add(material2);
29422
29423						}
29424
29425					} else {
29426
29427						prepareMaterial(material, targetScene, object);
29428						materials.add(material);
29429
29430					}
29431
29432				}
29433
29434			});
29435
29436			renderStateStack.pop();
29437			currentRenderState = null;
29438
29439			return materials;
29440
29441		};
29442
29443		// compileAsync
29444
29445		this.compileAsync = function (scene, camera, targetScene = null) {
29446
29447			const materials = this.compile(scene, camera, targetScene);
29448
29449			// Wait for all the materials in the new object to indicate that they're
29450			// ready to be used before resolving the promise.
29451
29452			return new Promise((resolve) => {
29453
29454				function checkMaterialsReady() {
29455
29456					materials.forEach(function (material) {
29457
29458						const materialProperties = properties.get(material);
29459						const program = materialProperties.currentProgram;
29460
29461						if (program.isReady()) {
29462
29463							// remove any programs that report they're ready to use from the list
29464							materials.delete(material);
29465
29466						}
29467
29468					});
29469
29470					// once the list of compiling materials is empty, call the callback
29471
29472					if (materials.size === 0) {
29473
29474						resolve(scene);
29475						return;
29476
29477					}
29478
29479					// if some materials are still not ready, wait a bit and check again
29480
29481					setTimeout(checkMaterialsReady, 10);
29482
29483				}
29484
29485				if (extensions.get('KHR_parallel_shader_compile') !== null) {
29486
29487					// If we can check the compilation status of the materials without
29488					// blocking then do so right away.
29489
29490					checkMaterialsReady();
29491
29492				} else {
29493
29494					// Otherwise start by waiting a bit to give the materials we just
29495					// initialized a chance to finish.
29496
29497					setTimeout(checkMaterialsReady, 10);
29498
29499				}
29500
29501			});
29502
29503		};
29504
29505		// Animation Loop
29506
29507		let onAnimationFrameCallback = null;
29508
29509		function onAnimationFrame(time) {
29510
29511			if (onAnimationFrameCallback) onAnimationFrameCallback(time);
29512
29513		}
29514
29515		function onXRSessionStart() {
29516
29517			animation.stop();
29518
29519		}
29520
29521		function onXRSessionEnd() {
29522
29523			animation.start();
29524
29525		}
29526
29527		const animation = new WebGLAnimation();
29528		animation.setAnimationLoop(onAnimationFrame);
29529
29530		if (typeof self !== 'undefined') animation.setContext(self);
29531
29532		this.setAnimationLoop = function (callback) {
29533
29534			onAnimationFrameCallback = callback;
29535			xr.setAnimationLoop(callback);
29536
29537			(callback === null) ? animation.stop() : animation.start();
29538
29539		};
29540
29541		xr.addEventListener('sessionstart', onXRSessionStart);
29542		xr.addEventListener('sessionend', onXRSessionEnd);
29543
29544		// Rendering
29545
29546		this.render = function (scene, camera) {
29547
29548			if (camera !== undefined && camera.isCamera !== true) {
29549
29550				console.error('THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.');
29551				return;
29552
29553			}
29554
29555			if (_isContextLost === true) return;
29556
29557			// update scene graph
29558
29559			if (scene.matrixWorldAutoUpdate === true) scene.updateMatrixWorld();
29560
29561			// update camera matrices and frustum
29562
29563			if (camera.parent === null && camera.matrixWorldAutoUpdate === true) camera.updateMatrixWorld();
29564
29565			if (xr.enabled === true && xr.isPresenting === true) {
29566
29567				if (xr.cameraAutoUpdate === true) xr.updateCamera(camera);
29568
29569				camera = xr.getCamera(); // use XR camera for rendering
29570
29571			}
29572
29573			//
29574			if (scene.isScene === true) scene.onBeforeRender(_this, scene, camera, _currentRenderTarget);
29575
29576			currentRenderState = renderStates.get(scene, renderStateStack.length);
29577			currentRenderState.init();
29578
29579			renderStateStack.push(currentRenderState);
29580
29581			_projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
29582			_frustum.setFromProjectionMatrix(_projScreenMatrix);
29583
29584			_localClippingEnabled = this.localClippingEnabled;
29585			_clippingEnabled = clipping.init(this.clippingPlanes, _localClippingEnabled);
29586
29587			currentRenderList = renderLists.get(scene, renderListStack.length);
29588			currentRenderList.init();
29589
29590			renderListStack.push(currentRenderList);
29591
29592			projectObject(scene, camera, 0, _this.sortObjects);
29593
29594			currentRenderList.finish();
29595
29596			if (_this.sortObjects === true) {
29597
29598				currentRenderList.sort(_opaqueSort, _transparentSort);
29599
29600			}
29601
29602			//
29603
29604			this.info.render.frame++;
29605
29606			if (_clippingEnabled === true) clipping.beginShadows();
29607
29608			const shadowsArray = currentRenderState.state.shadowsArray;
29609
29610			shadowMap.render(shadowsArray, scene, camera);
29611
29612			if (_clippingEnabled === true) clipping.endShadows();
29613
29614			//
29615
29616			if (this.info.autoReset === true) this.info.reset();
29617
29618
29619			//
29620
29621			background.render(currentRenderList, scene);
29622
29623			// render scene
29624
29625			currentRenderState.setupLights(_this._useLegacyLights);
29626
29627			if (camera.isArrayCamera) {
29628
29629				const cameras = camera.cameras;
29630
29631				for (let i = 0, l = cameras.length; i < l; i++) {
29632
29633					const camera2 = cameras[i];
29634
29635					renderScene(currentRenderList, scene, camera2, camera2.viewport);
29636
29637				}
29638
29639			} else {
29640
29641				renderScene(currentRenderList, scene, camera);
29642
29643			}
29644
29645			//
29646
29647			if (_currentRenderTarget !== null) {
29648
29649				// resolve multisample renderbuffers to a single-sample texture if necessary
29650
29651				textures.updateMultisampleRenderTarget(_currentRenderTarget);
29652
29653				// Generate mipmap if we're using any kind of mipmap filtering
29654
29655				textures.updateRenderTargetMipmap(_currentRenderTarget);
29656
29657			}
29658
29659			//
29660
29661			if (scene.isScene === true) scene.onAfterRender(_this, scene, camera);
29662
29663			// _gl.finish();
29664
29665			bindingStates.resetDefaultState();
29666			_currentMaterialId = - 1;
29667			_currentCamera = null;
29668
29669			renderStateStack.pop();
29670
29671			if (renderStateStack.length > 0) {
29672
29673				currentRenderState = renderStateStack[renderStateStack.length - 1];
29674
29675			} else {
29676
29677				currentRenderState = null;
29678
29679			}
29680
29681			renderListStack.pop();
29682
29683			if (renderListStack.length > 0) {
29684
29685				currentRenderList = renderListStack[renderListStack.length - 1];
29686
29687			} else {
29688
29689				currentRenderList = null;
29690
29691			}
29692
29693		};
29694
29695		function projectObject(object, camera, groupOrder, sortObjects) {
29696
29697			if (object.visible === false) return;
29698
29699			const visible = object.layers.test(camera.layers);
29700
29701			if (visible) {
29702
29703				if (object.isGroup) {
29704
29705					groupOrder = object.renderOrder;
29706
29707				} else if (object.isLOD) {
29708
29709					if (object.autoUpdate === true) object.update(camera);
29710
29711				} else if (object.isLight) {
29712
29713					currentRenderState.pushLight(object);
29714
29715					if (object.castShadow) {
29716
29717						currentRenderState.pushShadow(object);
29718
29719					}
29720
29721				} else if (object.isSprite) {
29722
29723					if (!object.frustumCulled || _frustum.intersectsSprite(object)) {
29724
29725						if (sortObjects) {
29726
29727							_vector3.setFromMatrixPosition(object.matrixWorld)
29728								.applyMatrix4(_projScreenMatrix);
29729
29730						}
29731
29732						const geometry = objects.update(object);
29733						const material = object.material;
29734
29735						if (material.visible) {
29736
29737							currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null);
29738
29739						}
29740
29741					}
29742
29743				} else if (object.isMesh || object.isLine || object.isPoints) {
29744
29745					if (!object.frustumCulled || _frustum.intersectsObject(object)) {
29746
29747						const geometry = objects.update(object);
29748						const material = object.material;
29749
29750						if (sortObjects) {
29751
29752							if (object.boundingSphere !== undefined) {
29753
29754								if (object.boundingSphere === null) object.computeBoundingSphere();
29755								_vector3.copy(object.boundingSphere.center);
29756
29757							} else {
29758
29759								if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
29760								_vector3.copy(geometry.boundingSphere.center);
29761
29762							}
29763
29764							_vector3
29765								.applyMatrix4(object.matrixWorld)
29766								.applyMatrix4(_projScreenMatrix);
29767
29768						}
29769
29770						if (Array.isArray(material)) {
29771
29772							const groups = geometry.groups;
29773
29774							for (let i = 0, l = groups.length; i < l; i++) {
29775
29776								const group = groups[i];
29777								const groupMaterial = material[group.materialIndex];
29778
29779								if (groupMaterial && groupMaterial.visible) {
29780
29781									currentRenderList.push(object, geometry, groupMaterial, groupOrder, _vector3.z, group);
29782
29783								}
29784
29785							}
29786
29787						} else if (material.visible) {
29788
29789							currentRenderList.push(object, geometry, material, groupOrder, _vector3.z, null);
29790
29791						}
29792
29793					}
29794
29795				}
29796
29797			}
29798
29799			const children = object.children;
29800
29801			for (let i = 0, l = children.length; i < l; i++) {
29802
29803				projectObject(children[i], camera, groupOrder, sortObjects);
29804
29805			}
29806
29807		}
29808
29809		function renderScene(currentRenderList, scene, camera, viewport) {
29810
29811			const opaqueObjects = currentRenderList.opaque;
29812			const transmissiveObjects = currentRenderList.transmissive;
29813			const transparentObjects = currentRenderList.transparent;
29814
29815			currentRenderState.setupLightsView(camera);
29816
29817			if (_clippingEnabled === true) clipping.setGlobalState(_this.clippingPlanes, camera);
29818
29819			if (transmissiveObjects.length > 0) renderTransmissionPass(opaqueObjects, transmissiveObjects, scene, camera);
29820
29821			if (viewport) state.viewport(_currentViewport.copy(viewport));
29822
29823			if (opaqueObjects.length > 0) renderObjects(opaqueObjects, scene, camera);
29824			if (transmissiveObjects.length > 0) renderObjects(transmissiveObjects, scene, camera);
29825			if (transparentObjects.length > 0) renderObjects(transparentObjects, scene, camera);
29826
29827			// Ensure depth buffer writing is enabled so it can be cleared on next render
29828
29829			state.buffers.depth.setTest(true);
29830			state.buffers.depth.setMask(true);
29831			state.buffers.color.setMask(true);
29832
29833			state.setPolygonOffset(false);
29834
29835		}
29836
29837		function renderTransmissionPass(opaqueObjects, transmissiveObjects, scene, camera) {
29838
29839			const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
29840
29841			if (overrideMaterial !== null) {
29842
29843				return;
29844
29845			}
29846
29847			const isWebGL2 = capabilities.isWebGL2;
29848
29849			if (_transmissionRenderTarget === null) {
29850
29851				_transmissionRenderTarget = new WebGLRenderTarget(1, 1, {
29852					generateMipmaps: true,
29853					type: extensions.has('EXT_color_buffer_half_float') ? HalfFloatType : UnsignedByteType,
29854					minFilter: LinearMipmapLinearFilter,
29855					samples: (isWebGL2) ? 4 : 0
29856				});
29857
29858				// debug
29859
29860				/*
29861				const geometry = new PlaneGeometry();
29862				const material = new MeshBasicMaterial( { map: _transmissionRenderTarget.texture } );
29863
29864				const mesh = new Mesh( geometry, material );
29865				scene.add( mesh );
29866				*/
29867
29868			}
29869
29870			_this.getDrawingBufferSize(_vector2);
29871
29872			if (isWebGL2) {
29873
29874				_transmissionRenderTarget.setSize(_vector2.x, _vector2.y);
29875
29876			} else {
29877
29878				_transmissionRenderTarget.setSize(floorPowerOfTwo(_vector2.x), floorPowerOfTwo(_vector2.y));
29879
29880			}
29881
29882			//
29883
29884			const currentRenderTarget = _this.getRenderTarget();
29885			_this.setRenderTarget(_transmissionRenderTarget);
29886
29887			_this.getClearColor(_currentClearColor);
29888			_currentClearAlpha = _this.getClearAlpha();
29889			if (_currentClearAlpha < 1) _this.setClearColor(0xffffff, 0.5);
29890
29891			_this.clear();
29892
29893			// Turn off the features which can affect the frag color for opaque objects pass.
29894			// Otherwise they are applied twice in opaque objects pass and transmission objects pass.
29895			const currentToneMapping = _this.toneMapping;
29896			_this.toneMapping = NoToneMapping;
29897
29898			renderObjects(opaqueObjects, scene, camera);
29899
29900			textures.updateMultisampleRenderTarget(_transmissionRenderTarget);
29901			textures.updateRenderTargetMipmap(_transmissionRenderTarget);
29902
29903			let renderTargetNeedsUpdate = false;
29904
29905			for (let i = 0, l = transmissiveObjects.length; i < l; i++) {
29906
29907				const renderItem = transmissiveObjects[i];
29908
29909				const object = renderItem.object;
29910				const geometry = renderItem.geometry;
29911				const material = renderItem.material;
29912				const group = renderItem.group;
29913
29914				if (material.side === DoubleSide && object.layers.test(camera.layers)) {
29915
29916					const currentSide = material.side;
29917
29918					material.side = BackSide;
29919					material.needsUpdate = true;
29920
29921					renderObject(object, scene, camera, geometry, material, group);
29922
29923					material.side = currentSide;
29924					material.needsUpdate = true;
29925
29926					renderTargetNeedsUpdate = true;
29927
29928				}
29929
29930			}
29931
29932			if (renderTargetNeedsUpdate === true) {
29933
29934				textures.updateMultisampleRenderTarget(_transmissionRenderTarget);
29935				textures.updateRenderTargetMipmap(_transmissionRenderTarget);
29936
29937			}
29938
29939			_this.setRenderTarget(currentRenderTarget);
29940
29941			_this.setClearColor(_currentClearColor, _currentClearAlpha);
29942
29943			_this.toneMapping = currentToneMapping;
29944
29945		}
29946
29947		function renderObjects(renderList, scene, camera) {
29948
29949			const overrideMaterial = scene.isScene === true ? scene.overrideMaterial : null;
29950
29951			for (let i = 0, l = renderList.length; i < l; i++) {
29952
29953				const renderItem = renderList[i];
29954
29955				const object = renderItem.object;
29956				const geometry = renderItem.geometry;
29957				const material = overrideMaterial === null ? renderItem.material : overrideMaterial;
29958				const group = renderItem.group;
29959
29960				if (object.layers.test(camera.layers)) {
29961
29962					renderObject(object, scene, camera, geometry, material, group);
29963
29964				}
29965
29966			}
29967
29968		}
29969
29970		function renderObject(object, scene, camera, geometry, material, group) {
29971
29972			object.onBeforeRender(_this, scene, camera, geometry, material, group);
29973
29974			object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld);
29975			object.normalMatrix.getNormalMatrix(object.modelViewMatrix);
29976
29977			material.onBeforeRender(_this, scene, camera, geometry, object, group);
29978
29979			if (material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false) {
29980
29981				material.side = BackSide;
29982				material.needsUpdate = true;
29983				_this.renderBufferDirect(camera, scene, geometry, material, object, group);
29984
29985				material.side = FrontSide;
29986				material.needsUpdate = true;
29987				_this.renderBufferDirect(camera, scene, geometry, material, object, group);
29988
29989				material.side = DoubleSide;
29990
29991			} else {
29992
29993				_this.renderBufferDirect(camera, scene, geometry, material, object, group);
29994
29995			}
29996
29997			object.onAfterRender(_this, scene, camera, geometry, material, group);
29998
29999		}
30000
30001		function getProgram(material, scene, object) {
30002
30003			if (scene.isScene !== true) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
30004
30005			const materialProperties = properties.get(material);
30006
30007			const lights = currentRenderState.state.lights;
30008			const shadowsArray = currentRenderState.state.shadowsArray;
30009
30010			const lightsStateVersion = lights.state.version;
30011
30012			const parameters = programCache.getParameters(material, lights.state, shadowsArray, scene, object);
30013			const programCacheKey = programCache.getProgramCacheKey(parameters);
30014
30015			let programs = materialProperties.programs;
30016
30017			// always update environment and fog - changing these trigger an getProgram call, but it's possible that the program doesn't change
30018
30019			materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
30020			materialProperties.fog = scene.fog;
30021			materialProperties.envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || materialProperties.environment);
30022
30023			if (programs === undefined) {
30024
30025				// new material
30026
30027				material.addEventListener('dispose', onMaterialDispose);
30028
30029				programs = new Map();
30030				materialProperties.programs = programs;
30031
30032			}
30033
30034			let program = programs.get(programCacheKey);
30035
30036			if (program !== undefined) {
30037
30038				// early out if program and light state is identical
30039
30040				if (materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion) {
30041
30042					updateCommonMaterialProperties(material, parameters);
30043
30044					return program;
30045
30046				}
30047
30048			} else {
30049
30050				parameters.uniforms = programCache.getUniforms(material);
30051
30052				material.onBuild(object, parameters, _this);
30053
30054				material.onBeforeCompile(parameters, _this);
30055
30056				program = programCache.acquireProgram(parameters, programCacheKey);
30057				programs.set(programCacheKey, program);
30058
30059				materialProperties.uniforms = parameters.uniforms;
30060
30061			}
30062
30063			const uniforms = materialProperties.uniforms;
30064
30065			if ((!material.isShaderMaterial && !material.isRawShaderMaterial) || material.clipping === true) {
30066
30067				uniforms.clippingPlanes = clipping.uniform;
30068
30069			}
30070
30071			updateCommonMaterialProperties(material, parameters);
30072
30073			// store the light setup it was created for
30074
30075			materialProperties.needsLights = materialNeedsLights(material);
30076			materialProperties.lightsStateVersion = lightsStateVersion;
30077
30078			if (materialProperties.needsLights) {
30079
30080				// wire up the material to this renderer's lighting state
30081
30082				uniforms.ambientLightColor.value = lights.state.ambient;
30083				uniforms.lightProbe.value = lights.state.probe;
30084				uniforms.directionalLights.value = lights.state.directional;
30085				uniforms.directionalLightShadows.value = lights.state.directionalShadow;
30086				uniforms.spotLights.value = lights.state.spot;
30087				uniforms.spotLightShadows.value = lights.state.spotShadow;
30088				uniforms.rectAreaLights.value = lights.state.rectArea;
30089				uniforms.ltc_1.value = lights.state.rectAreaLTC1;
30090				uniforms.ltc_2.value = lights.state.rectAreaLTC2;
30091				uniforms.pointLights.value = lights.state.point;
30092				uniforms.pointLightShadows.value = lights.state.pointShadow;
30093				uniforms.hemisphereLights.value = lights.state.hemi;
30094
30095				uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
30096				uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
30097				uniforms.spotShadowMap.value = lights.state.spotShadowMap;
30098				uniforms.spotLightMatrix.value = lights.state.spotLightMatrix;
30099				uniforms.spotLightMap.value = lights.state.spotLightMap;
30100				uniforms.pointShadowMap.value = lights.state.pointShadowMap;
30101				uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
30102				// TODO (abelnation): add area lights shadow info to uniforms
30103
30104			}
30105
30106			materialProperties.currentProgram = program;
30107			materialProperties.uniformsList = null;
30108
30109			return program;
30110
30111		}
30112
30113		function getUniformList(materialProperties) {
30114
30115			if (materialProperties.uniformsList === null) {
30116
30117				const progUniforms = materialProperties.currentProgram.getUniforms();
30118				materialProperties.uniformsList = WebGLUniforms.seqWithValue(progUniforms.seq, materialProperties.uniforms);
30119
30120			}
30121
30122			return materialProperties.uniformsList;
30123
30124		}
30125
30126		function updateCommonMaterialProperties(material, parameters) {
30127
30128			const materialProperties = properties.get(material);
30129
30130			materialProperties.outputColorSpace = parameters.outputColorSpace;
30131			materialProperties.batching = parameters.batching;
30132			materialProperties.instancing = parameters.instancing;
30133			materialProperties.instancingColor = parameters.instancingColor;
30134			materialProperties.skinning = parameters.skinning;
30135			materialProperties.morphTargets = parameters.morphTargets;
30136			materialProperties.morphNormals = parameters.morphNormals;
30137			materialProperties.morphColors = parameters.morphColors;
30138			materialProperties.morphTargetsCount = parameters.morphTargetsCount;
30139			materialProperties.numClippingPlanes = parameters.numClippingPlanes;
30140			materialProperties.numIntersection = parameters.numClipIntersection;
30141			materialProperties.vertexAlphas = parameters.vertexAlphas;
30142			materialProperties.vertexTangents = parameters.vertexTangents;
30143			materialProperties.toneMapping = parameters.toneMapping;
30144
30145		}
30146
30147		function setProgram(camera, scene, geometry, material, object) {
30148
30149			if (scene.isScene !== true) scene = _emptyScene; // scene could be a Mesh, Line, Points, ...
30150
30151			textures.resetTextureUnits();
30152
30153			const fog = scene.fog;
30154			const environment = material.isMeshStandardMaterial ? scene.environment : null;
30155			const colorSpace = (_currentRenderTarget === null) ? _this.outputColorSpace : (_currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace);
30156			const envMap = (material.isMeshStandardMaterial ? cubeuvmaps : cubemaps).get(material.envMap || environment);
30157			const vertexAlphas = material.vertexColors === true && !!geometry.attributes.color && geometry.attributes.color.itemSize === 4;
30158			const vertexTangents = !!geometry.attributes.tangent && (!!material.normalMap || material.anisotropy > 0);
30159			const morphTargets = !!geometry.morphAttributes.position;
30160			const morphNormals = !!geometry.morphAttributes.normal;
30161			const morphColors = !!geometry.morphAttributes.color;
30162
30163			let toneMapping = NoToneMapping;
30164
30165			if (material.toneMapped) {
30166
30167				if (_currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true) {
30168
30169					toneMapping = _this.toneMapping;
30170
30171				}
30172
30173			}
30174
30175			const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
30176			const morphTargetsCount = (morphAttribute !== undefined) ? morphAttribute.length : 0;
30177
30178			const materialProperties = properties.get(material);
30179			const lights = currentRenderState.state.lights;
30180
30181			if (_clippingEnabled === true) {
30182
30183				if (_localClippingEnabled === true || camera !== _currentCamera) {
30184
30185					const useCache =
30186						camera === _currentCamera &&
30187						material.id === _currentMaterialId;
30188
30189					// we might want to call this function with some ClippingGroup
30190					// object instead of the material, once it becomes feasible
30191					// (#8465, #8379)
30192					clipping.setState(material, camera, useCache);
30193
30194				}
30195
30196			}
30197
30198			//
30199
30200			let needsProgramChange = false;
30201
30202			if (material.version === materialProperties.__version) {
30203
30204				if (materialProperties.needsLights && (materialProperties.lightsStateVersion !== lights.state.version)) {
30205
30206					needsProgramChange = true;
30207
30208				} else if (materialProperties.outputColorSpace !== colorSpace) {
30209
30210					needsProgramChange = true;
30211
30212				} else if (object.isBatchedMesh && materialProperties.batching === false) {
30213
30214					needsProgramChange = true;
30215
30216				} else if (!object.isBatchedMesh && materialProperties.batching === true) {
30217
30218					needsProgramChange = true;
30219
30220				} else if (object.isInstancedMesh && materialProperties.instancing === false) {
30221
30222					needsProgramChange = true;
30223
30224				} else if (!object.isInstancedMesh && materialProperties.instancing === true) {
30225
30226					needsProgramChange = true;
30227
30228				} else if (object.isSkinnedMesh && materialProperties.skinning === false) {
30229
30230					needsProgramChange = true;
30231
30232				} else if (!object.isSkinnedMesh && materialProperties.skinning === true) {
30233
30234					needsProgramChange = true;
30235
30236				} else if (object.isInstancedMesh && materialProperties.instancingColor === true && object.instanceColor === null) {
30237
30238					needsProgramChange = true;
30239
30240				} else if (object.isInstancedMesh && materialProperties.instancingColor === false && object.instanceColor !== null) {
30241
30242					needsProgramChange = true;
30243
30244				} else if (materialProperties.envMap !== envMap) {
30245
30246					needsProgramChange = true;
30247
30248				} else if (material.fog === true && materialProperties.fog !== fog) {
30249
30250					needsProgramChange = true;
30251
30252				} else if (materialProperties.numClippingPlanes !== undefined &&
30253					(materialProperties.numClippingPlanes !== clipping.numPlanes ||
30254						materialProperties.numIntersection !== clipping.numIntersection)) {
30255
30256					needsProgramChange = true;
30257
30258				} else if (materialProperties.vertexAlphas !== vertexAlphas) {
30259
30260					needsProgramChange = true;
30261
30262				} else if (materialProperties.vertexTangents !== vertexTangents) {
30263
30264					needsProgramChange = true;
30265
30266				} else if (materialProperties.morphTargets !== morphTargets) {
30267
30268					needsProgramChange = true;
30269
30270				} else if (materialProperties.morphNormals !== morphNormals) {
30271
30272					needsProgramChange = true;
30273
30274				} else if (materialProperties.morphColors !== morphColors) {
30275
30276					needsProgramChange = true;
30277
30278				} else if (materialProperties.toneMapping !== toneMapping) {
30279
30280					needsProgramChange = true;
30281
30282				} else if (capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount) {
30283
30284					needsProgramChange = true;
30285
30286				}
30287
30288			} else {
30289
30290				needsProgramChange = true;
30291				materialProperties.__version = material.version;
30292
30293			}
30294
30295			//
30296
30297			let program = materialProperties.currentProgram;
30298
30299			if (needsProgramChange === true) {
30300
30301				program = getProgram(material, scene, object);
30302
30303			}
30304
30305			let refreshProgram = false;
30306			let refreshMaterial = false;
30307			let refreshLights = false;
30308
30309			const p_uniforms = program.getUniforms(),
30310				m_uniforms = materialProperties.uniforms;
30311
30312			if (state.useProgram(program.program)) {
30313
30314				refreshProgram = true;
30315				refreshMaterial = true;
30316				refreshLights = true;
30317
30318			}
30319
30320			if (material.id !== _currentMaterialId) {
30321
30322				_currentMaterialId = material.id;
30323
30324				refreshMaterial = true;
30325
30326			}
30327
30328			if (refreshProgram || _currentCamera !== camera) {
30329
30330				// common camera uniforms
30331
30332				p_uniforms.setValue(_gl, 'projectionMatrix', camera.projectionMatrix);
30333				p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse);
30334
30335				const uCamPos = p_uniforms.map.cameraPosition;
30336
30337				if (uCamPos !== undefined) {
30338
30339					uCamPos.setValue(_gl, _vector3.setFromMatrixPosition(camera.matrixWorld));
30340
30341				}
30342
30343				if (capabilities.logarithmicDepthBuffer) {
30344
30345					p_uniforms.setValue(_gl, 'logDepthBufFC',
30346						2.0 / (Math.log(camera.far + 1.0) / Math.LN2));
30347
30348				}
30349
30350				// consider moving isOrthographic to UniformLib and WebGLMaterials, see https://github.com/mrdoob/three.js/pull/26467#issuecomment-1645185067
30351
30352				if (material.isMeshPhongMaterial ||
30353					material.isMeshToonMaterial ||
30354					material.isMeshLambertMaterial ||
30355					material.isMeshBasicMaterial ||
30356					material.isMeshStandardMaterial ||
30357					material.isShaderMaterial) {
30358
30359					p_uniforms.setValue(_gl, 'isOrthographic', camera.isOrthographicCamera === true);
30360
30361				}
30362
30363				if (_currentCamera !== camera) {
30364
30365					_currentCamera = camera;
30366
30367					// lighting uniforms depend on the camera so enforce an update
30368					// now, in case this material supports lights - or later, when
30369					// the next material that does gets activated:
30370
30371					refreshMaterial = true;		// set to true on material change
30372					refreshLights = true;		// remains set until update done
30373
30374				}
30375
30376			}
30377
30378			// skinning and morph target uniforms must be set even if material didn't change
30379			// auto-setting of texture unit for bone and morph texture must go before other textures
30380			// otherwise textures used for skinning and morphing can take over texture units reserved for other material textures
30381
30382			if (object.isSkinnedMesh) {
30383
30384				p_uniforms.setOptional(_gl, object, 'bindMatrix');
30385				p_uniforms.setOptional(_gl, object, 'bindMatrixInverse');
30386
30387				const skeleton = object.skeleton;
30388
30389				if (skeleton) {
30390
30391					if (capabilities.floatVertexTextures) {
30392
30393						if (skeleton.boneTexture === null) skeleton.computeBoneTexture();
30394
30395						p_uniforms.setValue(_gl, 'boneTexture', skeleton.boneTexture, textures);
30396
30397					} else {
30398
30399						console.warn('THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.');
30400
30401					}
30402
30403				}
30404
30405			}
30406
30407			if (object.isBatchedMesh) {
30408
30409				p_uniforms.setOptional(_gl, object, 'batchingTexture');
30410				p_uniforms.setValue(_gl, 'batchingTexture', object._matricesTexture, textures);
30411
30412			}
30413
30414			const morphAttributes = geometry.morphAttributes;
30415
30416			if (morphAttributes.position !== undefined || morphAttributes.normal !== undefined || (morphAttributes.color !== undefined && capabilities.isWebGL2 === true)) {
30417
30418				morphtargets.update(object, geometry, program);
30419
30420			}
30421
30422			if (refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow) {
30423
30424				materialProperties.receiveShadow = object.receiveShadow;
30425				p_uniforms.setValue(_gl, 'receiveShadow', object.receiveShadow);
30426
30427			}
30428
30429			// https://github.com/mrdoob/three.js/pull/24467#issuecomment-1209031512
30430
30431			if (material.isMeshGouraudMaterial && material.envMap !== null) {
30432
30433				m_uniforms.envMap.value = envMap;
30434
30435				m_uniforms.flipEnvMap.value = (envMap.isCubeTexture && envMap.isRenderTargetTexture === false) ? - 1 : 1;
30436
30437			}
30438
30439			if (refreshMaterial) {
30440
30441				p_uniforms.setValue(_gl, 'toneMappingExposure', _this.toneMappingExposure);
30442
30443				if (materialProperties.needsLights) {
30444
30445					// the current material requires lighting info
30446
30447					// note: all lighting uniforms are always set correctly
30448					// they simply reference the renderer's state for their
30449					// values
30450					//
30451					// use the current material's .needsUpdate flags to set
30452					// the GL state when required
30453
30454					markUniformsLightsNeedsUpdate(m_uniforms, refreshLights);
30455
30456				}
30457
30458				// refresh uniforms common to several materials
30459
30460				if (fog && material.fog === true) {
30461
30462					materials.refreshFogUniforms(m_uniforms, fog);
30463
30464				}
30465
30466				materials.refreshMaterialUniforms(m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget);
30467
30468				WebGLUniforms.upload(_gl, getUniformList(materialProperties), m_uniforms, textures);
30469
30470			}
30471
30472			if (material.isShaderMaterial && material.uniformsNeedUpdate === true) {
30473
30474				WebGLUniforms.upload(_gl, getUniformList(materialProperties), m_uniforms, textures);
30475				material.uniformsNeedUpdate = false;
30476
30477			}
30478
30479			if (material.isSpriteMaterial) {
30480
30481				p_uniforms.setValue(_gl, 'center', object.center);
30482
30483			}
30484
30485			// common matrices
30486
30487			p_uniforms.setValue(_gl, 'modelViewMatrix', object.modelViewMatrix);
30488			p_uniforms.setValue(_gl, 'normalMatrix', object.normalMatrix);
30489			p_uniforms.setValue(_gl, 'modelMatrix', object.matrixWorld);
30490
30491			// UBOs
30492
30493			if (material.isShaderMaterial || material.isRawShaderMaterial) {
30494
30495				const groups = material.uniformsGroups;
30496
30497				for (let i = 0, l = groups.length; i < l; i++) {
30498
30499					if (capabilities.isWebGL2) {
30500
30501						const group = groups[i];
30502
30503						uniformsGroups.update(group, program);
30504						uniformsGroups.bind(group, program);
30505
30506					} else {
30507
30508						console.warn('THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.');
30509
30510					}
30511
30512				}
30513
30514			}
30515
30516			return program;
30517
30518		}
30519
30520		// If uniforms are marked as clean, they don't need to be loaded to the GPU.
30521
30522		function markUniformsLightsNeedsUpdate(uniforms, value) {
30523
30524			uniforms.ambientLightColor.needsUpdate = value;
30525			uniforms.lightProbe.needsUpdate = value;
30526
30527			uniforms.directionalLights.needsUpdate = value;
30528			uniforms.directionalLightShadows.needsUpdate = value;
30529			uniforms.pointLights.needsUpdate = value;
30530			uniforms.pointLightShadows.needsUpdate = value;
30531			uniforms.spotLights.needsUpdate = value;
30532			uniforms.spotLightShadows.needsUpdate = value;
30533			uniforms.rectAreaLights.needsUpdate = value;
30534			uniforms.hemisphereLights.needsUpdate = value;
30535
30536		}
30537
30538		function materialNeedsLights(material) {
30539
30540			return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
30541				material.isMeshStandardMaterial || material.isShadowMaterial ||
30542				(material.isShaderMaterial && material.lights === true);
30543
30544		}
30545
30546		this.getActiveCubeFace = function () {
30547
30548			return _currentActiveCubeFace;
30549
30550		};
30551
30552		this.getActiveMipmapLevel = function () {
30553
30554			return _currentActiveMipmapLevel;
30555
30556		};
30557
30558		this.getRenderTarget = function () {
30559
30560			return _currentRenderTarget;
30561
30562		};
30563
30564		this.setRenderTargetTextures = function (renderTarget, colorTexture, depthTexture) {
30565
30566			properties.get(renderTarget.texture).__webglTexture = colorTexture;
30567			properties.get(renderTarget.depthTexture).__webglTexture = depthTexture;
30568
30569			const renderTargetProperties = properties.get(renderTarget);
30570			renderTargetProperties.__hasExternalTextures = true;
30571
30572			if (renderTargetProperties.__hasExternalTextures) {
30573
30574				renderTargetProperties.__autoAllocateDepthBuffer = depthTexture === undefined;
30575
30576				if (!renderTargetProperties.__autoAllocateDepthBuffer) {
30577
30578					// The multisample_render_to_texture extension doesn't work properly if there
30579					// are midframe flushes and an external depth buffer. Disable use of the extension.
30580					if (extensions.has('WEBGL_multisampled_render_to_texture') === true) {
30581
30582						console.warn('THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided');
30583						renderTargetProperties.__useRenderToTexture = false;
30584
30585					}
30586
30587				}
30588
30589			}
30590
30591		};
30592
30593		this.setRenderTargetFramebuffer = function (renderTarget, defaultFramebuffer) {
30594
30595			const renderTargetProperties = properties.get(renderTarget);
30596			renderTargetProperties.__webglFramebuffer = defaultFramebuffer;
30597			renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer === undefined;
30598
30599		};
30600
30601		this.setRenderTarget = function (renderTarget, activeCubeFace = 0, activeMipmapLevel = 0) {
30602
30603			_currentRenderTarget = renderTarget;
30604			_currentActiveCubeFace = activeCubeFace;
30605			_currentActiveMipmapLevel = activeMipmapLevel;
30606
30607			let useDefaultFramebuffer = true;
30608			let framebuffer = null;
30609			let isCube = false;
30610			let isRenderTarget3D = false;
30611
30612			if (renderTarget) {
30613
30614				const renderTargetProperties = properties.get(renderTarget);
30615
30616				if (renderTargetProperties.__useDefaultFramebuffer !== undefined) {
30617
30618					// We need to make sure to rebind the framebuffer.
30619					state.bindFramebuffer(_gl.FRAMEBUFFER, null);
30620					useDefaultFramebuffer = false;
30621
30622				} else if (renderTargetProperties.__webglFramebuffer === undefined) {
30623
30624					textures.setupRenderTarget(renderTarget);
30625
30626				} else if (renderTargetProperties.__hasExternalTextures) {
30627
30628					// Color and depth texture must be rebound in order for the swapchain to update.
30629					textures.rebindTextures(renderTarget, properties.get(renderTarget.texture).__webglTexture, properties.get(renderTarget.depthTexture).__webglTexture);
30630
30631				}
30632
30633				const texture = renderTarget.texture;
30634
30635				if (texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture) {
30636
30637					isRenderTarget3D = true;
30638
30639				}
30640
30641				const __webglFramebuffer = properties.get(renderTarget).__webglFramebuffer;
30642
30643				if (renderTarget.isWebGLCubeRenderTarget) {
30644
30645					if (Array.isArray(__webglFramebuffer[activeCubeFace])) {
30646
30647						framebuffer = __webglFramebuffer[activeCubeFace][activeMipmapLevel];
30648
30649					} else {
30650
30651						framebuffer = __webglFramebuffer[activeCubeFace];
30652
30653					}
30654
30655					isCube = true;
30656
30657				} else if ((capabilities.isWebGL2 && renderTarget.samples > 0) && textures.useMultisampledRTT(renderTarget) === false) {
30658
30659					framebuffer = properties.get(renderTarget).__webglMultisampledFramebuffer;
30660
30661				} else {
30662
30663					if (Array.isArray(__webglFramebuffer)) {
30664
30665						framebuffer = __webglFramebuffer[activeMipmapLevel];
30666
30667					} else {
30668
30669						framebuffer = __webglFramebuffer;
30670
30671					}
30672
30673				}
30674
30675				_currentViewport.copy(renderTarget.viewport);
30676				_currentScissor.copy(renderTarget.scissor);
30677				_currentScissorTest = renderTarget.scissorTest;
30678
30679			} else {
30680
30681				_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio).floor();
30682				_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio).floor();
30683				_currentScissorTest = _scissorTest;
30684
30685			}
30686
30687			const framebufferBound = state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
30688
30689			if (framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer) {
30690
30691				state.drawBuffers(renderTarget, framebuffer);
30692
30693			}
30694
30695			state.viewport(_currentViewport);
30696			state.scissor(_currentScissor);
30697			state.setScissorTest(_currentScissorTest);
30698
30699			if (isCube) {
30700
30701				const textureProperties = properties.get(renderTarget.texture);
30702				_gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel);
30703
30704			} else if (isRenderTarget3D) {
30705
30706				const textureProperties = properties.get(renderTarget.texture);
30707				const layer = activeCubeFace || 0;
30708				_gl.framebufferTextureLayer(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer);
30709
30710			}
30711
30712			_currentMaterialId = - 1; // reset current material to ensure correct uniform bindings
30713
30714		};
30715
30716		this.readRenderTargetPixels = function (renderTarget, x, y, width, height, buffer, activeCubeFaceIndex) {
30717
30718			if (!(renderTarget && renderTarget.isWebGLRenderTarget)) {
30719
30720				console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.');
30721				return;
30722
30723			}
30724
30725			let framebuffer = properties.get(renderTarget).__webglFramebuffer;
30726
30727			if (renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined) {
30728
30729				framebuffer = framebuffer[activeCubeFaceIndex];
30730
30731			}
30732
30733			if (framebuffer) {
30734
30735				state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
30736
30737				try {
30738
30739					const texture = renderTarget.texture;
30740					const textureFormat = texture.format;
30741					const textureType = texture.type;
30742
30743					if (textureFormat !== RGBAFormat && utils.convert(textureFormat) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_FORMAT)) {
30744
30745						console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.');
30746						return;
30747
30748					}
30749
30750					const halfFloatSupportedByExt = (textureType === HalfFloatType) && (extensions.has('EXT_color_buffer_half_float') || (capabilities.isWebGL2 && extensions.has('EXT_color_buffer_float')));
30751
30752					if (textureType !== UnsignedByteType && utils.convert(textureType) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_TYPE) && // Edge and Chrome Mac < 52 (#9513)
30753						!(textureType === FloatType && (capabilities.isWebGL2 || extensions.has('OES_texture_float') || extensions.has('WEBGL_color_buffer_float'))) && // Chrome Mac >= 52 and Firefox
30754						!halfFloatSupportedByExt) {
30755
30756						console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.');
30757						return;
30758
30759					}
30760
30761					// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)
30762
30763					if ((x >= 0 && x <= (renderTarget.width - width)) && (y >= 0 && y <= (renderTarget.height - height))) {
30764
30765						_gl.readPixels(x, y, width, height, utils.convert(textureFormat), utils.convert(textureType), buffer);
30766
30767					}
30768
30769				} finally {
30770
30771					// restore framebuffer of current render target if necessary
30772
30773					const framebuffer = (_currentRenderTarget !== null) ? properties.get(_currentRenderTarget).__webglFramebuffer : null;
30774					state.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
30775
30776				}
30777
30778			}
30779
30780		};
30781
30782		this.copyFramebufferToTexture = function (position, texture, level = 0) {
30783
30784			const levelScale = Math.pow(2, - level);
30785			const width = Math.floor(texture.image.width * levelScale);
30786			const height = Math.floor(texture.image.height * levelScale);
30787
30788			textures.setTexture2D(texture, 0);
30789
30790			_gl.copyTexSubImage2D(_gl.TEXTURE_2D, level, 0, 0, position.x, position.y, width, height);
30791
30792			state.unbindTexture();
30793
30794		};
30795
30796		this.copyTextureToTexture = function (position, srcTexture, dstTexture, level = 0) {
30797
30798			const width = srcTexture.image.width;
30799			const height = srcTexture.image.height;
30800			const glFormat = utils.convert(dstTexture.format);
30801			const glType = utils.convert(dstTexture.type);
30802
30803			textures.setTexture2D(dstTexture, 0);
30804
30805			// As another texture upload may have changed pixelStorei
30806			// parameters, make sure they are correct for the dstTexture
30807			_gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY);
30808			_gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha);
30809			_gl.pixelStorei(_gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment);
30810
30811			if (srcTexture.isDataTexture) {
30812
30813				_gl.texSubImage2D(_gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data);
30814
30815			} else {
30816
30817				if (srcTexture.isCompressedTexture) {
30818
30819					_gl.compressedTexSubImage2D(_gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[0].width, srcTexture.mipmaps[0].height, glFormat, srcTexture.mipmaps[0].data);
30820
30821				} else {
30822
30823					_gl.texSubImage2D(_gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image);
30824
30825				}
30826
30827			}
30828
30829			// Generate mipmaps only when copying level 0
30830			if (level === 0 && dstTexture.generateMipmaps) _gl.generateMipmap(_gl.TEXTURE_2D);
30831
30832			state.unbindTexture();
30833
30834		};
30835
30836		this.copyTextureToTexture3D = function (sourceBox, position, srcTexture, dstTexture, level = 0) {
30837
30838			if (_this.isWebGL1Renderer) {
30839
30840				console.warn('THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.');
30841				return;
30842
30843			}
30844
30845			const width = sourceBox.max.x - sourceBox.min.x + 1;
30846			const height = sourceBox.max.y - sourceBox.min.y + 1;
30847			const depth = sourceBox.max.z - sourceBox.min.z + 1;
30848			const glFormat = utils.convert(dstTexture.format);
30849			const glType = utils.convert(dstTexture.type);
30850			let glTarget;
30851
30852			if (dstTexture.isData3DTexture) {
30853
30854				textures.setTexture3D(dstTexture, 0);
30855				glTarget = _gl.TEXTURE_3D;
30856
30857			} else if (dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture) {
30858
30859				textures.setTexture2DArray(dstTexture, 0);
30860				glTarget = _gl.TEXTURE_2D_ARRAY;
30861
30862			} else {
30863
30864				console.warn('THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.');
30865				return;
30866
30867			}
30868
30869			_gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY);
30870			_gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha);
30871			_gl.pixelStorei(_gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment);
30872
30873			const unpackRowLen = _gl.getParameter(_gl.UNPACK_ROW_LENGTH);
30874			const unpackImageHeight = _gl.getParameter(_gl.UNPACK_IMAGE_HEIGHT);
30875			const unpackSkipPixels = _gl.getParameter(_gl.UNPACK_SKIP_PIXELS);
30876			const unpackSkipRows = _gl.getParameter(_gl.UNPACK_SKIP_ROWS);
30877			const unpackSkipImages = _gl.getParameter(_gl.UNPACK_SKIP_IMAGES);
30878
30879			const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[level] : srcTexture.image;
30880
30881			_gl.pixelStorei(_gl.UNPACK_ROW_LENGTH, image.width);
30882			_gl.pixelStorei(_gl.UNPACK_IMAGE_HEIGHT, image.height);
30883			_gl.pixelStorei(_gl.UNPACK_SKIP_PIXELS, sourceBox.min.x);
30884			_gl.pixelStorei(_gl.UNPACK_SKIP_ROWS, sourceBox.min.y);
30885			_gl.pixelStorei(_gl.UNPACK_SKIP_IMAGES, sourceBox.min.z);
30886
30887			if (srcTexture.isDataTexture || srcTexture.isData3DTexture) {
30888
30889				_gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image.data);
30890
30891			} else {
30892
30893				if (srcTexture.isCompressedArrayTexture) {
30894
30895					console.warn('THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.');
30896					_gl.compressedTexSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, image.data);
30897
30898				} else {
30899
30900					_gl.texSubImage3D(glTarget, level, position.x, position.y, position.z, width, height, depth, glFormat, glType, image);
30901
30902				}
30903
30904			}
30905
30906			_gl.pixelStorei(_gl.UNPACK_ROW_LENGTH, unpackRowLen);
30907			_gl.pixelStorei(_gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight);
30908			_gl.pixelStorei(_gl.UNPACK_SKIP_PIXELS, unpackSkipPixels);
30909			_gl.pixelStorei(_gl.UNPACK_SKIP_ROWS, unpackSkipRows);
30910			_gl.pixelStorei(_gl.UNPACK_SKIP_IMAGES, unpackSkipImages);
30911
30912			// Generate mipmaps only when copying level 0
30913			if (level === 0 && dstTexture.generateMipmaps) _gl.generateMipmap(glTarget);
30914
30915			state.unbindTexture();
30916
30917		};
30918
30919		this.initTexture = function (texture) {
30920
30921			if (texture.isCubeTexture) {
30922
30923				textures.setTextureCube(texture, 0);
30924
30925			} else if (texture.isData3DTexture) {
30926
30927				textures.setTexture3D(texture, 0);
30928
30929			} else if (texture.isDataArrayTexture || texture.isCompressedArrayTexture) {
30930
30931				textures.setTexture2DArray(texture, 0);
30932
30933			} else {
30934
30935				textures.setTexture2D(texture, 0);
30936
30937			}
30938
30939			state.unbindTexture();
30940
30941		};
30942
30943		this.resetState = function () {
30944
30945			_currentActiveCubeFace = 0;
30946			_currentActiveMipmapLevel = 0;
30947			_currentRenderTarget = null;
30948
30949			state.reset();
30950			bindingStates.reset();
30951
30952		};
30953
30954		if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
30955
30956			__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('observe', { detail: this }));
30957
30958		}
30959
30960	}
30961
30962	get coordinateSystem() {
30963
30964		return WebGLCoordinateSystem;
30965
30966	}
30967
30968	get outputColorSpace() {
30969
30970		return this._outputColorSpace;
30971
30972	}
30973
30974	set outputColorSpace(colorSpace) {
30975
30976		this._outputColorSpace = colorSpace;
30977
30978		const gl = this.getContext();
30979		gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ? 'display-p3' : 'srgb';
30980		gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ? 'display-p3' : 'srgb';
30981
30982	}
30983
30984	get outputEncoding() { // @deprecated, r152
30985
30986		console.warn('THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.');
30987		return this.outputColorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
30988
30989	}
30990
30991	set outputEncoding(encoding) { // @deprecated, r152
30992
30993		console.warn('THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.');
30994		this.outputColorSpace = encoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
30995
30996	}
30997
30998	get useLegacyLights() { // @deprecated, r155
30999
31000		console.warn('THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.');
31001		return this._useLegacyLights;
31002
31003	}
31004
31005	set useLegacyLights(value) { // @deprecated, r155
31006
31007		console.warn('THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.');
31008		this._useLegacyLights = value;
31009
31010	}
31011
31012}
31013
31014class WebGL1Renderer extends WebGLRenderer { }
31015
31016WebGL1Renderer.prototype.isWebGL1Renderer = true;
31017
31018class FogExp2 {
31019
31020	constructor(color, density = 0.00025) {
31021
31022		this.isFogExp2 = true;
31023
31024		this.name = '';
31025
31026		this.color = new Color(color);
31027		this.density = density;
31028
31029	}
31030
31031	clone() {
31032
31033		return new FogExp2(this.color, this.density);
31034
31035	}
31036
31037	toJSON( /* meta */) {
31038
31039		return {
31040			type: 'FogExp2',
31041			name: this.name,
vendor: 5,137 bytes, lines 31042-31341
31042			color: this.color.getHex(),
31043			density: this.density
31044		};
31045
31046	}
31047
31048}
31049
31050class Fog {
31051
31052	constructor(color, near = 1, far = 1000) {
31053
31054		this.isFog = true;
31055
31056		this.name = '';
31057
31058		this.color = new Color(color);
31059
31060		this.near = near;
31061		this.far = far;
31062
31063	}
31064
31065	clone() {
31066
31067		return new Fog(this.color, this.near, this.far);
31068
31069	}
31070
31071	toJSON( /* meta */) {
31072
31073		return {
31074			type: 'Fog',
31075			name: this.name,
31076			color: this.color.getHex(),
31077			near: this.near,
31078			far: this.far
31079		};
31080
31081	}
31082
31083}
31084
31085class Scene extends Object3D {
31086
31087	constructor() {
31088
31089		super();
31090
31091		this.isScene = true;
31092
31093		this.type = 'Scene';
31094
31095		this.background = null;
31096		this.environment = null;
31097		this.fog = null;
31098
31099		this.backgroundBlurriness = 0;
31100		this.backgroundIntensity = 1;
31101
31102		this.overrideMaterial = null;
31103
31104		if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
31105
31106			__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('observe', { detail: this }));
31107
31108		}
31109
31110	}
31111
31112	copy(source, recursive) {
31113
31114		super.copy(source, recursive);
31115
31116		if (source.background !== null) this.background = source.background.clone();
31117		if (source.environment !== null) this.environment = source.environment.clone();
31118		if (source.fog !== null) this.fog = source.fog.clone();
31119
31120		this.backgroundBlurriness = source.backgroundBlurriness;
31121		this.backgroundIntensity = source.backgroundIntensity;
31122
31123		if (source.overrideMaterial !== null) this.overrideMaterial = source.overrideMaterial.clone();
31124
31125		this.matrixAutoUpdate = source.matrixAutoUpdate;
31126
31127		return this;
31128
31129	}
31130
31131	toJSON(meta) {
31132
31133		const data = super.toJSON(meta);
31134
31135		if (this.fog !== null) data.object.fog = this.fog.toJSON();
31136		if (this.backgroundBlurriness > 0) data.object.backgroundBlurriness = this.backgroundBlurriness;
31137		if (this.backgroundIntensity !== 1) data.object.backgroundIntensity = this.backgroundIntensity;
31138
31139		return data;
31140
31141	}
31142
31143}
31144
31145class InterleavedBuffer {
31146
31147	constructor(array, stride) {
31148
31149		this.isInterleavedBuffer = true;
31150
31151		this.array = array;
31152		this.stride = stride;
31153		this.count = array !== undefined ? array.length / stride : 0;
31154
31155		this.usage = StaticDrawUsage;
31156		this._updateRange = { offset: 0, count: - 1 };
31157		this.updateRanges = [];
31158
31159		this.version = 0;
31160
31161		this.uuid = generateUUID();
31162
31163	}
31164
31165	onUploadCallback() { }
31166
31167	set needsUpdate(value) {
31168
31169		if (value === true) this.version++;
31170
31171	}
31172
31173	get updateRange() {
31174
31175		console.warn('THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.'); // @deprecated, r159
31176		return this._updateRange;
31177
31178	}
31179
31180	setUsage(value) {
31181
31182		this.usage = value;
31183
31184		return this;
31185
31186	}
31187
31188	addUpdateRange(start, count) {
31189
31190		this.updateRanges.push({ start, count });
31191
31192	}
31193
31194	clearUpdateRanges() {
31195
31196		this.updateRanges.length = 0;
31197
31198	}
31199
31200	copy(source) {
31201
31202		this.array = new source.array.constructor(source.array);
31203		this.count = source.count;
31204		this.stride = source.stride;
31205		this.usage = source.usage;
31206
31207		return this;
31208
31209	}
31210
31211	copyAt(index1, attribute, index2) {
31212
31213		index1 *= this.stride;
31214		index2 *= attribute.stride;
31215
31216		for (let i = 0, l = this.stride; i < l; i++) {
31217
31218			this.array[index1 + i] = attribute.array[index2 + i];
31219
31220		}
31221
31222		return this;
31223
31224	}
31225
31226	set(value, offset = 0) {
31227
31228		this.array.set(value, offset);
31229
31230		return this;
31231
31232	}
31233
31234	clone(data) {
31235
31236		if (data.arrayBuffers === undefined) {
31237
31238			data.arrayBuffers = {};
31239
31240		}
31241
31242		if (this.array.buffer._uuid === undefined) {
31243
31244			this.array.buffer._uuid = generateUUID();
31245
31246		}
31247
31248		if (data.arrayBuffers[this.array.buffer._uuid] === undefined) {
31249
31250			data.arrayBuffers[this.array.buffer._uuid] = this.array.slice(0).buffer;
31251
31252		}
31253
31254		const array = new this.array.constructor(data.arrayBuffers[this.array.buffer._uuid]);
31255
31256		const ib = new this.constructor(array, this.stride);
31257		ib.setUsage(this.usage);
31258
31259		return ib;
31260
31261	}
31262
31263	onUpload(callback) {
31264
31265		this.onUploadCallback = callback;
31266
31267		return this;
31268
31269	}
31270
31271	toJSON(data) {
31272
31273		if (data.arrayBuffers === undefined) {
31274
31275			data.arrayBuffers = {};
31276
31277		}
31278
31279		// generate UUID for array buffer if necessary
31280
31281		if (this.array.buffer._uuid === undefined) {
31282
31283			this.array.buffer._uuid = generateUUID();
31284
31285		}
31286
31287		if (data.arrayBuffers[this.array.buffer._uuid] === undefined) {
31288
31289			data.arrayBuffers[this.array.buffer._uuid] = Array.from(new Uint32Array(this.array.buffer));
31290
31291		}
31292
31293		//
31294
31295		return {
31296			uuid: this.uuid,
31297			buffer: this.array.buffer._uuid,
31298			type: this.array.constructor.name,
31299			stride: this.stride
31300		};
31301
31302	}
31303
31304}
31305
31306const _vector$6 = /*@__PURE__*/ new Vector3();
31307
31308class InterleavedBufferAttribute {
31309
31310	constructor(interleavedBuffer, itemSize, offset, normalized = false) {
31311
31312		this.isInterleavedBufferAttribute = true;
31313
31314		this.name = '';
31315
31316		this.data = interleavedBuffer;
31317		this.itemSize = itemSize;
31318		this.offset = offset;
31319
31320		this.normalized = normalized;
31321
31322	}
31323
31324	get count() {
31325
31326		return this.data.count;
31327
31328	}
31329
31330	get array() {
31331
31332		return this.data.array;
31333
31334	}
31335
31336	set needsUpdate(value) {
31337
31338		this.data.needsUpdate = value;
31339
31340	}
31341
vendor: 15,636 bytes, lines 31342-32161
31342	applyMatrix4(m) {
31343
31344		for (let i = 0, l = this.data.count; i < l; i++) {
31345
31346			_vector$6.fromBufferAttribute(this, i);
31347
31348			_vector$6.applyMatrix4(m);
31349
31350			this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z);
31351
31352		}
31353
31354		return this;
31355
31356	}
31357
31358	applyNormalMatrix(m) {
31359
31360		for (let i = 0, l = this.count; i < l; i++) {
31361
31362			_vector$6.fromBufferAttribute(this, i);
31363
31364			_vector$6.applyNormalMatrix(m);
31365
31366			this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z);
31367
31368		}
31369
31370		return this;
31371
31372	}
31373
31374	transformDirection(m) {
31375
31376		for (let i = 0, l = this.count; i < l; i++) {
31377
31378			_vector$6.fromBufferAttribute(this, i);
31379
31380			_vector$6.transformDirection(m);
31381
31382			this.setXYZ(i, _vector$6.x, _vector$6.y, _vector$6.z);
31383
31384		}
31385
31386		return this;
31387
31388	}
31389
31390	setX(index, x) {
31391
31392		if (this.normalized) x = normalize(x, this.array);
31393
31394		this.data.array[index * this.data.stride + this.offset] = x;
31395
31396		return this;
31397
31398	}
31399
31400	setY(index, y) {
31401
31402		if (this.normalized) y = normalize(y, this.array);
31403
31404		this.data.array[index * this.data.stride + this.offset + 1] = y;
31405
31406		return this;
31407
31408	}
31409
31410	setZ(index, z) {
31411
31412		if (this.normalized) z = normalize(z, this.array);
31413
31414		this.data.array[index * this.data.stride + this.offset + 2] = z;
31415
31416		return this;
31417
31418	}
31419
31420	setW(index, w) {
31421
31422		if (this.normalized) w = normalize(w, this.array);
31423
31424		this.data.array[index * this.data.stride + this.offset + 3] = w;
31425
31426		return this;
31427
31428	}
31429
31430	getX(index) {
31431
31432		let x = this.data.array[index * this.data.stride + this.offset];
31433
31434		if (this.normalized) x = denormalize(x, this.array);
31435
31436		return x;
31437
31438	}
31439
31440	getY(index) {
31441
31442		let y = this.data.array[index * this.data.stride + this.offset + 1];
31443
31444		if (this.normalized) y = denormalize(y, this.array);
31445
31446		return y;
31447
31448	}
31449
31450	getZ(index) {
31451
31452		let z = this.data.array[index * this.data.stride + this.offset + 2];
31453
31454		if (this.normalized) z = denormalize(z, this.array);
31455
31456		return z;
31457
31458	}
31459
31460	getW(index) {
31461
31462		let w = this.data.array[index * this.data.stride + this.offset + 3];
31463
31464		if (this.normalized) w = denormalize(w, this.array);
31465
31466		return w;
31467
31468	}
31469
31470	setXY(index, x, y) {
31471
31472		index = index * this.data.stride + this.offset;
31473
31474		if (this.normalized) {
31475
31476			x = normalize(x, this.array);
31477			y = normalize(y, this.array);
31478
31479		}
31480
31481		this.data.array[index + 0] = x;
31482		this.data.array[index + 1] = y;
31483
31484		return this;
31485
31486	}
31487
31488	setXYZ(index, x, y, z) {
31489
31490		index = index * this.data.stride + this.offset;
31491
31492		if (this.normalized) {
31493
31494			x = normalize(x, this.array);
31495			y = normalize(y, this.array);
31496			z = normalize(z, this.array);
31497
31498		}
31499
31500		this.data.array[index + 0] = x;
31501		this.data.array[index + 1] = y;
31502		this.data.array[index + 2] = z;
31503
31504		return this;
31505
31506	}
31507
31508	setXYZW(index, x, y, z, w) {
31509
31510		index = index * this.data.stride + this.offset;
31511
31512		if (this.normalized) {
31513
31514			x = normalize(x, this.array);
31515			y = normalize(y, this.array);
31516			z = normalize(z, this.array);
31517			w = normalize(w, this.array);
31518
31519		}
31520
31521		this.data.array[index + 0] = x;
31522		this.data.array[index + 1] = y;
31523		this.data.array[index + 2] = z;
31524		this.data.array[index + 3] = w;
31525
31526		return this;
31527
31528	}
31529
31530	clone(data) {
31531
31532		if (data === undefined) {
31533
31534			console.log('THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.');
31535
31536			const array = [];
31537
31538			for (let i = 0; i < this.count; i++) {
31539
31540				const index = i * this.data.stride + this.offset;
31541
31542				for (let j = 0; j < this.itemSize; j++) {
31543
31544					array.push(this.data.array[index + j]);
31545
31546				}
31547
31548			}
31549
31550			return new BufferAttribute(new this.array.constructor(array), this.itemSize, this.normalized);
31551
31552		} else {
31553
31554			if (data.interleavedBuffers === undefined) {
31555
31556				data.interleavedBuffers = {};
31557
31558			}
31559
31560			if (data.interleavedBuffers[this.data.uuid] === undefined) {
31561
31562				data.interleavedBuffers[this.data.uuid] = this.data.clone(data);
31563
31564			}
31565
31566			return new InterleavedBufferAttribute(data.interleavedBuffers[this.data.uuid], this.itemSize, this.offset, this.normalized);
31567
31568		}
31569
31570	}
31571
31572	toJSON(data) {
31573
31574		if (data === undefined) {
31575
31576			console.log('THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.');
31577
31578			const array = [];
31579
31580			for (let i = 0; i < this.count; i++) {
31581
31582				const index = i * this.data.stride + this.offset;
31583
31584				for (let j = 0; j < this.itemSize; j++) {
31585
31586					array.push(this.data.array[index + j]);
31587
31588				}
31589
31590			}
31591
31592			// de-interleave data and save it as an ordinary buffer attribute for now
31593
31594			return {
31595				itemSize: this.itemSize,
31596				type: this.array.constructor.name,
31597				array: array,
31598				normalized: this.normalized
31599			};
31600
31601		} else {
31602
31603			// save as true interleaved attribute
31604
31605			if (data.interleavedBuffers === undefined) {
31606
31607				data.interleavedBuffers = {};
31608
31609			}
31610
31611			if (data.interleavedBuffers[this.data.uuid] === undefined) {
31612
31613				data.interleavedBuffers[this.data.uuid] = this.data.toJSON(data);
31614
31615			}
31616
31617			return {
31618				isInterleavedBufferAttribute: true,
31619				itemSize: this.itemSize,
31620				data: this.data.uuid,
31621				offset: this.offset,
31622				normalized: this.normalized
31623			};
31624
31625		}
31626
31627	}
31628
31629}
31630
31631class SpriteMaterial extends Material {
31632
31633	constructor(parameters) {
31634
31635		super();
31636
31637		this.isSpriteMaterial = true;
31638
31639		this.type = 'SpriteMaterial';
31640
31641		this.color = new Color(0xffffff);
31642
31643		this.map = null;
31644
31645		this.alphaMap = null;
31646
31647		this.rotation = 0;
31648
31649		this.sizeAttenuation = true;
31650
31651		this.transparent = true;
31652
31653		this.fog = true;
31654
31655		this.setValues(parameters);
31656
31657	}
31658
31659	copy(source) {
31660
31661		super.copy(source);
31662
31663		this.color.copy(source.color);
31664
31665		this.map = source.map;
31666
31667		this.alphaMap = source.alphaMap;
31668
31669		this.rotation = source.rotation;
31670
31671		this.sizeAttenuation = source.sizeAttenuation;
31672
31673		this.fog = source.fog;
31674
31675		return this;
31676
31677	}
31678
31679}
31680
31681let _geometry;
31682
31683const _intersectPoint = /*@__PURE__*/ new Vector3();
31684const _worldScale = /*@__PURE__*/ new Vector3();
31685const _mvPosition = /*@__PURE__*/ new Vector3();
31686
31687const _alignedPosition = /*@__PURE__*/ new Vector2();
31688const _rotatedPosition = /*@__PURE__*/ new Vector2();
31689const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
31690
31691const _vA = /*@__PURE__*/ new Vector3();
31692const _vB = /*@__PURE__*/ new Vector3();
31693const _vC = /*@__PURE__*/ new Vector3();
31694
31695const _uvA = /*@__PURE__*/ new Vector2();
31696const _uvB = /*@__PURE__*/ new Vector2();
31697const _uvC = /*@__PURE__*/ new Vector2();
31698
31699class Sprite extends Object3D {
31700
31701	constructor(material = new SpriteMaterial()) {
31702
31703		super();
31704
31705		this.isSprite = true;
31706
31707		this.type = 'Sprite';
31708
31709		if (_geometry === undefined) {
31710
31711			_geometry = new BufferGeometry();
31712
31713			const float32Array = new Float32Array([
31714				- 0.5, - 0.5, 0, 0, 0,
31715				0.5, - 0.5, 0, 1, 0,
31716				0.5, 0.5, 0, 1, 1,
31717				- 0.5, 0.5, 0, 0, 1
31718			]);
31719
31720			const interleavedBuffer = new InterleavedBuffer(float32Array, 5);
31721
31722			_geometry.setIndex([0, 1, 2, 0, 2, 3]);
31723			_geometry.setAttribute('position', new InterleavedBufferAttribute(interleavedBuffer, 3, 0, false));
31724			_geometry.setAttribute('uv', new InterleavedBufferAttribute(interleavedBuffer, 2, 3, false));
31725
31726		}
31727
31728		this.geometry = _geometry;
31729		this.material = material;
31730
31731		this.center = new Vector2(0.5, 0.5);
31732
31733	}
31734
31735	raycast(raycaster, intersects) {
31736
31737		if (raycaster.camera === null) {
31738
31739			console.error('THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.');
31740
31741		}
31742
31743		_worldScale.setFromMatrixScale(this.matrixWorld);
31744
31745		_viewWorldMatrix.copy(raycaster.camera.matrixWorld);
31746		this.modelViewMatrix.multiplyMatrices(raycaster.camera.matrixWorldInverse, this.matrixWorld);
31747
31748		_mvPosition.setFromMatrixPosition(this.modelViewMatrix);
31749
31750		if (raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false) {
31751
31752			_worldScale.multiplyScalar(- _mvPosition.z);
31753
31754		}
31755
31756		const rotation = this.material.rotation;
31757		let sin, cos;
31758
31759		if (rotation !== 0) {
31760
31761			cos = Math.cos(rotation);
31762			sin = Math.sin(rotation);
31763
31764		}
31765
31766		const center = this.center;
31767
31768		transformVertex(_vA.set(- 0.5, - 0.5, 0), _mvPosition, center, _worldScale, sin, cos);
31769		transformVertex(_vB.set(0.5, - 0.5, 0), _mvPosition, center, _worldScale, sin, cos);
31770		transformVertex(_vC.set(0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos);
31771
31772		_uvA.set(0, 0);
31773		_uvB.set(1, 0);
31774		_uvC.set(1, 1);
31775
31776		// check first triangle
31777		let intersect = raycaster.ray.intersectTriangle(_vA, _vB, _vC, false, _intersectPoint);
31778
31779		if (intersect === null) {
31780
31781			// check second triangle
31782			transformVertex(_vB.set(- 0.5, 0.5, 0), _mvPosition, center, _worldScale, sin, cos);
31783			_uvB.set(0, 1);
31784
31785			intersect = raycaster.ray.intersectTriangle(_vA, _vC, _vB, false, _intersectPoint);
31786			if (intersect === null) {
31787
31788				return;
31789
31790			}
31791
31792		}
31793
31794		const distance = raycaster.ray.origin.distanceTo(_intersectPoint);
31795
31796		if (distance < raycaster.near || distance > raycaster.far) return;
31797
31798		intersects.push({
31799
31800			distance: distance,
31801			point: _intersectPoint.clone(),
31802			uv: Triangle.getInterpolation(_intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2()),
31803			face: null,
31804			object: this
31805
31806		});
31807
31808	}
31809
31810	copy(source, recursive) {
31811
31812		super.copy(source, recursive);
31813
31814		if (source.center !== undefined) this.center.copy(source.center);
31815
31816		this.material = source.material;
31817
31818		return this;
31819
31820	}
31821
31822}
31823
31824function transformVertex(vertexPosition, mvPosition, center, scale, sin, cos) {
31825
31826	// compute position in camera space
31827	_alignedPosition.subVectors(vertexPosition, center).addScalar(0.5).multiply(scale);
31828
31829	// to check if rotation is not zero
31830	if (sin !== undefined) {
31831
31832		_rotatedPosition.x = (cos * _alignedPosition.x) - (sin * _alignedPosition.y);
31833		_rotatedPosition.y = (sin * _alignedPosition.x) + (cos * _alignedPosition.y);
31834
31835	} else {
31836
31837		_rotatedPosition.copy(_alignedPosition);
31838
31839	}
31840
31841
31842	vertexPosition.copy(mvPosition);
31843	vertexPosition.x += _rotatedPosition.x;
31844	vertexPosition.y += _rotatedPosition.y;
31845
31846	// transform to world space
31847	vertexPosition.applyMatrix4(_viewWorldMatrix);
31848
31849}
31850
31851const _v1$2 = /*@__PURE__*/ new Vector3();
31852const _v2$1 = /*@__PURE__*/ new Vector3();
31853
31854class LOD extends Object3D {
31855
31856	constructor() {
31857
31858		super();
31859
31860		this._currentLevel = 0;
31861
31862		this.type = 'LOD';
31863
31864		Object.defineProperties(this, {
31865			levels: {
31866				enumerable: true,
31867				value: []
31868			},
31869			isLOD: {
31870				value: true,
31871			}
31872		});
31873
31874		this.autoUpdate = true;
31875
31876	}
31877
31878	copy(source) {
31879
31880		super.copy(source, false);
31881
31882		const levels = source.levels;
31883
31884		for (let i = 0, l = levels.length; i < l; i++) {
31885
31886			const level = levels[i];
31887
31888			this.addLevel(level.object.clone(), level.distance, level.hysteresis);
31889
31890		}
31891
31892		this.autoUpdate = source.autoUpdate;
31893
31894		return this;
31895
31896	}
31897
31898	addLevel(object, distance = 0, hysteresis = 0) {
31899
31900		distance = Math.abs(distance);
31901
31902		const levels = this.levels;
31903
31904		let l;
31905
31906		for (l = 0; l < levels.length; l++) {
31907
31908			if (distance < levels[l].distance) {
31909
31910				break;
31911
31912			}
31913
31914		}
31915
31916		levels.splice(l, 0, { distance: distance, hysteresis: hysteresis, object: object });
31917
31918		this.add(object);
31919
31920		return this;
31921
31922	}
31923
31924	getCurrentLevel() {
31925
31926		return this._currentLevel;
31927
31928	}
31929
31930
31931
31932	getObjectForDistance(distance) {
31933
31934		const levels = this.levels;
31935
31936		if (levels.length > 0) {
31937
31938			let i, l;
31939
31940			for (i = 1, l = levels.length; i < l; i++) {
31941
31942				let levelDistance = levels[i].distance;
31943
31944				if (levels[i].object.visible) {
31945
31946					levelDistance -= levelDistance * levels[i].hysteresis;
31947
31948				}
31949
31950				if (distance < levelDistance) {
31951
31952					break;
31953
31954				}
31955
31956			}
31957
31958			return levels[i - 1].object;
31959
31960		}
31961
31962		return null;
31963
31964	}
31965
31966	raycast(raycaster, intersects) {
31967
31968		const levels = this.levels;
31969
31970		if (levels.length > 0) {
31971
31972			_v1$2.setFromMatrixPosition(this.matrixWorld);
31973
31974			const distance = raycaster.ray.origin.distanceTo(_v1$2);
31975
31976			this.getObjectForDistance(distance).raycast(raycaster, intersects);
31977
31978		}
31979
31980	}
31981
31982	update(camera) {
31983
31984		const levels = this.levels;
31985
31986		if (levels.length > 1) {
31987
31988			_v1$2.setFromMatrixPosition(camera.matrixWorld);
31989			_v2$1.setFromMatrixPosition(this.matrixWorld);
31990
31991			const distance = _v1$2.distanceTo(_v2$1) / camera.zoom;
31992
31993			levels[0].object.visible = true;
31994
31995			let i, l;
31996
31997			for (i = 1, l = levels.length; i < l; i++) {
31998
31999				let levelDistance = levels[i].distance;
32000
32001				if (levels[i].object.visible) {
32002
32003					levelDistance -= levelDistance * levels[i].hysteresis;
32004
32005				}
32006
32007				if (distance >= levelDistance) {
32008
32009					levels[i - 1].object.visible = false;
32010					levels[i].object.visible = true;
32011
32012				} else {
32013
32014					break;
32015
32016				}
32017
32018			}
32019
32020			this._currentLevel = i - 1;
32021
32022			for (; i < l; i++) {
32023
32024				levels[i].object.visible = false;
32025
32026			}
32027
32028		}
32029
32030	}
32031
32032	toJSON(meta) {
32033
32034		const data = super.toJSON(meta);
32035
32036		if (this.autoUpdate === false) data.object.autoUpdate = false;
32037
32038		data.object.levels = [];
32039
32040		const levels = this.levels;
32041
32042		for (let i = 0, l = levels.length; i < l; i++) {
32043
32044			const level = levels[i];
32045
32046			data.object.levels.push({
32047				object: level.object.uuid,
32048				distance: level.distance,
32049				hysteresis: level.hysteresis
32050			});
32051
32052		}
32053
32054		return data;
32055
32056	}
32057
32058}
32059
32060const _basePosition = /*@__PURE__*/ new Vector3();
32061
32062const _skinIndex = /*@__PURE__*/ new Vector4();
32063const _skinWeight = /*@__PURE__*/ new Vector4();
32064
32065const _vector3 = /*@__PURE__*/ new Vector3();
32066const _matrix4 = /*@__PURE__*/ new Matrix4();
32067const _vertex = /*@__PURE__*/ new Vector3();
32068
32069const _sphere$4 = /*@__PURE__*/ new Sphere();
32070const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4();
32071const _ray$2 = /*@__PURE__*/ new Ray();
32072
32073class SkinnedMesh extends Mesh {
32074
32075	constructor(geometry, material) {
32076
32077		super(geometry, material);
32078
32079		this.isSkinnedMesh = true;
32080
32081		this.type = 'SkinnedMesh';
32082
32083		this.bindMode = AttachedBindMode;
32084		this.bindMatrix = new Matrix4();
32085		this.bindMatrixInverse = new Matrix4();
32086
32087		this.boundingBox = null;
32088		this.boundingSphere = null;
32089
32090	}
32091
32092	computeBoundingBox() {
32093
32094		const geometry = this.geometry;
32095
32096		if (this.boundingBox === null) {
32097
32098			this.boundingBox = new Box3();
32099
32100		}
32101
32102		this.boundingBox.makeEmpty();
32103
32104		const positionAttribute = geometry.getAttribute('position');
32105
32106		for (let i = 0; i < positionAttribute.count; i++) {
32107
32108			this.getVertexPosition(i, _vertex);
32109			this.boundingBox.expandByPoint(_vertex);
32110
32111		}
32112
32113	}
32114
32115	computeBoundingSphere() {
32116
32117		const geometry = this.geometry;
32118
32119		if (this.boundingSphere === null) {
32120
32121			this.boundingSphere = new Sphere();
32122
32123		}
32124
32125		this.boundingSphere.makeEmpty();
32126
32127		const positionAttribute = geometry.getAttribute('position');
32128
32129		for (let i = 0; i < positionAttribute.count; i++) {
32130
32131			this.getVertexPosition(i, _vertex);
32132			this.boundingSphere.expandByPoint(_vertex);
32133
32134		}
32135
32136	}
32137
32138	copy(source, recursive) {
32139
32140		super.copy(source, recursive);
32141
32142		this.bindMode = source.bindMode;
32143		this.bindMatrix.copy(source.bindMatrix);
32144		this.bindMatrixInverse.copy(source.bindMatrixInverse);
32145
32146		this.skeleton = source.skeleton;
32147
32148		if (source.boundingBox !== null) this.boundingBox = source.boundingBox.clone();
32149		if (source.boundingSphere !== null) this.boundingSphere = source.boundingSphere.clone();
32150
32151		return this;
32152
32153	}
32154
32155	raycast(raycaster, intersects) {
32156
32157		const material = this.material;
32158		const matrixWorld = this.matrixWorld;
32159
32160		if (material === undefined) return;
32161
vendor: 13,367 bytes, lines 32162-32838
32162		// test with bounding sphere in world space
32163
32164		if (this.boundingSphere === null) this.computeBoundingSphere();
32165
32166		_sphere$4.copy(this.boundingSphere);
32167		_sphere$4.applyMatrix4(matrixWorld);
32168
32169		if (raycaster.ray.intersectsSphere(_sphere$4) === false) return;
32170
32171		// convert ray to local space of skinned mesh
32172
32173		_inverseMatrix$2.copy(matrixWorld).invert();
32174		_ray$2.copy(raycaster.ray).applyMatrix4(_inverseMatrix$2);
32175
32176		// test with bounding box in local space
32177
32178		if (this.boundingBox !== null) {
32179
32180			if (_ray$2.intersectsBox(this.boundingBox) === false) return;
32181
32182		}
32183
32184		// test for intersections with geometry
32185
32186		this._computeIntersections(raycaster, intersects, _ray$2);
32187
32188	}
32189
32190	getVertexPosition(index, target) {
32191
32192		super.getVertexPosition(index, target);
32193
32194		this.applyBoneTransform(index, target);
32195
32196		return target;
32197
32198	}
32199
32200	bind(skeleton, bindMatrix) {
32201
32202		this.skeleton = skeleton;
32203
32204		if (bindMatrix === undefined) {
32205
32206			this.updateMatrixWorld(true);
32207
32208			this.skeleton.calculateInverses();
32209
32210			bindMatrix = this.matrixWorld;
32211
32212		}
32213
32214		this.bindMatrix.copy(bindMatrix);
32215		this.bindMatrixInverse.copy(bindMatrix).invert();
32216
32217	}
32218
32219	pose() {
32220
32221		this.skeleton.pose();
32222
32223	}
32224
32225	normalizeSkinWeights() {
32226
32227		const vector = new Vector4();
32228
32229		const skinWeight = this.geometry.attributes.skinWeight;
32230
32231		for (let i = 0, l = skinWeight.count; i < l; i++) {
32232
32233			vector.fromBufferAttribute(skinWeight, i);
32234
32235			const scale = 1.0 / vector.manhattanLength();
32236
32237			if (scale !== Infinity) {
32238
32239				vector.multiplyScalar(scale);
32240
32241			} else {
32242
32243				vector.set(1, 0, 0, 0); // do something reasonable
32244
32245			}
32246
32247			skinWeight.setXYZW(i, vector.x, vector.y, vector.z, vector.w);
32248
32249		}
32250
32251	}
32252
32253	updateMatrixWorld(force) {
32254
32255		super.updateMatrixWorld(force);
32256
32257		if (this.bindMode === AttachedBindMode) {
32258
32259			this.bindMatrixInverse.copy(this.matrixWorld).invert();
32260
32261		} else if (this.bindMode === DetachedBindMode) {
32262
32263			this.bindMatrixInverse.copy(this.bindMatrix).invert();
32264
32265		} else {
32266
32267			console.warn('THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode);
32268
32269		}
32270
32271	}
32272
32273	applyBoneTransform(index, vector) {
32274
32275		const skeleton = this.skeleton;
32276		const geometry = this.geometry;
32277
32278		_skinIndex.fromBufferAttribute(geometry.attributes.skinIndex, index);
32279		_skinWeight.fromBufferAttribute(geometry.attributes.skinWeight, index);
32280
32281		_basePosition.copy(vector).applyMatrix4(this.bindMatrix);
32282
32283		vector.set(0, 0, 0);
32284
32285		for (let i = 0; i < 4; i++) {
32286
32287			const weight = _skinWeight.getComponent(i);
32288
32289			if (weight !== 0) {
32290
32291				const boneIndex = _skinIndex.getComponent(i);
32292
32293				_matrix4.multiplyMatrices(skeleton.bones[boneIndex].matrixWorld, skeleton.boneInverses[boneIndex]);
32294
32295				vector.addScaledVector(_vector3.copy(_basePosition).applyMatrix4(_matrix4), weight);
32296
32297			}
32298
32299		}
32300
32301		return vector.applyMatrix4(this.bindMatrixInverse);
32302
32303	}
32304
32305	boneTransform(index, vector) { // @deprecated, r151
32306
32307		console.warn('THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.');
32308		return this.applyBoneTransform(index, vector);
32309
32310	}
32311
32312
32313}
32314
32315class Bone extends Object3D {
32316
32317	constructor() {
32318
32319		super();
32320
32321		this.isBone = true;
32322
32323		this.type = 'Bone';
32324
32325	}
32326
32327}
32328
32329class DataTexture extends Texture {
32330
32331	constructor(data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace) {
32332
32333		super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace);
32334
32335		this.isDataTexture = true;
32336
32337		this.image = { data: data, width: width, height: height };
32338
32339		this.generateMipmaps = false;
32340		this.flipY = false;
32341		this.unpackAlignment = 1;
32342
32343	}
32344
32345}
32346
32347const _offsetMatrix = /*@__PURE__*/ new Matrix4();
32348const _identityMatrix$1 = /*@__PURE__*/ new Matrix4();
32349
32350class Skeleton {
32351
32352	constructor(bones = [], boneInverses = []) {
32353
32354		this.uuid = generateUUID();
32355
32356		this.bones = bones.slice(0);
32357		this.boneInverses = boneInverses;
32358		this.boneMatrices = null;
32359
32360		this.boneTexture = null;
32361
32362		this.init();
32363
32364	}
32365
32366	init() {
32367
32368		const bones = this.bones;
32369		const boneInverses = this.boneInverses;
32370
32371		this.boneMatrices = new Float32Array(bones.length * 16);
32372
32373		// calculate inverse bone matrices if necessary
32374
32375		if (boneInverses.length === 0) {
32376
32377			this.calculateInverses();
32378
32379		} else {
32380
32381			// handle special case
32382
32383			if (bones.length !== boneInverses.length) {
32384
32385				console.warn('THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.');
32386
32387				this.boneInverses = [];
32388
32389				for (let i = 0, il = this.bones.length; i < il; i++) {
32390
32391					this.boneInverses.push(new Matrix4());
32392
32393				}
32394
32395			}
32396
32397		}
32398
32399	}
32400
32401	calculateInverses() {
32402
32403		this.boneInverses.length = 0;
32404
32405		for (let i = 0, il = this.bones.length; i < il; i++) {
32406
32407			const inverse = new Matrix4();
32408
32409			if (this.bones[i]) {
32410
32411				inverse.copy(this.bones[i].matrixWorld).invert();
32412
32413			}
32414
32415			this.boneInverses.push(inverse);
32416
32417		}
32418
32419	}
32420
32421	pose() {
32422
32423		// recover the bind-time world matrices
32424
32425		for (let i = 0, il = this.bones.length; i < il; i++) {
32426
32427			const bone = this.bones[i];
32428
32429			if (bone) {
32430
32431				bone.matrixWorld.copy(this.boneInverses[i]).invert();
32432
32433			}
32434
32435		}
32436
32437		// compute the local matrices, positions, rotations and scales
32438
32439		for (let i = 0, il = this.bones.length; i < il; i++) {
32440
32441			const bone = this.bones[i];
32442
32443			if (bone) {
32444
32445				if (bone.parent && bone.parent.isBone) {
32446
32447					bone.matrix.copy(bone.parent.matrixWorld).invert();
32448					bone.matrix.multiply(bone.matrixWorld);
32449
32450				} else {
32451
32452					bone.matrix.copy(bone.matrixWorld);
32453
32454				}
32455
32456				bone.matrix.decompose(bone.position, bone.quaternion, bone.scale);
32457
32458			}
32459
32460		}
32461
32462	}
32463
32464	update() {
32465
32466		const bones = this.bones;
32467		const boneInverses = this.boneInverses;
32468		const boneMatrices = this.boneMatrices;
32469		const boneTexture = this.boneTexture;
32470
32471		// flatten bone matrices to array
32472
32473		for (let i = 0, il = bones.length; i < il; i++) {
32474
32475			// compute the offset between the current and the original transform
32476
32477			const matrix = bones[i] ? bones[i].matrixWorld : _identityMatrix$1;
32478
32479			_offsetMatrix.multiplyMatrices(matrix, boneInverses[i]);
32480			_offsetMatrix.toArray(boneMatrices, i * 16);
32481
32482		}
32483
32484		if (boneTexture !== null) {
32485
32486			boneTexture.needsUpdate = true;
32487
32488		}
32489
32490	}
32491
32492	clone() {
32493
32494		return new Skeleton(this.bones, this.boneInverses);
32495
32496	}
32497
32498	computeBoneTexture() {
32499
32500		// layout (1 matrix = 4 pixels)
32501		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
32502		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
32503		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
32504		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
32505		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
32506
32507		let size = Math.sqrt(this.bones.length * 4); // 4 pixels needed for 1 matrix
32508		size = Math.ceil(size / 4) * 4;
32509		size = Math.max(size, 4);
32510
32511		const boneMatrices = new Float32Array(size * size * 4); // 4 floats per RGBA pixel
32512		boneMatrices.set(this.boneMatrices); // copy current values
32513
32514		const boneTexture = new DataTexture(boneMatrices, size, size, RGBAFormat, FloatType);
32515		boneTexture.needsUpdate = true;
32516
32517		this.boneMatrices = boneMatrices;
32518		this.boneTexture = boneTexture;
32519
32520		return this;
32521
32522	}
32523
32524	getBoneByName(name) {
32525
32526		for (let i = 0, il = this.bones.length; i < il; i++) {
32527
32528			const bone = this.bones[i];
32529
32530			if (bone.name === name) {
32531
32532				return bone;
32533
32534			}
32535
32536		}
32537
32538		return undefined;
32539
32540	}
32541
32542	dispose() {
32543
32544		if (this.boneTexture !== null) {
32545
32546			this.boneTexture.dispose();
32547
32548			this.boneTexture = null;
32549
32550		}
32551
32552	}
32553
32554	fromJSON(json, bones) {
32555
32556		this.uuid = json.uuid;
32557
32558		for (let i = 0, l = json.bones.length; i < l; i++) {
32559
32560			const uuid = json.bones[i];
32561			let bone = bones[uuid];
32562
32563			if (bone === undefined) {
32564
32565				console.warn('THREE.Skeleton: No bone found with UUID:', uuid);
32566				bone = new Bone();
32567
32568			}
32569
32570			this.bones.push(bone);
32571			this.boneInverses.push(new Matrix4().fromArray(json.boneInverses[i]));
32572
32573		}
32574
32575		this.init();
32576
32577		return this;
32578
32579	}
32580
32581	toJSON() {
32582
32583		const data = {
32584			metadata: {
32585				version: 4.6,
32586				type: 'Skeleton',
32587				generator: 'Skeleton.toJSON'
32588			},
32589			bones: [],
32590			boneInverses: []
32591		};
32592
32593		data.uuid = this.uuid;
32594
32595		const bones = this.bones;
32596		const boneInverses = this.boneInverses;
32597
32598		for (let i = 0, l = bones.length; i < l; i++) {
32599
32600			const bone = bones[i];
32601			data.bones.push(bone.uuid);
32602
32603			const boneInverse = boneInverses[i];
32604			data.boneInverses.push(boneInverse.toArray());
32605
32606		}
32607
32608		return data;
32609
32610	}
32611
32612}
32613
32614class InstancedBufferAttribute extends BufferAttribute {
32615
32616	constructor(array, itemSize, normalized, meshPerAttribute = 1) {
32617
32618		super(array, itemSize, normalized);
32619
32620		this.isInstancedBufferAttribute = true;
32621
32622		this.meshPerAttribute = meshPerAttribute;
32623
32624	}
32625
32626	copy(source) {
32627
32628		super.copy(source);
32629
32630		this.meshPerAttribute = source.meshPerAttribute;
32631
32632		return this;
32633
32634	}
32635
32636	toJSON() {
32637
32638		const data = super.toJSON();
32639
32640		data.meshPerAttribute = this.meshPerAttribute;
32641
32642		data.isInstancedBufferAttribute = true;
32643
32644		return data;
32645
32646	}
32647
32648}
32649
32650const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
32651const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
32652
32653const _instanceIntersects = [];
32654
32655const _box3 = /*@__PURE__*/ new Box3();
32656const _identity = /*@__PURE__*/ new Matrix4();
32657const _mesh$1 = /*@__PURE__*/ new Mesh();
32658const _sphere$3 = /*@__PURE__*/ new Sphere();
32659
32660class InstancedMesh extends Mesh {
32661
32662	constructor(geometry, material, count) {
32663
32664		super(geometry, material);
32665
32666		this.isInstancedMesh = true;
32667
32668		this.instanceMatrix = new InstancedBufferAttribute(new Float32Array(count * 16), 16);
32669		this.instanceColor = null;
32670
32671		this.count = count;
32672
32673		this.boundingBox = null;
32674		this.boundingSphere = null;
32675
32676		for (let i = 0; i < count; i++) {
32677
32678			this.setMatrixAt(i, _identity);
32679
32680		}
32681
32682	}
32683
32684	computeBoundingBox() {
32685
32686		const geometry = this.geometry;
32687		const count = this.count;
32688
32689		if (this.boundingBox === null) {
32690
32691			this.boundingBox = new Box3();
32692
32693		}
32694
32695		if (geometry.boundingBox === null) {
32696
32697			geometry.computeBoundingBox();
32698
32699		}
32700
32701		this.boundingBox.makeEmpty();
32702
32703		for (let i = 0; i < count; i++) {
32704
32705			this.getMatrixAt(i, _instanceLocalMatrix);
32706
32707			_box3.copy(geometry.boundingBox).applyMatrix4(_instanceLocalMatrix);
32708
32709			this.boundingBox.union(_box3);
32710
32711		}
32712
32713	}
32714
32715	computeBoundingSphere() {
32716
32717		const geometry = this.geometry;
32718		const count = this.count;
32719
32720		if (this.boundingSphere === null) {
32721
32722			this.boundingSphere = new Sphere();
32723
32724		}
32725
32726		if (geometry.boundingSphere === null) {
32727
32728			geometry.computeBoundingSphere();
32729
32730		}
32731
32732		this.boundingSphere.makeEmpty();
32733
32734		for (let i = 0; i < count; i++) {
32735
32736			this.getMatrixAt(i, _instanceLocalMatrix);
32737
32738			_sphere$3.copy(geometry.boundingSphere).applyMatrix4(_instanceLocalMatrix);
32739
32740			this.boundingSphere.union(_sphere$3);
32741
32742		}
32743
32744	}
32745
32746	copy(source, recursive) {
32747
32748		super.copy(source, recursive);
32749
32750		this.instanceMatrix.copy(source.instanceMatrix);
32751
32752		if (source.instanceColor !== null) this.instanceColor = source.instanceColor.clone();
32753
32754		this.count = source.count;
32755
32756		if (source.boundingBox !== null) this.boundingBox = source.boundingBox.clone();
32757		if (source.boundingSphere !== null) this.boundingSphere = source.boundingSphere.clone();
32758
32759		return this;
32760
32761	}
32762
32763	getColorAt(index, color) {
32764
32765		color.fromArray(this.instanceColor.array, index * 3);
32766
32767	}
32768
32769	getMatrixAt(index, matrix) {
32770
32771		matrix.fromArray(this.instanceMatrix.array, index * 16);
32772
32773	}
32774
32775	raycast(raycaster, intersects) {
32776
32777		const matrixWorld = this.matrixWorld;
32778		const raycastTimes = this.count;
32779
32780		_mesh$1.geometry = this.geometry;
32781		_mesh$1.material = this.material;
32782
32783		if (_mesh$1.material === undefined) return;
32784
32785		// test with bounding sphere first
32786
32787		if (this.boundingSphere === null) this.computeBoundingSphere();
32788
32789		_sphere$3.copy(this.boundingSphere);
32790		_sphere$3.applyMatrix4(matrixWorld);
32791
32792		if (raycaster.ray.intersectsSphere(_sphere$3) === false) return;
32793
32794		// now test each instance
32795
32796		for (let instanceId = 0; instanceId < raycastTimes; instanceId++) {
32797
32798			// calculate the world matrix for each instance
32799
32800			this.getMatrixAt(instanceId, _instanceLocalMatrix);
32801
32802			_instanceWorldMatrix.multiplyMatrices(matrixWorld, _instanceLocalMatrix);
32803
32804			// the mesh represents this single instance
32805
32806			_mesh$1.matrixWorld = _instanceWorldMatrix;
32807
32808			_mesh$1.raycast(raycaster, _instanceIntersects);
32809
32810			// process the result of raycast
32811
32812			for (let i = 0, l = _instanceIntersects.length; i < l; i++) {
32813
32814				const intersect = _instanceIntersects[i];
32815				intersect.instanceId = instanceId;
32816				intersect.object = this;
32817				intersects.push(intersect);
32818
32819			}
32820
32821			_instanceIntersects.length = 0;
32822
32823		}
32824
32825	}
32826
32827	setColorAt(index, color) {
32828
32829		if (this.instanceColor === null) {
32830
32831			this.instanceColor = new InstancedBufferAttribute(new Float32Array(this.instanceMatrix.count * 3), 3);
32832
32833		}
32834
32835		color.toArray(this.instanceColor.array, index * 3);
32836
32837	}
32838
32839	setMatrixAt(index, matrix) {
32840
32841		matrix.toArray(this.instanceMatrix.array, index * 16);
32842
32843	}
32844
32845	updateMorphTargets() {
32846
32847	}
32848
32849	dispose() {
32850
32851		this.dispatchEvent({ type: 'dispose' });
32852
32853	}
32854
32855}
32856
32857function sortOpaque(a, b) {
32858
32859	return a.z - b.z;
32860
32861}
32862
32863function sortTransparent(a, b) {
32864
32865	return b.z - a.z;
32866
32867}
32868
32869class MultiDrawRenderList {
32870
32871	constructor() {
32872
32873		this.index = 0;
32874		this.pool = [];
32875		this.list = [];
32876
32877	}
32878
32879	push(drawRange, z) {
32880
32881		const pool = this.pool;
32882		const list = this.list;
32883		if (this.index >= pool.length) {
32884
32885			pool.push({
32886
32887				start: - 1,
32888				count: - 1,
32889				z: - 1,
32890
32891			});
32892
32893		}
32894
32895		const item = pool[this.index];
32896		list.push(item);
32897		this.index++;
32898
32899		item.start = drawRange.start;
32900		item.count = drawRange.count;
32901		item.z = z;
32902
32903	}
32904
32905	reset() {
32906
32907		this.list.length = 0;
32908		this.index = 0;
32909
32910	}
32911
32912}
32913
32914const ID_ATTR_NAME = 'batchId';
32915const _matrix = /*@__PURE__*/ new Matrix4();
32916const _invMatrixWorld = /*@__PURE__*/ new Matrix4();
32917const _identityMatrix = /*@__PURE__*/ new Matrix4();
32918const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4();
32919const _frustum = /*@__PURE__*/ new Frustum();
32920const _box$1 = /*@__PURE__*/ new Box3();
32921const _sphere$2 = /*@__PURE__*/ new Sphere();
32922const _vector$5 = /*@__PURE__*/ new Vector3();
32923const _renderList = /*@__PURE__*/ new MultiDrawRenderList();
32924const _mesh = /*@__PURE__*/ new Mesh();
32925const _batchIntersects = [];
32926
32927// @TODO: SkinnedMesh support?
32928// @TODO: geometry.groups support?
32929// @TODO: geometry.drawRange support?
32930// @TODO: geometry.morphAttributes support?
32931// @TODO: Support uniform parameter per geometry
32932// @TODO: Add an "optimize" function to pack geometry and remove data gaps
32933
32934// copies data from attribute "src" into "target" starting at "targetOffset"
32935function copyAttributeData(src, target, targetOffset = 0) {
32936
32937	const itemSize = target.itemSize;
32938	if (src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor) {
32939
32940		// use the component getters and setters if the array data cannot
32941		// be copied directly
32942		const vertexCount = src.count;
32943		for (let i = 0; i < vertexCount; i++) {
32944
32945			for (let c = 0; c < itemSize; c++) {
32946
32947				target.setComponent(i + targetOffset, c, src.getComponent(i, c));
32948
32949			}
32950
32951		}
32952
32953	} else {
32954
32955		// faster copy approach using typed array set function
32956		target.array.set(src.array, targetOffset * itemSize);
32957
32958	}
32959
32960	target.needsUpdate = true;
32961
32962}
32963
32964class BatchedMesh extends Mesh {
32965
32966	get maxGeometryCount() {
32967
32968		return this._maxGeometryCount;
32969
32970	}
32971
32972	constructor(maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material) {
32973
32974		super(new BufferGeometry(), material);
32975
32976		this.isBatchedMesh = true;
32977		this.perObjectFrustumCulled = true;
32978		this.sortObjects = true;
32979		this.boundingBox = null;
32980		this.boundingSphere = null;
32981		this.customSort = null;
32982
32983		this._drawRanges = [];
32984		this._reservedRanges = [];
32985
32986		this._visibility = [];
32987		this._active = [];
32988		this._bounds = [];
32989
32990		this._maxGeometryCount = maxGeometryCount;
32991		this._maxVertexCount = maxVertexCount;
32992		this._maxIndexCount = maxIndexCount;
32993
32994		this._geometryInitialized = false;
32995		this._geometryCount = 0;
32996		this._multiDrawCounts = new Int32Array(maxGeometryCount);
32997		this._multiDrawStarts = new Int32Array(maxGeometryCount);
32998		this._multiDrawCount = 0;
32999		this._visibilityChanged = true;
33000
33001		// Local matrix per geometry by using data texture
33002		this._matricesTexture = null;
33003
33004		this._initMatricesTexture();
33005
33006	}
33007
33008	_initMatricesTexture() {
33009
33010		// layout (1 matrix = 4 pixels)
33011		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
33012		//  with  8x8  pixel texture max   16 matrices * 4 pixels =  (8 * 8)
33013		//       16x16 pixel texture max   64 matrices * 4 pixels = (16 * 16)
33014		//       32x32 pixel texture max  256 matrices * 4 pixels = (32 * 32)
33015		//       64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64)
33016
33017		let size = Math.sqrt(this._maxGeometryCount * 4); // 4 pixels needed for 1 matrix
33018		size = Math.ceil(size / 4) * 4;
33019		size = Math.max(size, 4);
33020
33021		const matricesArray = new Float32Array(size * size * 4); // 4 floats per RGBA pixel
33022		const matricesTexture = new DataTexture(matricesArray, size, size, RGBAFormat, FloatType);
33023
33024		this._matricesTexture = matricesTexture;
33025
33026	}
33027
33028	_initializeGeometry(reference) {
33029
33030		const geometry = this.geometry;
33031		const maxVertexCount = this._maxVertexCount;
33032		const maxGeometryCount = this._maxGeometryCount;
33033		const maxIndexCount = this._maxIndexCount;
33034		if (this._geometryInitialized === false) {
33035
33036			for (const attributeName in reference.attributes) {
33037
33038				const srcAttribute = reference.getAttribute(attributeName);
33039				const { array, itemSize, normalized } = srcAttribute;
33040
33041				const dstArray = new array.constructor(maxVertexCount * itemSize);
33042				const dstAttribute = new srcAttribute.constructor(dstArray, itemSize, normalized);
33043				dstAttribute.setUsage(srcAttribute.usage);
33044
33045				geometry.setAttribute(attributeName, dstAttribute);
33046
33047			}
33048
33049			if (reference.getIndex() !== null) {
33050
33051				const indexArray = maxVertexCount > 65536
33052					? new Uint32Array(maxIndexCount)
33053					: new Uint16Array(maxIndexCount);
33054
33055				geometry.setIndex(new BufferAttribute(indexArray, 1));
33056
33057			}
33058
33059			const idArray = maxGeometryCount > 65536
33060				? new Uint32Array(maxVertexCount)
33061				: new Uint16Array(maxVertexCount);
33062			geometry.setAttribute(ID_ATTR_NAME, new BufferAttribute(idArray, 1));
33063
33064			this._geometryInitialized = true;
33065
33066		}
33067
33068	}
33069
33070	// Make sure the geometry is compatible with the existing combined geometry atributes
33071	_validateGeometry(geometry) {
33072
33073		// check that the geometry doesn't have a version of our reserved id attribute
33074		if (geometry.getAttribute(ID_ATTR_NAME)) {
33075
33076			throw new Error(`BatchedMesh: Geometry cannot use attribute "${ID_ATTR_NAME}"`);
33077
33078		}
33079
33080		// check to ensure the geometries are using consistent attributes and indices
33081		const batchGeometry = this.geometry;
33082		if (Boolean(geometry.getIndex()) !== Boolean(batchGeometry.getIndex())) {
33083
33084			throw new Error('BatchedMesh: All geometries must consistently have "index".');
33085
33086		}
33087
33088		for (const attributeName in batchGeometry.attributes) {
33089
33090			if (attributeName === ID_ATTR_NAME) {
33091
33092				continue;
33093
33094			}
33095
33096			if (!geometry.hasAttribute(attributeName)) {
33097
33098				throw new Error(`BatchedMesh: Added geometry missing "${attributeName}". All geometries must have consistent attributes.`);
33099
33100			}
33101
33102			const srcAttribute = geometry.getAttribute(attributeName);
33103			const dstAttribute = batchGeometry.getAttribute(attributeName);
33104			if (srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized) {
33105
33106				throw new Error('BatchedMesh: All attributes must have a consistent itemSize and normalized value.');
33107
33108			}
33109
33110		}
33111
33112	}
33113
33114	setCustomSort(func) {
33115
33116		this.customSort = func;
33117		return this;
33118
33119	}
33120
33121	computeBoundingBox() {
33122
33123		if (this.boundingBox === null) {
33124
33125			this.boundingBox = new Box3();
33126
33127		}
33128
33129		const geometryCount = this._geometryCount;
33130		const boundingBox = this.boundingBox;
33131		const active = this._active;
33132
33133		boundingBox.makeEmpty();
33134		for (let i = 0; i < geometryCount; i++) {
33135
33136			if (active[i] === false) continue;
33137
33138			this.getMatrixAt(i, _matrix);
33139			this.getBoundingBoxAt(i, _box$1).applyMatrix4(_matrix);
33140			boundingBox.union(_box$1);
33141
33142		}
33143
33144	}
33145
33146	computeBoundingSphere() {
33147
33148		if (this.boundingSphere === null) {
33149
33150			this.boundingSphere = new Sphere();
33151
33152		}
33153
33154		const geometryCount = this._geometryCount;
33155		const boundingSphere = this.boundingSphere;
33156		const active = this._active;
33157
33158		boundingSphere.makeEmpty();
33159		for (let i = 0; i < geometryCount; i++) {
33160
33161			if (active[i] === false) continue;
33162
33163			this.getMatrixAt(i, _matrix);
33164			this.getBoundingSphereAt(i, _sphere$2).applyMatrix4(_matrix);
33165			boundingSphere.union(_sphere$2);
33166
33167		}
33168
33169	}
33170
33171	addGeometry(geometry, vertexCount = - 1, indexCount = - 1) {
33172
33173		this._initializeGeometry(geometry);
33174
33175		this._validateGeometry(geometry);
33176
33177		// ensure we're not over geometry
33178		if (this._geometryCount >= this._maxGeometryCount) {
33179
33180			throw new Error('BatchedMesh: Maximum geometry count reached.');
33181
33182		}
33183
33184		// get the necessary range fo the geometry
33185		const reservedRange = {
33186			vertexStart: - 1,
33187			vertexCount: - 1,
33188			indexStart: - 1,
33189			indexCount: - 1,
33190		};
33191
33192		let lastRange = null;
33193		const reservedRanges = this._reservedRanges;
33194		const drawRanges = this._drawRanges;
33195		const bounds = this._bounds;
33196		if (this._geometryCount !== 0) {
33197
33198			lastRange = reservedRanges[reservedRanges.length - 1];
33199
33200		}
33201
33202		if (vertexCount === - 1) {
33203
33204			reservedRange.vertexCount = geometry.getAttribute('position').count;
33205
33206		} else {
33207
33208			reservedRange.vertexCount = vertexCount;
33209
33210		}
33211
33212		if (lastRange === null) {
33213
33214			reservedRange.vertexStart = 0;
33215
33216		} else {
33217
33218			reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount;
33219
33220		}
33221
33222		const index = geometry.getIndex();
33223		const hasIndex = index !== null;
33224		if (hasIndex) {
33225
33226			if (indexCount === - 1) {
33227
33228				reservedRange.indexCount = index.count;
33229
33230			} else {
33231
33232				reservedRange.indexCount = indexCount;
33233
33234			}
33235
33236			if (lastRange === null) {
33237
33238				reservedRange.indexStart = 0;
33239
33240			} else {
33241
33242				reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount;
33243
33244			}
33245
33246		}
33247
33248		if (
33249			reservedRange.indexStart !== - 1 &&
33250			reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount ||
33251			reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount
33252		) {
33253
33254			throw new Error('BatchedMesh: Reserved space request exceeds the maximum buffer size.');
33255
33256		}
33257
33258		const visibility = this._visibility;
33259		const active = this._active;
33260		const matricesTexture = this._matricesTexture;
33261		const matricesArray = this._matricesTexture.image.data;
33262
33263		// push new visibility states
33264		visibility.push(true);
33265		active.push(true);
33266
33267		// update id
33268		const geometryId = this._geometryCount;
33269		this._geometryCount++;
33270
33271		// initialize matrix information
33272		_identityMatrix.toArray(matricesArray, geometryId * 16);
33273		matricesTexture.needsUpdate = true;
33274
33275		// add the reserved range and draw range objects
33276		reservedRanges.push(reservedRange);
33277		drawRanges.push({
33278			start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart,
33279			count: - 1
33280		});
33281		bounds.push({
33282			boxInitialized: false,
33283			box: new Box3(),
33284
33285			sphereInitialized: false,
33286			sphere: new Sphere()
33287		});
33288
33289		// set the id for the geometry
33290		const idAttribute = this.geometry.getAttribute(ID_ATTR_NAME);
33291		for (let i = 0; i < reservedRange.vertexCount; i++) {
33292
33293			idAttribute.setX(reservedRange.vertexStart + i, geometryId);
33294
33295		}
33296
33297		idAttribute.needsUpdate = true;
33298
33299		// update the geometry
33300		this.setGeometryAt(geometryId, geometry);
33301
33302		return geometryId;
33303
33304	}
33305
33306	setGeometryAt(id, geometry) {
33307
33308		if (id >= this._geometryCount) {
33309
33310			throw new Error('BatchedMesh: Maximum geometry count reached.');
33311
33312		}
33313
33314		this._validateGeometry(geometry);
33315
33316		const batchGeometry = this.geometry;
33317		const hasIndex = batchGeometry.getIndex() !== null;
33318		const dstIndex = batchGeometry.getIndex();
33319		const srcIndex = geometry.getIndex();
33320		const reservedRange = this._reservedRanges[id];
33321		if (
33322			hasIndex &&
33323			srcIndex.count > reservedRange.indexCount ||
33324			geometry.attributes.position.count > reservedRange.vertexCount
33325		) {
33326
33327			throw new Error('BatchedMesh: Reserved space not large enough for provided geometry.');
33328
33329		}
33330
33331		// copy geometry over
33332		const vertexStart = reservedRange.vertexStart;
33333		const vertexCount = reservedRange.vertexCount;
33334		for (const attributeName in batchGeometry.attributes) {
33335
33336			if (attributeName === ID_ATTR_NAME) {
33337
33338				continue;
33339
33340			}
33341
33342			// copy attribute data
33343			const srcAttribute = geometry.getAttribute(attributeName);
33344			const dstAttribute = batchGeometry.getAttribute(attributeName);
33345			copyAttributeData(srcAttribute, dstAttribute, vertexStart);
33346
33347			// fill the rest in with zeroes
33348			const itemSize = srcAttribute.itemSize;
33349			for (let i = srcAttribute.count, l = vertexCount; i < l; i++) {
33350
33351				const index = vertexStart + i;
33352				for (let c = 0; c < itemSize; c++) {
33353
33354					dstAttribute.setComponent(index, c, 0);
33355
33356				}
33357
33358			}
33359
33360			dstAttribute.needsUpdate = true;
33361
33362		}
33363
33364		// copy index
33365		if (hasIndex) {
33366
33367			const indexStart = reservedRange.indexStart;
33368
33369			// copy index data over
33370			for (let i = 0; i < srcIndex.count; i++) {
33371
33372				dstIndex.setX(indexStart + i, vertexStart + srcIndex.getX(i));
33373
33374			}
33375
33376			// fill the rest in with zeroes
33377			for (let i = srcIndex.count, l = reservedRange.indexCount; i < l; i++) {
33378
33379				dstIndex.setX(indexStart + i, vertexStart);
33380
33381			}
33382
33383			dstIndex.needsUpdate = true;
33384
33385		}
33386
33387		// store the bounding boxes
33388		const bound = this._bounds[id];
33389		if (geometry.boundingBox !== null) {
33390
33391			bound.box.copy(geometry.boundingBox);
33392			bound.boxInitialized = true;
33393
33394		} else {
33395
33396			bound.boxInitialized = false;
33397
33398		}
33399
33400		if (geometry.boundingSphere !== null) {
33401
33402			bound.sphere.copy(geometry.boundingSphere);
33403			bound.sphereInitialized = true;
33404
33405		} else {
33406
33407			bound.sphereInitialized = false;
33408
33409		}
33410
33411		// set drawRange count
33412		const drawRange = this._drawRanges[id];
33413		const posAttr = geometry.getAttribute('position');
33414		drawRange.count = hasIndex ? srcIndex.count : posAttr.count;
33415		this._visibilityChanged = true;
33416
33417		return id;
33418
33419	}
33420
33421	deleteGeometry(geometryId) {
33422
33423		// Note: User needs to call optimize() afterward to pack the data.
33424
33425		const active = this._active;
33426		if (geometryId >= active.length || active[geometryId] === false) {
33427
33428			return this;
33429
33430		}
33431
33432		active[geometryId] = false;
33433		this._visibilityChanged = true;
33434
33435		return this;
33436
33437	}
33438
33439	// get bounding box and compute it if it doesn't exist
33440	getBoundingBoxAt(id, target) {
33441
33442		const active = this._active;
33443		if (active[id] === false) {
33444
33445			return this;
33446
33447		}
33448
33449		// compute bounding box
33450		const bound = this._bounds[id];
33451		const box = bound.box;
33452		const geometry = this.geometry;
33453		if (bound.boxInitialized === false) {
33454
33455			box.makeEmpty();
33456
33457			const index = geometry.index;
33458			const position = geometry.attributes.position;
33459			const drawRange = this._drawRanges[id];
33460			for (let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i++) {
33461
33462				let iv = i;
33463				if (index) {
33464
33465					iv = index.getX(iv);
33466
33467				}
33468
33469				box.expandByPoint(_vector$5.fromBufferAttribute(position, iv));
33470
33471			}
33472
33473			bound.boxInitialized = true;
33474
33475		}
33476
33477		target.copy(box);
33478		return target;
33479
33480	}
33481
33482	// get bounding sphere and compute it if it doesn't exist
33483	getBoundingSphereAt(id, target) {
33484
33485		const active = this._active;
33486		if (active[id] === false) {
33487
33488			return this;
33489
33490		}
33491
33492		// compute bounding sphere
33493		const bound = this._bounds[id];
33494		const sphere = bound.sphere;
33495		const geometry = this.geometry;
33496		if (bound.sphereInitialized === false) {
33497
33498			sphere.makeEmpty();
33499
33500			this.getBoundingBoxAt(id, _box$1);
33501			_box$1.getCenter(sphere.center);
33502
33503			const index = geometry.index;
33504			const position = geometry.attributes.position;
33505			const drawRange = this._drawRanges[id];
33506
33507			let maxRadiusSq = 0;
33508			for (let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i++) {
33509
33510				let iv = i;
33511				if (index) {
33512
33513					iv = index.getX(iv);
33514
33515				}
33516
33517				_vector$5.fromBufferAttribute(position, iv);
33518				maxRadiusSq = Math.max(maxRadiusSq, sphere.center.distanceToSquared(_vector$5));
33519
33520			}
33521
33522			sphere.radius = Math.sqrt(maxRadiusSq);
33523			bound.sphereInitialized = true;
33524
33525		}
33526
33527		target.copy(sphere);
33528		return target;
33529
33530	}
33531
33532	setMatrixAt(geometryId, matrix) {
33533
33534		// @TODO: Map geometryId to index of the arrays because
33535		//        optimize() can make geometryId mismatch the index
33536
33537		const active = this._active;
33538		const matricesTexture = this._matricesTexture;
33539		const matricesArray = this._matricesTexture.image.data;
33540		const geometryCount = this._geometryCount;
33541		if (geometryId >= geometryCount || active[geometryId] === false) {
33542
33543			return this;
33544
33545		}
33546
33547		matrix.toArray(matricesArray, geometryId * 16);
33548		matricesTexture.needsUpdate = true;
33549
33550		return this;
33551
33552	}
33553
33554	getMatrixAt(geometryId, matrix) {
33555
33556		const active = this._active;
33557		const matricesArray = this._matricesTexture.image.data;
33558		const geometryCount = this._geometryCount;
33559		if (geometryId >= geometryCount || active[geometryId] === false) {
33560
33561			return null;
33562
33563		}
33564
33565		return matrix.fromArray(matricesArray, geometryId * 16);
33566
33567	}
33568
33569	setVisibleAt(geometryId, value) {
33570
33571		const visibility = this._visibility;
33572		const active = this._active;
33573		const geometryCount = this._geometryCount;
33574
33575		// if the geometry is out of range, not active, or visibility state
33576		// does not change then return early
33577		if (
33578			geometryId >= geometryCount ||
33579			active[geometryId] === false ||
33580			visibility[geometryId] === value
33581		) {
33582
33583			return this;
33584
33585		}
33586
33587		visibility[geometryId] = value;
33588		this._visibilityChanged = true;
33589
33590		return this;
33591
33592	}
33593
33594	getVisibleAt(geometryId) {
33595
33596		const visibility = this._visibility;
33597		const active = this._active;
33598		const geometryCount = this._geometryCount;
33599
33600		// return early if the geometry is out of range or not active
33601		if (geometryId >= geometryCount || active[geometryId] === false) {
33602
33603			return false;
33604
33605		}
33606
33607		return visibility[geometryId];
33608
33609	}
33610
33611	raycast(raycaster, intersects) {
33612
33613		const visibility = this._visibility;
33614		const active = this._active;
33615		const drawRanges = this._drawRanges;
33616		const geometryCount = this._geometryCount;
33617		const matrixWorld = this.matrixWorld;
33618		const batchGeometry = this.geometry;
33619
33620		// iterate over each geometry
33621		_mesh.material = this.material;
33622		_mesh.geometry.index = batchGeometry.index;
33623		_mesh.geometry.attributes = batchGeometry.attributes;
33624		if (_mesh.geometry.boundingBox === null) {
33625
33626			_mesh.geometry.boundingBox = new Box3();
33627
33628		}
33629
33630		if (_mesh.geometry.boundingSphere === null) {
33631
33632			_mesh.geometry.boundingSphere = new Sphere();
33633
33634		}
33635
33636		for (let i = 0; i < geometryCount; i++) {
33637
33638			if (!visibility[i] || !active[i]) {
33639
33640				continue;
33641
33642			}
33643
33644			const drawRange = drawRanges[i];
33645			_mesh.geometry.setDrawRange(drawRange.start, drawRange.count);
33646
33647			// ge the intersects
33648			this.getMatrixAt(i, _mesh.matrixWorld).premultiply(matrixWorld);
33649			this.getBoundingBoxAt(i, _mesh.geometry.boundingBox);
33650			this.getBoundingSphereAt(i, _mesh.geometry.boundingSphere);
33651			_mesh.raycast(raycaster, _batchIntersects);
33652
33653			// add batch id to the intersects
33654			for (let j = 0, l = _batchIntersects.length; j < l; j++) {
33655
33656				const intersect = _batchIntersects[j];
33657				intersect.object = this;
33658				intersect.batchId = i;
33659				intersects.push(intersect);
33660
33661			}
33662
33663			_batchIntersects.length = 0;
33664
33665		}
33666
33667		_mesh.material = null;
33668		_mesh.geometry.index = null;
33669		_mesh.geometry.attributes = {};
33670		_mesh.geometry.setDrawRange(0, Infinity);
33671
33672	}
33673
33674	copy(source) {
33675
33676		super.copy(source);
33677
33678		this.geometry = source.geometry.clone();
33679		this.perObjectFrustumCulled = source.perObjectFrustumCulled;
33680		this.sortObjects = source.sortObjects;
33681		this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
33682		this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
33683
33684		this._drawRanges = source._drawRanges.map(range => ({ ...range }));
33685		this._reservedRanges = source._reservedRanges.map(range => ({ ...range }));
33686
33687		this._visibility = source._visibility.slice();
33688		this._active = source._active.slice();
33689		this._bounds = source._bounds.map(bound => ({
33690			boxInitialized: bound.boxInitialized,
33691			box: bound.box.clone(),
33692
33693			sphereInitialized: bound.sphereInitialized,
33694			sphere: bound.sphere.clone()
33695		}));
33696
33697		this._maxGeometryCount = source._maxGeometryCount;
33698		this._maxVertexCount = source._maxVertexCount;
33699		this._maxIndexCount = source._maxIndexCount;
33700
33701		this._geometryInitialized = source._geometryInitialized;
33702		this._geometryCount = source._geometryCount;
33703		this._multiDrawCounts = source._multiDrawCounts.slice();
33704		this._multiDrawStarts = source._multiDrawStarts.slice();
33705
33706		this._matricesTexture = source._matricesTexture.clone();
33707		this._matricesTexture.image.data = this._matricesTexture.image.slice();
33708
33709		return this;
33710
33711	}
33712
33713	dispose() {
33714
33715		// Assuming the geometry is not shared with other meshes
33716		this.geometry.dispose();
33717
33718		this._matricesTexture.dispose();
33719		this._matricesTexture = null;
33720		return this;
33721
33722	}
33723
33724	onBeforeRender(renderer, scene, camera, geometry, material/*, _group*/) {
33725
33726		// if visibility has not changed and frustum culling and object sorting is not required
33727		// then skip iterating over all items
33728		if (!this._visibilityChanged && !this.perObjectFrustumCulled && !this.sortObjects) {
33729
33730			return;
33731
33732		}
33733
33734		// the indexed version of the multi draw function requires specifying the start
33735		// offset in bytes.
33736		const index = geometry.getIndex();
33737		const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
33738
33739		const visibility = this._visibility;
33740		const multiDrawStarts = this._multiDrawStarts;
33741		const multiDrawCounts = this._multiDrawCounts;
33742		const drawRanges = this._drawRanges;
33743		const perObjectFrustumCulled = this.perObjectFrustumCulled;
33744
33745		// prepare the frustum in the local frame
33746		if (perObjectFrustumCulled) {
33747
33748			_projScreenMatrix$2
33749				.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)
33750				.multiply(this.matrixWorld);
33751			_frustum.setFromProjectionMatrix(
33752				_projScreenMatrix$2,
33753				renderer.isWebGPURenderer ? WebGPUCoordinateSystem : WebGLCoordinateSystem
33754			);
33755
33756		}
33757
33758		let count = 0;
33759		if (this.sortObjects) {
33760
33761			// get the camera position in the local frame
33762			_invMatrixWorld.copy(this.matrixWorld).invert();
33763			_vector$5.setFromMatrixPosition(camera.matrixWorld).applyMatrix4(_invMatrixWorld);
33764
33765			for (let i = 0, l = visibility.length; i < l; i++) {
33766
33767				if (visibility[i]) {
33768
33769					// get the bounds in world space
33770					this.getMatrixAt(i, _matrix);
33771					this.getBoundingSphereAt(i, _sphere$2).applyMatrix4(_matrix);
33772
33773					// determine whether the batched geometry is within the frustum
33774					let culled = false;
33775					if (perObjectFrustumCulled) {
33776
33777						culled = !_frustum.intersectsSphere(_sphere$2);
33778
33779					}
33780
33781					if (!culled) {
33782
33783						// get the distance from camera used for sorting
33784						const z = _vector$5.distanceTo(_sphere$2.center);
33785						_renderList.push(drawRanges[i], z);
33786
33787					}
33788
33789				}
33790
33791			}
33792
33793			// Sort the draw ranges and prep for rendering
33794			const list = _renderList.list;
33795			const customSort = this.customSort;
33796			if (customSort === null) {
33797
33798				list.sort(material.transparent ? sortTransparent : sortOpaque);
33799
33800			} else {
33801
33802				customSort.call(this, list, camera);
33803
33804			}
33805
33806			for (let i = 0, l = list.length; i < l; i++) {
33807
33808				const item = list[i];
33809				multiDrawStarts[count] = item.start * bytesPerElement;
33810				multiDrawCounts[count] = item.count;
33811				count++;
33812
33813			}
33814
33815			_renderList.reset();
33816
33817		} else {
33818
33819			for (let i = 0, l = visibility.length; i < l; i++) {
33820
33821				if (visibility[i]) {
33822
33823					// determine whether the batched geometry is within the frustum
33824					let culled = false;
33825					if (perObjectFrustumCulled) {
33826
33827						// get the bounds in world space
33828						this.getMatrixAt(i, _matrix);
33829						this.getBoundingSphereAt(i, _sphere$2).applyMatrix4(_matrix);
33830						culled = !_frustum.intersectsSphere(_sphere$2);
33831
33832					}
33833
33834					if (!culled) {
33835
33836						const range = drawRanges[i];
33837						multiDrawStarts[count] = range.start * bytesPerElement;
33838						multiDrawCounts[count] = range.count;
33839						count++;
33840
33841					}
33842
33843				}
33844
33845			}
33846
33847		}
33848
33849		this._multiDrawCount = count;
33850		this._visibilityChanged = false;
33851
33852	}
33853
33854	onBeforeShadow(renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */) {
33855
33856		this.onBeforeRender(renderer, null, shadowCamera, geometry, depthMaterial);
33857
33858	}
33859
33860}
33861
33862class LineBasicMaterial extends Material {
33863
33864	constructor(parameters) {
33865
33866		super();
33867
33868		this.isLineBasicMaterial = true;
33869
33870		this.type = 'LineBasicMaterial';
33871
33872		this.color = new Color(0xffffff);
33873
33874		this.map = null;
33875
33876		this.linewidth = 1;
33877		this.linecap = 'round';
33878		this.linejoin = 'round';
33879
33880		this.fog = true;
33881
33882		this.setValues(parameters);
33883
33884	}
33885
33886
33887	copy(source) {
33888
33889		super.copy(source);
33890
33891		this.color.copy(source.color);
33892
33893		this.map = source.map;
33894
33895		this.linewidth = source.linewidth;
33896		this.linecap = source.linecap;
33897		this.linejoin = source.linejoin;
33898
vendor: 5,092 bytes, lines 33899-34095
33899		this.fog = source.fog;
33900
33901		return this;
33902
33903	}
33904
33905}
33906
33907const _start$1 = /*@__PURE__*/ new Vector3();
33908const _end$1 = /*@__PURE__*/ new Vector3();
33909const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4();
33910const _ray$1 = /*@__PURE__*/ new Ray();
33911const _sphere$1 = /*@__PURE__*/ new Sphere();
33912
33913class Line extends Object3D {
33914
33915	constructor(geometry = new BufferGeometry(), material = new LineBasicMaterial()) {
33916
33917		super();
33918
33919		this.isLine = true;
33920
33921		this.type = 'Line';
33922
33923		this.geometry = geometry;
33924		this.material = material;
33925
33926		this.updateMorphTargets();
33927
33928	}
33929
33930	copy(source, recursive) {
33931
33932		super.copy(source, recursive);
33933
33934		this.material = Array.isArray(source.material) ? source.material.slice() : source.material;
33935		this.geometry = source.geometry;
33936
33937		return this;
33938
33939	}
33940
33941	computeLineDistances() {
33942
33943		const geometry = this.geometry;
33944
33945		// we assume non-indexed geometry
33946
33947		if (geometry.index === null) {
33948
33949			const positionAttribute = geometry.attributes.position;
33950			const lineDistances = [0];
33951
33952			for (let i = 1, l = positionAttribute.count; i < l; i++) {
33953
33954				_start$1.fromBufferAttribute(positionAttribute, i - 1);
33955				_end$1.fromBufferAttribute(positionAttribute, i);
33956
33957				lineDistances[i] = lineDistances[i - 1];
33958				lineDistances[i] += _start$1.distanceTo(_end$1);
33959
33960			}
33961
33962			geometry.setAttribute('lineDistance', new Float32BufferAttribute(lineDistances, 1));
33963
33964		} else {
33965
33966			console.warn('THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.');
33967
33968		}
33969
33970		return this;
33971
33972	}
33973
33974	raycast(raycaster, intersects) {
33975
33976		const geometry = this.geometry;
33977		const matrixWorld = this.matrixWorld;
33978		const threshold = raycaster.params.Line.threshold;
33979		const drawRange = geometry.drawRange;
33980
33981		// Checking boundingSphere distance to ray
33982
33983		if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
33984
33985		_sphere$1.copy(geometry.boundingSphere);
33986		_sphere$1.applyMatrix4(matrixWorld);
33987		_sphere$1.radius += threshold;
33988
33989		if (raycaster.ray.intersectsSphere(_sphere$1) === false) return;
33990
33991		//
33992
33993		_inverseMatrix$1.copy(matrixWorld).invert();
33994		_ray$1.copy(raycaster.ray).applyMatrix4(_inverseMatrix$1);
33995
33996		const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
33997		const localThresholdSq = localThreshold * localThreshold;
33998
33999		const vStart = new Vector3();
34000		const vEnd = new Vector3();
34001		const interSegment = new Vector3();
34002		const interRay = new Vector3();
34003		const step = this.isLineSegments ? 2 : 1;
34004
34005		const index = geometry.index;
34006		const attributes = geometry.attributes;
34007		const positionAttribute = attributes.position;
34008
34009		if (index !== null) {
34010
34011			const start = Math.max(0, drawRange.start);
34012			const end = Math.min(index.count, (drawRange.start + drawRange.count));
34013
34014			for (let i = start, l = end - 1; i < l; i += step) {
34015
34016				const a = index.getX(i);
34017				const b = index.getX(i + 1);
34018
34019				vStart.fromBufferAttribute(positionAttribute, a);
34020				vEnd.fromBufferAttribute(positionAttribute, b);
34021
34022				const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
34023
34024				if (distSq > localThresholdSq) continue;
34025
34026				interRay.applyMatrix4(this.matrixWorld); //Move back to world space for distance calculation
34027
34028				const distance = raycaster.ray.origin.distanceTo(interRay);
34029
34030				if (distance < raycaster.near || distance > raycaster.far) continue;
34031
34032				intersects.push({
34033
34034					distance: distance,
34035					// What do we want? intersection point on the ray or on the segment??
34036					// point: raycaster.ray.at( distance ),
34037					point: interSegment.clone().applyMatrix4(this.matrixWorld),
34038					index: i,
34039					face: null,
34040					faceIndex: null,
34041					object: this
34042
34043				});
34044
34045			}
34046
34047		} else {
34048
34049			const start = Math.max(0, drawRange.start);
34050			const end = Math.min(positionAttribute.count, (drawRange.start + drawRange.count));
34051
34052			for (let i = start, l = end - 1; i < l; i += step) {
34053
34054				vStart.fromBufferAttribute(positionAttribute, i);
34055				vEnd.fromBufferAttribute(positionAttribute, i + 1);
34056
34057				const distSq = _ray$1.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
34058
34059				if (distSq > localThresholdSq) continue;
34060
34061				interRay.applyMatrix4(this.matrixWorld); //Move back to world space for distance calculation
34062
34063				const distance = raycaster.ray.origin.distanceTo(interRay);
34064
34065				if (distance < raycaster.near || distance > raycaster.far) continue;
34066
34067				intersects.push({
34068
34069					distance: distance,
34070					// What do we want? intersection point on the ray or on the segment??
34071					// point: raycaster.ray.at( distance ),
34072					point: interSegment.clone().applyMatrix4(this.matrixWorld),
34073					index: i,
34074					face: null,
34075					faceIndex: null,
34076					object: this
34077
34078				});
34079
34080			}
34081
34082		}
34083
34084	}
34085
34086	updateMorphTargets() {
34087
34088		const geometry = this.geometry;
34089
34090		const morphAttributes = geometry.morphAttributes;
34091		const keys = Object.keys(morphAttributes);
34092
34093		if (keys.length > 0) {
34094
34095			const morphAttribute = morphAttributes[keys[0]];
vendor: 13,861 bytes, lines 34096-34779
34096
34097			if (morphAttribute !== undefined) {
34098
34099				this.morphTargetInfluences = [];
34100				this.morphTargetDictionary = {};
34101
34102				for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
34103
34104					const name = morphAttribute[m].name || String(m);
34105
34106					this.morphTargetInfluences.push(0);
34107					this.morphTargetDictionary[name] = m;
34108
34109				}
34110
34111			}
34112
34113		}
34114
34115	}
34116
34117}
34118
34119const _start = /*@__PURE__*/ new Vector3();
34120const _end = /*@__PURE__*/ new Vector3();
34121
34122class LineSegments extends Line {
34123
34124	constructor(geometry, material) {
34125
34126		super(geometry, material);
34127
34128		this.isLineSegments = true;
34129
34130		this.type = 'LineSegments';
34131
34132	}
34133
34134	computeLineDistances() {
34135
34136		const geometry = this.geometry;
34137
34138		// we assume non-indexed geometry
34139
34140		if (geometry.index === null) {
34141
34142			const positionAttribute = geometry.attributes.position;
34143			const lineDistances = [];
34144
34145			for (let i = 0, l = positionAttribute.count; i < l; i += 2) {
34146
34147				_start.fromBufferAttribute(positionAttribute, i);
34148				_end.fromBufferAttribute(positionAttribute, i + 1);
34149
34150				lineDistances[i] = (i === 0) ? 0 : lineDistances[i - 1];
34151				lineDistances[i + 1] = lineDistances[i] + _start.distanceTo(_end);
34152
34153			}
34154
34155			geometry.setAttribute('lineDistance', new Float32BufferAttribute(lineDistances, 1));
34156
34157		} else {
34158
34159			console.warn('THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.');
34160
34161		}
34162
34163		return this;
34164
34165	}
34166
34167}
34168
34169class LineLoop extends Line {
34170
34171	constructor(geometry, material) {
34172
34173		super(geometry, material);
34174
34175		this.isLineLoop = true;
34176
34177		this.type = 'LineLoop';
34178
34179	}
34180
34181}
34182
34183class PointsMaterial extends Material {
34184
34185	constructor(parameters) {
34186
34187		super();
34188
34189		this.isPointsMaterial = true;
34190
34191		this.type = 'PointsMaterial';
34192
34193		this.color = new Color(0xffffff);
34194
34195		this.map = null;
34196
34197		this.alphaMap = null;
34198
34199		this.size = 1;
34200		this.sizeAttenuation = true;
34201
34202		this.fog = true;
34203
34204		this.setValues(parameters);
34205
34206	}
34207
34208	copy(source) {
34209
34210		super.copy(source);
34211
34212		this.color.copy(source.color);
34213
34214		this.map = source.map;
34215
34216		this.alphaMap = source.alphaMap;
34217
34218		this.size = source.size;
34219		this.sizeAttenuation = source.sizeAttenuation;
34220
34221		this.fog = source.fog;
34222
34223		return this;
34224
34225	}
34226
34227}
34228
34229const _inverseMatrix = /*@__PURE__*/ new Matrix4();
34230const _ray = /*@__PURE__*/ new Ray();
34231const _sphere = /*@__PURE__*/ new Sphere();
34232const _position$2 = /*@__PURE__*/ new Vector3();
34233
34234class Points extends Object3D {
34235
34236	constructor(geometry = new BufferGeometry(), material = new PointsMaterial()) {
34237
34238		super();
34239
34240		this.isPoints = true;
34241
34242		this.type = 'Points';
34243
34244		this.geometry = geometry;
34245		this.material = material;
34246
34247		this.updateMorphTargets();
34248
34249	}
34250
34251	copy(source, recursive) {
34252
34253		super.copy(source, recursive);
34254
34255		this.material = Array.isArray(source.material) ? source.material.slice() : source.material;
34256		this.geometry = source.geometry;
34257
34258		return this;
34259
34260	}
34261
34262	raycast(raycaster, intersects) {
34263
34264		const geometry = this.geometry;
34265		const matrixWorld = this.matrixWorld;
34266		const threshold = raycaster.params.Points.threshold;
34267		const drawRange = geometry.drawRange;
34268
34269		// Checking boundingSphere distance to ray
34270
34271		if (geometry.boundingSphere === null) geometry.computeBoundingSphere();
34272
34273		_sphere.copy(geometry.boundingSphere);
34274		_sphere.applyMatrix4(matrixWorld);
34275		_sphere.radius += threshold;
34276
34277		if (raycaster.ray.intersectsSphere(_sphere) === false) return;
34278
34279		//
34280
34281		_inverseMatrix.copy(matrixWorld).invert();
34282		_ray.copy(raycaster.ray).applyMatrix4(_inverseMatrix);
34283
34284		const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
34285		const localThresholdSq = localThreshold * localThreshold;
34286
34287		const index = geometry.index;
34288		const attributes = geometry.attributes;
34289		const positionAttribute = attributes.position;
34290
34291		if (index !== null) {
34292
34293			const start = Math.max(0, drawRange.start);
34294			const end = Math.min(index.count, (drawRange.start + drawRange.count));
34295
34296			for (let i = start, il = end; i < il; i++) {
34297
34298				const a = index.getX(i);
34299
34300				_position$2.fromBufferAttribute(positionAttribute, a);
34301
34302				testPoint(_position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this);
34303
34304			}
34305
34306		} else {
34307
34308			const start = Math.max(0, drawRange.start);
34309			const end = Math.min(positionAttribute.count, (drawRange.start + drawRange.count));
34310
34311			for (let i = start, l = end; i < l; i++) {
34312
34313				_position$2.fromBufferAttribute(positionAttribute, i);
34314
34315				testPoint(_position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this);
34316
34317			}
34318
34319		}
34320
34321	}
34322
34323	updateMorphTargets() {
34324
34325		const geometry = this.geometry;
34326
34327		const morphAttributes = geometry.morphAttributes;
34328		const keys = Object.keys(morphAttributes);
34329
34330		if (keys.length > 0) {
34331
34332			const morphAttribute = morphAttributes[keys[0]];
34333
34334			if (morphAttribute !== undefined) {
34335
34336				this.morphTargetInfluences = [];
34337				this.morphTargetDictionary = {};
34338
34339				for (let m = 0, ml = morphAttribute.length; m < ml; m++) {
34340
34341					const name = morphAttribute[m].name || String(m);
34342
34343					this.morphTargetInfluences.push(0);
34344					this.morphTargetDictionary[name] = m;
34345
34346				}
34347
34348			}
34349
34350		}
34351
34352	}
34353
34354}
34355
34356function testPoint(point, index, localThresholdSq, matrixWorld, raycaster, intersects, object) {
34357
34358	const rayPointDistanceSq = _ray.distanceSqToPoint(point);
34359
34360	if (rayPointDistanceSq < localThresholdSq) {
34361
34362		const intersectPoint = new Vector3();
34363
34364		_ray.closestPointToPoint(point, intersectPoint);
34365		intersectPoint.applyMatrix4(matrixWorld);
34366
34367		const distance = raycaster.ray.origin.distanceTo(intersectPoint);
34368
34369		if (distance < raycaster.near || distance > raycaster.far) return;
34370
34371		intersects.push({
34372
34373			distance: distance,
34374			distanceToRay: Math.sqrt(rayPointDistanceSq),
34375			point: intersectPoint,
34376			index: index,
34377			face: null,
34378			object: object
34379
34380		});
34381
34382	}
34383
34384}
34385
34386class VideoTexture extends Texture {
34387
34388	constructor(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
34389
34390		super(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
34391
34392		this.isVideoTexture = true;
34393
34394		this.minFilter = minFilter !== undefined ? minFilter : LinearFilter;
34395		this.magFilter = magFilter !== undefined ? magFilter : LinearFilter;
34396
34397		this.generateMipmaps = false;
34398
34399		const scope = this;
34400
34401		function updateVideo() {
34402
34403			scope.needsUpdate = true;
34404			video.requestVideoFrameCallback(updateVideo);
34405
34406		}
34407
34408		if ('requestVideoFrameCallback' in video) {
34409
34410			video.requestVideoFrameCallback(updateVideo);
34411
34412		}
34413
34414	}
34415
34416	clone() {
34417
34418		return new this.constructor(this.image).copy(this);
34419
34420	}
34421
34422	update() {
34423
34424		const video = this.image;
34425		const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
34426
34427		if (hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA) {
34428
34429			this.needsUpdate = true;
34430
34431		}
34432
34433	}
34434
34435}
34436
34437class FramebufferTexture extends Texture {
34438
34439	constructor(width, height) {
34440
34441		super({ width, height });
34442
34443		this.isFramebufferTexture = true;
34444
34445		this.magFilter = NearestFilter;
34446		this.minFilter = NearestFilter;
34447
34448		this.generateMipmaps = false;
34449
34450		this.needsUpdate = true;
34451
34452	}
34453
34454}
34455
34456class CompressedTexture extends Texture {
34457
34458	constructor(mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace) {
34459
34460		super(null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace);
34461
34462		this.isCompressedTexture = true;
34463
34464		this.image = { width: width, height: height };
34465		this.mipmaps = mipmaps;
34466
34467		// no flipping for cube textures
34468		// (also flipping doesn't work for compressed textures )
34469
34470		this.flipY = false;
34471
34472		// can't generate mipmaps for compressed textures
34473		// mips must be embedded in DDS files
34474
34475		this.generateMipmaps = false;
34476
34477	}
34478
34479}
34480
34481class CompressedArrayTexture extends CompressedTexture {
34482
34483	constructor(mipmaps, width, height, depth, format, type) {
34484
34485		super(mipmaps, width, height, format, type);
34486
34487		this.isCompressedArrayTexture = true;
34488		this.image.depth = depth;
34489		this.wrapR = ClampToEdgeWrapping;
34490
34491	}
34492
34493}
34494
34495class CompressedCubeTexture extends CompressedTexture {
34496
34497	constructor(images, format, type) {
34498
34499		super(undefined, images[0].width, images[0].height, format, type, CubeReflectionMapping);
34500
34501		this.isCompressedCubeTexture = true;
34502		this.isCubeTexture = true;
34503
34504		this.image = images;
34505
34506	}
34507
34508}
34509
34510class CanvasTexture extends Texture {
34511
34512	constructor(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
34513
34514		super(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
34515
34516		this.isCanvasTexture = true;
34517
34518		this.needsUpdate = true;
34519
34520	}
34521
34522}
34523
34524/**
34525 * Extensible curve object.
34526 *
34527 * Some common of curve methods:
34528 * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget )
34529 * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget )
34530 * .getPoints(), .getSpacedPoints()
34531 * .getLength()
34532 * .updateArcLengths()
34533 *
34534 * This following curves inherit from THREE.Curve:
34535 *
34536 * -- 2D curves --
34537 * THREE.ArcCurve
34538 * THREE.CubicBezierCurve
34539 * THREE.EllipseCurve
34540 * THREE.LineCurve
34541 * THREE.QuadraticBezierCurve
34542 * THREE.SplineCurve
34543 *
34544 * -- 3D curves --
34545 * THREE.CatmullRomCurve3
34546 * THREE.CubicBezierCurve3
34547 * THREE.LineCurve3
34548 * THREE.QuadraticBezierCurve3
34549 *
34550 * A series of curves can be represented as a THREE.CurvePath.
34551 *
34552 **/
34553
34554class Curve {
34555
34556	constructor() {
34557
34558		this.type = 'Curve';
34559
34560		this.arcLengthDivisions = 200;
34561
34562	}
34563
34564	// Virtual base class method to overwrite and implement in subclasses
34565	//	- t [0 .. 1]
34566
34567	getPoint( /* t, optionalTarget */) {
34568
34569		console.warn('THREE.Curve: .getPoint() not implemented.');
34570		return null;
34571
34572	}
34573
34574	// Get point at relative position in curve according to arc length
34575	// - u [0 .. 1]
34576
34577	getPointAt(u, optionalTarget) {
34578
34579		const t = this.getUtoTmapping(u);
34580		return this.getPoint(t, optionalTarget);
34581
34582	}
34583
34584	// Get sequence of points using getPoint( t )
34585
34586	getPoints(divisions = 5) {
34587
34588		const points = [];
34589
34590		for (let d = 0; d <= divisions; d++) {
34591
34592			points.push(this.getPoint(d / divisions));
34593
34594		}
34595
34596		return points;
34597
34598	}
34599
34600	// Get sequence of points using getPointAt( u )
34601
34602	getSpacedPoints(divisions = 5) {
34603
34604		const points = [];
34605
34606		for (let d = 0; d <= divisions; d++) {
34607
34608			points.push(this.getPointAt(d / divisions));
34609
34610		}
34611
34612		return points;
34613
34614	}
34615
34616	// Get total curve arc length
34617
34618	getLength() {
34619
34620		const lengths = this.getLengths();
34621		return lengths[lengths.length - 1];
34622
34623	}
34624
34625	// Get list of cumulative segment lengths
34626
34627	getLengths(divisions = this.arcLengthDivisions) {
34628
34629		if (this.cacheArcLengths &&
34630			(this.cacheArcLengths.length === divisions + 1) &&
34631			!this.needsUpdate) {
34632
34633			return this.cacheArcLengths;
34634
34635		}
34636
34637		this.needsUpdate = false;
34638
34639		const cache = [];
34640		let current, last = this.getPoint(0);
34641		let sum = 0;
34642
34643		cache.push(0);
34644
34645		for (let p = 1; p <= divisions; p++) {
34646
34647			current = this.getPoint(p / divisions);
34648			sum += current.distanceTo(last);
34649			cache.push(sum);
34650			last = current;
34651
34652		}
34653
34654		this.cacheArcLengths = cache;
34655
34656		return cache; // { sums: cache, sum: sum }; Sum is in the last element.
34657
34658	}
34659
34660	updateArcLengths() {
34661
34662		this.needsUpdate = true;
34663		this.getLengths();
34664
34665	}
34666
34667	// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
34668
34669	getUtoTmapping(u, distance) {
34670
34671		const arcLengths = this.getLengths();
34672
34673		let i = 0;
34674		const il = arcLengths.length;
34675
34676		let targetArcLength; // The targeted u distance value to get
34677
34678		if (distance) {
34679
34680			targetArcLength = distance;
34681
34682		} else {
34683
34684			targetArcLength = u * arcLengths[il - 1];
34685
34686		}
34687
34688		// binary search for the index with largest value smaller than target u distance
34689
34690		let low = 0, high = il - 1, comparison;
34691
34692		while (low <= high) {
34693
34694			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
34695
34696			comparison = arcLengths[i] - targetArcLength;
34697
34698			if (comparison < 0) {
34699
34700				low = i + 1;
34701
34702			} else if (comparison > 0) {
34703
34704				high = i - 1;
34705
34706			} else {
34707
34708				high = i;
34709				break;
34710
34711				// DONE
34712
34713			}
34714
34715		}
34716
34717		i = high;
34718
34719		if (arcLengths[i] === targetArcLength) {
34720
34721			return i / (il - 1);
34722
34723		}
34724
34725		// we could get finer grain at lengths, or use simple interpolation between two points
34726
34727		const lengthBefore = arcLengths[i];
34728		const lengthAfter = arcLengths[i + 1];
34729
34730		const segmentLength = lengthAfter - lengthBefore;
34731
34732		// determine where we are between the 'before' and 'after' points
34733
34734		const segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
34735
34736		// add that fractional amount to t
34737
34738		const t = (i + segmentFraction) / (il - 1);
34739
34740		return t;
34741
34742	}
34743
34744	// Returns a unit vector tangent at t
34745	// In case any sub curve does not implement its tangent derivation,
34746	// 2 points a small delta apart will be used to find its gradient
34747	// which seems to give a reasonable approximation
34748
34749	getTangent(t, optionalTarget) {
34750
34751		const delta = 0.0001;
34752		let t1 = t - delta;
34753		let t2 = t + delta;
34754
34755		// Capping in case of danger
34756
34757		if (t1 < 0) t1 = 0;
34758		if (t2 > 1) t2 = 1;
34759
34760		const pt1 = this.getPoint(t1);
34761		const pt2 = this.getPoint(t2);
34762
34763		const tangent = optionalTarget || ((pt1.isVector2) ? new Vector2() : new Vector3());
34764
34765		tangent.copy(pt2).sub(pt1).normalize();
34766
34767		return tangent;
34768
34769	}
34770
34771	getTangentAt(u, optionalTarget) {
34772
34773		const t = this.getUtoTmapping(u);
34774		return this.getTangent(t, optionalTarget);
34775
34776	}
34777
34778	computeFrenetFrames(segments, closed) {
34779
vendor: 4,437 bytes, lines 34780-35007
34780		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
34781
34782		const normal = new Vector3();
34783
34784		const tangents = [];
34785		const normals = [];
34786		const binormals = [];
34787
34788		const vec = new Vector3();
34789		const mat = new Matrix4();
34790
34791		// compute the tangent vectors for each segment on the curve
34792
34793		for (let i = 0; i <= segments; i++) {
34794
34795			const u = i / segments;
34796
34797			tangents[i] = this.getTangentAt(u, new Vector3());
34798
34799		}
34800
34801		// select an initial normal vector perpendicular to the first tangent vector,
34802		// and in the direction of the minimum tangent xyz component
34803
34804		normals[0] = new Vector3();
34805		binormals[0] = new Vector3();
34806		let min = Number.MAX_VALUE;
34807		const tx = Math.abs(tangents[0].x);
34808		const ty = Math.abs(tangents[0].y);
34809		const tz = Math.abs(tangents[0].z);
34810
34811		if (tx <= min) {
34812
34813			min = tx;
34814			normal.set(1, 0, 0);
34815
34816		}
34817
34818		if (ty <= min) {
34819
34820			min = ty;
34821			normal.set(0, 1, 0);
34822
34823		}
34824
34825		if (tz <= min) {
34826
34827			normal.set(0, 0, 1);
34828
34829		}
34830
34831		vec.crossVectors(tangents[0], normal).normalize();
34832
34833		normals[0].crossVectors(tangents[0], vec);
34834		binormals[0].crossVectors(tangents[0], normals[0]);
34835
34836
34837		// compute the slowly-varying normal and binormal vectors for each segment on the curve
34838
34839		for (let i = 1; i <= segments; i++) {
34840
34841			normals[i] = normals[i - 1].clone();
34842
34843			binormals[i] = binormals[i - 1].clone();
34844
34845			vec.crossVectors(tangents[i - 1], tangents[i]);
34846
34847			if (vec.length() > Number.EPSILON) {
34848
34849				vec.normalize();
34850
34851				const theta = Math.acos(clamp(tangents[i - 1].dot(tangents[i]), - 1, 1)); // clamp for floating pt errors
34852
34853				normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
34854
34855			}
34856
34857			binormals[i].crossVectors(tangents[i], normals[i]);
34858
34859		}
34860
34861		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
34862
34863		if (closed === true) {
34864
34865			let theta = Math.acos(clamp(normals[0].dot(normals[segments]), - 1, 1));
34866			theta /= segments;
34867
34868			if (tangents[0].dot(vec.crossVectors(normals[0], normals[segments])) > 0) {
34869
34870				theta = - theta;
34871
34872			}
34873
34874			for (let i = 1; i <= segments; i++) {
34875
34876				// twist a little...
34877				normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
34878				binormals[i].crossVectors(tangents[i], normals[i]);
34879
34880			}
34881
34882		}
34883
34884		return {
34885			tangents: tangents,
34886			normals: normals,
34887			binormals: binormals
34888		};
34889
34890	}
34891
34892	clone() {
34893
34894		return new this.constructor().copy(this);
34895
34896	}
34897
34898	copy(source) {
34899
34900		this.arcLengthDivisions = source.arcLengthDivisions;
34901
34902		return this;
34903
34904	}
34905
34906	toJSON() {
34907
34908		const data = {
34909			metadata: {
34910				version: 4.6,
34911				type: 'Curve',
34912				generator: 'Curve.toJSON'
34913			}
34914		};
34915
34916		data.arcLengthDivisions = this.arcLengthDivisions;
34917		data.type = this.type;
34918
34919		return data;
34920
34921	}
34922
34923	fromJSON(json) {
34924
34925		this.arcLengthDivisions = json.arcLengthDivisions;
34926
34927		return this;
34928
34929	}
34930
34931}
34932
34933class EllipseCurve extends Curve {
34934
34935	constructor(aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0) {
34936
34937		super();
34938
34939		this.isEllipseCurve = true;
34940
34941		this.type = 'EllipseCurve';
34942
34943		this.aX = aX;
34944		this.aY = aY;
34945
34946		this.xRadius = xRadius;
34947		this.yRadius = yRadius;
34948
34949		this.aStartAngle = aStartAngle;
34950		this.aEndAngle = aEndAngle;
34951
34952		this.aClockwise = aClockwise;
34953
34954		this.aRotation = aRotation;
34955
34956	}
34957
34958	getPoint(t, optionalTarget) {
34959
34960		const point = optionalTarget || new Vector2();
34961
34962		const twoPi = Math.PI * 2;
34963		let deltaAngle = this.aEndAngle - this.aStartAngle;
34964		const samePoints = Math.abs(deltaAngle) < Number.EPSILON;
34965
34966		// ensures that deltaAngle is 0 .. 2 PI
34967		while (deltaAngle < 0) deltaAngle += twoPi;
34968		while (deltaAngle > twoPi) deltaAngle -= twoPi;
34969
34970		if (deltaAngle < Number.EPSILON) {
34971
34972			if (samePoints) {
34973
34974				deltaAngle = 0;
34975
34976			} else {
34977
34978				deltaAngle = twoPi;
34979
34980			}
34981
34982		}
34983
34984		if (this.aClockwise === true && !samePoints) {
34985
34986			if (deltaAngle === twoPi) {
34987
34988				deltaAngle = - twoPi;
34989
34990			} else {
34991
34992				deltaAngle = deltaAngle - twoPi;
34993
34994			}
34995
34996		}
34997
34998		const angle = this.aStartAngle + t * deltaAngle;
34999		let x = this.aX + this.xRadius * Math.cos(angle);
35000		let y = this.aY + this.yRadius * Math.sin(angle);
35001
35002		if (this.aRotation !== 0) {
35003
35004			const cos = Math.cos(this.aRotation);
35005			const sin = Math.sin(this.aRotation);
35006
35007			const tx = x - this.aX;
vendor: 29,584 bytes, lines 35008-36647
35008			const ty = y - this.aY;
35009
35010			// Rotate the point about the center of the ellipse.
35011			x = tx * cos - ty * sin + this.aX;
35012			y = tx * sin + ty * cos + this.aY;
35013
35014		}
35015
35016		return point.set(x, y);
35017
35018	}
35019
35020	copy(source) {
35021
35022		super.copy(source);
35023
35024		this.aX = source.aX;
35025		this.aY = source.aY;
35026
35027		this.xRadius = source.xRadius;
35028		this.yRadius = source.yRadius;
35029
35030		this.aStartAngle = source.aStartAngle;
35031		this.aEndAngle = source.aEndAngle;
35032
35033		this.aClockwise = source.aClockwise;
35034
35035		this.aRotation = source.aRotation;
35036
35037		return this;
35038
35039	}
35040
35041	toJSON() {
35042
35043		const data = super.toJSON();
35044
35045		data.aX = this.aX;
35046		data.aY = this.aY;
35047
35048		data.xRadius = this.xRadius;
35049		data.yRadius = this.yRadius;
35050
35051		data.aStartAngle = this.aStartAngle;
35052		data.aEndAngle = this.aEndAngle;
35053
35054		data.aClockwise = this.aClockwise;
35055
35056		data.aRotation = this.aRotation;
35057
35058		return data;
35059
35060	}
35061
35062	fromJSON(json) {
35063
35064		super.fromJSON(json);
35065
35066		this.aX = json.aX;
35067		this.aY = json.aY;
35068
35069		this.xRadius = json.xRadius;
35070		this.yRadius = json.yRadius;
35071
35072		this.aStartAngle = json.aStartAngle;
35073		this.aEndAngle = json.aEndAngle;
35074
35075		this.aClockwise = json.aClockwise;
35076
35077		this.aRotation = json.aRotation;
35078
35079		return this;
35080
35081	}
35082
35083}
35084
35085class ArcCurve extends EllipseCurve {
35086
35087	constructor(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
35088
35089		super(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
35090
35091		this.isArcCurve = true;
35092
35093		this.type = 'ArcCurve';
35094
35095	}
35096
35097}
35098
35099/**
35100 * Centripetal CatmullRom Curve - which is useful for avoiding
35101 * cusps and self-intersections in non-uniform catmull rom curves.
35102 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
35103 *
35104 * curve.type accepts centripetal(default), chordal and catmullrom
35105 * curve.tension is used for catmullrom which defaults to 0.5
35106 */
35107
35108
35109/*
35110Based on an optimized c++ solution in
35111 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
35112 - http://ideone.com/NoEbVM
35113
35114This CubicPoly class could be used for reusing some variables and calculations,
35115but for three.js curve use, it could be possible inlined and flatten into a single function call
35116which can be placed in CurveUtils.
35117*/
35118
35119function CubicPoly() {
35120
35121	let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
35122
35123	/*
35124	 * Compute coefficients for a cubic polynomial
35125	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
35126	 * such that
35127	 *   p(0) = x0, p(1) = x1
35128	 *  and
35129	 *   p'(0) = t0, p'(1) = t1.
35130	 */
35131	function init(x0, x1, t0, t1) {
35132
35133		c0 = x0;
35134		c1 = t0;
35135		c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
35136		c3 = 2 * x0 - 2 * x1 + t0 + t1;
35137
35138	}
35139
35140	return {
35141
35142		initCatmullRom: function (x0, x1, x2, x3, tension) {
35143
35144			init(x1, x2, tension * (x2 - x0), tension * (x3 - x1));
35145
35146		},
35147
35148		initNonuniformCatmullRom: function (x0, x1, x2, x3, dt0, dt1, dt2) {
35149
35150			// compute tangents when parameterized in [t1,t2]
35151			let t1 = (x1 - x0) / dt0 - (x2 - x0) / (dt0 + dt1) + (x2 - x1) / dt1;
35152			let t2 = (x2 - x1) / dt1 - (x3 - x1) / (dt1 + dt2) + (x3 - x2) / dt2;
35153
35154			// rescale tangents for parametrization in [0,1]
35155			t1 *= dt1;
35156			t2 *= dt1;
35157
35158			init(x1, x2, t1, t2);
35159
35160		},
35161
35162		calc: function (t) {
35163
35164			const t2 = t * t;
35165			const t3 = t2 * t;
35166			return c0 + c1 * t + c2 * t2 + c3 * t3;
35167
35168		}
35169
35170	};
35171
35172}
35173
35174//
35175
35176const tmp = /*@__PURE__*/ new Vector3();
35177const px = /*@__PURE__*/ new CubicPoly();
35178const py = /*@__PURE__*/ new CubicPoly();
35179const pz = /*@__PURE__*/ new CubicPoly();
35180
35181class CatmullRomCurve3 extends Curve {
35182
35183	constructor(points = [], closed = false, curveType = 'centripetal', tension = 0.5) {
35184
35185		super();
35186
35187		this.isCatmullRomCurve3 = true;
35188
35189		this.type = 'CatmullRomCurve3';
35190
35191		this.points = points;
35192		this.closed = closed;
35193		this.curveType = curveType;
35194		this.tension = tension;
35195
35196	}
35197
35198	getPoint(t, optionalTarget = new Vector3()) {
35199
35200		const point = optionalTarget;
35201
35202		const points = this.points;
35203		const l = points.length;
35204
35205		const p = (l - (this.closed ? 0 : 1)) * t;
35206		let intPoint = Math.floor(p);
35207		let weight = p - intPoint;
35208
35209		if (this.closed) {
35210
35211			intPoint += intPoint > 0 ? 0 : (Math.floor(Math.abs(intPoint) / l) + 1) * l;
35212
35213		} else if (weight === 0 && intPoint === l - 1) {
35214
35215			intPoint = l - 2;
35216			weight = 1;
35217
35218		}
35219
35220		let p0, p3; // 4 points (p1 & p2 defined below)
35221
35222		if (this.closed || intPoint > 0) {
35223
35224			p0 = points[(intPoint - 1) % l];
35225
35226		} else {
35227
35228			// extrapolate first point
35229			tmp.subVectors(points[0], points[1]).add(points[0]);
35230			p0 = tmp;
35231
35232		}
35233
35234		const p1 = points[intPoint % l];
35235		const p2 = points[(intPoint + 1) % l];
35236
35237		if (this.closed || intPoint + 2 < l) {
35238
35239			p3 = points[(intPoint + 2) % l];
35240
35241		} else {
35242
35243			// extrapolate last point
35244			tmp.subVectors(points[l - 1], points[l - 2]).add(points[l - 1]);
35245			p3 = tmp;
35246
35247		}
35248
35249		if (this.curveType === 'centripetal' || this.curveType === 'chordal') {
35250
35251			// init Centripetal / Chordal Catmull-Rom
35252			const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
35253			let dt0 = Math.pow(p0.distanceToSquared(p1), pow);
35254			let dt1 = Math.pow(p1.distanceToSquared(p2), pow);
35255			let dt2 = Math.pow(p2.distanceToSquared(p3), pow);
35256
35257			// safety check for repeated points
35258			if (dt1 < 1e-4) dt1 = 1.0;
35259			if (dt0 < 1e-4) dt0 = dt1;
35260			if (dt2 < 1e-4) dt2 = dt1;
35261
35262			px.initNonuniformCatmullRom(p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2);
35263			py.initNonuniformCatmullRom(p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2);
35264			pz.initNonuniformCatmullRom(p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2);
35265
35266		} else if (this.curveType === 'catmullrom') {
35267
35268			px.initCatmullRom(p0.x, p1.x, p2.x, p3.x, this.tension);
35269			py.initCatmullRom(p0.y, p1.y, p2.y, p3.y, this.tension);
35270			pz.initCatmullRom(p0.z, p1.z, p2.z, p3.z, this.tension);
35271
35272		}
35273
35274		point.set(
35275			px.calc(weight),
35276			py.calc(weight),
35277			pz.calc(weight)
35278		);
35279
35280		return point;
35281
35282	}
35283
35284	copy(source) {
35285
35286		super.copy(source);
35287
35288		this.points = [];
35289
35290		for (let i = 0, l = source.points.length; i < l; i++) {
35291
35292			const point = source.points[i];
35293
35294			this.points.push(point.clone());
35295
35296		}
35297
35298		this.closed = source.closed;
35299		this.curveType = source.curveType;
35300		this.tension = source.tension;
35301
35302		return this;
35303
35304	}
35305
35306	toJSON() {
35307
35308		const data = super.toJSON();
35309
35310		data.points = [];
35311
35312		for (let i = 0, l = this.points.length; i < l; i++) {
35313
35314			const point = this.points[i];
35315			data.points.push(point.toArray());
35316
35317		}
35318
35319		data.closed = this.closed;
35320		data.curveType = this.curveType;
35321		data.tension = this.tension;
35322
35323		return data;
35324
35325	}
35326
35327	fromJSON(json) {
35328
35329		super.fromJSON(json);
35330
35331		this.points = [];
35332
35333		for (let i = 0, l = json.points.length; i < l; i++) {
35334
35335			const point = json.points[i];
35336			this.points.push(new Vector3().fromArray(point));
35337
35338		}
35339
35340		this.closed = json.closed;
35341		this.curveType = json.curveType;
35342		this.tension = json.tension;
35343
35344		return this;
35345
35346	}
35347
35348}
35349
35350/**
35351 * Bezier Curves formulas obtained from
35352 * https://en.wikipedia.org/wiki/B%C3%A9zier_curve
35353 */
35354
35355function CatmullRom(t, p0, p1, p2, p3) {
35356
35357	const v0 = (p2 - p0) * 0.5;
35358	const v1 = (p3 - p1) * 0.5;
35359	const t2 = t * t;
35360	const t3 = t * t2;
35361	return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (- 3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
35362
35363}
35364
35365//
35366
35367function QuadraticBezierP0(t, p) {
35368
35369	const k = 1 - t;
35370	return k * k * p;
35371
35372}
35373
35374function QuadraticBezierP1(t, p) {
35375
35376	return 2 * (1 - t) * t * p;
35377
35378}
35379
35380function QuadraticBezierP2(t, p) {
35381
35382	return t * t * p;
35383
35384}
35385
35386function QuadraticBezier(t, p0, p1, p2) {
35387
35388	return QuadraticBezierP0(t, p0) + QuadraticBezierP1(t, p1) +
35389		QuadraticBezierP2(t, p2);
35390
35391}
35392
35393//
35394
35395function CubicBezierP0(t, p) {
35396
35397	const k = 1 - t;
35398	return k * k * k * p;
35399
35400}
35401
35402function CubicBezierP1(t, p) {
35403
35404	const k = 1 - t;
35405	return 3 * k * k * t * p;
35406
35407}
35408
35409function CubicBezierP2(t, p) {
35410
35411	return 3 * (1 - t) * t * t * p;
35412
35413}
35414
35415function CubicBezierP3(t, p) {
35416
35417	return t * t * t * p;
35418
35419}
35420
35421function CubicBezier(t, p0, p1, p2, p3) {
35422
35423	return CubicBezierP0(t, p0) + CubicBezierP1(t, p1) + CubicBezierP2(t, p2) +
35424		CubicBezierP3(t, p3);
35425
35426}
35427
35428class CubicBezierCurve extends Curve {
35429
35430	constructor(v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2()) {
35431
35432		super();
35433
35434		this.isCubicBezierCurve = true;
35435
35436		this.type = 'CubicBezierCurve';
35437
35438		this.v0 = v0;
35439		this.v1 = v1;
35440		this.v2 = v2;
35441		this.v3 = v3;
35442
35443	}
35444
35445	getPoint(t, optionalTarget = new Vector2()) {
35446
35447		const point = optionalTarget;
35448
35449		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35450
35451		point.set(
35452			CubicBezier(t, v0.x, v1.x, v2.x, v3.x),
35453			CubicBezier(t, v0.y, v1.y, v2.y, v3.y)
35454		);
35455
35456		return point;
35457
35458	}
35459
35460	copy(source) {
35461
35462		super.copy(source);
35463
35464		this.v0.copy(source.v0);
35465		this.v1.copy(source.v1);
35466		this.v2.copy(source.v2);
35467		this.v3.copy(source.v3);
35468
35469		return this;
35470
35471	}
35472
35473	toJSON() {
35474
35475		const data = super.toJSON();
35476
35477		data.v0 = this.v0.toArray();
35478		data.v1 = this.v1.toArray();
35479		data.v2 = this.v2.toArray();
35480		data.v3 = this.v3.toArray();
35481
35482		return data;
35483
35484	}
35485
35486	fromJSON(json) {
35487
35488		super.fromJSON(json);
35489
35490		this.v0.fromArray(json.v0);
35491		this.v1.fromArray(json.v1);
35492		this.v2.fromArray(json.v2);
35493		this.v3.fromArray(json.v3);
35494
35495		return this;
35496
35497	}
35498
35499}
35500
35501class CubicBezierCurve3 extends Curve {
35502
35503	constructor(v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3()) {
35504
35505		super();
35506
35507		this.isCubicBezierCurve3 = true;
35508
35509		this.type = 'CubicBezierCurve3';
35510
35511		this.v0 = v0;
35512		this.v1 = v1;
35513		this.v2 = v2;
35514		this.v3 = v3;
35515
35516	}
35517
35518	getPoint(t, optionalTarget = new Vector3()) {
35519
35520		const point = optionalTarget;
35521
35522		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
35523
35524		point.set(
35525			CubicBezier(t, v0.x, v1.x, v2.x, v3.x),
35526			CubicBezier(t, v0.y, v1.y, v2.y, v3.y),
35527			CubicBezier(t, v0.z, v1.z, v2.z, v3.z)
35528		);
35529
35530		return point;
35531
35532	}
35533
35534	copy(source) {
35535
35536		super.copy(source);
35537
35538		this.v0.copy(source.v0);
35539		this.v1.copy(source.v1);
35540		this.v2.copy(source.v2);
35541		this.v3.copy(source.v3);
35542
35543		return this;
35544
35545	}
35546
35547	toJSON() {
35548
35549		const data = super.toJSON();
35550
35551		data.v0 = this.v0.toArray();
35552		data.v1 = this.v1.toArray();
35553		data.v2 = this.v2.toArray();
35554		data.v3 = this.v3.toArray();
35555
35556		return data;
35557
35558	}
35559
35560	fromJSON(json) {
35561
35562		super.fromJSON(json);
35563
35564		this.v0.fromArray(json.v0);
35565		this.v1.fromArray(json.v1);
35566		this.v2.fromArray(json.v2);
35567		this.v3.fromArray(json.v3);
35568
35569		return this;
35570
35571	}
35572
35573}
35574
35575class LineCurve extends Curve {
35576
35577	constructor(v1 = new Vector2(), v2 = new Vector2()) {
35578
35579		super();
35580
35581		this.isLineCurve = true;
35582
35583		this.type = 'LineCurve';
35584
35585		this.v1 = v1;
35586		this.v2 = v2;
35587
35588	}
35589
35590	getPoint(t, optionalTarget = new Vector2()) {
35591
35592		const point = optionalTarget;
35593
35594		if (t === 1) {
35595
35596			point.copy(this.v2);
35597
35598		} else {
35599
35600			point.copy(this.v2).sub(this.v1);
35601			point.multiplyScalar(t).add(this.v1);
35602
35603		}
35604
35605		return point;
35606
35607	}
35608
35609	// Line curve is linear, so we can overwrite default getPointAt
35610	getPointAt(u, optionalTarget) {
35611
35612		return this.getPoint(u, optionalTarget);
35613
35614	}
35615
35616	getTangent(t, optionalTarget = new Vector2()) {
35617
35618		return optionalTarget.subVectors(this.v2, this.v1).normalize();
35619
35620	}
35621
35622	getTangentAt(u, optionalTarget) {
35623
35624		return this.getTangent(u, optionalTarget);
35625
35626	}
35627
35628	copy(source) {
35629
35630		super.copy(source);
35631
35632		this.v1.copy(source.v1);
35633		this.v2.copy(source.v2);
35634
35635		return this;
35636
35637	}
35638
35639	toJSON() {
35640
35641		const data = super.toJSON();
35642
35643		data.v1 = this.v1.toArray();
35644		data.v2 = this.v2.toArray();
35645
35646		return data;
35647
35648	}
35649
35650	fromJSON(json) {
35651
35652		super.fromJSON(json);
35653
35654		this.v1.fromArray(json.v1);
35655		this.v2.fromArray(json.v2);
35656
35657		return this;
35658
35659	}
35660
35661}
35662
35663class LineCurve3 extends Curve {
35664
35665	constructor(v1 = new Vector3(), v2 = new Vector3()) {
35666
35667		super();
35668
35669		this.isLineCurve3 = true;
35670
35671		this.type = 'LineCurve3';
35672
35673		this.v1 = v1;
35674		this.v2 = v2;
35675
35676	}
35677
35678	getPoint(t, optionalTarget = new Vector3()) {
35679
35680		const point = optionalTarget;
35681
35682		if (t === 1) {
35683
35684			point.copy(this.v2);
35685
35686		} else {
35687
35688			point.copy(this.v2).sub(this.v1);
35689			point.multiplyScalar(t).add(this.v1);
35690
35691		}
35692
35693		return point;
35694
35695	}
35696
35697	// Line curve is linear, so we can overwrite default getPointAt
35698	getPointAt(u, optionalTarget) {
35699
35700		return this.getPoint(u, optionalTarget);
35701
35702	}
35703
35704	getTangent(t, optionalTarget = new Vector3()) {
35705
35706		return optionalTarget.subVectors(this.v2, this.v1).normalize();
35707
35708	}
35709
35710	getTangentAt(u, optionalTarget) {
35711
35712		return this.getTangent(u, optionalTarget);
35713
35714	}
35715
35716	copy(source) {
35717
35718		super.copy(source);
35719
35720		this.v1.copy(source.v1);
35721		this.v2.copy(source.v2);
35722
35723		return this;
35724
35725	}
35726
35727	toJSON() {
35728
35729		const data = super.toJSON();
35730
35731		data.v1 = this.v1.toArray();
35732		data.v2 = this.v2.toArray();
35733
35734		return data;
35735
35736	}
35737
35738	fromJSON(json) {
35739
35740		super.fromJSON(json);
35741
35742		this.v1.fromArray(json.v1);
35743		this.v2.fromArray(json.v2);
35744
35745		return this;
35746
35747	}
35748
35749}
35750
35751class QuadraticBezierCurve extends Curve {
35752
35753	constructor(v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2()) {
35754
35755		super();
35756
35757		this.isQuadraticBezierCurve = true;
35758
35759		this.type = 'QuadraticBezierCurve';
35760
35761		this.v0 = v0;
35762		this.v1 = v1;
35763		this.v2 = v2;
35764
35765	}
35766
35767	getPoint(t, optionalTarget = new Vector2()) {
35768
35769		const point = optionalTarget;
35770
35771		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
35772
35773		point.set(
35774			QuadraticBezier(t, v0.x, v1.x, v2.x),
35775			QuadraticBezier(t, v0.y, v1.y, v2.y)
35776		);
35777
35778		return point;
35779
35780	}
35781
35782	copy(source) {
35783
35784		super.copy(source);
35785
35786		this.v0.copy(source.v0);
35787		this.v1.copy(source.v1);
35788		this.v2.copy(source.v2);
35789
35790		return this;
35791
35792	}
35793
35794	toJSON() {
35795
35796		const data = super.toJSON();
35797
35798		data.v0 = this.v0.toArray();
35799		data.v1 = this.v1.toArray();
35800		data.v2 = this.v2.toArray();
35801
35802		return data;
35803
35804	}
35805
35806	fromJSON(json) {
35807
35808		super.fromJSON(json);
35809
35810		this.v0.fromArray(json.v0);
35811		this.v1.fromArray(json.v1);
35812		this.v2.fromArray(json.v2);
35813
35814		return this;
35815
35816	}
35817
35818}
35819
35820class QuadraticBezierCurve3 extends Curve {
35821
35822	constructor(v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3()) {
35823
35824		super();
35825
35826		this.isQuadraticBezierCurve3 = true;
35827
35828		this.type = 'QuadraticBezierCurve3';
35829
35830		this.v0 = v0;
35831		this.v1 = v1;
35832		this.v2 = v2;
35833
35834	}
35835
35836	getPoint(t, optionalTarget = new Vector3()) {
35837
35838		const point = optionalTarget;
35839
35840		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
35841
35842		point.set(
35843			QuadraticBezier(t, v0.x, v1.x, v2.x),
35844			QuadraticBezier(t, v0.y, v1.y, v2.y),
35845			QuadraticBezier(t, v0.z, v1.z, v2.z)
35846		);
35847
35848		return point;
35849
35850	}
35851
35852	copy(source) {
35853
35854		super.copy(source);
35855
35856		this.v0.copy(source.v0);
35857		this.v1.copy(source.v1);
35858		this.v2.copy(source.v2);
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
35872		return data;
35873
35874	}
35875
35876	fromJSON(json) {
35877
35878		super.fromJSON(json);
35879
35880		this.v0.fromArray(json.v0);
35881		this.v1.fromArray(json.v1);
35882		this.v2.fromArray(json.v2);
35883
35884		return this;
35885
35886	}
35887
35888}
35889
35890class SplineCurve extends Curve {
35891
35892	constructor(points = []) {
35893
35894		super();
35895
35896		this.isSplineCurve = true;
35897
35898		this.type = 'SplineCurve';
35899
35900		this.points = points;
35901
35902	}
35903
35904	getPoint(t, optionalTarget = new Vector2()) {
35905
35906		const point = optionalTarget;
35907
35908		const points = this.points;
35909		const p = (points.length - 1) * t;
35910
35911		const intPoint = Math.floor(p);
35912		const weight = p - intPoint;
35913
35914		const p0 = points[intPoint === 0 ? intPoint : intPoint - 1];
35915		const p1 = points[intPoint];
35916		const p2 = points[intPoint > points.length - 2 ? points.length - 1 : intPoint + 1];
35917		const p3 = points[intPoint > points.length - 3 ? points.length - 1 : intPoint + 2];
35918
35919		point.set(
35920			CatmullRom(weight, p0.x, p1.x, p2.x, p3.x),
35921			CatmullRom(weight, p0.y, p1.y, p2.y, p3.y)
35922		);
35923
35924		return point;
35925
35926	}
35927
35928	copy(source) {
35929
35930		super.copy(source);
35931
35932		this.points = [];
35933
35934		for (let i = 0, l = source.points.length; i < l; i++) {
35935
35936			const point = source.points[i];
35937
35938			this.points.push(point.clone());
35939
35940		}
35941
35942		return this;
35943
35944	}
35945
35946	toJSON() {
35947
35948		const data = super.toJSON();
35949
35950		data.points = [];
35951
35952		for (let i = 0, l = this.points.length; i < l; i++) {
35953
35954			const point = this.points[i];
35955			data.points.push(point.toArray());
35956
35957		}
35958
35959		return data;
35960
35961	}
35962
35963	fromJSON(json) {
35964
35965		super.fromJSON(json);
35966
35967		this.points = [];
35968
35969		for (let i = 0, l = json.points.length; i < l; i++) {
35970
35971			const point = json.points[i];
35972			this.points.push(new Vector2().fromArray(point));
35973
35974		}
35975
35976		return this;
35977
35978	}
35979
35980}
35981
35982var Curves = /*#__PURE__*/Object.freeze({
35983	__proto__: null,
35984	ArcCurve: ArcCurve,
35985	CatmullRomCurve3: CatmullRomCurve3,
35986	CubicBezierCurve: CubicBezierCurve,
35987	CubicBezierCurve3: CubicBezierCurve3,
35988	EllipseCurve: EllipseCurve,
35989	LineCurve: LineCurve,
35990	LineCurve3: LineCurve3,
35991	QuadraticBezierCurve: QuadraticBezierCurve,
35992	QuadraticBezierCurve3: QuadraticBezierCurve3,
35993	SplineCurve: SplineCurve
35994});
35995
35996/**************************************************************
35997 *	Curved Path - a curve path is simply a array of connected
35998 *  curves, but retains the api of a curve
35999 **************************************************************/
36000
36001class CurvePath extends Curve {
36002
36003	constructor() {
36004
36005		super();
36006
36007		this.type = 'CurvePath';
36008
36009		this.curves = [];
36010		this.autoClose = false; // Automatically closes the path
36011
36012	}
36013
36014	add(curve) {
36015
36016		this.curves.push(curve);
36017
36018	}
36019
36020	closePath() {
36021
36022		// Add a line curve if start and end of lines are not connected
36023		const startPoint = this.curves[0].getPoint(0);
36024		const endPoint = this.curves[this.curves.length - 1].getPoint(1);
36025
36026		if (!startPoint.equals(endPoint)) {
36027
36028			const lineType = (startPoint.isVector2 === true) ? 'LineCurve' : 'LineCurve3';
36029			this.curves.push(new Curves[lineType](endPoint, startPoint));
36030
36031		}
36032
36033		return this;
36034
36035	}
36036
36037	// To get accurate point with reference to
36038	// entire path distance at time t,
36039	// following has to be done:
36040
36041	// 1. Length of each sub path have to be known
36042	// 2. Locate and identify type of curve
36043	// 3. Get t for the curve
36044	// 4. Return curve.getPointAt(t')
36045
36046	getPoint(t, optionalTarget) {
36047
36048		const d = t * this.getLength();
36049		const curveLengths = this.getCurveLengths();
36050		let i = 0;
36051
36052		// To think about boundaries points.
36053
36054		while (i < curveLengths.length) {
36055
36056			if (curveLengths[i] >= d) {
36057
36058				const diff = curveLengths[i] - d;
36059				const curve = this.curves[i];
36060
36061				const segmentLength = curve.getLength();
36062				const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
36063
36064				return curve.getPointAt(u, optionalTarget);
36065
36066			}
36067
36068			i++;
36069
36070		}
36071
36072		return null;
36073
36074		// loop where sum != 0, sum > d , sum+1 <d
36075
36076	}
36077
36078	// We cannot use the default THREE.Curve getPoint() with getLength() because in
36079	// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
36080	// getPoint() depends on getLength
36081
36082	getLength() {
36083
36084		const lens = this.getCurveLengths();
36085		return lens[lens.length - 1];
36086
36087	}
36088
36089	// cacheLengths must be recalculated.
36090	updateArcLengths() {
36091
36092		this.needsUpdate = true;
36093		this.cacheLengths = null;
36094		this.getCurveLengths();
36095
36096	}
36097
36098	// Compute lengths and cache them
36099	// We cannot overwrite getLengths() because UtoT mapping uses it.
36100
36101	getCurveLengths() {
36102
36103		// We use cache values if curves and cache array are same length
36104
36105		if (this.cacheLengths && this.cacheLengths.length === this.curves.length) {
36106
36107			return this.cacheLengths;
36108
36109		}
36110
36111		// Get length of sub-curve
36112		// Push sums into cached array
36113
36114		const lengths = [];
36115		let sums = 0;
36116
36117		for (let i = 0, l = this.curves.length; i < l; i++) {
36118
36119			sums += this.curves[i].getLength();
36120			lengths.push(sums);
36121
36122		}
36123
36124		this.cacheLengths = lengths;
36125
36126		return lengths;
36127
36128	}
36129
36130	getSpacedPoints(divisions = 40) {
36131
36132		const points = [];
36133
36134		for (let i = 0; i <= divisions; i++) {
36135
36136			points.push(this.getPoint(i / divisions));
36137
36138		}
36139
36140		if (this.autoClose) {
36141
36142			points.push(points[0]);
36143
36144		}
36145
36146		return points;
36147
36148	}
36149
36150	getPoints(divisions = 12) {
36151
36152		const points = [];
36153		let last;
36154
36155		for (let i = 0, curves = this.curves; i < curves.length; i++) {
36156
36157			const curve = curves[i];
36158			const resolution = curve.isEllipseCurve ? divisions * 2
36159				: (curve.isLineCurve || curve.isLineCurve3) ? 1
36160					: curve.isSplineCurve ? divisions * curve.points.length
36161						: divisions;
36162
36163			const pts = curve.getPoints(resolution);
36164
36165			for (let j = 0; j < pts.length; j++) {
36166
36167				const point = pts[j];
36168
36169				if (last && last.equals(point)) continue; // ensures no consecutive points are duplicates
36170
36171				points.push(point);
36172				last = point;
36173
36174			}
36175
36176		}
36177
36178		if (this.autoClose && points.length > 1 && !points[points.length - 1].equals(points[0])) {
36179
36180			points.push(points[0]);
36181
36182		}
36183
36184		return points;
36185
36186	}
36187
36188	copy(source) {
36189
36190		super.copy(source);
36191
36192		this.curves = [];
36193
36194		for (let i = 0, l = source.curves.length; i < l; i++) {
36195
36196			const curve = source.curves[i];
36197
36198			this.curves.push(curve.clone());
36199
36200		}
36201
36202		this.autoClose = source.autoClose;
36203
36204		return this;
36205
36206	}
36207
36208	toJSON() {
36209
36210		const data = super.toJSON();
36211
36212		data.autoClose = this.autoClose;
36213		data.curves = [];
36214
36215		for (let i = 0, l = this.curves.length; i < l; i++) {
36216
36217			const curve = this.curves[i];
36218			data.curves.push(curve.toJSON());
36219
36220		}
36221
36222		return data;
36223
36224	}
36225
36226	fromJSON(json) {
36227
36228		super.fromJSON(json);
36229
36230		this.autoClose = json.autoClose;
36231		this.curves = [];
36232
36233		for (let i = 0, l = json.curves.length; i < l; i++) {
36234
36235			const curve = json.curves[i];
36236			this.curves.push(new Curves[curve.type]().fromJSON(curve));
36237
36238		}
36239
36240		return this;
36241
36242	}
36243
36244}
36245
36246class Path extends CurvePath {
36247
36248	constructor(points) {
36249
36250		super();
36251
36252		this.type = 'Path';
36253
36254		this.currentPoint = new Vector2();
36255
36256		if (points) {
36257
36258			this.setFromPoints(points);
36259
36260		}
36261
36262	}
36263
36264	setFromPoints(points) {
36265
36266		this.moveTo(points[0].x, points[0].y);
36267
36268		for (let i = 1, l = points.length; i < l; i++) {
36269
36270			this.lineTo(points[i].x, points[i].y);
36271
36272		}
36273
36274		return this;
36275
36276	}
36277
36278	moveTo(x, y) {
36279
36280		this.currentPoint.set(x, y); // TODO consider referencing vectors instead of copying?
36281
36282		return this;
36283
36284	}
36285
36286	lineTo(x, y) {
36287
36288		const curve = new LineCurve(this.currentPoint.clone(), new Vector2(x, y));
36289		this.curves.push(curve);
36290
36291		this.currentPoint.set(x, y);
36292
36293		return this;
36294
36295	}
36296
36297	quadraticCurveTo(aCPx, aCPy, aX, aY) {
36298
36299		const curve = new QuadraticBezierCurve(
36300			this.currentPoint.clone(),
36301			new Vector2(aCPx, aCPy),
36302			new Vector2(aX, aY)
36303		);
36304
36305		this.curves.push(curve);
36306
36307		this.currentPoint.set(aX, aY);
36308
36309		return this;
36310
36311	}
36312
36313	bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
36314
36315		const curve = new CubicBezierCurve(
36316			this.currentPoint.clone(),
36317			new Vector2(aCP1x, aCP1y),
36318			new Vector2(aCP2x, aCP2y),
36319			new Vector2(aX, aY)
36320		);
36321
36322		this.curves.push(curve);
36323
36324		this.currentPoint.set(aX, aY);
36325
36326		return this;
36327
36328	}
36329
36330	splineThru(pts /*Array of Vector*/) {
36331
36332		const npts = [this.currentPoint.clone()].concat(pts);
36333
36334		const curve = new SplineCurve(npts);
36335		this.curves.push(curve);
36336
36337		this.currentPoint.copy(pts[pts.length - 1]);
36338
36339		return this;
36340
36341	}
36342
36343	arc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
36344
36345		const x0 = this.currentPoint.x;
36346		const y0 = this.currentPoint.y;
36347
36348		this.absarc(aX + x0, aY + y0, aRadius,
36349			aStartAngle, aEndAngle, aClockwise);
36350
36351		return this;
36352
36353	}
36354
36355	absarc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
36356
36357		this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
36358
36359		return this;
36360
36361	}
36362
36363	ellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
36364
36365		const x0 = this.currentPoint.x;
36366		const y0 = this.currentPoint.y;
36367
36368		this.absellipse(aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
36369
36370		return this;
36371
36372	}
36373
36374	absellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
36375
36376		const curve = new EllipseCurve(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
36377
36378		if (this.curves.length > 0) {
36379
36380			// if a previous curve is present, attempt to join
36381			const firstPoint = curve.getPoint(0);
36382
36383			if (!firstPoint.equals(this.currentPoint)) {
36384
36385				this.lineTo(firstPoint.x, firstPoint.y);
36386
36387			}
36388
36389		}
36390
36391		this.curves.push(curve);
36392
36393		const lastPoint = curve.getPoint(1);
36394		this.currentPoint.copy(lastPoint);
36395
36396		return this;
36397
36398	}
36399
36400	copy(source) {
36401
36402		super.copy(source);
36403
36404		this.currentPoint.copy(source.currentPoint);
36405
36406		return this;
36407
36408	}
36409
36410	toJSON() {
36411
36412		const data = super.toJSON();
36413
36414		data.currentPoint = this.currentPoint.toArray();
36415
36416		return data;
36417
36418	}
36419
36420	fromJSON(json) {
36421
36422		super.fromJSON(json);
36423
36424		this.currentPoint.fromArray(json.currentPoint);
36425
36426		return this;
36427
36428	}
36429
36430}
36431
36432class LatheGeometry extends BufferGeometry {
36433
36434	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) {
36435
36436		super();
36437
36438		this.type = 'LatheGeometry';
36439
36440		this.parameters = {
36441			points: points,
36442			segments: segments,
36443			phiStart: phiStart,
36444			phiLength: phiLength
36445		};
36446
36447		segments = Math.floor(segments);
36448
36449		// clamp phiLength so it's in range of [ 0, 2PI ]
36450
36451		phiLength = clamp(phiLength, 0, Math.PI * 2);
36452
36453		// buffers
36454
36455		const indices = [];
36456		const vertices = [];
36457		const uvs = [];
36458		const initNormals = [];
36459		const normals = [];
36460
36461		// helper variables
36462
36463		const inverseSegments = 1.0 / segments;
36464		const vertex = new Vector3();
36465		const uv = new Vector2();
36466		const normal = new Vector3();
36467		const curNormal = new Vector3();
36468		const prevNormal = new Vector3();
36469		let dx = 0;
36470		let dy = 0;
36471
36472		// pre-compute normals for initial "meridian"
36473
36474		for (let j = 0; j <= (points.length - 1); j++) {
36475
36476			switch (j) {
36477
36478				case 0:				// special handling for 1st vertex on path
36479
36480					dx = points[j + 1].x - points[j].x;
36481					dy = points[j + 1].y - points[j].y;
36482
36483					normal.x = dy * 1.0;
36484					normal.y = - dx;
36485					normal.z = dy * 0.0;
36486
36487					prevNormal.copy(normal);
36488
36489					normal.normalize();
36490
36491					initNormals.push(normal.x, normal.y, normal.z);
36492
36493					break;
36494
36495				case (points.length - 1):	// special handling for last Vertex on path
36496
36497					initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z);
36498
36499					break;
36500
36501				default:			// default handling for all vertices in between
36502
36503					dx = points[j + 1].x - points[j].x;
36504					dy = points[j + 1].y - points[j].y;
36505
36506					normal.x = dy * 1.0;
36507					normal.y = - dx;
36508					normal.z = dy * 0.0;
36509
36510					curNormal.copy(normal);
36511
36512					normal.x += prevNormal.x;
36513					normal.y += prevNormal.y;
36514					normal.z += prevNormal.z;
36515
36516					normal.normalize();
36517
36518					initNormals.push(normal.x, normal.y, normal.z);
36519
36520					prevNormal.copy(curNormal);
36521
36522			}
36523
36524		}
36525
36526		// generate vertices, uvs and normals
36527
36528		for (let i = 0; i <= segments; i++) {
36529
36530			const phi = phiStart + i * inverseSegments * phiLength;
36531
36532			const sin = Math.sin(phi);
36533			const cos = Math.cos(phi);
36534
36535			for (let j = 0; j <= (points.length - 1); j++) {
36536
36537				// vertex
36538
36539				vertex.x = points[j].x * sin;
36540				vertex.y = points[j].y;
36541				vertex.z = points[j].x * cos;
36542
36543				vertices.push(vertex.x, vertex.y, vertex.z);
36544
36545				// uv
36546
36547				uv.x = i / segments;
36548				uv.y = j / (points.length - 1);
36549
36550				uvs.push(uv.x, uv.y);
36551
36552				// normal
36553
36554				const x = initNormals[3 * j + 0] * sin;
36555				const y = initNormals[3 * j + 1];
36556				const z = initNormals[3 * j + 0] * cos;
36557
36558				normals.push(x, y, z);
36559
36560			}
36561
36562		}
36563
36564		// indices
36565
36566		for (let i = 0; i < segments; i++) {
36567
36568			for (let j = 0; j < (points.length - 1); j++) {
36569
36570				const base = j + i * points.length;
36571
36572				const a = base;
36573				const b = base + points.length;
36574				const c = base + points.length + 1;
36575				const d = base + 1;
36576
36577				// faces
36578
36579				indices.push(a, b, d);
36580				indices.push(c, d, b);
36581
36582			}
36583
36584		}
36585
36586		// build geometry
36587
36588		this.setIndex(indices);
36589		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
36590		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
36591		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
36592
36593	}
36594
36595	copy(source) {
36596
36597		super.copy(source);
36598
36599		this.parameters = Object.assign({}, source.parameters);
36600
36601		return this;
36602
36603	}
36604
36605	static fromJSON(data) {
36606
36607		return new LatheGeometry(data.points, data.segments, data.phiStart, data.phiLength);
36608
36609	}
36610
36611}
36612
36613class CapsuleGeometry extends LatheGeometry {
36614
36615	constructor(radius = 1, length = 1, capSegments = 4, radialSegments = 8) {
36616
36617		const path = new Path();
36618		path.absarc(0, - length / 2, radius, Math.PI * 1.5, 0);
36619		path.absarc(0, length / 2, radius, 0, Math.PI * 0.5);
36620
36621		super(path.getPoints(capSegments), radialSegments);
36622
36623		this.type = 'CapsuleGeometry';
36624
36625		this.parameters = {
36626			radius: radius,
36627			length: length,
36628			capSegments: capSegments,
36629			radialSegments: radialSegments,
36630		};
36631
36632	}
36633
36634	static fromJSON(data) {
36635
36636		return new CapsuleGeometry(data.radius, data.length, data.capSegments, data.radialSegments);
36637
36638	}
36639
36640}
36641
36642class CircleGeometry extends BufferGeometry {
36643
36644	constructor(radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2) {
36645
36646		super();
36647
vendor: 5,120 bytes, lines 36648-36896
36648		this.type = 'CircleGeometry';
36649
36650		this.parameters = {
36651			radius: radius,
36652			segments: segments,
36653			thetaStart: thetaStart,
36654			thetaLength: thetaLength
36655		};
36656
36657		segments = Math.max(3, segments);
36658
36659		// buffers
36660
36661		const indices = [];
36662		const vertices = [];
36663		const normals = [];
36664		const uvs = [];
36665
36666		// helper variables
36667
36668		const vertex = new Vector3();
36669		const uv = new Vector2();
36670
36671		// center point
36672
36673		vertices.push(0, 0, 0);
36674		normals.push(0, 0, 1);
36675		uvs.push(0.5, 0.5);
36676
36677		for (let s = 0, i = 3; s <= segments; s++, i += 3) {
36678
36679			const segment = thetaStart + s / segments * thetaLength;
36680
36681			// vertex
36682
36683			vertex.x = radius * Math.cos(segment);
36684			vertex.y = radius * Math.sin(segment);
36685
36686			vertices.push(vertex.x, vertex.y, vertex.z);
36687
36688			// normal
36689
36690			normals.push(0, 0, 1);
36691
36692			// uvs
36693
36694			uv.x = (vertices[i] / radius + 1) / 2;
36695			uv.y = (vertices[i + 1] / radius + 1) / 2;
36696
36697			uvs.push(uv.x, uv.y);
36698
36699		}
36700
36701		// indices
36702
36703		for (let i = 1; i <= segments; i++) {
36704
36705			indices.push(i, i + 1, 0);
36706
36707		}
36708
36709		// build geometry
36710
36711		this.setIndex(indices);
36712		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
36713		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
36714		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
36715
36716	}
36717
36718	copy(source) {
36719
36720		super.copy(source);
36721
36722		this.parameters = Object.assign({}, source.parameters);
36723
36724		return this;
36725
36726	}
36727
36728	static fromJSON(data) {
36729
36730		return new CircleGeometry(data.radius, data.segments, data.thetaStart, data.thetaLength);
36731
36732	}
36733
36734}
36735
36736class CylinderGeometry extends BufferGeometry {
36737
36738	constructor(radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
36739
36740		super();
36741
36742		this.type = 'CylinderGeometry';
36743
36744		this.parameters = {
36745			radiusTop: radiusTop,
36746			radiusBottom: radiusBottom,
36747			height: height,
36748			radialSegments: radialSegments,
36749			heightSegments: heightSegments,
36750			openEnded: openEnded,
36751			thetaStart: thetaStart,
36752			thetaLength: thetaLength
36753		};
36754
36755		const scope = this;
36756
36757		radialSegments = Math.floor(radialSegments);
36758		heightSegments = Math.floor(heightSegments);
36759
36760		// buffers
36761
36762		const indices = [];
36763		const vertices = [];
36764		const normals = [];
36765		const uvs = [];
36766
36767		// helper variables
36768
36769		let index = 0;
36770		const indexArray = [];
36771		const halfHeight = height / 2;
36772		let groupStart = 0;
36773
36774		// generate geometry
36775
36776		generateTorso();
36777
36778		if (openEnded === false) {
36779
36780			if (radiusTop > 0) generateCap(true);
36781			if (radiusBottom > 0) generateCap(false);
36782
36783		}
36784
36785		// build geometry
36786
36787		this.setIndex(indices);
36788		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
36789		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
36790		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
36791
36792		function generateTorso() {
36793
36794			const normal = new Vector3();
36795			const vertex = new Vector3();
36796
36797			let groupCount = 0;
36798
36799			// this will be used to calculate the normal
36800			const slope = (radiusBottom - radiusTop) / height;
36801
36802			// generate vertices, normals and uvs
36803
36804			for (let y = 0; y <= heightSegments; y++) {
36805
36806				const indexRow = [];
36807
36808				const v = y / heightSegments;
36809
36810				// calculate the radius of the current row
36811
36812				const radius = v * (radiusBottom - radiusTop) + radiusTop;
36813
36814				for (let x = 0; x <= radialSegments; x++) {
36815
36816					const u = x / radialSegments;
36817
36818					const theta = u * thetaLength + thetaStart;
36819
36820					const sinTheta = Math.sin(theta);
36821					const cosTheta = Math.cos(theta);
36822
36823					// vertex
36824
36825					vertex.x = radius * sinTheta;
36826					vertex.y = - v * height + halfHeight;
36827					vertex.z = radius * cosTheta;
36828					vertices.push(vertex.x, vertex.y, vertex.z);
36829
36830					// normal
36831
36832					normal.set(sinTheta, slope, cosTheta).normalize();
36833					normals.push(normal.x, normal.y, normal.z);
36834
36835					// uv
36836
36837					uvs.push(u, 1 - v);
36838
36839					// save index of vertex in respective row
36840
36841					indexRow.push(index++);
36842
36843				}
36844
36845				// now save vertices of the row in our index array
36846
36847				indexArray.push(indexRow);
36848
36849			}
36850
36851			// generate indices
36852
36853			for (let x = 0; x < radialSegments; x++) {
36854
36855				for (let y = 0; y < heightSegments; y++) {
36856
36857					// we use the index array to access the correct indices
36858
36859					const a = indexArray[y][x];
36860					const b = indexArray[y + 1][x];
36861					const c = indexArray[y + 1][x + 1];
36862					const d = indexArray[y][x + 1];
36863
36864					// faces
36865
36866					indices.push(a, b, d);
36867					indices.push(b, c, d);
36868
36869					// update group counter
36870
36871					groupCount += 6;
36872
36873				}
36874
36875			}
36876
36877			// add a group to the geometry. this will ensure multi material support
36878
36879			scope.addGroup(groupStart, groupCount, 0);
36880
36881			// calculate new start value for groups
36882
36883			groupStart += groupCount;
36884
36885		}
36886
36887		function generateCap(top) {
36888
36889			// save the index of the first center vertex
36890			const centerIndexStart = index;
36891
36892			const uv = new Vector2();
36893			const vertex = new Vector3();
36894
36895			let groupCount = 0;
36896
vendor: 16,422 bytes, lines 36897-37688
36897			const radius = (top === true) ? radiusTop : radiusBottom;
36898			const sign = (top === true) ? 1 : - 1;
36899
36900			// first we generate the center vertex data of the cap.
36901			// because the geometry needs one set of uvs per face,
36902			// we must generate a center vertex per face/segment
36903
36904			for (let x = 1; x <= radialSegments; x++) {
36905
36906				// vertex
36907
36908				vertices.push(0, halfHeight * sign, 0);
36909
36910				// normal
36911
36912				normals.push(0, sign, 0);
36913
36914				// uv
36915
36916				uvs.push(0.5, 0.5);
36917
36918				// increase index
36919
36920				index++;
36921
36922			}
36923
36924			// save the index of the last center vertex
36925			const centerIndexEnd = index;
36926
36927			// now we generate the surrounding vertices, normals and uvs
36928
36929			for (let x = 0; x <= radialSegments; x++) {
36930
36931				const u = x / radialSegments;
36932				const theta = u * thetaLength + thetaStart;
36933
36934				const cosTheta = Math.cos(theta);
36935				const sinTheta = Math.sin(theta);
36936
36937				// vertex
36938
36939				vertex.x = radius * sinTheta;
36940				vertex.y = halfHeight * sign;
36941				vertex.z = radius * cosTheta;
36942				vertices.push(vertex.x, vertex.y, vertex.z);
36943
36944				// normal
36945
36946				normals.push(0, sign, 0);
36947
36948				// uv
36949
36950				uv.x = (cosTheta * 0.5) + 0.5;
36951				uv.y = (sinTheta * 0.5 * sign) + 0.5;
36952				uvs.push(uv.x, uv.y);
36953
36954				// increase index
36955
36956				index++;
36957
36958			}
36959
36960			// generate indices
36961
36962			for (let x = 0; x < radialSegments; x++) {
36963
36964				const c = centerIndexStart + x;
36965				const i = centerIndexEnd + x;
36966
36967				if (top === true) {
36968
36969					// face top
36970
36971					indices.push(i, i + 1, c);
36972
36973				} else {
36974
36975					// face bottom
36976
36977					indices.push(i + 1, i, c);
36978
36979				}
36980
36981				groupCount += 3;
36982
36983			}
36984
36985			// add a group to the geometry. this will ensure multi material support
36986
36987			scope.addGroup(groupStart, groupCount, top === true ? 1 : 2);
36988
36989			// calculate new start value for groups
36990
36991			groupStart += groupCount;
36992
36993		}
36994
36995	}
36996
36997	copy(source) {
36998
36999		super.copy(source);
37000
37001		this.parameters = Object.assign({}, source.parameters);
37002
37003		return this;
37004
37005	}
37006
37007	static fromJSON(data) {
37008
37009		return new CylinderGeometry(data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength);
37010
37011	}
37012
37013}
37014
37015class ConeGeometry extends CylinderGeometry {
37016
37017	constructor(radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
37018
37019		super(0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength);
37020
37021		this.type = 'ConeGeometry';
37022
37023		this.parameters = {
37024			radius: radius,
37025			height: height,
37026			radialSegments: radialSegments,
37027			heightSegments: heightSegments,
37028			openEnded: openEnded,
37029			thetaStart: thetaStart,
37030			thetaLength: thetaLength
37031		};
37032
37033	}
37034
37035	static fromJSON(data) {
37036
37037		return new ConeGeometry(data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength);
37038
37039	}
37040
37041}
37042
37043class PolyhedronGeometry extends BufferGeometry {
37044
37045	constructor(vertices = [], indices = [], radius = 1, detail = 0) {
37046
37047		super();
37048
37049		this.type = 'PolyhedronGeometry';
37050
37051		this.parameters = {
37052			vertices: vertices,
37053			indices: indices,
37054			radius: radius,
37055			detail: detail
37056		};
37057
37058		// default buffer data
37059
37060		const vertexBuffer = [];
37061		const uvBuffer = [];
37062
37063		// the subdivision creates the vertex buffer data
37064
37065		subdivide(detail);
37066
37067		// all vertices should lie on a conceptual sphere with a given radius
37068
37069		applyRadius(radius);
37070
37071		// finally, create the uv data
37072
37073		generateUVs();
37074
37075		// build non-indexed geometry
37076
37077		this.setAttribute('position', new Float32BufferAttribute(vertexBuffer, 3));
37078		this.setAttribute('normal', new Float32BufferAttribute(vertexBuffer.slice(), 3));
37079		this.setAttribute('uv', new Float32BufferAttribute(uvBuffer, 2));
37080
37081		if (detail === 0) {
37082
37083			this.computeVertexNormals(); // flat normals
37084
37085		} else {
37086
37087			this.normalizeNormals(); // smooth normals
37088
37089		}
37090
37091		// helper functions
37092
37093		function subdivide(detail) {
37094
37095			const a = new Vector3();
37096			const b = new Vector3();
37097			const c = new Vector3();
37098
37099			// iterate over all faces and apply a subdivision with the given detail value
37100
37101			for (let i = 0; i < indices.length; i += 3) {
37102
37103				// get the vertices of the face
37104
37105				getVertexByIndex(indices[i + 0], a);
37106				getVertexByIndex(indices[i + 1], b);
37107				getVertexByIndex(indices[i + 2], c);
37108
37109				// perform subdivision
37110
37111				subdivideFace(a, b, c, detail);
37112
37113			}
37114
37115		}
37116
37117		function subdivideFace(a, b, c, detail) {
37118
37119			const cols = detail + 1;
37120
37121			// we use this multidimensional array as a data structure for creating the subdivision
37122
37123			const v = [];
37124
37125			// construct all of the vertices for this subdivision
37126
37127			for (let i = 0; i <= cols; i++) {
37128
37129				v[i] = [];
37130
37131				const aj = a.clone().lerp(c, i / cols);
37132				const bj = b.clone().lerp(c, i / cols);
37133
37134				const rows = cols - i;
37135
37136				for (let j = 0; j <= rows; j++) {
37137
37138					if (j === 0 && i === cols) {
37139
37140						v[i][j] = aj;
37141
37142					} else {
37143
37144						v[i][j] = aj.clone().lerp(bj, j / rows);
37145
37146					}
37147
37148				}
37149
37150			}
37151
37152			// construct all of the faces
37153
37154			for (let i = 0; i < cols; i++) {
37155
37156				for (let j = 0; j < 2 * (cols - i) - 1; j++) {
37157
37158					const k = Math.floor(j / 2);
37159
37160					if (j % 2 === 0) {
37161
37162						pushVertex(v[i][k + 1]);
37163						pushVertex(v[i + 1][k]);
37164						pushVertex(v[i][k]);
37165
37166					} else {
37167
37168						pushVertex(v[i][k + 1]);
37169						pushVertex(v[i + 1][k + 1]);
37170						pushVertex(v[i + 1][k]);
37171
37172					}
37173
37174				}
37175
37176			}
37177
37178		}
37179
37180		function applyRadius(radius) {
37181
37182			const vertex = new Vector3();
37183
37184			// iterate over the entire buffer and apply the radius to each vertex
37185
37186			for (let i = 0; i < vertexBuffer.length; i += 3) {
37187
37188				vertex.x = vertexBuffer[i + 0];
37189				vertex.y = vertexBuffer[i + 1];
37190				vertex.z = vertexBuffer[i + 2];
37191
37192				vertex.normalize().multiplyScalar(radius);
37193
37194				vertexBuffer[i + 0] = vertex.x;
37195				vertexBuffer[i + 1] = vertex.y;
37196				vertexBuffer[i + 2] = vertex.z;
37197
37198			}
37199
37200		}
37201
37202		function generateUVs() {
37203
37204			const vertex = new Vector3();
37205
37206			for (let i = 0; i < vertexBuffer.length; i += 3) {
37207
37208				vertex.x = vertexBuffer[i + 0];
37209				vertex.y = vertexBuffer[i + 1];
37210				vertex.z = vertexBuffer[i + 2];
37211
37212				const u = azimuth(vertex) / 2 / Math.PI + 0.5;
37213				const v = inclination(vertex) / Math.PI + 0.5;
37214				uvBuffer.push(u, 1 - v);
37215
37216			}
37217
37218			correctUVs();
37219
37220			correctSeam();
37221
37222		}
37223
37224		function correctSeam() {
37225
37226			// handle case when face straddles the seam, see #3269
37227
37228			for (let i = 0; i < uvBuffer.length; i += 6) {
37229
37230				// uv data of a single face
37231
37232				const x0 = uvBuffer[i + 0];
37233				const x1 = uvBuffer[i + 2];
37234				const x2 = uvBuffer[i + 4];
37235
37236				const max = Math.max(x0, x1, x2);
37237				const min = Math.min(x0, x1, x2);
37238
37239				// 0.9 is somewhat arbitrary
37240
37241				if (max > 0.9 && min < 0.1) {
37242
37243					if (x0 < 0.2) uvBuffer[i + 0] += 1;
37244					if (x1 < 0.2) uvBuffer[i + 2] += 1;
37245					if (x2 < 0.2) uvBuffer[i + 4] += 1;
37246
37247				}
37248
37249			}
37250
37251		}
37252
37253		function pushVertex(vertex) {
37254
37255			vertexBuffer.push(vertex.x, vertex.y, vertex.z);
37256
37257		}
37258
37259		function getVertexByIndex(index, vertex) {
37260
37261			const stride = index * 3;
37262
37263			vertex.x = vertices[stride + 0];
37264			vertex.y = vertices[stride + 1];
37265			vertex.z = vertices[stride + 2];
37266
37267		}
37268
37269		function correctUVs() {
37270
37271			const a = new Vector3();
37272			const b = new Vector3();
37273			const c = new Vector3();
37274
37275			const centroid = new Vector3();
37276
37277			const uvA = new Vector2();
37278			const uvB = new Vector2();
37279			const uvC = new Vector2();
37280
37281			for (let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6) {
37282
37283				a.set(vertexBuffer[i + 0], vertexBuffer[i + 1], vertexBuffer[i + 2]);
37284				b.set(vertexBuffer[i + 3], vertexBuffer[i + 4], vertexBuffer[i + 5]);
37285				c.set(vertexBuffer[i + 6], vertexBuffer[i + 7], vertexBuffer[i + 8]);
37286
37287				uvA.set(uvBuffer[j + 0], uvBuffer[j + 1]);
37288				uvB.set(uvBuffer[j + 2], uvBuffer[j + 3]);
37289				uvC.set(uvBuffer[j + 4], uvBuffer[j + 5]);
37290
37291				centroid.copy(a).add(b).add(c).divideScalar(3);
37292
37293				const azi = azimuth(centroid);
37294
37295				correctUV(uvA, j + 0, a, azi);
37296				correctUV(uvB, j + 2, b, azi);
37297				correctUV(uvC, j + 4, c, azi);
37298
37299			}
37300
37301		}
37302
37303		function correctUV(uv, stride, vector, azimuth) {
37304
37305			if ((azimuth < 0) && (uv.x === 1)) {
37306
37307				uvBuffer[stride] = uv.x - 1;
37308
37309			}
37310
37311			if ((vector.x === 0) && (vector.z === 0)) {
37312
37313				uvBuffer[stride] = azimuth / 2 / Math.PI + 0.5;
37314
37315			}
37316
37317		}
37318
37319		// Angle around the Y axis, counter-clockwise when looking from above.
37320
37321		function azimuth(vector) {
37322
37323			return Math.atan2(vector.z, - vector.x);
37324
37325		}
37326
37327
37328		// Angle above the XZ plane.
37329
37330		function inclination(vector) {
37331
37332			return Math.atan2(- vector.y, Math.sqrt((vector.x * vector.x) + (vector.z * vector.z)));
37333
37334		}
37335
37336	}
37337
37338	copy(source) {
37339
37340		super.copy(source);
37341
37342		this.parameters = Object.assign({}, source.parameters);
37343
37344		return this;
37345
37346	}
37347
37348	static fromJSON(data) {
37349
37350		return new PolyhedronGeometry(data.vertices, data.indices, data.radius, data.details);
37351
37352	}
37353
37354}
37355
37356class DodecahedronGeometry extends PolyhedronGeometry {
37357
37358	constructor(radius = 1, detail = 0) {
37359
37360		const t = (1 + Math.sqrt(5)) / 2;
37361		const r = 1 / t;
37362
37363		const vertices = [
37364
37365			// (±1, ±1, ±1)
37366			- 1, - 1, - 1, - 1, - 1, 1,
37367			- 1, 1, - 1, - 1, 1, 1,
37368			1, - 1, - 1, 1, - 1, 1,
37369			1, 1, - 1, 1, 1, 1,
37370
37371			// (0, ±1/φ, ±φ)
37372			0, - r, - t, 0, - r, t,
37373			0, r, - t, 0, r, t,
37374
37375			// (±1/φ, ±φ, 0)
37376			- r, - t, 0, - r, t, 0,
37377			r, - t, 0, r, t, 0,
37378
37379			// (±φ, 0, ±1/φ)
37380			- t, 0, - r, t, 0, - r,
37381			- t, 0, r, t, 0, r
37382		];
37383
37384		const indices = [
37385			3, 11, 7, 3, 7, 15, 3, 15, 13,
37386			7, 19, 17, 7, 17, 6, 7, 6, 15,
37387			17, 4, 8, 17, 8, 10, 17, 10, 6,
37388			8, 0, 16, 8, 16, 2, 8, 2, 10,
37389			0, 12, 1, 0, 1, 18, 0, 18, 16,
37390			6, 10, 2, 6, 2, 13, 6, 13, 15,
37391			2, 16, 18, 2, 18, 3, 2, 3, 13,
37392			18, 1, 9, 18, 9, 11, 18, 11, 3,
37393			4, 14, 12, 4, 12, 0, 4, 0, 8,
37394			11, 9, 5, 11, 5, 19, 11, 19, 7,
37395			19, 5, 14, 19, 14, 4, 19, 4, 17,
37396			1, 12, 14, 1, 14, 5, 1, 5, 9
37397		];
37398
37399		super(vertices, indices, radius, detail);
37400
37401		this.type = 'DodecahedronGeometry';
37402
37403		this.parameters = {
37404			radius: radius,
37405			detail: detail
37406		};
37407
37408	}
37409
37410	static fromJSON(data) {
37411
37412		return new DodecahedronGeometry(data.radius, data.detail);
37413
37414	}
37415
37416}
37417
37418const _v0 = /*@__PURE__*/ new Vector3();
37419const _v1$1 = /*@__PURE__*/ new Vector3();
37420const _normal = /*@__PURE__*/ new Vector3();
37421const _triangle = /*@__PURE__*/ new Triangle();
37422
37423class EdgesGeometry extends BufferGeometry {
37424
37425	constructor(geometry = null, thresholdAngle = 1) {
37426
37427		super();
37428
37429		this.type = 'EdgesGeometry';
37430
37431		this.parameters = {
37432			geometry: geometry,
37433			thresholdAngle: thresholdAngle
37434		};
37435
37436		if (geometry !== null) {
37437
37438			const precisionPoints = 4;
37439			const precision = Math.pow(10, precisionPoints);
37440			const thresholdDot = Math.cos(DEG2RAD * thresholdAngle);
37441
37442			const indexAttr = geometry.getIndex();
37443			const positionAttr = geometry.getAttribute('position');
37444			const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
37445
37446			const indexArr = [0, 0, 0];
37447			const vertKeys = ['a', 'b', 'c'];
37448			const hashes = new Array(3);
37449
37450			const edgeData = {};
37451			const vertices = [];
37452			for (let i = 0; i < indexCount; i += 3) {
37453
37454				if (indexAttr) {
37455
37456					indexArr[0] = indexAttr.getX(i);
37457					indexArr[1] = indexAttr.getX(i + 1);
37458					indexArr[2] = indexAttr.getX(i + 2);
37459
37460				} else {
37461
37462					indexArr[0] = i;
37463					indexArr[1] = i + 1;
37464					indexArr[2] = i + 2;
37465
37466				}
37467
37468				const { a, b, c } = _triangle;
37469				a.fromBufferAttribute(positionAttr, indexArr[0]);
37470				b.fromBufferAttribute(positionAttr, indexArr[1]);
37471				c.fromBufferAttribute(positionAttr, indexArr[2]);
37472				_triangle.getNormal(_normal);
37473
37474				// create hashes for the edge from the vertices
37475				hashes[0] = `${Math.round(a.x * precision)},${Math.round(a.y * precision)},${Math.round(a.z * precision)}`;
37476				hashes[1] = `${Math.round(b.x * precision)},${Math.round(b.y * precision)},${Math.round(b.z * precision)}`;
37477				hashes[2] = `${Math.round(c.x * precision)},${Math.round(c.y * precision)},${Math.round(c.z * precision)}`;
37478
37479				// skip degenerate triangles
37480				if (hashes[0] === hashes[1] || hashes[1] === hashes[2] || hashes[2] === hashes[0]) {
37481
37482					continue;
37483
37484				}
37485
37486				// iterate over every edge
37487				for (let j = 0; j < 3; j++) {
37488
37489					// get the first and next vertex making up the edge
37490					const jNext = (j + 1) % 3;
37491					const vecHash0 = hashes[j];
37492					const vecHash1 = hashes[jNext];
37493					const v0 = _triangle[vertKeys[j]];
37494					const v1 = _triangle[vertKeys[jNext]];
37495
37496					const hash = `${vecHash0}_${vecHash1}`;
37497					const reverseHash = `${vecHash1}_${vecHash0}`;
37498
37499					if (reverseHash in edgeData && edgeData[reverseHash]) {
37500
37501						// if we found a sibling edge add it into the vertex array if
37502						// it meets the angle threshold and delete the edge from the map.
37503						if (_normal.dot(edgeData[reverseHash].normal) <= thresholdDot) {
37504
37505							vertices.push(v0.x, v0.y, v0.z);
37506							vertices.push(v1.x, v1.y, v1.z);
37507
37508						}
37509
37510						edgeData[reverseHash] = null;
37511
37512					} else if (!(hash in edgeData)) {
37513
37514						// if we've already got an edge here then skip adding a new one
37515						edgeData[hash] = {
37516
37517							index0: indexArr[j],
37518							index1: indexArr[jNext],
37519							normal: _normal.clone(),
37520
37521						};
37522
37523					}
37524
37525				}
37526
37527			}
37528
37529			// iterate over all remaining, unmatched edges and add them to the vertex array
37530			for (const key in edgeData) {
37531
37532				if (edgeData[key]) {
37533
37534					const { index0, index1 } = edgeData[key];
37535					_v0.fromBufferAttribute(positionAttr, index0);
37536					_v1$1.fromBufferAttribute(positionAttr, index1);
37537
37538					vertices.push(_v0.x, _v0.y, _v0.z);
37539					vertices.push(_v1$1.x, _v1$1.y, _v1$1.z);
37540
37541				}
37542
37543			}
37544
37545			this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
37546
37547		}
37548
37549	}
37550
37551	copy(source) {
37552
37553		super.copy(source);
37554
37555		this.parameters = Object.assign({}, source.parameters);
37556
37557		return this;
37558
37559	}
37560
37561}
37562
37563class Shape extends Path {
37564
37565	constructor(points) {
37566
37567		super(points);
37568
37569		this.uuid = generateUUID();
37570
37571		this.type = 'Shape';
37572
37573		this.holes = [];
37574
37575	}
37576
37577	getPointsHoles(divisions) {
37578
37579		const holesPts = [];
37580
37581		for (let i = 0, l = this.holes.length; i < l; i++) {
37582
37583			holesPts[i] = this.holes[i].getPoints(divisions);
37584
37585		}
37586
37587		return holesPts;
37588
37589	}
37590
37591	// get points of shape and holes (keypoints based on segments parameter)
37592
37593	extractPoints(divisions) {
37594
37595		return {
37596
37597			shape: this.getPoints(divisions),
37598			holes: this.getPointsHoles(divisions)
37599
37600		};
37601
37602	}
37603
37604	copy(source) {
37605
37606		super.copy(source);
37607
37608		this.holes = [];
37609
37610		for (let i = 0, l = source.holes.length; i < l; i++) {
37611
37612			const hole = source.holes[i];
37613
37614			this.holes.push(hole.clone());
37615
37616		}
37617
37618		return this;
37619
37620	}
37621
37622	toJSON() {
37623
37624		const data = super.toJSON();
37625
37626		data.uuid = this.uuid;
37627		data.holes = [];
37628
37629		for (let i = 0, l = this.holes.length; i < l; i++) {
37630
37631			const hole = this.holes[i];
37632			data.holes.push(hole.toJSON());
37633
37634		}
37635
37636		return data;
37637
37638	}
37639
37640	fromJSON(json) {
37641
37642		super.fromJSON(json);
37643
37644		this.uuid = json.uuid;
37645		this.holes = [];
37646
37647		for (let i = 0, l = json.holes.length; i < l; i++) {
37648
37649			const hole = json.holes[i];
37650			this.holes.push(new Path().fromJSON(hole));
37651
37652		}
37653
37654		return this;
37655
37656	}
37657
37658}
37659
37660/**
37661 * Port from https://github.com/mapbox/earcut (v2.2.4)
37662 */
37663
37664const Earcut = {
37665
37666	triangulate: function (data, holeIndices, dim = 2) {
37667
37668		const hasHoles = holeIndices && holeIndices.length;
37669		const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
37670		let outerNode = linkedList(data, 0, outerLen, dim, true);
37671		const triangles = [];
37672
37673		if (!outerNode || outerNode.next === outerNode.prev) return triangles;
37674
37675		let minX, minY, maxX, maxY, x, y, invSize;
37676
37677		if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
37678
37679		// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
37680		if (data.length > 80 * dim) {
37681
37682			minX = maxX = data[0];
37683			minY = maxY = data[1];
37684
37685			for (let i = dim; i < outerLen; i += dim) {
37686
37687				x = data[i];
37688				y = data[i + 1];
vendor: 13,292 bytes, lines 37689-38274
37689				if (x < minX) minX = x;
37690				if (y < minY) minY = y;
37691				if (x > maxX) maxX = x;
37692				if (y > maxY) maxY = y;
37693
37694			}
37695
37696			// minX, minY and invSize are later used to transform coords into integers for z-order calculation
37697			invSize = Math.max(maxX - minX, maxY - minY);
37698			invSize = invSize !== 0 ? 32767 / invSize : 0;
37699
37700		}
37701
37702		earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
37703
37704		return triangles;
37705
37706	}
37707
37708};
37709
37710// create a circular doubly linked list from polygon points in the specified winding order
37711function linkedList(data, start, end, dim, clockwise) {
37712
37713	let i, last;
37714
37715	if (clockwise === (signedArea(data, start, end, dim) > 0)) {
37716
37717		for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
37718
37719	} else {
37720
37721		for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
37722
37723	}
37724
37725	if (last && equals(last, last.next)) {
37726
37727		removeNode(last);
37728		last = last.next;
37729
37730	}
37731
37732	return last;
37733
37734}
37735
37736// eliminate colinear or duplicate points
37737function filterPoints(start, end) {
37738
37739	if (!start) return start;
37740	if (!end) end = start;
37741
37742	let p = start,
37743		again;
37744	do {
37745
37746		again = false;
37747
37748		if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
37749
37750			removeNode(p);
37751			p = end = p.prev;
37752			if (p === p.next) break;
37753			again = true;
37754
37755		} else {
37756
37757			p = p.next;
37758
37759		}
37760
37761	} while (again || p !== end);
37762
37763	return end;
37764
37765}
37766
37767// main ear slicing loop which triangulates a polygon (given as a linked list)
37768function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
37769
37770	if (!ear) return;
37771
37772	// interlink polygon nodes in z-order
37773	if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
37774
37775	let stop = ear,
37776		prev, next;
37777
37778	// iterate through ears, slicing them one by one
37779	while (ear.prev !== ear.next) {
37780
37781		prev = ear.prev;
37782		next = ear.next;
37783
37784		if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
37785
37786			// cut off the triangle
37787			triangles.push(prev.i / dim | 0);
37788			triangles.push(ear.i / dim | 0);
37789			triangles.push(next.i / dim | 0);
37790
37791			removeNode(ear);
37792
37793			// skipping the next vertex leads to less sliver triangles
37794			ear = next.next;
37795			stop = next.next;
37796
37797			continue;
37798
37799		}
37800
37801		ear = next;
37802
37803		// if we looped through the whole remaining polygon and can't find any more ears
37804		if (ear === stop) {
37805
37806			// try filtering points and slicing again
37807			if (!pass) {
37808
37809				earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
37810
37811				// if this didn't work, try curing all small self-intersections locally
37812
37813			} else if (pass === 1) {
37814
37815				ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
37816				earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
37817
37818				// as a last resort, try splitting the remaining polygon into two
37819
37820			} else if (pass === 2) {
37821
37822				splitEarcut(ear, triangles, dim, minX, minY, invSize);
37823
37824			}
37825
37826			break;
37827
37828		}
37829
37830	}
37831
37832}
37833
37834// check whether a polygon node forms a valid ear with adjacent nodes
37835function isEar(ear) {
37836
37837	const a = ear.prev,
37838		b = ear,
37839		c = ear.next;
37840
37841	if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
37842
37843	// now make sure we don't have other points inside the potential ear
37844	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
37845
37846	// triangle bbox; min & max are calculated like this for speed
37847	const x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),
37848		y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),
37849		x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),
37850		y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);
37851
37852	let p = c.next;
37853	while (p !== a) {
37854
37855		if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
37856			pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) &&
37857			area(p.prev, p, p.next) >= 0) return false;
37858		p = p.next;
37859
37860	}
37861
37862	return true;
37863
37864}
37865
37866function isEarHashed(ear, minX, minY, invSize) {
37867
37868	const a = ear.prev,
37869		b = ear,
37870		c = ear.next;
37871
37872	if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
37873
37874	const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
37875
37876	// triangle bbox; min & max are calculated like this for speed
37877	const x0 = ax < bx ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx),
37878		y0 = ay < by ? (ay < cy ? ay : cy) : (by < cy ? by : cy),
37879		x1 = ax > bx ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx),
37880		y1 = ay > by ? (ay > cy ? ay : cy) : (by > cy ? by : cy);
37881
37882	// z-order range for the current triangle bbox;
37883	const minZ = zOrder(x0, y0, minX, minY, invSize),
37884		maxZ = zOrder(x1, y1, minX, minY, invSize);
37885
37886	let p = ear.prevZ,
37887		n = ear.nextZ;
37888
37889	// look for points inside the triangle in both directions
37890	while (p && p.z >= minZ && n && n.z <= maxZ) {
37891
37892		if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
37893			pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
37894		p = p.prevZ;
37895
37896		if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
37897			pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
37898		n = n.nextZ;
37899
37900	}
37901
37902	// look for remaining points in decreasing z-order
37903	while (p && p.z >= minZ) {
37904
37905		if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
37906			pointInTriangle(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
37907		p = p.prevZ;
37908
37909	}
37910
37911	// look for remaining points in increasing z-order
37912	while (n && n.z <= maxZ) {
37913
37914		if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
37915			pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
37916		n = n.nextZ;
37917
37918	}
37919
37920	return true;
37921
37922}
37923
37924// go through all polygon nodes and cure small local self-intersections
37925function cureLocalIntersections(start, triangles, dim) {
37926
37927	let p = start;
37928	do {
37929
37930		const a = p.prev,
37931			b = p.next.next;
37932
37933		if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
37934
37935			triangles.push(a.i / dim | 0);
37936			triangles.push(p.i / dim | 0);
37937			triangles.push(b.i / dim | 0);
37938
37939			// remove two nodes involved
37940			removeNode(p);
37941			removeNode(p.next);
37942
37943			p = start = b;
37944
37945		}
37946
37947		p = p.next;
37948
37949	} while (p !== start);
37950
37951	return filterPoints(p);
37952
37953}
37954
37955// try splitting polygon into two and triangulate them independently
37956function splitEarcut(start, triangles, dim, minX, minY, invSize) {
37957
37958	// look for a valid diagonal that divides the polygon into two
37959	let a = start;
37960	do {
37961
37962		let b = a.next.next;
37963		while (b !== a.prev) {
37964
37965			if (a.i !== b.i && isValidDiagonal(a, b)) {
37966
37967				// split the polygon in two by the diagonal
37968				let c = splitPolygon(a, b);
37969
37970				// filter colinear points around the cuts
37971				a = filterPoints(a, a.next);
37972				c = filterPoints(c, c.next);
37973
37974				// run earcut on each half
37975				earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
37976				earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
37977				return;
37978
37979			}
37980
37981			b = b.next;
37982
37983		}
37984
37985		a = a.next;
37986
37987	} while (a !== start);
37988
37989}
37990
37991// link every hole into the outer loop, producing a single-ring polygon without holes
37992function eliminateHoles(data, holeIndices, outerNode, dim) {
37993
37994	const queue = [];
37995	let i, len, start, end, list;
37996
37997	for (i = 0, len = holeIndices.length; i < len; i++) {
37998
37999		start = holeIndices[i] * dim;
38000		end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
38001		list = linkedList(data, start, end, dim, false);
38002		if (list === list.next) list.steiner = true;
38003		queue.push(getLeftmost(list));
38004
38005	}
38006
38007	queue.sort(compareX);
38008
38009	// process holes from left to right
38010	for (i = 0; i < queue.length; i++) {
38011
38012		outerNode = eliminateHole(queue[i], outerNode);
38013
38014	}
38015
38016	return outerNode;
38017
38018}
38019
38020function compareX(a, b) {
38021
38022	return a.x - b.x;
38023
38024}
38025
38026// find a bridge between vertices that connects hole with an outer ring and link it
38027function eliminateHole(hole, outerNode) {
38028
38029	const bridge = findHoleBridge(hole, outerNode);
38030	if (!bridge) {
38031
38032		return outerNode;
38033
38034	}
38035
38036	const bridgeReverse = splitPolygon(bridge, hole);
38037
38038	// filter collinear points around the cuts
38039	filterPoints(bridgeReverse, bridgeReverse.next);
38040	return filterPoints(bridge, bridge.next);
38041
38042}
38043
38044// David Eberly's algorithm for finding a bridge between hole and outer polygon
38045function findHoleBridge(hole, outerNode) {
38046
38047	let p = outerNode,
38048		qx = - Infinity,
38049		m;
38050
38051	const hx = hole.x, hy = hole.y;
38052
38053	// find a segment intersected by a ray from the hole's leftmost point to the left;
38054	// segment's endpoint with lesser x will be potential connection point
38055	do {
38056
38057		if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
38058
38059			const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
38060			if (x <= hx && x > qx) {
38061
38062				qx = x;
38063				m = p.x < p.next.x ? p : p.next;
38064				if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
38065
38066			}
38067
38068		}
38069
38070		p = p.next;
38071
38072	} while (p !== outerNode);
38073
38074	if (!m) return null;
38075
38076	// look for points inside the triangle of hole point, segment intersection and endpoint;
38077	// if there are no points found, we have a valid connection;
38078	// otherwise choose the point of the minimum angle with the ray as connection point
38079
38080	const stop = m,
38081		mx = m.x,
38082		my = m.y;
38083	let tanMin = Infinity, tan;
38084
38085	p = m;
38086
38087	do {
38088
38089		if (hx >= p.x && p.x >= mx && hx !== p.x &&
38090			pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
38091
38092			tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
38093
38094			if (locallyInside(p, hole) && (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
38095
38096				m = p;
38097				tanMin = tan;
38098
38099			}
38100
38101		}
38102
38103		p = p.next;
38104
38105	} while (p !== stop);
38106
38107	return m;
38108
38109}
38110
38111// whether sector in vertex m contains sector in vertex p in the same coordinates
38112function sectorContainsSector(m, p) {
38113
38114	return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
38115
38116}
38117
38118// interlink polygon nodes in z-order
38119function indexCurve(start, minX, minY, invSize) {
38120
38121	let p = start;
38122	do {
38123
38124		if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
38125		p.prevZ = p.prev;
38126		p.nextZ = p.next;
38127		p = p.next;
38128
38129	} while (p !== start);
38130
38131	p.prevZ.nextZ = null;
38132	p.prevZ = null;
38133
38134	sortLinked(p);
38135
38136}
38137
38138// Simon Tatham's linked list merge sort algorithm
38139// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
38140function sortLinked(list) {
38141
38142	let i, p, q, e, tail, numMerges, pSize, qSize,
38143		inSize = 1;
38144
38145	do {
38146
38147		p = list;
38148		list = null;
38149		tail = null;
38150		numMerges = 0;
38151
38152		while (p) {
38153
38154			numMerges++;
38155			q = p;
38156			pSize = 0;
38157			for (i = 0; i < inSize; i++) {
38158
38159				pSize++;
38160				q = q.nextZ;
38161				if (!q) break;
38162
38163			}
38164
38165			qSize = inSize;
38166
38167			while (pSize > 0 || (qSize > 0 && q)) {
38168
38169				if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
38170
38171					e = p;
38172					p = p.nextZ;
38173					pSize--;
38174
38175				} else {
38176
38177					e = q;
38178					q = q.nextZ;
38179					qSize--;
38180
38181				}
38182
38183				if (tail) tail.nextZ = e;
38184				else list = e;
38185
38186				e.prevZ = tail;
38187				tail = e;
38188
38189			}
38190
38191			p = q;
38192
38193		}
38194
38195		tail.nextZ = null;
38196		inSize *= 2;
38197
38198	} while (numMerges > 1);
38199
38200	return list;
38201
38202}
38203
38204// z-order of a point given coords and inverse of the longer side of data bbox
38205function zOrder(x, y, minX, minY, invSize) {
38206
38207	// coords are transformed into non-negative 15-bit integer range
38208	x = (x - minX) * invSize | 0;
38209	y = (y - minY) * invSize | 0;
38210
38211	x = (x | (x << 8)) & 0x00FF00FF;
38212	x = (x | (x << 4)) & 0x0F0F0F0F;
38213	x = (x | (x << 2)) & 0x33333333;
38214	x = (x | (x << 1)) & 0x55555555;
38215
38216	y = (y | (y << 8)) & 0x00FF00FF;
38217	y = (y | (y << 4)) & 0x0F0F0F0F;
38218	y = (y | (y << 2)) & 0x33333333;
38219	y = (y | (y << 1)) & 0x55555555;
38220
38221	return x | (y << 1);
38222
38223}
38224
38225// find the leftmost node of a polygon ring
38226function getLeftmost(start) {
38227
38228	let p = start,
38229		leftmost = start;
38230	do {
38231
38232		if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;
38233		p = p.next;
38234
38235	} while (p !== start);
38236
38237	return leftmost;
38238
38239}
38240
38241// check if a point lies within a convex triangle
38242function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
38243
38244	return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
38245		(ax - px) * (by - py) >= (bx - px) * (ay - py) &&
38246		(bx - px) * (cy - py) >= (cx - px) * (by - py);
38247
38248}
38249
38250// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
38251function isValidDiagonal(a, b) {
38252
38253	return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
38254		(locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
38255			(area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
38256			equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case
38257
38258}
38259
38260// signed area of a triangle
38261function area(p, q, r) {
38262
38263	return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
38264
38265}
38266
38267// check if two points are equal
38268function equals(p1, p2) {
38269
38270	return p1.x === p2.x && p1.y === p2.y;
38271
38272}
38273
38274// check if two segments intersect
vendor: 7,761 bytes, lines 38275-38622
38275function intersects(p1, q1, p2, q2) {
38276
38277	const o1 = sign(area(p1, q1, p2));
38278	const o2 = sign(area(p1, q1, q2));
38279	const o3 = sign(area(p2, q2, p1));
38280	const o4 = sign(area(p2, q2, q1));
38281
38282	if (o1 !== o2 && o3 !== o4) return true; // general case
38283
38284	if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
38285	if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
38286	if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
38287	if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
38288
38289	return false;
38290
38291}
38292
38293// for collinear points p, q, r, check if point q lies on segment pr
38294function onSegment(p, q, r) {
38295
38296	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);
38297
38298}
38299
38300function sign(num) {
38301
38302	return num > 0 ? 1 : num < 0 ? - 1 : 0;
38303
38304}
38305
38306// check if a polygon diagonal intersects any polygon segments
38307function intersectsPolygon(a, b) {
38308
38309	let p = a;
38310	do {
38311
38312		if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
38313			intersects(p, p.next, a, b)) return true;
38314		p = p.next;
38315
38316	} while (p !== a);
38317
38318	return false;
38319
38320}
38321
38322// check if a polygon diagonal is locally inside the polygon
38323function locallyInside(a, b) {
38324
38325	return area(a.prev, a, a.next) < 0 ?
38326		area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
38327		area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
38328
38329}
38330
38331// check if the middle point of a polygon diagonal is inside the polygon
38332function middleInside(a, b) {
38333
38334	let p = a,
38335		inside = false;
38336	const px = (a.x + b.x) / 2,
38337		py = (a.y + b.y) / 2;
38338	do {
38339
38340		if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
38341			(px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
38342			inside = !inside;
38343		p = p.next;
38344
38345	} while (p !== a);
38346
38347	return inside;
38348
38349}
38350
38351// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
38352// if one belongs to the outer ring and another to a hole, it merges it into a single ring
38353function splitPolygon(a, b) {
38354
38355	const a2 = new Node(a.i, a.x, a.y),
38356		b2 = new Node(b.i, b.x, b.y),
38357		an = a.next,
38358		bp = b.prev;
38359
38360	a.next = b;
38361	b.prev = a;
38362
38363	a2.next = an;
38364	an.prev = a2;
38365
38366	b2.next = a2;
38367	a2.prev = b2;
38368
38369	bp.next = b2;
38370	b2.prev = bp;
38371
38372	return b2;
38373
38374}
38375
38376// create a node and optionally link it with previous one (in a circular doubly linked list)
38377function insertNode(i, x, y, last) {
38378
38379	const p = new Node(i, x, y);
38380
38381	if (!last) {
38382
38383		p.prev = p;
38384		p.next = p;
38385
38386	} else {
38387
38388		p.next = last.next;
38389		p.prev = last;
38390		last.next.prev = p;
38391		last.next = p;
38392
38393	}
38394
38395	return p;
38396
38397}
38398
38399function removeNode(p) {
38400
38401	p.next.prev = p.prev;
38402	p.prev.next = p.next;
38403
38404	if (p.prevZ) p.prevZ.nextZ = p.nextZ;
38405	if (p.nextZ) p.nextZ.prevZ = p.prevZ;
38406
38407}
38408
38409function Node(i, x, y) {
38410
38411	// vertex index in coordinates array
38412	this.i = i;
38413
38414	// vertex coordinates
38415	this.x = x;
38416	this.y = y;
38417
38418	// previous and next vertex nodes in a polygon ring
38419	this.prev = null;
38420	this.next = null;
38421
38422	// z-order curve value
38423	this.z = 0;
38424
38425	// previous and next nodes in z-order
38426	this.prevZ = null;
38427	this.nextZ = null;
38428
38429	// indicates whether this is a steiner point
38430	this.steiner = false;
38431
38432}
38433
38434function signedArea(data, start, end, dim) {
38435
38436	let sum = 0;
38437	for (let i = start, j = end - dim; i < end; i += dim) {
38438
38439		sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
38440		j = i;
38441
38442	}
38443
38444	return sum;
38445
38446}
38447
38448class ShapeUtils {
38449
38450	// calculate area of the contour polygon
38451
38452	static area(contour) {
38453
38454		const n = contour.length;
38455		let a = 0.0;
38456
38457		for (let p = n - 1, q = 0; q < n; p = q++) {
38458
38459			a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
38460
38461		}
38462
38463		return a * 0.5;
38464
38465	}
38466
38467	static isClockWise(pts) {
38468
38469		return ShapeUtils.area(pts) < 0;
38470
38471	}
38472
38473	static triangulateShape(contour, holes) {
38474
38475		const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
38476		const holeIndices = []; // array of hole indices
38477		const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
38478
38479		removeDupEndPts(contour);
38480		addContour(vertices, contour);
38481
38482		//
38483
38484		let holeIndex = contour.length;
38485
38486		holes.forEach(removeDupEndPts);
38487
38488		for (let i = 0; i < holes.length; i++) {
38489
38490			holeIndices.push(holeIndex);
38491			holeIndex += holes[i].length;
38492			addContour(vertices, holes[i]);
38493
38494		}
38495
38496		//
38497
38498		const triangles = Earcut.triangulate(vertices, holeIndices);
38499
38500		//
38501
38502		for (let i = 0; i < triangles.length; i += 3) {
38503
38504			faces.push(triangles.slice(i, i + 3));
38505
38506		}
38507
38508		return faces;
38509
38510	}
38511
38512}
38513
38514function removeDupEndPts(points) {
38515
38516	const l = points.length;
38517
38518	if (l > 2 && points[l - 1].equals(points[0])) {
38519
38520		points.pop();
38521
38522	}
38523
38524}
38525
38526function addContour(vertices, contour) {
38527
38528	for (let i = 0; i < contour.length; i++) {
38529
38530		vertices.push(contour[i].x);
38531		vertices.push(contour[i].y);
38532
38533	}
38534
38535}
38536
38537/**
38538 * Creates extruded geometry from a path shape.
38539 *
38540 * parameters = {
38541 *
38542 *  curveSegments: <int>, // number of points on the curves
38543 *  steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too
38544 *  depth: <float>, // Depth to extrude the shape
38545 *
38546 *  bevelEnabled: <bool>, // turn on bevel
38547 *  bevelThickness: <float>, // how deep into the original shape bevel goes
38548 *  bevelSize: <float>, // how far from shape outline (including bevelOffset) is bevel
38549 *  bevelOffset: <float>, // how far from shape outline does bevel start
38550 *  bevelSegments: <int>, // number of bevel layers
38551 *
38552 *  extrudePath: <THREE.Curve> // curve to extrude shape along
38553 *
38554 *  UVGenerator: <Object> // object that provides UV generator functions
38555 *
38556 * }
38557 */
38558
38559
38560class ExtrudeGeometry extends BufferGeometry {
38561
38562	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 = {}) {
38563
38564		super();
38565
38566		this.type = 'ExtrudeGeometry';
38567
38568		this.parameters = {
38569			shapes: shapes,
38570			options: options
38571		};
38572
38573		shapes = Array.isArray(shapes) ? shapes : [shapes];
38574
38575		const scope = this;
38576
38577		const verticesArray = [];
38578		const uvArray = [];
38579
38580		for (let i = 0, l = shapes.length; i < l; i++) {
38581
38582			const shape = shapes[i];
38583			addShape(shape);
38584
38585		}
38586
38587		// build geometry
38588
38589		this.setAttribute('position', new Float32BufferAttribute(verticesArray, 3));
38590		this.setAttribute('uv', new Float32BufferAttribute(uvArray, 2));
38591
38592		this.computeVertexNormals();
38593
38594		// functions
38595
38596		function addShape(shape) {
38597
38598			const placeholder = [];
38599
38600			// options
38601
38602			const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
38603			const steps = options.steps !== undefined ? options.steps : 1;
38604			const depth = options.depth !== undefined ? options.depth : 1;
38605
38606			let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
38607			let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
38608			let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
38609			let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
38610			let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
38611
38612			const extrudePath = options.extrudePath;
38613
38614			const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
38615
38616			//
38617
38618			let extrudePts, extrudeByPath = false;
38619			let splineTube, binormal, normal, position2;
38620
38621			if (extrudePath) {
38622
vendor: 2,780 bytes, lines 38623-38732
38623				extrudePts = extrudePath.getSpacedPoints(steps);
38624
38625				extrudeByPath = true;
38626				bevelEnabled = false; // bevels not supported for path extrusion
38627
38628				// SETUP TNB variables
38629
38630				// TODO1 - have a .isClosed in spline?
38631
38632				splineTube = extrudePath.computeFrenetFrames(steps, false);
38633
38634				// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
38635
38636				binormal = new Vector3();
38637				normal = new Vector3();
38638				position2 = new Vector3();
38639
38640			}
38641
38642			// Safeguards if bevels are not enabled
38643
38644			if (!bevelEnabled) {
38645
38646				bevelSegments = 0;
38647				bevelThickness = 0;
38648				bevelSize = 0;
38649				bevelOffset = 0;
38650
38651			}
38652
38653			// Variables initialization
38654
38655			const shapePoints = shape.extractPoints(curveSegments);
38656
38657			let vertices = shapePoints.shape;
38658			const holes = shapePoints.holes;
38659
38660			const reverse = !ShapeUtils.isClockWise(vertices);
38661
38662			if (reverse) {
38663
38664				vertices = vertices.reverse();
38665
38666				// Maybe we should also check if holes are in the opposite direction, just to be safe ...
38667
38668				for (let h = 0, hl = holes.length; h < hl; h++) {
38669
38670					const ahole = holes[h];
38671
38672					if (ShapeUtils.isClockWise(ahole)) {
38673
38674						holes[h] = ahole.reverse();
38675
38676					}
38677
38678				}
38679
38680			}
38681
38682
38683			const faces = ShapeUtils.triangulateShape(vertices, holes);
38684
38685			/* Vertices */
38686
38687			const contour = vertices; // vertices has all points but contour has only points of circumference
38688
38689			for (let h = 0, hl = holes.length; h < hl; h++) {
38690
38691				const ahole = holes[h];
38692
38693				vertices = vertices.concat(ahole);
38694
38695			}
38696
38697
38698			function scalePt2(pt, vec, size) {
38699
38700				if (!vec) console.error('THREE.ExtrudeGeometry: vec does not exist');
38701
38702				return pt.clone().addScaledVector(vec, size);
38703
38704			}
38705
38706			const vlen = vertices.length, flen = faces.length;
38707
38708
38709			// Find directions for point movement
38710
38711
38712			function getBevelVec(inPt, inPrev, inNext) {
38713
38714				// computes for inPt the corresponding point inPt' on a new contour
38715				//   shifted by 1 unit (length of normalized vector) to the left
38716				// if we walk along contour clockwise, this new contour is outside the old one
38717				//
38718				// inPt' is the intersection of the two lines parallel to the two
38719				//  adjacent edges of inPt at a distance of 1 unit on the left side.
38720
38721				let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
38722
38723				// good reading for geometry algorithms (here: line-line intersection)
38724				// http://geomalgorithms.com/a05-_intersect-1.html
38725
38726				const v_prev_x = inPt.x - inPrev.x,
38727					v_prev_y = inPt.y - inPrev.y;
38728				const v_next_x = inNext.x - inPt.x,
38729					v_next_y = inNext.y - inPt.y;
38730
38731				const v_prev_lensq = (v_prev_x * v_prev_x + v_prev_y * v_prev_y);
38732
vendor: 17,749 bytes, lines 38733-39586
38733				// check for collinear edges
38734				const collinear0 = (v_prev_x * v_next_y - v_prev_y * v_next_x);
38735
38736				if (Math.abs(collinear0) > Number.EPSILON) {
38737
38738					// not collinear
38739
38740					// length of vectors for normalizing
38741
38742					const v_prev_len = Math.sqrt(v_prev_lensq);
38743					const v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y);
38744
38745					// shift adjacent points by unit vectors to the left
38746
38747					const ptPrevShift_x = (inPrev.x - v_prev_y / v_prev_len);
38748					const ptPrevShift_y = (inPrev.y + v_prev_x / v_prev_len);
38749
38750					const ptNextShift_x = (inNext.x - v_next_y / v_next_len);
38751					const ptNextShift_y = (inNext.y + v_next_x / v_next_len);
38752
38753					// scaling factor for v_prev to intersection point
38754
38755					const sf = ((ptNextShift_x - ptPrevShift_x) * v_next_y -
38756						(ptNextShift_y - ptPrevShift_y) * v_next_x) /
38757						(v_prev_x * v_next_y - v_prev_y * v_next_x);
38758
38759					// vector from inPt to intersection point
38760
38761					v_trans_x = (ptPrevShift_x + v_prev_x * sf - inPt.x);
38762					v_trans_y = (ptPrevShift_y + v_prev_y * sf - inPt.y);
38763
38764					// Don't normalize!, otherwise sharp corners become ugly
38765					//  but prevent crazy spikes
38766					const v_trans_lensq = (v_trans_x * v_trans_x + v_trans_y * v_trans_y);
38767					if (v_trans_lensq <= 2) {
38768
38769						return new Vector2(v_trans_x, v_trans_y);
38770
38771					} else {
38772
38773						shrink_by = Math.sqrt(v_trans_lensq / 2);
38774
38775					}
38776
38777				} else {
38778
38779					// handle special case of collinear edges
38780
38781					let direction_eq = false; // assumes: opposite
38782
38783					if (v_prev_x > Number.EPSILON) {
38784
38785						if (v_next_x > Number.EPSILON) {
38786
38787							direction_eq = true;
38788
38789						}
38790
38791					} else {
38792
38793						if (v_prev_x < - Number.EPSILON) {
38794
38795							if (v_next_x < - Number.EPSILON) {
38796
38797								direction_eq = true;
38798
38799							}
38800
38801						} else {
38802
38803							if (Math.sign(v_prev_y) === Math.sign(v_next_y)) {
38804
38805								direction_eq = true;
38806
38807							}
38808
38809						}
38810
38811					}
38812
38813					if (direction_eq) {
38814
38815						// console.log("Warning: lines are a straight sequence");
38816						v_trans_x = - v_prev_y;
38817						v_trans_y = v_prev_x;
38818						shrink_by = Math.sqrt(v_prev_lensq);
38819
38820					} else {
38821
38822						// console.log("Warning: lines are a straight spike");
38823						v_trans_x = v_prev_x;
38824						v_trans_y = v_prev_y;
38825						shrink_by = Math.sqrt(v_prev_lensq / 2);
38826
38827					}
38828
38829				}
38830
38831				return new Vector2(v_trans_x / shrink_by, v_trans_y / shrink_by);
38832
38833			}
38834
38835
38836			const contourMovements = [];
38837
38838			for (let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
38839
38840				if (j === il) j = 0;
38841				if (k === il) k = 0;
38842
38843				//  (j)---(i)---(k)
38844				// console.log('i,j,k', i, j , k)
38845
38846				contourMovements[i] = getBevelVec(contour[i], contour[j], contour[k]);
38847
38848			}
38849
38850			const holesMovements = [];
38851			let oneHoleMovements, verticesMovements = contourMovements.concat();
38852
38853			for (let h = 0, hl = holes.length; h < hl; h++) {
38854
38855				const ahole = holes[h];
38856
38857				oneHoleMovements = [];
38858
38859				for (let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
38860
38861					if (j === il) j = 0;
38862					if (k === il) k = 0;
38863
38864					//  (j)---(i)---(k)
38865					oneHoleMovements[i] = getBevelVec(ahole[i], ahole[j], ahole[k]);
38866
38867				}
38868
38869				holesMovements.push(oneHoleMovements);
38870				verticesMovements = verticesMovements.concat(oneHoleMovements);
38871
38872			}
38873
38874
38875			// Loop bevelSegments, 1 for the front, 1 for the back
38876
38877			for (let b = 0; b < bevelSegments; b++) {
38878
38879				//for ( b = bevelSegments; b > 0; b -- ) {
38880
38881				const t = b / bevelSegments;
38882				const z = bevelThickness * Math.cos(t * Math.PI / 2);
38883				const bs = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
38884
38885				// contract shape
38886
38887				for (let i = 0, il = contour.length; i < il; i++) {
38888
38889					const vert = scalePt2(contour[i], contourMovements[i], bs);
38890
38891					v(vert.x, vert.y, - z);
38892
38893				}
38894
38895				// expand holes
38896
38897				for (let h = 0, hl = holes.length; h < hl; h++) {
38898
38899					const ahole = holes[h];
38900					oneHoleMovements = holesMovements[h];
38901
38902					for (let i = 0, il = ahole.length; i < il; i++) {
38903
38904						const vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
38905
38906						v(vert.x, vert.y, - z);
38907
38908					}
38909
38910				}
38911
38912			}
38913
38914			const bs = bevelSize + bevelOffset;
38915
38916			// Back facing vertices
38917
38918			for (let i = 0; i < vlen; i++) {
38919
38920				const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
38921
38922				if (!extrudeByPath) {
38923
38924					v(vert.x, vert.y, 0);
38925
38926				} else {
38927
38928					// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
38929
38930					normal.copy(splineTube.normals[0]).multiplyScalar(vert.x);
38931					binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y);
38932
38933					position2.copy(extrudePts[0]).add(normal).add(binormal);
38934
38935					v(position2.x, position2.y, position2.z);
38936
38937				}
38938
38939			}
38940
38941			// Add stepped vertices...
38942			// Including front facing vertices
38943
38944			for (let s = 1; s <= steps; s++) {
38945
38946				for (let i = 0; i < vlen; i++) {
38947
38948					const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
38949
38950					if (!extrudeByPath) {
38951
38952						v(vert.x, vert.y, depth / steps * s);
38953
38954					} else {
38955
38956						// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
38957
38958						normal.copy(splineTube.normals[s]).multiplyScalar(vert.x);
38959						binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y);
38960
38961						position2.copy(extrudePts[s]).add(normal).add(binormal);
38962
38963						v(position2.x, position2.y, position2.z);
38964
38965					}
38966
38967				}
38968
38969			}
38970
38971
38972			// Add bevel segments planes
38973
38974			//for ( b = 1; b <= bevelSegments; b ++ ) {
38975			for (let b = bevelSegments - 1; b >= 0; b--) {
38976
38977				const t = b / bevelSegments;
38978				const z = bevelThickness * Math.cos(t * Math.PI / 2);
38979				const bs = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
38980
38981				// contract shape
38982
38983				for (let i = 0, il = contour.length; i < il; i++) {
38984
38985					const vert = scalePt2(contour[i], contourMovements[i], bs);
38986					v(vert.x, vert.y, depth + z);
38987
38988				}
38989
38990				// expand holes
38991
38992				for (let h = 0, hl = holes.length; h < hl; h++) {
38993
38994					const ahole = holes[h];
38995					oneHoleMovements = holesMovements[h];
38996
38997					for (let i = 0, il = ahole.length; i < il; i++) {
38998
38999						const vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
39000
39001						if (!extrudeByPath) {
39002
39003							v(vert.x, vert.y, depth + z);
39004
39005						} else {
39006
39007							v(vert.x, vert.y + extrudePts[steps - 1].y, extrudePts[steps - 1].x + z);
39008
39009						}
39010
39011					}
39012
39013				}
39014
39015			}
39016
39017			/* Faces */
39018
39019			// Top and bottom faces
39020
39021			buildLidFaces();
39022
39023			// Sides faces
39024
39025			buildSideFaces();
39026
39027
39028			/////  Internal functions
39029
39030			function buildLidFaces() {
39031
39032				const start = verticesArray.length / 3;
39033
39034				if (bevelEnabled) {
39035
39036					let layer = 0; // steps + 1
39037					let offset = vlen * layer;
39038
39039					// Bottom faces
39040
39041					for (let i = 0; i < flen; i++) {
39042
39043						const face = faces[i];
39044						f3(face[2] + offset, face[1] + offset, face[0] + offset);
39045
39046					}
39047
39048					layer = steps + bevelSegments * 2;
39049					offset = vlen * layer;
39050
39051					// Top faces
39052
39053					for (let i = 0; i < flen; i++) {
39054
39055						const face = faces[i];
39056						f3(face[0] + offset, face[1] + offset, face[2] + offset);
39057
39058					}
39059
39060				} else {
39061
39062					// Bottom faces
39063
39064					for (let i = 0; i < flen; i++) {
39065
39066						const face = faces[i];
39067						f3(face[2], face[1], face[0]);
39068
39069					}
39070
39071					// Top faces
39072
39073					for (let i = 0; i < flen; i++) {
39074
39075						const face = faces[i];
39076						f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
39077
39078					}
39079
39080				}
39081
39082				scope.addGroup(start, verticesArray.length / 3 - start, 0);
39083
39084			}
39085
39086			// Create faces for the z-sides of the shape
39087
39088			function buildSideFaces() {
39089
39090				const start = verticesArray.length / 3;
39091				let layeroffset = 0;
39092				sidewalls(contour, layeroffset);
39093				layeroffset += contour.length;
39094
39095				for (let h = 0, hl = holes.length; h < hl; h++) {
39096
39097					const ahole = holes[h];
39098					sidewalls(ahole, layeroffset);
39099
39100					//, true
39101					layeroffset += ahole.length;
39102
39103				}
39104
39105
39106				scope.addGroup(start, verticesArray.length / 3 - start, 1);
39107
39108
39109			}
39110
39111			function sidewalls(contour, layeroffset) {
39112
39113				let i = contour.length;
39114
39115				while (--i >= 0) {
39116
39117					const j = i;
39118					let k = i - 1;
39119					if (k < 0) k = contour.length - 1;
39120
39121					//console.log('b', i,j, i-1, k,vertices.length);
39122
39123					for (let s = 0, sl = (steps + bevelSegments * 2); s < sl; s++) {
39124
39125						const slen1 = vlen * s;
39126						const slen2 = vlen * (s + 1);
39127
39128						const a = layeroffset + j + slen1,
39129							b = layeroffset + k + slen1,
39130							c = layeroffset + k + slen2,
39131							d = layeroffset + j + slen2;
39132
39133						f4(a, b, c, d);
39134
39135					}
39136
39137				}
39138
39139			}
39140
39141			function v(x, y, z) {
39142
39143				placeholder.push(x);
39144				placeholder.push(y);
39145				placeholder.push(z);
39146
39147			}
39148
39149
39150			function f3(a, b, c) {
39151
39152				addVertex(a);
39153				addVertex(b);
39154				addVertex(c);
39155
39156				const nextIndex = verticesArray.length / 3;
39157				const uvs = uvgen.generateTopUV(scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1);
39158
39159				addUV(uvs[0]);
39160				addUV(uvs[1]);
39161				addUV(uvs[2]);
39162
39163			}
39164
39165			function f4(a, b, c, d) {
39166
39167				addVertex(a);
39168				addVertex(b);
39169				addVertex(d);
39170
39171				addVertex(b);
39172				addVertex(c);
39173				addVertex(d);
39174
39175
39176				const nextIndex = verticesArray.length / 3;
39177				const uvs = uvgen.generateSideWallUV(scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1);
39178
39179				addUV(uvs[0]);
39180				addUV(uvs[1]);
39181				addUV(uvs[3]);
39182
39183				addUV(uvs[1]);
39184				addUV(uvs[2]);
39185				addUV(uvs[3]);
39186
39187			}
39188
39189			function addVertex(index) {
39190
39191				verticesArray.push(placeholder[index * 3 + 0]);
39192				verticesArray.push(placeholder[index * 3 + 1]);
39193				verticesArray.push(placeholder[index * 3 + 2]);
39194
39195			}
39196
39197
39198			function addUV(vector2) {
39199
39200				uvArray.push(vector2.x);
39201				uvArray.push(vector2.y);
39202
39203			}
39204
39205		}
39206
39207	}
39208
39209	copy(source) {
39210
39211		super.copy(source);
39212
39213		this.parameters = Object.assign({}, source.parameters);
39214
39215		return this;
39216
39217	}
39218
39219	toJSON() {
39220
39221		const data = super.toJSON();
39222
39223		const shapes = this.parameters.shapes;
39224		const options = this.parameters.options;
39225
39226		return toJSON$1(shapes, options, data);
39227
39228	}
39229
39230	static fromJSON(data, shapes) {
39231
39232		const geometryShapes = [];
39233
39234		for (let j = 0, jl = data.shapes.length; j < jl; j++) {
39235
39236			const shape = shapes[data.shapes[j]];
39237
39238			geometryShapes.push(shape);
39239
39240		}
39241
39242		const extrudePath = data.options.extrudePath;
39243
39244		if (extrudePath !== undefined) {
39245
39246			data.options.extrudePath = new Curves[extrudePath.type]().fromJSON(extrudePath);
39247
39248		}
39249
39250		return new ExtrudeGeometry(geometryShapes, data.options);
39251
39252	}
39253
39254}
39255
39256const WorldUVGenerator = {
39257
39258	generateTopUV: function (geometry, vertices, indexA, indexB, indexC) {
39259
39260		const a_x = vertices[indexA * 3];
39261		const a_y = vertices[indexA * 3 + 1];
39262		const b_x = vertices[indexB * 3];
39263		const b_y = vertices[indexB * 3 + 1];
39264		const c_x = vertices[indexC * 3];
39265		const c_y = vertices[indexC * 3 + 1];
39266
39267		return [
39268			new Vector2(a_x, a_y),
39269			new Vector2(b_x, b_y),
39270			new Vector2(c_x, c_y)
39271		];
39272
39273	},
39274
39275	generateSideWallUV: function (geometry, vertices, indexA, indexB, indexC, indexD) {
39276
39277		const a_x = vertices[indexA * 3];
39278		const a_y = vertices[indexA * 3 + 1];
39279		const a_z = vertices[indexA * 3 + 2];
39280		const b_x = vertices[indexB * 3];
39281		const b_y = vertices[indexB * 3 + 1];
39282		const b_z = vertices[indexB * 3 + 2];
39283		const c_x = vertices[indexC * 3];
39284		const c_y = vertices[indexC * 3 + 1];
39285		const c_z = vertices[indexC * 3 + 2];
39286		const d_x = vertices[indexD * 3];
39287		const d_y = vertices[indexD * 3 + 1];
39288		const d_z = vertices[indexD * 3 + 2];
39289
39290		if (Math.abs(a_y - b_y) < Math.abs(a_x - b_x)) {
39291
39292			return [
39293				new Vector2(a_x, 1 - a_z),
39294				new Vector2(b_x, 1 - b_z),
39295				new Vector2(c_x, 1 - c_z),
39296				new Vector2(d_x, 1 - d_z)
39297			];
39298
39299		} else {
39300
39301			return [
39302				new Vector2(a_y, 1 - a_z),
39303				new Vector2(b_y, 1 - b_z),
39304				new Vector2(c_y, 1 - c_z),
39305				new Vector2(d_y, 1 - d_z)
39306			];
39307
39308		}
39309
39310	}
39311
39312};
39313
39314function toJSON$1(shapes, options, data) {
39315
39316	data.shapes = [];
39317
39318	if (Array.isArray(shapes)) {
39319
39320		for (let i = 0, l = shapes.length; i < l; i++) {
39321
39322			const shape = shapes[i];
39323
39324			data.shapes.push(shape.uuid);
39325
39326		}
39327
39328	} else {
39329
39330		data.shapes.push(shapes.uuid);
39331
39332	}
39333
39334	data.options = Object.assign({}, options);
39335
39336	if (options.extrudePath !== undefined) data.options.extrudePath = options.extrudePath.toJSON();
39337
39338	return data;
39339
39340}
39341
39342class IcosahedronGeometry extends PolyhedronGeometry {
39343
39344	constructor(radius = 1, detail = 0) {
39345
39346		const t = (1 + Math.sqrt(5)) / 2;
39347
39348		const vertices = [
39349			- 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0,
39350			0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t,
39351			t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1
39352		];
39353
39354		const indices = [
39355			0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
39356			1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
39357			3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
39358			4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
39359		];
39360
39361		super(vertices, indices, radius, detail);
39362
39363		this.type = 'IcosahedronGeometry';
39364
39365		this.parameters = {
39366			radius: radius,
39367			detail: detail
39368		};
39369
39370	}
39371
39372	static fromJSON(data) {
39373
39374		return new IcosahedronGeometry(data.radius, data.detail);
39375
39376	}
39377
39378}
39379
39380class OctahedronGeometry extends PolyhedronGeometry {
39381
39382	constructor(radius = 1, detail = 0) {
39383
39384		const vertices = [
39385			1, 0, 0, - 1, 0, 0, 0, 1, 0,
39386			0, - 1, 0, 0, 0, 1, 0, 0, - 1
39387		];
39388
39389		const indices = [
39390			0, 2, 4, 0, 4, 3, 0, 3, 5,
39391			0, 5, 2, 1, 2, 5, 1, 5, 3,
39392			1, 3, 4, 1, 4, 2
39393		];
39394
39395		super(vertices, indices, radius, detail);
39396
39397		this.type = 'OctahedronGeometry';
39398
39399		this.parameters = {
39400			radius: radius,
39401			detail: detail
39402		};
39403
39404	}
39405
39406	static fromJSON(data) {
39407
39408		return new OctahedronGeometry(data.radius, data.detail);
39409
39410	}
39411
39412}
39413
39414class RingGeometry extends BufferGeometry {
39415
39416	constructor(innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) {
39417
39418		super();
39419
39420		this.type = 'RingGeometry';
39421
39422		this.parameters = {
39423			innerRadius: innerRadius,
39424			outerRadius: outerRadius,
39425			thetaSegments: thetaSegments,
39426			phiSegments: phiSegments,
39427			thetaStart: thetaStart,
39428			thetaLength: thetaLength
39429		};
39430
39431		thetaSegments = Math.max(3, thetaSegments);
39432		phiSegments = Math.max(1, phiSegments);
39433
39434		// buffers
39435
39436		const indices = [];
39437		const vertices = [];
39438		const normals = [];
39439		const uvs = [];
39440
39441		// some helper variables
39442
39443		let radius = innerRadius;
39444		const radiusStep = ((outerRadius - innerRadius) / phiSegments);
39445		const vertex = new Vector3();
39446		const uv = new Vector2();
39447
39448		// generate vertices, normals and uvs
39449
39450		for (let j = 0; j <= phiSegments; j++) {
39451
39452			for (let i = 0; i <= thetaSegments; i++) {
39453
39454				// values are generate from the inside of the ring to the outside
39455
39456				const segment = thetaStart + i / thetaSegments * thetaLength;
39457
39458				// vertex
39459
39460				vertex.x = radius * Math.cos(segment);
39461				vertex.y = radius * Math.sin(segment);
39462
39463				vertices.push(vertex.x, vertex.y, vertex.z);
39464
39465				// normal
39466
39467				normals.push(0, 0, 1);
39468
39469				// uv
39470
39471				uv.x = (vertex.x / outerRadius + 1) / 2;
39472				uv.y = (vertex.y / outerRadius + 1) / 2;
39473
39474				uvs.push(uv.x, uv.y);
39475
39476			}
39477
39478			// increase the radius for next row of vertices
39479
39480			radius += radiusStep;
39481
39482		}
39483
39484		// indices
39485
39486		for (let j = 0; j < phiSegments; j++) {
39487
39488			const thetaSegmentLevel = j * (thetaSegments + 1);
39489
39490			for (let i = 0; i < thetaSegments; i++) {
39491
39492				const segment = i + thetaSegmentLevel;
39493
39494				const a = segment;
39495				const b = segment + thetaSegments + 1;
39496				const c = segment + thetaSegments + 2;
39497				const d = segment + 1;
39498
39499				// faces
39500
39501				indices.push(a, b, d);
39502				indices.push(b, c, d);
39503
39504			}
39505
39506		}
39507
39508		// build geometry
39509
39510		this.setIndex(indices);
39511		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
39512		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
39513		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
39514
39515	}
39516
39517	copy(source) {
39518
39519		super.copy(source);
39520
39521		this.parameters = Object.assign({}, source.parameters);
39522
39523		return this;
39524
39525	}
39526
39527	static fromJSON(data) {
39528
39529		return new RingGeometry(data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength);
39530
39531	}
39532
39533}
39534
39535class ShapeGeometry extends BufferGeometry {
39536
39537	constructor(shapes = new Shape([new Vector2(0, 0.5), new Vector2(- 0.5, - 0.5), new Vector2(0.5, - 0.5)]), curveSegments = 12) {
39538
39539		super();
39540
39541		this.type = 'ShapeGeometry';
39542
39543		this.parameters = {
39544			shapes: shapes,
39545			curveSegments: curveSegments
39546		};
39547
39548		// buffers
39549
39550		const indices = [];
39551		const vertices = [];
39552		const normals = [];
39553		const uvs = [];
39554
39555		// helper variables
39556
39557		let groupStart = 0;
39558		let groupCount = 0;
39559
39560		// allow single and array values for "shapes" parameter
39561
39562		if (Array.isArray(shapes) === false) {
39563
39564			addShape(shapes);
39565
39566		} else {
39567
39568			for (let i = 0; i < shapes.length; i++) {
39569
39570				addShape(shapes[i]);
39571
39572				this.addGroup(groupStart, groupCount, i); // enables MultiMaterial support
39573
39574				groupStart += groupCount;
39575				groupCount = 0;
39576
39577			}
39578
39579		}
39580
39581		// build geometry
39582
39583		this.setIndex(indices);
39584		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
39585		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
39586		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
vendor: 4,428 bytes, lines 39587-39816
39587
39588
39589		// helper functions
39590
39591		function addShape(shape) {
39592
39593			const indexOffset = vertices.length / 3;
39594			const points = shape.extractPoints(curveSegments);
39595
39596			let shapeVertices = points.shape;
39597			const shapeHoles = points.holes;
39598
39599			// check direction of vertices
39600
39601			if (ShapeUtils.isClockWise(shapeVertices) === false) {
39602
39603				shapeVertices = shapeVertices.reverse();
39604
39605			}
39606
39607			for (let i = 0, l = shapeHoles.length; i < l; i++) {
39608
39609				const shapeHole = shapeHoles[i];
39610
39611				if (ShapeUtils.isClockWise(shapeHole) === true) {
39612
39613					shapeHoles[i] = shapeHole.reverse();
39614
39615				}
39616
39617			}
39618
39619			const faces = ShapeUtils.triangulateShape(shapeVertices, shapeHoles);
39620
39621			// join vertices of inner and outer paths to a single array
39622
39623			for (let i = 0, l = shapeHoles.length; i < l; i++) {
39624
39625				const shapeHole = shapeHoles[i];
39626				shapeVertices = shapeVertices.concat(shapeHole);
39627
39628			}
39629
39630			// vertices, normals, uvs
39631
39632			for (let i = 0, l = shapeVertices.length; i < l; i++) {
39633
39634				const vertex = shapeVertices[i];
39635
39636				vertices.push(vertex.x, vertex.y, 0);
39637				normals.push(0, 0, 1);
39638				uvs.push(vertex.x, vertex.y); // world uvs
39639
39640			}
39641
39642			// indices
39643
39644			for (let i = 0, l = faces.length; i < l; i++) {
39645
39646				const face = faces[i];
39647
39648				const a = face[0] + indexOffset;
39649				const b = face[1] + indexOffset;
39650				const c = face[2] + indexOffset;
39651
39652				indices.push(a, b, c);
39653				groupCount += 3;
39654
39655			}
39656
39657		}
39658
39659	}
39660
39661	copy(source) {
39662
39663		super.copy(source);
39664
39665		this.parameters = Object.assign({}, source.parameters);
39666
39667		return this;
39668
39669	}
39670
39671	toJSON() {
39672
39673		const data = super.toJSON();
39674
39675		const shapes = this.parameters.shapes;
39676
39677		return toJSON(shapes, data);
39678
39679	}
39680
39681	static fromJSON(data, shapes) {
39682
39683		const geometryShapes = [];
39684
39685		for (let j = 0, jl = data.shapes.length; j < jl; j++) {
39686
39687			const shape = shapes[data.shapes[j]];
39688
39689			geometryShapes.push(shape);
39690
39691		}
39692
39693		return new ShapeGeometry(geometryShapes, data.curveSegments);
39694
39695	}
39696
39697}
39698
39699function toJSON(shapes, data) {
39700
39701	data.shapes = [];
39702
39703	if (Array.isArray(shapes)) {
39704
39705		for (let i = 0, l = shapes.length; i < l; i++) {
39706
39707			const shape = shapes[i];
39708
39709			data.shapes.push(shape.uuid);
39710
39711		}
39712
39713	} else {
39714
39715		data.shapes.push(shapes.uuid);
39716
39717	}
39718
39719	return data;
39720
39721}
39722
39723class SphereGeometry extends BufferGeometry {
39724
39725	constructor(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) {
39726
39727		super();
39728
39729		this.type = 'SphereGeometry';
39730
39731		this.parameters = {
39732			radius: radius,
39733			widthSegments: widthSegments,
39734			heightSegments: heightSegments,
39735			phiStart: phiStart,
39736			phiLength: phiLength,
39737			thetaStart: thetaStart,
39738			thetaLength: thetaLength
39739		};
39740
39741		widthSegments = Math.max(3, Math.floor(widthSegments));
39742		heightSegments = Math.max(2, Math.floor(heightSegments));
39743
39744		const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI);
39745
39746		let index = 0;
39747		const grid = [];
39748
39749		const vertex = new Vector3();
39750		const normal = new Vector3();
39751
39752		// buffers
39753
39754		const indices = [];
39755		const vertices = [];
39756		const normals = [];
39757		const uvs = [];
39758
39759		// generate vertices, normals and uvs
39760
39761		for (let iy = 0; iy <= heightSegments; iy++) {
39762
39763			const verticesRow = [];
39764
39765			const v = iy / heightSegments;
39766
39767			// special case for the poles
39768
39769			let uOffset = 0;
39770
39771			if (iy === 0 && thetaStart === 0) {
39772
39773				uOffset = 0.5 / widthSegments;
39774
39775			} else if (iy === heightSegments && thetaEnd === Math.PI) {
39776
39777				uOffset = - 0.5 / widthSegments;
39778
39779			}
39780
39781			for (let ix = 0; ix <= widthSegments; ix++) {
39782
39783				const u = ix / widthSegments;
39784
39785				// vertex
39786
39787				vertex.x = - radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
39788				vertex.y = radius * Math.cos(thetaStart + v * thetaLength);
39789				vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
39790
39791				vertices.push(vertex.x, vertex.y, vertex.z);
39792
39793				// normal
39794
39795				normal.copy(vertex).normalize();
39796				normals.push(normal.x, normal.y, normal.z);
39797
39798				// uv
39799
39800				uvs.push(u + uOffset, 1 - v);
39801
39802				verticesRow.push(index++);
39803
39804			}
39805
39806			grid.push(verticesRow);
39807
39808		}
39809
39810		// indices
39811
39812		for (let iy = 0; iy < heightSegments; iy++) {
39813
39814			for (let ix = 0; ix < widthSegments; ix++) {
39815
39816				const a = grid[iy][ix + 1];
vendor: 7,187 bytes, lines 39817-40126
39817				const b = grid[iy][ix];
39818				const c = grid[iy + 1][ix];
39819				const d = grid[iy + 1][ix + 1];
39820
39821				if (iy !== 0 || thetaStart > 0) indices.push(a, b, d);
39822				if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d);
39823
39824			}
39825
39826		}
39827
39828		// build geometry
39829
39830		this.setIndex(indices);
39831		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
39832		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
39833		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
39834
39835	}
39836
39837	copy(source) {
39838
39839		super.copy(source);
39840
39841		this.parameters = Object.assign({}, source.parameters);
39842
39843		return this;
39844
39845	}
39846
39847	static fromJSON(data) {
39848
39849		return new SphereGeometry(data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength);
39850
39851	}
39852
39853}
39854
39855class TetrahedronGeometry extends PolyhedronGeometry {
39856
39857	constructor(radius = 1, detail = 0) {
39858
39859		const vertices = [
39860			1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
39861		];
39862
39863		const indices = [
39864			2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
39865		];
39866
39867		super(vertices, indices, radius, detail);
39868
39869		this.type = 'TetrahedronGeometry';
39870
39871		this.parameters = {
39872			radius: radius,
39873			detail: detail
39874		};
39875
39876	}
39877
39878	static fromJSON(data) {
39879
39880		return new TetrahedronGeometry(data.radius, data.detail);
39881
39882	}
39883
39884}
39885
39886class TorusGeometry extends BufferGeometry {
39887
39888	constructor(radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2) {
39889
39890		super();
39891
39892		this.type = 'TorusGeometry';
39893
39894		this.parameters = {
39895			radius: radius,
39896			tube: tube,
39897			radialSegments: radialSegments,
39898			tubularSegments: tubularSegments,
39899			arc: arc
39900		};
39901
39902		radialSegments = Math.floor(radialSegments);
39903		tubularSegments = Math.floor(tubularSegments);
39904
39905		// buffers
39906
39907		const indices = [];
39908		const vertices = [];
39909		const normals = [];
39910		const uvs = [];
39911
39912		// helper variables
39913
39914		const center = new Vector3();
39915		const vertex = new Vector3();
39916		const normal = new Vector3();
39917
39918		// generate vertices, normals and uvs
39919
39920		for (let j = 0; j <= radialSegments; j++) {
39921
39922			for (let i = 0; i <= tubularSegments; i++) {
39923
39924				const u = i / tubularSegments * arc;
39925				const v = j / radialSegments * Math.PI * 2;
39926
39927				// vertex
39928
39929				vertex.x = (radius + tube * Math.cos(v)) * Math.cos(u);
39930				vertex.y = (radius + tube * Math.cos(v)) * Math.sin(u);
39931				vertex.z = tube * Math.sin(v);
39932
39933				vertices.push(vertex.x, vertex.y, vertex.z);
39934
39935				// normal
39936
39937				center.x = radius * Math.cos(u);
39938				center.y = radius * Math.sin(u);
39939				normal.subVectors(vertex, center).normalize();
39940
39941				normals.push(normal.x, normal.y, normal.z);
39942
39943				// uv
39944
39945				uvs.push(i / tubularSegments);
39946				uvs.push(j / radialSegments);
39947
39948			}
39949
39950		}
39951
39952		// generate indices
39953
39954		for (let j = 1; j <= radialSegments; j++) {
39955
39956			for (let i = 1; i <= tubularSegments; i++) {
39957
39958				// indices
39959
39960				const a = (tubularSegments + 1) * j + i - 1;
39961				const b = (tubularSegments + 1) * (j - 1) + i - 1;
39962				const c = (tubularSegments + 1) * (j - 1) + i;
39963				const d = (tubularSegments + 1) * j + i;
39964
39965				// faces
39966
39967				indices.push(a, b, d);
39968				indices.push(b, c, d);
39969
39970			}
39971
39972		}
39973
39974		// build geometry
39975
39976		this.setIndex(indices);
39977		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
39978		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
39979		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
39980
39981	}
39982
39983	copy(source) {
39984
39985		super.copy(source);
39986
39987		this.parameters = Object.assign({}, source.parameters);
39988
39989		return this;
39990
39991	}
39992
39993	static fromJSON(data) {
39994
39995		return new TorusGeometry(data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc);
39996
39997	}
39998
39999}
40000
40001class TorusKnotGeometry extends BufferGeometry {
40002
40003	constructor(radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3) {
40004
40005		super();
40006
40007		this.type = 'TorusKnotGeometry';
40008
40009		this.parameters = {
40010			radius: radius,
40011			tube: tube,
40012			tubularSegments: tubularSegments,
40013			radialSegments: radialSegments,
40014			p: p,
40015			q: q
40016		};
40017
40018		tubularSegments = Math.floor(tubularSegments);
40019		radialSegments = Math.floor(radialSegments);
40020
40021		// buffers
40022
40023		const indices = [];
40024		const vertices = [];
40025		const normals = [];
40026		const uvs = [];
40027
40028		// helper variables
40029
40030		const vertex = new Vector3();
40031		const normal = new Vector3();
40032
40033		const P1 = new Vector3();
40034		const P2 = new Vector3();
40035
40036		const B = new Vector3();
40037		const T = new Vector3();
40038		const N = new Vector3();
40039
40040		// generate vertices, normals and uvs
40041
40042		for (let i = 0; i <= tubularSegments; ++i) {
40043
40044			// the radian "u" is used to calculate the position on the torus curve of the current tubular segment
40045
40046			const u = i / tubularSegments * p * Math.PI * 2;
40047
40048			// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
40049			// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
40050
40051			calculatePositionOnCurve(u, p, q, radius, P1);
40052			calculatePositionOnCurve(u + 0.01, p, q, radius, P2);
40053
40054			// calculate orthonormal basis
40055
40056			T.subVectors(P2, P1);
40057			N.addVectors(P2, P1);
40058			B.crossVectors(T, N);
40059			N.crossVectors(B, T);
40060
40061			// normalize B, N. T can be ignored, we don't use it
40062
40063			B.normalize();
40064			N.normalize();
40065
40066			for (let j = 0; j <= radialSegments; ++j) {
40067
40068				// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
40069				// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
40070
40071				const v = j / radialSegments * Math.PI * 2;
40072				const cx = - tube * Math.cos(v);
40073				const cy = tube * Math.sin(v);
40074
40075				// now calculate the final vertex position.
40076				// first we orient the extrusion with our basis vectors, then we add it to the current position on the curve
40077
40078				vertex.x = P1.x + (cx * N.x + cy * B.x);
40079				vertex.y = P1.y + (cx * N.y + cy * B.y);
40080				vertex.z = P1.z + (cx * N.z + cy * B.z);
40081
40082				vertices.push(vertex.x, vertex.y, vertex.z);
40083
40084				// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
40085
40086				normal.subVectors(vertex, P1).normalize();
40087
40088				normals.push(normal.x, normal.y, normal.z);
40089
40090				// uv
40091
40092				uvs.push(i / tubularSegments);
40093				uvs.push(j / radialSegments);
40094
40095			}
40096
40097		}
40098
40099		// generate indices
40100
40101		for (let j = 1; j <= tubularSegments; j++) {
40102
40103			for (let i = 1; i <= radialSegments; i++) {
40104
40105				// indices
40106
40107				const a = (radialSegments + 1) * (j - 1) + (i - 1);
40108				const b = (radialSegments + 1) * j + (i - 1);
40109				const c = (radialSegments + 1) * j + i;
40110				const d = (radialSegments + 1) * (j - 1) + i;
40111
40112				// faces
40113
40114				indices.push(a, b, d);
40115				indices.push(b, c, d);
40116
40117			}
40118
40119		}
40120
40121		// build geometry
40122
40123		this.setIndex(indices);
40124		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
40125		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
40126		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
vendor: 42,316 bytes, lines 40127-42180
40127
40128		// this function calculates the current position on the torus curve
40129
40130		function calculatePositionOnCurve(u, p, q, radius, position) {
40131
40132			const cu = Math.cos(u);
40133			const su = Math.sin(u);
40134			const quOverP = q / p * u;
40135			const cs = Math.cos(quOverP);
40136
40137			position.x = radius * (2 + cs) * 0.5 * cu;
40138			position.y = radius * (2 + cs) * su * 0.5;
40139			position.z = radius * Math.sin(quOverP) * 0.5;
40140
40141		}
40142
40143	}
40144
40145	copy(source) {
40146
40147		super.copy(source);
40148
40149		this.parameters = Object.assign({}, source.parameters);
40150
40151		return this;
40152
40153	}
40154
40155	static fromJSON(data) {
40156
40157		return new TorusKnotGeometry(data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q);
40158
40159	}
40160
40161}
40162
40163class TubeGeometry extends BufferGeometry {
40164
40165	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) {
40166
40167		super();
40168
40169		this.type = 'TubeGeometry';
40170
40171		this.parameters = {
40172			path: path,
40173			tubularSegments: tubularSegments,
40174			radius: radius,
40175			radialSegments: radialSegments,
40176			closed: closed
40177		};
40178
40179		const frames = path.computeFrenetFrames(tubularSegments, closed);
40180
40181		// expose internals
40182
40183		this.tangents = frames.tangents;
40184		this.normals = frames.normals;
40185		this.binormals = frames.binormals;
40186
40187		// helper variables
40188
40189		const vertex = new Vector3();
40190		const normal = new Vector3();
40191		const uv = new Vector2();
40192		let P = new Vector3();
40193
40194		// buffer
40195
40196		const vertices = [];
40197		const normals = [];
40198		const uvs = [];
40199		const indices = [];
40200
40201		// create buffer data
40202
40203		generateBufferData();
40204
40205		// build geometry
40206
40207		this.setIndex(indices);
40208		this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
40209		this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
40210		this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
40211
40212		// functions
40213
40214		function generateBufferData() {
40215
40216			for (let i = 0; i < tubularSegments; i++) {
40217
40218				generateSegment(i);
40219
40220			}
40221
40222			// if the geometry is not closed, generate the last row of vertices and normals
40223			// at the regular position on the given path
40224			//
40225			// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
40226
40227			generateSegment((closed === false) ? tubularSegments : 0);
40228
40229			// uvs are generated in a separate function.
40230			// this makes it easy compute correct values for closed geometries
40231
40232			generateUVs();
40233
40234			// finally create faces
40235
40236			generateIndices();
40237
40238		}
40239
40240		function generateSegment(i) {
40241
40242			// we use getPointAt to sample evenly distributed points from the given path
40243
40244			P = path.getPointAt(i / tubularSegments, P);
40245
40246			// retrieve corresponding normal and binormal
40247
40248			const N = frames.normals[i];
40249			const B = frames.binormals[i];
40250
40251			// generate normals and vertices for the current segment
40252
40253			for (let j = 0; j <= radialSegments; j++) {
40254
40255				const v = j / radialSegments * Math.PI * 2;
40256
40257				const sin = Math.sin(v);
40258				const cos = - Math.cos(v);
40259
40260				// normal
40261
40262				normal.x = (cos * N.x + sin * B.x);
40263				normal.y = (cos * N.y + sin * B.y);
40264				normal.z = (cos * N.z + sin * B.z);
40265				normal.normalize();
40266
40267				normals.push(normal.x, normal.y, normal.z);
40268
40269				// vertex
40270
40271				vertex.x = P.x + radius * normal.x;
40272				vertex.y = P.y + radius * normal.y;
40273				vertex.z = P.z + radius * normal.z;
40274
40275				vertices.push(vertex.x, vertex.y, vertex.z);
40276
40277			}
40278
40279		}
40280
40281		function generateIndices() {
40282
40283			for (let j = 1; j <= tubularSegments; j++) {
40284
40285				for (let i = 1; i <= radialSegments; i++) {
40286
40287					const a = (radialSegments + 1) * (j - 1) + (i - 1);
40288					const b = (radialSegments + 1) * j + (i - 1);
40289					const c = (radialSegments + 1) * j + i;
40290					const d = (radialSegments + 1) * (j - 1) + i;
40291
40292					// faces
40293
40294					indices.push(a, b, d);
40295					indices.push(b, c, d);
40296
40297				}
40298
40299			}
40300
40301		}
40302
40303		function generateUVs() {
40304
40305			for (let i = 0; i <= tubularSegments; i++) {
40306
40307				for (let j = 0; j <= radialSegments; j++) {
40308
40309					uv.x = i / tubularSegments;
40310					uv.y = j / radialSegments;
40311
40312					uvs.push(uv.x, uv.y);
40313
40314				}
40315
40316			}
40317
40318		}
40319
40320	}
40321
40322	copy(source) {
40323
40324		super.copy(source);
40325
40326		this.parameters = Object.assign({}, source.parameters);
40327
40328		return this;
40329
40330	}
40331
40332	toJSON() {
40333
40334		const data = super.toJSON();
40335
40336		data.path = this.parameters.path.toJSON();
40337
40338		return data;
40339
40340	}
40341
40342	static fromJSON(data) {
40343
40344		// This only works for built-in curves (e.g. CatmullRomCurve3).
40345		// User defined curves or instances of CurvePath will not be deserialized.
40346		return new TubeGeometry(
40347			new Curves[data.path.type]().fromJSON(data.path),
40348			data.tubularSegments,
40349			data.radius,
40350			data.radialSegments,
40351			data.closed
40352		);
40353
40354	}
40355
40356}
40357
40358class WireframeGeometry extends BufferGeometry {
40359
40360	constructor(geometry = null) {
40361
40362		super();
40363
40364		this.type = 'WireframeGeometry';
40365
40366		this.parameters = {
40367			geometry: geometry
40368		};
40369
40370		if (geometry !== null) {
40371
40372			// buffer
40373
40374			const vertices = [];
40375			const edges = new Set();
40376
40377			// helper variables
40378
40379			const start = new Vector3();
40380			const end = new Vector3();
40381
40382			if (geometry.index !== null) {
40383
40384				// indexed BufferGeometry
40385
40386				const position = geometry.attributes.position;
40387				const indices = geometry.index;
40388				let groups = geometry.groups;
40389
40390				if (groups.length === 0) {
40391
40392					groups = [{ start: 0, count: indices.count, materialIndex: 0 }];
40393
40394				}
40395
40396				// create a data structure that contains all edges without duplicates
40397
40398				for (let o = 0, ol = groups.length; o < ol; ++o) {
40399
40400					const group = groups[o];
40401
40402					const groupStart = group.start;
40403					const groupCount = group.count;
40404
40405					for (let i = groupStart, l = (groupStart + groupCount); i < l; i += 3) {
40406
40407						for (let j = 0; j < 3; j++) {
40408
40409							const index1 = indices.getX(i + j);
40410							const index2 = indices.getX(i + (j + 1) % 3);
40411
40412							start.fromBufferAttribute(position, index1);
40413							end.fromBufferAttribute(position, index2);
40414
40415							if (isUniqueEdge(start, end, edges) === true) {
40416
40417								vertices.push(start.x, start.y, start.z);
40418								vertices.push(end.x, end.y, end.z);
40419
40420							}
40421
40422						}
40423
40424					}
40425
40426				}
40427
40428			} else {
40429
40430				// non-indexed BufferGeometry
40431
40432				const position = geometry.attributes.position;
40433
40434				for (let i = 0, l = (position.count / 3); i < l; i++) {
40435
40436					for (let j = 0; j < 3; j++) {
40437
40438						// three edges per triangle, an edge is represented as (index1, index2)
40439						// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
40440
40441						const index1 = 3 * i + j;
40442						const index2 = 3 * i + ((j + 1) % 3);
40443
40444						start.fromBufferAttribute(position, index1);
40445						end.fromBufferAttribute(position, index2);
40446
40447						if (isUniqueEdge(start, end, edges) === true) {
40448
40449							vertices.push(start.x, start.y, start.z);
40450							vertices.push(end.x, end.y, end.z);
40451
40452						}
40453
40454					}
40455
40456				}
40457
40458			}
40459
40460			// build geometry
40461
40462			this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
40463
40464		}
40465
40466	}
40467
40468	copy(source) {
40469
40470		super.copy(source);
40471
40472		this.parameters = Object.assign({}, source.parameters);
40473
40474		return this;
40475
40476	}
40477
40478}
40479
40480function isUniqueEdge(start, end, edges) {
40481
40482	const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`;
40483	const hash2 = `${end.x},${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge
40484
40485	if (edges.has(hash1) === true || edges.has(hash2) === true) {
40486
40487		return false;
40488
40489	} else {
40490
40491		edges.add(hash1);
40492		edges.add(hash2);
40493		return true;
40494
40495	}
40496
40497}
40498
40499var Geometries = /*#__PURE__*/Object.freeze({
40500	__proto__: null,
40501	BoxGeometry: BoxGeometry,
40502	CapsuleGeometry: CapsuleGeometry,
40503	CircleGeometry: CircleGeometry,
40504	ConeGeometry: ConeGeometry,
40505	CylinderGeometry: CylinderGeometry,
40506	DodecahedronGeometry: DodecahedronGeometry,
40507	EdgesGeometry: EdgesGeometry,
40508	ExtrudeGeometry: ExtrudeGeometry,
40509	IcosahedronGeometry: IcosahedronGeometry,
40510	LatheGeometry: LatheGeometry,
40511	OctahedronGeometry: OctahedronGeometry,
40512	PlaneGeometry: PlaneGeometry,
40513	PolyhedronGeometry: PolyhedronGeometry,
40514	RingGeometry: RingGeometry,
40515	ShapeGeometry: ShapeGeometry,
40516	SphereGeometry: SphereGeometry,
40517	TetrahedronGeometry: TetrahedronGeometry,
40518	TorusGeometry: TorusGeometry,
40519	TorusKnotGeometry: TorusKnotGeometry,
40520	TubeGeometry: TubeGeometry,
40521	WireframeGeometry: WireframeGeometry
40522});
40523
40524class ShadowMaterial extends Material {
40525
40526	constructor(parameters) {
40527
40528		super();
40529
40530		this.isShadowMaterial = true;
40531
40532		this.type = 'ShadowMaterial';
40533
40534		this.color = new Color(0x000000);
40535		this.transparent = true;
40536
40537		this.fog = true;
40538
40539		this.setValues(parameters);
40540
40541	}
40542
40543	copy(source) {
40544
40545		super.copy(source);
40546
40547		this.color.copy(source.color);
40548
40549		this.fog = source.fog;
40550
40551		return this;
40552
40553	}
40554
40555}
40556
40557class RawShaderMaterial extends ShaderMaterial {
40558
40559	constructor(parameters) {
40560
40561		super(parameters);
40562
40563		this.isRawShaderMaterial = true;
40564
40565		this.type = 'RawShaderMaterial';
40566
40567	}
40568
40569}
40570
40571class MeshStandardMaterial extends Material {
40572
40573	constructor(parameters) {
40574
40575		super();
40576
40577		this.isMeshStandardMaterial = true;
40578
40579		this.defines = { 'STANDARD': '' };
40580
40581		this.type = 'MeshStandardMaterial';
40582
40583		this.color = new Color(0xffffff); // diffuse
40584		this.roughness = 1.0;
40585		this.metalness = 0.0;
40586
40587		this.map = null;
40588
40589		this.lightMap = null;
40590		this.lightMapIntensity = 1.0;
40591
40592		this.aoMap = null;
40593		this.aoMapIntensity = 1.0;
40594
40595		this.emissive = new Color(0x000000);
40596		this.emissiveIntensity = 1.0;
40597		this.emissiveMap = null;
40598
40599		this.bumpMap = null;
40600		this.bumpScale = 1;
40601
40602		this.normalMap = null;
40603		this.normalMapType = TangentSpaceNormalMap;
40604		this.normalScale = new Vector2(1, 1);
40605
40606		this.displacementMap = null;
40607		this.displacementScale = 1;
40608		this.displacementBias = 0;
40609
40610		this.roughnessMap = null;
40611
40612		this.metalnessMap = null;
40613
40614		this.alphaMap = null;
40615
40616		this.envMap = null;
40617		this.envMapIntensity = 1.0;
40618
40619		this.wireframe = false;
40620		this.wireframeLinewidth = 1;
40621		this.wireframeLinecap = 'round';
40622		this.wireframeLinejoin = 'round';
40623
40624		this.flatShading = false;
40625
40626		this.fog = true;
40627
40628		this.setValues(parameters);
40629
40630	}
40631
40632	copy(source) {
40633
40634		super.copy(source);
40635
40636		this.defines = { 'STANDARD': '' };
40637
40638		this.color.copy(source.color);
40639		this.roughness = source.roughness;
40640		this.metalness = source.metalness;
40641
40642		this.map = source.map;
40643
40644		this.lightMap = source.lightMap;
40645		this.lightMapIntensity = source.lightMapIntensity;
40646
40647		this.aoMap = source.aoMap;
40648		this.aoMapIntensity = source.aoMapIntensity;
40649
40650		this.emissive.copy(source.emissive);
40651		this.emissiveMap = source.emissiveMap;
40652		this.emissiveIntensity = source.emissiveIntensity;
40653
40654		this.bumpMap = source.bumpMap;
40655		this.bumpScale = source.bumpScale;
40656
40657		this.normalMap = source.normalMap;
40658		this.normalMapType = source.normalMapType;
40659		this.normalScale.copy(source.normalScale);
40660
40661		this.displacementMap = source.displacementMap;
40662		this.displacementScale = source.displacementScale;
40663		this.displacementBias = source.displacementBias;
40664
40665		this.roughnessMap = source.roughnessMap;
40666
40667		this.metalnessMap = source.metalnessMap;
40668
40669		this.alphaMap = source.alphaMap;
40670
40671		this.envMap = source.envMap;
40672		this.envMapIntensity = source.envMapIntensity;
40673
40674		this.wireframe = source.wireframe;
40675		this.wireframeLinewidth = source.wireframeLinewidth;
40676		this.wireframeLinecap = source.wireframeLinecap;
40677		this.wireframeLinejoin = source.wireframeLinejoin;
40678
40679		this.flatShading = source.flatShading;
40680
40681		this.fog = source.fog;
40682
40683		return this;
40684
40685	}
40686
40687}
40688
40689class MeshPhysicalMaterial extends MeshStandardMaterial {
40690
40691	constructor(parameters) {
40692
40693		super();
40694
40695		this.isMeshPhysicalMaterial = true;
40696
40697		this.defines = {
40698
40699			'STANDARD': '',
40700			'PHYSICAL': ''
40701
40702		};
40703
40704		this.type = 'MeshPhysicalMaterial';
40705
40706		this.anisotropyRotation = 0;
40707		this.anisotropyMap = null;
40708
40709		this.clearcoatMap = null;
40710		this.clearcoatRoughness = 0.0;
40711		this.clearcoatRoughnessMap = null;
40712		this.clearcoatNormalScale = new Vector2(1, 1);
40713		this.clearcoatNormalMap = null;
40714
40715		this.ior = 1.5;
40716
40717		Object.defineProperty(this, 'reflectivity', {
40718			get: function () {
40719
40720				return (clamp(2.5 * (this.ior - 1) / (this.ior + 1), 0, 1));
40721
40722			},
40723			set: function (reflectivity) {
40724
40725				this.ior = (1 + 0.4 * reflectivity) / (1 - 0.4 * reflectivity);
40726
40727			}
40728		});
40729
40730		this.iridescenceMap = null;
40731		this.iridescenceIOR = 1.3;
40732		this.iridescenceThicknessRange = [100, 400];
40733		this.iridescenceThicknessMap = null;
40734
40735		this.sheenColor = new Color(0x000000);
40736		this.sheenColorMap = null;
40737		this.sheenRoughness = 1.0;
40738		this.sheenRoughnessMap = null;
40739
40740		this.transmissionMap = null;
40741
40742		this.thickness = 0;
40743		this.thicknessMap = null;
40744		this.attenuationDistance = Infinity;
40745		this.attenuationColor = new Color(1, 1, 1);
40746
40747		this.specularIntensity = 1.0;
40748		this.specularIntensityMap = null;
40749		this.specularColor = new Color(1, 1, 1);
40750		this.specularColorMap = null;
40751
40752		this._anisotropy = 0;
40753		this._clearcoat = 0;
40754		this._iridescence = 0;
40755		this._sheen = 0.0;
40756		this._transmission = 0;
40757
40758		this.setValues(parameters);
40759
40760	}
40761
40762	get anisotropy() {
40763
40764		return this._anisotropy;
40765
40766	}
40767
40768	set anisotropy(value) {
40769
40770		if (this._anisotropy > 0 !== value > 0) {
40771
40772			this.version++;
40773
40774		}
40775
40776		this._anisotropy = value;
40777
40778	}
40779
40780	get clearcoat() {
40781
40782		return this._clearcoat;
40783
40784	}
40785
40786	set clearcoat(value) {
40787
40788		if (this._clearcoat > 0 !== value > 0) {
40789
40790			this.version++;
40791
40792		}
40793
40794		this._clearcoat = value;
40795
40796	}
40797
40798	get iridescence() {
40799
40800		return this._iridescence;
40801
40802	}
40803
40804	set iridescence(value) {
40805
40806		if (this._iridescence > 0 !== value > 0) {
40807
40808			this.version++;
40809
40810		}
40811
40812		this._iridescence = value;
40813
40814	}
40815
40816	get sheen() {
40817
40818		return this._sheen;
40819
40820	}
40821
40822	set sheen(value) {
40823
40824		if (this._sheen > 0 !== value > 0) {
40825
40826			this.version++;
40827
40828		}
40829
40830		this._sheen = value;
40831
40832	}
40833
40834	get transmission() {
40835
40836		return this._transmission;
40837
40838	}
40839
40840	set transmission(value) {
40841
40842		if (this._transmission > 0 !== value > 0) {
40843
40844			this.version++;
40845
40846		}
40847
40848		this._transmission = value;
40849
40850	}
40851
40852	copy(source) {
40853
40854		super.copy(source);
40855
40856		this.defines = {
40857
40858			'STANDARD': '',
40859			'PHYSICAL': ''
40860
40861		};
40862
40863		this.anisotropy = source.anisotropy;
40864		this.anisotropyRotation = source.anisotropyRotation;
40865		this.anisotropyMap = source.anisotropyMap;
40866
40867		this.clearcoat = source.clearcoat;
40868		this.clearcoatMap = source.clearcoatMap;
40869		this.clearcoatRoughness = source.clearcoatRoughness;
40870		this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
40871		this.clearcoatNormalMap = source.clearcoatNormalMap;
40872		this.clearcoatNormalScale.copy(source.clearcoatNormalScale);
40873
40874		this.ior = source.ior;
40875
40876		this.iridescence = source.iridescence;
40877		this.iridescenceMap = source.iridescenceMap;
40878		this.iridescenceIOR = source.iridescenceIOR;
40879		this.iridescenceThicknessRange = [...source.iridescenceThicknessRange];
40880		this.iridescenceThicknessMap = source.iridescenceThicknessMap;
40881
40882		this.sheen = source.sheen;
40883		this.sheenColor.copy(source.sheenColor);
40884		this.sheenColorMap = source.sheenColorMap;
40885		this.sheenRoughness = source.sheenRoughness;
40886		this.sheenRoughnessMap = source.sheenRoughnessMap;
40887
40888		this.transmission = source.transmission;
40889		this.transmissionMap = source.transmissionMap;
40890
40891		this.thickness = source.thickness;
40892		this.thicknessMap = source.thicknessMap;
40893		this.attenuationDistance = source.attenuationDistance;
40894		this.attenuationColor.copy(source.attenuationColor);
40895
40896		this.specularIntensity = source.specularIntensity;
40897		this.specularIntensityMap = source.specularIntensityMap;
40898		this.specularColor.copy(source.specularColor);
40899		this.specularColorMap = source.specularColorMap;
40900
40901		return this;
40902
40903	}
40904
40905}
40906
40907class MeshPhongMaterial extends Material {
40908
40909	constructor(parameters) {
40910
40911		super();
40912
40913		this.isMeshPhongMaterial = true;
40914
40915		this.type = 'MeshPhongMaterial';
40916
40917		this.color = new Color(0xffffff); // diffuse
40918		this.specular = new Color(0x111111);
40919		this.shininess = 30;
40920
40921		this.map = null;
40922
40923		this.lightMap = null;
40924		this.lightMapIntensity = 1.0;
40925
40926		this.aoMap = null;
40927		this.aoMapIntensity = 1.0;
40928
40929		this.emissive = new Color(0x000000);
40930		this.emissiveIntensity = 1.0;
40931		this.emissiveMap = null;
40932
40933		this.bumpMap = null;
40934		this.bumpScale = 1;
40935
40936		this.normalMap = null;
40937		this.normalMapType = TangentSpaceNormalMap;
40938		this.normalScale = new Vector2(1, 1);
40939
40940		this.displacementMap = null;
40941		this.displacementScale = 1;
40942		this.displacementBias = 0;
40943
40944		this.specularMap = null;
40945
40946		this.alphaMap = null;
40947
40948		this.envMap = null;
40949		this.combine = MultiplyOperation;
40950		this.reflectivity = 1;
40951		this.refractionRatio = 0.98;
40952
40953		this.wireframe = false;
40954		this.wireframeLinewidth = 1;
40955		this.wireframeLinecap = 'round';
40956		this.wireframeLinejoin = 'round';
40957
40958		this.flatShading = false;
40959
40960		this.fog = true;
40961
40962		this.setValues(parameters);
40963
40964	}
40965
40966	copy(source) {
40967
40968		super.copy(source);
40969
40970		this.color.copy(source.color);
40971		this.specular.copy(source.specular);
40972		this.shininess = source.shininess;
40973
40974		this.map = source.map;
40975
40976		this.lightMap = source.lightMap;
40977		this.lightMapIntensity = source.lightMapIntensity;
40978
40979		this.aoMap = source.aoMap;
40980		this.aoMapIntensity = source.aoMapIntensity;
40981
40982		this.emissive.copy(source.emissive);
40983		this.emissiveMap = source.emissiveMap;
40984		this.emissiveIntensity = source.emissiveIntensity;
40985
40986		this.bumpMap = source.bumpMap;
40987		this.bumpScale = source.bumpScale;
40988
40989		this.normalMap = source.normalMap;
40990		this.normalMapType = source.normalMapType;
40991		this.normalScale.copy(source.normalScale);
40992
40993		this.displacementMap = source.displacementMap;
40994		this.displacementScale = source.displacementScale;
40995		this.displacementBias = source.displacementBias;
40996
40997		this.specularMap = source.specularMap;
40998
40999		this.alphaMap = source.alphaMap;
41000
41001		this.envMap = source.envMap;
41002		this.combine = source.combine;
41003		this.reflectivity = source.reflectivity;
41004		this.refractionRatio = source.refractionRatio;
41005
41006		this.wireframe = source.wireframe;
41007		this.wireframeLinewidth = source.wireframeLinewidth;
41008		this.wireframeLinecap = source.wireframeLinecap;
41009		this.wireframeLinejoin = source.wireframeLinejoin;
41010
41011		this.flatShading = source.flatShading;
41012
41013		this.fog = source.fog;
41014
41015		return this;
41016
41017	}
41018
41019}
41020
41021class MeshToonMaterial extends Material {
41022
41023	constructor(parameters) {
41024
41025		super();
41026
41027		this.isMeshToonMaterial = true;
41028
41029		this.defines = { 'TOON': '' };
41030
41031		this.type = 'MeshToonMaterial';
41032
41033		this.color = new Color(0xffffff);
41034
41035		this.map = null;
41036		this.gradientMap = null;
41037
41038		this.lightMap = null;
41039		this.lightMapIntensity = 1.0;
41040
41041		this.aoMap = null;
41042		this.aoMapIntensity = 1.0;
41043
41044		this.emissive = new Color(0x000000);
41045		this.emissiveIntensity = 1.0;
41046		this.emissiveMap = null;
41047
41048		this.bumpMap = null;
41049		this.bumpScale = 1;
41050
41051		this.normalMap = null;
41052		this.normalMapType = TangentSpaceNormalMap;
41053		this.normalScale = new Vector2(1, 1);
41054
41055		this.displacementMap = null;
41056		this.displacementScale = 1;
41057		this.displacementBias = 0;
41058
41059		this.alphaMap = null;
41060
41061		this.wireframe = false;
41062		this.wireframeLinewidth = 1;
41063		this.wireframeLinecap = 'round';
41064		this.wireframeLinejoin = 'round';
41065
41066		this.fog = true;
41067
41068		this.setValues(parameters);
41069
41070	}
41071
41072	copy(source) {
41073
41074		super.copy(source);
41075
41076		this.color.copy(source.color);
41077
41078		this.map = source.map;
41079		this.gradientMap = source.gradientMap;
41080
41081		this.lightMap = source.lightMap;
41082		this.lightMapIntensity = source.lightMapIntensity;
41083
41084		this.aoMap = source.aoMap;
41085		this.aoMapIntensity = source.aoMapIntensity;
41086
41087		this.emissive.copy(source.emissive);
41088		this.emissiveMap = source.emissiveMap;
41089		this.emissiveIntensity = source.emissiveIntensity;
41090
41091		this.bumpMap = source.bumpMap;
41092		this.bumpScale = source.bumpScale;
41093
41094		this.normalMap = source.normalMap;
41095		this.normalMapType = source.normalMapType;
41096		this.normalScale.copy(source.normalScale);
41097
41098		this.displacementMap = source.displacementMap;
41099		this.displacementScale = source.displacementScale;
41100		this.displacementBias = source.displacementBias;
41101
41102		this.alphaMap = source.alphaMap;
41103
41104		this.wireframe = source.wireframe;
41105		this.wireframeLinewidth = source.wireframeLinewidth;
41106		this.wireframeLinecap = source.wireframeLinecap;
41107		this.wireframeLinejoin = source.wireframeLinejoin;
41108
41109		this.fog = source.fog;
41110
41111		return this;
41112
41113	}
41114
41115}
41116
41117class MeshNormalMaterial extends Material {
41118
41119	constructor(parameters) {
41120
41121		super();
41122
41123		this.isMeshNormalMaterial = true;
41124
41125		this.type = 'MeshNormalMaterial';
41126
41127		this.bumpMap = null;
41128		this.bumpScale = 1;
41129
41130		this.normalMap = null;
41131		this.normalMapType = TangentSpaceNormalMap;
41132		this.normalScale = new Vector2(1, 1);
41133
41134		this.displacementMap = null;
41135		this.displacementScale = 1;
41136		this.displacementBias = 0;
41137
41138		this.wireframe = false;
41139		this.wireframeLinewidth = 1;
41140
41141		this.flatShading = false;
41142
41143		this.setValues(parameters);
41144
41145	}
41146
41147	copy(source) {
41148
41149		super.copy(source);
41150
41151		this.bumpMap = source.bumpMap;
41152		this.bumpScale = source.bumpScale;
41153
41154		this.normalMap = source.normalMap;
41155		this.normalMapType = source.normalMapType;
41156		this.normalScale.copy(source.normalScale);
41157
41158		this.displacementMap = source.displacementMap;
41159		this.displacementScale = source.displacementScale;
41160		this.displacementBias = source.displacementBias;
41161
41162		this.wireframe = source.wireframe;
41163		this.wireframeLinewidth = source.wireframeLinewidth;
41164
41165		this.flatShading = source.flatShading;
41166
41167		return this;
41168
41169	}
41170
41171}
41172
41173class MeshLambertMaterial extends Material {
41174
41175	constructor(parameters) {
41176
41177		super();
41178
41179		this.isMeshLambertMaterial = true;
41180
41181		this.type = 'MeshLambertMaterial';
41182
41183		this.color = new Color(0xffffff); // diffuse
41184
41185		this.map = null;
41186
41187		this.lightMap = null;
41188		this.lightMapIntensity = 1.0;
41189
41190		this.aoMap = null;
41191		this.aoMapIntensity = 1.0;
41192
41193		this.emissive = new Color(0x000000);
41194		this.emissiveIntensity = 1.0;
41195		this.emissiveMap = null;
41196
41197		this.bumpMap = null;
41198		this.bumpScale = 1;
41199
41200		this.normalMap = null;
41201		this.normalMapType = TangentSpaceNormalMap;
41202		this.normalScale = new Vector2(1, 1);
41203
41204		this.displacementMap = null;
41205		this.displacementScale = 1;
41206		this.displacementBias = 0;
41207
41208		this.specularMap = null;
41209
41210		this.alphaMap = null;
41211
41212		this.envMap = null;
41213		this.combine = MultiplyOperation;
41214		this.reflectivity = 1;
41215		this.refractionRatio = 0.98;
41216
41217		this.wireframe = false;
41218		this.wireframeLinewidth = 1;
41219		this.wireframeLinecap = 'round';
41220		this.wireframeLinejoin = 'round';
41221
41222		this.flatShading = false;
41223
41224		this.fog = true;
41225
41226		this.setValues(parameters);
41227
41228	}
41229
41230	copy(source) {
41231
41232		super.copy(source);
41233
41234		this.color.copy(source.color);
41235
41236		this.map = source.map;
41237
41238		this.lightMap = source.lightMap;
41239		this.lightMapIntensity = source.lightMapIntensity;
41240
41241		this.aoMap = source.aoMap;
41242		this.aoMapIntensity = source.aoMapIntensity;
41243
41244		this.emissive.copy(source.emissive);
41245		this.emissiveMap = source.emissiveMap;
41246		this.emissiveIntensity = source.emissiveIntensity;
41247
41248		this.bumpMap = source.bumpMap;
41249		this.bumpScale = source.bumpScale;
41250
41251		this.normalMap = source.normalMap;
41252		this.normalMapType = source.normalMapType;
41253		this.normalScale.copy(source.normalScale);
41254
41255		this.displacementMap = source.displacementMap;
41256		this.displacementScale = source.displacementScale;
41257		this.displacementBias = source.displacementBias;
41258
41259		this.specularMap = source.specularMap;
41260
41261		this.alphaMap = source.alphaMap;
41262
41263		this.envMap = source.envMap;
41264		this.combine = source.combine;
41265		this.reflectivity = source.reflectivity;
41266		this.refractionRatio = source.refractionRatio;
41267
41268		this.wireframe = source.wireframe;
41269		this.wireframeLinewidth = source.wireframeLinewidth;
41270		this.wireframeLinecap = source.wireframeLinecap;
41271		this.wireframeLinejoin = source.wireframeLinejoin;
41272
41273		this.flatShading = source.flatShading;
41274
41275		this.fog = source.fog;
41276
41277		return this;
41278
41279	}
41280
41281}
41282
41283class MeshMatcapMaterial extends Material {
41284
41285	constructor(parameters) {
41286
41287		super();
41288
41289		this.isMeshMatcapMaterial = true;
41290
41291		this.defines = { 'MATCAP': '' };
41292
41293		this.type = 'MeshMatcapMaterial';
41294
41295		this.color = new Color(0xffffff); // diffuse
41296
41297		this.matcap = null;
41298
41299		this.map = null;
41300
41301		this.bumpMap = null;
41302		this.bumpScale = 1;
41303
41304		this.normalMap = null;
41305		this.normalMapType = TangentSpaceNormalMap;
41306		this.normalScale = new Vector2(1, 1);
41307
41308		this.displacementMap = null;
41309		this.displacementScale = 1;
41310		this.displacementBias = 0;
41311
41312		this.alphaMap = null;
41313
41314		this.flatShading = false;
41315
41316		this.fog = true;
41317
41318		this.setValues(parameters);
41319
41320	}
41321
41322
41323	copy(source) {
41324
41325		super.copy(source);
41326
41327		this.defines = { 'MATCAP': '' };
41328
41329		this.color.copy(source.color);
41330
41331		this.matcap = source.matcap;
41332
41333		this.map = source.map;
41334
41335		this.bumpMap = source.bumpMap;
41336		this.bumpScale = source.bumpScale;
41337
41338		this.normalMap = source.normalMap;
41339		this.normalMapType = source.normalMapType;
41340		this.normalScale.copy(source.normalScale);
41341
41342		this.displacementMap = source.displacementMap;
41343		this.displacementScale = source.displacementScale;
41344		this.displacementBias = source.displacementBias;
41345
41346		this.alphaMap = source.alphaMap;
41347
41348		this.flatShading = source.flatShading;
41349
41350		this.fog = source.fog;
41351
41352		return this;
41353
41354	}
41355
41356}
41357
41358class LineDashedMaterial extends LineBasicMaterial {
41359
41360	constructor(parameters) {
41361
41362		super();
41363
41364		this.isLineDashedMaterial = true;
41365
41366		this.type = 'LineDashedMaterial';
41367
41368		this.scale = 1;
41369		this.dashSize = 3;
41370		this.gapSize = 1;
41371
41372		this.setValues(parameters);
41373
41374	}
41375
41376	copy(source) {
41377
41378		super.copy(source);
41379
41380		this.scale = source.scale;
41381		this.dashSize = source.dashSize;
41382		this.gapSize = source.gapSize;
41383
41384		return this;
41385
41386	}
41387
41388}
41389
41390// converts an array to a specific type
41391function convertArray(array, type, forceClone) {
41392
41393	if (!array || // let 'undefined' and 'null' pass
41394		!forceClone && array.constructor === type) return array;
41395
41396	if (typeof type.BYTES_PER_ELEMENT === 'number') {
41397
41398		return new type(array); // create typed array
41399
41400	}
41401
41402	return Array.prototype.slice.call(array); // create Array
41403
41404}
41405
41406function isTypedArray(object) {
41407
41408	return ArrayBuffer.isView(object) &&
41409		!(object instanceof DataView);
41410
41411}
41412
41413// returns an array by which times and values can be sorted
41414function getKeyframeOrder(times) {
41415
41416	function compareTime(i, j) {
41417
41418		return times[i] - times[j];
41419
41420	}
41421
41422	const n = times.length;
41423	const result = new Array(n);
41424	for (let i = 0; i !== n; ++i) result[i] = i;
41425
41426	result.sort(compareTime);
41427
41428	return result;
41429
41430}
41431
41432// uses the array previously returned by 'getKeyframeOrder' to sort data
41433function sortedArray(values, stride, order) {
41434
41435	const nValues = values.length;
41436	const result = new values.constructor(nValues);
41437
41438	for (let i = 0, dstOffset = 0; dstOffset !== nValues; ++i) {
41439
41440		const srcOffset = order[i] * stride;
41441
41442		for (let j = 0; j !== stride; ++j) {
41443
41444			result[dstOffset++] = values[srcOffset + j];
41445
41446		}
41447
41448	}
41449
41450	return result;
41451
41452}
41453
41454// function for parsing AOS keyframe formats
41455function flattenJSON(jsonKeys, times, values, valuePropertyName) {
41456
41457	let i = 1, key = jsonKeys[0];
41458
41459	while (key !== undefined && key[valuePropertyName] === undefined) {
41460
41461		key = jsonKeys[i++];
41462
41463	}
41464
41465	if (key === undefined) return; // no data
41466
41467	let value = key[valuePropertyName];
41468	if (value === undefined) return; // no data
41469
41470	if (Array.isArray(value)) {
41471
41472		do {
41473
41474			value = key[valuePropertyName];
41475
41476			if (value !== undefined) {
41477
41478				times.push(key.time);
41479				values.push.apply(values, value); // push all elements
41480
41481			}
41482
41483			key = jsonKeys[i++];
41484
41485		} while (key !== undefined);
41486
41487	} else if (value.toArray !== undefined) {
41488
41489		// ...assume THREE.Math-ish
41490
41491		do {
41492
41493			value = key[valuePropertyName];
41494
41495			if (value !== undefined) {
41496
41497				times.push(key.time);
41498				value.toArray(values, values.length);
41499
41500			}
41501
41502			key = jsonKeys[i++];
41503
41504		} while (key !== undefined);
41505
41506	} else {
41507
41508		// otherwise push as-is
41509
41510		do {
41511
41512			value = key[valuePropertyName];
41513
41514			if (value !== undefined) {
41515
41516				times.push(key.time);
41517				values.push(value);
41518
41519			}
41520
41521			key = jsonKeys[i++];
41522
41523		} while (key !== undefined);
41524
41525	}
41526
41527}
41528
41529function subclip(sourceClip, name, startFrame, endFrame, fps = 30) {
41530
41531	const clip = sourceClip.clone();
41532
41533	clip.name = name;
41534
41535	const tracks = [];
41536
41537	for (let i = 0; i < clip.tracks.length; ++i) {
41538
41539		const track = clip.tracks[i];
41540		const valueSize = track.getValueSize();
41541
41542		const times = [];
41543		const values = [];
41544
41545		for (let j = 0; j < track.times.length; ++j) {
41546
41547			const frame = track.times[j] * fps;
41548
41549			if (frame < startFrame || frame >= endFrame) continue;
41550
41551			times.push(track.times[j]);
41552
41553			for (let k = 0; k < valueSize; ++k) {
41554
41555				values.push(track.values[j * valueSize + k]);
41556
41557			}
41558
41559		}
41560
41561		if (times.length === 0) continue;
41562
41563		track.times = convertArray(times, track.times.constructor);
41564		track.values = convertArray(values, track.values.constructor);
41565
41566		tracks.push(track);
41567
41568	}
41569
41570	clip.tracks = tracks;
41571
41572	// find minimum .times value across all tracks in the trimmed clip
41573
41574	let minStartTime = Infinity;
41575
41576	for (let i = 0; i < clip.tracks.length; ++i) {
41577
41578		if (minStartTime > clip.tracks[i].times[0]) {
41579
41580			minStartTime = clip.tracks[i].times[0];
41581
41582		}
41583
41584	}
41585
41586	// shift all tracks such that clip begins at t=0
41587
41588	for (let i = 0; i < clip.tracks.length; ++i) {
41589
41590		clip.tracks[i].shift(- 1 * minStartTime);
41591
41592	}
41593
41594	clip.resetDuration();
41595
41596	return clip;
41597
41598}
41599
41600function makeClipAdditive(targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30) {
41601
41602	if (fps <= 0) fps = 30;
41603
41604	const numTracks = referenceClip.tracks.length;
41605	const referenceTime = referenceFrame / fps;
41606
41607	// Make each track's values relative to the values at the reference frame
41608	for (let i = 0; i < numTracks; ++i) {
41609
41610		const referenceTrack = referenceClip.tracks[i];
41611		const referenceTrackType = referenceTrack.ValueTypeName;
41612
41613		// Skip this track if it's non-numeric
41614		if (referenceTrackType === 'bool' || referenceTrackType === 'string') continue;
41615
41616		// Find the track in the target clip whose name and type matches the reference track
41617		const targetTrack = targetClip.tracks.find(function (track) {
41618
41619			return track.name === referenceTrack.name
41620				&& track.ValueTypeName === referenceTrackType;
41621
41622		});
41623
41624		if (targetTrack === undefined) continue;
41625
41626		let referenceOffset = 0;
41627		const referenceValueSize = referenceTrack.getValueSize();
41628
41629		if (referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) {
41630
41631			referenceOffset = referenceValueSize / 3;
41632
41633		}
41634
41635		let targetOffset = 0;
41636		const targetValueSize = targetTrack.getValueSize();
41637
41638		if (targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline) {
41639
41640			targetOffset = targetValueSize / 3;
41641
41642		}
41643
41644		const lastIndex = referenceTrack.times.length - 1;
41645		let referenceValue;
41646
41647		// Find the value to subtract out of the track
41648		if (referenceTime <= referenceTrack.times[0]) {
41649
41650			// Reference frame is earlier than the first keyframe, so just use the first keyframe
41651			const startIndex = referenceOffset;
41652			const endIndex = referenceValueSize - referenceOffset;
41653			referenceValue = referenceTrack.values.slice(startIndex, endIndex);
41654
41655		} else if (referenceTime >= referenceTrack.times[lastIndex]) {
41656
41657			// Reference frame is after the last keyframe, so just use the last keyframe
41658			const startIndex = lastIndex * referenceValueSize + referenceOffset;
41659			const endIndex = startIndex + referenceValueSize - referenceOffset;
41660			referenceValue = referenceTrack.values.slice(startIndex, endIndex);
41661
41662		} else {
41663
41664			// Interpolate to the reference value
41665			const interpolant = referenceTrack.createInterpolant();
41666			const startIndex = referenceOffset;
41667			const endIndex = referenceValueSize - referenceOffset;
41668			interpolant.evaluate(referenceTime);
41669			referenceValue = interpolant.resultBuffer.slice(startIndex, endIndex);
41670
41671		}
41672
41673		// Conjugate the quaternion
41674		if (referenceTrackType === 'quaternion') {
41675
41676			const referenceQuat = new Quaternion().fromArray(referenceValue).normalize().conjugate();
41677			referenceQuat.toArray(referenceValue);
41678
41679		}
41680
41681		// Subtract the reference value from all of the track values
41682
41683		const numTimes = targetTrack.times.length;
41684		for (let j = 0; j < numTimes; ++j) {
41685
41686			const valueStart = j * targetValueSize + targetOffset;
41687
41688			if (referenceTrackType === 'quaternion') {
41689
41690				// Multiply the conjugate for quaternion track types
41691				Quaternion.multiplyQuaternionsFlat(
41692					targetTrack.values,
41693					valueStart,
41694					referenceValue,
41695					0,
41696					targetTrack.values,
41697					valueStart
41698				);
41699
41700			} else {
41701
41702				const valueEnd = targetValueSize - targetOffset * 2;
41703
41704				// Subtract each value for all other numeric track types
41705				for (let k = 0; k < valueEnd; ++k) {
41706
41707					targetTrack.values[valueStart + k] -= referenceValue[k];
41708
41709				}
41710
41711			}
41712
41713		}
41714
41715	}
41716
41717	targetClip.blendMode = AdditiveAnimationBlendMode;
41718
41719	return targetClip;
41720
41721}
41722
41723const AnimationUtils = {
41724	convertArray: convertArray,
41725	isTypedArray: isTypedArray,
41726	getKeyframeOrder: getKeyframeOrder,
41727	sortedArray: sortedArray,
41728	flattenJSON: flattenJSON,
41729	subclip: subclip,
41730	makeClipAdditive: makeClipAdditive
41731};
41732
41733/**
41734 * Abstract base class of interpolants over parametric samples.
41735 *
41736 * The parameter domain is one dimensional, typically the time or a path
41737 * along a curve defined by the data.
41738 *
41739 * The sample values can have any dimensionality and derived classes may
41740 * apply special interpretations to the data.
41741 *
41742 * This class provides the interval seek in a Template Method, deferring
41743 * the actual interpolation to derived classes.
41744 *
41745 * Time complexity is O(1) for linear access crossing at most two points
41746 * and O(log N) for random access, where N is the number of positions.
41747 *
41748 * References:
41749 *
41750 * 		http://www.oodesign.com/template-method-pattern.html
41751 *
41752 */
41753
41754class Interpolant {
41755
41756	constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
41757
41758		this.parameterPositions = parameterPositions;
41759		this._cachedIndex = 0;
41760
41761		this.resultBuffer = resultBuffer !== undefined ?
41762			resultBuffer : new sampleValues.constructor(sampleSize);
41763		this.sampleValues = sampleValues;
41764		this.valueSize = sampleSize;
41765
41766		this.settings = null;
41767		this.DefaultSettings_ = {};
41768
41769	}
41770
41771	evaluate(t) {
41772
41773		const pp = this.parameterPositions;
41774		let i1 = this._cachedIndex,
41775			t1 = pp[i1],
41776			t0 = pp[i1 - 1];
41777
41778		validate_interval: {
41779
41780			seek: {
41781
41782				let right;
41783
41784				linear_scan: {
41785
41786					//- See http://jsperf.com/comparison-to-undefined/3
41787					//- slower code:
41788					//-
41789					//- 				if ( t >= t1 || t1 === undefined ) {
41790					forward_scan: if (!(t < t1)) {
41791
41792						for (let giveUpAt = i1 + 2; ;) {
41793
41794							if (t1 === undefined) {
41795
41796								if (t < t0) break forward_scan;
41797
41798								// after end
41799
41800								i1 = pp.length;
41801								this._cachedIndex = i1;
41802								return this.copySampleValue_(i1 - 1);
41803
41804							}
41805
41806							if (i1 === giveUpAt) break; // this loop
41807
41808							t0 = t1;
41809							t1 = pp[++i1];
41810
41811							if (t < t1) {
41812
41813								// we have arrived at the sought interval
41814								break seek;
41815
41816							}
41817
41818						}
41819
41820						// prepare binary search on the right side of the index
41821						right = pp.length;
41822						break linear_scan;
41823
41824					}
41825
41826					//- slower code:
41827					//-					if ( t < t0 || t0 === undefined ) {
41828					if (!(t >= t0)) {
41829
41830						// looping?
41831
41832						const t1global = pp[1];
41833
41834						if (t < t1global) {
41835
41836							i1 = 2; // + 1, using the scan for the details
41837							t0 = t1global;
41838
41839						}
41840
41841						// linear reverse scan
41842
41843						for (let giveUpAt = i1 - 2; ;) {
41844
41845							if (t0 === undefined) {
41846
41847								// before start
41848
41849								this._cachedIndex = 0;
41850								return this.copySampleValue_(0);
41851
41852							}
41853
41854							if (i1 === giveUpAt) break; // this loop
41855
41856							t1 = t0;
41857							t0 = pp[--i1 - 1];
41858
41859							if (t >= t0) {
41860
41861								// we have arrived at the sought interval
41862								break seek;
41863
41864							}
41865
41866						}
41867
41868						// prepare binary search on the left side of the index
41869						right = i1;
41870						i1 = 0;
41871						break linear_scan;
41872
41873					}
41874
41875					// the interval is valid
41876
41877					break validate_interval;
41878
41879				} // linear scan
41880
41881				// binary search
41882
41883				while (i1 < right) {
41884
41885					const mid = (i1 + right) >>> 1;
41886
41887					if (t < pp[mid]) {
41888
41889						right = mid;
41890
41891					} else {
41892
41893						i1 = mid + 1;
41894
41895					}
41896
41897				}
41898
41899				t1 = pp[i1];
41900				t0 = pp[i1 - 1];
41901
41902				// check boundary cases, again
41903
41904				if (t0 === undefined) {
41905
41906					this._cachedIndex = 0;
41907					return this.copySampleValue_(0);
41908
41909				}
41910
41911				if (t1 === undefined) {
41912
41913					i1 = pp.length;
41914					this._cachedIndex = i1;
41915					return this.copySampleValue_(i1 - 1);
41916
41917				}
41918
41919			} // seek
41920
41921			this._cachedIndex = i1;
41922
41923			this.intervalChanged_(i1, t0, t1);
41924
41925		} // validate_interval
41926
41927		return this.interpolate_(i1, t0, t, t1);
41928
41929	}
41930
41931	getSettings_() {
41932
41933		return this.settings || this.DefaultSettings_;
41934
41935	}
41936
41937	copySampleValue_(index) {
41938
41939		// copies a sample value to the result buffer
41940
41941		const result = this.resultBuffer,
41942			values = this.sampleValues,
41943			stride = this.valueSize,
41944			offset = index * stride;
41945
41946		for (let i = 0; i !== stride; ++i) {
41947
41948			result[i] = values[offset + i];
41949
41950		}
41951
41952		return result;
41953
41954	}
41955
41956	// Template methods for derived classes:
41957
41958	interpolate_( /* i1, t0, t, t1 */) {
41959
41960		throw new Error('call to abstract method');
41961		// implementations shall return this.resultBuffer
41962
41963	}
41964
41965	intervalChanged_( /* i1, t0, t1 */) {
41966
41967		// empty
41968
41969	}
41970
41971}
41972
41973/**
41974 * Fast and simple cubic spline interpolant.
41975 *
41976 * It was derived from a Hermitian construction setting the first derivative
41977 * at each sample position to the linear slope between neighboring positions
41978 * over their parameter interval.
41979 */
41980
41981class CubicInterpolant extends Interpolant {
41982
41983	constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
41984
41985		super(parameterPositions, sampleValues, sampleSize, resultBuffer);
41986
41987		this._weightPrev = - 0;
41988		this._offsetPrev = - 0;
41989		this._weightNext = - 0;
41990		this._offsetNext = - 0;
41991
41992		this.DefaultSettings_ = {
41993
41994			endingStart: ZeroCurvatureEnding,
41995			endingEnd: ZeroCurvatureEnding
41996
41997		};
41998
41999	}
42000
42001	intervalChanged_(i1, t0, t1) {
42002
42003		const pp = this.parameterPositions;
42004		let iPrev = i1 - 2,
42005			iNext = i1 + 1,
42006
42007			tPrev = pp[iPrev],
42008			tNext = pp[iNext];
42009
42010		if (tPrev === undefined) {
42011
42012			switch (this.getSettings_().endingStart) {
42013
42014				case ZeroSlopeEnding:
42015
42016					// f'(t0) = 0
42017					iPrev = i1;
42018					tPrev = 2 * t0 - t1;
42019
42020					break;
42021
42022				case WrapAroundEnding:
42023
42024					// use the other end of the curve
42025					iPrev = pp.length - 2;
42026					tPrev = t0 + pp[iPrev] - pp[iPrev + 1];
42027
42028					break;
42029
42030				default: // ZeroCurvatureEnding
42031
42032					// f''(t0) = 0 a.k.a. Natural Spline
42033					iPrev = i1;
42034					tPrev = t1;
42035
42036			}
42037
42038		}
42039
42040		if (tNext === undefined) {
42041
42042			switch (this.getSettings_().endingEnd) {
42043
42044				case ZeroSlopeEnding:
42045
42046					// f'(tN) = 0
42047					iNext = i1;
42048					tNext = 2 * t1 - t0;
42049
42050					break;
42051
42052				case WrapAroundEnding:
42053
42054					// use the other end of the curve
42055					iNext = 1;
42056					tNext = t1 + pp[1] - pp[0];
42057
42058					break;
42059
42060				default: // ZeroCurvatureEnding
42061
42062					// f''(tN) = 0, a.k.a. Natural Spline
42063					iNext = i1 - 1;
42064					tNext = t0;
42065
42066			}
42067
42068		}
42069
42070		const halfDt = (t1 - t0) * 0.5,
42071			stride = this.valueSize;
42072
42073		this._weightPrev = halfDt / (t0 - tPrev);
42074		this._weightNext = halfDt / (tNext - t1);
42075		this._offsetPrev = iPrev * stride;
42076		this._offsetNext = iNext * stride;
42077
42078	}
42079
42080	interpolate_(i1, t0, t, t1) {
42081
42082		const result = this.resultBuffer,
42083			values = this.sampleValues,
42084			stride = this.valueSize,
42085
42086			o1 = i1 * stride, o0 = o1 - stride,
42087			oP = this._offsetPrev, oN = this._offsetNext,
42088			wP = this._weightPrev, wN = this._weightNext,
42089
42090			p = (t - t0) / (t1 - t0),
42091			pp = p * p,
42092			ppp = pp * p;
42093
42094		// evaluate polynomials
42095
42096		const sP = - wP * ppp + 2 * wP * pp - wP * p;
42097		const s0 = (1 + wP) * ppp + (- 1.5 - 2 * wP) * pp + (- 0.5 + wP) * p + 1;
42098		const s1 = (- 1 - wN) * ppp + (1.5 + wN) * pp + 0.5 * p;
42099		const sN = wN * ppp - wN * pp;
42100
42101		// combine data linearly
42102
42103		for (let i = 0; i !== stride; ++i) {
42104
42105			result[i] =
42106				sP * values[oP + i] +
42107				s0 * values[o0 + i] +
42108				s1 * values[o1 + i] +
42109				sN * values[oN + i];
42110
42111		}
42112
42113		return result;
42114
42115	}
42116
42117}
42118
42119class LinearInterpolant extends Interpolant {
42120
42121	constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
42122
42123		super(parameterPositions, sampleValues, sampleSize, resultBuffer);
42124
42125	}
42126
42127	interpolate_(i1, t0, t, t1) {
42128
42129		const result = this.resultBuffer,
42130			values = this.sampleValues,
42131			stride = this.valueSize,
42132
42133			offset1 = i1 * stride,
42134			offset0 = offset1 - stride,
42135
42136			weight1 = (t - t0) / (t1 - t0),
42137			weight0 = 1 - weight1;
42138
42139		for (let i = 0; i !== stride; ++i) {
42140
42141			result[i] =
42142				values[offset0 + i] * weight0 +
42143				values[offset1 + i] * weight1;
42144
42145		}
42146
42147		return result;
42148
42149	}
42150
42151}
42152
42153/**
42154 *
42155 * Interpolant that evaluates to the sample value at the position preceding
42156 * the parameter.
42157 */
42158
42159class DiscreteInterpolant extends Interpolant {
42160
42161	constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
42162
42163		super(parameterPositions, sampleValues, sampleSize, resultBuffer);
42164
42165	}
42166
42167	interpolate_(i1 /*, t0, t, t1 */) {
42168
42169		return this.copySampleValue_(i1 - 1);
42170
42171	}
42172
42173}
42174
42175class KeyframeTrack {
42176
42177	constructor(name, times, values, interpolation) {
42178
42179		if (name === undefined) throw new Error('THREE.KeyframeTrack: track name is undefined');
42180		if (times === undefined || times.length === 0) throw new Error('THREE.KeyframeTrack: no keyframes in track named ' + n
vendor: 26,993 bytes, lines 42180-43579
42180ame);
42181
42182		this.name = name;
42183
42184		this.times = convertArray(times, this.TimeBufferType);
42185		this.values = convertArray(values, this.ValueBufferType);
42186
42187		this.setInterpolation(interpolation || this.DefaultInterpolation);
42188
42189	}
42190
42191	// Serialization (in static context, because of constructor invocation
42192	// and automatic invocation of .toJSON):
42193
42194	static toJSON(track) {
42195
42196		const trackType = track.constructor;
42197
42198		let json;
42199
42200		// derived classes can define a static toJSON method
42201		if (trackType.toJSON !== this.toJSON) {
42202
42203			json = trackType.toJSON(track);
42204
42205		} else {
42206
42207			// by default, we assume the data can be serialized as-is
42208			json = {
42209
42210				'name': track.name,
42211				'times': convertArray(track.times, Array),
42212				'values': convertArray(track.values, Array)
42213
42214			};
42215
42216			const interpolation = track.getInterpolation();
42217
42218			if (interpolation !== track.DefaultInterpolation) {
42219
42220				json.interpolation = interpolation;
42221
42222			}
42223
42224		}
42225
42226		json.type = track.ValueTypeName; // mandatory
42227
42228		return json;
42229
42230	}
42231
42232	InterpolantFactoryMethodDiscrete(result) {
42233
42234		return new DiscreteInterpolant(this.times, this.values, this.getValueSize(), result);
42235
42236	}
42237
42238	InterpolantFactoryMethodLinear(result) {
42239
42240		return new LinearInterpolant(this.times, this.values, this.getValueSize(), result);
42241
42242	}
42243
42244	InterpolantFactoryMethodSmooth(result) {
42245
42246		return new CubicInterpolant(this.times, this.values, this.getValueSize(), result);
42247
42248	}
42249
42250	setInterpolation(interpolation) {
42251
42252		let factoryMethod;
42253
42254		switch (interpolation) {
42255
42256			case InterpolateDiscrete:
42257
42258				factoryMethod = this.InterpolantFactoryMethodDiscrete;
42259
42260				break;
42261
42262			case InterpolateLinear:
42263
42264				factoryMethod = this.InterpolantFactoryMethodLinear;
42265
42266				break;
42267
42268			case InterpolateSmooth:
42269
42270				factoryMethod = this.InterpolantFactoryMethodSmooth;
42271
42272				break;
42273
42274		}
42275
42276		if (factoryMethod === undefined) {
42277
42278			const message = 'unsupported interpolation for ' +
42279				this.ValueTypeName + ' keyframe track named ' + this.name;
42280
42281			if (this.createInterpolant === undefined) {
42282
42283				// fall back to default, unless the default itself is messed up
42284				if (interpolation !== this.DefaultInterpolation) {
42285
42286					this.setInterpolation(this.DefaultInterpolation);
42287
42288				} else {
42289
42290					throw new Error(message); // fatal, in this case
42291
42292				}
42293
42294			}
42295
42296			console.warn('THREE.KeyframeTrack:', message);
42297			return this;
42298
42299		}
42300
42301		this.createInterpolant = factoryMethod;
42302
42303		return this;
42304
42305	}
42306
42307	getInterpolation() {
42308
42309		switch (this.createInterpolant) {
42310
42311			case this.InterpolantFactoryMethodDiscrete:
42312
42313				return InterpolateDiscrete;
42314
42315			case this.InterpolantFactoryMethodLinear:
42316
42317				return InterpolateLinear;
42318
42319			case this.InterpolantFactoryMethodSmooth:
42320
42321				return InterpolateSmooth;
42322
42323		}
42324
42325	}
42326
42327	getValueSize() {
42328
42329		return this.values.length / this.times.length;
42330
42331	}
42332
42333	// move all keyframes either forwards or backwards in time
42334	shift(timeOffset) {
42335
42336		if (timeOffset !== 0.0) {
42337
42338			const times = this.times;
42339
42340			for (let i = 0, n = times.length; i !== n; ++i) {
42341
42342				times[i] += timeOffset;
42343
42344			}
42345
42346		}
42347
42348		return this;
42349
42350	}
42351
42352	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
42353	scale(timeScale) {
42354
42355		if (timeScale !== 1.0) {
42356
42357			const times = this.times;
42358
42359			for (let i = 0, n = times.length; i !== n; ++i) {
42360
42361				times[i] *= timeScale;
42362
42363			}
42364
42365		}
42366
42367		return this;
42368
42369	}
42370
42371	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
42372	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
42373	trim(startTime, endTime) {
42374
42375		const times = this.times,
42376			nKeys = times.length;
42377
42378		let from = 0,
42379			to = nKeys - 1;
42380
42381		while (from !== nKeys && times[from] < startTime) {
42382
42383			++from;
42384
42385		}
42386
42387		while (to !== - 1 && times[to] > endTime) {
42388
42389			--to;
42390
42391		}
42392
42393		++to; // inclusive -> exclusive bound
42394
42395		if (from !== 0 || to !== nKeys) {
42396
42397			// empty tracks are forbidden, so keep at least one keyframe
42398			if (from >= to) {
42399
42400				to = Math.max(to, 1);
42401				from = to - 1;
42402
42403			}
42404
42405			const stride = this.getValueSize();
42406			this.times = times.slice(from, to);
42407			this.values = this.values.slice(from * stride, to * stride);
42408
42409		}
42410
42411		return this;
42412
42413	}
42414
42415	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
42416	validate() {
42417
42418		let valid = true;
42419
42420		const valueSize = this.getValueSize();
42421		if (valueSize - Math.floor(valueSize) !== 0) {
42422
42423			console.error('THREE.KeyframeTrack: Invalid value size in track.', this);
42424			valid = false;
42425
42426		}
42427
42428		const times = this.times,
42429			values = this.values,
42430
42431			nKeys = times.length;
42432
42433		if (nKeys === 0) {
42434
42435			console.error('THREE.KeyframeTrack: Track is empty.', this);
42436			valid = false;
42437
42438		}
42439
42440		let prevTime = null;
42441
42442		for (let i = 0; i !== nKeys; i++) {
42443
42444			const currTime = times[i];
42445
42446			if (typeof currTime === 'number' && isNaN(currTime)) {
42447
42448				console.error('THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime);
42449				valid = false;
42450				break;
42451
42452			}
42453
42454			if (prevTime !== null && prevTime > currTime) {
42455
42456				console.error('THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime);
42457				valid = false;
42458				break;
42459
42460			}
42461
42462			prevTime = currTime;
42463
42464		}
42465
42466		if (values !== undefined) {
42467
42468			if (isTypedArray(values)) {
42469
42470				for (let i = 0, n = values.length; i !== n; ++i) {
42471
42472					const value = values[i];
42473
42474					if (isNaN(value)) {
42475
42476						console.error('THREE.KeyframeTrack: Value is not a valid number.', this, i, value);
42477						valid = false;
42478						break;
42479
42480					}
42481
42482				}
42483
42484			}
42485
42486		}
42487
42488		return valid;
42489
42490	}
42491
42492	// removes equivalent sequential keys as common in morph target sequences
42493	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
42494	optimize() {
42495
42496		// times or values may be shared with other tracks, so overwriting is unsafe
42497		const times = this.times.slice(),
42498			values = this.values.slice(),
42499			stride = this.getValueSize(),
42500
42501			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
42502
42503			lastIndex = times.length - 1;
42504
42505		let writeIndex = 1;
42506
42507		for (let i = 1; i < lastIndex; ++i) {
42508
42509			let keep = false;
42510
42511			const time = times[i];
42512			const timeNext = times[i + 1];
42513
42514			// remove adjacent keyframes scheduled at the same time
42515
42516			if (time !== timeNext && (i !== 1 || time !== times[0])) {
42517
42518				if (!smoothInterpolation) {
42519
42520					// remove unnecessary keyframes same as their neighbors
42521
42522					const offset = i * stride,
42523						offsetP = offset - stride,
42524						offsetN = offset + stride;
42525
42526					for (let j = 0; j !== stride; ++j) {
42527
42528						const value = values[offset + j];
42529
42530						if (value !== values[offsetP + j] ||
42531							value !== values[offsetN + j]) {
42532
42533							keep = true;
42534							break;
42535
42536						}
42537
42538					}
42539
42540				} else {
42541
42542					keep = true;
42543
42544				}
42545
42546			}
42547
42548			// in-place compaction
42549
42550			if (keep) {
42551
42552				if (i !== writeIndex) {
42553
42554					times[writeIndex] = times[i];
42555
42556					const readOffset = i * stride,
42557						writeOffset = writeIndex * stride;
42558
42559					for (let j = 0; j !== stride; ++j) {
42560
42561						values[writeOffset + j] = values[readOffset + j];
42562
42563					}
42564
42565				}
42566
42567				++writeIndex;
42568
42569			}
42570
42571		}
42572
42573		// flush last keyframe (compaction looks ahead)
42574
42575		if (lastIndex > 0) {
42576
42577			times[writeIndex] = times[lastIndex];
42578
42579			for (let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++j) {
42580
42581				values[writeOffset + j] = values[readOffset + j];
42582
42583			}
42584
42585			++writeIndex;
42586
42587		}
42588
42589		if (writeIndex !== times.length) {
42590
42591			this.times = times.slice(0, writeIndex);
42592			this.values = values.slice(0, writeIndex * stride);
42593
42594		} else {
42595
42596			this.times = times;
42597			this.values = values;
42598
42599		}
42600
42601		return this;
42602
42603	}
42604
42605	clone() {
42606
42607		const times = this.times.slice();
42608		const values = this.values.slice();
42609
42610		const TypedKeyframeTrack = this.constructor;
42611		const track = new TypedKeyframeTrack(this.name, times, values);
42612
42613		// Interpolant argument to constructor is not saved, so copy the factory method directly.
42614		track.createInterpolant = this.createInterpolant;
42615
42616		return track;
42617
42618	}
42619
42620}
42621
42622KeyframeTrack.prototype.TimeBufferType = Float32Array;
42623KeyframeTrack.prototype.ValueBufferType = Float32Array;
42624KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42625
42626/**
42627 * A Track of Boolean keyframe values.
42628 */
42629class BooleanKeyframeTrack extends KeyframeTrack { }
42630
42631BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
42632BooleanKeyframeTrack.prototype.ValueBufferType = Array;
42633BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42634BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
42635BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42636
42637/**
42638 * A Track of keyframe values that represent color.
42639 */
42640class ColorKeyframeTrack extends KeyframeTrack { }
42641
42642ColorKeyframeTrack.prototype.ValueTypeName = 'color';
42643
42644/**
42645 * A Track of numeric keyframe values.
42646 */
42647class NumberKeyframeTrack extends KeyframeTrack { }
42648
42649NumberKeyframeTrack.prototype.ValueTypeName = 'number';
42650
42651/**
42652 * Spherical linear unit quaternion interpolant.
42653 */
42654
42655class QuaternionLinearInterpolant extends Interpolant {
42656
42657	constructor(parameterPositions, sampleValues, sampleSize, resultBuffer) {
42658
42659		super(parameterPositions, sampleValues, sampleSize, resultBuffer);
42660
42661	}
42662
42663	interpolate_(i1, t0, t, t1) {
42664
42665		const result = this.resultBuffer,
42666			values = this.sampleValues,
42667			stride = this.valueSize,
42668
42669			alpha = (t - t0) / (t1 - t0);
42670
42671		let offset = i1 * stride;
42672
42673		for (let end = offset + stride; offset !== end; offset += 4) {
42674
42675			Quaternion.slerpFlat(result, 0, values, offset - stride, values, offset, alpha);
42676
42677		}
42678
42679		return result;
42680
42681	}
42682
42683}
42684
42685/**
42686 * A Track of quaternion keyframe values.
42687 */
42688class QuaternionKeyframeTrack extends KeyframeTrack {
42689
42690	InterpolantFactoryMethodLinear(result) {
42691
42692		return new QuaternionLinearInterpolant(this.times, this.values, this.getValueSize(), result);
42693
42694	}
42695
42696}
42697
42698QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
42699// ValueBufferType is inherited
42700QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42701QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42702
42703/**
42704 * A Track that interpolates Strings
42705 */
42706class StringKeyframeTrack extends KeyframeTrack { }
42707
42708StringKeyframeTrack.prototype.ValueTypeName = 'string';
42709StringKeyframeTrack.prototype.ValueBufferType = Array;
42710StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42711StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
42712StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
42713
42714/**
42715 * A Track of vectored keyframe values.
42716 */
42717class VectorKeyframeTrack extends KeyframeTrack { }
42718
42719VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
42720
42721class AnimationClip {
42722
42723	constructor(name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode) {
42724
42725		this.name = name;
42726		this.tracks = tracks;
42727		this.duration = duration;
42728		this.blendMode = blendMode;
42729
42730		this.uuid = generateUUID();
42731
42732		// this means it should figure out its duration by scanning the tracks
42733		if (this.duration < 0) {
42734
42735			this.resetDuration();
42736
42737		}
42738
42739	}
42740
42741
42742	static parse(json) {
42743
42744		const tracks = [],
42745			jsonTracks = json.tracks,
42746			frameTime = 1.0 / (json.fps || 1.0);
42747
42748		for (let i = 0, n = jsonTracks.length; i !== n; ++i) {
42749
42750			tracks.push(parseKeyframeTrack(jsonTracks[i]).scale(frameTime));
42751
42752		}
42753
42754		const clip = new this(json.name, json.duration, tracks, json.blendMode);
42755		clip.uuid = json.uuid;
42756
42757		return clip;
42758
42759	}
42760
42761	static toJSON(clip) {
42762
42763		const tracks = [],
42764			clipTracks = clip.tracks;
42765
42766		const json = {
42767
42768			'name': clip.name,
42769			'duration': clip.duration,
42770			'tracks': tracks,
42771			'uuid': clip.uuid,
42772			'blendMode': clip.blendMode
42773
42774		};
42775
42776		for (let i = 0, n = clipTracks.length; i !== n; ++i) {
42777
42778			tracks.push(KeyframeTrack.toJSON(clipTracks[i]));
42779
42780		}
42781
42782		return json;
42783
42784	}
42785
42786	static CreateFromMorphTargetSequence(name, morphTargetSequence, fps, noLoop) {
42787
42788		const numMorphTargets = morphTargetSequence.length;
42789		const tracks = [];
42790
42791		for (let i = 0; i < numMorphTargets; i++) {
42792
42793			let times = [];
42794			let values = [];
42795
42796			times.push(
42797				(i + numMorphTargets - 1) % numMorphTargets,
42798				i,
42799				(i + 1) % numMorphTargets);
42800
42801			values.push(0, 1, 0);
42802
42803			const order = getKeyframeOrder(times);
42804			times = sortedArray(times, 1, order);
42805			values = sortedArray(values, 1, order);
42806
42807			// if there is a key at the first frame, duplicate it as the
42808			// last frame as well for perfect loop.
42809			if (!noLoop && times[0] === 0) {
42810
42811				times.push(numMorphTargets);
42812				values.push(values[0]);
42813
42814			}
42815
42816			tracks.push(
42817				new NumberKeyframeTrack(
42818					'.morphTargetInfluences[' + morphTargetSequence[i].name + ']',
42819					times, values
42820				).scale(1.0 / fps));
42821
42822		}
42823
42824		return new this(name, - 1, tracks);
42825
42826	}
42827
42828	static findByName(objectOrClipArray, name) {
42829
42830		let clipArray = objectOrClipArray;
42831
42832		if (!Array.isArray(objectOrClipArray)) {
42833
42834			const o = objectOrClipArray;
42835			clipArray = o.geometry && o.geometry.animations || o.animations;
42836
42837		}
42838
42839		for (let i = 0; i < clipArray.length; i++) {
42840
42841			if (clipArray[i].name === name) {
42842
42843				return clipArray[i];
42844
42845			}
42846
42847		}
42848
42849		return null;
42850
42851	}
42852
42853	static CreateClipsFromMorphTargetSequences(morphTargets, fps, noLoop) {
42854
42855		const animationToMorphTargets = {};
42856
42857		// tested with https://regex101.com/ on trick sequences
42858		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
42859		const pattern = /^([\w-]*?)([\d]+)$/;
42860
42861		// sort morph target names into animation groups based
42862		// patterns like Walk_001, Walk_002, Run_001, Run_002
42863		for (let i = 0, il = morphTargets.length; i < il; i++) {
42864
42865			const morphTarget = morphTargets[i];
42866			const parts = morphTarget.name.match(pattern);
42867
42868			if (parts && parts.length > 1) {
42869
42870				const name = parts[1];
42871
42872				let animationMorphTargets = animationToMorphTargets[name];
42873
42874				if (!animationMorphTargets) {
42875
42876					animationToMorphTargets[name] = animationMorphTargets = [];
42877
42878				}
42879
42880				animationMorphTargets.push(morphTarget);
42881
42882			}
42883
42884		}
42885
42886		const clips = [];
42887
42888		for (const name in animationToMorphTargets) {
42889
42890			clips.push(this.CreateFromMorphTargetSequence(name, animationToMorphTargets[name], fps, noLoop));
42891
42892		}
42893
42894		return clips;
42895
42896	}
42897
42898	// parse the animation.hierarchy format
42899	static parseAnimation(animation, bones) {
42900
42901		if (!animation) {
42902
42903			console.error('THREE.AnimationClip: No animation in JSONLoader data.');
42904			return null;
42905
42906		}
42907
42908		const addNonemptyTrack = function (trackType, trackName, animationKeys, propertyName, destTracks) {
42909
42910			// only return track if there are actually keys.
42911			if (animationKeys.length !== 0) {
42912
42913				const times = [];
42914				const values = [];
42915
42916				flattenJSON(animationKeys, times, values, propertyName);
42917
42918				// empty keys are filtered out, so check again
42919				if (times.length !== 0) {
42920
42921					destTracks.push(new trackType(trackName, times, values));
42922
42923				}
42924
42925			}
42926
42927		};
42928
42929		const tracks = [];
42930
42931		const clipName = animation.name || 'default';
42932		const fps = animation.fps || 30;
42933		const blendMode = animation.blendMode;
42934
42935		// automatic length determination in AnimationClip.
42936		let duration = animation.length || - 1;
42937
42938		const hierarchyTracks = animation.hierarchy || [];
42939
42940		for (let h = 0; h < hierarchyTracks.length; h++) {
42941
42942			const animationKeys = hierarchyTracks[h].keys;
42943
42944			// skip empty tracks
42945			if (!animationKeys || animationKeys.length === 0) continue;
42946
42947			// process morph targets
42948			if (animationKeys[0].morphTargets) {
42949
42950				// figure out all morph targets used in this track
42951				const morphTargetNames = {};
42952
42953				let k;
42954
42955				for (k = 0; k < animationKeys.length; k++) {
42956
42957					if (animationKeys[k].morphTargets) {
42958
42959						for (let m = 0; m < animationKeys[k].morphTargets.length; m++) {
42960
42961							morphTargetNames[animationKeys[k].morphTargets[m]] = - 1;
42962
42963						}
42964
42965					}
42966
42967				}
42968
42969				// create a track for each morph target with all zero
42970				// morphTargetInfluences except for the keys in which
42971				// the morphTarget is named.
42972				for (const morphTargetName in morphTargetNames) {
42973
42974					const times = [];
42975					const values = [];
42976
42977					for (let m = 0; m !== animationKeys[k].morphTargets.length; ++m) {
42978
42979						const animationKey = animationKeys[k];
42980
42981						times.push(animationKey.time);
42982						values.push((animationKey.morphTarget === morphTargetName) ? 1 : 0);
42983
42984					}
42985
42986					tracks.push(new NumberKeyframeTrack('.morphTargetInfluence[' + morphTargetName + ']', times, values));
42987
42988				}
42989
42990				duration = morphTargetNames.length * fps;
42991
42992			} else {
42993
42994				// ...assume skeletal animation
42995
42996				const boneName = '.bones[' + bones[h].name + ']';
42997
42998				addNonemptyTrack(
42999					VectorKeyframeTrack, boneName + '.position',
43000					animationKeys, 'pos', tracks);
43001
43002				addNonemptyTrack(
43003					QuaternionKeyframeTrack, boneName + '.quaternion',
43004					animationKeys, 'rot', tracks);
43005
43006				addNonemptyTrack(
43007					VectorKeyframeTrack, boneName + '.scale',
43008					animationKeys, 'scl', tracks);
43009
43010			}
43011
43012		}
43013
43014		if (tracks.length === 0) {
43015
43016			return null;
43017
43018		}
43019
43020		const clip = new this(clipName, duration, tracks, blendMode);
43021
43022		return clip;
43023
43024	}
43025
43026	resetDuration() {
43027
43028		const tracks = this.tracks;
43029		let duration = 0;
43030
43031		for (let i = 0, n = tracks.length; i !== n; ++i) {
43032
43033			const track = this.tracks[i];
43034
43035			duration = Math.max(duration, track.times[track.times.length - 1]);
43036
43037		}
43038
43039		this.duration = duration;
43040
43041		return this;
43042
43043	}
43044
43045	trim() {
43046
43047		for (let i = 0; i < this.tracks.length; i++) {
43048
43049			this.tracks[i].trim(0, this.duration);
43050
43051		}
43052
43053		return this;
43054
43055	}
43056
43057	validate() {
43058
43059		let valid = true;
43060
43061		for (let i = 0; i < this.tracks.length; i++) {
43062
43063			valid = valid && this.tracks[i].validate();
43064
43065		}
43066
43067		return valid;
43068
43069	}
43070
43071	optimize() {
43072
43073		for (let i = 0; i < this.tracks.length; i++) {
43074
43075			this.tracks[i].optimize();
43076
43077		}
43078
43079		return this;
43080
43081	}
43082
43083	clone() {
43084
43085		const tracks = [];
43086
43087		for (let i = 0; i < this.tracks.length; i++) {
43088
43089			tracks.push(this.tracks[i].clone());
43090
43091		}
43092
43093		return new this.constructor(this.name, this.duration, tracks, this.blendMode);
43094
43095	}
43096
43097	toJSON() {
43098
43099		return this.constructor.toJSON(this);
43100
43101	}
43102
43103}
43104
43105function getTrackTypeForValueTypeName(typeName) {
43106
43107	switch (typeName.toLowerCase()) {
43108
43109		case 'scalar':
43110		case 'double':
43111		case 'float':
43112		case 'number':
43113		case 'integer':
43114
43115			return NumberKeyframeTrack;
43116
43117		case 'vector':
43118		case 'vector2':
43119		case 'vector3':
43120		case 'vector4':
43121
43122			return VectorKeyframeTrack;
43123
43124		case 'color':
43125
43126			return ColorKeyframeTrack;
43127
43128		case 'quaternion':
43129
43130			return QuaternionKeyframeTrack;
43131
43132		case 'bool':
43133		case 'boolean':
43134
43135			return BooleanKeyframeTrack;
43136
43137		case 'string':
43138
43139			return StringKeyframeTrack;
43140
43141	}
43142
43143	throw new Error('THREE.KeyframeTrack: Unsupported typeName: ' + typeName);
43144
43145}
43146
43147function parseKeyframeTrack(json) {
43148
43149	if (json.type === undefined) {
43150
43151		throw new Error('THREE.KeyframeTrack: track type undefined, can not parse');
43152
43153	}
43154
43155	const trackType = getTrackTypeForValueTypeName(json.type);
43156
43157	if (json.times === undefined) {
43158
43159		const times = [], values = [];
43160
43161		flattenJSON(json.keys, times, values, 'value');
43162
43163		json.times = times;
43164		json.values = values;
43165
43166	}
43167
43168	// derived classes can define a static parse method
43169	if (trackType.parse !== undefined) {
43170
43171		return trackType.parse(json);
43172
43173	} else {
43174
43175		// by default, we assume a constructor compatible with the base
43176		return new trackType(json.name, json.times, json.values, json.interpolation);
43177
43178	}
43179
43180}
43181
43182const Cache = {
43183
43184	enabled: false,
43185
43186	files: {},
43187
43188	add: function (key, file) {
43189
43190		if (this.enabled === false) return;
43191
43192		// console.log( 'THREE.Cache', 'Adding key:', key );
43193
43194		this.files[key] = file;
43195
43196	},
43197
43198	get: function (key) {
43199
43200		if (this.enabled === false) return;
43201
43202		// console.log( 'THREE.Cache', 'Checking key:', key );
43203
43204		return this.files[key];
43205
43206	},
43207
43208	remove: function (key) {
43209
43210		delete this.files[key];
43211
43212	},
43213
43214	clear: function () {
43215
43216		this.files = {};
43217
43218	}
43219
43220};
43221
43222class LoadingManager {
43223
43224	constructor(onLoad, onProgress, onError) {
43225
43226		const scope = this;
43227
43228		let isLoading = false;
43229		let itemsLoaded = 0;
43230		let itemsTotal = 0;
43231		let urlModifier = undefined;
43232		const handlers = [];
43233
43234		// Refer to #5689 for the reason why we don't set .onStart
43235		// in the constructor
43236
43237		this.onStart = undefined;
43238		this.onLoad = onLoad;
43239		this.onProgress = onProgress;
43240		this.onError = onError;
43241
43242		this.itemStart = function (url) {
43243
43244			itemsTotal++;
43245
43246			if (isLoading === false) {
43247
43248				if (scope.onStart !== undefined) {
43249
43250					scope.onStart(url, itemsLoaded, itemsTotal);
43251
43252				}
43253
43254			}
43255
43256			isLoading = true;
43257
43258		};
43259
43260		this.itemEnd = function (url) {
43261
43262			itemsLoaded++;
43263
43264			if (scope.onProgress !== undefined) {
43265
43266				scope.onProgress(url, itemsLoaded, itemsTotal);
43267
43268			}
43269
43270			if (itemsLoaded === itemsTotal) {
43271
43272				isLoading = false;
43273
43274				if (scope.onLoad !== undefined) {
43275
43276					scope.onLoad();
43277
43278				}
43279
43280			}
43281
43282		};
43283
43284		this.itemError = function (url) {
43285
43286			if (scope.onError !== undefined) {
43287
43288				scope.onError(url);
43289
43290			}
43291
43292		};
43293
43294		this.resolveURL = function (url) {
43295
43296			if (urlModifier) {
43297
43298				return urlModifier(url);
43299
43300			}
43301
43302			return url;
43303
43304		};
43305
43306		this.setURLModifier = function (transform) {
43307
43308			urlModifier = transform;
43309
43310			return this;
43311
43312		};
43313
43314		this.addHandler = function (regex, loader) {
43315
43316			handlers.push(regex, loader);
43317
43318			return this;
43319
43320		};
43321
43322		this.removeHandler = function (regex) {
43323
43324			const index = handlers.indexOf(regex);
43325
43326			if (index !== - 1) {
43327
43328				handlers.splice(index, 2);
43329
43330			}
43331
43332			return this;
43333
43334		};
43335
43336		this.getHandler = function (file) {
43337
43338			for (let i = 0, l = handlers.length; i < l; i += 2) {
43339
43340				const regex = handlers[i];
43341				const loader = handlers[i + 1];
43342
43343				if (regex.global) regex.lastIndex = 0; // see #17920
43344
43345				if (regex.test(file)) {
43346
43347					return loader;
43348
43349				}
43350
43351			}
43352
43353			return null;
43354
43355		};
43356
43357	}
43358
43359}
43360
43361const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager();
43362
43363class Loader {
43364
43365	constructor(manager) {
43366
43367		this.manager = (manager !== undefined) ? manager : DefaultLoadingManager;
43368
43369		this.crossOrigin = 'anonymous';
43370		this.withCredentials = false;
43371		this.path = '';
43372		this.resourcePath = '';
43373		this.requestHeader = {};
43374
43375	}
43376
43377	load( /* url, onLoad, onProgress, onError */) { }
43378
43379	loadAsync(url, onProgress) {
43380
43381		const scope = this;
43382
43383		return new Promise(function (resolve, reject) {
43384
43385			scope.load(url, resolve, onProgress, reject);
43386
43387		});
43388
43389	}
43390
43391	parse( /* data */) { }
43392
43393	setCrossOrigin(crossOrigin) {
43394
43395		this.crossOrigin = crossOrigin;
43396		return this;
43397
43398	}
43399
43400	setWithCredentials(value) {
43401
43402		this.withCredentials = value;
43403		return this;
43404
43405	}
43406
43407	setPath(path) {
43408
43409		this.path = path;
43410		return this;
43411
43412	}
43413
43414	setResourcePath(resourcePath) {
43415
43416		this.resourcePath = resourcePath;
43417		return this;
43418
43419	}
43420
43421	setRequestHeader(requestHeader) {
43422
43423		this.requestHeader = requestHeader;
43424		return this;
43425
43426	}
43427
43428}
43429
43430Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT';
43431
43432const loading = {};
43433
43434class HttpError extends Error {
43435
43436	constructor(message, response) {
43437
43438		super(message);
43439		this.response = response;
43440
43441	}
43442
43443}
43444
43445class FileLoader extends Loader {
43446
43447	constructor(manager) {
43448
43449		super(manager);
43450
43451	}
43452
43453	load(url, onLoad, onProgress, onError) {
43454
43455		if (url === undefined) url = '';
43456
43457		if (this.path !== undefined) url = this.path + url;
43458
43459		url = this.manager.resolveURL(url);
43460
43461		const cached = Cache.get(url);
43462
43463		if (cached !== undefined) {
43464
43465			this.manager.itemStart(url);
43466
43467			setTimeout(() => {
43468
43469				if (onLoad) onLoad(cached);
43470
43471				this.manager.itemEnd(url);
43472
43473			}, 0);
43474
43475			return cached;
43476
43477		}
43478
43479		// Check if request is duplicate
43480
43481		if (loading[url] !== undefined) {
43482
43483			loading[url].push({
43484
43485				onLoad: onLoad,
43486				onProgress: onProgress,
43487				onError: onError
43488
43489			});
43490
43491			return;
43492
43493		}
43494
43495		// Initialise array for duplicate requests
43496		loading[url] = [];
43497
43498		loading[url].push({
43499			onLoad: onLoad,
43500			onProgress: onProgress,
43501			onError: onError,
43502		});
43503
43504		// create request
43505		const req = new Request(url, {
43506			headers: new Headers(this.requestHeader),
43507			credentials: this.withCredentials ? 'include' : 'same-origin',
43508			// An abort controller could be added within a future PR
43509		});
43510
43511		// record states ( avoid data race )
43512		const mimeType = this.mimeType;
43513		const responseType = this.responseType;
43514
43515		// start the fetch
43516		fetch(req)
43517			.then(response => {
43518
43519				if (response.status === 200 || response.status === 0) {
43520
43521					// Some browsers return HTTP Status 0 when using non-http protocol
43522					// e.g. 'file://' or 'data://'. Handle as success.
43523
43524					if (response.status === 0) {
43525
43526						console.warn('THREE.FileLoader: HTTP Status 0 received.');
43527
43528					}
43529
43530					// Workaround: Checking if response.body === undefined for Alipay browser #23548
43531
43532					if (typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined) {
43533
43534						return response;
43535
43536					}
43537
43538					const callbacks = loading[url];
43539					const reader = response.body.getReader();
43540
43541					// Nginx needs X-File-Size check
43542					// https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content
43543					const contentLength = response.headers.get('Content-Length') || response.headers.get('X-File-Size');
43544					const total = contentLength ? parseInt(contentLength) : 0;
43545					const lengthComputable = total !== 0;
43546					let loaded = 0;
43547
43548					// periodically read data into the new stream tracking while download progress
43549					const stream = new ReadableStream({
43550						start(controller) {
43551
43552							readData();
43553
43554							function readData() {
43555
43556								reader.read().then(({ done, value }) => {
43557
43558									if (done) {
43559
43560										controller.close();
43561
43562									} else {
43563
43564										loaded += value.byteLength;
43565
43566										const event = new ProgressEvent('progress', { lengthComputable, loaded, total });
43567										for (let i = 0, il = callbacks.length; i < il; i++) {
43568
43569											const callback = callbacks[i];
43570											if (callback.onProgress) callback.onProgress(event);
43571
43572										}
43573
43574										controller.enqueue(value);
43575										readData();
43576
43577									}
43578
43579								});
vendor: 9,077 bytes, lines 43580-44096
43580
43581							}
43582
43583						}
43584
43585					});
43586
43587					return new Response(stream);
43588
43589				} else {
43590
43591					throw new HttpError(`fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response);
43592
43593				}
43594
43595			})
43596			.then(response => {
43597
43598				switch (responseType) {
43599
43600					case 'arraybuffer':
43601
43602						return response.arrayBuffer();
43603
43604					case 'blob':
43605
43606						return response.blob();
43607
43608					case 'document':
43609
43610						return response.text()
43611							.then(text => {
43612
43613								const parser = new DOMParser();
43614								return parser.parseFromString(text, mimeType);
43615
43616							});
43617
43618					case 'json':
43619
43620						return response.json();
43621
43622					default:
43623
43624						if (mimeType === undefined) {
43625
43626							return response.text();
43627
43628						} else {
43629
43630							// sniff encoding
43631							const re = /charset="?([^;"\s]*)"?/i;
43632							const exec = re.exec(mimeType);
43633							const label = exec && exec[1] ? exec[1].toLowerCase() : undefined;
43634							const decoder = new TextDecoder(label);
43635							return response.arrayBuffer().then(ab => decoder.decode(ab));
43636
43637						}
43638
43639				}
43640
43641			})
43642			.then(data => {
43643
43644				// Add to cache only on HTTP success, so that we do not cache
43645				// error response bodies as proper responses to requests.
43646				Cache.add(url, data);
43647
43648				const callbacks = loading[url];
43649				delete loading[url];
43650
43651				for (let i = 0, il = callbacks.length; i < il; i++) {
43652
43653					const callback = callbacks[i];
43654					if (callback.onLoad) callback.onLoad(data);
43655
43656				}
43657
43658			})
43659			.catch(err => {
43660
43661				// Abort errors and other errors are handled the same
43662
43663				const callbacks = loading[url];
43664
43665				if (callbacks === undefined) {
43666
43667					// When onLoad was called and url was deleted in `loading`
43668					this.manager.itemError(url);
43669					throw err;
43670
43671				}
43672
43673				delete loading[url];
43674
43675				for (let i = 0, il = callbacks.length; i < il; i++) {
43676
43677					const callback = callbacks[i];
43678					if (callback.onError) callback.onError(err);
43679
43680				}
43681
43682				this.manager.itemError(url);
43683
43684			})
43685			.finally(() => {
43686
43687				this.manager.itemEnd(url);
43688
43689			});
43690
43691		this.manager.itemStart(url);
43692
43693	}
43694
43695	setResponseType(value) {
43696
43697		this.responseType = value;
43698		return this;
43699
43700	}
43701
43702	setMimeType(value) {
43703
43704		this.mimeType = value;
43705		return this;
43706
43707	}
43708
43709}
43710
43711class AnimationLoader extends Loader {
43712
43713	constructor(manager) {
43714
43715		super(manager);
43716
43717	}
43718
43719	load(url, onLoad, onProgress, onError) {
43720
43721		const scope = this;
43722
43723		const loader = new FileLoader(this.manager);
43724		loader.setPath(this.path);
43725		loader.setRequestHeader(this.requestHeader);
43726		loader.setWithCredentials(this.withCredentials);
43727		loader.load(url, function (text) {
43728
43729			try {
43730
43731				onLoad(scope.parse(JSON.parse(text)));
43732
43733			} catch (e) {
43734
43735				if (onError) {
43736
43737					onError(e);
43738
43739				} else {
43740
43741					console.error(e);
43742
43743				}
43744
43745				scope.manager.itemError(url);
43746
43747			}
43748
43749		}, onProgress, onError);
43750
43751	}
43752
43753	parse(json) {
43754
43755		const animations = [];
43756
43757		for (let i = 0; i < json.length; i++) {
43758
43759			const clip = AnimationClip.parse(json[i]);
43760
43761			animations.push(clip);
43762
43763		}
43764
43765		return animations;
43766
43767	}
43768
43769}
43770
43771/**
43772 * Abstract Base class to block based textures loader (dds, pvr, ...)
43773 *
43774 * Sub classes have to implement the parse() method which will be used in load().
43775 */
43776
43777class CompressedTextureLoader extends Loader {
43778
43779	constructor(manager) {
43780
43781		super(manager);
43782
43783	}
43784
43785	load(url, onLoad, onProgress, onError) {
43786
43787		const scope = this;
43788
43789		const images = [];
43790
43791		const texture = new CompressedTexture();
43792
43793		const loader = new FileLoader(this.manager);
43794		loader.setPath(this.path);
43795		loader.setResponseType('arraybuffer');
43796		loader.setRequestHeader(this.requestHeader);
43797		loader.setWithCredentials(scope.withCredentials);
43798
43799		let loaded = 0;
43800
43801		function loadTexture(i) {
43802
43803			loader.load(url[i], function (buffer) {
43804
43805				const texDatas = scope.parse(buffer, true);
43806
43807				images[i] = {
43808					width: texDatas.width,
43809					height: texDatas.height,
43810					format: texDatas.format,
43811					mipmaps: texDatas.mipmaps
43812				};
43813
43814				loaded += 1;
43815
43816				if (loaded === 6) {
43817
43818					if (texDatas.mipmapCount === 1) texture.minFilter = LinearFilter;
43819
43820					texture.image = images;
43821					texture.format = texDatas.format;
43822					texture.needsUpdate = true;
43823
43824					if (onLoad) onLoad(texture);
43825
43826				}
43827
43828			}, onProgress, onError);
43829
43830		}
43831
43832		if (Array.isArray(url)) {
43833
43834			for (let i = 0, il = url.length; i < il; ++i) {
43835
43836				loadTexture(i);
43837
43838			}
43839
43840		} else {
43841
43842			// compressed cubemap texture stored in a single DDS file
43843
43844			loader.load(url, function (buffer) {
43845
43846				const texDatas = scope.parse(buffer, true);
43847
43848				if (texDatas.isCubemap) {
43849
43850					const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
43851
43852					for (let f = 0; f < faces; f++) {
43853
43854						images[f] = { mipmaps: [] };
43855
43856						for (let i = 0; i < texDatas.mipmapCount; i++) {
43857
43858							images[f].mipmaps.push(texDatas.mipmaps[f * texDatas.mipmapCount + i]);
43859							images[f].format = texDatas.format;
43860							images[f].width = texDatas.width;
43861							images[f].height = texDatas.height;
43862
43863						}
43864
43865					}
43866
43867					texture.image = images;
43868
43869				} else {
43870
43871					texture.image.width = texDatas.width;
43872					texture.image.height = texDatas.height;
43873					texture.mipmaps = texDatas.mipmaps;
43874
43875				}
43876
43877				if (texDatas.mipmapCount === 1) {
43878
43879					texture.minFilter = LinearFilter;
43880
43881				}
43882
43883				texture.format = texDatas.format;
43884				texture.needsUpdate = true;
43885
43886				if (onLoad) onLoad(texture);
43887
43888			}, onProgress, onError);
43889
43890		}
43891
43892		return texture;
43893
43894	}
43895
43896}
43897
43898class ImageLoader extends Loader {
43899
43900	constructor(manager) {
43901
43902		super(manager);
43903
43904	}
43905
43906	load(url, onLoad, onProgress, onError) {
43907
43908		if (this.path !== undefined) url = this.path + url;
43909
43910		url = this.manager.resolveURL(url);
43911
43912		const scope = this;
43913
43914		const cached = Cache.get(url);
43915
43916		if (cached !== undefined) {
43917
43918			scope.manager.itemStart(url);
43919
43920			setTimeout(function () {
43921
43922				if (onLoad) onLoad(cached);
43923
43924				scope.manager.itemEnd(url);
43925
43926			}, 0);
43927
43928			return cached;
43929
43930		}
43931
43932		const image = createElementNS('img');
43933
43934		function onImageLoad() {
43935
43936			removeEventListeners();
43937
43938			Cache.add(url, this);
43939
43940			if (onLoad) onLoad(this);
43941
43942			scope.manager.itemEnd(url);
43943
43944		}
43945
43946		function onImageError(event) {
43947
43948			removeEventListeners();
43949
43950			if (onError) onError(event);
43951
43952			scope.manager.itemError(url);
43953			scope.manager.itemEnd(url);
43954
43955		}
43956
43957		function removeEventListeners() {
43958
43959			image.removeEventListener('load', onImageLoad, false);
43960			image.removeEventListener('error', onImageError, false);
43961
43962		}
43963
43964		image.addEventListener('load', onImageLoad, false);
43965		image.addEventListener('error', onImageError, false);
43966
43967		if (url.slice(0, 5) !== 'data:') {
43968
43969			if (this.crossOrigin !== undefined) image.crossOrigin = this.crossOrigin;
43970
43971		}
43972
43973		scope.manager.itemStart(url);
43974
43975		image.src = url;
43976
43977		return image;
43978
43979	}
43980
43981}
43982
43983class CubeTextureLoader extends Loader {
43984
43985	constructor(manager) {
43986
43987		super(manager);
43988
43989	}
43990
43991	load(urls, onLoad, onProgress, onError) {
43992
43993		const texture = new CubeTexture();
43994		texture.colorSpace = SRGBColorSpace;
43995
43996		const loader = new ImageLoader(this.manager);
43997		loader.setCrossOrigin(this.crossOrigin);
43998		loader.setPath(this.path);
43999
44000		let loaded = 0;
44001
44002		function loadTexture(i) {
44003
44004			loader.load(urls[i], function (image) {
44005
44006				texture.images[i] = image;
44007
44008				loaded++;
44009
44010				if (loaded === 6) {
44011
44012					texture.needsUpdate = true;
44013
44014					if (onLoad) onLoad(texture);
44015
44016				}
44017
44018			}, undefined, onError);
44019
44020		}
44021
44022		for (let i = 0; i < urls.length; ++i) {
44023
44024			loadTexture(i);
44025
44026		}
44027
44028		return texture;
44029
44030	}
44031
44032}
44033
44034/**
44035 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
44036 *
44037 * Sub classes have to implement the parse() method which will be used in load().
44038 */
44039
44040class DataTextureLoader extends Loader {
44041
44042	constructor(manager) {
44043
44044		super(manager);
44045
44046	}
44047
44048	load(url, onLoad, onProgress, onError) {
44049
44050		const scope = this;
44051
44052		const texture = new DataTexture();
44053
44054		const loader = new FileLoader(this.manager);
44055		loader.setResponseType('arraybuffer');
44056		loader.setRequestHeader(this.requestHeader);
44057		loader.setPath(this.path);
44058		loader.setWithCredentials(scope.withCredentials);
44059		loader.load(url, function (buffer) {
44060
44061			let texData;
44062
44063			try {
44064
44065				texData = scope.parse(buffer);
44066
44067			} catch (error) {
44068
44069				if (onError !== undefined) {
44070
44071					onError(error);
44072
44073				} else {
44074
44075					console.error(error);
44076					return;
44077
44078				}
44079
44080			}
44081
44082			if (texData.image !== undefined) {
44083
44084				texture.image = texData.image;
44085
44086			} else if (texData.data !== undefined) {
44087
44088				texture.image.width = texData.width;
44089				texture.image.height = texData.height;
44090				texture.image.data = texData.data;
44091
44092			}
44093
44094			texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
44095			texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
44096
vendor: 5,243 bytes, lines 44097-44387
44097			texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
44098			texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
44099
44100			texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
44101
44102			if (texData.colorSpace !== undefined) {
44103
44104				texture.colorSpace = texData.colorSpace;
44105
44106			} else if (texData.encoding !== undefined) { // @deprecated, r152
44107
44108				texture.encoding = texData.encoding;
44109
44110			}
44111
44112			if (texData.flipY !== undefined) {
44113
44114				texture.flipY = texData.flipY;
44115
44116			}
44117
44118			if (texData.format !== undefined) {
44119
44120				texture.format = texData.format;
44121
44122			}
44123
44124			if (texData.type !== undefined) {
44125
44126				texture.type = texData.type;
44127
44128			}
44129
44130			if (texData.mipmaps !== undefined) {
44131
44132				texture.mipmaps = texData.mipmaps;
44133				texture.minFilter = LinearMipmapLinearFilter; // presumably...
44134
44135			}
44136
44137			if (texData.mipmapCount === 1) {
44138
44139				texture.minFilter = LinearFilter;
44140
44141			}
44142
44143			if (texData.generateMipmaps !== undefined) {
44144
44145				texture.generateMipmaps = texData.generateMipmaps;
44146
44147			}
44148
44149			texture.needsUpdate = true;
44150
44151			if (onLoad) onLoad(texture, texData);
44152
44153		}, onProgress, onError);
44154
44155
44156		return texture;
44157
44158	}
44159
44160}
44161
44162class TextureLoader extends Loader {
44163
44164	constructor(manager) {
44165
44166		super(manager);
44167
44168	}
44169
44170	load(url, onLoad, onProgress, onError) {
44171
44172		const texture = new Texture();
44173
44174		const loader = new ImageLoader(this.manager);
44175		loader.setCrossOrigin(this.crossOrigin);
44176		loader.setPath(this.path);
44177
44178		loader.load(url, function (image) {
44179
44180			texture.image = image;
44181			texture.needsUpdate = true;
44182
44183			if (onLoad !== undefined) {
44184
44185				onLoad(texture);
44186
44187			}
44188
44189		}, onProgress, onError);
44190
44191		return texture;
44192
44193	}
44194
44195}
44196
44197class Light extends Object3D {
44198
44199	constructor(color, intensity = 1) {
44200
44201		super();
44202
44203		this.isLight = true;
44204
44205		this.type = 'Light';
44206
44207		this.color = new Color(color);
44208		this.intensity = intensity;
44209
44210	}
44211
44212	dispose() {
44213
44214		// Empty here in base class; some subclasses override.
44215
44216	}
44217
44218	copy(source, recursive) {
44219
44220		super.copy(source, recursive);
44221
44222		this.color.copy(source.color);
44223		this.intensity = source.intensity;
44224
44225		return this;
44226
44227	}
44228
44229	toJSON(meta) {
44230
44231		const data = super.toJSON(meta);
44232
44233		data.object.color = this.color.getHex();
44234		data.object.intensity = this.intensity;
44235
44236		if (this.groundColor !== undefined) data.object.groundColor = this.groundColor.getHex();
44237
44238		if (this.distance !== undefined) data.object.distance = this.distance;
44239		if (this.angle !== undefined) data.object.angle = this.angle;
44240		if (this.decay !== undefined) data.object.decay = this.decay;
44241		if (this.penumbra !== undefined) data.object.penumbra = this.penumbra;
44242
44243		if (this.shadow !== undefined) data.object.shadow = this.shadow.toJSON();
44244
44245		return data;
44246
44247	}
44248
44249}
44250
44251class HemisphereLight extends Light {
44252
44253	constructor(skyColor, groundColor, intensity) {
44254
44255		super(skyColor, intensity);
44256
44257		this.isHemisphereLight = true;
44258
44259		this.type = 'HemisphereLight';
44260
44261		this.position.copy(Object3D.DEFAULT_UP);
44262		this.updateMatrix();
44263
44264		this.groundColor = new Color(groundColor);
44265
44266	}
44267
44268	copy(source, recursive) {
44269
44270		super.copy(source, recursive);
44271
44272		this.groundColor.copy(source.groundColor);
44273
44274		return this;
44275
44276	}
44277
44278}
44279
44280const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
44281const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3();
44282const _lookTarget$1 = /*@__PURE__*/ new Vector3();
44283
44284class LightShadow {
44285
44286	constructor(camera) {
44287
44288		this.camera = camera;
44289
44290		this.bias = 0;
44291		this.normalBias = 0;
44292		this.radius = 1;
44293		this.blurSamples = 8;
44294
44295		this.mapSize = new Vector2(512, 512);
44296
44297		this.map = null;
44298		this.mapPass = null;
44299		this.matrix = new Matrix4();
44300
44301		this.autoUpdate = true;
44302		this.needsUpdate = false;
44303
44304		this._frustum = new Frustum();
44305		this._frameExtents = new Vector2(1, 1);
44306
44307		this._viewportCount = 1;
44308
44309		this._viewports = [
44310
44311			new Vector4(0, 0, 1, 1)
44312
44313		];
44314
44315	}
44316
44317	getViewportCount() {
44318
44319		return this._viewportCount;
44320
44321	}
44322
44323	getFrustum() {
44324
44325		return this._frustum;
44326
44327	}
44328
44329	updateMatrices(light) {
44330
44331		const shadowCamera = this.camera;
44332		const shadowMatrix = this.matrix;
44333
44334		_lightPositionWorld$1.setFromMatrixPosition(light.matrixWorld);
44335		shadowCamera.position.copy(_lightPositionWorld$1);
44336
44337		_lookTarget$1.setFromMatrixPosition(light.target.matrixWorld);
44338		shadowCamera.lookAt(_lookTarget$1);
44339		shadowCamera.updateMatrixWorld();
44340
44341		_projScreenMatrix$1.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
44342		this._frustum.setFromProjectionMatrix(_projScreenMatrix$1);
44343
44344		shadowMatrix.set(
44345			0.5, 0.0, 0.0, 0.5,
44346			0.0, 0.5, 0.0, 0.5,
44347			0.0, 0.0, 0.5, 0.5,
44348			0.0, 0.0, 0.0, 1.0
44349		);
44350
44351		shadowMatrix.multiply(_projScreenMatrix$1);
44352
44353	}
44354
44355	getViewport(viewportIndex) {
44356
44357		return this._viewports[viewportIndex];
44358
44359	}
44360
44361	getFrameExtents() {
44362
44363		return this._frameExtents;
44364
44365	}
44366
44367	dispose() {
44368
44369		if (this.map) {
44370
44371			this.map.dispose();
44372
44373		}
44374
44375		if (this.mapPass) {
44376
44377			this.mapPass.dispose();
44378
44379		}
44380
44381	}
44382
44383	copy(source) {
44384
44385		this.camera = source.camera.clone();
44386
44387		this.bias = source.bias;
vendor: 5,877 bytes, lines 44388-44675
44388		this.radius = source.radius;
44389
44390		this.mapSize.copy(source.mapSize);
44391
44392		return this;
44393
44394	}
44395
44396	clone() {
44397
44398		return new this.constructor().copy(this);
44399
44400	}
44401
44402	toJSON() {
44403
44404		const object = {};
44405
44406		if (this.bias !== 0) object.bias = this.bias;
44407		if (this.normalBias !== 0) object.normalBias = this.normalBias;
44408		if (this.radius !== 1) object.radius = this.radius;
44409		if (this.mapSize.x !== 512 || this.mapSize.y !== 512) object.mapSize = this.mapSize.toArray();
44410
44411		object.camera = this.camera.toJSON(false).object;
44412		delete object.camera.matrix;
44413
44414		return object;
44415
44416	}
44417
44418}
44419
44420class SpotLightShadow extends LightShadow {
44421
44422	constructor() {
44423
44424		super(new PerspectiveCamera(50, 1, 0.5, 500));
44425
44426		this.isSpotLightShadow = true;
44427
44428		this.focus = 1;
44429
44430	}
44431
44432	updateMatrices(light) {
44433
44434		const camera = this.camera;
44435
44436		const fov = RAD2DEG * 2 * light.angle * this.focus;
44437		const aspect = this.mapSize.width / this.mapSize.height;
44438		const far = light.distance || camera.far;
44439
44440		if (fov !== camera.fov || aspect !== camera.aspect || far !== camera.far) {
44441
44442			camera.fov = fov;
44443			camera.aspect = aspect;
44444			camera.far = far;
44445			camera.updateProjectionMatrix();
44446
44447		}
44448
44449		super.updateMatrices(light);
44450
44451	}
44452
44453	copy(source) {
44454
44455		super.copy(source);
44456
44457		this.focus = source.focus;
44458
44459		return this;
44460
44461	}
44462
44463}
44464
44465class SpotLight extends Light {
44466
44467	constructor(color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2) {
44468
44469		super(color, intensity);
44470
44471		this.isSpotLight = true;
44472
44473		this.type = 'SpotLight';
44474
44475		this.position.copy(Object3D.DEFAULT_UP);
44476		this.updateMatrix();
44477
44478		this.target = new Object3D();
44479
44480		this.distance = distance;
44481		this.angle = angle;
44482		this.penumbra = penumbra;
44483		this.decay = decay;
44484
44485		this.map = null;
44486
44487		this.shadow = new SpotLightShadow();
44488
44489	}
44490
44491	get power() {
44492
44493		// compute the light's luminous power (in lumens) from its intensity (in candela)
44494		// by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
44495		return this.intensity * Math.PI;
44496
44497	}
44498
44499	set power(power) {
44500
44501		// set the light's intensity (in candela) from the desired luminous power (in lumens)
44502		this.intensity = power / Math.PI;
44503
44504	}
44505
44506	dispose() {
44507
44508		this.shadow.dispose();
44509
44510	}
44511
44512	copy(source, recursive) {
44513
44514		super.copy(source, recursive);
44515
44516		this.distance = source.distance;
44517		this.angle = source.angle;
44518		this.penumbra = source.penumbra;
44519		this.decay = source.decay;
44520
44521		this.target = source.target.clone();
44522
44523		this.shadow = source.shadow.clone();
44524
44525		return this;
44526
44527	}
44528
44529}
44530
44531const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
44532const _lightPositionWorld = /*@__PURE__*/ new Vector3();
44533const _lookTarget = /*@__PURE__*/ new Vector3();
44534
44535class PointLightShadow extends LightShadow {
44536
44537	constructor() {
44538
44539		super(new PerspectiveCamera(90, 1, 0.5, 500));
44540
44541		this.isPointLightShadow = true;
44542
44543		this._frameExtents = new Vector2(4, 2);
44544
44545		this._viewportCount = 6;
44546
44547		this._viewports = [
44548			// These viewports map a cube-map onto a 2D texture with the
44549			// following orientation:
44550			//
44551			//  xzXZ
44552			//   y Y
44553			//
44554			// X - Positive x direction
44555			// x - Negative x direction
44556			// Y - Positive y direction
44557			// y - Negative y direction
44558			// Z - Positive z direction
44559			// z - Negative z direction
44560
44561			// positive X
44562			new Vector4(2, 1, 1, 1),
44563			// negative X
44564			new Vector4(0, 1, 1, 1),
44565			// positive Z
44566			new Vector4(3, 1, 1, 1),
44567			// negative Z
44568			new Vector4(1, 1, 1, 1),
44569			// positive Y
44570			new Vector4(3, 0, 1, 1),
44571			// negative Y
44572			new Vector4(1, 0, 1, 1)
44573		];
44574
44575		this._cubeDirections = [
44576			new Vector3(1, 0, 0), new Vector3(- 1, 0, 0), new Vector3(0, 0, 1),
44577			new Vector3(0, 0, - 1), new Vector3(0, 1, 0), new Vector3(0, - 1, 0)
44578		];
44579
44580		this._cubeUps = [
44581			new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0),
44582			new Vector3(0, 1, 0), new Vector3(0, 0, 1), new Vector3(0, 0, - 1)
44583		];
44584
44585	}
44586
44587	updateMatrices(light, viewportIndex = 0) {
44588
44589		const camera = this.camera;
44590		const shadowMatrix = this.matrix;
44591
44592		const far = light.distance || camera.far;
44593
44594		if (far !== camera.far) {
44595
44596			camera.far = far;
44597			camera.updateProjectionMatrix();
44598
44599		}
44600
44601		_lightPositionWorld.setFromMatrixPosition(light.matrixWorld);
44602		camera.position.copy(_lightPositionWorld);
44603
44604		_lookTarget.copy(camera.position);
44605		_lookTarget.add(this._cubeDirections[viewportIndex]);
44606		camera.up.copy(this._cubeUps[viewportIndex]);
44607		camera.lookAt(_lookTarget);
44608		camera.updateMatrixWorld();
44609
44610		shadowMatrix.makeTranslation(- _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z);
44611
44612		_projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
44613		this._frustum.setFromProjectionMatrix(_projScreenMatrix);
44614
44615	}
44616
44617}
44618
44619class PointLight extends Light {
44620
44621	constructor(color, intensity, distance = 0, decay = 2) {
44622
44623		super(color, intensity);
44624
44625		this.isPointLight = true;
44626
44627		this.type = 'PointLight';
44628
44629		this.distance = distance;
44630		this.decay = decay;
44631
44632		this.shadow = new PointLightShadow();
44633
44634	}
44635
44636	get power() {
44637
44638		// compute the light's luminous power (in lumens) from its intensity (in candela)
44639		// for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
44640		return this.intensity * 4 * Math.PI;
44641
44642	}
44643
44644	set power(power) {
44645
44646		// set the light's intensity (in candela) from the desired luminous power (in lumens)
44647		this.intensity = power / (4 * Math.PI);
44648
44649	}
44650
44651	dispose() {
44652
44653		this.shadow.dispose();
44654
44655	}
44656
44657	copy(source, recursive) {
44658
44659		super.copy(source, recursive);
44660
44661		this.distance = source.distance;
44662		this.decay = source.decay;
44663
44664		this.shadow = source.shadow.clone();
44665
44666		return this;
44667
44668	}
44669
44670}
44671
44672class DirectionalLightShadow extends LightShadow {
44673
44674	constructor() {
44675
vendor: 4,346 bytes, lines 44676-44897
44676		super(new OrthographicCamera(- 5, 5, 5, - 5, 0.5, 500));
44677
44678		this.isDirectionalLightShadow = true;
44679
44680	}
44681
44682}
44683
44684class DirectionalLight extends Light {
44685
44686	constructor(color, intensity) {
44687
44688		super(color, intensity);
44689
44690		this.isDirectionalLight = true;
44691
44692		this.type = 'DirectionalLight';
44693
44694		this.position.copy(Object3D.DEFAULT_UP);
44695		this.updateMatrix();
44696
44697		this.target = new Object3D();
44698
44699		this.shadow = new DirectionalLightShadow();
44700
44701	}
44702
44703	dispose() {
44704
44705		this.shadow.dispose();
44706
44707	}
44708
44709	copy(source) {
44710
44711		super.copy(source);
44712
44713		this.target = source.target.clone();
44714		this.shadow = source.shadow.clone();
44715
44716		return this;
44717
44718	}
44719
44720}
44721
44722class AmbientLight extends Light {
44723
44724	constructor(color, intensity) {
44725
44726		super(color, intensity);
44727
44728		this.isAmbientLight = true;
44729
44730		this.type = 'AmbientLight';
44731
44732	}
44733
44734}
44735
44736class RectAreaLight extends Light {
44737
44738	constructor(color, intensity, width = 10, height = 10) {
44739
44740		super(color, intensity);
44741
44742		this.isRectAreaLight = true;
44743
44744		this.type = 'RectAreaLight';
44745
44746		this.width = width;
44747		this.height = height;
44748
44749	}
44750
44751	get power() {
44752
44753		// compute the light's luminous power (in lumens) from its intensity (in nits)
44754		return this.intensity * this.width * this.height * Math.PI;
44755
44756	}
44757
44758	set power(power) {
44759
44760		// set the light's intensity (in nits) from the desired luminous power (in lumens)
44761		this.intensity = power / (this.width * this.height * Math.PI);
44762
44763	}
44764
44765	copy(source) {
44766
44767		super.copy(source);
44768
44769		this.width = source.width;
44770		this.height = source.height;
44771
44772		return this;
44773
44774	}
44775
44776	toJSON(meta) {
44777
44778		const data = super.toJSON(meta);
44779
44780		data.object.width = this.width;
44781		data.object.height = this.height;
44782
44783		return data;
44784
44785	}
44786
44787}
44788
44789/**
44790 * Primary reference:
44791 *   https://graphics.stanford.edu/papers/envmap/envmap.pdf
44792 *
44793 * Secondary reference:
44794 *   https://www.ppsloan.org/publications/StupidSH36.pdf
44795 */
44796
44797// 3-band SH defined by 9 coefficients
44798
44799class SphericalHarmonics3 {
44800
44801	constructor() {
44802
44803		this.isSphericalHarmonics3 = true;
44804
44805		this.coefficients = [];
44806
44807		for (let i = 0; i < 9; i++) {
44808
44809			this.coefficients.push(new Vector3());
44810
44811		}
44812
44813	}
44814
44815	set(coefficients) {
44816
44817		for (let i = 0; i < 9; i++) {
44818
44819			this.coefficients[i].copy(coefficients[i]);
44820
44821		}
44822
44823		return this;
44824
44825	}
44826
44827	zero() {
44828
44829		for (let i = 0; i < 9; i++) {
44830
44831			this.coefficients[i].set(0, 0, 0);
44832
44833		}
44834
44835		return this;
44836
44837	}
44838
44839	// get the radiance in the direction of the normal
44840	// target is a Vector3
44841	getAt(normal, target) {
44842
44843		// normal is assumed to be unit length
44844
44845		const x = normal.x, y = normal.y, z = normal.z;
44846
44847		const coeff = this.coefficients;
44848
44849		// band 0
44850		target.copy(coeff[0]).multiplyScalar(0.282095);
44851
44852		// band 1
44853		target.addScaledVector(coeff[1], 0.488603 * y);
44854		target.addScaledVector(coeff[2], 0.488603 * z);
44855		target.addScaledVector(coeff[3], 0.488603 * x);
44856
44857		// band 2
44858		target.addScaledVector(coeff[4], 1.092548 * (x * y));
44859		target.addScaledVector(coeff[5], 1.092548 * (y * z));
44860		target.addScaledVector(coeff[6], 0.315392 * (3.0 * z * z - 1.0));
44861		target.addScaledVector(coeff[7], 1.092548 * (x * z));
44862		target.addScaledVector(coeff[8], 0.546274 * (x * x - y * y));
44863
44864		return target;
44865
44866	}
44867
44868	// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
44869	// target is a Vector3
44870	// https://graphics.stanford.edu/papers/envmap/envmap.pdf
44871	getIrradianceAt(normal, target) {
44872
44873		// normal is assumed to be unit length
44874
44875		const x = normal.x, y = normal.y, z = normal.z;
44876
44877		const coeff = this.coefficients;
44878
44879		// band 0
44880		target.copy(coeff[0]).multiplyScalar(0.886227); // π * 0.282095
44881
44882		// band 1
44883		target.addScaledVector(coeff[1], 2.0 * 0.511664 * y); // ( 2 * π / 3 ) * 0.488603
44884		target.addScaledVector(coeff[2], 2.0 * 0.511664 * z);
44885		target.addScaledVector(coeff[3], 2.0 * 0.511664 * x);
44886
44887		// band 2
44888		target.addScaledVector(coeff[4], 2.0 * 0.429043 * x * y); // ( π / 4 ) * 1.092548
44889		target.addScaledVector(coeff[5], 2.0 * 0.429043 * y * z);
44890		target.addScaledVector(coeff[6], 0.743125 * z * z - 0.247708); // ( π / 4 ) * 0.315392 * 3
44891		target.addScaledVector(coeff[7], 2.0 * 0.429043 * x * z);
44892		target.addScaledVector(coeff[8], 0.429043 * (x * x - y * y)); // ( π / 4 ) * 0.546274
44893
44894		return target;
44895
44896	}
44897
vendor: 24,027 bytes, lines 44898-45786
44898	add(sh) {
44899
44900		for (let i = 0; i < 9; i++) {
44901
44902			this.coefficients[i].add(sh.coefficients[i]);
44903
44904		}
44905
44906		return this;
44907
44908	}
44909
44910	addScaledSH(sh, s) {
44911
44912		for (let i = 0; i < 9; i++) {
44913
44914			this.coefficients[i].addScaledVector(sh.coefficients[i], s);
44915
44916		}
44917
44918		return this;
44919
44920	}
44921
44922	scale(s) {
44923
44924		for (let i = 0; i < 9; i++) {
44925
44926			this.coefficients[i].multiplyScalar(s);
44927
44928		}
44929
44930		return this;
44931
44932	}
44933
44934	lerp(sh, alpha) {
44935
44936		for (let i = 0; i < 9; i++) {
44937
44938			this.coefficients[i].lerp(sh.coefficients[i], alpha);
44939
44940		}
44941
44942		return this;
44943
44944	}
44945
44946	equals(sh) {
44947
44948		for (let i = 0; i < 9; i++) {
44949
44950			if (!this.coefficients[i].equals(sh.coefficients[i])) {
44951
44952				return false;
44953
44954			}
44955
44956		}
44957
44958		return true;
44959
44960	}
44961
44962	copy(sh) {
44963
44964		return this.set(sh.coefficients);
44965
44966	}
44967
44968	clone() {
44969
44970		return new this.constructor().copy(this);
44971
44972	}
44973
44974	fromArray(array, offset = 0) {
44975
44976		const coefficients = this.coefficients;
44977
44978		for (let i = 0; i < 9; i++) {
44979
44980			coefficients[i].fromArray(array, offset + (i * 3));
44981
44982		}
44983
44984		return this;
44985
44986	}
44987
44988	toArray(array = [], offset = 0) {
44989
44990		const coefficients = this.coefficients;
44991
44992		for (let i = 0; i < 9; i++) {
44993
44994			coefficients[i].toArray(array, offset + (i * 3));
44995
44996		}
44997
44998		return array;
44999
45000	}
45001
45002	// evaluate the basis functions
45003	// shBasis is an Array[ 9 ]
45004	static getBasisAt(normal, shBasis) {
45005
45006		// normal is assumed to be unit length
45007
45008		const x = normal.x, y = normal.y, z = normal.z;
45009
45010		// band 0
45011		shBasis[0] = 0.282095;
45012
45013		// band 1
45014		shBasis[1] = 0.488603 * y;
45015		shBasis[2] = 0.488603 * z;
45016		shBasis[3] = 0.488603 * x;
45017
45018		// band 2
45019		shBasis[4] = 1.092548 * x * y;
45020		shBasis[5] = 1.092548 * y * z;
45021		shBasis[6] = 0.315392 * (3 * z * z - 1);
45022		shBasis[7] = 1.092548 * x * z;
45023		shBasis[8] = 0.546274 * (x * x - y * y);
45024
45025	}
45026
45027}
45028
45029class LightProbe extends Light {
45030
45031	constructor(sh = new SphericalHarmonics3(), intensity = 1) {
45032
45033		super(undefined, intensity);
45034
45035		this.isLightProbe = true;
45036
45037		this.sh = sh;
45038
45039	}
45040
45041	copy(source) {
45042
45043		super.copy(source);
45044
45045		this.sh.copy(source.sh);
45046
45047		return this;
45048
45049	}
45050
45051	fromJSON(json) {
45052
45053		this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
45054		this.sh.fromArray(json.sh);
45055
45056		return this;
45057
45058	}
45059
45060	toJSON(meta) {
45061
45062		const data = super.toJSON(meta);
45063
45064		data.object.sh = this.sh.toArray();
45065
45066		return data;
45067
45068	}
45069
45070}
45071
45072class MaterialLoader extends Loader {
45073
45074	constructor(manager) {
45075
45076		super(manager);
45077		this.textures = {};
45078
45079	}
45080
45081	load(url, onLoad, onProgress, onError) {
45082
45083		const scope = this;
45084
45085		const loader = new FileLoader(scope.manager);
45086		loader.setPath(scope.path);
45087		loader.setRequestHeader(scope.requestHeader);
45088		loader.setWithCredentials(scope.withCredentials);
45089		loader.load(url, function (text) {
45090
45091			try {
45092
45093				onLoad(scope.parse(JSON.parse(text)));
45094
45095			} catch (e) {
45096
45097				if (onError) {
45098
45099					onError(e);
45100
45101				} else {
45102
45103					console.error(e);
45104
45105				}
45106
45107				scope.manager.itemError(url);
45108
45109			}
45110
45111		}, onProgress, onError);
45112
45113	}
45114
45115	parse(json) {
45116
45117		const textures = this.textures;
45118
45119		function getTexture(name) {
45120
45121			if (textures[name] === undefined) {
45122
45123				console.warn('THREE.MaterialLoader: Undefined texture', name);
45124
45125			}
45126
45127			return textures[name];
45128
45129		}
45130
45131		const material = MaterialLoader.createMaterialFromType(json.type);
45132
45133		if (json.uuid !== undefined) material.uuid = json.uuid;
45134		if (json.name !== undefined) material.name = json.name;
45135		if (json.color !== undefined && material.color !== undefined) material.color.setHex(json.color);
45136		if (json.roughness !== undefined) material.roughness = json.roughness;
45137		if (json.metalness !== undefined) material.metalness = json.metalness;
45138		if (json.sheen !== undefined) material.sheen = json.sheen;
45139		if (json.sheenColor !== undefined) material.sheenColor = new Color().setHex(json.sheenColor);
45140		if (json.sheenRoughness !== undefined) material.sheenRoughness = json.sheenRoughness;
45141		if (json.emissive !== undefined && material.emissive !== undefined) material.emissive.setHex(json.emissive);
45142		if (json.specular !== undefined && material.specular !== undefined) material.specular.setHex(json.specular);
45143		if (json.specularIntensity !== undefined) material.specularIntensity = json.specularIntensity;
45144		if (json.specularColor !== undefined && material.specularColor !== undefined) material.specularColor.setHex(json.specularColor);
45145		if (json.shininess !== undefined) material.shininess = json.shininess;
45146		if (json.clearcoat !== undefined) material.clearcoat = json.clearcoat;
45147		if (json.clearcoatRoughness !== undefined) material.clearcoatRoughness = json.clearcoatRoughness;
45148		if (json.iridescence !== undefined) material.iridescence = json.iridescence;
45149		if (json.iridescenceIOR !== undefined) material.iridescenceIOR = json.iridescenceIOR;
45150		if (json.iridescenceThicknessRange !== undefined) material.iridescenceThicknessRange = json.iridescenceThicknessRange;
45151		if (json.transmission !== undefined) material.transmission = json.transmission;
45152		if (json.thickness !== undefined) material.thickness = json.thickness;
45153		if (json.attenuationDistance !== undefined) material.attenuationDistance = json.attenuationDistance;
45154		if (json.attenuationColor !== undefined && material.attenuationColor !== undefined) material.attenuationColor.setHex(json.attenuationColor);
45155		if (json.anisotropy !== undefined) material.anisotropy = json.anisotropy;
45156		if (json.anisotropyRotation !== undefined) material.anisotropyRotation = json.anisotropyRotation;
45157		if (json.fog !== undefined) material.fog = json.fog;
45158		if (json.flatShading !== undefined) material.flatShading = json.flatShading;
45159		if (json.blending !== undefined) material.blending = json.blending;
45160		if (json.combine !== undefined) material.combine = json.combine;
45161		if (json.side !== undefined) material.side = json.side;
45162		if (json.shadowSide !== undefined) material.shadowSide = json.shadowSide;
45163		if (json.opacity !== undefined) material.opacity = json.opacity;
45164		if (json.transparent !== undefined) material.transparent = json.transparent;
45165		if (json.alphaTest !== undefined) material.alphaTest = json.alphaTest;
45166		if (json.alphaHash !== undefined) material.alphaHash = json.alphaHash;
45167		if (json.depthFunc !== undefined) material.depthFunc = json.depthFunc;
45168		if (json.depthTest !== undefined) material.depthTest = json.depthTest;
45169		if (json.depthWrite !== undefined) material.depthWrite = json.depthWrite;
45170		if (json.colorWrite !== undefined) material.colorWrite = json.colorWrite;
45171		if (json.blendSrc !== undefined) material.blendSrc = json.blendSrc;
45172		if (json.blendDst !== undefined) material.blendDst = json.blendDst;
45173		if (json.blendEquation !== undefined) material.blendEquation = json.blendEquation;
45174		if (json.blendSrcAlpha !== undefined) material.blendSrcAlpha = json.blendSrcAlpha;
45175		if (json.blendDstAlpha !== undefined) material.blendDstAlpha = json.blendDstAlpha;
45176		if (json.blendEquationAlpha !== undefined) material.blendEquationAlpha = json.blendEquationAlpha;
45177		if (json.blendColor !== undefined && material.blendColor !== undefined) material.blendColor.setHex(json.blendColor);
45178		if (json.blendAlpha !== undefined) material.blendAlpha = json.blendAlpha;
45179		if (json.stencilWriteMask !== undefined) material.stencilWriteMask = json.stencilWriteMask;
45180		if (json.stencilFunc !== undefined) material.stencilFunc = json.stencilFunc;
45181		if (json.stencilRef !== undefined) material.stencilRef = json.stencilRef;
45182		if (json.stencilFuncMask !== undefined) material.stencilFuncMask = json.stencilFuncMask;
45183		if (json.stencilFail !== undefined) material.stencilFail = json.stencilFail;
45184		if (json.stencilZFail !== undefined) material.stencilZFail = json.stencilZFail;
45185		if (json.stencilZPass !== undefined) material.stencilZPass = json.stencilZPass;
45186		if (json.stencilWrite !== undefined) material.stencilWrite = json.stencilWrite;
45187
45188		if (json.wireframe !== undefined) material.wireframe = json.wireframe;
45189		if (json.wireframeLinewidth !== undefined) material.wireframeLinewidth = json.wireframeLinewidth;
45190		if (json.wireframeLinecap !== undefined) material.wireframeLinecap = json.wireframeLinecap;
45191		if (json.wireframeLinejoin !== undefined) material.wireframeLinejoin = json.wireframeLinejoin;
45192
45193		if (json.rotation !== undefined) material.rotation = json.rotation;
45194
45195		if (json.linewidth !== undefined) material.linewidth = json.linewidth;
45196		if (json.dashSize !== undefined) material.dashSize = json.dashSize;
45197		if (json.gapSize !== undefined) material.gapSize = json.gapSize;
45198		if (json.scale !== undefined) material.scale = json.scale;
45199
45200		if (json.polygonOffset !== undefined) material.polygonOffset = json.polygonOffset;
45201		if (json.polygonOffsetFactor !== undefined) material.polygonOffsetFactor = json.polygonOffsetFactor;
45202		if (json.polygonOffsetUnits !== undefined) material.polygonOffsetUnits = json.polygonOffsetUnits;
45203
45204		if (json.dithering !== undefined) material.dithering = json.dithering;
45205
45206		if (json.alphaToCoverage !== undefined) material.alphaToCoverage = json.alphaToCoverage;
45207		if (json.premultipliedAlpha !== undefined) material.premultipliedAlpha = json.premultipliedAlpha;
45208		if (json.forceSinglePass !== undefined) material.forceSinglePass = json.forceSinglePass;
45209
45210		if (json.visible !== undefined) material.visible = json.visible;
45211
45212		if (json.toneMapped !== undefined) material.toneMapped = json.toneMapped;
45213
45214		if (json.userData !== undefined) material.userData = json.userData;
45215
45216		if (json.vertexColors !== undefined) {
45217
45218			if (typeof json.vertexColors === 'number') {
45219
45220				material.vertexColors = (json.vertexColors > 0) ? true : false;
45221
45222			} else {
45223
45224				material.vertexColors = json.vertexColors;
45225
45226			}
45227
45228		}
45229
45230		// Shader Material
45231
45232		if (json.uniforms !== undefined) {
45233
45234			for (const name in json.uniforms) {
45235
45236				const uniform = json.uniforms[name];
45237
45238				material.uniforms[name] = {};
45239
45240				switch (uniform.type) {
45241
45242					case 't':
45243						material.uniforms[name].value = getTexture(uniform.value);
45244						break;
45245
45246					case 'c':
45247						material.uniforms[name].value = new Color().setHex(uniform.value);
45248						break;
45249
45250					case 'v2':
45251						material.uniforms[name].value = new Vector2().fromArray(uniform.value);
45252						break;
45253
45254					case 'v3':
45255						material.uniforms[name].value = new Vector3().fromArray(uniform.value);
45256						break;
45257
45258					case 'v4':
45259						material.uniforms[name].value = new Vector4().fromArray(uniform.value);
45260						break;
45261
45262					case 'm3':
45263						material.uniforms[name].value = new Matrix3().fromArray(uniform.value);
45264						break;
45265
45266					case 'm4':
45267						material.uniforms[name].value = new Matrix4().fromArray(uniform.value);
45268						break;
45269
45270					default:
45271						material.uniforms[name].value = uniform.value;
45272
45273				}
45274
45275			}
45276
45277		}
45278
45279		if (json.defines !== undefined) material.defines = json.defines;
45280		if (json.vertexShader !== undefined) material.vertexShader = json.vertexShader;
45281		if (json.fragmentShader !== undefined) material.fragmentShader = json.fragmentShader;
45282		if (json.glslVersion !== undefined) material.glslVersion = json.glslVersion;
45283
45284		if (json.extensions !== undefined) {
45285
45286			for (const key in json.extensions) {
45287
45288				material.extensions[key] = json.extensions[key];
45289
45290			}
45291
45292		}
45293
45294		if (json.lights !== undefined) material.lights = json.lights;
45295		if (json.clipping !== undefined) material.clipping = json.clipping;
45296
45297		// for PointsMaterial
45298
45299		if (json.size !== undefined) material.size = json.size;
45300		if (json.sizeAttenuation !== undefined) material.sizeAttenuation = json.sizeAttenuation;
45301
45302		// maps
45303
45304		if (json.map !== undefined) material.map = getTexture(json.map);
45305		if (json.matcap !== undefined) material.matcap = getTexture(json.matcap);
45306
45307		if (json.alphaMap !== undefined) material.alphaMap = getTexture(json.alphaMap);
45308
45309		if (json.bumpMap !== undefined) material.bumpMap = getTexture(json.bumpMap);
45310		if (json.bumpScale !== undefined) material.bumpScale = json.bumpScale;
45311
45312		if (json.normalMap !== undefined) material.normalMap = getTexture(json.normalMap);
45313		if (json.normalMapType !== undefined) material.normalMapType = json.normalMapType;
45314		if (json.normalScale !== undefined) {
45315
45316			let normalScale = json.normalScale;
45317
45318			if (Array.isArray(normalScale) === false) {
45319
45320				// Blender exporter used to export a scalar. See #7459
45321
45322				normalScale = [normalScale, normalScale];
45323
45324			}
45325
45326			material.normalScale = new Vector2().fromArray(normalScale);
45327
45328		}
45329
45330		if (json.displacementMap !== undefined) material.displacementMap = getTexture(json.displacementMap);
45331		if (json.displacementScale !== undefined) material.displacementScale = json.displacementScale;
45332		if (json.displacementBias !== undefined) material.displacementBias = json.displacementBias;
45333
45334		if (json.roughnessMap !== undefined) material.roughnessMap = getTexture(json.roughnessMap);
45335		if (json.metalnessMap !== undefined) material.metalnessMap = getTexture(json.metalnessMap);
45336
45337		if (json.emissiveMap !== undefined) material.emissiveMap = getTexture(json.emissiveMap);
45338		if (json.emissiveIntensity !== undefined) material.emissiveIntensity = json.emissiveIntensity;
45339
45340		if (json.specularMap !== undefined) material.specularMap = getTexture(json.specularMap);
45341		if (json.specularIntensityMap !== undefined) material.specularIntensityMap = getTexture(json.specularIntensityMap);
45342		if (json.specularColorMap !== undefined) material.specularColorMap = getTexture(json.specularColorMap);
45343
45344		if (json.envMap !== undefined) material.envMap = getTexture(json.envMap);
45345		if (json.envMapIntensity !== undefined) material.envMapIntensity = json.envMapIntensity;
45346
45347		if (json.reflectivity !== undefined) material.reflectivity = json.reflectivity;
45348		if (json.refractionRatio !== undefined) material.refractionRatio = json.refractionRatio;
45349
45350		if (json.lightMap !== undefined) material.lightMap = getTexture(json.lightMap);
45351		if (json.lightMapIntensity !== undefined) material.lightMapIntensity = json.lightMapIntensity;
45352
45353		if (json.aoMap !== undefined) material.aoMap = getTexture(json.aoMap);
45354		if (json.aoMapIntensity !== undefined) material.aoMapIntensity = json.aoMapIntensity;
45355
45356		if (json.gradientMap !== undefined) material.gradientMap = getTexture(json.gradientMap);
45357
45358		if (json.clearcoatMap !== undefined) material.clearcoatMap = getTexture(json.clearcoatMap);
45359		if (json.clearcoatRoughnessMap !== undefined) material.clearcoatRoughnessMap = getTexture(json.clearcoatRoughnessMap);
45360		if (json.clearcoatNormalMap !== undefined) material.clearcoatNormalMap = getTexture(json.clearcoatNormalMap);
45361		if (json.clearcoatNormalScale !== undefined) material.clearcoatNormalScale = new Vector2().fromArray(json.clearcoatNormalScale);
45362
45363		if (json.iridescenceMap !== undefined) material.iridescenceMap = getTexture(json.iridescenceMap);
45364		if (json.iridescenceThicknessMap !== undefined) material.iridescenceThicknessMap = getTexture(json.iridescenceThicknessMap);
45365
45366		if (json.transmissionMap !== undefined) material.transmissionMap = getTexture(json.transmissionMap);
45367		if (json.thicknessMap !== undefined) material.thicknessMap = getTexture(json.thicknessMap);
45368
45369		if (json.anisotropyMap !== undefined) material.anisotropyMap = getTexture(json.anisotropyMap);
45370
45371		if (json.sheenColorMap !== undefined) material.sheenColorMap = getTexture(json.sheenColorMap);
45372		if (json.sheenRoughnessMap !== undefined) material.sheenRoughnessMap = getTexture(json.sheenRoughnessMap);
45373
45374		return material;
45375
45376	}
45377
45378	setTextures(value) {
45379
45380		this.textures = value;
45381		return this;
45382
45383	}
45384
45385	static createMaterialFromType(type) {
45386
45387		const materialLib = {
45388			ShadowMaterial,
45389			SpriteMaterial,
45390			RawShaderMaterial,
45391			ShaderMaterial,
45392			PointsMaterial,
45393			MeshPhysicalMaterial,
45394			MeshStandardMaterial,
45395			MeshPhongMaterial,
45396			MeshToonMaterial,
45397			MeshNormalMaterial,
45398			MeshLambertMaterial,
45399			MeshDepthMaterial,
45400			MeshDistanceMaterial,
45401			MeshBasicMaterial,
45402			MeshMatcapMaterial,
45403			LineDashedMaterial,
45404			LineBasicMaterial,
45405			Material
45406		};
45407
45408		return new materialLib[type]();
45409
45410	}
45411
45412}
45413
45414class LoaderUtils {
45415
45416	static decodeText(array) {
45417
45418		if (typeof TextDecoder !== 'undefined') {
45419
45420			return new TextDecoder().decode(array);
45421
45422		}
45423
45424		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
45425		// throws a "maximum call stack size exceeded" error for large arrays.
45426
45427		let s = '';
45428
45429		for (let i = 0, il = array.length; i < il; i++) {
45430
45431			// Implicitly assumes little-endian.
45432			s += String.fromCharCode(array[i]);
45433
45434		}
45435
45436		try {
45437
45438			// merges multi-byte utf-8 characters.
45439
45440			return decodeURIComponent(escape(s));
45441
45442		} catch (e) { // see #16358
45443
45444			return s;
45445
45446		}
45447
45448	}
45449
45450	static extractUrlBase(url) {
45451
45452		const index = url.lastIndexOf('/');
45453
45454		if (index === - 1) return './';
45455
45456		return url.slice(0, index + 1);
45457
45458	}
45459
45460	static resolveURL(url, path) {
45461
45462		// Invalid URL
45463		if (typeof url !== 'string' || url === '') return '';
45464
45465		// Host Relative URL
45466		if (/^https?:\/\//i.test(path) && /^\//.test(url)) {
45467
45468			path = path.replace(/(^https?:\/\/[^\/]+).*/i, '$1');
45469
45470		}
45471
45472		// Absolute URL http://,https://,//
45473		if (/^(https?:)?\/\//i.test(url)) return url;
45474
45475		// Data URI
45476		if (/^data:.*,.*$/i.test(url)) return url;
45477
45478		// Blob URL
45479		if (/^blob:.*$/i.test(url)) return url;
45480
45481		// Relative URL
45482		return path + url;
45483
45484	}
45485
45486}
45487
45488class InstancedBufferGeometry extends BufferGeometry {
45489
45490	constructor() {
45491
45492		super();
45493
45494		this.isInstancedBufferGeometry = true;
45495
45496		this.type = 'InstancedBufferGeometry';
45497		this.instanceCount = Infinity;
45498
45499	}
45500
45501	copy(source) {
45502
45503		super.copy(source);
45504
45505		this.instanceCount = source.instanceCount;
45506
45507		return this;
45508
45509	}
45510
45511	toJSON() {
45512
45513		const data = super.toJSON();
45514
45515		data.instanceCount = this.instanceCount;
45516
45517		data.isInstancedBufferGeometry = true;
45518
45519		return data;
45520
45521	}
45522
45523}
45524
45525class BufferGeometryLoader extends Loader {
45526
45527	constructor(manager) {
45528
45529		super(manager);
45530
45531	}
45532
45533	load(url, onLoad, onProgress, onError) {
45534
45535		const scope = this;
45536
45537		const loader = new FileLoader(scope.manager);
45538		loader.setPath(scope.path);
45539		loader.setRequestHeader(scope.requestHeader);
45540		loader.setWithCredentials(scope.withCredentials);
45541		loader.load(url, function (text) {
45542
45543			try {
45544
45545				onLoad(scope.parse(JSON.parse(text)));
45546
45547			} catch (e) {
45548
45549				if (onError) {
45550
45551					onError(e);
45552
45553				} else {
45554
45555					console.error(e);
45556
45557				}
45558
45559				scope.manager.itemError(url);
45560
45561			}
45562
45563		}, onProgress, onError);
45564
45565	}
45566
45567	parse(json) {
45568
45569		const interleavedBufferMap = {};
45570		const arrayBufferMap = {};
45571
45572		function getInterleavedBuffer(json, uuid) {
45573
45574			if (interleavedBufferMap[uuid] !== undefined) return interleavedBufferMap[uuid];
45575
45576			const interleavedBuffers = json.interleavedBuffers;
45577			const interleavedBuffer = interleavedBuffers[uuid];
45578
45579			const buffer = getArrayBuffer(json, interleavedBuffer.buffer);
45580
45581			const array = getTypedArray(interleavedBuffer.type, buffer);
45582			const ib = new InterleavedBuffer(array, interleavedBuffer.stride);
45583			ib.uuid = interleavedBuffer.uuid;
45584
45585			interleavedBufferMap[uuid] = ib;
45586
45587			return ib;
45588
45589		}
45590
45591		function getArrayBuffer(json, uuid) {
45592
45593			if (arrayBufferMap[uuid] !== undefined) return arrayBufferMap[uuid];
45594
45595			const arrayBuffers = json.arrayBuffers;
45596			const arrayBuffer = arrayBuffers[uuid];
45597
45598			const ab = new Uint32Array(arrayBuffer).buffer;
45599
45600			arrayBufferMap[uuid] = ab;
45601
45602			return ab;
45603
45604		}
45605
45606		const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
45607
45608		const index = json.data.index;
45609
45610		if (index !== undefined) {
45611
45612			const typedArray = getTypedArray(index.type, index.array);
45613			geometry.setIndex(new BufferAttribute(typedArray, 1));
45614
45615		}
45616
45617		const attributes = json.data.attributes;
45618
45619		for (const key in attributes) {
45620
45621			const attribute = attributes[key];
45622			let bufferAttribute;
45623
45624			if (attribute.isInterleavedBufferAttribute) {
45625
45626				const interleavedBuffer = getInterleavedBuffer(json.data, attribute.data);
45627				bufferAttribute = new InterleavedBufferAttribute(interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized);
45628
45629			} else {
45630
45631				const typedArray = getTypedArray(attribute.type, attribute.array);
45632				const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
45633				bufferAttribute = new bufferAttributeConstr(typedArray, attribute.itemSize, attribute.normalized);
45634
45635			}
45636
45637			if (attribute.name !== undefined) bufferAttribute.name = attribute.name;
45638			if (attribute.usage !== undefined) bufferAttribute.setUsage(attribute.usage);
45639
45640			geometry.setAttribute(key, bufferAttribute);
45641
45642		}
45643
45644		const morphAttributes = json.data.morphAttributes;
45645
45646		if (morphAttributes) {
45647
45648			for (const key in morphAttributes) {
45649
45650				const attributeArray = morphAttributes[key];
45651
45652				const array = [];
45653
45654				for (let i = 0, il = attributeArray.length; i < il; i++) {
45655
45656					const attribute = attributeArray[i];
45657					let bufferAttribute;
45658
45659					if (attribute.isInterleavedBufferAttribute) {
45660
45661						const interleavedBuffer = getInterleavedBuffer(json.data, attribute.data);
45662						bufferAttribute = new InterleavedBufferAttribute(interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized);
45663
45664					} else {
45665
45666						const typedArray = getTypedArray(attribute.type, attribute.array);
45667						bufferAttribute = new BufferAttribute(typedArray, attribute.itemSize, attribute.normalized);
45668
45669					}
45670
45671					if (attribute.name !== undefined) bufferAttribute.name = attribute.name;
45672					array.push(bufferAttribute);
45673
45674				}
45675
45676				geometry.morphAttributes[key] = array;
45677
45678			}
45679
45680		}
45681
45682		const morphTargetsRelative = json.data.morphTargetsRelative;
45683
45684		if (morphTargetsRelative) {
45685
45686			geometry.morphTargetsRelative = true;
45687
45688		}
45689
45690		const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
45691
45692		if (groups !== undefined) {
45693
45694			for (let i = 0, n = groups.length; i !== n; ++i) {
45695
45696				const group = groups[i];
45697
45698				geometry.addGroup(group.start, group.count, group.materialIndex);
45699
45700			}
45701
45702		}
45703
45704		const boundingSphere = json.data.boundingSphere;
45705
45706		if (boundingSphere !== undefined) {
45707
45708			const center = new Vector3();
45709
45710			if (boundingSphere.center !== undefined) {
45711
45712				center.fromArray(boundingSphere.center);
45713
45714			}
45715
45716			geometry.boundingSphere = new Sphere(center, boundingSphere.radius);
45717
45718		}
45719
45720		if (json.name) geometry.name = json.name;
45721		if (json.userData) geometry.userData = json.userData;
45722
45723		return geometry;
45724
45725	}
45726
45727}
45728
45729class ObjectLoader extends Loader {
45730
45731	constructor(manager) {
45732
45733		super(manager);
45734
45735	}
45736
45737	load(url, onLoad, onProgress, onError) {
45738
45739		const scope = this;
45740
45741		const path = (this.path === '') ? LoaderUtils.extractUrlBase(url) : this.path;
45742		this.resourcePath = this.resourcePath || path;
45743
45744		const loader = new FileLoader(this.manager);
45745		loader.setPath(this.path);
45746		loader.setRequestHeader(this.requestHeader);
45747		loader.setWithCredentials(this.withCredentials);
45748		loader.load(url, function (text) {
45749
45750			let json = null;
45751
45752			try {
45753
45754				json = JSON.parse(text);
45755
45756			} catch (error) {
45757
45758				if (onError !== undefined) onError(error);
45759
45760				console.error('THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message);
45761
45762				return;
45763
45764			}
45765
45766			const metadata = json.metadata;
45767
45768			if (metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry') {
45769
45770				if (onError !== undefined) onError(new Error('THREE.ObjectLoader: Can\'t load ' + url));
45771
45772				console.error('THREE.ObjectLoader: Can\'t load ' + url);
45773				return;
45774
45775			}
45776
45777			scope.parse(json, onLoad);
45778
45779		}, onProgress, onError);
45780
45781	}
45782
45783	async loadAsync(url, onProgress) {
45784
45785		const scope = this;
45786
vendor: 7,138 bytes, lines 45787-46160
45787		const path = (this.path === '') ? LoaderUtils.extractUrlBase(url) : this.path;
45788		this.resourcePath = this.resourcePath || path;
45789
45790		const loader = new FileLoader(this.manager);
45791		loader.setPath(this.path);
45792		loader.setRequestHeader(this.requestHeader);
45793		loader.setWithCredentials(this.withCredentials);
45794
45795		const text = await loader.loadAsync(url, onProgress);
45796
45797		const json = JSON.parse(text);
45798
45799		const metadata = json.metadata;
45800
45801		if (metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry') {
45802
45803			throw new Error('THREE.ObjectLoader: Can\'t load ' + url);
45804
45805		}
45806
45807		return await scope.parseAsync(json);
45808
45809	}
45810
45811	parse(json, onLoad) {
45812
45813		const animations = this.parseAnimations(json.animations);
45814		const shapes = this.parseShapes(json.shapes);
45815		const geometries = this.parseGeometries(json.geometries, shapes);
45816
45817		const images = this.parseImages(json.images, function () {
45818
45819			if (onLoad !== undefined) onLoad(object);
45820
45821		});
45822
45823		const textures = this.parseTextures(json.textures, images);
45824		const materials = this.parseMaterials(json.materials, textures);
45825
45826		const object = this.parseObject(json.object, geometries, materials, textures, animations);
45827		const skeletons = this.parseSkeletons(json.skeletons, object);
45828
45829		this.bindSkeletons(object, skeletons);
45830
45831		//
45832
45833		if (onLoad !== undefined) {
45834
45835			let hasImages = false;
45836
45837			for (const uuid in images) {
45838
45839				if (images[uuid].data instanceof HTMLImageElement) {
45840
45841					hasImages = true;
45842					break;
45843
45844				}
45845
45846			}
45847
45848			if (hasImages === false) onLoad(object);
45849
45850		}
45851
45852		return object;
45853
45854	}
45855
45856	async parseAsync(json) {
45857
45858		const animations = this.parseAnimations(json.animations);
45859		const shapes = this.parseShapes(json.shapes);
45860		const geometries = this.parseGeometries(json.geometries, shapes);
45861
45862		const images = await this.parseImagesAsync(json.images);
45863
45864		const textures = this.parseTextures(json.textures, images);
45865		const materials = this.parseMaterials(json.materials, textures);
45866
45867		const object = this.parseObject(json.object, geometries, materials, textures, animations);
45868		const skeletons = this.parseSkeletons(json.skeletons, object);
45869
45870		this.bindSkeletons(object, skeletons);
45871
45872		return object;
45873
45874	}
45875
45876	parseShapes(json) {
45877
45878		const shapes = {};
45879
45880		if (json !== undefined) {
45881
45882			for (let i = 0, l = json.length; i < l; i++) {
45883
45884				const shape = new Shape().fromJSON(json[i]);
45885
45886				shapes[shape.uuid] = shape;
45887
45888			}
45889
45890		}
45891
45892		return shapes;
45893
45894	}
45895
45896	parseSkeletons(json, object) {
45897
45898		const skeletons = {};
45899		const bones = {};
45900
45901		// generate bone lookup table
45902
45903		object.traverse(function (child) {
45904
45905			if (child.isBone) bones[child.uuid] = child;
45906
45907		});
45908
45909		// create skeletons
45910
45911		if (json !== undefined) {
45912
45913			for (let i = 0, l = json.length; i < l; i++) {
45914
45915				const skeleton = new Skeleton().fromJSON(json[i], bones);
45916
45917				skeletons[skeleton.uuid] = skeleton;
45918
45919			}
45920
45921		}
45922
45923		return skeletons;
45924
45925	}
45926
45927	parseGeometries(json, shapes) {
45928
45929		const geometries = {};
45930
45931		if (json !== undefined) {
45932
45933			const bufferGeometryLoader = new BufferGeometryLoader();
45934
45935			for (let i = 0, l = json.length; i < l; i++) {
45936
45937				let geometry;
45938				const data = json[i];
45939
45940				switch (data.type) {
45941
45942					case 'BufferGeometry':
45943					case 'InstancedBufferGeometry':
45944
45945						geometry = bufferGeometryLoader.parse(data);
45946						break;
45947
45948					default:
45949
45950						if (data.type in Geometries) {
45951
45952							geometry = Geometries[data.type].fromJSON(data, shapes);
45953
45954						} else {
45955
45956							console.warn(`THREE.ObjectLoader: Unsupported geometry type "${data.type}"`);
45957
45958						}
45959
45960				}
45961
45962				geometry.uuid = data.uuid;
45963
45964				if (data.name !== undefined) geometry.name = data.name;
45965				if (data.userData !== undefined) geometry.userData = data.userData;
45966
45967				geometries[data.uuid] = geometry;
45968
45969			}
45970
45971		}
45972
45973		return geometries;
45974
45975	}
45976
45977	parseMaterials(json, textures) {
45978
45979		const cache = {}; // MultiMaterial
45980		const materials = {};
45981
45982		if (json !== undefined) {
45983
45984			const loader = new MaterialLoader();
45985			loader.setTextures(textures);
45986
45987			for (let i = 0, l = json.length; i < l; i++) {
45988
45989				const data = json[i];
45990
45991				if (cache[data.uuid] === undefined) {
45992
45993					cache[data.uuid] = loader.parse(data);
45994
45995				}
45996
45997				materials[data.uuid] = cache[data.uuid];
45998
45999			}
46000
46001		}
46002
46003		return materials;
46004
46005	}
46006
46007	parseAnimations(json) {
46008
46009		const animations = {};
46010
46011		if (json !== undefined) {
46012
46013			for (let i = 0; i < json.length; i++) {
46014
46015				const data = json[i];
46016
46017				const clip = AnimationClip.parse(data);
46018
46019				animations[clip.uuid] = clip;
46020
46021			}
46022
46023		}
46024
46025		return animations;
46026
46027	}
46028
46029	parseImages(json, onLoad) {
46030
46031		const scope = this;
46032		const images = {};
46033
46034		let loader;
46035
46036		function loadImage(url) {
46037
46038			scope.manager.itemStart(url);
46039
46040			return loader.load(url, function () {
46041
46042				scope.manager.itemEnd(url);
46043
46044			}, undefined, function () {
46045
46046				scope.manager.itemError(url);
46047				scope.manager.itemEnd(url);
46048
46049			});
46050
46051		}
46052
46053		function deserializeImage(image) {
46054
46055			if (typeof image === 'string') {
46056
46057				const url = image;
46058
46059				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(url) ? url : scope.resourcePath + url;
46060
46061				return loadImage(path);
46062
46063			} else {
46064
46065				if (image.data) {
46066
46067					return {
46068						data: getTypedArray(image.type, image.data),
46069						width: image.width,
46070						height: image.height
46071					};
46072
46073				} else {
46074
46075					return null;
46076
46077				}
46078
46079			}
46080
46081		}
46082
46083		if (json !== undefined && json.length > 0) {
46084
46085			const manager = new LoadingManager(onLoad);
46086
46087			loader = new ImageLoader(manager);
46088			loader.setCrossOrigin(this.crossOrigin);
46089
46090			for (let i = 0, il = json.length; i < il; i++) {
46091
46092				const image = json[i];
46093				const url = image.url;
46094
46095				if (Array.isArray(url)) {
46096
46097					// load array of images e.g CubeTexture
46098
46099					const imageArray = [];
46100
46101					for (let j = 0, jl = url.length; j < jl; j++) {
46102
46103						const currentUrl = url[j];
46104
46105						const deserializedImage = deserializeImage(currentUrl);
46106
46107						if (deserializedImage !== null) {
46108
46109							if (deserializedImage instanceof HTMLImageElement) {
46110
46111								imageArray.push(deserializedImage);
46112
46113							} else {
46114
46115								// special case: handle array of data textures for cube textures
46116
46117								imageArray.push(new DataTexture(deserializedImage.data, deserializedImage.width, deserializedImage.height));
46118
46119							}
46120
46121						}
46122
46123					}
46124
46125					images[image.uuid] = new Source(imageArray);
46126
46127				} else {
46128
46129					// load single image
46130
46131					const deserializedImage = deserializeImage(image.url);
46132					images[image.uuid] = new Source(deserializedImage);
46133
46134
46135				}
46136
46137			}
46138
46139		}
46140
46141		return images;
46142
46143	}
46144
46145	async parseImagesAsync(json) {
46146
46147		const scope = this;
46148		const images = {};
46149
46150		let loader;
46151
46152		async function deserializeImage(image) {
46153
46154			if (typeof image === 'string') {
46155
46156				const url = image;
46157
46158				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(url) ? url : scope.resourcePath + url;
46159
46160				return await loader.loadAsync(path);
vendor: 10,365 bytes, lines 46161-46591
46161
46162			} else {
46163
46164				if (image.data) {
46165
46166					return {
46167						data: getTypedArray(image.type, image.data),
46168						width: image.width,
46169						height: image.height
46170					};
46171
46172				} else {
46173
46174					return null;
46175
46176				}
46177
46178			}
46179
46180		}
46181
46182		if (json !== undefined && json.length > 0) {
46183
46184			loader = new ImageLoader(this.manager);
46185			loader.setCrossOrigin(this.crossOrigin);
46186
46187			for (let i = 0, il = json.length; i < il; i++) {
46188
46189				const image = json[i];
46190				const url = image.url;
46191
46192				if (Array.isArray(url)) {
46193
46194					// load array of images e.g CubeTexture
46195
46196					const imageArray = [];
46197
46198					for (let j = 0, jl = url.length; j < jl; j++) {
46199
46200						const currentUrl = url[j];
46201
46202						const deserializedImage = await deserializeImage(currentUrl);
46203
46204						if (deserializedImage !== null) {
46205
46206							if (deserializedImage instanceof HTMLImageElement) {
46207
46208								imageArray.push(deserializedImage);
46209
46210							} else {
46211
46212								// special case: handle array of data textures for cube textures
46213
46214								imageArray.push(new DataTexture(deserializedImage.data, deserializedImage.width, deserializedImage.height));
46215
46216							}
46217
46218						}
46219
46220					}
46221
46222					images[image.uuid] = new Source(imageArray);
46223
46224				} else {
46225
46226					// load single image
46227
46228					const deserializedImage = await deserializeImage(image.url);
46229					images[image.uuid] = new Source(deserializedImage);
46230
46231				}
46232
46233			}
46234
46235		}
46236
46237		return images;
46238
46239	}
46240
46241	parseTextures(json, images) {
46242
46243		function parseConstant(value, type) {
46244
46245			if (typeof value === 'number') return value;
46246
46247			console.warn('THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value);
46248
46249			return type[value];
46250
46251		}
46252
46253		const textures = {};
46254
46255		if (json !== undefined) {
46256
46257			for (let i = 0, l = json.length; i < l; i++) {
46258
46259				const data = json[i];
46260
46261				if (data.image === undefined) {
46262
46263					console.warn('THREE.ObjectLoader: No "image" specified for', data.uuid);
46264
46265				}
46266
46267				if (images[data.image] === undefined) {
46268
46269					console.warn('THREE.ObjectLoader: Undefined image', data.image);
46270
46271				}
46272
46273				const source = images[data.image];
46274				const image = source.data;
46275
46276				let texture;
46277
46278				if (Array.isArray(image)) {
46279
46280					texture = new CubeTexture();
46281
46282					if (image.length === 6) texture.needsUpdate = true;
46283
46284				} else {
46285
46286					if (image && image.data) {
46287
46288						texture = new DataTexture();
46289
46290					} else {
46291
46292						texture = new Texture();
46293
46294					}
46295
46296					if (image) texture.needsUpdate = true; // textures can have undefined image data
46297
46298				}
46299
46300				texture.source = source;
46301
46302				texture.uuid = data.uuid;
46303
46304				if (data.name !== undefined) texture.name = data.name;
46305
46306				if (data.mapping !== undefined) texture.mapping = parseConstant(data.mapping, TEXTURE_MAPPING);
46307				if (data.channel !== undefined) texture.channel = data.channel;
46308
46309				if (data.offset !== undefined) texture.offset.fromArray(data.offset);
46310				if (data.repeat !== undefined) texture.repeat.fromArray(data.repeat);
46311				if (data.center !== undefined) texture.center.fromArray(data.center);
46312				if (data.rotation !== undefined) texture.rotation = data.rotation;
46313
46314				if (data.wrap !== undefined) {
46315
46316					texture.wrapS = parseConstant(data.wrap[0], TEXTURE_WRAPPING);
46317					texture.wrapT = parseConstant(data.wrap[1], TEXTURE_WRAPPING);
46318
46319				}
46320
46321				if (data.format !== undefined) texture.format = data.format;
46322				if (data.internalFormat !== undefined) texture.internalFormat = data.internalFormat;
46323				if (data.type !== undefined) texture.type = data.type;
46324				if (data.colorSpace !== undefined) texture.colorSpace = data.colorSpace;
46325				if (data.encoding !== undefined) texture.encoding = data.encoding; // @deprecated, r152
46326
46327				if (data.minFilter !== undefined) texture.minFilter = parseConstant(data.minFilter, TEXTURE_FILTER);
46328				if (data.magFilter !== undefined) texture.magFilter = parseConstant(data.magFilter, TEXTURE_FILTER);
46329				if (data.anisotropy !== undefined) texture.anisotropy = data.anisotropy;
46330
46331				if (data.flipY !== undefined) texture.flipY = data.flipY;
46332
46333				if (data.generateMipmaps !== undefined) texture.generateMipmaps = data.generateMipmaps;
46334				if (data.premultiplyAlpha !== undefined) texture.premultiplyAlpha = data.premultiplyAlpha;
46335				if (data.unpackAlignment !== undefined) texture.unpackAlignment = data.unpackAlignment;
46336				if (data.compareFunction !== undefined) texture.compareFunction = data.compareFunction;
46337
46338				if (data.userData !== undefined) texture.userData = data.userData;
46339
46340				textures[data.uuid] = texture;
46341
46342			}
46343
46344		}
46345
46346		return textures;
46347
46348	}
46349
46350	parseObject(data, geometries, materials, textures, animations) {
46351
46352		let object;
46353
46354		function getGeometry(name) {
46355
46356			if (geometries[name] === undefined) {
46357
46358				console.warn('THREE.ObjectLoader: Undefined geometry', name);
46359
46360			}
46361
46362			return geometries[name];
46363
46364		}
46365
46366		function getMaterial(name) {
46367
46368			if (name === undefined) return undefined;
46369
46370			if (Array.isArray(name)) {
46371
46372				const array = [];
46373
46374				for (let i = 0, l = name.length; i < l; i++) {
46375
46376					const uuid = name[i];
46377
46378					if (materials[uuid] === undefined) {
46379
46380						console.warn('THREE.ObjectLoader: Undefined material', uuid);
46381
46382					}
46383
46384					array.push(materials[uuid]);
46385
46386				}
46387
46388				return array;
46389
46390			}
46391
46392			if (materials[name] === undefined) {
46393
46394				console.warn('THREE.ObjectLoader: Undefined material', name);
46395
46396			}
46397
46398			return materials[name];
46399
46400		}
46401
46402		function getTexture(uuid) {
46403
46404			if (textures[uuid] === undefined) {
46405
46406				console.warn('THREE.ObjectLoader: Undefined texture', uuid);
46407
46408			}
46409
46410			return textures[uuid];
46411
46412		}
46413
46414		let geometry, material;
46415
46416		switch (data.type) {
46417
46418			case 'Scene':
46419
46420				object = new Scene();
46421
46422				if (data.background !== undefined) {
46423
46424					if (Number.isInteger(data.background)) {
46425
46426						object.background = new Color(data.background);
46427
46428					} else {
46429
46430						object.background = getTexture(data.background);
46431
46432					}
46433
46434				}
46435
46436				if (data.environment !== undefined) {
46437
46438					object.environment = getTexture(data.environment);
46439
46440				}
46441
46442				if (data.fog !== undefined) {
46443
46444					if (data.fog.type === 'Fog') {
46445
46446						object.fog = new Fog(data.fog.color, data.fog.near, data.fog.far);
46447
46448					} else if (data.fog.type === 'FogExp2') {
46449
46450						object.fog = new FogExp2(data.fog.color, data.fog.density);
46451
46452					}
46453
46454					if (data.fog.name !== '') {
46455
46456						object.fog.name = data.fog.name;
46457
46458					}
46459
46460				}
46461
46462				if (data.backgroundBlurriness !== undefined) object.backgroundBlurriness = data.backgroundBlurriness;
46463				if (data.backgroundIntensity !== undefined) object.backgroundIntensity = data.backgroundIntensity;
46464
46465				break;
46466
46467			case 'PerspectiveCamera':
46468
46469				object = new PerspectiveCamera(data.fov, data.aspect, data.near, data.far);
46470
46471				if (data.focus !== undefined) object.focus = data.focus;
46472				if (data.zoom !== undefined) object.zoom = data.zoom;
46473				if (data.filmGauge !== undefined) object.filmGauge = data.filmGauge;
46474				if (data.filmOffset !== undefined) object.filmOffset = data.filmOffset;
46475				if (data.view !== undefined) object.view = Object.assign({}, data.view);
46476
46477				break;
46478
46479			case 'OrthographicCamera':
46480
46481				object = new OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);
46482
46483				if (data.zoom !== undefined) object.zoom = data.zoom;
46484				if (data.view !== undefined) object.view = Object.assign({}, data.view);
46485
46486				break;
46487
46488			case 'AmbientLight':
46489
46490				object = new AmbientLight(data.color, data.intensity);
46491
46492				break;
46493
46494			case 'DirectionalLight':
46495
46496				object = new DirectionalLight(data.color, data.intensity);
46497
46498				break;
46499
46500			case 'PointLight':
46501
46502				object = new PointLight(data.color, data.intensity, data.distance, data.decay);
46503
46504				break;
46505
46506			case 'RectAreaLight':
46507
46508				object = new RectAreaLight(data.color, data.intensity, data.width, data.height);
46509
46510				break;
46511
46512			case 'SpotLight':
46513
46514				object = new SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay);
46515
46516				break;
46517
46518			case 'HemisphereLight':
46519
46520				object = new HemisphereLight(data.color, data.groundColor, data.intensity);
46521
46522				break;
46523
46524			case 'LightProbe':
46525
46526				object = new LightProbe().fromJSON(data);
46527
46528				break;
46529
46530			case 'SkinnedMesh':
46531
46532				geometry = getGeometry(data.geometry);
46533				material = getMaterial(data.material);
46534
46535				object = new SkinnedMesh(geometry, material);
46536
46537				if (data.bindMode !== undefined) object.bindMode = data.bindMode;
46538				if (data.bindMatrix !== undefined) object.bindMatrix.fromArray(data.bindMatrix);
46539				if (data.skeleton !== undefined) object.skeleton = data.skeleton;
46540
46541				break;
46542
46543			case 'Mesh':
46544
46545				geometry = getGeometry(data.geometry);
46546				material = getMaterial(data.material);
46547
46548				object = new Mesh(geometry, material);
46549
46550				break;
46551
46552			case 'InstancedMesh':
46553
46554				geometry = getGeometry(data.geometry);
46555				material = getMaterial(data.material);
46556				const count = data.count;
46557				const instanceMatrix = data.instanceMatrix;
46558				const instanceColor = data.instanceColor;
46559
46560				object = new InstancedMesh(geometry, material, count);
46561				object.instanceMatrix = new InstancedBufferAttribute(new Float32Array(instanceMatrix.array), 16);
46562				if (instanceColor !== undefined) object.instanceColor = new InstancedBufferAttribute(new Float32Array(instanceColor.array), instanceColor.itemSize);
46563
46564				break;
46565
46566			case 'BatchedMesh':
46567
46568				geometry = getGeometry(data.geometry);
46569				material = getMaterial(data.material);
46570
46571				object = new BatchedMesh(data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material);
46572				object.geometry = geometry;
46573				object.perObjectFrustumCulled = data.perObjectFrustumCulled;
46574				object.sortObjects = data.sortObjects;
46575
46576				object._drawRanges = data.drawRanges;
46577				object._reservedRanges = data.reservedRanges;
46578
46579				object._visibility = data.visibility;
46580				object._active = data.active;
46581				object._bounds = data.bounds.map(bound => {
46582
46583					const box = new Box3();
46584					box.min.fromArray(bound.boxMin);
46585					box.max.fromArray(bound.boxMax);
46586
46587					const sphere = new Sphere();
46588					sphere.radius = bound.sphereRadius;
46589					sphere.center.fromArray(bound.sphereCenter);
46590
46591					return {
vendor: 11,586 bytes, lines 46592-47124
46592						boxInitialized: bound.boxInitialized,
46593						box: box,
46594
46595						sphereInitialized: bound.sphereInitialized,
46596						sphere: sphere
46597					};
46598
46599				});
46600
46601				object._maxGeometryCount = data.maxGeometryCount;
46602				object._maxVertexCount = data.maxVertexCount;
46603				object._maxIndexCount = data.maxIndexCount;
46604
46605				object._geometryInitialized = data.geometryInitialized;
46606				object._geometryCount = data.geometryCount;
46607
46608				object._matricesTexture = getTexture(data.matricesTexture.uuid);
46609
46610				break;
46611
46612			case 'LOD':
46613
46614				object = new LOD();
46615
46616				break;
46617
46618			case 'Line':
46619
46620				object = new Line(getGeometry(data.geometry), getMaterial(data.material));
46621
46622				break;
46623
46624			case 'LineLoop':
46625
46626				object = new LineLoop(getGeometry(data.geometry), getMaterial(data.material));
46627
46628				break;
46629
46630			case 'LineSegments':
46631
46632				object = new LineSegments(getGeometry(data.geometry), getMaterial(data.material));
46633
46634				break;
46635
46636			case 'PointCloud':
46637			case 'Points':
46638
46639				object = new Points(getGeometry(data.geometry), getMaterial(data.material));
46640
46641				break;
46642
46643			case 'Sprite':
46644
46645				object = new Sprite(getMaterial(data.material));
46646
46647				break;
46648
46649			case 'Group':
46650
46651				object = new Group();
46652
46653				break;
46654
46655			case 'Bone':
46656
46657				object = new Bone();
46658
46659				break;
46660
46661			default:
46662
46663				object = new Object3D();
46664
46665		}
46666
46667		object.uuid = data.uuid;
46668
46669		if (data.name !== undefined) object.name = data.name;
46670
46671		if (data.matrix !== undefined) {
46672
46673			object.matrix.fromArray(data.matrix);
46674
46675			if (data.matrixAutoUpdate !== undefined) object.matrixAutoUpdate = data.matrixAutoUpdate;
46676			if (object.matrixAutoUpdate) object.matrix.decompose(object.position, object.quaternion, object.scale);
46677
46678		} else {
46679
46680			if (data.position !== undefined) object.position.fromArray(data.position);
46681			if (data.rotation !== undefined) object.rotation.fromArray(data.rotation);
46682			if (data.quaternion !== undefined) object.quaternion.fromArray(data.quaternion);
46683			if (data.scale !== undefined) object.scale.fromArray(data.scale);
46684
46685		}
46686
46687		if (data.up !== undefined) object.up.fromArray(data.up);
46688
46689		if (data.castShadow !== undefined) object.castShadow = data.castShadow;
46690		if (data.receiveShadow !== undefined) object.receiveShadow = data.receiveShadow;
46691
46692		if (data.shadow) {
46693
46694			if (data.shadow.bias !== undefined) object.shadow.bias = data.shadow.bias;
46695			if (data.shadow.normalBias !== undefined) object.shadow.normalBias = data.shadow.normalBias;
46696			if (data.shadow.radius !== undefined) object.shadow.radius = data.shadow.radius;
46697			if (data.shadow.mapSize !== undefined) object.shadow.mapSize.fromArray(data.shadow.mapSize);
46698			if (data.shadow.camera !== undefined) object.shadow.camera = this.parseObject(data.shadow.camera);
46699
46700		}
46701
46702		if (data.visible !== undefined) object.visible = data.visible;
46703		if (data.frustumCulled !== undefined) object.frustumCulled = data.frustumCulled;
46704		if (data.renderOrder !== undefined) object.renderOrder = data.renderOrder;
46705		if (data.userData !== undefined) object.userData = data.userData;
46706		if (data.layers !== undefined) object.layers.mask = data.layers;
46707
46708		if (data.children !== undefined) {
46709
46710			const children = data.children;
46711
46712			for (let i = 0; i < children.length; i++) {
46713
46714				object.add(this.parseObject(children[i], geometries, materials, textures, animations));
46715
46716			}
46717
46718		}
46719
46720		if (data.animations !== undefined) {
46721
46722			const objectAnimations = data.animations;
46723
46724			for (let i = 0; i < objectAnimations.length; i++) {
46725
46726				const uuid = objectAnimations[i];
46727
46728				object.animations.push(animations[uuid]);
46729
46730			}
46731
46732		}
46733
46734		if (data.type === 'LOD') {
46735
46736			if (data.autoUpdate !== undefined) object.autoUpdate = data.autoUpdate;
46737
46738			const levels = data.levels;
46739
46740			for (let l = 0; l < levels.length; l++) {
46741
46742				const level = levels[l];
46743				const child = object.getObjectByProperty('uuid', level.object);
46744
46745				if (child !== undefined) {
46746
46747					object.addLevel(child, level.distance, level.hysteresis);
46748
46749				}
46750
46751			}
46752
46753		}
46754
46755		return object;
46756
46757	}
46758
46759	bindSkeletons(object, skeletons) {
46760
46761		if (Object.keys(skeletons).length === 0) return;
46762
46763		object.traverse(function (child) {
46764
46765			if (child.isSkinnedMesh === true && child.skeleton !== undefined) {
46766
46767				const skeleton = skeletons[child.skeleton];
46768
46769				if (skeleton === undefined) {
46770
46771					console.warn('THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton);
46772
46773				} else {
46774
46775					child.bind(skeleton, child.bindMatrix);
46776
46777				}
46778
46779			}
46780
46781		});
46782
46783	}
46784
46785}
46786
46787const TEXTURE_MAPPING = {
46788	UVMapping: UVMapping,
46789	CubeReflectionMapping: CubeReflectionMapping,
46790	CubeRefractionMapping: CubeRefractionMapping,
46791	EquirectangularReflectionMapping: EquirectangularReflectionMapping,
46792	EquirectangularRefractionMapping: EquirectangularRefractionMapping,
46793	CubeUVReflectionMapping: CubeUVReflectionMapping
46794};
46795
46796const TEXTURE_WRAPPING = {
46797	RepeatWrapping: RepeatWrapping,
46798	ClampToEdgeWrapping: ClampToEdgeWrapping,
46799	MirroredRepeatWrapping: MirroredRepeatWrapping
46800};
46801
46802const TEXTURE_FILTER = {
46803	NearestFilter: NearestFilter,
46804	NearestMipmapNearestFilter: NearestMipmapNearestFilter,
46805	NearestMipmapLinearFilter: NearestMipmapLinearFilter,
46806	LinearFilter: LinearFilter,
46807	LinearMipmapNearestFilter: LinearMipmapNearestFilter,
46808	LinearMipmapLinearFilter: LinearMipmapLinearFilter
46809};
46810
46811class ImageBitmapLoader extends Loader {
46812
46813	constructor(manager) {
46814
46815		super(manager);
46816
46817		this.isImageBitmapLoader = true;
46818
46819		if (typeof createImageBitmap === 'undefined') {
46820
46821			console.warn('THREE.ImageBitmapLoader: createImageBitmap() not supported.');
46822
46823		}
46824
46825		if (typeof fetch === 'undefined') {
46826
46827			console.warn('THREE.ImageBitmapLoader: fetch() not supported.');
46828
46829		}
46830
46831		this.options = { premultiplyAlpha: 'none' };
46832
46833	}
46834
46835	setOptions(options) {
46836
46837		this.options = options;
46838
46839		return this;
46840
46841	}
46842
46843	load(url, onLoad, onProgress, onError) {
46844
46845		if (url === undefined) url = '';
46846
46847		if (this.path !== undefined) url = this.path + url;
46848
46849		url = this.manager.resolveURL(url);
46850
46851		const scope = this;
46852
46853		const cached = Cache.get(url);
46854
46855		if (cached !== undefined) {
46856
46857			scope.manager.itemStart(url);
46858
46859			// If cached is a promise, wait for it to resolve
46860			if (cached.then) {
46861
46862				cached.then(imageBitmap => {
46863
46864					if (onLoad) onLoad(imageBitmap);
46865
46866					scope.manager.itemEnd(url);
46867
46868				}).catch(e => {
46869
46870					if (onError) onError(e);
46871
46872				});
46873				return;
46874
46875			}
46876
46877			// If cached is not a promise (i.e., it's already an imageBitmap)
46878			setTimeout(function () {
46879
46880				if (onLoad) onLoad(cached);
46881
46882				scope.manager.itemEnd(url);
46883
46884			}, 0);
46885
46886			return cached;
46887
46888		}
46889
46890		const fetchOptions = {};
46891		fetchOptions.credentials = (this.crossOrigin === 'anonymous') ? 'same-origin' : 'include';
46892		fetchOptions.headers = this.requestHeader;
46893
46894		const promise = fetch(url, fetchOptions).then(function (res) {
46895
46896			return res.blob();
46897
46898		}).then(function (blob) {
46899
46900			return createImageBitmap(blob, Object.assign(scope.options, { colorSpaceConversion: 'none' }));
46901
46902		}).then(function (imageBitmap) {
46903
46904			Cache.add(url, imageBitmap);
46905
46906			if (onLoad) onLoad(imageBitmap);
46907
46908			scope.manager.itemEnd(url);
46909
46910			return imageBitmap;
46911
46912		}).catch(function (e) {
46913
46914			if (onError) onError(e);
46915
46916			Cache.remove(url);
46917
46918			scope.manager.itemError(url);
46919			scope.manager.itemEnd(url);
46920
46921		});
46922
46923		Cache.add(url, promise);
46924		scope.manager.itemStart(url);
46925
46926	}
46927
46928}
46929
46930let _context;
46931
46932class AudioContext {
46933
46934	static getContext() {
46935
46936		if (_context === undefined) {
46937
46938			_context = new (window.AudioContext || window.webkitAudioContext)();
46939
46940		}
46941
46942		return _context;
46943
46944	}
46945
46946	static setContext(value) {
46947
46948		_context = value;
46949
46950	}
46951
46952}
46953
46954class AudioLoader extends Loader {
46955
46956	constructor(manager) {
46957
46958		super(manager);
46959
46960	}
46961
46962	load(url, onLoad, onProgress, onError) {
46963
46964		const scope = this;
46965
46966		const loader = new FileLoader(this.manager);
46967		loader.setResponseType('arraybuffer');
46968		loader.setPath(this.path);
46969		loader.setRequestHeader(this.requestHeader);
46970		loader.setWithCredentials(this.withCredentials);
46971		loader.load(url, function (buffer) {
46972
46973			try {
46974
46975				// Create a copy of the buffer. The `decodeAudioData` method
46976				// detaches the buffer when complete, preventing reuse.
46977				const bufferCopy = buffer.slice(0);
46978
46979				const context = AudioContext.getContext();
46980				context.decodeAudioData(bufferCopy, function (audioBuffer) {
46981
46982					onLoad(audioBuffer);
46983
46984				}).catch(handleError);
46985
46986			} catch (e) {
46987
46988				handleError(e);
46989
46990			}
46991
46992		}, onProgress, onError);
46993
46994		function handleError(e) {
46995
46996			if (onError) {
46997
46998				onError(e);
46999
47000			} else {
47001
47002				console.error(e);
47003
47004			}
47005
47006			scope.manager.itemError(url);
47007
47008		}
47009
47010	}
47011
47012}
47013
47014const _eyeRight = /*@__PURE__*/ new Matrix4();
47015const _eyeLeft = /*@__PURE__*/ new Matrix4();
47016const _projectionMatrix = /*@__PURE__*/ new Matrix4();
47017
47018class StereoCamera {
47019
47020	constructor() {
47021
47022		this.type = 'StereoCamera';
47023
47024		this.aspect = 1;
47025
47026		this.eyeSep = 0.064;
47027
47028		this.cameraL = new PerspectiveCamera();
47029		this.cameraL.layers.enable(1);
47030		this.cameraL.matrixAutoUpdate = false;
47031
47032		this.cameraR = new PerspectiveCamera();
47033		this.cameraR.layers.enable(2);
47034		this.cameraR.matrixAutoUpdate = false;
47035
47036		this._cache = {
47037			focus: null,
47038			fov: null,
47039			aspect: null,
47040			near: null,
47041			far: null,
47042			zoom: null,
47043			eyeSep: null
47044		};
47045
47046	}
47047
47048	update(camera) {
47049
47050		const cache = this._cache;
47051
47052		const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
47053			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
47054			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
47055
47056		if (needsUpdate) {
47057
47058			cache.focus = camera.focus;
47059			cache.fov = camera.fov;
47060			cache.aspect = camera.aspect * this.aspect;
47061			cache.near = camera.near;
47062			cache.far = camera.far;
47063			cache.zoom = camera.zoom;
47064			cache.eyeSep = this.eyeSep;
47065
47066			// Off-axis stereoscopic effect based on
47067			// http://paulbourke.net/stereographics/stereorender/
47068
47069			_projectionMatrix.copy(camera.projectionMatrix);
47070			const eyeSepHalf = cache.eyeSep / 2;
47071			const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
47072			const ymax = (cache.near * Math.tan(DEG2RAD * cache.fov * 0.5)) / cache.zoom;
47073			let xmin, xmax;
47074
47075			// translate xOffset
47076
47077			_eyeLeft.elements[12] = - eyeSepHalf;
47078			_eyeRight.elements[12] = eyeSepHalf;
47079
47080			// for left eye
47081
47082			xmin = - ymax * cache.aspect + eyeSepOnProjection;
47083			xmax = ymax * cache.aspect + eyeSepOnProjection;
47084
47085			_projectionMatrix.elements[0] = 2 * cache.near / (xmax - xmin);
47086			_projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin);
47087
47088			this.cameraL.projectionMatrix.copy(_projectionMatrix);
47089
47090			// for right eye
47091
47092			xmin = - ymax * cache.aspect - eyeSepOnProjection;
47093			xmax = ymax * cache.aspect - eyeSepOnProjection;
47094
47095			_projectionMatrix.elements[0] = 2 * cache.near / (xmax - xmin);
47096			_projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin);
47097
47098			this.cameraR.projectionMatrix.copy(_projectionMatrix);
47099
47100		}
47101
47102		this.cameraL.matrixWorld.copy(camera.matrixWorld).multiply(_eyeLeft);
47103		this.cameraR.matrixWorld.copy(camera.matrixWorld).multiply(_eyeRight);
47104
47105	}
47106
47107}
47108
47109class Clock {
47110
47111	constructor(autoStart = true) {
47112
47113		this.autoStart = autoStart;
47114
47115		this.startTime = 0;
47116		this.oldTime = 0;
47117		this.elapsedTime = 0;
47118
47119		this.running = false;
47120
47121	}
47122
47123	start() {
47124
vendor: 13,529 bytes, lines 47125-47914
47125		this.startTime = now();
47126
47127		this.oldTime = this.startTime;
47128		this.elapsedTime = 0;
47129		this.running = true;
47130
47131	}
47132
47133	stop() {
47134
47135		this.getElapsedTime();
47136		this.running = false;
47137		this.autoStart = false;
47138
47139	}
47140
47141	getElapsedTime() {
47142
47143		this.getDelta();
47144		return this.elapsedTime;
47145
47146	}
47147
47148	getDelta() {
47149
47150		let diff = 0;
47151
47152		if (this.autoStart && !this.running) {
47153
47154			this.start();
47155			return 0;
47156
47157		}
47158
47159		if (this.running) {
47160
47161			const newTime = now();
47162
47163			diff = (newTime - this.oldTime) / 1000;
47164			this.oldTime = newTime;
47165
47166			this.elapsedTime += diff;
47167
47168		}
47169
47170		return diff;
47171
47172	}
47173
47174}
47175
47176function now() {
47177
47178	return (typeof performance === 'undefined' ? Date : performance).now(); // see #10732
47179
47180}
47181
47182const _position$1 = /*@__PURE__*/ new Vector3();
47183const _quaternion$1 = /*@__PURE__*/ new Quaternion();
47184const _scale$1 = /*@__PURE__*/ new Vector3();
47185const _orientation$1 = /*@__PURE__*/ new Vector3();
47186
47187class AudioListener extends Object3D {
47188
47189	constructor() {
47190
47191		super();
47192
47193		this.type = 'AudioListener';
47194
47195		this.context = AudioContext.getContext();
47196
47197		this.gain = this.context.createGain();
47198		this.gain.connect(this.context.destination);
47199
47200		this.filter = null;
47201
47202		this.timeDelta = 0;
47203
47204		// private
47205
47206		this._clock = new Clock();
47207
47208	}
47209
47210	getInput() {
47211
47212		return this.gain;
47213
47214	}
47215
47216	removeFilter() {
47217
47218		if (this.filter !== null) {
47219
47220			this.gain.disconnect(this.filter);
47221			this.filter.disconnect(this.context.destination);
47222			this.gain.connect(this.context.destination);
47223			this.filter = null;
47224
47225		}
47226
47227		return this;
47228
47229	}
47230
47231	getFilter() {
47232
47233		return this.filter;
47234
47235	}
47236
47237	setFilter(value) {
47238
47239		if (this.filter !== null) {
47240
47241			this.gain.disconnect(this.filter);
47242			this.filter.disconnect(this.context.destination);
47243
47244		} else {
47245
47246			this.gain.disconnect(this.context.destination);
47247
47248		}
47249
47250		this.filter = value;
47251		this.gain.connect(this.filter);
47252		this.filter.connect(this.context.destination);
47253
47254		return this;
47255
47256	}
47257
47258	getMasterVolume() {
47259
47260		return this.gain.gain.value;
47261
47262	}
47263
47264	setMasterVolume(value) {
47265
47266		this.gain.gain.setTargetAtTime(value, this.context.currentTime, 0.01);
47267
47268		return this;
47269
47270	}
47271
47272	updateMatrixWorld(force) {
47273
47274		super.updateMatrixWorld(force);
47275
47276		const listener = this.context.listener;
47277		const up = this.up;
47278
47279		this.timeDelta = this._clock.getDelta();
47280
47281		this.matrixWorld.decompose(_position$1, _quaternion$1, _scale$1);
47282
47283		_orientation$1.set(0, 0, - 1).applyQuaternion(_quaternion$1);
47284
47285		if (listener.positionX) {
47286
47287			// code path for Chrome (see #14393)
47288
47289			const endTime = this.context.currentTime + this.timeDelta;
47290
47291			listener.positionX.linearRampToValueAtTime(_position$1.x, endTime);
47292			listener.positionY.linearRampToValueAtTime(_position$1.y, endTime);
47293			listener.positionZ.linearRampToValueAtTime(_position$1.z, endTime);
47294			listener.forwardX.linearRampToValueAtTime(_orientation$1.x, endTime);
47295			listener.forwardY.linearRampToValueAtTime(_orientation$1.y, endTime);
47296			listener.forwardZ.linearRampToValueAtTime(_orientation$1.z, endTime);
47297			listener.upX.linearRampToValueAtTime(up.x, endTime);
47298			listener.upY.linearRampToValueAtTime(up.y, endTime);
47299			listener.upZ.linearRampToValueAtTime(up.z, endTime);
47300
47301		} else {
47302
47303			listener.setPosition(_position$1.x, _position$1.y, _position$1.z);
47304			listener.setOrientation(_orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z);
47305
47306		}
47307
47308	}
47309
47310}
47311
47312class Audio extends Object3D {
47313
47314	constructor(listener) {
47315
47316		super();
47317
47318		this.type = 'Audio';
47319
47320		this.listener = listener;
47321		this.context = listener.context;
47322
47323		this.gain = this.context.createGain();
47324		this.gain.connect(listener.getInput());
47325
47326		this.autoplay = false;
47327
47328		this.buffer = null;
47329		this.detune = 0;
47330		this.loop = false;
47331		this.loopStart = 0;
47332		this.loopEnd = 0;
47333		this.offset = 0;
47334		this.duration = undefined;
47335		this.playbackRate = 1;
47336		this.isPlaying = false;
47337		this.hasPlaybackControl = true;
47338		this.source = null;
47339		this.sourceType = 'empty';
47340
47341		this._startedAt = 0;
47342		this._progress = 0;
47343		this._connected = false;
47344
47345		this.filters = [];
47346
47347	}
47348
47349	getOutput() {
47350
47351		return this.gain;
47352
47353	}
47354
47355	setNodeSource(audioNode) {
47356
47357		this.hasPlaybackControl = false;
47358		this.sourceType = 'audioNode';
47359		this.source = audioNode;
47360		this.connect();
47361
47362		return this;
47363
47364	}
47365
47366	setMediaElementSource(mediaElement) {
47367
47368		this.hasPlaybackControl = false;
47369		this.sourceType = 'mediaNode';
47370		this.source = this.context.createMediaElementSource(mediaElement);
47371		this.connect();
47372
47373		return this;
47374
47375	}
47376
47377	setMediaStreamSource(mediaStream) {
47378
47379		this.hasPlaybackControl = false;
47380		this.sourceType = 'mediaStreamNode';
47381		this.source = this.context.createMediaStreamSource(mediaStream);
47382		this.connect();
47383
47384		return this;
47385
47386	}
47387
47388	setBuffer(audioBuffer) {
47389
47390		this.buffer = audioBuffer;
47391		this.sourceType = 'buffer';
47392
47393		if (this.autoplay) this.play();
47394
47395		return this;
47396
47397	}
47398
47399	play(delay = 0) {
47400
47401		if (this.isPlaying === true) {
47402
47403			console.warn('THREE.Audio: Audio is already playing.');
47404			return;
47405
47406		}
47407
47408		if (this.hasPlaybackControl === false) {
47409
47410			console.warn('THREE.Audio: this Audio has no playback control.');
47411			return;
47412
47413		}
47414
47415		this._startedAt = this.context.currentTime + delay;
47416
47417		const source = this.context.createBufferSource();
47418		source.buffer = this.buffer;
47419		source.loop = this.loop;
47420		source.loopStart = this.loopStart;
47421		source.loopEnd = this.loopEnd;
47422		source.onended = this.onEnded.bind(this);
47423		source.start(this._startedAt, this._progress + this.offset, this.duration);
47424
47425		this.isPlaying = true;
47426
47427		this.source = source;
47428
47429		this.setDetune(this.detune);
47430		this.setPlaybackRate(this.playbackRate);
47431
47432		return this.connect();
47433
47434	}
47435
47436	pause() {
47437
47438		if (this.hasPlaybackControl === false) {
47439
47440			console.warn('THREE.Audio: this Audio has no playback control.');
47441			return;
47442
47443		}
47444
47445		if (this.isPlaying === true) {
47446
47447			// update current progress
47448
47449			this._progress += Math.max(this.context.currentTime - this._startedAt, 0) * this.playbackRate;
47450
47451			if (this.loop === true) {
47452
47453				// ensure _progress does not exceed duration with looped audios
47454
47455				this._progress = this._progress % (this.duration || this.buffer.duration);
47456
47457			}
47458
47459			this.source.stop();
47460			this.source.onended = null;
47461
47462			this.isPlaying = false;
47463
47464		}
47465
47466		return this;
47467
47468	}
47469
47470	stop() {
47471
47472		if (this.hasPlaybackControl === false) {
47473
47474			console.warn('THREE.Audio: this Audio has no playback control.');
47475			return;
47476
47477		}
47478
47479		this._progress = 0;
47480
47481		if (this.source !== null) {
47482
47483			this.source.stop();
47484			this.source.onended = null;
47485
47486		}
47487
47488		this.isPlaying = false;
47489
47490		return this;
47491
47492	}
47493
47494	connect() {
47495
47496		if (this.filters.length > 0) {
47497
47498			this.source.connect(this.filters[0]);
47499
47500			for (let i = 1, l = this.filters.length; i < l; i++) {
47501
47502				this.filters[i - 1].connect(this.filters[i]);
47503
47504			}
47505
47506			this.filters[this.filters.length - 1].connect(this.getOutput());
47507
47508		} else {
47509
47510			this.source.connect(this.getOutput());
47511
47512		}
47513
47514		this._connected = true;
47515
47516		return this;
47517
47518	}
47519
47520	disconnect() {
47521
47522		if (this._connected === false) {
47523
47524			return;
47525
47526		}
47527
47528		if (this.filters.length > 0) {
47529
47530			this.source.disconnect(this.filters[0]);
47531
47532			for (let i = 1, l = this.filters.length; i < l; i++) {
47533
47534				this.filters[i - 1].disconnect(this.filters[i]);
47535
47536			}
47537
47538			this.filters[this.filters.length - 1].disconnect(this.getOutput());
47539
47540		} else {
47541
47542			this.source.disconnect(this.getOutput());
47543
47544		}
47545
47546		this._connected = false;
47547
47548		return this;
47549
47550	}
47551
47552	getFilters() {
47553
47554		return this.filters;
47555
47556	}
47557
47558	setFilters(value) {
47559
47560		if (!value) value = [];
47561
47562		if (this._connected === true) {
47563
47564			this.disconnect();
47565			this.filters = value.slice();
47566			this.connect();
47567
47568		} else {
47569
47570			this.filters = value.slice();
47571
47572		}
47573
47574		return this;
47575
47576	}
47577
47578	setDetune(value) {
47579
47580		this.detune = value;
47581
47582		if (this.source.detune === undefined) return; // only set detune when available
47583
47584		if (this.isPlaying === true) {
47585
47586			this.source.detune.setTargetAtTime(this.detune, this.context.currentTime, 0.01);
47587
47588		}
47589
47590		return this;
47591
47592	}
47593
47594	getDetune() {
47595
47596		return this.detune;
47597
47598	}
47599
47600	getFilter() {
47601
47602		return this.getFilters()[0];
47603
47604	}
47605
47606	setFilter(filter) {
47607
47608		return this.setFilters(filter ? [filter] : []);
47609
47610	}
47611
47612	setPlaybackRate(value) {
47613
47614		if (this.hasPlaybackControl === false) {
47615
47616			console.warn('THREE.Audio: this Audio has no playback control.');
47617			return;
47618
47619		}
47620
47621		this.playbackRate = value;
47622
47623		if (this.isPlaying === true) {
47624
47625			this.source.playbackRate.setTargetAtTime(this.playbackRate, this.context.currentTime, 0.01);
47626
47627		}
47628
47629		return this;
47630
47631	}
47632
47633	getPlaybackRate() {
47634
47635		return this.playbackRate;
47636
47637	}
47638
47639	onEnded() {
47640
47641		this.isPlaying = false;
47642
47643	}
47644
47645	getLoop() {
47646
47647		if (this.hasPlaybackControl === false) {
47648
47649			console.warn('THREE.Audio: this Audio has no playback control.');
47650			return false;
47651
47652		}
47653
47654		return this.loop;
47655
47656	}
47657
47658	setLoop(value) {
47659
47660		if (this.hasPlaybackControl === false) {
47661
47662			console.warn('THREE.Audio: this Audio has no playback control.');
47663			return;
47664
47665		}
47666
47667		this.loop = value;
47668
47669		if (this.isPlaying === true) {
47670
47671			this.source.loop = this.loop;
47672
47673		}
47674
47675		return this;
47676
47677	}
47678
47679	setLoopStart(value) {
47680
47681		this.loopStart = value;
47682
47683		return this;
47684
47685	}
47686
47687	setLoopEnd(value) {
47688
47689		this.loopEnd = value;
47690
47691		return this;
47692
47693	}
47694
47695	getVolume() {
47696
47697		return this.gain.gain.value;
47698
47699	}
47700
47701	setVolume(value) {
47702
47703		this.gain.gain.setTargetAtTime(value, this.context.currentTime, 0.01);
47704
47705		return this;
47706
47707	}
47708
47709}
47710
47711const _position = /*@__PURE__*/ new Vector3();
47712const _quaternion = /*@__PURE__*/ new Quaternion();
47713const _scale = /*@__PURE__*/ new Vector3();
47714const _orientation = /*@__PURE__*/ new Vector3();
47715
47716class PositionalAudio extends Audio {
47717
47718	constructor(listener) {
47719
47720		super(listener);
47721
47722		this.panner = this.context.createPanner();
47723		this.panner.panningModel = 'HRTF';
47724		this.panner.connect(this.gain);
47725
47726	}
47727
47728	connect() {
47729
47730		super.connect();
47731
47732		this.panner.connect(this.gain);
47733
47734	}
47735
47736	disconnect() {
47737
47738		super.disconnect();
47739
47740		this.panner.disconnect(this.gain);
47741
47742	}
47743
47744	getOutput() {
47745
47746		return this.panner;
47747
47748	}
47749
47750	getRefDistance() {
47751
47752		return this.panner.refDistance;
47753
47754	}
47755
47756	setRefDistance(value) {
47757
47758		this.panner.refDistance = value;
47759
47760		return this;
47761
47762	}
47763
47764	getRolloffFactor() {
47765
47766		return this.panner.rolloffFactor;
47767
47768	}
47769
47770	setRolloffFactor(value) {
47771
47772		this.panner.rolloffFactor = value;
47773
47774		return this;
47775
47776	}
47777
47778	getDistanceModel() {
47779
47780		return this.panner.distanceModel;
47781
47782	}
47783
47784	setDistanceModel(value) {
47785
47786		this.panner.distanceModel = value;
47787
47788		return this;
47789
47790	}
47791
47792	getMaxDistance() {
47793
47794		return this.panner.maxDistance;
47795
47796	}
47797
47798	setMaxDistance(value) {
47799
47800		this.panner.maxDistance = value;
47801
47802		return this;
47803
47804	}
47805
47806	setDirectionalCone(coneInnerAngle, coneOuterAngle, coneOuterGain) {
47807
47808		this.panner.coneInnerAngle = coneInnerAngle;
47809		this.panner.coneOuterAngle = coneOuterAngle;
47810		this.panner.coneOuterGain = coneOuterGain;
47811
47812		return this;
47813
47814	}
47815
47816	updateMatrixWorld(force) {
47817
47818		super.updateMatrixWorld(force);
47819
47820		if (this.hasPlaybackControl === true && this.isPlaying === false) return;
47821
47822		this.matrixWorld.decompose(_position, _quaternion, _scale);
47823
47824		_orientation.set(0, 0, 1).applyQuaternion(_quaternion);
47825
47826		const panner = this.panner;
47827
47828		if (panner.positionX) {
47829
47830			// code path for Chrome and Firefox (see #14393)
47831
47832			const endTime = this.context.currentTime + this.listener.timeDelta;
47833
47834			panner.positionX.linearRampToValueAtTime(_position.x, endTime);
47835			panner.positionY.linearRampToValueAtTime(_position.y, endTime);
47836			panner.positionZ.linearRampToValueAtTime(_position.z, endTime);
47837			panner.orientationX.linearRampToValueAtTime(_orientation.x, endTime);
47838			panner.orientationY.linearRampToValueAtTime(_orientation.y, endTime);
47839			panner.orientationZ.linearRampToValueAtTime(_orientation.z, endTime);
47840
47841		} else {
47842
47843			panner.setPosition(_position.x, _position.y, _position.z);
47844			panner.setOrientation(_orientation.x, _orientation.y, _orientation.z);
47845
47846		}
47847
47848	}
47849
47850}
47851
47852class AudioAnalyser {
47853
47854	constructor(audio, fftSize = 2048) {
47855
47856		this.analyser = audio.context.createAnalyser();
47857		this.analyser.fftSize = fftSize;
47858
47859		this.data = new Uint8Array(this.analyser.frequencyBinCount);
47860
47861		audio.getOutput().connect(this.analyser);
47862
47863	}
47864
47865
47866	getFrequencyData() {
47867
47868		this.analyser.getByteFrequencyData(this.data);
47869
47870		return this.data;
47871
47872	}
47873
47874	getAverageFrequency() {
47875
47876		let value = 0;
47877		const data = this.getFrequencyData();
47878
47879		for (let i = 0; i < data.length; i++) {
47880
47881			value += data[i];
47882
47883		}
47884
47885		return value / data.length;
47886
47887	}
47888
47889}
47890
47891class PropertyMixer {
47892
47893	constructor(binding, typeName, valueSize) {
47894
47895		this.binding = binding;
47896		this.valueSize = valueSize;
47897
47898		let mixFunction,
47899			mixFunctionAdditive,
47900			setIdentity;
47901
47902		// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
47903		//
47904		// interpolators can use .buffer as their .result
47905		// the data then goes to 'incoming'
47906		//
47907		// 'accu0' and 'accu1' are used frame-interleaved for
47908		// the cumulative result and are compared to detect
47909		// changes
47910		//
47911		// 'orig' stores the original state of the property
47912		//
47913		// 'add' is used for additive cumulative results
47914		//
vendor: 14,096 bytes, lines 47915-48545
47915		// 'work' is optional and is only present for quaternion types. It is used
47916		// to store intermediate quaternion multiplication results
47917
47918		switch (typeName) {
47919
47920			case 'quaternion':
47921				mixFunction = this._slerp;
47922				mixFunctionAdditive = this._slerpAdditive;
47923				setIdentity = this._setAdditiveIdentityQuaternion;
47924
47925				this.buffer = new Float64Array(valueSize * 6);
47926				this._workIndex = 5;
47927				break;
47928
47929			case 'string':
47930			case 'bool':
47931				mixFunction = this._select;
47932
47933				// Use the regular mix function and for additive on these types,
47934				// additive is not relevant for non-numeric types
47935				mixFunctionAdditive = this._select;
47936
47937				setIdentity = this._setAdditiveIdentityOther;
47938
47939				this.buffer = new Array(valueSize * 5);
47940				break;
47941
47942			default:
47943				mixFunction = this._lerp;
47944				mixFunctionAdditive = this._lerpAdditive;
47945				setIdentity = this._setAdditiveIdentityNumeric;
47946
47947				this.buffer = new Float64Array(valueSize * 5);
47948
47949		}
47950
47951		this._mixBufferRegion = mixFunction;
47952		this._mixBufferRegionAdditive = mixFunctionAdditive;
47953		this._setIdentity = setIdentity;
47954		this._origIndex = 3;
47955		this._addIndex = 4;
47956
47957		this.cumulativeWeight = 0;
47958		this.cumulativeWeightAdditive = 0;
47959
47960		this.useCount = 0;
47961		this.referenceCount = 0;
47962
47963	}
47964
47965	// accumulate data in the 'incoming' region into 'accu<i>'
47966	accumulate(accuIndex, weight) {
47967
47968		// note: happily accumulating nothing when weight = 0, the caller knows
47969		// the weight and shouldn't have made the call in the first place
47970
47971		const buffer = this.buffer,
47972			stride = this.valueSize,
47973			offset = accuIndex * stride + stride;
47974
47975		let currentWeight = this.cumulativeWeight;
47976
47977		if (currentWeight === 0) {
47978
47979			// accuN := incoming * weight
47980
47981			for (let i = 0; i !== stride; ++i) {
47982
47983				buffer[offset + i] = buffer[i];
47984
47985			}
47986
47987			currentWeight = weight;
47988
47989		} else {
47990
47991			// accuN := accuN + incoming * weight
47992
47993			currentWeight += weight;
47994			const mix = weight / currentWeight;
47995			this._mixBufferRegion(buffer, offset, 0, mix, stride);
47996
47997		}
47998
47999		this.cumulativeWeight = currentWeight;
48000
48001	}
48002
48003	// accumulate data in the 'incoming' region into 'add'
48004	accumulateAdditive(weight) {
48005
48006		const buffer = this.buffer,
48007			stride = this.valueSize,
48008			offset = stride * this._addIndex;
48009
48010		if (this.cumulativeWeightAdditive === 0) {
48011
48012			// add = identity
48013
48014			this._setIdentity();
48015
48016		}
48017
48018		// add := add + incoming * weight
48019
48020		this._mixBufferRegionAdditive(buffer, offset, 0, weight, stride);
48021		this.cumulativeWeightAdditive += weight;
48022
48023	}
48024
48025	// apply the state of 'accu<i>' to the binding when accus differ
48026	apply(accuIndex) {
48027
48028		const stride = this.valueSize,
48029			buffer = this.buffer,
48030			offset = accuIndex * stride + stride,
48031
48032			weight = this.cumulativeWeight,
48033			weightAdditive = this.cumulativeWeightAdditive,
48034
48035			binding = this.binding;
48036
48037		this.cumulativeWeight = 0;
48038		this.cumulativeWeightAdditive = 0;
48039
48040		if (weight < 1) {
48041
48042			// accuN := accuN + original * ( 1 - cumulativeWeight )
48043
48044			const originalValueOffset = stride * this._origIndex;
48045
48046			this._mixBufferRegion(
48047				buffer, offset, originalValueOffset, 1 - weight, stride);
48048
48049		}
48050
48051		if (weightAdditive > 0) {
48052
48053			// accuN := accuN + additive accuN
48054
48055			this._mixBufferRegionAdditive(buffer, offset, this._addIndex * stride, 1, stride);
48056
48057		}
48058
48059		for (let i = stride, e = stride + stride; i !== e; ++i) {
48060
48061			if (buffer[i] !== buffer[i + stride]) {
48062
48063				// value has changed -> update scene graph
48064
48065				binding.setValue(buffer, offset);
48066				break;
48067
48068			}
48069
48070		}
48071
48072	}
48073
48074	// remember the state of the bound property and copy it to both accus
48075	saveOriginalState() {
48076
48077		const binding = this.binding;
48078
48079		const buffer = this.buffer,
48080			stride = this.valueSize,
48081
48082			originalValueOffset = stride * this._origIndex;
48083
48084		binding.getValue(buffer, originalValueOffset);
48085
48086		// accu[0..1] := orig -- initially detect changes against the original
48087		for (let i = stride, e = originalValueOffset; i !== e; ++i) {
48088
48089			buffer[i] = buffer[originalValueOffset + (i % stride)];
48090
48091		}
48092
48093		// Add to identity for additive
48094		this._setIdentity();
48095
48096		this.cumulativeWeight = 0;
48097		this.cumulativeWeightAdditive = 0;
48098
48099	}
48100
48101	// apply the state previously taken via 'saveOriginalState' to the binding
48102	restoreOriginalState() {
48103
48104		const originalValueOffset = this.valueSize * 3;
48105		this.binding.setValue(this.buffer, originalValueOffset);
48106
48107	}
48108
48109	_setAdditiveIdentityNumeric() {
48110
48111		const startIndex = this._addIndex * this.valueSize;
48112		const endIndex = startIndex + this.valueSize;
48113
48114		for (let i = startIndex; i < endIndex; i++) {
48115
48116			this.buffer[i] = 0;
48117
48118		}
48119
48120	}
48121
48122	_setAdditiveIdentityQuaternion() {
48123
48124		this._setAdditiveIdentityNumeric();
48125		this.buffer[this._addIndex * this.valueSize + 3] = 1;
48126
48127	}
48128
48129	_setAdditiveIdentityOther() {
48130
48131		const startIndex = this._origIndex * this.valueSize;
48132		const targetIndex = this._addIndex * this.valueSize;
48133
48134		for (let i = 0; i < this.valueSize; i++) {
48135
48136			this.buffer[targetIndex + i] = this.buffer[startIndex + i];
48137
48138		}
48139
48140	}
48141
48142
48143	// mix functions
48144
48145	_select(buffer, dstOffset, srcOffset, t, stride) {
48146
48147		if (t >= 0.5) {
48148
48149			for (let i = 0; i !== stride; ++i) {
48150
48151				buffer[dstOffset + i] = buffer[srcOffset + i];
48152
48153			}
48154
48155		}
48156
48157	}
48158
48159	_slerp(buffer, dstOffset, srcOffset, t) {
48160
48161		Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t);
48162
48163	}
48164
48165	_slerpAdditive(buffer, dstOffset, srcOffset, t, stride) {
48166
48167		const workOffset = this._workIndex * stride;
48168
48169		// Store result in intermediate buffer offset
48170		Quaternion.multiplyQuaternionsFlat(buffer, workOffset, buffer, dstOffset, buffer, srcOffset);
48171
48172		// Slerp to the intermediate result
48173		Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t);
48174
48175	}
48176
48177	_lerp(buffer, dstOffset, srcOffset, t, stride) {
48178
48179		const s = 1 - t;
48180
48181		for (let i = 0; i !== stride; ++i) {
48182
48183			const j = dstOffset + i;
48184
48185			buffer[j] = buffer[j] * s + buffer[srcOffset + i] * t;
48186
48187		}
48188
48189	}
48190
48191	_lerpAdditive(buffer, dstOffset, srcOffset, t, stride) {
48192
48193		for (let i = 0; i !== stride; ++i) {
48194
48195			const j = dstOffset + i;
48196
48197			buffer[j] = buffer[j] + buffer[srcOffset + i] * t;
48198
48199		}
48200
48201	}
48202
48203}
48204
48205// Characters [].:/ are reserved for track binding syntax.
48206const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
48207const _reservedRe = new RegExp('[' + _RESERVED_CHARS_RE + ']', 'g');
48208
48209// Attempts to allow node names from any language. ES5's `\w` regexp matches
48210// only latin characters, and the unicode \p{L} is not yet supported. So
48211// instead, we exclude reserved characters and match everything else.
48212const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
48213const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace('\\.', '') + ']';
48214
48215// Parent directories, delimited by '/' or ':'. Currently unused, but must
48216// be matched to parse the rest of the track name.
48217const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace('WC', _wordChar);
48218
48219// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
48220const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace('WCOD', _wordCharOrDot);
48221
48222// Object on target node, and accessor. May not contain reserved
48223// characters. Accessor may contain any character except closing bracket.
48224const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace('WC', _wordChar);
48225
48226// Property and accessor. May not contain reserved characters. Accessor may
48227// contain any non-bracket characters.
48228const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace('WC', _wordChar);
48229
48230const _trackRe = new RegExp(''
48231	+ '^'
48232	+ _directoryRe
48233	+ _nodeRe
48234	+ _objectRe
48235	+ _propertyRe
48236	+ '$'
48237);
48238
48239const _supportedObjectNames = ['material', 'materials', 'bones', 'map'];
48240
48241class Composite {
48242
48243	constructor(targetGroup, path, optionalParsedPath) {
48244
48245		const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName(path);
48246
48247		this._targetGroup = targetGroup;
48248		this._bindings = targetGroup.subscribe_(path, parsedPath);
48249
48250	}
48251
48252	getValue(array, offset) {
48253
48254		this.bind(); // bind all binding
48255
48256		const firstValidIndex = this._targetGroup.nCachedObjects_,
48257			binding = this._bindings[firstValidIndex];
48258
48259		// and only call .getValue on the first
48260		if (binding !== undefined) binding.getValue(array, offset);
48261
48262	}
48263
48264	setValue(array, offset) {
48265
48266		const bindings = this._bindings;
48267
48268		for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
48269
48270			bindings[i].setValue(array, offset);
48271
48272		}
48273
48274	}
48275
48276	bind() {
48277
48278		const bindings = this._bindings;
48279
48280		for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
48281
48282			bindings[i].bind();
48283
48284		}
48285
48286	}
48287
48288	unbind() {
48289
48290		const bindings = this._bindings;
48291
48292		for (let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++i) {
48293
48294			bindings[i].unbind();
48295
48296		}
48297
48298	}
48299
48300}
48301
48302// Note: This class uses a State pattern on a per-method basis:
48303// 'bind' sets 'this.getValue' / 'setValue' and shadows the
48304// prototype version of these methods with one that represents
48305// the bound state. When the property is not found, the methods
48306// become no-ops.
48307class PropertyBinding {
48308
48309	constructor(rootNode, path, parsedPath) {
48310
48311		this.path = path;
48312		this.parsedPath = parsedPath || PropertyBinding.parseTrackName(path);
48313
48314		this.node = PropertyBinding.findNode(rootNode, this.parsedPath.nodeName);
48315
48316		this.rootNode = rootNode;
48317
48318		// initial state of these methods that calls 'bind'
48319		this.getValue = this._getValue_unbound;
48320		this.setValue = this._setValue_unbound;
48321
48322	}
48323
48324
48325	static create(root, path, parsedPath) {
48326
48327		if (!(root && root.isAnimationObjectGroup)) {
48328
48329			return new PropertyBinding(root, path, parsedPath);
48330
48331		} else {
48332
48333			return new PropertyBinding.Composite(root, path, parsedPath);
48334
48335		}
48336
48337	}
48338
48339	/**
48340	 * Replaces spaces with underscores and removes unsupported characters from
48341	 * node names, to ensure compatibility with parseTrackName().
48342	 *
48343	 * @param {string} name Node name to be sanitized.
48344	 * @return {string}
48345	 */
48346	static sanitizeNodeName(name) {
48347
48348		return name.replace(/\s/g, '_').replace(_reservedRe, '');
48349
48350	}
48351
48352	static parseTrackName(trackName) {
48353
48354		const matches = _trackRe.exec(trackName);
48355
48356		if (matches === null) {
48357
48358			throw new Error('PropertyBinding: Cannot parse trackName: ' + trackName);
48359
48360		}
48361
48362		const results = {
48363			// directoryName: matches[ 1 ], // (tschw) currently unused
48364			nodeName: matches[2],
48365			objectName: matches[3],
48366			objectIndex: matches[4],
48367			propertyName: matches[5], // required
48368			propertyIndex: matches[6]
48369		};
48370
48371		const lastDot = results.nodeName && results.nodeName.lastIndexOf('.');
48372
48373		if (lastDot !== undefined && lastDot !== - 1) {
48374
48375			const objectName = results.nodeName.substring(lastDot + 1);
48376
48377			// Object names must be checked against an allowlist. Otherwise, there
48378			// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
48379			// 'bar' could be the objectName, or part of a nodeName (which can
48380			// include '.' characters).
48381			if (_supportedObjectNames.indexOf(objectName) !== - 1) {
48382
48383				results.nodeName = results.nodeName.substring(0, lastDot);
48384				results.objectName = objectName;
48385
48386			}
48387
48388		}
48389
48390		if (results.propertyName === null || results.propertyName.length === 0) {
48391
48392			throw new Error('PropertyBinding: can not parse propertyName from trackName: ' + trackName);
48393
48394		}
48395
48396		return results;
48397
48398	}
48399
48400	static findNode(root, nodeName) {
48401
48402		if (nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid) {
48403
48404			return root;
48405
48406		}
48407
48408		// search into skeleton bones.
48409		if (root.skeleton) {
48410
48411			const bone = root.skeleton.getBoneByName(nodeName);
48412
48413			if (bone !== undefined) {
48414
48415				return bone;
48416
48417			}
48418
48419		}
48420
48421		// search into node subtree.
48422		if (root.children) {
48423
48424			const searchNodeSubtree = function (children) {
48425
48426				for (let i = 0; i < children.length; i++) {
48427
48428					const childNode = children[i];
48429
48430					if (childNode.name === nodeName || childNode.uuid === nodeName) {
48431
48432						return childNode;
48433
48434					}
48435
48436					const result = searchNodeSubtree(childNode.children);
48437
48438					if (result) return result;
48439
48440				}
48441
48442				return null;
48443
48444			};
48445
48446			const subTreeNode = searchNodeSubtree(root.children);
48447
48448			if (subTreeNode) {
48449
48450				return subTreeNode;
48451
48452			}
48453
48454		}
48455
48456		return null;
48457
48458	}
48459
48460	// these are used to "bind" a nonexistent property
48461	_getValue_unavailable() { }
48462	_setValue_unavailable() { }
48463
48464	// Getters
48465
48466	_getValue_direct(buffer, offset) {
48467
48468		buffer[offset] = this.targetObject[this.propertyName];
48469
48470	}
48471
48472	_getValue_array(buffer, offset) {
48473
48474		const source = this.resolvedProperty;
48475
48476		for (let i = 0, n = source.length; i !== n; ++i) {
48477
48478			buffer[offset++] = source[i];
48479
48480		}
48481
48482	}
48483
48484	_getValue_arrayElement(buffer, offset) {
48485
48486		buffer[offset] = this.resolvedProperty[this.propertyIndex];
48487
48488	}
48489
48490	_getValue_toArray(buffer, offset) {
48491
48492		this.resolvedProperty.toArray(buffer, offset);
48493
48494	}
48495
48496	// Direct
48497
48498	_setValue_direct(buffer, offset) {
48499
48500		this.targetObject[this.propertyName] = buffer[offset];
48501
48502	}
48503
48504	_setValue_direct_setNeedsUpdate(buffer, offset) {
48505
48506		this.targetObject[this.propertyName] = buffer[offset];
48507		this.targetObject.needsUpdate = true;
48508
48509	}
48510
48511	_setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) {
48512
48513		this.targetObject[this.propertyName] = buffer[offset];
48514		this.targetObject.matrixWorldNeedsUpdate = true;
48515
48516	}
48517
48518	// EntireArray
48519
48520	_setValue_array(buffer, offset) {
48521
48522		const dest = this.resolvedProperty;
48523
48524		for (let i = 0, n = dest.length; i !== n; ++i) {
48525
48526			dest[i] = buffer[offset++];
48527
48528		}
48529
48530	}
48531
48532	_setValue_array_setNeedsUpdate(buffer, offset) {
48533
48534		const dest = this.resolvedProperty;
48535
48536		for (let i = 0, n = dest.length; i !== n; ++i) {
48537
48538			dest[i] = buffer[offset++];
48539
48540		}
48541
48542		this.targetObject.needsUpdate = true;
48543
48544	}
48545
vendor: 7,729 bytes, lines 48546-48877
48546	_setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) {
48547
48548		const dest = this.resolvedProperty;
48549
48550		for (let i = 0, n = dest.length; i !== n; ++i) {
48551
48552			dest[i] = buffer[offset++];
48553
48554		}
48555
48556		this.targetObject.matrixWorldNeedsUpdate = true;
48557
48558	}
48559
48560	// ArrayElement
48561
48562	_setValue_arrayElement(buffer, offset) {
48563
48564		this.resolvedProperty[this.propertyIndex] = buffer[offset];
48565
48566	}
48567
48568	_setValue_arrayElement_setNeedsUpdate(buffer, offset) {
48569
48570		this.resolvedProperty[this.propertyIndex] = buffer[offset];
48571		this.targetObject.needsUpdate = true;
48572
48573	}
48574
48575	_setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) {
48576
48577		this.resolvedProperty[this.propertyIndex] = buffer[offset];
48578		this.targetObject.matrixWorldNeedsUpdate = true;
48579
48580	}
48581
48582	// HasToFromArray
48583
48584	_setValue_fromArray(buffer, offset) {
48585
48586		this.resolvedProperty.fromArray(buffer, offset);
48587
48588	}
48589
48590	_setValue_fromArray_setNeedsUpdate(buffer, offset) {
48591
48592		this.resolvedProperty.fromArray(buffer, offset);
48593		this.targetObject.needsUpdate = true;
48594
48595	}
48596
48597	_setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) {
48598
48599		this.resolvedProperty.fromArray(buffer, offset);
48600		this.targetObject.matrixWorldNeedsUpdate = true;
48601
48602	}
48603
48604	_getValue_unbound(targetArray, offset) {
48605
48606		this.bind();
48607		this.getValue(targetArray, offset);
48608
48609	}
48610
48611	_setValue_unbound(sourceArray, offset) {
48612
48613		this.bind();
48614		this.setValue(sourceArray, offset);
48615
48616	}
48617
48618	// create getter / setter pair for a property in the scene graph
48619	bind() {
48620
48621		let targetObject = this.node;
48622		const parsedPath = this.parsedPath;
48623
48624		const objectName = parsedPath.objectName;
48625		const propertyName = parsedPath.propertyName;
48626		let propertyIndex = parsedPath.propertyIndex;
48627
48628		if (!targetObject) {
48629
48630			targetObject = PropertyBinding.findNode(this.rootNode, parsedPath.nodeName);
48631
48632			this.node = targetObject;
48633
48634		}
48635
48636		// set fail state so we can just 'return' on error
48637		this.getValue = this._getValue_unavailable;
48638		this.setValue = this._setValue_unavailable;
48639
48640		// ensure there is a value node
48641		if (!targetObject) {
48642
48643			console.warn('THREE.PropertyBinding: No target node found for track: ' + this.path + '.');
48644			return;
48645
48646		}
48647
48648		if (objectName) {
48649
48650			let objectIndex = parsedPath.objectIndex;
48651
48652			// special cases were we need to reach deeper into the hierarchy to get the face materials....
48653			switch (objectName) {
48654
48655				case 'materials':
48656
48657					if (!targetObject.material) {
48658
48659						console.error('THREE.PropertyBinding: Can not bind to material as node does not have a material.', this);
48660						return;
48661
48662					}
48663
48664					if (!targetObject.material.materials) {
48665
48666						console.error('THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this);
48667						return;
48668
48669					}
48670
48671					targetObject = targetObject.material.materials;
48672
48673					break;
48674
48675				case 'bones':
48676
48677					if (!targetObject.skeleton) {
48678
48679						console.error('THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this);
48680						return;
48681
48682					}
48683
48684					// potential future optimization: skip this if propertyIndex is already an integer
48685					// and convert the integer string to a true integer.
48686
48687					targetObject = targetObject.skeleton.bones;
48688
48689					// support resolving morphTarget names into indices.
48690					for (let i = 0; i < targetObject.length; i++) {
48691
48692						if (targetObject[i].name === objectIndex) {
48693
48694							objectIndex = i;
48695							break;
48696
48697						}
48698
48699					}
48700
48701					break;
48702
48703				case 'map':
48704
48705					if ('map' in targetObject) {
48706
48707						targetObject = targetObject.map;
48708						break;
48709
48710					}
48711
48712					if (!targetObject.material) {
48713
48714						console.error('THREE.PropertyBinding: Can not bind to material as node does not have a material.', this);
48715						return;
48716
48717					}
48718
48719					if (!targetObject.material.map) {
48720
48721						console.error('THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this);
48722						return;
48723
48724					}
48725
48726					targetObject = targetObject.material.map;
48727					break;
48728
48729				default:
48730
48731					if (targetObject[objectName] === undefined) {
48732
48733						console.error('THREE.PropertyBinding: Can not bind to objectName of node undefined.', this);
48734						return;
48735
48736					}
48737
48738					targetObject = targetObject[objectName];
48739
48740			}
48741
48742
48743			if (objectIndex !== undefined) {
48744
48745				if (targetObject[objectIndex] === undefined) {
48746
48747					console.error('THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject);
48748					return;
48749
48750				}
48751
48752				targetObject = targetObject[objectIndex];
48753
48754			}
48755
48756		}
48757
48758		// resolve property
48759		const nodeProperty = targetObject[propertyName];
48760
48761		if (nodeProperty === undefined) {
48762
48763			const nodeName = parsedPath.nodeName;
48764
48765			console.error('THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
48766				'.' + propertyName + ' but it wasn\'t found.', targetObject);
48767			return;
48768
48769		}
48770
48771		// determine versioning scheme
48772		let versioning = this.Versioning.None;
48773
48774		this.targetObject = targetObject;
48775
48776		if (targetObject.needsUpdate !== undefined) { // material
48777
48778			versioning = this.Versioning.NeedsUpdate;
48779
48780		} else if (targetObject.matrixWorldNeedsUpdate !== undefined) { // node transform
48781
48782			versioning = this.Versioning.MatrixWorldNeedsUpdate;
48783
48784		}
48785
48786		// determine how the property gets bound
48787		let bindingType = this.BindingType.Direct;
48788
48789		if (propertyIndex !== undefined) {
48790
48791			// access a sub element of the property array (only primitives are supported right now)
48792
48793			if (propertyName === 'morphTargetInfluences') {
48794
48795				// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
48796
48797				// support resolving morphTarget names into indices.
48798				if (!targetObject.geometry) {
48799
48800					console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this);
48801					return;
48802
48803				}
48804
48805				if (!targetObject.geometry.morphAttributes) {
48806
48807					console.error('THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this);
48808					return;
48809
48810				}
48811
48812				if (targetObject.morphTargetDictionary[propertyIndex] !== undefined) {
48813
48814					propertyIndex = targetObject.morphTargetDictionary[propertyIndex];
48815
48816				}
48817
48818			}
48819
48820			bindingType = this.BindingType.ArrayElement;
48821
48822			this.resolvedProperty = nodeProperty;
48823			this.propertyIndex = propertyIndex;
48824
48825		} else if (nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined) {
48826
48827			// must use copy for Object3D.Euler/Quaternion
48828
48829			bindingType = this.BindingType.HasFromToArray;
48830
48831			this.resolvedProperty = nodeProperty;
48832
48833		} else if (Array.isArray(nodeProperty)) {
48834
48835			bindingType = this.BindingType.EntireArray;
48836
48837			this.resolvedProperty = nodeProperty;
48838
48839		} else {
48840
48841			this.propertyName = propertyName;
48842
48843		}
48844
48845		// select getter / setter
48846		this.getValue = this.GetterByBindingType[bindingType];
48847		this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning];
48848
48849	}
48850
48851	unbind() {
48852
48853		this.node = null;
48854
48855		// back to the prototype version of getValue / setValue
48856		// note: avoiding to mutate the shape of 'this' via 'delete'
48857		this.getValue = this._getValue_unbound;
48858		this.setValue = this._setValue_unbound;
48859
48860	}
48861
48862}
48863
48864PropertyBinding.Composite = Composite;
48865
48866PropertyBinding.prototype.BindingType = {
48867	Direct: 0,
48868	EntireArray: 1,
48869	ArrayElement: 2,
48870	HasFromToArray: 3
48871};
48872
48873PropertyBinding.prototype.Versioning = {
48874	None: 0,
48875	NeedsUpdate: 1,
48876	MatrixWorldNeedsUpdate: 2
48877};
vendor: 4,388 bytes, lines 48878-49058
48878
48879PropertyBinding.prototype.GetterByBindingType = [
48880
48881	PropertyBinding.prototype._getValue_direct,
48882	PropertyBinding.prototype._getValue_array,
48883	PropertyBinding.prototype._getValue_arrayElement,
48884	PropertyBinding.prototype._getValue_toArray,
48885
48886];
48887
48888PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
48889
48890	[
48891		// Direct
48892		PropertyBinding.prototype._setValue_direct,
48893		PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
48894		PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
48895
48896	], [
48897
48898		// EntireArray
48899
48900		PropertyBinding.prototype._setValue_array,
48901		PropertyBinding.prototype._setValue_array_setNeedsUpdate,
48902		PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
48903
48904	], [
48905
48906		// ArrayElement
48907		PropertyBinding.prototype._setValue_arrayElement,
48908		PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
48909		PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
48910
48911	], [
48912
48913		// HasToFromArray
48914		PropertyBinding.prototype._setValue_fromArray,
48915		PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
48916		PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
48917
48918	]
48919
48920];
48921
48922/**
48923 *
48924 * A group of objects that receives a shared animation state.
48925 *
48926 * Usage:
48927 *
48928 *  - Add objects you would otherwise pass as 'root' to the
48929 *    constructor or the .clipAction method of AnimationMixer.
48930 *
48931 *  - Instead pass this object as 'root'.
48932 *
48933 *  - You can also add and remove objects later when the mixer
48934 *    is running.
48935 *
48936 * Note:
48937 *
48938 *    Objects of this class appear as one object to the mixer,
48939 *    so cache control of the individual objects must be done
48940 *    on the group.
48941 *
48942 * Limitation:
48943 *
48944 *  - The animated properties must be compatible among the
48945 *    all objects in the group.
48946 *
48947 *  - A single property can either be controlled through a
48948 *    target group or directly, but not both.
48949 */
48950
48951class AnimationObjectGroup {
48952
48953	constructor() {
48954
48955		this.isAnimationObjectGroup = true;
48956
48957		this.uuid = generateUUID();
48958
48959		// cached objects followed by the active ones
48960		this._objects = Array.prototype.slice.call(arguments);
48961
48962		this.nCachedObjects_ = 0; // threshold
48963		// note: read by PropertyBinding.Composite
48964
48965		const indices = {};
48966		this._indicesByUUID = indices; // for bookkeeping
48967
48968		for (let i = 0, n = arguments.length; i !== n; ++i) {
48969
48970			indices[arguments[i].uuid] = i;
48971
48972		}
48973
48974		this._paths = []; // inside: string
48975		this._parsedPaths = []; // inside: { we don't care, here }
48976		this._bindings = []; // inside: Array< PropertyBinding >
48977		this._bindingsIndicesByPath = {}; // inside: indices in these arrays
48978
48979		const scope = this;
48980
48981		this.stats = {
48982
48983			objects: {
48984				get total() {
48985
48986					return scope._objects.length;
48987
48988				},
48989				get inUse() {
48990
48991					return this.total - scope.nCachedObjects_;
48992
48993				}
48994			},
48995			get bindingsPerObject() {
48996
48997				return scope._bindings.length;
48998
48999			}
49000
49001		};
49002
49003	}
49004
49005	add() {
49006
49007		const objects = this._objects,
49008			indicesByUUID = this._indicesByUUID,
49009			paths = this._paths,
49010			parsedPaths = this._parsedPaths,
49011			bindings = this._bindings,
49012			nBindings = bindings.length;
49013
49014		let knownObject = undefined,
49015			nObjects = objects.length,
49016			nCachedObjects = this.nCachedObjects_;
49017
49018		for (let i = 0, n = arguments.length; i !== n; ++i) {
49019
49020			const object = arguments[i],
49021				uuid = object.uuid;
49022			let index = indicesByUUID[uuid];
49023
49024			if (index === undefined) {
49025
49026				// unknown object -> add it to the ACTIVE region
49027
49028				index = nObjects++;
49029				indicesByUUID[uuid] = index;
49030				objects.push(object);
49031
49032				// accounting is done, now do the same for all bindings
49033
49034				for (let j = 0, m = nBindings; j !== m; ++j) {
49035
49036					bindings[j].push(new PropertyBinding(object, paths[j], parsedPaths[j]));
49037
49038				}
49039
49040			} else if (index < nCachedObjects) {
49041
49042				knownObject = objects[index];
49043
49044				// move existing object to the ACTIVE region
49045
49046				const firstActiveIndex = --nCachedObjects,
49047					lastCachedObject = objects[firstActiveIndex];
49048
49049				indicesByUUID[lastCachedObject.uuid] = index;
49050				objects[index] = lastCachedObject;
49051
49052				indicesByUUID[uuid] = firstActiveIndex;
49053				objects[firstActiveIndex] = object;
49054
49055				// accounting is done, now do the same for all bindings
49056
49057				for (let j = 0, m = nBindings; j !== m; ++j) {
49058
vendor: 4,615 bytes, lines 49059-49241
49059					const bindingsForPath = bindings[j],
49060						lastCached = bindingsForPath[firstActiveIndex];
49061
49062					let binding = bindingsForPath[index];
49063
49064					bindingsForPath[index] = lastCached;
49065
49066					if (binding === undefined) {
49067
49068						// since we do not bother to create new bindings
49069						// for objects that are cached, the binding may
49070						// or may not exist
49071
49072						binding = new PropertyBinding(object, paths[j], parsedPaths[j]);
49073
49074					}
49075
49076					bindingsForPath[firstActiveIndex] = binding;
49077
49078				}
49079
49080			} else if (objects[index] !== knownObject) {
49081
49082				console.error('THREE.AnimationObjectGroup: Different objects with the same UUID ' +
49083					'detected. Clean the caches or recreate your infrastructure when reloading scenes.');
49084
49085			} // else the object is already where we want it to be
49086
49087		} // for arguments
49088
49089		this.nCachedObjects_ = nCachedObjects;
49090
49091	}
49092
49093	remove() {
49094
49095		const objects = this._objects,
49096			indicesByUUID = this._indicesByUUID,
49097			bindings = this._bindings,
49098			nBindings = bindings.length;
49099
49100		let nCachedObjects = this.nCachedObjects_;
49101
49102		for (let i = 0, n = arguments.length; i !== n; ++i) {
49103
49104			const object = arguments[i],
49105				uuid = object.uuid,
49106				index = indicesByUUID[uuid];
49107
49108			if (index !== undefined && index >= nCachedObjects) {
49109
49110				// move existing object into the CACHED region
49111
49112				const lastCachedIndex = nCachedObjects++,
49113					firstActiveObject = objects[lastCachedIndex];
49114
49115				indicesByUUID[firstActiveObject.uuid] = index;
49116				objects[index] = firstActiveObject;
49117
49118				indicesByUUID[uuid] = lastCachedIndex;
49119				objects[lastCachedIndex] = object;
49120
49121				// accounting is done, now do the same for all bindings
49122
49123				for (let j = 0, m = nBindings; j !== m; ++j) {
49124
49125					const bindingsForPath = bindings[j],
49126						firstActive = bindingsForPath[lastCachedIndex],
49127						binding = bindingsForPath[index];
49128
49129					bindingsForPath[index] = firstActive;
49130					bindingsForPath[lastCachedIndex] = binding;
49131
49132				}
49133
49134			}
49135
49136		} // for arguments
49137
49138		this.nCachedObjects_ = nCachedObjects;
49139
49140	}
49141
49142	// remove & forget
49143	uncache() {
49144
49145		const objects = this._objects,
49146			indicesByUUID = this._indicesByUUID,
49147			bindings = this._bindings,
49148			nBindings = bindings.length;
49149
49150		let nCachedObjects = this.nCachedObjects_,
49151			nObjects = objects.length;
49152
49153		for (let i = 0, n = arguments.length; i !== n; ++i) {
49154
49155			const object = arguments[i],
49156				uuid = object.uuid,
49157				index = indicesByUUID[uuid];
49158
49159			if (index !== undefined) {
49160
49161				delete indicesByUUID[uuid];
49162
49163				if (index < nCachedObjects) {
49164
49165					// object is cached, shrink the CACHED region
49166
49167					const firstActiveIndex = --nCachedObjects,
49168						lastCachedObject = objects[firstActiveIndex],
49169						lastIndex = --nObjects,
49170						lastObject = objects[lastIndex];
49171
49172					// last cached object takes this object's place
49173					indicesByUUID[lastCachedObject.uuid] = index;
49174					objects[index] = lastCachedObject;
49175
49176					// last object goes to the activated slot and pop
49177					indicesByUUID[lastObject.uuid] = firstActiveIndex;
49178					objects[firstActiveIndex] = lastObject;
49179					objects.pop();
49180
49181					// accounting is done, now do the same for all bindings
49182
49183					for (let j = 0, m = nBindings; j !== m; ++j) {
49184
49185						const bindingsForPath = bindings[j],
49186							lastCached = bindingsForPath[firstActiveIndex],
49187							last = bindingsForPath[lastIndex];
49188
49189						bindingsForPath[index] = lastCached;
49190						bindingsForPath[firstActiveIndex] = last;
49191						bindingsForPath.pop();
49192
49193					}
49194
49195				} else {
49196
49197					// object is active, just swap with the last and pop
49198
49199					const lastIndex = --nObjects,
49200						lastObject = objects[lastIndex];
49201
49202					if (lastIndex > 0) {
49203
49204						indicesByUUID[lastObject.uuid] = index;
49205
49206					}
49207
49208					objects[index] = lastObject;
49209					objects.pop();
49210
49211					// accounting is done, now do the same for all bindings
49212
49213					for (let j = 0, m = nBindings; j !== m; ++j) {
49214
49215						const bindingsForPath = bindings[j];
49216
49217						bindingsForPath[index] = bindingsForPath[lastIndex];
49218						bindingsForPath.pop();
49219
49220					}
49221
49222				} // cached or active
49223
49224			} // if object is known
49225
49226		} // for arguments
49227
49228		this.nCachedObjects_ = nCachedObjects;
49229
49230	}
49231
49232	// Internal interface used by befriended PropertyBinding.Composite:
49233
49234	subscribe_(path, parsedPath) {
49235
49236		// returns an array of bindings for the given path that is changed
49237		// according to the contained objects in the group
49238
49239		const indicesByPath = this._bindingsIndicesByPath;
49240		let index = indicesByPath[path];
49241		const bindings = this._bindings;
vendor: 8,095 bytes, lines 49242-49643
49242
49243		if (index !== undefined) return bindings[index];
49244
49245		const paths = this._paths,
49246			parsedPaths = this._parsedPaths,
49247			objects = this._objects,
49248			nObjects = objects.length,
49249			nCachedObjects = this.nCachedObjects_,
49250			bindingsForPath = new Array(nObjects);
49251
49252		index = bindings.length;
49253
49254		indicesByPath[path] = index;
49255
49256		paths.push(path);
49257		parsedPaths.push(parsedPath);
49258		bindings.push(bindingsForPath);
49259
49260		for (let i = nCachedObjects, n = objects.length; i !== n; ++i) {
49261
49262			const object = objects[i];
49263			bindingsForPath[i] = new PropertyBinding(object, path, parsedPath);
49264
49265		}
49266
49267		return bindingsForPath;
49268
49269	}
49270
49271	unsubscribe_(path) {
49272
49273		// tells the group to forget about a property path and no longer
49274		// update the array previously obtained with 'subscribe_'
49275
49276		const indicesByPath = this._bindingsIndicesByPath,
49277			index = indicesByPath[path];
49278
49279		if (index !== undefined) {
49280
49281			const paths = this._paths,
49282				parsedPaths = this._parsedPaths,
49283				bindings = this._bindings,
49284				lastBindingsIndex = bindings.length - 1,
49285				lastBindings = bindings[lastBindingsIndex],
49286				lastBindingsPath = path[lastBindingsIndex];
49287
49288			indicesByPath[lastBindingsPath] = index;
49289
49290			bindings[index] = lastBindings;
49291			bindings.pop();
49292
49293			parsedPaths[index] = parsedPaths[lastBindingsIndex];
49294			parsedPaths.pop();
49295
49296			paths[index] = paths[lastBindingsIndex];
49297			paths.pop();
49298
49299		}
49300
49301	}
49302
49303}
49304
49305class AnimationAction {
49306
49307	constructor(mixer, clip, localRoot = null, blendMode = clip.blendMode) {
49308
49309		this._mixer = mixer;
49310		this._clip = clip;
49311		this._localRoot = localRoot;
49312		this.blendMode = blendMode;
49313
49314		const tracks = clip.tracks,
49315			nTracks = tracks.length,
49316			interpolants = new Array(nTracks);
49317
49318		const interpolantSettings = {
49319			endingStart: ZeroCurvatureEnding,
49320			endingEnd: ZeroCurvatureEnding
49321		};
49322
49323		for (let i = 0; i !== nTracks; ++i) {
49324
49325			const interpolant = tracks[i].createInterpolant(null);
49326			interpolants[i] = interpolant;
49327			interpolant.settings = interpolantSettings;
49328
49329		}
49330
49331		this._interpolantSettings = interpolantSettings;
49332
49333		this._interpolants = interpolants; // bound by the mixer
49334
49335		// inside: PropertyMixer (managed by the mixer)
49336		this._propertyBindings = new Array(nTracks);
49337
49338		this._cacheIndex = null; // for the memory manager
49339		this._byClipCacheIndex = null; // for the memory manager
49340
49341		this._timeScaleInterpolant = null;
49342		this._weightInterpolant = null;
49343
49344		this.loop = LoopRepeat;
49345		this._loopCount = - 1;
49346
49347		// global mixer time when the action is to be started
49348		// it's set back to 'null' upon start of the action
49349		this._startTime = null;
49350
49351		// scaled local time of the action
49352		// gets clamped or wrapped to 0..clip.duration according to loop
49353		this.time = 0;
49354
49355		this.timeScale = 1;
49356		this._effectiveTimeScale = 1;
49357
49358		this.weight = 1;
49359		this._effectiveWeight = 1;
49360
49361		this.repetitions = Infinity; // no. of repetitions when looping
49362
49363		this.paused = false; // true -> zero effective time scale
49364		this.enabled = true; // false -> zero effective weight
49365
49366		this.clampWhenFinished = false;// keep feeding the last frame?
49367
49368		this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
49369		this.zeroSlopeAtEnd = true;// clips for start, loop and end
49370
49371	}
49372
49373	// State & Scheduling
49374
49375	play() {
49376
49377		this._mixer._activateAction(this);
49378
49379		return this;
49380
49381	}
49382
49383	stop() {
49384
49385		this._mixer._deactivateAction(this);
49386
49387		return this.reset();
49388
49389	}
49390
49391	reset() {
49392
49393		this.paused = false;
49394		this.enabled = true;
49395
49396		this.time = 0; // restart clip
49397		this._loopCount = - 1;// forget previous loops
49398		this._startTime = null;// forget scheduling
49399
49400		return this.stopFading().stopWarping();
49401
49402	}
49403
49404	isRunning() {
49405
49406		return this.enabled && !this.paused && this.timeScale !== 0 &&
49407			this._startTime === null && this._mixer._isActiveAction(this);
49408
49409	}
49410
49411	// return true when play has been called
49412	isScheduled() {
49413
49414		return this._mixer._isActiveAction(this);
49415
49416	}
49417
49418	startAt(time) {
49419
49420		this._startTime = time;
49421
49422		return this;
49423
49424	}
49425
49426	setLoop(mode, repetitions) {
49427
49428		this.loop = mode;
49429		this.repetitions = repetitions;
49430
49431		return this;
49432
49433	}
49434
49435	// Weight
49436
49437	// set the weight stopping any scheduled fading
49438	// although .enabled = false yields an effective weight of zero, this
49439	// method does *not* change .enabled, because it would be confusing
49440	setEffectiveWeight(weight) {
49441
49442		this.weight = weight;
49443
49444		// note: same logic as when updated at runtime
49445		this._effectiveWeight = this.enabled ? weight : 0;
49446
49447		return this.stopFading();
49448
49449	}
49450
49451	// return the weight considering fading and .enabled
49452	getEffectiveWeight() {
49453
49454		return this._effectiveWeight;
49455
49456	}
49457
49458	fadeIn(duration) {
49459
49460		return this._scheduleFading(duration, 0, 1);
49461
49462	}
49463
49464	fadeOut(duration) {
49465
49466		return this._scheduleFading(duration, 1, 0);
49467
49468	}
49469
49470	crossFadeFrom(fadeOutAction, duration, warp) {
49471
49472		fadeOutAction.fadeOut(duration);
49473		this.fadeIn(duration);
49474
49475		if (warp) {
49476
49477			const fadeInDuration = this._clip.duration,
49478				fadeOutDuration = fadeOutAction._clip.duration,
49479
49480				startEndRatio = fadeOutDuration / fadeInDuration,
49481				endStartRatio = fadeInDuration / fadeOutDuration;
49482
49483			fadeOutAction.warp(1.0, startEndRatio, duration);
49484			this.warp(endStartRatio, 1.0, duration);
49485
49486		}
49487
49488		return this;
49489
49490	}
49491
49492	crossFadeTo(fadeInAction, duration, warp) {
49493
49494		return fadeInAction.crossFadeFrom(this, duration, warp);
49495
49496	}
49497
49498	stopFading() {
49499
49500		const weightInterpolant = this._weightInterpolant;
49501
49502		if (weightInterpolant !== null) {
49503
49504			this._weightInterpolant = null;
49505			this._mixer._takeBackControlInterpolant(weightInterpolant);
49506
49507		}
49508
49509		return this;
49510
49511	}
49512
49513	// Time Scale Control
49514
49515	// set the time scale stopping any scheduled warping
49516	// although .paused = true yields an effective time scale of zero, this
49517	// method does *not* change .paused, because it would be confusing
49518	setEffectiveTimeScale(timeScale) {
49519
49520		this.timeScale = timeScale;
49521		this._effectiveTimeScale = this.paused ? 0 : timeScale;
49522
49523		return this.stopWarping();
49524
49525	}
49526
49527	// return the time scale considering warping and .paused
49528	getEffectiveTimeScale() {
49529
49530		return this._effectiveTimeScale;
49531
49532	}
49533
49534	setDuration(duration) {
49535
49536		this.timeScale = this._clip.duration / duration;
49537
49538		return this.stopWarping();
49539
49540	}
49541
49542	syncWith(action) {
49543
49544		this.time = action.time;
49545		this.timeScale = action.timeScale;
49546
49547		return this.stopWarping();
49548
49549	}
49550
49551	halt(duration) {
49552
49553		return this.warp(this._effectiveTimeScale, 0, duration);
49554
49555	}
49556
49557	warp(startTimeScale, endTimeScale, duration) {
49558
49559		const mixer = this._mixer,
49560			now = mixer.time,
49561			timeScale = this.timeScale;
49562
49563		let interpolant = this._timeScaleInterpolant;
49564
49565		if (interpolant === null) {
49566
49567			interpolant = mixer._lendControlInterpolant();
49568			this._timeScaleInterpolant = interpolant;
49569
49570		}
49571
49572		const times = interpolant.parameterPositions,
49573			values = interpolant.sampleValues;
49574
49575		times[0] = now;
49576		times[1] = now + duration;
49577
49578		values[0] = startTimeScale / timeScale;
49579		values[1] = endTimeScale / timeScale;
49580
49581		return this;
49582
49583	}
49584
49585	stopWarping() {
49586
49587		const timeScaleInterpolant = this._timeScaleInterpolant;
49588
49589		if (timeScaleInterpolant !== null) {
49590
49591			this._timeScaleInterpolant = null;
49592			this._mixer._takeBackControlInterpolant(timeScaleInterpolant);
49593
49594		}
49595
49596		return this;
49597
49598	}
49599
49600	// Object Accessors
49601
49602	getMixer() {
49603
49604		return this._mixer;
49605
49606	}
49607
49608	getClip() {
49609
49610		return this._clip;
49611
49612	}
49613
49614	getRoot() {
49615
49616		return this._localRoot || this._mixer._root;
49617
49618	}
49619
49620	// Interna
49621
49622	_update(time, deltaTime, timeDirection, accuIndex) {
49623
49624		// called by the mixer
49625
49626		if (!this.enabled) {
49627
49628			// call ._updateWeight() to update ._effectiveWeight
49629
49630			this._updateWeight(time);
49631			return;
49632
49633		}
49634
49635		const startTime = this._startTime;
49636
49637		if (startTime !== null) {
49638
49639			// check for scheduled start of action
49640
49641			const timeRunning = (time - startTime) * timeDirection;
49642			if (timeRunning < 0 || timeDirection === 0) {
49643
vendor: 8,546 bytes, lines 49644-50107
49644				deltaTime = 0;
49645
49646			} else {
49647
49648
49649				this._startTime = null; // unschedule
49650				deltaTime = timeDirection * timeRunning;
49651
49652			}
49653
49654		}
49655
49656		// apply time scale and advance time
49657
49658		deltaTime *= this._updateTimeScale(time);
49659		const clipTime = this._updateTime(deltaTime);
49660
49661		// note: _updateTime may disable the action resulting in
49662		// an effective weight of 0
49663
49664		const weight = this._updateWeight(time);
49665
49666		if (weight > 0) {
49667
49668			const interpolants = this._interpolants;
49669			const propertyMixers = this._propertyBindings;
49670
49671			switch (this.blendMode) {
49672
49673				case AdditiveAnimationBlendMode:
49674
49675					for (let j = 0, m = interpolants.length; j !== m; ++j) {
49676
49677						interpolants[j].evaluate(clipTime);
49678						propertyMixers[j].accumulateAdditive(weight);
49679
49680					}
49681
49682					break;
49683
49684				case NormalAnimationBlendMode:
49685				default:
49686
49687					for (let j = 0, m = interpolants.length; j !== m; ++j) {
49688
49689						interpolants[j].evaluate(clipTime);
49690						propertyMixers[j].accumulate(accuIndex, weight);
49691
49692					}
49693
49694			}
49695
49696		}
49697
49698	}
49699
49700	_updateWeight(time) {
49701
49702		let weight = 0;
49703
49704		if (this.enabled) {
49705
49706			weight = this.weight;
49707			const interpolant = this._weightInterpolant;
49708
49709			if (interpolant !== null) {
49710
49711				const interpolantValue = interpolant.evaluate(time)[0];
49712
49713				weight *= interpolantValue;
49714
49715				if (time > interpolant.parameterPositions[1]) {
49716
49717					this.stopFading();
49718
49719					if (interpolantValue === 0) {
49720
49721						// faded out, disable
49722						this.enabled = false;
49723
49724					}
49725
49726				}
49727
49728			}
49729
49730		}
49731
49732		this._effectiveWeight = weight;
49733		return weight;
49734
49735	}
49736
49737	_updateTimeScale(time) {
49738
49739		let timeScale = 0;
49740
49741		if (!this.paused) {
49742
49743			timeScale = this.timeScale;
49744
49745			const interpolant = this._timeScaleInterpolant;
49746
49747			if (interpolant !== null) {
49748
49749				const interpolantValue = interpolant.evaluate(time)[0];
49750
49751				timeScale *= interpolantValue;
49752
49753				if (time > interpolant.parameterPositions[1]) {
49754
49755					this.stopWarping();
49756
49757					if (timeScale === 0) {
49758
49759						// motion has halted, pause
49760						this.paused = true;
49761
49762					} else {
49763
49764						// warp done - apply final time scale
49765						this.timeScale = timeScale;
49766
49767					}
49768
49769				}
49770
49771			}
49772
49773		}
49774
49775		this._effectiveTimeScale = timeScale;
49776		return timeScale;
49777
49778	}
49779
49780	_updateTime(deltaTime) {
49781
49782		const duration = this._clip.duration;
49783		const loop = this.loop;
49784
49785		let time = this.time + deltaTime;
49786		let loopCount = this._loopCount;
49787
49788		const pingPong = (loop === LoopPingPong);
49789
49790		if (deltaTime === 0) {
49791
49792			if (loopCount === - 1) return time;
49793
49794			return (pingPong && (loopCount & 1) === 1) ? duration - time : time;
49795
49796		}
49797
49798		if (loop === LoopOnce) {
49799
49800			if (loopCount === - 1) {
49801
49802				// just started
49803
49804				this._loopCount = 0;
49805				this._setEndings(true, true, false);
49806
49807			}
49808
49809			handle_stop: {
49810
49811				if (time >= duration) {
49812
49813					time = duration;
49814
49815				} else if (time < 0) {
49816
49817					time = 0;
49818
49819				} else {
49820
49821					this.time = time;
49822
49823					break handle_stop;
49824
49825				}
49826
49827				if (this.clampWhenFinished) this.paused = true;
49828				else this.enabled = false;
49829
49830				this.time = time;
49831
49832				this._mixer.dispatchEvent({
49833					type: 'finished', action: this,
49834					direction: deltaTime < 0 ? - 1 : 1
49835				});
49836
49837			}
49838
49839		} else { // repetitive Repeat or PingPong
49840
49841			if (loopCount === - 1) {
49842
49843				// just started
49844
49845				if (deltaTime >= 0) {
49846
49847					loopCount = 0;
49848
49849					this._setEndings(true, this.repetitions === 0, pingPong);
49850
49851				} else {
49852
49853					// when looping in reverse direction, the initial
49854					// transition through zero counts as a repetition,
49855					// so leave loopCount at -1
49856
49857					this._setEndings(this.repetitions === 0, true, pingPong);
49858
49859				}
49860
49861			}
49862
49863			if (time >= duration || time < 0) {
49864
49865				// wrap around
49866
49867				const loopDelta = Math.floor(time / duration); // signed
49868				time -= duration * loopDelta;
49869
49870				loopCount += Math.abs(loopDelta);
49871
49872				const pending = this.repetitions - loopCount;
49873
49874				if (pending <= 0) {
49875
49876					// have to stop (switch state, clamp time, fire event)
49877
49878					if (this.clampWhenFinished) this.paused = true;
49879					else this.enabled = false;
49880
49881					time = deltaTime > 0 ? duration : 0;
49882
49883					this.time = time;
49884
49885					this._mixer.dispatchEvent({
49886						type: 'finished', action: this,
49887						direction: deltaTime > 0 ? 1 : - 1
49888					});
49889
49890				} else {
49891
49892					// keep running
49893
49894					if (pending === 1) {
49895
49896						// entering the last round
49897
49898						const atStart = deltaTime < 0;
49899						this._setEndings(atStart, !atStart, pingPong);
49900
49901					} else {
49902
49903						this._setEndings(false, false, pingPong);
49904
49905					}
49906
49907					this._loopCount = loopCount;
49908
49909					this.time = time;
49910
49911					this._mixer.dispatchEvent({
49912						type: 'loop', action: this, loopDelta: loopDelta
49913					});
49914
49915				}
49916
49917			} else {
49918
49919				this.time = time;
49920
49921			}
49922
49923			if (pingPong && (loopCount & 1) === 1) {
49924
49925				// invert time for the "pong round"
49926
49927				return duration - time;
49928
49929			}
49930
49931		}
49932
49933		return time;
49934
49935	}
49936
49937	_setEndings(atStart, atEnd, pingPong) {
49938
49939		const settings = this._interpolantSettings;
49940
49941		if (pingPong) {
49942
49943			settings.endingStart = ZeroSlopeEnding;
49944			settings.endingEnd = ZeroSlopeEnding;
49945
49946		} else {
49947
49948			// assuming for LoopOnce atStart == atEnd == true
49949
49950			if (atStart) {
49951
49952				settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
49953
49954			} else {
49955
49956				settings.endingStart = WrapAroundEnding;
49957
49958			}
49959
49960			if (atEnd) {
49961
49962				settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
49963
49964			} else {
49965
49966				settings.endingEnd = WrapAroundEnding;
49967
49968			}
49969
49970		}
49971
49972	}
49973
49974	_scheduleFading(duration, weightNow, weightThen) {
49975
49976		const mixer = this._mixer, now = mixer.time;
49977		let interpolant = this._weightInterpolant;
49978
49979		if (interpolant === null) {
49980
49981			interpolant = mixer._lendControlInterpolant();
49982			this._weightInterpolant = interpolant;
49983
49984		}
49985
49986		const times = interpolant.parameterPositions,
49987			values = interpolant.sampleValues;
49988
49989		times[0] = now;
49990		values[0] = weightNow;
49991		times[1] = now + duration;
49992		values[1] = weightThen;
49993
49994		return this;
49995
49996	}
49997
49998}
49999
50000const _controlInterpolantsResultBuffer = new Float32Array(1);
50001
50002
50003class AnimationMixer extends EventDispatcher {
50004
50005	constructor(root) {
50006
50007		super();
50008
50009		this._root = root;
50010		this._initMemoryManager();
50011		this._accuIndex = 0;
50012		this.time = 0;
50013		this.timeScale = 1.0;
50014
50015	}
50016
50017	_bindAction(action, prototypeAction) {
50018
50019		const root = action._localRoot || this._root,
50020			tracks = action._clip.tracks,
50021			nTracks = tracks.length,
50022			bindings = action._propertyBindings,
50023			interpolants = action._interpolants,
50024			rootUuid = root.uuid,
50025			bindingsByRoot = this._bindingsByRootAndName;
50026
50027		let bindingsByName = bindingsByRoot[rootUuid];
50028
50029		if (bindingsByName === undefined) {
50030
50031			bindingsByName = {};
50032			bindingsByRoot[rootUuid] = bindingsByName;
50033
50034		}
50035
50036		for (let i = 0; i !== nTracks; ++i) {
50037
50038			const track = tracks[i],
50039				trackName = track.name;
50040
50041			let binding = bindingsByName[trackName];
50042
50043			if (binding !== undefined) {
50044
50045				++binding.referenceCount;
50046				bindings[i] = binding;
50047
50048			} else {
50049
50050				binding = bindings[i];
50051
50052				if (binding !== undefined) {
50053
50054					// existing binding, make sure the cache knows
50055
50056					if (binding._cacheIndex === null) {
50057
50058						++binding.referenceCount;
50059						this._addInactiveBinding(binding, rootUuid, trackName);
50060
50061					}
50062
50063					continue;
50064
50065				}
50066
50067				const path = prototypeAction && prototypeAction.
50068					_propertyBindings[i].binding.parsedPath;
50069
50070				binding = new PropertyMixer(
50071					PropertyBinding.create(root, trackName, path),
50072					track.ValueTypeName, track.getValueSize());
50073
50074				++binding.referenceCount;
50075				this._addInactiveBinding(binding, rootUuid, trackName);
50076
50077				bindings[i] = binding;
50078
50079			}
50080
50081			interpolants[i].resultBuffer = binding.buffer;
50082
50083		}
50084
50085	}
50086
50087	_activateAction(action) {
50088
50089		if (!this._isActiveAction(action)) {
50090
50091			if (action._cacheIndex === null) {
50092
50093				// this action has been forgotten by the cache, but the user
50094				// appears to be still using it -> rebind
50095
50096				const rootUuid = (action._localRoot || this._root).uuid,
50097					clipUuid = action._clip.uuid,
50098					actionsForClip = this._actionsByClip[clipUuid];
50099
50100				this._bindAction(action,
50101					actionsForClip && actionsForClip.knownActions[0]);
50102
50103				this._addInactiveAction(action, clipUuid, rootUuid);
50104
50105			}
50106
50107			const bindings = action._propertyBindings;
vendor: 11,327 bytes, lines 50108-50632
50108
50109			// increment reference counts / sort out state
50110			for (let i = 0, n = bindings.length; i !== n; ++i) {
50111
50112				const binding = bindings[i];
50113
50114				if (binding.useCount++ === 0) {
50115
50116					this._lendBinding(binding);
50117					binding.saveOriginalState();
50118
50119				}
50120
50121			}
50122
50123			this._lendAction(action);
50124
50125		}
50126
50127	}
50128
50129	_deactivateAction(action) {
50130
50131		if (this._isActiveAction(action)) {
50132
50133			const bindings = action._propertyBindings;
50134
50135			// decrement reference counts / sort out state
50136			for (let i = 0, n = bindings.length; i !== n; ++i) {
50137
50138				const binding = bindings[i];
50139
50140				if (--binding.useCount === 0) {
50141
50142					binding.restoreOriginalState();
50143					this._takeBackBinding(binding);
50144
50145				}
50146
50147			}
50148
50149			this._takeBackAction(action);
50150
50151		}
50152
50153	}
50154
50155	// Memory manager
50156
50157	_initMemoryManager() {
50158
50159		this._actions = []; // 'nActiveActions' followed by inactive ones
50160		this._nActiveActions = 0;
50161
50162		this._actionsByClip = {};
50163		// inside:
50164		// {
50165		// 	knownActions: Array< AnimationAction > - used as prototypes
50166		// 	actionByRoot: AnimationAction - lookup
50167		// }
50168
50169
50170		this._bindings = []; // 'nActiveBindings' followed by inactive ones
50171		this._nActiveBindings = 0;
50172
50173		this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
50174
50175
50176		this._controlInterpolants = []; // same game as above
50177		this._nActiveControlInterpolants = 0;
50178
50179		const scope = this;
50180
50181		this.stats = {
50182
50183			actions: {
50184				get total() {
50185
50186					return scope._actions.length;
50187
50188				},
50189				get inUse() {
50190
50191					return scope._nActiveActions;
50192
50193				}
50194			},
50195			bindings: {
50196				get total() {
50197
50198					return scope._bindings.length;
50199
50200				},
50201				get inUse() {
50202
50203					return scope._nActiveBindings;
50204
50205				}
50206			},
50207			controlInterpolants: {
50208				get total() {
50209
50210					return scope._controlInterpolants.length;
50211
50212				},
50213				get inUse() {
50214
50215					return scope._nActiveControlInterpolants;
50216
50217				}
50218			}
50219
50220		};
50221
50222	}
50223
50224	// Memory management for AnimationAction objects
50225
50226	_isActiveAction(action) {
50227
50228		const index = action._cacheIndex;
50229		return index !== null && index < this._nActiveActions;
50230
50231	}
50232
50233	_addInactiveAction(action, clipUuid, rootUuid) {
50234
50235		const actions = this._actions,
50236			actionsByClip = this._actionsByClip;
50237
50238		let actionsForClip = actionsByClip[clipUuid];
50239
50240		if (actionsForClip === undefined) {
50241
50242			actionsForClip = {
50243
50244				knownActions: [action],
50245				actionByRoot: {}
50246
50247			};
50248
50249			action._byClipCacheIndex = 0;
50250
50251			actionsByClip[clipUuid] = actionsForClip;
50252
50253		} else {
50254
50255			const knownActions = actionsForClip.knownActions;
50256
50257			action._byClipCacheIndex = knownActions.length;
50258			knownActions.push(action);
50259
50260		}
50261
50262		action._cacheIndex = actions.length;
50263		actions.push(action);
50264
50265		actionsForClip.actionByRoot[rootUuid] = action;
50266
50267	}
50268
50269	_removeInactiveAction(action) {
50270
50271		const actions = this._actions,
50272			lastInactiveAction = actions[actions.length - 1],
50273			cacheIndex = action._cacheIndex;
50274
50275		lastInactiveAction._cacheIndex = cacheIndex;
50276		actions[cacheIndex] = lastInactiveAction;
50277		actions.pop();
50278
50279		action._cacheIndex = null;
50280
50281
50282		const clipUuid = action._clip.uuid,
50283			actionsByClip = this._actionsByClip,
50284			actionsForClip = actionsByClip[clipUuid],
50285			knownActionsForClip = actionsForClip.knownActions,
50286
50287			lastKnownAction =
50288				knownActionsForClip[knownActionsForClip.length - 1],
50289
50290			byClipCacheIndex = action._byClipCacheIndex;
50291
50292		lastKnownAction._byClipCacheIndex = byClipCacheIndex;
50293		knownActionsForClip[byClipCacheIndex] = lastKnownAction;
50294		knownActionsForClip.pop();
50295
50296		action._byClipCacheIndex = null;
50297
50298
50299		const actionByRoot = actionsForClip.actionByRoot,
50300			rootUuid = (action._localRoot || this._root).uuid;
50301
50302		delete actionByRoot[rootUuid];
50303
50304		if (knownActionsForClip.length === 0) {
50305
50306			delete actionsByClip[clipUuid];
50307
50308		}
50309
50310		this._removeInactiveBindingsForAction(action);
50311
50312	}
50313
50314	_removeInactiveBindingsForAction(action) {
50315
50316		const bindings = action._propertyBindings;
50317
50318		for (let i = 0, n = bindings.length; i !== n; ++i) {
50319
50320			const binding = bindings[i];
50321
50322			if (--binding.referenceCount === 0) {
50323
50324				this._removeInactiveBinding(binding);
50325
50326			}
50327
50328		}
50329
50330	}
50331
50332	_lendAction(action) {
50333
50334		// [ active actions |  inactive actions  ]
50335		// [  active actions >| inactive actions ]
50336		//                 s        a
50337		//                  <-swap->
50338		//                 a        s
50339
50340		const actions = this._actions,
50341			prevIndex = action._cacheIndex,
50342
50343			lastActiveIndex = this._nActiveActions++,
50344
50345			firstInactiveAction = actions[lastActiveIndex];
50346
50347		action._cacheIndex = lastActiveIndex;
50348		actions[lastActiveIndex] = action;
50349
50350		firstInactiveAction._cacheIndex = prevIndex;
50351		actions[prevIndex] = firstInactiveAction;
50352
50353	}
50354
50355	_takeBackAction(action) {
50356
50357		// [  active actions  | inactive actions ]
50358		// [ active actions |< inactive actions  ]
50359		//        a        s
50360		//         <-swap->
50361		//        s        a
50362
50363		const actions = this._actions,
50364			prevIndex = action._cacheIndex,
50365
50366			firstInactiveIndex = --this._nActiveActions,
50367
50368			lastActiveAction = actions[firstInactiveIndex];
50369
50370		action._cacheIndex = firstInactiveIndex;
50371		actions[firstInactiveIndex] = action;
50372
50373		lastActiveAction._cacheIndex = prevIndex;
50374		actions[prevIndex] = lastActiveAction;
50375
50376	}
50377
50378	// Memory management for PropertyMixer objects
50379
50380	_addInactiveBinding(binding, rootUuid, trackName) {
50381
50382		const bindingsByRoot = this._bindingsByRootAndName,
50383			bindings = this._bindings;
50384
50385		let bindingByName = bindingsByRoot[rootUuid];
50386
50387		if (bindingByName === undefined) {
50388
50389			bindingByName = {};
50390			bindingsByRoot[rootUuid] = bindingByName;
50391
50392		}
50393
50394		bindingByName[trackName] = binding;
50395
50396		binding._cacheIndex = bindings.length;
50397		bindings.push(binding);
50398
50399	}
50400
50401	_removeInactiveBinding(binding) {
50402
50403		const bindings = this._bindings,
50404			propBinding = binding.binding,
50405			rootUuid = propBinding.rootNode.uuid,
50406			trackName = propBinding.path,
50407			bindingsByRoot = this._bindingsByRootAndName,
50408			bindingByName = bindingsByRoot[rootUuid],
50409
50410			lastInactiveBinding = bindings[bindings.length - 1],
50411			cacheIndex = binding._cacheIndex;
50412
50413		lastInactiveBinding._cacheIndex = cacheIndex;
50414		bindings[cacheIndex] = lastInactiveBinding;
50415		bindings.pop();
50416
50417		delete bindingByName[trackName];
50418
50419		if (Object.keys(bindingByName).length === 0) {
50420
50421			delete bindingsByRoot[rootUuid];
50422
50423		}
50424
50425	}
50426
50427	_lendBinding(binding) {
50428
50429		const bindings = this._bindings,
50430			prevIndex = binding._cacheIndex,
50431
50432			lastActiveIndex = this._nActiveBindings++,
50433
50434			firstInactiveBinding = bindings[lastActiveIndex];
50435
50436		binding._cacheIndex = lastActiveIndex;
50437		bindings[lastActiveIndex] = binding;
50438
50439		firstInactiveBinding._cacheIndex = prevIndex;
50440		bindings[prevIndex] = firstInactiveBinding;
50441
50442	}
50443
50444	_takeBackBinding(binding) {
50445
50446		const bindings = this._bindings,
50447			prevIndex = binding._cacheIndex,
50448
50449			firstInactiveIndex = --this._nActiveBindings,
50450
50451			lastActiveBinding = bindings[firstInactiveIndex];
50452
50453		binding._cacheIndex = firstInactiveIndex;
50454		bindings[firstInactiveIndex] = binding;
50455
50456		lastActiveBinding._cacheIndex = prevIndex;
50457		bindings[prevIndex] = lastActiveBinding;
50458
50459	}
50460
50461
50462	// Memory management of Interpolants for weight and time scale
50463
50464	_lendControlInterpolant() {
50465
50466		const interpolants = this._controlInterpolants,
50467			lastActiveIndex = this._nActiveControlInterpolants++;
50468
50469		let interpolant = interpolants[lastActiveIndex];
50470
50471		if (interpolant === undefined) {
50472
50473			interpolant = new LinearInterpolant(
50474				new Float32Array(2), new Float32Array(2),
50475				1, _controlInterpolantsResultBuffer);
50476
50477			interpolant.__cacheIndex = lastActiveIndex;
50478			interpolants[lastActiveIndex] = interpolant;
50479
50480		}
50481
50482		return interpolant;
50483
50484	}
50485
50486	_takeBackControlInterpolant(interpolant) {
50487
50488		const interpolants = this._controlInterpolants,
50489			prevIndex = interpolant.__cacheIndex,
50490
50491			firstInactiveIndex = --this._nActiveControlInterpolants,
50492
50493			lastActiveInterpolant = interpolants[firstInactiveIndex];
50494
50495		interpolant.__cacheIndex = firstInactiveIndex;
50496		interpolants[firstInactiveIndex] = interpolant;
50497
50498		lastActiveInterpolant.__cacheIndex = prevIndex;
50499		interpolants[prevIndex] = lastActiveInterpolant;
50500
50501	}
50502
50503	// return an action for a clip optionally using a custom root target
50504	// object (this method allocates a lot of dynamic memory in case a
50505	// previously unknown clip/root combination is specified)
50506	clipAction(clip, optionalRoot, blendMode) {
50507
50508		const root = optionalRoot || this._root,
50509			rootUuid = root.uuid;
50510
50511		let clipObject = typeof clip === 'string' ? AnimationClip.findByName(root, clip) : clip;
50512
50513		const clipUuid = clipObject !== null ? clipObject.uuid : clip;
50514
50515		const actionsForClip = this._actionsByClip[clipUuid];
50516		let prototypeAction = null;
50517
50518		if (blendMode === undefined) {
50519
50520			if (clipObject !== null) {
50521
50522				blendMode = clipObject.blendMode;
50523
50524			} else {
50525
50526				blendMode = NormalAnimationBlendMode;
50527
50528			}
50529
50530		}
50531
50532		if (actionsForClip !== undefined) {
50533
50534			const existingAction = actionsForClip.actionByRoot[rootUuid];
50535
50536			if (existingAction !== undefined && existingAction.blendMode === blendMode) {
50537
50538				return existingAction;
50539
50540			}
50541
50542			// we know the clip, so we don't have to parse all
50543			// the bindings again but can just copy
50544			prototypeAction = actionsForClip.knownActions[0];
50545
50546			// also, take the clip from the prototype action
50547			if (clipObject === null)
50548				clipObject = prototypeAction._clip;
50549
50550		}
50551
50552		// clip must be known when specified via string
50553		if (clipObject === null) return null;
50554
50555		// allocate all resources required to run it
50556		const newAction = new AnimationAction(this, clipObject, optionalRoot, blendMode);
50557
50558		this._bindAction(newAction, prototypeAction);
50559
50560		// and make the action known to the memory manager
50561		this._addInactiveAction(newAction, clipUuid, rootUuid);
50562
50563		return newAction;
50564
50565	}
50566
50567	// get an existing action
50568	existingAction(clip, optionalRoot) {
50569
50570		const root = optionalRoot || this._root,
50571			rootUuid = root.uuid,
50572
50573			clipObject = typeof clip === 'string' ?
50574				AnimationClip.findByName(root, clip) : clip,
50575
50576			clipUuid = clipObject ? clipObject.uuid : clip,
50577
50578			actionsForClip = this._actionsByClip[clipUuid];
50579
50580		if (actionsForClip !== undefined) {
50581
50582			return actionsForClip.actionByRoot[rootUuid] || null;
50583
50584		}
50585
50586		return null;
50587
50588	}
50589
50590	// deactivates all previously scheduled actions
50591	stopAllAction() {
50592
50593		const actions = this._actions,
50594			nActions = this._nActiveActions;
50595
50596		for (let i = nActions - 1; i >= 0; --i) {
50597
50598			actions[i].stop();
50599
50600		}
50601
50602		return this;
50603
50604	}
50605
50606	// advance the time and update apply the animation
50607	update(deltaTime) {
50608
50609		deltaTime *= this.timeScale;
50610
50611		const actions = this._actions,
50612			nActions = this._nActiveActions,
50613
50614			time = this.time += deltaTime,
50615			timeDirection = Math.sign(deltaTime),
50616
50617			accuIndex = this._accuIndex ^= 1;
50618
50619		// run active actions
50620
50621		for (let i = 0; i !== nActions; ++i) {
50622
50623			const action = actions[i];
50624
50625			action._update(time, deltaTime, timeDirection, accuIndex);
50626
50627		}
50628
50629		// update scene graph
50630
50631		const bindings = this._bindings,
50632			nBindings = this._nActiveBindings;
vendor: 2,943 bytes, lines 50633-50777
50633
50634		for (let i = 0; i !== nBindings; ++i) {
50635
50636			bindings[i].apply(accuIndex);
50637
50638		}
50639
50640		return this;
50641
50642	}
50643
50644	// Allows you to seek to a specific time in an animation.
50645	setTime(timeInSeconds) {
50646
50647		this.time = 0; // Zero out time attribute for AnimationMixer object;
50648		for (let i = 0; i < this._actions.length; i++) {
50649
50650			this._actions[i].time = 0; // Zero out time attribute for all associated AnimationAction objects.
50651
50652		}
50653
50654		return this.update(timeInSeconds); // Update used to set exact time. Returns "this" AnimationMixer object.
50655
50656	}
50657
50658	// return this mixer's root target object
50659	getRoot() {
50660
50661		return this._root;
50662
50663	}
50664
50665	// free all resources specific to a particular clip
50666	uncacheClip(clip) {
50667
50668		const actions = this._actions,
50669			clipUuid = clip.uuid,
50670			actionsByClip = this._actionsByClip,
50671			actionsForClip = actionsByClip[clipUuid];
50672
50673		if (actionsForClip !== undefined) {
50674
50675			// note: just calling _removeInactiveAction would mess up the
50676			// iteration state and also require updating the state we can
50677			// just throw away
50678
50679			const actionsToRemove = actionsForClip.knownActions;
50680
50681			for (let i = 0, n = actionsToRemove.length; i !== n; ++i) {
50682
50683				const action = actionsToRemove[i];
50684
50685				this._deactivateAction(action);
50686
50687				const cacheIndex = action._cacheIndex,
50688					lastInactiveAction = actions[actions.length - 1];
50689
50690				action._cacheIndex = null;
50691				action._byClipCacheIndex = null;
50692
50693				lastInactiveAction._cacheIndex = cacheIndex;
50694				actions[cacheIndex] = lastInactiveAction;
50695				actions.pop();
50696
50697				this._removeInactiveBindingsForAction(action);
50698
50699			}
50700
50701			delete actionsByClip[clipUuid];
50702
50703		}
50704
50705	}
50706
50707	// free all resources specific to a particular root target object
50708	uncacheRoot(root) {
50709
50710		const rootUuid = root.uuid,
50711			actionsByClip = this._actionsByClip;
50712
50713		for (const clipUuid in actionsByClip) {
50714
50715			const actionByRoot = actionsByClip[clipUuid].actionByRoot,
50716				action = actionByRoot[rootUuid];
50717
50718			if (action !== undefined) {
50719
50720				this._deactivateAction(action);
50721				this._removeInactiveAction(action);
50722
50723			}
50724
50725		}
50726
50727		const bindingsByRoot = this._bindingsByRootAndName,
50728			bindingByName = bindingsByRoot[rootUuid];
50729
50730		if (bindingByName !== undefined) {
50731
50732			for (const trackName in bindingByName) {
50733
50734				const binding = bindingByName[trackName];
50735				binding.restoreOriginalState();
50736				this._removeInactiveBinding(binding);
50737
50738			}
50739
50740		}
50741
50742	}
50743
50744	// remove a targeted clip from the cache
50745	uncacheAction(clip, optionalRoot) {
50746
50747		const action = this.existingAction(clip, optionalRoot);
50748
50749		if (action !== null) {
50750
50751			this._deactivateAction(action);
50752			this._removeInactiveAction(action);
50753
50754		}
50755
50756	}
50757
50758}
50759
50760class Uniform {
50761
50762	constructor(value) {
50763
50764		this.value = value;
50765
50766	}
50767
50768	clone() {
50769
50770		return new Uniform(this.value.clone === undefined ? this.value : this.value.clone());
50771
50772	}
50773
50774}
50775
50776let _id = 0;
50777
vendor: 4,517 bytes, lines 50778-51059
50778class UniformsGroup extends EventDispatcher {
50779
50780	constructor() {
50781
50782		super();
50783
50784		this.isUniformsGroup = true;
50785
50786		Object.defineProperty(this, 'id', { value: _id++ });
50787
50788		this.name = '';
50789
50790		this.usage = StaticDrawUsage;
50791		this.uniforms = [];
50792
50793	}
50794
50795	add(uniform) {
50796
50797		this.uniforms.push(uniform);
50798
50799		return this;
50800
50801	}
50802
50803	remove(uniform) {
50804
50805		const index = this.uniforms.indexOf(uniform);
50806
50807		if (index !== - 1) this.uniforms.splice(index, 1);
50808
50809		return this;
50810
50811	}
50812
50813	setName(name) {
50814
50815		this.name = name;
50816
50817		return this;
50818
50819	}
50820
50821	setUsage(value) {
50822
50823		this.usage = value;
50824
50825		return this;
50826
50827	}
50828
50829	dispose() {
50830
50831		this.dispatchEvent({ type: 'dispose' });
50832
50833		return this;
50834
50835	}
50836
50837	copy(source) {
50838
50839		this.name = source.name;
50840		this.usage = source.usage;
50841
50842		const uniformsSource = source.uniforms;
50843
50844		this.uniforms.length = 0;
50845
50846		for (let i = 0, l = uniformsSource.length; i < l; i++) {
50847
50848			const uniforms = Array.isArray(uniformsSource[i]) ? uniformsSource[i] : [uniformsSource[i]];
50849
50850			for (let j = 0; j < uniforms.length; j++) {
50851
50852				this.uniforms.push(uniforms[j].clone());
50853
50854			}
50855
50856		}
50857
50858		return this;
50859
50860	}
50861
50862	clone() {
50863
50864		return new this.constructor().copy(this);
50865
50866	}
50867
50868}
50869
50870class InstancedInterleavedBuffer extends InterleavedBuffer {
50871
50872	constructor(array, stride, meshPerAttribute = 1) {
50873
50874		super(array, stride);
50875
50876		this.isInstancedInterleavedBuffer = true;
50877
50878		this.meshPerAttribute = meshPerAttribute;
50879
50880	}
50881
50882	copy(source) {
50883
50884		super.copy(source);
50885
50886		this.meshPerAttribute = source.meshPerAttribute;
50887
50888		return this;
50889
50890	}
50891
50892	clone(data) {
50893
50894		const ib = super.clone(data);
50895
50896		ib.meshPerAttribute = this.meshPerAttribute;
50897
50898		return ib;
50899
50900	}
50901
50902	toJSON(data) {
50903
50904		const json = super.toJSON(data);
50905
50906		json.isInstancedInterleavedBuffer = true;
50907		json.meshPerAttribute = this.meshPerAttribute;
50908
50909		return json;
50910
50911	}
50912
50913}
50914
50915class GLBufferAttribute {
50916
50917	constructor(buffer, type, itemSize, elementSize, count) {
50918
50919		this.isGLBufferAttribute = true;
50920
50921		this.name = '';
50922
50923		this.buffer = buffer;
50924		this.type = type;
50925		this.itemSize = itemSize;
50926		this.elementSize = elementSize;
50927		this.count = count;
50928
50929		this.version = 0;
50930
50931	}
50932
50933	set needsUpdate(value) {
50934
50935		if (value === true) this.version++;
50936
50937	}
50938
50939	setBuffer(buffer) {
50940
50941		this.buffer = buffer;
50942
50943		return this;
50944
50945	}
50946
50947	setType(type, elementSize) {
50948
50949		this.type = type;
50950		this.elementSize = elementSize;
50951
50952		return this;
50953
50954	}
50955
50956	setItemSize(itemSize) {
50957
50958		this.itemSize = itemSize;
50959
50960		return this;
50961
50962	}
50963
50964	setCount(count) {
50965
50966		this.count = count;
50967
50968		return this;
50969
50970	}
50971
50972}
50973
50974class Raycaster {
50975
50976	constructor(origin, direction, near = 0, far = Infinity) {
50977
50978		this.ray = new Ray(origin, direction);
50979		// direction is assumed to be normalized (for accurate distance calculations)
50980
50981		this.near = near;
50982		this.far = far;
50983		this.camera = null;
50984		this.layers = new Layers();
50985
50986		this.params = {
50987			Mesh: {},
50988			Line: { threshold: 1 },
50989			LOD: {},
50990			Points: { threshold: 1 },
50991			Sprite: {}
50992		};
50993
50994	}
50995
50996	set(origin, direction) {
50997
50998		// direction is assumed to be normalized (for accurate distance calculations)
50999
51000		this.ray.set(origin, direction);
51001
51002	}
51003
51004	setFromCamera(coords, camera) {
51005
51006		if (camera.isPerspectiveCamera) {
51007
51008			this.ray.origin.setFromMatrixPosition(camera.matrixWorld);
51009			this.ray.direction.set(coords.x, coords.y, 0.5).unproject(camera).sub(this.ray.origin).normalize();
51010			this.camera = camera;
51011
51012		} else if (camera.isOrthographicCamera) {
51013
51014			this.ray.origin.set(coords.x, coords.y, (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera); // set origin in plane of camera
51015			this.ray.direction.set(0, 0, - 1).transformDirection(camera.matrixWorld);
51016			this.camera = camera;
51017
51018		} else {
51019
51020			console.error('THREE.Raycaster: Unsupported camera type: ' + camera.type);
51021
51022		}
51023
51024	}
51025
51026	intersectObject(object, recursive = true, intersects = []) {
51027
51028		intersectObject(object, this, intersects, recursive);
51029
51030		intersects.sort(ascSort);
51031
51032		return intersects;
51033
51034	}
51035
51036	intersectObjects(objects, recursive = true, intersects = []) {
51037
51038		for (let i = 0, l = objects.length; i < l; i++) {
51039
51040			intersectObject(objects[i], this, intersects, recursive);
51041
51042		}
51043
51044		intersects.sort(ascSort);
51045
51046		return intersects;
51047
51048	}
51049
51050}
51051
51052function ascSort(a, b) {
51053
51054	return a.distance - b.distance;
51055
51056}
51057
51058function intersectObject(object, raycaster, intersects, recursive) {
51059
vendor: 24,314 bytes, lines 51060-52274
51060	if (object.layers.test(raycaster.layers)) {
51061
51062		object.raycast(raycaster, intersects);
51063
51064	}
51065
51066	if (recursive === true) {
51067
51068		const children = object.children;
51069
51070		for (let i = 0, l = children.length; i < l; i++) {
51071
51072			intersectObject(children[i], raycaster, intersects, true);
51073
51074		}
51075
51076	}
51077
51078}
51079
51080/**
51081 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system
51082 *
51083 * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.
51084 * The azimuthal angle (theta) is measured from the positive z-axis.
51085 */
51086
51087
51088class Spherical {
51089
51090	constructor(radius = 1, phi = 0, theta = 0) {
51091
51092		this.radius = radius;
51093		this.phi = phi; // polar angle
51094		this.theta = theta; // azimuthal angle
51095
51096		return this;
51097
51098	}
51099
51100	set(radius, phi, theta) {
51101
51102		this.radius = radius;
51103		this.phi = phi;
51104		this.theta = theta;
51105
51106		return this;
51107
51108	}
51109
51110	copy(other) {
51111
51112		this.radius = other.radius;
51113		this.phi = other.phi;
51114		this.theta = other.theta;
51115
51116		return this;
51117
51118	}
51119
51120	// restrict phi to be between EPS and PI-EPS
51121	makeSafe() {
51122
51123		const EPS = 0.000001;
51124		this.phi = Math.max(EPS, Math.min(Math.PI - EPS, this.phi));
51125
51126		return this;
51127
51128	}
51129
51130	setFromVector3(v) {
51131
51132		return this.setFromCartesianCoords(v.x, v.y, v.z);
51133
51134	}
51135
51136	setFromCartesianCoords(x, y, z) {
51137
51138		this.radius = Math.sqrt(x * x + y * y + z * z);
51139
51140		if (this.radius === 0) {
51141
51142			this.theta = 0;
51143			this.phi = 0;
51144
51145		} else {
51146
51147			this.theta = Math.atan2(x, z);
51148			this.phi = Math.acos(clamp(y / this.radius, - 1, 1));
51149
51150		}
51151
51152		return this;
51153
51154	}
51155
51156	clone() {
51157
51158		return new this.constructor().copy(this);
51159
51160	}
51161
51162}
51163
51164/**
51165 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system
51166 */
51167
51168class Cylindrical {
51169
51170	constructor(radius = 1, theta = 0, y = 0) {
51171
51172		this.radius = radius; // distance from the origin to a point in the x-z plane
51173		this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
51174		this.y = y; // height above the x-z plane
51175
51176		return this;
51177
51178	}
51179
51180	set(radius, theta, y) {
51181
51182		this.radius = radius;
51183		this.theta = theta;
51184		this.y = y;
51185
51186		return this;
51187
51188	}
51189
51190	copy(other) {
51191
51192		this.radius = other.radius;
51193		this.theta = other.theta;
51194		this.y = other.y;
51195
51196		return this;
51197
51198	}
51199
51200	setFromVector3(v) {
51201
51202		return this.setFromCartesianCoords(v.x, v.y, v.z);
51203
51204	}
51205
51206	setFromCartesianCoords(x, y, z) {
51207
51208		this.radius = Math.sqrt(x * x + z * z);
51209		this.theta = Math.atan2(x, z);
51210		this.y = y;
51211
51212		return this;
51213
51214	}
51215
51216	clone() {
51217
51218		return new this.constructor().copy(this);
51219
51220	}
51221
51222}
51223
51224const _vector$4 = /*@__PURE__*/ new Vector2();
51225
51226class Box2 {
51227
51228	constructor(min = new Vector2(+ Infinity, + Infinity), max = new Vector2(- Infinity, - Infinity)) {
51229
51230		this.isBox2 = true;
51231
51232		this.min = min;
51233		this.max = max;
51234
51235	}
51236
51237	set(min, max) {
51238
51239		this.min.copy(min);
51240		this.max.copy(max);
51241
51242		return this;
51243
51244	}
51245
51246	setFromPoints(points) {
51247
51248		this.makeEmpty();
51249
51250		for (let i = 0, il = points.length; i < il; i++) {
51251
51252			this.expandByPoint(points[i]);
51253
51254		}
51255
51256		return this;
51257
51258	}
51259
51260	setFromCenterAndSize(center, size) {
51261
51262		const halfSize = _vector$4.copy(size).multiplyScalar(0.5);
51263		this.min.copy(center).sub(halfSize);
51264		this.max.copy(center).add(halfSize);
51265
51266		return this;
51267
51268	}
51269
51270	clone() {
51271
51272		return new this.constructor().copy(this);
51273
51274	}
51275
51276	copy(box) {
51277
51278		this.min.copy(box.min);
51279		this.max.copy(box.max);
51280
51281		return this;
51282
51283	}
51284
51285	makeEmpty() {
51286
51287		this.min.x = this.min.y = + Infinity;
51288		this.max.x = this.max.y = - Infinity;
51289
51290		return this;
51291
51292	}
51293
51294	isEmpty() {
51295
51296		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
51297
51298		return (this.max.x < this.min.x) || (this.max.y < this.min.y);
51299
51300	}
51301
51302	getCenter(target) {
51303
51304		return this.isEmpty() ? target.set(0, 0) : target.addVectors(this.min, this.max).multiplyScalar(0.5);
51305
51306	}
51307
51308	getSize(target) {
51309
51310		return this.isEmpty() ? target.set(0, 0) : target.subVectors(this.max, this.min);
51311
51312	}
51313
51314	expandByPoint(point) {
51315
51316		this.min.min(point);
51317		this.max.max(point);
51318
51319		return this;
51320
51321	}
51322
51323	expandByVector(vector) {
51324
51325		this.min.sub(vector);
51326		this.max.add(vector);
51327
51328		return this;
51329
51330	}
51331
51332	expandByScalar(scalar) {
51333
51334		this.min.addScalar(- scalar);
51335		this.max.addScalar(scalar);
51336
51337		return this;
51338
51339	}
51340
51341	containsPoint(point) {
51342
51343		return point.x < this.min.x || point.x > this.max.x ||
51344			point.y < this.min.y || point.y > this.max.y ? false : true;
51345
51346	}
51347
51348	containsBox(box) {
51349
51350		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
51351			this.min.y <= box.min.y && box.max.y <= this.max.y;
51352
51353	}
51354
51355	getParameter(point, target) {
51356
51357		// This can potentially have a divide by zero if the box
51358		// has a size dimension of 0.
51359
51360		return target.set(
51361			(point.x - this.min.x) / (this.max.x - this.min.x),
51362			(point.y - this.min.y) / (this.max.y - this.min.y)
51363		);
51364
51365	}
51366
51367	intersectsBox(box) {
51368
51369		// using 4 splitting planes to rule out intersections
51370
51371		return box.max.x < this.min.x || box.min.x > this.max.x ||
51372			box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
51373
51374	}
51375
51376	clampPoint(point, target) {
51377
51378		return target.copy(point).clamp(this.min, this.max);
51379
51380	}
51381
51382	distanceToPoint(point) {
51383
51384		return this.clampPoint(point, _vector$4).distanceTo(point);
51385
51386	}
51387
51388	intersect(box) {
51389
51390		this.min.max(box.min);
51391		this.max.min(box.max);
51392
51393		if (this.isEmpty()) this.makeEmpty();
51394
51395		return this;
51396
51397	}
51398
51399	union(box) {
51400
51401		this.min.min(box.min);
51402		this.max.max(box.max);
51403
51404		return this;
51405
51406	}
51407
51408	translate(offset) {
51409
51410		this.min.add(offset);
51411		this.max.add(offset);
51412
51413		return this;
51414
51415	}
51416
51417	equals(box) {
51418
51419		return box.min.equals(this.min) && box.max.equals(this.max);
51420
51421	}
51422
51423}
51424
51425const _startP = /*@__PURE__*/ new Vector3();
51426const _startEnd = /*@__PURE__*/ new Vector3();
51427
51428class Line3 {
51429
51430	constructor(start = new Vector3(), end = new Vector3()) {
51431
51432		this.start = start;
51433		this.end = end;
51434
51435	}
51436
51437	set(start, end) {
51438
51439		this.start.copy(start);
51440		this.end.copy(end);
51441
51442		return this;
51443
51444	}
51445
51446	copy(line) {
51447
51448		this.start.copy(line.start);
51449		this.end.copy(line.end);
51450
51451		return this;
51452
51453	}
51454
51455	getCenter(target) {
51456
51457		return target.addVectors(this.start, this.end).multiplyScalar(0.5);
51458
51459	}
51460
51461	delta(target) {
51462
51463		return target.subVectors(this.end, this.start);
51464
51465	}
51466
51467	distanceSq() {
51468
51469		return this.start.distanceToSquared(this.end);
51470
51471	}
51472
51473	distance() {
51474
51475		return this.start.distanceTo(this.end);
51476
51477	}
51478
51479	at(t, target) {
51480
51481		return this.delta(target).multiplyScalar(t).add(this.start);
51482
51483	}
51484
51485	closestPointToPointParameter(point, clampToLine) {
51486
51487		_startP.subVectors(point, this.start);
51488		_startEnd.subVectors(this.end, this.start);
51489
51490		const startEnd2 = _startEnd.dot(_startEnd);
51491		const startEnd_startP = _startEnd.dot(_startP);
51492
51493		let t = startEnd_startP / startEnd2;
51494
51495		if (clampToLine) {
51496
51497			t = clamp(t, 0, 1);
51498
51499		}
51500
51501		return t;
51502
51503	}
51504
51505	closestPointToPoint(point, clampToLine, target) {
51506
51507		const t = this.closestPointToPointParameter(point, clampToLine);
51508
51509		return this.delta(target).multiplyScalar(t).add(this.start);
51510
51511	}
51512
51513	applyMatrix4(matrix) {
51514
51515		this.start.applyMatrix4(matrix);
51516		this.end.applyMatrix4(matrix);
51517
51518		return this;
51519
51520	}
51521
51522	equals(line) {
51523
51524		return line.start.equals(this.start) && line.end.equals(this.end);
51525
51526	}
51527
51528	clone() {
51529
51530		return new this.constructor().copy(this);
51531
51532	}
51533
51534}
51535
51536const _vector$3 = /*@__PURE__*/ new Vector3();
51537
51538class SpotLightHelper extends Object3D {
51539
51540	constructor(light, color) {
51541
51542		super();
51543
51544		this.light = light;
51545
51546		this.matrix = light.matrixWorld;
51547		this.matrixAutoUpdate = false;
51548
51549		this.color = color;
51550
51551		this.type = 'SpotLightHelper';
51552
51553		const geometry = new BufferGeometry();
51554
51555		const positions = [
51556			0, 0, 0, 0, 0, 1,
51557			0, 0, 0, 1, 0, 1,
51558			0, 0, 0, - 1, 0, 1,
51559			0, 0, 0, 0, 1, 1,
51560			0, 0, 0, 0, - 1, 1
51561		];
51562
51563		for (let i = 0, j = 1, l = 32; i < l; i++, j++) {
51564
51565			const p1 = (i / l) * Math.PI * 2;
51566			const p2 = (j / l) * Math.PI * 2;
51567
51568			positions.push(
51569				Math.cos(p1), Math.sin(p1), 1,
51570				Math.cos(p2), Math.sin(p2), 1
51571			);
51572
51573		}
51574
51575		geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
51576
51577		const material = new LineBasicMaterial({ fog: false, toneMapped: false });
51578
51579		this.cone = new LineSegments(geometry, material);
51580		this.add(this.cone);
51581
51582		this.update();
51583
51584	}
51585
51586	dispose() {
51587
51588		this.cone.geometry.dispose();
51589		this.cone.material.dispose();
51590
51591	}
51592
51593	update() {
51594
51595		this.light.updateWorldMatrix(true, false);
51596		this.light.target.updateWorldMatrix(true, false);
51597
51598		const coneLength = this.light.distance ? this.light.distance : 1000;
51599		const coneWidth = coneLength * Math.tan(this.light.angle);
51600
51601		this.cone.scale.set(coneWidth, coneWidth, coneLength);
51602
51603		_vector$3.setFromMatrixPosition(this.light.target.matrixWorld);
51604
51605		this.cone.lookAt(_vector$3);
51606
51607		if (this.color !== undefined) {
51608
51609			this.cone.material.color.set(this.color);
51610
51611		} else {
51612
51613			this.cone.material.color.copy(this.light.color);
51614
51615		}
51616
51617	}
51618
51619}
51620
51621const _vector$2 = /*@__PURE__*/ new Vector3();
51622const _boneMatrix = /*@__PURE__*/ new Matrix4();
51623const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
51624
51625
51626class SkeletonHelper extends LineSegments {
51627
51628	constructor(object) {
51629
51630		const bones = getBoneList(object);
51631
51632		const geometry = new BufferGeometry();
51633
51634		const vertices = [];
51635		const colors = [];
51636
51637		const color1 = new Color(0, 0, 1);
51638		const color2 = new Color(0, 1, 0);
51639
51640		for (let i = 0; i < bones.length; i++) {
51641
51642			const bone = bones[i];
51643
51644			if (bone.parent && bone.parent.isBone) {
51645
51646				vertices.push(0, 0, 0);
51647				vertices.push(0, 0, 0);
51648				colors.push(color1.r, color1.g, color1.b);
51649				colors.push(color2.r, color2.g, color2.b);
51650
51651			}
51652
51653		}
51654
51655		geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
51656		geometry.setAttribute('color', new Float32BufferAttribute(colors, 3));
51657
51658		const material = new LineBasicMaterial({ vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true });
51659
51660		super(geometry, material);
51661
51662		this.isSkeletonHelper = true;
51663
51664		this.type = 'SkeletonHelper';
51665
51666		this.root = object;
51667		this.bones = bones;
51668
51669		this.matrix = object.matrixWorld;
51670		this.matrixAutoUpdate = false;
51671
51672	}
51673
51674	updateMatrixWorld(force) {
51675
51676		const bones = this.bones;
51677
51678		const geometry = this.geometry;
51679		const position = geometry.getAttribute('position');
51680
51681		_matrixWorldInv.copy(this.root.matrixWorld).invert();
51682
51683		for (let i = 0, j = 0; i < bones.length; i++) {
51684
51685			const bone = bones[i];
51686
51687			if (bone.parent && bone.parent.isBone) {
51688
51689				_boneMatrix.multiplyMatrices(_matrixWorldInv, bone.matrixWorld);
51690				_vector$2.setFromMatrixPosition(_boneMatrix);
51691				position.setXYZ(j, _vector$2.x, _vector$2.y, _vector$2.z);
51692
51693				_boneMatrix.multiplyMatrices(_matrixWorldInv, bone.parent.matrixWorld);
51694				_vector$2.setFromMatrixPosition(_boneMatrix);
51695				position.setXYZ(j + 1, _vector$2.x, _vector$2.y, _vector$2.z);
51696
51697				j += 2;
51698
51699			}
51700
51701		}
51702
51703		geometry.getAttribute('position').needsUpdate = true;
51704
51705		super.updateMatrixWorld(force);
51706
51707	}
51708
51709	dispose() {
51710
51711		this.geometry.dispose();
51712		this.material.dispose();
51713
51714	}
51715
51716}
51717
51718
51719function getBoneList(object) {
51720
51721	const boneList = [];
51722
51723	if (object.isBone === true) {
51724
51725		boneList.push(object);
51726
51727	}
51728
51729	for (let i = 0; i < object.children.length; i++) {
51730
51731		boneList.push.apply(boneList, getBoneList(object.children[i]));
51732
51733	}
51734
51735	return boneList;
51736
51737}
51738
51739class PointLightHelper extends Mesh {
51740
51741	constructor(light, sphereSize, color) {
51742
51743		const geometry = new SphereGeometry(sphereSize, 4, 2);
51744		const material = new MeshBasicMaterial({ wireframe: true, fog: false, toneMapped: false });
51745
51746		super(geometry, material);
51747
51748		this.light = light;
51749
51750		this.color = color;
51751
51752		this.type = 'PointLightHelper';
51753
51754		this.matrix = this.light.matrixWorld;
51755		this.matrixAutoUpdate = false;
51756
51757		this.update();
51758
51759
51760		/*
51761	// TODO: delete this comment?
51762	const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
51763	const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
51764
51765	this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
51766	this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
51767
51768	const d = light.distance;
51769
51770	if ( d === 0.0 ) {
51771
51772		this.lightDistance.visible = false;
51773
51774	} else {
51775
51776		this.lightDistance.scale.set( d, d, d );
51777
51778	}
51779
51780	this.add( this.lightDistance );
51781	*/
51782
51783	}
51784
51785	dispose() {
51786
51787		this.geometry.dispose();
51788		this.material.dispose();
51789
51790	}
51791
51792	update() {
51793
51794		this.light.updateWorldMatrix(true, false);
51795
51796		if (this.color !== undefined) {
51797
51798			this.material.color.set(this.color);
51799
51800		} else {
51801
51802			this.material.color.copy(this.light.color);
51803
51804		}
51805
51806		/*
51807		const d = this.light.distance;
51808
51809		if ( d === 0.0 ) {
51810
51811			this.lightDistance.visible = false;
51812
51813		} else {
51814
51815			this.lightDistance.visible = true;
51816			this.lightDistance.scale.set( d, d, d );
51817
51818		}
51819		*/
51820
51821	}
51822
51823}
51824
51825const _vector$1 = /*@__PURE__*/ new Vector3();
51826const _color1 = /*@__PURE__*/ new Color();
51827const _color2 = /*@__PURE__*/ new Color();
51828
51829class HemisphereLightHelper extends Object3D {
51830
51831	constructor(light, size, color) {
51832
51833		super();
51834
51835		this.light = light;
51836
51837		this.matrix = light.matrixWorld;
51838		this.matrixAutoUpdate = false;
51839
51840		this.color = color;
51841
51842		this.type = 'HemisphereLightHelper';
51843
51844		const geometry = new OctahedronGeometry(size);
51845		geometry.rotateY(Math.PI * 0.5);
51846
51847		this.material = new MeshBasicMaterial({ wireframe: true, fog: false, toneMapped: false });
51848		if (this.color === undefined) this.material.vertexColors = true;
51849
51850		const position = geometry.getAttribute('position');
51851		const colors = new Float32Array(position.count * 3);
51852
51853		geometry.setAttribute('color', new BufferAttribute(colors, 3));
51854
51855		this.add(new Mesh(geometry, this.material));
51856
51857		this.update();
51858
51859	}
51860
51861	dispose() {
51862
51863		this.children[0].geometry.dispose();
51864		this.children[0].material.dispose();
51865
51866	}
51867
51868	update() {
51869
51870		const mesh = this.children[0];
51871
51872		if (this.color !== undefined) {
51873
51874			this.material.color.set(this.color);
51875
51876		} else {
51877
51878			const colors = mesh.geometry.getAttribute('color');
51879
51880			_color1.copy(this.light.color);
51881			_color2.copy(this.light.groundColor);
51882
51883			for (let i = 0, l = colors.count; i < l; i++) {
51884
51885				const color = (i < (l / 2)) ? _color1 : _color2;
51886
51887				colors.setXYZ(i, color.r, color.g, color.b);
51888
51889			}
51890
51891			colors.needsUpdate = true;
51892
51893		}
51894
51895		this.light.updateWorldMatrix(true, false);
51896
51897		mesh.lookAt(_vector$1.setFromMatrixPosition(this.light.matrixWorld).negate());
51898
51899	}
51900
51901}
51902
51903class GridHelper extends LineSegments {
51904
51905	constructor(size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888) {
51906
51907		color1 = new Color(color1);
51908		color2 = new Color(color2);
51909
51910		const center = divisions / 2;
51911		const step = size / divisions;
51912		const halfSize = size / 2;
51913
51914		const vertices = [], colors = [];
51915
51916		for (let i = 0, j = 0, k = - halfSize; i <= divisions; i++, k += step) {
51917
51918			vertices.push(- halfSize, 0, k, halfSize, 0, k);
51919			vertices.push(k, 0, - halfSize, k, 0, halfSize);
51920
51921			const color = i === center ? color1 : color2;
51922
51923			color.toArray(colors, j); j += 3;
51924			color.toArray(colors, j); j += 3;
51925			color.toArray(colors, j); j += 3;
51926			color.toArray(colors, j); j += 3;
51927
51928		}
51929
51930		const geometry = new BufferGeometry();
51931		geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
51932		geometry.setAttribute('color', new Float32BufferAttribute(colors, 3));
51933
51934		const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false });
51935
51936		super(geometry, material);
51937
51938		this.type = 'GridHelper';
51939
51940	}
51941
51942	dispose() {
51943
51944		this.geometry.dispose();
51945		this.material.dispose();
51946
51947	}
51948
51949}
51950
51951class PolarGridHelper extends LineSegments {
51952
51953	constructor(radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888) {
51954
51955		color1 = new Color(color1);
51956		color2 = new Color(color2);
51957
51958		const vertices = [];
51959		const colors = [];
51960
51961		// create the sectors
51962
51963		if (sectors > 1) {
51964
51965			for (let i = 0; i < sectors; i++) {
51966
51967				const v = (i / sectors) * (Math.PI * 2);
51968
51969				const x = Math.sin(v) * radius;
51970				const z = Math.cos(v) * radius;
51971
51972				vertices.push(0, 0, 0);
51973				vertices.push(x, 0, z);
51974
51975				const color = (i & 1) ? color1 : color2;
51976
51977				colors.push(color.r, color.g, color.b);
51978				colors.push(color.r, color.g, color.b);
51979
51980			}
51981
51982		}
51983
51984		// create the rings
51985
51986		for (let i = 0; i < rings; i++) {
51987
51988			const color = (i & 1) ? color1 : color2;
51989
51990			const r = radius - (radius / rings * i);
51991
51992			for (let j = 0; j < divisions; j++) {
51993
51994				// first vertex
51995
51996				let v = (j / divisions) * (Math.PI * 2);
51997
51998				let x = Math.sin(v) * r;
51999				let z = Math.cos(v) * r;
52000
52001				vertices.push(x, 0, z);
52002				colors.push(color.r, color.g, color.b);
52003
52004				// second vertex
52005
52006				v = ((j + 1) / divisions) * (Math.PI * 2);
52007
52008				x = Math.sin(v) * r;
52009				z = Math.cos(v) * r;
52010
52011				vertices.push(x, 0, z);
52012				colors.push(color.r, color.g, color.b);
52013
52014			}
52015
52016		}
52017
52018		const geometry = new BufferGeometry();
52019		geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
52020		geometry.setAttribute('color', new Float32BufferAttribute(colors, 3));
52021
52022		const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false });
52023
52024		super(geometry, material);
52025
52026		this.type = 'PolarGridHelper';
52027
52028	}
52029
52030	dispose() {
52031
52032		this.geometry.dispose();
52033		this.material.dispose();
52034
52035	}
52036
52037}
52038
52039const _v1 = /*@__PURE__*/ new Vector3();
52040const _v2 = /*@__PURE__*/ new Vector3();
52041const _v3 = /*@__PURE__*/ new Vector3();
52042
52043class DirectionalLightHelper extends Object3D {
52044
52045	constructor(light, size, color) {
52046
52047		super();
52048
52049		this.light = light;
52050
52051		this.matrix = light.matrixWorld;
52052		this.matrixAutoUpdate = false;
52053
52054		this.color = color;
52055
52056		this.type = 'DirectionalLightHelper';
52057
52058		if (size === undefined) size = 1;
52059
52060		let geometry = new BufferGeometry();
52061		geometry.setAttribute('position', new Float32BufferAttribute([
52062			- size, size, 0,
52063			size, size, 0,
52064			size, - size, 0,
52065			- size, - size, 0,
52066			- size, size, 0
52067		], 3));
52068
52069		const material = new LineBasicMaterial({ fog: false, toneMapped: false });
52070
52071		this.lightPlane = new Line(geometry, material);
52072		this.add(this.lightPlane);
52073
52074		geometry = new BufferGeometry();
52075		geometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 0, 1], 3));
52076
52077		this.targetLine = new Line(geometry, material);
52078		this.add(this.targetLine);
52079
52080		this.update();
52081
52082	}
52083
52084	dispose() {
52085
52086		this.lightPlane.geometry.dispose();
52087		this.lightPlane.material.dispose();
52088		this.targetLine.geometry.dispose();
52089		this.targetLine.material.dispose();
52090
52091	}
52092
52093	update() {
52094
52095		this.light.updateWorldMatrix(true, false);
52096		this.light.target.updateWorldMatrix(true, false);
52097
52098		_v1.setFromMatrixPosition(this.light.matrixWorld);
52099		_v2.setFromMatrixPosition(this.light.target.matrixWorld);
52100		_v3.subVectors(_v2, _v1);
52101
52102		this.lightPlane.lookAt(_v2);
52103
52104		if (this.color !== undefined) {
52105
52106			this.lightPlane.material.color.set(this.color);
52107			this.targetLine.material.color.set(this.color);
52108
52109		} else {
52110
52111			this.lightPlane.material.color.copy(this.light.color);
52112			this.targetLine.material.color.copy(this.light.color);
52113
52114		}
52115
52116		this.targetLine.lookAt(_v2);
52117		this.targetLine.scale.z = _v3.length();
52118
52119	}
52120
52121}
52122
52123const _vector = /*@__PURE__*/ new Vector3();
52124const _camera = /*@__PURE__*/ new Camera();
52125
52126/**
52127 *	- shows frustum, line of sight and up of the camera
52128 *	- suitable for fast updates
52129 * 	- based on frustum visualization in lightgl.js shadowmap example
52130 *		https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html
52131 */
52132
52133class CameraHelper extends LineSegments {
52134
52135	constructor(camera) {
52136
52137		const geometry = new BufferGeometry();
52138		const material = new LineBasicMaterial({ color: 0xffffff, vertexColors: true, toneMapped: false });
52139
52140		const vertices = [];
52141		const colors = [];
52142
52143		const pointMap = {};
52144
52145		// near
52146
52147		addLine('n1', 'n2');
52148		addLine('n2', 'n4');
52149		addLine('n4', 'n3');
52150		addLine('n3', 'n1');
52151
52152		// far
52153
52154		addLine('f1', 'f2');
52155		addLine('f2', 'f4');
52156		addLine('f4', 'f3');
52157		addLine('f3', 'f1');
52158
52159		// sides
52160
52161		addLine('n1', 'f1');
52162		addLine('n2', 'f2');
52163		addLine('n3', 'f3');
52164		addLine('n4', 'f4');
52165
52166		// cone
52167
52168		addLine('p', 'n1');
52169		addLine('p', 'n2');
52170		addLine('p', 'n3');
52171		addLine('p', 'n4');
52172
52173		// up
52174
52175		addLine('u1', 'u2');
52176		addLine('u2', 'u3');
52177		addLine('u3', 'u1');
52178
52179		// target
52180
52181		addLine('c', 't');
52182		addLine('p', 'c');
52183
52184		// cross
52185
52186		addLine('cn1', 'cn2');
52187		addLine('cn3', 'cn4');
52188
52189		addLine('cf1', 'cf2');
52190		addLine('cf3', 'cf4');
52191
52192		function addLine(a, b) {
52193
52194			addPoint(a);
52195			addPoint(b);
52196
52197		}
52198
52199		function addPoint(id) {
52200
52201			vertices.push(0, 0, 0);
52202			colors.push(0, 0, 0);
52203
52204			if (pointMap[id] === undefined) {
52205
52206				pointMap[id] = [];
52207
52208			}
52209
52210			pointMap[id].push((vertices.length / 3) - 1);
52211
52212		}
52213
52214		geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
52215		geometry.setAttribute('color', new Float32BufferAttribute(colors, 3));
52216
52217		super(geometry, material);
52218
52219		this.type = 'CameraHelper';
52220
52221		this.camera = camera;
52222		if (this.camera.updateProjectionMatrix) this.camera.updateProjectionMatrix();
52223
52224		this.matrix = camera.matrixWorld;
52225		this.matrixAutoUpdate = false;
52226
52227		this.pointMap = pointMap;
52228
52229		this.update();
52230
52231		// colors
52232
52233		const colorFrustum = new Color(0xffaa00);
52234		const colorCone = new Color(0xff0000);
52235		const colorUp = new Color(0x00aaff);
52236		const colorTarget = new Color(0xffffff);
52237		const colorCross = new Color(0x333333);
52238
52239		this.setColors(colorFrustum, colorCone, colorUp, colorTarget, colorCross);
52240
52241	}
52242
52243	setColors(frustum, cone, up, target, cross) {
52244
52245		const geometry = this.geometry;
52246
52247		const colorAttribute = geometry.getAttribute('color');
52248
52249		// near
52250
52251		colorAttribute.setXYZ(0, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(1, frustum.r, frustum.g, frustum.b); // n1, n2
52252		colorAttribute.setXYZ(2, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(3, frustum.r, frustum.g, frustum.b); // n2, n4
52253		colorAttribute.setXYZ(4, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(5, frustum.r, frustum.g, frustum.b); // n4, n3
52254		colorAttribute.setXYZ(6, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(7, frustum.r, frustum.g, frustum.b); // n3, n1
52255
52256		// far
52257
52258		colorAttribute.setXYZ(8, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(9, frustum.r, frustum.g, frustum.b); // f1, f2
52259		colorAttribute.setXYZ(10, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(11, frustum.r, frustum.g, frustum.b); // f2, f4
52260		colorAttribute.setXYZ(12, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(13, frustum.r, frustum.g, frustum.b); // f4, f3
52261		colorAttribute.setXYZ(14, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(15, frustum.r, frustum.g, frustum.b); // f3, f1
52262
52263		// sides
52264
52265		colorAttribute.setXYZ(16, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(17, frustum.r, frustum.g, frustum.b); // n1, f1
52266		colorAttribute.setXYZ(18, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(19, frustum.r, frustum.g, frustum.b); // n2, f2
52267		colorAttribute.setXYZ(20, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(21, frustum.r, frustum.g, frustum.b); // n3, f3
52268		colorAttribute.setXYZ(22, frustum.r, frustum.g, frustum.b); colorAttribute.setXYZ(23, frustum.r, frustum.g, frustum.b); // n4, f4
52269
52270		// cone
52271
52272		colorAttribute.setXYZ(24, cone.r, cone.g, cone.b); colorAttribute.setXYZ(25, cone.r, cone.g, cone.b); // p, n1
52273		colorAttribute.setXYZ(26, cone.r, cone.g, cone.b); colorAttribute.setXYZ(27, cone.r, cone.g, cone.b); // p, n2
52274		colorAttribute.setXYZ(28, cone.r, cone.g, cone.b); colorAttribute.setXYZ(29, cone.r, cone.g, cone.b); // p, n3
52275		colorAttribute.setXYZ(30, cone.r, cone.g, cone.b); colorAttribute.setXYZ(31, cone.r, cone.g, cone.b); // p, n4
52276
52277		// up
52278
52279		colorAttribute.setXYZ(32, up.r, up.g, up.b); colorAttribute.setXYZ(33, up.r, up.g, up.b); // u1, u2
52280		colorAttribute.setXYZ(34, up.r, up.g, up.b); colorAttribute.setXYZ(35, up.r, up.g, up.b); // u2, u3
52281		colorAttribute.setXYZ(36, up.r, up.g, up.b); colorAttribute.setXYZ(37, up.r, up.g, up.b); // u3, u1
52282
52283		// target
52284
52285		colorAttribute.setXYZ(38, target.r, target.g, target.b); colorAttribute.setXYZ(39, target.r, target.g, target.b); // c, t
52286		colorAttribute.setXYZ(40, cross.r, cross.g, cross.b); colorAttribute.setXYZ(41, cross.r, cross.g, cross.b); // p, c
52287
52288		// cross
52289
52290		colorAttribute.setXYZ(42, cross.r, cross.g, cross.b); colorAttribute.setXYZ(43, cross.r, cross.g, cross.b); // cn1, cn2
52291		colorAttribute.setXYZ(44, cross.r, cross.g, cross.b); colorAttribute.setXYZ(45, cross.r, cross.g, cross.b); // cn3, cn4
52292
52293		colorAttribute.setXYZ(46, cross.r, cross.g, cross.b); colorAttribute.setXYZ(47, cross.r, cross.g, cross.b); // cf1, cf2
52294		colorAttribute.setXYZ(48, cross.r, cross.g, cross.b); colorAttribute.setXYZ(49, cross.r, cross.g, cross.b); // cf3, cf4
52295
52296		colorAttribute.needsUpdate = true;
52297
52298	}
52299
52300	update() {
52301
52302		const geometry = this.geometry;
52303		const pointMap = this.pointMap;
52304
52305		const w = 1, h = 1;
52306
52307		// we need just camera projection matrix inverse
52308		// world matrix must be identity
52309
52310		_camera.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse);
52311
52312		// center / target
52313
52314		setPoint('c', pointMap, geometry, _camera, 0, 0, - 1);
52315		setPoint('t', pointMap, geometry, _camera, 0, 0, 1);
52316
52317		// near
52318
52319		setPoint('n1', pointMap, geometry, _camera, - w, - h, - 1);
52320		setPoint('n2', pointMap, geometry, _camera, w, - h, - 1);
52321		setPoint('n3', pointMap, geometry, _camera, - w, h, - 1);
52322		setPoint('n4', pointMap, geometry, _camera, w, h, - 1);
52323
52324		// far
52325
52326		setPoint('f1', pointMap, geometry, _camera, - w, - h, 1);
52327		setPoint('f2', pointMap, geometry, _camera, w, - h, 1);
52328		setPoint('f3', pointMap, geometry, _camera, - w, h, 1);
52329		setPoint('f4', pointMap, geometry, _camera, w, h, 1);
52330
52331		// up
52332
52333		setPoint('u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1);
52334		setPoint('u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1);
52335		setPoint('u3', pointMap, geometry, _camera, 0, h * 2, - 1);
52336
52337		// cross
52338
52339		setPoint('cf1', pointMap, geometry, _camera, - w, 0, 1);
52340		setPoint('cf2', pointMap, geometry, _camera, w, 0, 1);
52341		setPoint('cf3', pointMap, geometry, _camera, 0, - h, 1);
52342		setPoint('cf4', pointMap, geometry, _camera, 0, h, 1);
52343
52344		setPoint('cn1', pointMap, geometry, _camera, - w, 0, - 1);
52345		setPoint('cn2', pointMap, geometry, _camera, w, 0, - 1);
52346		setPoint('cn3', pointMap, geometry, _camera, 0, - h, - 1);
52347		setPoint('cn4', pointMap, geometry, _camera, 0, h, - 1);
52348
52349		geometry.getAttribute('position').needsUpdate = true;
52350
52351	}
52352
52353	dispose() {
52354
52355		this.geometry.dispose();
52356		this.material.dispose();
52357
52358	}
52359
52360}
52361
52362
52363function setPoint(point, pointMap, geometry, camera, x, y, z) {
52364
52365	_vector.set(x, y, z).unproject(camera);
52366
52367	const points = pointMap[point];
52368
52369	if (points !== undefined) {
52370
52371		const position = geometry.getAttribute('position');
52372
52373		for (let i = 0, l = points.length; i < l; i++) {
52374
52375			position.setXYZ(points[i], _vector.x, _vector.y, _vector.z);
52376
52377		}
52378
52379	}
52380
52381}
52382
52383const _box = /*@__PURE__*/ new Box3();
52384
52385class BoxHelper extends LineSegments {
52386
52387	constructor(object, color = 0xffff00) {
52388
52389		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]);
52390		const positions = new Float32Array(8 * 3);
52391
52392		const geometry = new BufferGeometry();
52393		geometry.setIndex(new BufferAttribute(indices, 1));
52394		geometry.setAttribute('position', new BufferAttribute(positions, 3));
52395
52396		super(geometry, new LineBasicMaterial({ color: color, toneMapped: false }));
52397
52398		this.object = object;
52399		this.type = 'BoxHelper';
52400
52401		this.matrixAutoUpdate = false;
52402
52403		this.update();
52404
52405	}
52406
52407	update(object) {
52408
52409		if (object !== undefined) {
52410
vendor: 5,317 bytes, lines 52411-52648
52411			console.warn('THREE.BoxHelper: .update() has no longer arguments.');
52412
52413		}
52414
52415		if (this.object !== undefined) {
52416
52417			_box.setFromObject(this.object);
52418
52419		}
52420
52421		if (_box.isEmpty()) return;
52422
52423		const min = _box.min;
52424		const max = _box.max;
52425
52426		/*
52427			5____4
52428		1/___0/|
52429		| 6__|_7
52430		2/___3/
52431
52432		0: max.x, max.y, max.z
52433		1: min.x, max.y, max.z
52434		2: min.x, min.y, max.z
52435		3: max.x, min.y, max.z
52436		4: max.x, max.y, min.z
52437		5: min.x, max.y, min.z
52438		6: min.x, min.y, min.z
52439		7: max.x, min.y, min.z
52440		*/
52441
52442		const position = this.geometry.attributes.position;
52443		const array = position.array;
52444
52445		array[0] = max.x; array[1] = max.y; array[2] = max.z;
52446		array[3] = min.x; array[4] = max.y; array[5] = max.z;
52447		array[6] = min.x; array[7] = min.y; array[8] = max.z;
52448		array[9] = max.x; array[10] = min.y; array[11] = max.z;
52449		array[12] = max.x; array[13] = max.y; array[14] = min.z;
52450		array[15] = min.x; array[16] = max.y; array[17] = min.z;
52451		array[18] = min.x; array[19] = min.y; array[20] = min.z;
52452		array[21] = max.x; array[22] = min.y; array[23] = min.z;
52453
52454		position.needsUpdate = true;
52455
52456		this.geometry.computeBoundingSphere();
52457
52458	}
52459
52460	setFromObject(object) {
52461
52462		this.object = object;
52463		this.update();
52464
52465		return this;
52466
52467	}
52468
52469	copy(source, recursive) {
52470
52471		super.copy(source, recursive);
52472
52473		this.object = source.object;
52474
52475		return this;
52476
52477	}
52478
52479	dispose() {
52480
52481		this.geometry.dispose();
52482		this.material.dispose();
52483
52484	}
52485
52486}
52487
52488class Box3Helper extends LineSegments {
52489
52490	constructor(box, color = 0xffff00) {
52491
52492		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]);
52493
52494		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];
52495
52496		const geometry = new BufferGeometry();
52497
52498		geometry.setIndex(new BufferAttribute(indices, 1));
52499
52500		geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
52501
52502		super(geometry, new LineBasicMaterial({ color: color, toneMapped: false }));
52503
52504		this.box = box;
52505
52506		this.type = 'Box3Helper';
52507
52508		this.geometry.computeBoundingSphere();
52509
52510	}
52511
52512	updateMatrixWorld(force) {
52513
52514		const box = this.box;
52515
52516		if (box.isEmpty()) return;
52517
52518		box.getCenter(this.position);
52519
52520		box.getSize(this.scale);
52521
52522		this.scale.multiplyScalar(0.5);
52523
52524		super.updateMatrixWorld(force);
52525
52526	}
52527
52528	dispose() {
52529
52530		this.geometry.dispose();
52531		this.material.dispose();
52532
52533	}
52534
52535}
52536
52537class PlaneHelper extends Line {
52538
52539	constructor(plane, size = 1, hex = 0xffff00) {
52540
52541		const color = hex;
52542
52543		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];
52544
52545		const geometry = new BufferGeometry();
52546		geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
52547		geometry.computeBoundingSphere();
52548
52549		super(geometry, new LineBasicMaterial({ color: color, toneMapped: false }));
52550
52551		this.type = 'PlaneHelper';
52552
52553		this.plane = plane;
52554
52555		this.size = size;
52556
52557		const positions2 = [1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0];
52558
52559		const geometry2 = new BufferGeometry();
52560		geometry2.setAttribute('position', new Float32BufferAttribute(positions2, 3));
52561		geometry2.computeBoundingSphere();
52562
52563		this.add(new Mesh(geometry2, new MeshBasicMaterial({ color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false })));
52564
52565	}
52566
52567	updateMatrixWorld(force) {
52568
52569		this.position.set(0, 0, 0);
52570
52571		this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
52572
52573		this.lookAt(this.plane.normal);
52574
52575		this.translateZ(- this.plane.constant);
52576
52577		super.updateMatrixWorld(force);
52578
52579	}
52580
52581	dispose() {
52582
52583		this.geometry.dispose();
52584		this.material.dispose();
52585		this.children[0].geometry.dispose();
52586		this.children[0].material.dispose();
52587
52588	}
52589
52590}
52591
52592const _axis = /*@__PURE__*/ new Vector3();
52593let _lineGeometry, _coneGeometry;
52594
52595class ArrowHelper extends Object3D {
52596
52597	// dir is assumed to be normalized
52598
52599	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) {
52600
52601		super();
52602
52603		this.type = 'ArrowHelper';
52604
52605		if (_lineGeometry === undefined) {
52606
52607			_lineGeometry = new BufferGeometry();
52608			_lineGeometry.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 0, 1, 0], 3));
52609
52610			_coneGeometry = new CylinderGeometry(0, 0.5, 1, 5, 1);
52611			_coneGeometry.translate(0, - 0.5, 0);
52612
52613		}
52614
52615		this.position.copy(origin);
52616
52617		this.line = new Line(_lineGeometry, new LineBasicMaterial({ color: color, toneMapped: false }));
52618		this.line.matrixAutoUpdate = false;
52619		this.add(this.line);
52620
52621		this.cone = new Mesh(_coneGeometry, new MeshBasicMaterial({ color: color, toneMapped: false }));
52622		this.cone.matrixAutoUpdate = false;
52623		this.add(this.cone);
52624
52625		this.setDirection(dir);
52626		this.setLength(length, headLength, headWidth);
52627
52628	}
52629
52630	setDirection(dir) {
52631
52632		// dir is assumed to be normalized
52633
52634		if (dir.y > 0.99999) {
52635
52636			this.quaternion.set(0, 0, 0, 1);
52637
52638		} else if (dir.y < - 0.99999) {
52639
52640			this.quaternion.set(1, 0, 0, 0);
52641
52642		} else {
52643
52644			_axis.set(dir.z, 0, - dir.x).normalize();
52645
52646			const radians = Math.acos(dir.y);
52647
52648			this.quaternion.setFromAxisAngle(_axis, radians);
vendor: 12,207 bytes, lines 52649-53062
52649
52650		}
52651
52652	}
52653
52654	setLength(length, headLength = length * 0.2, headWidth = headLength * 0.2) {
52655
52656		this.line.scale.set(1, Math.max(0.0001, length - headLength), 1); // see #17458
52657		this.line.updateMatrix();
52658
52659		this.cone.scale.set(headWidth, headLength, headWidth);
52660		this.cone.position.y = length;
52661		this.cone.updateMatrix();
52662
52663	}
52664
52665	setColor(color) {
52666
52667		this.line.material.color.set(color);
52668		this.cone.material.color.set(color);
52669
52670	}
52671
52672	copy(source) {
52673
52674		super.copy(source, false);
52675
52676		this.line.copy(source.line);
52677		this.cone.copy(source.cone);
52678
52679		return this;
52680
52681	}
52682
52683	dispose() {
52684
52685		this.line.geometry.dispose();
52686		this.line.material.dispose();
52687		this.cone.geometry.dispose();
52688		this.cone.material.dispose();
52689
52690	}
52691
52692}
52693
52694class AxesHelper extends LineSegments {
52695
52696	constructor(size = 1) {
52697
52698		const vertices = [
52699			0, 0, 0, size, 0, 0,
52700			0, 0, 0, 0, size, 0,
52701			0, 0, 0, 0, 0, size
52702		];
52703
52704		const colors = [
52705			1, 0, 0, 1, 0.6, 0,
52706			0, 1, 0, 0.6, 1, 0,
52707			0, 0, 1, 0, 0.6, 1
52708		];
52709
52710		const geometry = new BufferGeometry();
52711		geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3));
52712		geometry.setAttribute('color', new Float32BufferAttribute(colors, 3));
52713
52714		const material = new LineBasicMaterial({ vertexColors: true, toneMapped: false });
52715
52716		super(geometry, material);
52717
52718		this.type = 'AxesHelper';
52719
52720	}
52721
52722	setColors(xAxisColor, yAxisColor, zAxisColor) {
52723
52724		const color = new Color();
52725		const array = this.geometry.attributes.color.array;
52726
52727		color.set(xAxisColor);
52728		color.toArray(array, 0);
52729		color.toArray(array, 3);
52730
52731		color.set(yAxisColor);
52732		color.toArray(array, 6);
52733		color.toArray(array, 9);
52734
52735		color.set(zAxisColor);
52736		color.toArray(array, 12);
52737		color.toArray(array, 15);
52738
52739		this.geometry.attributes.color.needsUpdate = true;
52740
52741		return this;
52742
52743	}
52744
52745	dispose() {
52746
52747		this.geometry.dispose();
52748		this.material.dispose();
52749
52750	}
52751
52752}
52753
52754class ShapePath {
52755
52756	constructor() {
52757
52758		this.type = 'ShapePath';
52759
52760		this.color = new Color();
52761
52762		this.subPaths = [];
52763		this.currentPath = null;
52764
52765	}
52766
52767	moveTo(x, y) {
52768
52769		this.currentPath = new Path();
52770		this.subPaths.push(this.currentPath);
52771		this.currentPath.moveTo(x, y);
52772
52773		return this;
52774
52775	}
52776
52777	lineTo(x, y) {
52778
52779		this.currentPath.lineTo(x, y);
52780
52781		return this;
52782
52783	}
52784
52785	quadraticCurveTo(aCPx, aCPy, aX, aY) {
52786
52787		this.currentPath.quadraticCurveTo(aCPx, aCPy, aX, aY);
52788
52789		return this;
52790
52791	}
52792
52793	bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
52794
52795		this.currentPath.bezierCurveTo(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY);
52796
52797		return this;
52798
52799	}
52800
52801	splineThru(pts) {
52802
52803		this.currentPath.splineThru(pts);
52804
52805		return this;
52806
52807	}
52808
52809	toShapes(isCCW) {
52810
52811		function toShapesNoHoles(inSubpaths) {
52812
52813			const shapes = [];
52814
52815			for (let i = 0, l = inSubpaths.length; i < l; i++) {
52816
52817				const tmpPath = inSubpaths[i];
52818
52819				const tmpShape = new Shape();
52820				tmpShape.curves = tmpPath.curves;
52821
52822				shapes.push(tmpShape);
52823
52824			}
52825
52826			return shapes;
52827
52828		}
52829
52830		function isPointInsidePolygon(inPt, inPolygon) {
52831
52832			const polyLen = inPolygon.length;
52833
52834			// inPt on polygon contour => immediate success    or
52835			// toggling of inside/outside at every single! intersection point of an edge
52836			//  with the horizontal line through inPt, left of inPt
52837			//  not counting lowerY endpoints of edges and whole edges on that line
52838			let inside = false;
52839			for (let p = polyLen - 1, q = 0; q < polyLen; p = q++) {
52840
52841				let edgeLowPt = inPolygon[p];
52842				let edgeHighPt = inPolygon[q];
52843
52844				let edgeDx = edgeHighPt.x - edgeLowPt.x;
52845				let edgeDy = edgeHighPt.y - edgeLowPt.y;
52846
52847				if (Math.abs(edgeDy) > Number.EPSILON) {
52848
52849					// not parallel
52850					if (edgeDy < 0) {
52851
52852						edgeLowPt = inPolygon[q]; edgeDx = - edgeDx;
52853						edgeHighPt = inPolygon[p]; edgeDy = - edgeDy;
52854
52855					}
52856
52857					if ((inPt.y < edgeLowPt.y) || (inPt.y > edgeHighPt.y)) continue;
52858
52859					if (inPt.y === edgeLowPt.y) {
52860
52861						if (inPt.x === edgeLowPt.x) return true;		// inPt is on contour ?
52862						// continue;				// no intersection or edgeLowPt => doesn't count !!!
52863
52864					} else {
52865
52866						const perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
52867						if (perpEdge === 0) return true;		// inPt is on contour ?
52868						if (perpEdge < 0) continue;
52869						inside = !inside;		// true intersection left of inPt
52870
52871					}
52872
52873				} else {
52874
52875					// parallel or collinear
52876					if (inPt.y !== edgeLowPt.y) continue;			// parallel
52877					// edge lies on the same horizontal line as inPt
52878					if (((edgeHighPt.x <= inPt.x) && (inPt.x <= edgeLowPt.x)) ||
52879						((edgeLowPt.x <= inPt.x) && (inPt.x <= edgeHighPt.x))) return true;	// inPt: Point on contour !
52880					// continue;
52881
52882				}
52883
52884			}
52885
52886			return inside;
52887
52888		}
52889
52890		const isClockWise = ShapeUtils.isClockWise;
52891
52892		const subPaths = this.subPaths;
52893		if (subPaths.length === 0) return [];
52894
52895		let solid, tmpPath, tmpShape;
52896		const shapes = [];
52897
52898		if (subPaths.length === 1) {
52899
52900			tmpPath = subPaths[0];
52901			tmpShape = new Shape();
52902			tmpShape.curves = tmpPath.curves;
52903			shapes.push(tmpShape);
52904			return shapes;
52905
52906		}
52907
52908		let holesFirst = !isClockWise(subPaths[0].getPoints());
52909		holesFirst = isCCW ? !holesFirst : holesFirst;
52910
52911		// console.log("Holes first", holesFirst);
52912
52913		const betterShapeHoles = [];
52914		const newShapes = [];
52915		let newShapeHoles = [];
52916		let mainIdx = 0;
52917		let tmpPoints;
52918
52919		newShapes[mainIdx] = undefined;
52920		newShapeHoles[mainIdx] = [];
52921
52922		for (let i = 0, l = subPaths.length; i < l; i++) {
52923
52924			tmpPath = subPaths[i];
52925			tmpPoints = tmpPath.getPoints();
52926			solid = isClockWise(tmpPoints);
52927			solid = isCCW ? !solid : solid;
52928
52929			if (solid) {
52930
52931				if ((!holesFirst) && (newShapes[mainIdx])) mainIdx++;
52932
52933				newShapes[mainIdx] = { s: new Shape(), p: tmpPoints };
52934				newShapes[mainIdx].s.curves = tmpPath.curves;
52935
52936				if (holesFirst) mainIdx++;
52937				newShapeHoles[mainIdx] = [];
52938
52939				//console.log('cw', i);
52940
52941			} else {
52942
52943				newShapeHoles[mainIdx].push({ h: tmpPath, p: tmpPoints[0] });
52944
52945				//console.log('ccw', i);
52946
52947			}
52948
52949		}
52950
52951		// only Holes? -> probably all Shapes with wrong orientation
52952		if (!newShapes[0]) return toShapesNoHoles(subPaths);
52953
52954
52955		if (newShapes.length > 1) {
52956
52957			let ambiguous = false;
52958			let toChange = 0;
52959
52960			for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
52961
52962				betterShapeHoles[sIdx] = [];
52963
52964			}
52965
52966			for (let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx++) {
52967
52968				const sho = newShapeHoles[sIdx];
52969
52970				for (let hIdx = 0; hIdx < sho.length; hIdx++) {
52971
52972					const ho = sho[hIdx];
52973					let hole_unassigned = true;
52974
52975					for (let s2Idx = 0; s2Idx < newShapes.length; s2Idx++) {
52976
52977						if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) {
52978
52979							if (sIdx !== s2Idx) toChange++;
52980
52981							if (hole_unassigned) {
52982
52983								hole_unassigned = false;
52984								betterShapeHoles[s2Idx].push(ho);
52985
52986							} else {
52987
52988								ambiguous = true;
52989
52990							}
52991
52992						}
52993
52994					}
52995
52996					if (hole_unassigned) {
52997
52998						betterShapeHoles[sIdx].push(ho);
52999
53000					}
53001
53002				}
53003
53004			}
53005
53006			if (toChange > 0 && ambiguous === false) {
53007
53008				newShapeHoles = betterShapeHoles;
53009
53010			}
53011
53012		}
53013
53014		let tmpHoles;
53015
53016		for (let i = 0, il = newShapes.length; i < il; i++) {
53017
53018			tmpShape = newShapes[i].s;
53019			shapes.push(tmpShape);
53020			tmpHoles = newShapeHoles[i];
53021
53022			for (let j = 0, jl = tmpHoles.length; j < jl; j++) {
53023
53024				tmpShape.holes.push(tmpHoles[j].h);
53025
53026			}
53027
53028		}
53029
53030		//console.log("shape", shapes);
53031
53032		return shapes;
53033
53034	}
53035
53036}
53037
53038if (typeof __THREE_DEVTOOLS__ !== 'undefined') {
53039
53040	__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent('register', {
53041		detail: {
53042			revision: REVISION,
53043		}
53044	}));
53045
53046}
53047
53048if (typeof window !== 'undefined') {
53049
53050	if (window.__THREE__) {
53051
53052		console.warn('WARNING: Multiple instances of Three.js being imported.');
53053
53054	} else {
53055
53056		window.__THREE__ = REVISION;
53057
53058	}
53059
53060}
53061
53062export { 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, Float64BufferAttribute, 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, LinearEncoding, 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, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, Orthogra
53062phicCamera, 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, 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, TwoPassDoubleSide, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsLib, UniformsUtils, UnsignedByteType, UnsignedInt248Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoTexture, WebGL1Renderer, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGLRenderer, WebGLUtils, WebGPUCoordinateSystem, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, _SRGBAFormat, createCanvasElement, sRGBEncoding };

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