PageSourceSearch

https://starwarsdatabase.com/gallery/assets/vendor/three.core.js

js starwarsdatabase.com collected 2026-10-07 19:31:03 UTC 1,458,113 bytes, 60,586 lines download raw bytes

vendor: 1,458,113 bytes, lines 1-60586
1/**
2 * @license
3 * Copyright 2010-2026 Three.js Authors
4 * SPDX-License-Identifier: MIT
5 */
6const REVISION = '186';
7
8/**
9 * Represents mouse buttons and interaction types in context of controls.
10 *
11 * @type {ConstantsMouse}
12 * @constant
13 */
14const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
15
16/**
17 * Represents touch interaction types in context of controls.
18 *
19 * @type {ConstantsTouch}
20 * @constant
21 */
22const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
23
24/**
25 * Disables face culling.
26 *
27 * @type {number}
28 * @constant
29 */
30const CullFaceNone = 0;
31
32/**
33 * Culls back faces.
34 *
35 * @type {number}
36 * @constant
37 */
38const CullFaceBack = 1;
39
40/**
41 * Culls front faces.
42 *
43 * @type {number}
44 * @constant
45 */
46const CullFaceFront = 2;
47
48/**
49 * Culls both front and back faces.
50 *
51 * @type {number}
52 * @constant
53 */
54const CullFaceFrontBack = 3;
55
56/**
57 * Gives unfiltered shadow maps - fastest, but lowest quality.
58 *
59 * @type {number}
60 * @constant
61 */
62const BasicShadowMap = 0;
63
64/**
65 * Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm.
66 *
67 * @type {number}
68 * @constant
69 */
70const PCFShadowMap = 1;
71
72/**
73 * Filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm with
74 * better soft shadows especially when using low-resolution shadow maps.
75 *
76 * @type {number}
77 * @constant
78 * @deprecated since r186. Use `PCFShadowMap` instead.
79 */
80const PCFSoftShadowMap = 2;
81
82/**
83 * Filters shadow maps using the Variance Shadow Map (VSM) algorithm.
84 * When using VSMShadowMap all shadow receivers will also cast shadows.
85 *
86 * @type {number}
87 * @constant
88 */
89const VSMShadowMap = 3;
90
91/**
92 * Only front faces are rendered.
93 *
94 * @type {number}
95 * @constant
96 */
97const FrontSide = 0;
98
99/**
100 * Only back faces are rendered.
101 *
102 * @type {number}
103 * @constant
104 */
105const BackSide = 1;
106
107/**
108 * Both front and back faces are rendered.
109 *
110 * @type {number}
111 * @constant
112 */
113const DoubleSide = 2;
114
115/**
116 * No blending is performed which effectively disables
117 * alpha transparency.
118 *
119 * @type {number}
120 * @constant
121 */
122const NoBlending = 0;
123
124/**
125 * The default blending.
126 *
127 * @type {number}
128 * @constant
129 */
130const NormalBlending = 1;
131
132/**
133 * Represents additive blending.
134 *
135 * @type {number}
136 * @constant
137 */
138const AdditiveBlending = 2;
139
140/**
141 * Represents subtractive blending.
142 *
143 * @type {number}
144 * @constant
145 */
146const SubtractiveBlending = 3;
147
148/**
149 * Represents multiply blending.
150 *
151 * @type {number}
152 * @constant
153 */
154const MultiplyBlending = 4;
155
156/**
157 * Represents custom blending.
158 *
159 * @type {number}
160 * @constant
161 */
162const CustomBlending = 5;
163
164/**
165 * Represents material blending.
166 *
167 * @type {number}
168 * @constant
169 */
170const MaterialBlending = 6;
171
172/**
173 * A `source + destination` blending equation.
174 *
175 * @type {number}
176 * @constant
177 */
178const AddEquation = 100;
179
180/**
181 * A `source - destination` blending equation.
182 *
183 * @type {number}
184 * @constant
185 */
186const SubtractEquation = 101;
187
188/**
189 * A `destination - source` blending equation.
190 *
191 * @type {number}
192 * @constant
193 */
194const ReverseSubtractEquation = 102;
195
196/**
197 * A blend equation that uses the minimum of source and destination.
198 *
199 * @type {number}
200 * @constant
201 */
202const MinEquation = 103;
203
204/**
205 * A blend equation that uses the maximum of source and destination.
206 *
207 * @type {number}
208 * @constant
209 */
210const MaxEquation = 104;
211
212/**
213 * Multiplies all colors by `0`.
214 *
215 * @type {number}
216 * @constant
217 */
218const ZeroFactor = 200;
219
220/**
221 * Multiplies all colors by `1`.
222 *
223 * @type {number}
224 * @constant
225 */
226const OneFactor = 201;
227
228/**
229 * Multiplies all colors by the source colors.
230 *
231 * @type {number}
232 * @constant
233 */
234const SrcColorFactor = 202;
235
236/**
237 * Multiplies all colors by `1` minus each source color.
238 *
239 * @type {number}
240 * @constant
241 */
242const OneMinusSrcColorFactor = 203;
243
244/**
245 * Multiplies all colors by the source alpha value.
246 *
247 * @type {number}
248 * @constant
249 */
250const SrcAlphaFactor = 204;
251
252/**
253 * Multiplies all colors by 1 minus the source alpha value.
254 *
255 * @type {number}
256 * @constant
257 */
258const OneMinusSrcAlphaFactor = 205;
259
260/**
261 * Multiplies all colors by the destination alpha value.
262 *
263 * @type {number}
264 * @constant
265 */
266const DstAlphaFactor = 206;
267
268/**
269 * Multiplies all colors by `1` minus the destination alpha value.
270 *
271 * @type {number}
272 * @constant
273 */
274const OneMinusDstAlphaFactor = 207;
275
276/**
277 * Multiplies all colors by the destination color.
278 *
279 * @type {number}
280 * @constant
281 */
282const DstColorFactor = 208;
283
284/**
285 * Multiplies all colors by `1` minus each destination color.
286 *
287 * @type {number}
288 * @constant
289 */
290const OneMinusDstColorFactor = 209;
291
292/**
293 * Multiplies the RGB colors by the smaller of either the source alpha
294 * value or the value of `1` minus the destination alpha value. The alpha
295 * value is multiplied by `1`.
296 *
297 * @type {number}
298 * @constant
299 */
300const SrcAlphaSaturateFactor = 210;
301
302/**
303 * Multiplies all colors by a constant color.
304 *
305 * @type {number}
306 * @constant
307 */
308const ConstantColorFactor = 211;
309
310/**
311 * Multiplies all colors by `1` minus a constant color.
312 *
313 * @type {number}
314 * @constant
315 */
316const OneMinusConstantColorFactor = 212;
317
318/**
319 * Multiplies all colors by a constant alpha value.
320 *
321 * @type {number}
322 * @constant
323 */
324const ConstantAlphaFactor = 213;
325
326/**
327 * Multiplies all colors by 1 minus a constant alpha value.
328 *
329 * @type {number}
330 * @constant
331 */
332const OneMinusConstantAlphaFactor = 214;
333
334/**
335 * Never pass.
336 *
337 * @type {number}
338 * @constant
339 */
340const NeverDepth = 0;
341
342/**
343 * Always pass.
344 *
345 * @type {number}
346 * @constant
347 */
348const AlwaysDepth = 1;
349
350/**
351 * Pass if the incoming value is less than the depth buffer value.
352 *
353 * @type {number}
354 * @constant
355 */
356const LessDepth = 2;
357
358/**
359 * Pass if the incoming value is less than or equal to the depth buffer value.
360 *
361 * @type {number}
362 * @constant
363 */
364const LessEqualDepth = 3;
365
366/**
367 * Pass if the incoming value equals the depth buffer value.
368 *
369 * @type {number}
370 * @constant
371 */
372const EqualDepth = 4;
373
374/**
375 * Pass if the incoming value is greater than or equal to the depth buffer value.
376 *
377 * @type {number}
378 * @constant
379 */
380const GreaterEqualDepth = 5;
381
382/**
383 * Pass if the incoming value is greater than the depth buffer value.
384 *
385 * @type {number}
386 * @constant
387 */
388const GreaterDepth = 6;
389
390/**
391 * Pass if the incoming value is not equal to the depth buffer value.
392 *
393 * @type {number}
394 * @constant
395 */
396const NotEqualDepth = 7;
397
398/**
399 * Multiplies the environment map color with the surface color.
400 *
401 * @type {number}
402 * @constant
403 */
404const MultiplyOperation = 0;
405
406/**
407 * Uses reflectivity to blend between the two colors.
408 *
409 * @type {number}
410 * @constant
411 */
412const MixOperation = 1;
413
414/**
415 * Adds the two colors.
416 *
417 * @type {number}
418 * @constant
419 */
420const AddOperation = 2;
421
422/**
423 * No tone mapping is applied.
424 *
425 * @type {number}
426 * @constant
427 */
428const NoToneMapping = 0;
429
430/**
431 * Linear tone mapping.
432 *
433 * @type {number}
434 * @constant
435 */
436const LinearToneMapping = 1;
437
438/**
439 * Reinhard tone mapping.
440 *
441 * @type {number}
442 * @constant
443 */
444const ReinhardToneMapping = 2;
445
446/**
447 * Cineon tone mapping.
448 *
449 * @type {number}
450 * @constant
451 */
452const CineonToneMapping = 3;
453
454/**
455 * ACES Filmic tone mapping.
456 *
457 * @type {number}
458 * @constant
459 */
460const ACESFilmicToneMapping = 4;
461
462/**
463 * Custom tone mapping.
464 *
465 * Expects a custom implementation by modifying shader code of the material's fragment shader.
466 *
467 * @type {number}
468 * @constant
469 */
470const CustomToneMapping = 5;
471
472/**
473 * AgX tone mapping.
474 *
475 * @type {number}
476 * @constant
477 */
478const AgXToneMapping = 6;
479
480/**
481 * Neutral tone mapping.
482 *
483 * Implementation based on the Khronos 3D Commerce Group standard tone mapping.
484 *
485 * @type {number}
486 * @constant
487 */
488const NeutralToneMapping = 7;
489
490/**
491 * The skinned mesh shares the same world space as the skeleton.
492 *
493 * @type {string}
494 * @constant
495 */
496const AttachedBindMode = 'attached';
497
498/**
499 * The skinned mesh does not share the same world space as the skeleton.
500 * This is useful when a skeleton is shared across multiple skinned meshes.
501 *
502 * @type {string}
503 * @constant
504 */
505const DetachedBindMode = 'detached';
506
507/**
508 * Maps textures using the geometry's UV coordinates.
509 *
510 * @type {number}
511 * @constant
512 */
513const UVMapping = 300;
514
515/**
516 * Reflection mapping for cube textures.
517 *
518 * @type {number}
519 * @constant
520 */
521const CubeReflectionMapping = 301;
522
523/**
524 * Refraction mapping for cube textures.
525 *
526 * @type {number}
527 * @constant
528 */
529const CubeRefractionMapping = 302;
530
531/**
532 * Reflection mapping for equirectangular textures.
533 *
534 * @type {number}
535 * @constant
536 */
537const EquirectangularReflectionMapping = 303;
538
539/**
540 * Refraction mapping for equirectangular textures.
541 *
542 * @type {number}
543 * @constant
544 */
545const EquirectangularRefractionMapping = 304;
546
547/**
548 * Reflection mapping for PMREM textures.
549 *
550 * @type {number}
551 * @constant
552 */
553const CubeUVReflectionMapping = 306;
554
555/**
556 * The texture will simply repeat to infinity.
557 *
558 * @type {number}
559 * @constant
560 */
561const RepeatWrapping = 1000;
562
563/**
564 * The last pixel of the texture stretches to the edge of the mesh.
565 *
566 * @type {number}
567 * @constant
568 */
569const ClampToEdgeWrapping = 1001;
570
571/**
572 * The texture will repeats to infinity, mirroring on each repeat.
573 *
574 * @type {number}
575 * @constant
576 */
577const MirroredRepeatWrapping = 1002;
578
579/**
580 * Returns the value of the texture element that is nearest (in Manhattan distance)
581 * to the specified texture coordinates.
582 *
583 * @type {number}
584 * @constant
585 */
586const NearestFilter = 1003;
587
588/**
589 * Chooses the mipmap that most closely matches the size of the pixel being textured
590 * and uses the `NearestFilter` criterion (the texel nearest to the center of the pixel)
591 * to produce a texture value.
592 *
593 * @type {number}
594 * @constant
595 */
596const NearestMipmapNearestFilter = 1004;
597const NearestMipMapNearestFilter = 1004; // legacy
598
599/**
600 * Chooses the two mipmaps that most closely match the size of the pixel being textured and
601 * uses the `NearestFilter` criterion to produce a texture value from each mipmap.
602 * The final texture value is a weighted average of those two values.
603 *
604 * @type {number}
605 * @constant
606 */
607const NearestMipmapLinearFilter = 1005;
608const NearestMipMapLinearFilter = 1005; // legacy
609
610/**
611 * Returns the weighted average of the four texture elements that are closest to the specified
612 * texture coordinates, and can include items wrapped or repeated from other parts of a texture,
613 * depending on the values of `wrapS` and `wrapT`, and on the exact mapping.
614 *
615 * @type {number}
616 * @constant
617 */
618const LinearFilter = 1006;
619
620/**
621 * Chooses the mipmap that most closely matches the size of the pixel being textured and uses
622 * the `LinearFilter` criterion (a weighted average of the four texels that are closest to the
623 * center of the pixel) to produce a texture value.
624 *
625 * @type {number}
626 * @constant
627 */
628const LinearMipmapNearestFilter = 1007;
629const LinearMipMapNearestFilter = 1007; // legacy
630
631/**
632 * Chooses the two mipmaps that most closely match the size of the pixel being textured and uses
633 * the `LinearFilter` criterion to produce a texture value from each mipmap. The final texture value
634 * is a weighted average of those two values.
635 *
636 * @type {number}
637 * @constant
638 */
639const LinearMipmapLinearFilter = 1008;
640const LinearMipMapLinearFilter = 1008; // legacy
641
642/**
643 * An unsigned byte data type for textures.
644 *
645 * @type {number}
646 * @constant
647 */
648const UnsignedByteType = 1009;
649
650/**
651 * A byte data type for textures.
652 *
653 * @type {number}
654 * @constant
655 */
656const ByteType = 1010;
657
658/**
659 * A short data type for textures.
660 *
661 * @type {number}
662 * @constant
663 */
664const ShortType = 1011;
665
666/**
667 * An unsigned short data type for textures.
668 *
669 * @type {number}
670 * @constant
671 */
672const UnsignedShortType = 1012;
673
674/**
675 * An int data type for textures.
676 *
677 * @type {number}
678 * @constant
679 */
680const IntType = 1013;
681
682/**
683 * An unsigned int data type for textures.
684 *
685 * @type {number}
686 * @constant
687 */
688const UnsignedIntType = 1014;
689
690/**
691 * A float data type for textures.
692 *
693 * @type {number}
694 * @constant
695 */
696const FloatType = 1015;
697
698/**
699 * A half float data type for textures.
700 *
701 * @type {number}
702 * @constant
703 */
704const HalfFloatType = 1016;
705
706/**
707 * An unsigned short 4_4_4_4 (packed) data type for textures.
708 *
709 * @type {number}
710 * @constant
711 */
712const UnsignedShort4444Type = 1017;
713
714/**
715 * An unsigned short 5_5_5_1 (packed) data type for textures.
716 *
717 * @type {number}
718 * @constant
719 */
720const UnsignedShort5551Type = 1018;
721
722/**
723 * An unsigned int 24_8 data type for textures.
724 *
725 * @type {number}
726 * @constant
727 */
728const UnsignedInt248Type = 1020;
729
730/**
731 * An unsigned int 5_9_9_9 (packed) data type for textures.
732 *
733 * @type {number}
734 * @constant
735 */
736const UnsignedInt5999Type = 35902;
737
738/**
739 * An unsigned int 10_11_11 (packed) data type for textures.
740 *
741 * @type {number}
742 * @constant
743 */
744const UnsignedInt101111Type = 35899;
745
746/**
747 * Discards the red, green and blue components and reads just the alpha component.
748 *
749 * @type {number}
750 * @constant
751 */
752const AlphaFormat = 1021;
753
754/**
755 * Discards the alpha component and reads the red, green and blue component.
756 *
757 * @type {number}
758 * @constant
759 */
760const RGBFormat = 1022;
761
762/**
763 * Reads the red, green, blue and alpha components.
764 *
765 * @type {number}
766 * @constant
767 */
768const RGBAFormat = 1023;
769
770/**
771 * Reads each element as a single depth value, converts it to floating point, and clamps to the range `[0,1]`.
772 *
773 * @type {number}
774 * @constant
775 */
776const DepthFormat = 1026;
777
778/**
779 * Reads each element is a pair of depth and stencil values. The depth component of the pair is interpreted as
780 * in `DepthFormat`. The stencil component is interpreted based on the depth + stencil internal format.
781 *
782 * @type {number}
783 * @constant
784 */
785const DepthStencilFormat = 1027;
786
787/**
788 * Discards the green, blue and alpha components and reads just the red component.
789 *
790 * @type {number}
791 * @constant
792 */
793const RedFormat = 1028;
794
795/**
796 * Discards the green, blue and alpha components and reads just the red component. The texels are read as integers instead of floating point.
797 *
798 * @type {number}
799 * @constant
800 */
801const RedIntegerFormat = 1029;
802
803/**
804 * Discards the alpha, and blue components and reads the red, and green components.
805 *
806 * @type {number}
807 * @constant
808 */
809const RGFormat = 1030;
810
811/**
812 * Discards the alpha, and blue components and reads the red, and green components. The texels are read as integers instead of floating point.
813 *
814 * @type {number}
815 * @constant
816 */
817const RGIntegerFormat = 1031;
818
819/**
820 * Discards the alpha component and reads the red, green and blue component. The texels are read as integers instead of floating point.
821 *
822 * @type {number}
823 * @constant
824 */
825const RGBIntegerFormat = 1032;
826
827/**
828 * Reads the red, green, blue and alpha components. The texels are read as integers instead of floating point.
829 *
830 * @type {number}
831 * @constant
832 */
833const RGBAIntegerFormat = 1033;
834
835/**
836 * A DXT1-compressed image in an RGB image format.
837 *
838 * @type {number}
839 * @constant
840 */
841const RGB_S3TC_DXT1_Format = 33776;
842
843/**
844 * A DXT1-compressed image in an RGB image format with a simple on/off alpha value.
845 *
846 * @type {number}
847 * @constant
848 */
849const RGBA_S3TC_DXT1_Format = 33777;
850
851/**
852 * A DXT3-compressed image in an RGBA image format. Compared to a 32-bit RGBA texture, it offers 4:1 compression.
853 *
854 * @type {number}
855 * @constant
856 */
857const RGBA_S3TC_DXT3_Format = 33778;
858
859/**
860 * A DXT5-compressed image in an RGBA image format. It also provides a 4:1 compression, but differs to the DXT3
861 * compression in how the alpha compression is done.
862 *
863 * @type {number}
864 * @constant
865 */
866const RGBA_S3TC_DXT5_Format = 33779;
867
868/**
869 * PVRTC RGB compression in 4-bit mode. One block for each 4×4 pixels.
870 *
871 * @type {number}
872 * @constant
873 */
874const RGB_PVRTC_4BPPV1_Format = 35840;
875
876/**
877 * PVRTC RGB compression in 2-bit mode. One block for each 8×4 pixels.
878 *
879 * @type {number}
880 * @constant
881 */
882const RGB_PVRTC_2BPPV1_Format = 35841;
883
884/**
885 * PVRTC RGBA compression in 4-bit mode. One block for each 4×4 pixels.
886 *
887 * @type {number}
888 * @constant
889 */
890const RGBA_PVRTC_4BPPV1_Format = 35842;
891
892/**
893 * PVRTC RGBA compression in 2-bit mode. One block for each 8×4 pixels.
894 *
895 * @type {number}
896 * @constant
897 */
898const RGBA_PVRTC_2BPPV1_Format = 35843;
899
900/**
901 * ETC1 RGB format.
902 *
903 * @type {number}
904 * @constant
905 */
906const RGB_ETC1_Format = 36196;
907
908/**
909 * ETC2 RGB format.
910 *
911 * @type {number}
912 * @constant
913 */
914const RGB_ETC2_Format = 37492;
915
916/**
917 * ETC2 RGBA format.
918 *
919 * @type {number}
920 * @constant
921 */
922const RGBA_ETC2_EAC_Format = 37496;
923
924/**
925 * EAC R11 UNORM format.
926 *
927 * @type {number}
928 * @constant
929 */
930const R11_EAC_Format = 37488; // 0x9270
931
932/**
933 * EAC R11 SNORM format.
934 *
935 * @type {number}
936 * @constant
937 */
938const SIGNED_R11_EAC_Format = 37489; // 0x9271
939
940/**
941 * EAC RG11 UNORM format.
942 *
943 * @type {number}
944 * @constant
945 */
946const RG11_EAC_Format = 37490; // 0x9272
947
948/**
949 * EAC RG11 SNORM format.
950 *
951 * @type {number}
952 * @constant
953 */
954const SIGNED_RG11_EAC_Format = 37491; // 0x9273
955
956/**
957 * ASTC RGBA 4x4 format.
958 *
959 * @type {number}
960 * @constant
961 */
962const RGBA_ASTC_4x4_Format = 37808;
963
964/**
965 * ASTC RGBA 5x4 format.
966 *
967 * @type {number}
968 * @constant
969 */
970const RGBA_ASTC_5x4_Format = 37809;
971
972/**
973 * ASTC RGBA 5x5 format.
974 *
975 * @type {number}
976 * @constant
977 */
978const RGBA_ASTC_5x5_Format = 37810;
979
980/**
981 * ASTC RGBA 6x5 format.
982 *
983 * @type {number}
984 * @constant
985 */
986const RGBA_ASTC_6x5_Format = 37811;
987
988/**
989 * ASTC RGBA 6x6 format.
990 *
991 * @type {number}
992 * @constant
993 */
994const RGBA_ASTC_6x6_Format = 37812;
995
996/**
997 * ASTC RGBA 8x5 format.
998 *
999 * @type {number}
1000 * @constant
1001 */
1002const RGBA_ASTC_8x5_Format = 37813;
1003
1004/**
1005 * ASTC RGBA 8x6 format.
1006 *
1007 * @type {number}
1008 * @constant
1009 */
1010const RGBA_ASTC_8x6_Format = 37814;
1011
1012/**
1013 * ASTC RGBA 8x8 format.
1014 *
1015 * @type {number}
1016 * @constant
1017 */
1018const RGBA_ASTC_8x8_Format = 37815;
1019
1020/**
1021 * ASTC RGBA 10x5 format.
1022 *
1023 * @type {number}
1024 * @constant
1025 */
1026const RGBA_ASTC_10x5_Format = 37816;
1027
1028/**
1029 * ASTC RGBA 10x6 format.
1030 *
1031 * @type {number}
1032 * @constant
1033 */
1034const RGBA_ASTC_10x6_Format = 37817;
1035
1036/**
1037 * ASTC RGBA 10x8 format.
1038 *
1039 * @type {number}
1040 * @constant
1041 */
1042const RGBA_ASTC_10x8_Format = 37818;
1043
1044/**
1045 * ASTC RGBA 10x10 format.
1046 *
1047 * @type {number}
1048 * @constant
1049 */
1050const RGBA_ASTC_10x10_Format = 37819;
1051
1052/**
1053 * ASTC RGBA 12x10 format.
1054 *
1055 * @type {number}
1056 * @constant
1057 */
1058const RGBA_ASTC_12x10_Format = 37820;
1059
1060/**
1061 * ASTC RGBA 12x12 format.
1062 *
1063 * @type {number}
1064 * @constant
1065 */
1066const RGBA_ASTC_12x12_Format = 37821;
1067
1068/**
1069 * BPTC RGBA format.
1070 *
1071 * @type {number}
1072 * @constant
1073 */
1074const RGBA_BPTC_Format = 36492;
1075
1076/**
1077 * BPTC Signed RGB format.
1078 *
1079 * @type {number}
1080 * @constant
1081 */
1082const RGB_BPTC_SIGNED_Format = 36494;
1083
1084/**
1085 * BPTC Unsigned RGB format.
1086 *
1087 * @type {number}
1088 * @constant
1089 */
1090const RGB_BPTC_UNSIGNED_Format = 36495;
1091
1092/**
1093 * RGTC1 Red format.
1094 *
1095 * @type {number}
1096 * @constant
1097 */
1098const RED_RGTC1_Format = 36283;
1099
1100/**
1101 * RGTC1 Signed Red format.
1102 *
1103 * @type {number}
1104 * @constant
1105 */
1106const SIGNED_RED_RGTC1_Format = 36284;
1107
1108/**
1109 * RGTC2 Red Green format.
1110 *
1111 * @type {number}
1112 * @constant
1113 */
1114const RED_GREEN_RGTC2_Format = 36285;
1115
1116/**
1117 * RGTC2 Signed Red Green format.
1118 *
1119 * @type {number}
1120 * @constant
1121 */
1122const SIGNED_RED_GREEN_RGTC2_Format = 36286;
1123
1124/**
1125 * Animations are played once.
1126 *
1127 * @type {number}
1128 * @constant
1129 */
1130const LoopOnce = 2200;
1131
1132/**
1133 * Animations are played with a chosen number of repetitions, each time jumping from
1134 * the end of the clip directly to its beginning.
1135 *
1136 * @type {number}
1137 * @constant
1138 */
1139const LoopRepeat = 2201;
1140
1141/**
1142 * Animations are played with a chosen number of repetitions, alternately playing forward
1143 * and backward.
1144 *
1145 * @type {number}
1146 * @constant
1147 */
1148const LoopPingPong = 2202;
1149
1150/**
1151 * Discrete interpolation mode for keyframe tracks.
1152 *
1153 * @type {number}
1154 * @constant
1155 */
1156const InterpolateDiscrete = 2300;
1157
1158/**
1159 * Linear interpolation mode for keyframe tracks.
1160 *
1161 * @type {number}
1162 * @constant
1163 */
1164const InterpolateLinear = 2301;
1165
1166/**
1167 * Smooth interpolation mode for keyframe tracks.
1168 *
1169 * @type {number}
1170 * @constant
1171 */
1172const InterpolateSmooth = 2302;
1173
1174/**
1175 * Bezier interpolation mode for keyframe tracks.
1176 *
1177 * Uses cubic Bezier curves with explicit 2D control points.
1178 * Requires tangent data to be set on the track.
1179 *
1180 * @type {number}
1181 * @constant
1182 */
1183const InterpolateBezier = 2303;
1184
1185/**
1186 * Zero curvature ending for animations.
1187 *
1188 * @type {number}
1189 * @constant
1190 */
1191const ZeroCurvatureEnding = 2400;
1192
1193/**
1194 * Zero slope ending for animations.
1195 *
1196 * @type {number}
1197 * @constant
1198 */
1199const ZeroSlopeEnding = 2401;
1200
1201/**
1202 * Wrap around ending for animations.
1203 *
1204 * @type {number}
1205 * @constant
1206 */
1207const WrapAroundEnding = 2402;
1208
1209/**
1210 * Default animation blend mode.
1211 *
1212 * @type {number}
1213 * @constant
1214 */
1215const NormalAnimationBlendMode = 2500;
1216
1217/**
1218 * Additive animation blend mode. Can be used to layer motions on top of
1219 * each other to build complex performances from smaller re-usable assets.
1220 *
1221 * @type {number}
1222 * @constant
1223 */
1224const AdditiveAnimationBlendMode = 2501;
1225
1226/**
1227 * For every three vertices draw a single triangle.
1228 *
1229 * @type {number}
1230 * @constant
1231 */
1232const TrianglesDrawMode = 0;
1233
1234/**
1235 * For each vertex draw a triangle from the last three vertices.
1236 *
1237 * @type {number}
1238 * @constant
1239 */
1240const TriangleStripDrawMode = 1;
1241
1242/**
1243 * For each vertex draw a triangle from the first vertex and the last two vertices.
1244 *
1245 * @type {number}
1246 * @constant
1247 */
1248const TriangleFanDrawMode = 2;
1249
1250/**
1251 * The depth value is inverted (1.0 - z) for visualization purposes.
1252 *
1253 * @type {number}
1254 * @constant
1255 */
1256const BasicDepthPacking = 3200;
1257
1258/**
1259 * The depth value is packed into 32 bit RGBA.
1260 *
1261 * @type {number}
1262 * @constant
1263 */
1264const RGBADepthPacking = 3201;
1265
1266/**
1267 * The depth value is packed into 24 bit RGB.
1268 *
1269 * @type {number}
1270 * @constant
1271 */
1272const RGBDepthPacking = 3202;
1273
1274/**
1275 * The depth value is packed into 16 bit RG.
1276 *
1277 * @type {number}
1278 * @constant
1279 */
1280const RGDepthPacking = 3203;
1281
1282/**
1283 * Normal information is relative to the underlying surface.
1284 *
1285 * @type {number}
1286 * @constant
1287 */
1288const TangentSpaceNormalMap = 0;
1289
1290/**
1291 * Normal information is relative to the object orientation.
1292 *
1293 * @type {number}
1294 * @constant
1295 */
1296const ObjectSpaceNormalMap = 1;
1297
1298// Color space string identifiers, matching CSS Color Module Level 4 and WebGPU names where available.
1299
1300/**
1301 * No color space.
1302 *
1303 * @type {string}
1304 * @constant
1305 */
1306const NoColorSpace = '';
1307
1308/**
1309 * sRGB color space.
1310 *
1311 * @type {string}
1312 * @constant
1313 */
1314const SRGBColorSpace = 'srgb';
1315
1316/**
1317 * sRGB-linear color space.
1318 *
1319 * @type {string}
1320 * @constant
1321 */
1322const LinearSRGBColorSpace = 'srgb-linear';
1323
1324/**
1325 * Linear transfer function.
1326 *
1327 * @type {string}
1328 * @constant
1329 */
1330const LinearTransfer = 'linear';
1331
1332/**
1333 * sRGB transfer function.
1334 *
1335 * @type {string}
1336 * @constant
1337 */
1338const SRGBTransfer = 'srgb';
1339
1340/**
1341 * No normal map packing.
1342 *
1343 * @type {string}
1344 * @constant
1345 */
1346const NoNormalPacking = '';
1347
1348/**
1349 * Normal RG packing.
1350 *
1351 * @type {string}
1352 * @constant
1353 */
1354const NormalRGPacking = 'rg';
1355
1356/**
1357 * Normal GA packing.
1358 *
1359 * @type {string}
1360 * @constant
1361 */
1362const NormalGAPacking = 'ga';
1363
1364/**
1365 * Sets the stencil buffer value to `0`.
1366 *
1367 * @type {number}
1368 * @constant
1369 */
1370const ZeroStencilOp = 0;
1371
1372/**
1373 * Keeps the current value.
1374 *
1375 * @type {number}
1376 * @constant
1377 */
1378const KeepStencilOp = 7680;
1379
1380/**
1381 * Sets the stencil buffer value to the specified reference value.
1382 *
1383 * @type {number}
1384 * @constant
1385 */
1386const ReplaceStencilOp = 7681;
1387
1388/**
1389 * Increments the current stencil buffer value. Clamps to the maximum representable unsigned value.
1390 *
1391 * @type {number}
1392 * @constant
1393 */
1394const IncrementStencilOp = 7682;
1395
1396/**
1397 * Decrements the current stencil buffer value. Clamps to `0`.
1398 *
1399 * @type {number}
1400 * @constant
1401 */
1402const DecrementStencilOp = 7683;
1403
1404/**
1405 * Increments the current stencil buffer value. Wraps stencil buffer value to zero when incrementing
1406 * the maximum representable unsigned value.
1407 *
1408 * @type {number}
1409 * @constant
1410 */
1411const IncrementWrapStencilOp = 34055;
1412
1413/**
1414 * Decrements the current stencil buffer value. Wraps stencil buffer value to the maximum representable
1415 * unsigned value when decrementing a stencil buffer value of `0`.
1416 *
1417 * @type {number}
1418 * @constant
1419 */
1420const DecrementWrapStencilOp = 34056;
1421
1422/**
1423 * Inverts the current stencil buffer value bitwise.
1424 *
1425 * @type {number}
1426 * @constant
1427 */
1428const InvertStencilOp = 5386;
1429
1430/**
1431 * Will never return true.
1432 *
1433 * @type {number}
1434 * @constant
1435 */
1436const NeverStencilFunc = 512;
1437
1438/**
1439 * Will return true if the stencil reference value is less than the current stencil value.
1440 *
1441 * @type {number}
1442 * @constant
1443 */
1444const LessStencilFunc = 513;
1445
1446/**
1447 * Will return true if the stencil reference value is equal to the current stencil value.
1448 *
1449 * @type {number}
1450 * @constant
1451 */
1452const EqualStencilFunc = 514;
1453
1454/**
1455 * Will return true if the stencil reference value is less than or equal to the current stencil value.
1456 *
1457 * @type {number}
1458 * @constant
1459 */
1460const LessEqualStencilFunc = 515;
1461
1462/**
1463 * Will return true if the stencil reference value is greater than the current stencil value.
1464 *
1465 * @type {number}
1466 * @constant
1467 */
1468const GreaterStencilFunc = 516;
1469
1470/**
1471 * Will return true if the stencil reference value is not equal to the current stencil value.
1472 *
1473 * @type {number}
1474 * @constant
1475 */
1476const NotEqualStencilFunc = 517;
1477
1478/**
1479 * Will return true if the stencil reference value is greater than or equal to the current stencil value.
1480 *
1481 * @type {number}
1482 * @constant
1483 */
1484const GreaterEqualStencilFunc = 518;
1485
1486/**
1487 * Will always return true.
1488 *
1489 * @type {number}
1490 * @constant
1491 */
1492const AlwaysStencilFunc = 519;
1493
1494/**
1495 * Never pass.
1496 *
1497 * @type {number}
1498 * @constant
1499 */
1500const NeverCompare = 512;
1501
1502/**
1503 * Pass if the incoming value is less than the texture value.
1504 *
1505 * @type {number}
1506 * @constant
1507 */
1508const LessCompare = 513;
1509
1510/**
1511 * Pass if the incoming value equals the texture value.
1512 *
1513 * @type {number}
1514 * @constant
1515 */
1516const EqualCompare = 514;
1517
1518/**
1519 * Pass if the incoming value is less than or equal to the texture value.
1520 *
1521 * @type {number}
1522 * @constant
1523 */
1524const LessEqualCompare = 515;
1525
1526/**
1527 * Pass if the incoming value is greater than the texture value.
1528 *
1529 * @type {number}
1530 * @constant
1531 */
1532const GreaterCompare = 516;
1533
1534/**
1535 * Pass if the incoming value is not equal to the texture value.
1536 *
1537 * @type {number}
1538 * @constant
1539 */
1540const NotEqualCompare = 517;
1541
1542/**
1543 * Pass if the incoming value is greater than or equal to the texture value.
1544 *
1545 * @type {number}
1546 * @constant
1547 */
1548const GreaterEqualCompare = 518;
1549
1550/**
1551 * Always pass.
1552 *
1553 * @type {number}
1554 * @constant
1555 */
1556const AlwaysCompare = 519;
1557
1558/**
1559 * The contents are intended to be specified once by the application, and used many
1560 * times as the source for drawing and image specification commands.
1561 *
1562 * @type {number}
1563 * @constant
1564 */
1565const StaticDrawUsage = 35044;
1566
1567/**
1568 * The contents are intended to be respecified repeatedly by the application, and
1569 * used many times as the source for drawing and image specification commands.
1570 *
1571 * @type {number}
1572 * @constant
1573 */
1574const DynamicDrawUsage = 35048;
1575
1576/**
1577 * The contents are intended to be specified once by the application, and used at most
1578 * a few times as the source for drawing and image specification commands.
1579 *
1580 * @type {number}
1581 * @constant
1582 */
1583const StreamDrawUsage = 35040;
1584
1585/**
1586 * The contents are intended to be specified once by reading data from the 3D API, and queried
1587 * many times by the application.
1588 *
1589 * @type {number}
1590 * @constant
1591 */
1592const StaticReadUsage = 35045;
1593
1594/**
1595 * The contents are intended to be respecified repeatedly by reading data from the 3D API, and queried
1596 * many times by the application.
1597 *
1598 * @type {number}
1599 * @constant
1600 */
1601const DynamicReadUsage = 35049;
1602
1603/**
1604 * The contents are intended to be specified once by reading data from the 3D API, and queried at most
1605 * a few times by the application
1606 *
1607 * @type {number}
1608 * @constant
1609 */
1610const StreamReadUsage = 35041;
1611
1612/**
1613 * The contents are intended to be specified once by reading data from the 3D API, and used many times as
1614 * the source for WebGL drawing and image specification commands.
1615 *
1616 * @type {number}
1617 * @constant
1618 */
1619const StaticCopyUsage = 35046;
1620
1621/**
1622 * The contents are intended to be respecified repeatedly by reading data from the 3D API, and used many times
1623 * as the source for WebGL drawing and image specification commands.
1624 *
1625 * @type {number}
1626 * @constant
1627 */
1628const DynamicCopyUsage = 35050;
1629
1630/**
1631 * The contents are intended to be specified once by reading data from the 3D API, and used at most a few times
1632 * as the source for WebGL drawing and image specification commands.
1633 *
1634 * @type {number}
1635 * @constant
1636 */
1637const StreamCopyUsage = 35042;
1638
1639/**
1640 * GLSL 1 shader code.
1641 *
1642 * @type {string}
1643 * @constant
1644 */
1645const GLSL1 = '100';
1646
1647/**
1648 * GLSL 3 shader code.
1649 *
1650 * @type {string}
1651 * @constant
1652 */
1653const GLSL3 = '300 es';
1654
1655/**
1656 * WebGL coordinate system.
1657 *
1658 * @type {number}
1659 * @constant
1660 */
1661const WebGLCoordinateSystem = 2000;
1662
1663/**
1664 * WebGPU coordinate system.
1665 *
1666 * @type {number}
1667 * @constant
1668 */
1669const WebGPUCoordinateSystem = 2001;
1670
1671/**
1672 * Represents the different timestamp query types.
1673 *
1674 * @type {ConstantsTimestampQuery}
1675 * @constant
1676 */
1677const TimestampQuery = {
1678	COMPUTE: 'compute',
1679	RENDER: 'render'
1680};
1681
1682/**
1683 * Represents mouse buttons and interaction types in context of controls.
1684 *
1685 * @type {ConstantsInterpolationSamplingType}
1686 * @constant
1687 */
1688const InterpolationSamplingType = {
1689	PERSPECTIVE: 'perspective',
1690	LINEAR: 'linear',
1691	FLAT: 'flat'
1692};
1693
1694/**
1695 * Represents the different interpolation sampling modes.
1696 *
1697 * @type {ConstantsInterpolationSamplingMode}
1698 * @constant
1699 */
1700const InterpolationSamplingMode = {
1701	NORMAL: 'normal',
1702	CENTROID: 'centroid',
1703	SAMPLE: 'sample',
1704	FIRST: 'first',
1705	EITHER: 'either'
1706};
1707
1708/**
1709 * Compatibility flags for features that may not be supported across all platforms.
1710 *
1711 * @type {Object}
1712 * @constant
1713 */
1714const Compatibility = {
1715	TEXTURE_COMPARE: 'depthTextureCompare'
1716};
1717
1718/**
1719 * Represents the refresh types of render objects.
1720 *
1721 * @type {ConstantsRenderObjectRefreshType}
1722 * @constant
1723 */
1724const RenderObjectRefreshType = {
1725	NONE: 0,
1726	SHARED: 1,
1727	FULL: 2
1728};
1729
1730/**
1731 * This type represents mouse buttons and interaction types in context of controls.
1732 *
1733 * @typedef {Object} ConstantsMouse
1734 * @property {number} MIDDLE - The left mouse button.
1735 * @property {number} LEFT - The middle mouse button.
1736 * @property {number} RIGHT - The right mouse button.
1737 * @property {number} ROTATE - A rotate interaction.
1738 * @property {number} DOLLY - A dolly interaction.
1739 * @property {number} PAN - A pan interaction.
1740 **/
1741
1742/**
1743 * This type represents touch interaction types in context of controls.
1744 *
1745 * @typedef {Object} ConstantsTouch
1746 * @property {number} ROTATE - A rotate interaction.
1747 * @property {number} PAN - A pan interaction.
1748 * @property {number} DOLLY_PAN - The dolly-pan interaction.
1749 * @property {number} DOLLY_ROTATE - A dolly-rotate interaction.
1750 **/
1751
1752/**
1753 * This type represents the different timestamp query types.
1754 *
1755 * @typedef {Object} ConstantsTimestampQuery
1756 * @property {string} COMPUTE - A `compute` timestamp query.
1757 * @property {string} RENDER - A `render` timestamp query.
1758 **/
1759
1760/**
1761 * Represents the different interpolation sampling types.
1762 *
1763 * @typedef {Object} ConstantsInterpolationSamplingType
1764 * @property {string} PERSPECTIVE - Perspective-correct interpolation.
1765 * @property {string} LINEAR - Linear interpolation.
1766 * @property {string} FLAT - Flat interpolation.
1767 */
1768
1769/**
1770 * Represents the different interpolation sampling modes.
1771 *
1772 * @typedef {Object} ConstantsInterpolationSamplingMode
1773 * @property {string} NORMAL - Normal sampling mode.
1774 * @property {string} CENTROID - Centroid sampling mode.
1775 * @property {string} SAMPLE - Sample-specific sampling mode.
1776 * @property {string} FIRST - Flat interpolation using the first vertex.
1777 * @property {string} EITHER - Flat interpolation using either vertex.
1778 */
1779
1780/**
1781 * Represents the refresh types of render objects.
1782 *
1783 * @typedef {Object} ConstantsRenderObjectRefreshType
1784 * @property {number} NONE - No refresh required.
1785 * @property {number} SHARED - Only shared uniform buffers require an update.
1786 * @property {number} FULL - The render object requires a full refresh.
1787 */
1788
1789/**
1790 * Checks if an array contains values that require Uint32 representation.
1791 *
1792 * This function determines whether the array contains any values >= 65535,
1793 * which would require a Uint32Array rather than a Uint16Array for proper storage.
1794 * The function iterates from the end of the array, assuming larger values are
1795 * typically located at the end.
1796 *
1797 * @private
1798 * @param {Array<number>} array - The array to check.
1799 * @return {boolean} True if the array contains values >= 65535, false otherwise.
1800 */
1801function arrayNeedsUint32( array ) {
1802
1803	// assumes larger values usually on last
1804
1805	for ( let i = array.length - 1; i >= 0; -- i ) {
1806
1807		if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
1808
1809	}
1810
1811	return false;
1812
1813}
1814
1815/**
1816 * Map of typed array constructor names to their constructors.
1817 * This mapping enables dynamic creation of typed arrays based on string type names.
1818 *
1819 * @private
1820 * @constant
1821 * @type {Object<string, TypedArrayConstructor>}
1822 */
1823const TYPED_ARRAYS = {
1824	Int8Array: Int8Array,
1825	Uint8Array: Uint8Array,
1826	Uint8ClampedArray: Uint8ClampedArray,
1827	Int16Array: Int16Array,
1828	Uint16Array: Uint16Array,
1829	Int32Array: Int32Array,
1830	Uint32Array: Uint32Array,
1831	Float32Array: Float32Array,
1832	Float64Array: Float64Array
1833};
1834
1835/**
1836 * Creates a typed array of the specified type from the given buffer.
1837 *
1838 * @private
1839 * @param {string} type - The name of the typed array type (e.g., 'Float32Array', 'Uint16Array').
1840 * @param {ArrayBuffer} buffer - The buffer to create the typed array from.
1841 * @return {TypedArray} A new typed array of the specified type.
1842 */
1843function getTypedArray( type, buffer ) {
1844
1845	return new TYPED_ARRAYS[ type ]( buffer );
1846
1847}
1848
1849/**
1850 * Returns `true` if the given object is a typed array.
1851 *
1852 * @param {any} array - The object to check.
1853 * @return {boolean} Whether the given object is a typed array.
1854 */
1855function isTypedArray( array ) {
1856
1857	return ArrayBuffer.isView( array ) && ! ( array instanceof DataView );
1858
1859}
1860
1861/**
1862 * Creates an XHTML element with the specified tag name.
1863 *
1864 * This function uses the XHTML namespace to create DOM elements,
1865 * ensuring proper element creation in XML-based contexts.
1866 *
1867 * @private
1868 * @param {string} name - The tag name of the element to create (e.g., 'canvas', 'div').
1869 * @return {HTMLElement} The created XHTML element.
1870 */
1871function createElementNS( name ) {
1872
1873	return document.createElementNS( 'http://www.w3.org/1999/xhtml', name );
1874
1875}
1876
1877/**
1878 * Creates a canvas element configured for block display.
1879 *
1880 * This is a convenience function that creates a canvas element with
1881 * display style set to 'block', which is commonly used in three.js
1882 * rendering contexts to avoid inline element spacing issues.
1883 *
1884 * @return {HTMLCanvasElement} A canvas element with display set to 'block'.
1885 */
1886function createCanvasElement() {
1887
1888	const canvas = createElementNS( 'canvas' );
1889	canvas.style.display = 'block';
1890	return canvas;
1891
1892}
1893
1894/**
1895 * Internal cache for tracking warning messages to prevent duplicate warnings.
1896 *
1897 * @private
1898 * @type {Object<string, boolean>}
1899 */
1900const _cache = {};
1901
1902/**
1903 * Custom console function handler for intercepting log, warn, and error calls.
1904 *
1905 * @private
1906 * @type {Function|null}
1907 */
1908let _setConsoleFunction = null;
1909
1910/**
1911 * Sets a custom function to handle console output.
1912 *
1913 * This allows external code to intercept and handle console.log, console.warn,
1914 * and console.error calls made by three.js, which is useful for custom logging,
1915 * testing, or debugging workflows.
1916 *
1917 * @param {Function} fn - The function to handle console output. Should accept
1918 *                        (type, message, ...params) where type is 'log', 'warn', or 'error'.
1919 */
1920function setConsoleFunction( fn ) {
1921
1922	_setConsoleFunction = fn;
1923
1924}
1925
1926/**
1927 * Gets the currently set custom console function.
1928 *
1929 * @return {Function|null} The custom console function, or null if not set.
1930 */
1931function getConsoleFunction() {
1932
1933	return _setConsoleFunction;
1934
1935}
1936
1937/**
1938 * Logs an informational message with the 'THREE.' prefix.
1939 *
1940 * If a custom console function is set via setConsoleFunction(), it will be used
1941 * instead of the native console.log. The first parameter is treated as the
1942 * method name and is automatically prefixed with 'THREE.'.
1943 *
1944 * @param {...any} params - The message components. The first param is used as
1945 *                          the method name and prefixed with 'THREE.'.
1946 */
1947function log( ...params ) {
1948
1949	const message = 'THREE.' + params.shift();
1950
1951	if ( _setConsoleFunction ) {
1952
1953		_setConsoleFunction( 'log', message, ...params );
1954
1955	} else {
1956
1957		console.log( message, ...params );
1958
1959	}
1960
1961}
1962
1963/**
1964 * Enhances log/warn/error messages related to TSL.
1965 *
1966 * @param {Array<any>} params - The original message parameters.
1967 * @returns {Array<any>} The filtered and enhanced message parameters.
1968 */
1969function enhanceLogMessage( params ) {
1970
1971	const message = params[ 0 ];
1972
1973	if ( typeof message === 'string' && message.startsWith( 'TSL:' ) ) {
1974
1975		const stackTrace = params[ 1 ];
1976
1977		if ( stackTrace && stackTrace.isStackTrace ) {
1978
1979			params[ 0 ] += ' ' + stackTrace.getLocation();
1980
1981		} else {
1982
1983			params[ 1 ] = 'Stack trace not available. Enable "THREE.Node.captureStackTrace" to capture stack traces.';
1984
1985		}
1986
1987	}
1988
1989	return params;
1990
1991}
1992
1993/**
1994 * Logs a warning message with the 'THREE.' prefix.
1995 *
1996 * If a custom console function is set via setConsoleFunction(), it will be used
1997 * instead of the native console.warn. The first parameter is treated as the
1998 * method name and is automatically prefixed with 'THREE.'.
1999 *
2000 * @param {...any} params - The message components. The first param is used as
2001 *                          the method name and prefixed with 'THREE.'.
2002 */
2003function warn( ...params ) {
2004
2005	params = enhanceLogMessage( params );
2006
2007	const message = 'THREE.' + params.shift();
2008
2009	if ( _setConsoleFunction ) {
2010
2011		_setConsoleFunction( 'warn', message, ...params );
2012
2013	} else {
2014
2015		const stackTrace = params[ 0 ];
2016
2017		if ( stackTrace && stackTrace.isStackTrace ) {
2018
2019			console.warn( stackTrace.getError( message ) );
2020
2021		} else {
2022
2023			console.warn( message, ...params );
2024
2025		}
2026
2027	}
2028
2029}
2030
2031/**
2032 * Logs an error message with the 'THREE.' prefix.
2033 *
2034 * If a custom console function is set via setConsoleFunction(), it will be used
2035 * instead of the native console.error. The first parameter is treated as the
2036 * method name and is automatically prefixed with 'THREE.'.
2037 *
2038 * @param {...any} params - The message components. The first param is used as
2039 *                          the method name and prefixed with 'THREE.'.
2040 */
2041function error( ...params ) {
2042
2043	params = enhanceLogMessage( params );
2044
2045	const message = 'THREE.' + params.shift();
2046
2047	if ( _setConsoleFunction ) {
2048
2049		_setConsoleFunction( 'error', message, ...params );
2050
2051	} else {
2052
2053		const stackTrace = params[ 0 ];
2054
2055		if ( stackTrace && stackTrace.isStackTrace ) {
2056
2057			console.error( stackTrace.getError( message ) );
2058
2059		} else {
2060
2061			console.error( message, ...params );
2062
2063		}
2064
2065	}
2066
2067}
2068
2069/**
2070 * Logs a warning message only once, preventing duplicate warnings.
2071 *
2072 * This function maintains an internal cache of warning messages and will only
2073 * output each unique warning message once. Useful for warnings that may be
2074 * triggered repeatedly but should only be shown to the user once.
2075 *
2076 * @param {...any} params - The warning message components.
2077 */
2078function warnOnce( ...params ) {
2079
2080	const message = params.join( ' ' );
2081
2082	if ( message in _cache ) return;
2083
2084	_cache[ message ] = true;
2085
2086	warn( ...params );
2087
2088}
2089
2090/**
2091 * Yields execution to the main thread to allow rendering and other tasks.
2092 * Uses scheduler.yield() when available (Chrome 115+), falls back to requestAnimationFrame.
2093 *
2094 * @return {Promise<void>}
2095 */
2096function yieldToMain() {
2097
2098	if ( typeof self !== 'undefined' && typeof self.scheduler !== 'undefined' && typeof self.scheduler.yield !== 'undefined' ) {
2099
2100		return self.scheduler.yield();
2101
2102	}
2103
2104	return new Promise( resolve => {
2105
2106		requestAnimationFrame( resolve );
2107
2108	} );
2109
2110}
2111
2112/**
2113 * Asynchronously probes for WebGL sync object completion.
2114 *
2115 * This function creates a promise that resolves when the WebGL sync object
2116 * signals completion or rejects if the sync operation fails. It uses polling
2117 * at the specified interval to check the sync status without blocking the
2118 * main thread. This is useful for GPU-CPU synchronization in WebGL contexts.
2119 *
2120 * @private
2121 * @param {WebGL2RenderingContext} gl - The WebGL rendering context.
2122 * @param {WebGLSync} sync - The WebGL sync object to wait for.
2123 * @param {number} interval - The polling interval in milliseconds.
2124 * @return {Promise<void>} A promise that resolves when the sync completes or rejects if it fails.
2125 */
2126function probeAsync( gl, sync, interval ) {
2127
2128	return new Promise( function ( resolve, reject ) {
2129
2130		function probe() {
2131
2132			switch ( gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ) ) {
2133
2134				case gl.WAIT_FAILED:
2135					reject();
2136					break;
2137
2138				case gl.TIMEOUT_EXPIRED:
2139					setTimeout( probe, interval );
2140					break;
2141
2142				default:
2143					resolve();
2144
2145			}
2146
2147		}
2148
2149		setTimeout( probe, interval );
2150
2151	} );
2152
2153}
2154
2155/**
2156 * Used to select the correct depth functions
2157 * when reversed depth buffer is used.
2158 *
2159 * @private
2160 * @type {Object}
2161 */
2162const ReversedDepthFuncs = {
2163	[ NeverDepth ]: AlwaysDepth,
2164	[ LessDepth ]: GreaterDepth,
2165	[ EqualDepth ]: NotEqualDepth,
2166	[ LessEqualDepth ]: GreaterEqualDepth,
2167
2168	[ AlwaysDepth ]: NeverDepth,
2169	[ GreaterDepth ]: LessDepth,
2170	[ NotEqualDepth ]: EqualDepth,
2171	[ GreaterEqualDepth ]: LessEqualDepth,
2172};
2173
2174/**
2175 * This modules allows to dispatch event objects on custom JavaScript objects.
2176 *
2177 * Main repository: [eventdispatcher.js](https://github.com/mrdoob/eventdispatcher.js/)
2178 *
2179 * Code Example:
2180 * ```js
2181 * class Car extends EventDispatcher {
2182 * 	start() {
2183 *		this.dispatchEvent( { type: 'start', message: 'vroom vroom!' } );
2184 *	}
2185 *};
2186 *
2187 * // Using events with the custom object
2188 * const car = new Car();
2189 * car.addEventListener( 'start', function ( event ) {
2190 * 	alert( event.message );
2191 * } );
2192 *
2193 * car.start();
2194 * ```
2195 */
2196class EventDispatcher {
2197
2198	/**
2199	 * Adds the given event listener to the given event type.
2200	 *
2201	 * @param {string} type - The type of event to listen to.
2202	 * @param {Function} listener - The function that gets called when the event is fired.
2203	 */
2204	addEventListener( type, listener ) {
2205
2206		if ( this._listeners === undefined ) this._listeners = {};
2207
2208		const listeners = this._listeners;
2209
2210		if ( listeners[ type ] === undefined ) {
2211
2212			listeners[ type ] = [];
2213
2214		}
2215
2216		if ( listeners[ type ].indexOf( listener ) === -1 ) {
2217
2218			listeners[ type ].push( listener );
2219
2220		}
2221
2222	}
2223
2224	/**
2225	 * Returns `true` if the given event listener has been added to the given event type.
2226	 *
2227	 * @param {string} type - The type of event.
2228	 * @param {Function} listener - The listener to check.
2229	 * @return {boolean} Whether the given event listener has been added to the given event type.
2230	 */
2231	hasEventListener( type, listener ) {
2232
2233		const listeners = this._listeners;
2234
2235		if ( listeners === undefined ) return false;
2236
2237		return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== -1;
2238
2239	}
2240
2241	/**
2242	 * Removes the given event listener from the given event type.
2243	 *
2244	 * @param {string} type - The type of event.
2245	 * @param {Function} listener - The listener to remove.
2246	 */
2247	removeEventListener( type, listener ) {
2248
2249		const listeners = this._listeners;
2250
2251		if ( listeners === undefined ) return;
2252
2253		const listenerArray = listeners[ type ];
2254
2255		if ( listenerArray !== undefined ) {
2256
2257			const index = listenerArray.indexOf( listener );
2258
2259			if ( index !== -1 ) {
2260
2261				listenerArray.splice( index, 1 );
2262
2263			}
2264
2265		}
2266
2267	}
2268
2269	/**
2270	 * Dispatches an event object.
2271	 *
2272	 * @param {Object} event - The event that gets fired.
2273	 */
2274	dispatchEvent( event ) {
2275
2276		const listeners = this._listeners;
2277
2278		if ( listeners === undefined ) return;
2279
2280		const listenerArray = listeners[ event.type ];
2281
2282		if ( listenerArray !== undefined ) {
2283
2284			event.target = this;
2285
2286			// Make a copy, in case listeners are removed while iterating.
2287			const array = listenerArray.slice( 0 );
2288
2289			for ( let i = 0, l = array.length; i < l; i ++ ) {
2290
2291				array[ i ].call( this, event );
2292
2293			}
2294
2295			event.target = null;
2296
2297		}
2298
2299	}
2300
2301}
2302
2303const _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' ];
2304
2305let _seed = 1234567;
2306
2307
2308const DEG2RAD = Math.PI / 180;
2309const RAD2DEG = 180 / Math.PI;
2310
2311/**
2312 * Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier)
2313 * (universally unique identifier).
2314 *
2315 * @return {string} The UUID.
2316 */
2317function generateUUID() {
2318
2319	// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
2320
2321	const d0 = Math.random() * 0xffffffff | 0;
2322	const d1 = Math.random() * 0xffffffff | 0;
2323	const d2 = Math.random() * 0xffffffff | 0;
2324	const d3 = Math.random() * 0xffffffff | 0;
2325	const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
2326			_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
2327			_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
2328			_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
2329
2330	// .toLowerCase() here flattens concatenated strings to save heap memory space.
2331	return uuid.toLowerCase();
2332
2333}
2334
2335/**
2336 * Clamps the given value between min and max.
2337 *
2338 * @param {number} value - The value to clamp.
2339 * @param {number} min - The min value.
2340 * @param {number} max - The max value.
2341 * @return {number} The clamped value.
2342 */
2343function clamp( value, min, max ) {
2344
2345	return Math.max( min, Math.min( max, value ) );
2346
2347}
2348
2349/**
2350 * Computes the Euclidean modulo of the given parameters that
2351 * is `( ( n % m ) + m ) % m`.
2352 *
2353 * @param {number} n - The first parameter.
2354 * @param {number} m - The second parameter.
2355 * @return {number} The Euclidean modulo.
2356 */
2357function euclideanModulo( n, m ) {
2358
2359	// https://en.wikipedia.org/wiki/Modulo_operation
2360
2361	return ( ( n % m ) + m ) % m;
2362
2363}
2364
2365/**
2366 * Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>`
2367 * for the given value. `a2` must be greater than `a1`.
2368 *
2369 * @param {number} x - The value to be mapped.
2370 * @param {number} a1 - Minimum value for range A.
2371 * @param {number} a2 - Maximum value for range A.
2372 * @param {number} b1 - Minimum value for range B.
2373 * @param {number} b2 - Maximum value for range B.
2374 * @return {number} The mapped value.
2375 */
2376function mapLinear( x, a1, a2, b1, b2 ) {
2377
2378	return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
2379
2380}
2381
2382/**
2383 * Returns the percentage in the closed interval `[0, 1]` of the given value
2384 * between the start and end point.
2385 *
2386 * @param {number} x - The start point
2387 * @param {number} y - The end point.
2388 * @param {number} value - A value between start and end.
2389 * @return {number} The interpolation factor.
2390 */
2391function inverseLerp( x, y, value ) {
2392
2393	// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
2394
2395	if ( x !== y ) {
2396
2397		return ( value - x ) / ( y - x );
2398
2399	} else {
2400
2401		return 0;
2402
2403	}
2404
2405}
2406
2407/**
2408 * Returns a value linearly interpolated from two known points based on the given interval -
2409 * `t = 0` will return `x` and `t = 1` will return `y`.
2410 *
2411 * @param {number} x - The start point
2412 * @param {number} y - The end point.
2413 * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
2414 * @return {number} The interpolated value.
2415 */
2416function lerp( x, y, t ) {
2417
2418	return ( 1 - t ) * x + t * y;
2419
2420}
2421
2422/**
2423 * Smoothly interpolate a number from `x` to `y` in  a spring-like manner using a delta
2424 * time to maintain frame rate independent movement. For details, see
2425 * [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/).
2426 *
2427 * @param {number} x - The current point.
2428 * @param {number} y - The target point.
2429 * @param {number} lambda - A higher lambda value will make the movement more sudden,
2430 * and a lower value will make the movement more gradual.
2431 * @param {number} dt - Delta time in seconds.
2432 * @return {number} The interpolated value.
2433 */
2434function damp( x, y, lambda, dt ) {
2435
2436	return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
2437
2438}
2439
2440/**
2441 * Returns a value that alternates between `0` and the given `length` parameter.
2442 *
2443 * @param {number} x - The value to pingpong.
2444 * @param {number} [length=1] - The positive value the function will pingpong to.
2445 * @return {number} The alternated value.
2446 */
2447function pingpong( x, length = 1 ) {
2448
2449	// https://www.desmos.com/calculator/vcsjnyz7x4
2450
2451	return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
2452
2453}
2454
2455/**
2456 * Returns a value in the range `[0,1]` that represents the percentage that `x` has
2457 * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to
2458 * the `min` and `max`.
2459 *
2460 * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details.
2461 *
2462 * @param {number} x - The value to evaluate based on its position between `min` and `max`.
2463 * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`.
2464 * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`.
2465 * @return {number} The alternated value.
2466 */
2467function smoothstep( x, min, max ) {
2468
2469	if ( x <= min ) return 0;
2470	if ( x >= max ) return 1;
2471
2472	x = ( x - min ) / ( max - min );
2473
2474	return x * x * ( 3 - 2 * x );
2475
2476}
2477
2478/**
2479 * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations)
2480 * that has zero 1st and 2nd order derivatives at `x=0` and `x=1`.
2481 *
2482 * @param {number} x - The value to evaluate based on its position between `min` and `max`.
2483 * @param {number} min - The min value. Any `x` value below `min` will be `0`. `min` must be lower than `max`.
2484 * @param {number} max - The max value. Any `x` value above `max` will be `1`. `max` must be greater than `min`.
2485 * @return {number} The alternated value.
2486 */
2487function smootherstep( x, min, max ) {
2488
2489	if ( x <= min ) return 0;
2490	if ( x >= max ) return 1;
2491
2492	x = ( x - min ) / ( max - min );
2493
2494	return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
2495
2496}
2497
2498/**
2499 * Returns a random integer from `<low, high>` interval.
2500 *
2501 * @param {number} low - The lower value boundary.
2502 * @param {number} high - The upper value boundary
2503 * @return {number} A random integer.
2504 */
2505function randInt( low, high ) {
2506
2507	return low + Math.floor( Math.random() * ( high - low + 1 ) );
2508
2509}
2510
2511/**
2512 * Returns a random float from `<low, high>` interval.
2513 *
2514 * @param {number} low - The lower value boundary.
2515 * @param {number} high - The upper value boundary
2516 * @return {number} A random float.
2517 */
2518function randFloat( low, high ) {
2519
2520	return low + Math.random() * ( high - low );
2521
2522}
2523
2524/**
2525 * Returns a random integer from `<-range/2, range/2>` interval.
2526 *
2527 * @param {number} range - Defines the value range.
2528 * @return {number} A random float.
2529 */
2530function randFloatSpread( range ) {
2531
2532	return range * ( 0.5 - Math.random() );
2533
2534}
2535
2536/**
2537 * Returns a deterministic pseudo-random float in the interval `[0, 1]`.
2538 *
2539 * @param {number} [s] - The integer seed.
2540 * @return {number} A random float.
2541 */
2542function seededRandom( s ) {
2543
2544	if ( s !== undefined ) _seed = s;
2545
2546	// Mulberry32 generator
2547
2548	let t = _seed += 0x6D2B79F5;
2549
2550	t = Math.imul( t ^ t >>> 15, t | 1 );
2551
2552	t ^= t + Math.imul( t ^ t >>> 7, t | 61 );
2553
2554	return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296;
2555
2556}
2557
2558/**
2559 * Converts degrees to radians.
2560 *
2561 * @param {number} degrees - A value in degrees.
2562 * @return {number} The converted value in radians.
2563 */
2564function degToRad( degrees ) {
2565
2566	return degrees * DEG2RAD;
2567
2568}
2569
2570/**
2571 * Converts radians to degrees.
2572 *
2573 * @param {number} radians - A value in radians.
2574 * @return {number} The converted value in degrees.
2575 */
2576function radToDeg( radians ) {
2577
2578	return radians * RAD2DEG;
2579
2580}
2581
2582/**
2583 * Returns `true` if the given integer is a power of two.
2584 *
2585 * @param {number} value - The value to check.
2586 * @return {boolean} Whether the given integer is a power of two or not.
2587 */
2588function isPowerOfTwo( value ) {
2589
2590	return value > 0 && Number.isInteger( value ) && 2 ** Math.round( Math.log2( value ) ) === value;
2591
2592}
2593
2594/**
2595 * Returns the smallest power of two that is greater than or equal to the given number.
2596 *
2597 * @param {number} value - The value to find a POT for. Must be greater than `0`.
2598 * @return {number} The smallest power of two that is greater than or equal to the given number.
2599 */
2600function ceilPowerOfTwo( value ) {
2601
2602	return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
2603
2604}
2605
2606/**
2607 * Returns the largest power of two that is less than or equal to the given number.
2608 *
2609 * @param {number} value - The value to find a POT for. Must be greater than `0`.
2610 * @return {number} The largest power of two that is less than or equal to the given number.
2611 */
2612function floorPowerOfTwo( value ) {
2613
2614	return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
2615
2616}
2617
2618/**
2619 * Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles)
2620 * defined by the given angles and order.
2621 *
2622 * Rotations are applied to the axes in the order specified by order:
2623 * rotation by angle `a` is applied first, then by angle `b`, then by angle `c`.
2624 *
2625 * @param {Quaternion} q - The quaternion to set.
2626 * @param {number} a - The rotation applied to the first axis, in radians.
2627 * @param {number} b - The rotation applied to the second axis, in radians.
2628 * @param {number} c - The rotation applied to the third axis, in radians.
2629 * @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order.
2630 */
2631function setQuaternionFromProperEuler( q, a, b, c, order ) {
2632
2633	const cos = Math.cos;
2634	const sin = Math.sin;
2635
2636	const c2 = cos( b / 2 );
2637	const s2 = sin( b / 2 );
2638
2639	const c13 = cos( ( a + c ) / 2 );
2640	const s13 = sin( ( a + c ) / 2 );
2641
2642	const c1_3 = cos( ( a - c ) / 2 );
2643	const s1_3 = sin( ( a - c ) / 2 );
2644
2645	const c3_1 = cos( ( c - a ) / 2 );
2646	const s3_1 = sin( ( c - a ) / 2 );
2647
2648	switch ( order ) {
2649
2650		case 'XYX':
2651			q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
2652			break;
2653
2654		case 'YZY':
2655			q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
2656			break;
2657
2658		case 'ZXZ':
2659			q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
2660			break;
2661
2662		case 'XZX':
2663			q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
2664			break;
2665
2666		case 'YXY':
2667			q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
2668			break;
2669
2670		case 'ZYZ':
2671			q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
2672			break;
2673
2674		default:
2675			warn( 'MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
2676
2677	}
2678
2679}
2680
2681/**
2682 * Denormalizes the given value according to the given typed array.
2683 *
2684 * @param {number} value - The value to denormalize.
2685 * @param {TypedArray} array - The typed array that defines the data type of the value.
2686 * @return {number} The denormalize (float) value in the range `[0,1]`.
2687 */
2688function denormalize( value, array ) {
2689
2690	switch ( array.constructor ) {
2691
2692		case Float32Array:
2693
2694			return value;
2695
2696		case Uint32Array:
2697
2698			return value / 4294967295.0;
2699
2700		case Uint16Array:
2701
2702			return value / 65535.0;
2703
2704		case Uint8Array:
2705		case Uint8ClampedArray:
2706
2707			return value / 255.0;
2708
2709		case Int32Array:
2710
2711			return Math.max( value / 2147483647.0, -1 );
2712
2713		case Int16Array:
2714
2715			return Math.max( value / 32767.0, -1 );
2716
2717		case Int8Array:
2718
2719			return Math.max( value / 127.0, -1 );
2720
2721		default:
2722
2723			throw new Error( 'THREE.MathUtils: Invalid component type.' );
2724
2725	}
2726
2727}
2728
2729/**
2730 * Normalizes the given value according to the given typed array.
2731 *
2732 * @param {number} value - The float value in the range `[0,1]` to normalize.
2733 * @param {TypedArray} array - The typed array that defines the data type of the value.
2734 * @return {number} The normalize value.
2735 */
2736function normalize( value, array ) {
2737
2738	switch ( array.constructor ) {
2739
2740		case Float32Array:
2741
2742			return value;
2743
2744		case Uint32Array:
2745
2746			return Math.round( value * 4294967295.0 );
2747
2748		case Uint16Array:
2749
2750			return Math.round( value * 65535.0 );
2751
2752		case Uint8Array:
2753		case Uint8ClampedArray:
2754
2755			return Math.round( value * 255.0 );
2756
2757		case Int32Array:
2758
2759			return Math.round( value * 2147483647.0 );
2760
2761		case Int16Array:
2762
2763			return Math.round( value * 32767.0 );
2764
2765		case Int8Array:
2766
2767			return Math.round( value * 127.0 );
2768
2769		default:
2770
2771			throw new Error( 'THREE.MathUtils: Invalid component type.' );
2772
2773	}
2774
2775}
2776
2777/**
2778 * @class
2779 * @classdesc A collection of math utility functions.
2780 * @hideconstructor
2781 */
2782const MathUtils = {
2783	DEG2RAD: DEG2RAD,
2784	RAD2DEG: RAD2DEG,
2785	/**
2786	 * Generate a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier)
2787	 * (universally unique identifier).
2788	 *
2789	 * @static
2790	 * @method
2791	 * @return {string} The UUID.
2792	 */
2793	generateUUID: generateUUID,
2794	/**
2795	 * Clamps the given value between min and max.
2796	 *
2797	 * @static
2798	 * @method
2799	 * @param {number} value - The value to clamp.
2800	 * @param {number} min - The min value.
2801	 * @param {number} max - The max value.
2802	 * @return {number} The clamped value.
2803	 */
2804	clamp: clamp,
2805	/**
2806	 * Computes the Euclidean modulo of the given parameters that
2807	 * is `( ( n % m ) + m ) % m`.
2808	 *
2809	 * @static
2810	 * @method
2811	 * @param {number} n - The first parameter.
2812	 * @param {number} m - The second parameter.
2813	 * @return {number} The Euclidean modulo.
2814	 */
2815	euclideanModulo: euclideanModulo,
2816	/**
2817	 * Performs a linear mapping from range `<a1, a2>` to range `<b1, b2>`
2818	 * for the given value.
2819	 *
2820	 * @static
2821	 * @method
2822	 * @param {number} x - The value to be mapped.
2823	 * @param {number} a1 - Minimum value for range A.
2824	 * @param {number} a2 - Maximum value for range A.
2825	 * @param {number} b1 - Minimum value for range B.
2826	 * @param {number} b2 - Maximum value for range B.
2827	 * @return {number} The mapped value.
2828	 */
2829	mapLinear: mapLinear,
2830	/**
2831	 * Returns the percentage in the closed interval `[0, 1]` of the given value
2832	 * between the start and end point.
2833	 *
2834	 * @static
2835	 * @method
2836	 * @param {number} x - The start point
2837	 * @param {number} y - The end point.
2838	 * @param {number} value - A value between start and end.
2839	 * @return {number} The interpolation factor.
2840	 */
2841	inverseLerp: inverseLerp,
2842	/**
2843	 * Returns a value linearly interpolated from two known points based on the given interval -
2844	 * `t = 0` will return `x` and `t = 1` will return `y`.
2845	 *
2846	 * @static
2847	 * @method
2848	 * @param {number} x - The start point
2849	 * @param {number} y - The end point.
2850	 * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
2851	 * @return {number} The interpolated value.
2852	 */
2853	lerp: lerp,
2854	/**
2855	 * Smoothly interpolate a number from `x` to `y` in  a spring-like manner using a delta
2856	 * time to maintain frame rate independent movement. For details, see
2857	 * [Frame rate independent damping using lerp](http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/).
2858	 *
2859	 * @static
2860	 * @method
2861	 * @param {number} x - The current point.
2862	 * @param {number} y - The target point.
2863	 * @param {number} lambda - A higher lambda value will make the movement more sudden,
2864	 * and a lower value will make the movement more gradual.
2865	 * @param {number} dt - Delta time in seconds.
2866	 * @return {number} The interpolated value.
2867	 */
2868	damp: damp,
2869	/**
2870	 * Returns a value that alternates between `0` and the given `length` parameter.
2871	 *
2872	 * @static
2873	 * @method
2874	 * @param {number} x - The value to pingpong.
2875	 * @param {number} [length=1] - The positive value the function will pingpong to.
2876	 * @return {number} The alternated value.
2877	 */
2878	pingpong: pingpong,
2879	/**
2880	 * Returns a value in the range `[0,1]` that represents the percentage that `x` has
2881	 * moved between `min` and `max`, but smoothed or slowed down the closer `x` is to
2882	 * the `min` and `max`.
2883	 *
2884	 * See [Smoothstep](http://en.wikipedia.org/wiki/Smoothstep) for more details.
2885	 *
2886	 * @static
2887	 * @method
2888	 * @param {number} x - The value to evaluate based on its position between min and max.
2889	 * @param {number} min - The min value. Any x value below min will be `0`.
2890	 * @param {number} max - The max value. Any x value above max will be `1`.
2891	 * @return {number} The alternated value.
2892	 */
2893	smoothstep: smoothstep,
2894	/**
2895	 * A [variation on smoothstep](https://en.wikipedia.org/wiki/Smoothstep#Variations)
2896	 * that has zero 1st and 2nd order derivatives at x=0 and x=1.
2897	 *
2898	 * @static
2899	 * @method
2900	 * @param {number} x - The value to evaluate based on its position between min and max.
2901	 * @param {number} min - The min value. Any x value below min will be `0`.
2902	 * @param {number} max - The max value. Any x value above max will be `1`.
2903	 * @return {number} The alternated value.
2904	 */
2905	smootherstep: smootherstep,
2906	/**
2907	 * Returns a random integer from `<low, high>` interval.
2908	 *
2909	 * @static
2910	 * @method
2911	 * @param {number} low - The lower value boundary.
2912	 * @param {number} high - The upper value boundary
2913	 * @return {number} A random integer.
2914	 */
2915	randInt: randInt,
2916	/**
2917	 * Returns a random float from `<low, high>` interval.
2918	 *
2919	 * @static
2920	 * @method
2921	 * @param {number} low - The lower value boundary.
2922	 * @param {number} high - The upper value boundary
2923	 * @return {number} A random float.
2924	 */
2925	randFloat: randFloat,
2926	/**
2927	 * Returns a random integer from `<-range/2, range/2>` interval.
2928	 *
2929	 * @static
2930	 * @method
2931	 * @param {number} range - Defines the value range.
2932	 * @return {number} A random float.
2933	 */
2934	randFloatSpread: randFloatSpread,
2935	/**
2936	 * Returns a deterministic pseudo-random float in the interval `[0, 1]`.
2937	 *
2938	 * @static
2939	 * @method
2940	 * @param {number} [s] - The integer seed.
2941	 * @return {number} A random float.
2942	 */
2943	seededRandom: seededRandom,
2944	/**
2945	 * Converts degrees to radians.
2946	 *
2947	 * @static
2948	 * @method
2949	 * @param {number} degrees - A value in degrees.
2950	 * @return {number} The converted value in radians.
2951	 */
2952	degToRad: degToRad,
2953	/**
2954	 * Converts radians to degrees.
2955	 *
2956	 * @static
2957	 * @method
2958	 * @param {number} radians - A value in radians.
2959	 * @return {number} The converted value in degrees.
2960	 */
2961	radToDeg: radToDeg,
2962	/**
2963	 * Returns `true` if the given number is a power of two.
2964	 *
2965	 * @static
2966	 * @method
2967	 * @param {number} value - The value to check.
2968	 * @return {boolean} Whether the given number is a power of two or not.
2969	 */
2970	isPowerOfTwo: isPowerOfTwo,
2971	/**
2972	 * Returns the smallest power of two that is greater than or equal to the given number.
2973	 *
2974	 * @static
2975	 * @method
2976	 * @param {number} value - The value to find a POT for.
2977	 * @return {number} The smallest power of two that is greater than or equal to the given number.
2978	 */
2979	ceilPowerOfTwo: ceilPowerOfTwo,
2980	/**
2981	 * Returns the largest power of two that is less than or equal to the given number.
2982	 *
2983	 * @static
2984	 * @method
2985	 * @param {number} value - The value to find a POT for.
2986	 * @return {number} The largest power of two that is less than or equal to the given number.
2987	 */
2988	floorPowerOfTwo: floorPowerOfTwo,
2989	/**
2990	 * Sets the given quaternion from the [Intrinsic Proper Euler Angles](https://en.wikipedia.org/wiki/Euler_angles)
2991	 * defined by the given angles and order.
2992	 *
2993	 * Rotations are applied to the axes in the order specified by order:
2994	 * rotation by angle `a` is applied first, then by angle `b`, then by angle `c`.
2995	 *
2996	 * @static
2997	 * @method
2998	 * @param {Quaternion} q - The quaternion to set.
2999	 * @param {number} a - The rotation applied to the first axis, in radians.
3000	 * @param {number} b - The rotation applied to the second axis, in radians.
3001	 * @param {number} c - The rotation applied to the third axis, in radians.
3002	 * @param {('XYX'|'XZX'|'YXY'|'YZY'|'ZXZ'|'ZYZ')} order - A string specifying the axes order.
3003	 */
3004	setQuaternionFromProperEuler: setQuaternionFromProperEuler,
3005	/**
3006	 * Normalizes the given value according to the given typed array.
3007	 *
3008	 * @static
3009	 * @method
3010	 * @param {number} value - The float value in the range `[0,1]` to normalize.
3011	 * @param {TypedArray} array - The typed array that defines the data type of the value.
3012	 * @return {number} The normalize value.
3013	 */
3014	normalize: normalize,
3015	/**
3016	 * Denormalizes the given value according to the given typed array.
3017	 *
3018	 * @static
3019	 * @method
3020	 * @param {number} value - The value to denormalize.
3021	 * @param {TypedArray} array - The typed array that defines the data type of the value.
3022	 * @return {number} The denormalize (float) value in the range `[0,1]`.
3023	 */
3024	denormalize: denormalize
3025};
3026
3027/**
3028 * Class representing a 2D vector. A 2D vector is an ordered pair of numbers
3029 * (labeled x and y), which can be used to represent a number of things, such as:
3030 *
3031 * - A point in 2D space (i.e. a position on a plane).
3032 * - A direction and length across a plane. In three.js the length will
3033 * always be the Euclidean distance(straight-line distance) from `(0, 0)` to `(x, y)`
3034 * and the direction is also measured from `(0, 0)` towards `(x, y)`.
3035 * - Any arbitrary ordered pair of numbers.
3036 *
3037 * There are other things a 2D vector can be used to represent, such as
3038 * momentum vectors, complex numbers and so on, however these are the most
3039 * common uses in three.js.
3040 *
3041 * Iterating through a vector instance will yield its components `(x, y)` in
3042 * the corresponding order.
3043 * ```js
3044 * const a = new THREE.Vector2( 0, 1 );
3045 *
3046 * //no arguments; will be initialised to (0, 0)
3047 * const b = new THREE.Vector2( );
3048 *
3049 * const d = a.distanceTo( b );
3050 * ```
3051 */
3052class Vector2 {
3053
3054	static {
3055
3056		/**
3057		 * This flag can be used for type testing.
3058		 *
3059		 * @type {boolean}
3060		 * @readonly
3061		 * @default true
3062		 */
3063		Vector2.prototype.isVector2 = true;
3064
3065	}
3066
3067	/**
3068	 * Constructs a new 2D vector.
3069	 *
3070	 * @param {number} [x=0] - The x value of this vector.
3071	 * @param {number} [y=0] - The y value of this vector.
3072	 */
3073	constructor( x = 0, y = 0 ) {
3074
3075		/**
3076		 * The x value of this vector.
3077		 *
3078		 * @type {number}
3079		 */
3080		this.x = x;
3081
3082		/**
3083		 * The y value of this vector.
3084		 *
3085		 * @type {number}
3086		 */
3087		this.y = y;
3088
3089	}
3090
3091	/**
3092	 * Alias for {@link Vector2#x}.
3093	 *
3094	 * @type {number}
3095	 */
3096	get width() {
3097
3098		return this.x;
3099
3100	}
3101
3102	set width( value ) {
3103
3104		this.x = value;
3105
3106	}
3107
3108	/**
3109	 * Alias for {@link Vector2#y}.
3110	 *
3111	 * @type {number}
3112	 */
3113	get height() {
3114
3115		return this.y;
3116
3117	}
3118
3119	set height( value ) {
3120
3121		this.y = value;
3122
3123	}
3124
3125	/**
3126	 * Sets the vector components.
3127	 *
3128	 * @param {number} x - The value of the x component.
3129	 * @param {number} y - The value of the y component.
3130	 * @return {Vector2} A reference to this vector.
3131	 */
3132	set( x, y ) {
3133
3134		this.x = x;
3135		this.y = y;
3136
3137		return this;
3138
3139	}
3140
3141	/**
3142	 * Sets the vector components to the same value.
3143	 *
3144	 * @param {number} scalar - The value to set for all vector components.
3145	 * @return {Vector2} A reference to this vector.
3146	 */
3147	setScalar( scalar ) {
3148
3149		this.x = scalar;
3150		this.y = scalar;
3151
3152		return this;
3153
3154	}
3155
3156	/**
3157	 * Sets the vector's x component to the given value
3158	 *
3159	 * @param {number} x - The value to set.
3160	 * @return {Vector2} A reference to this vector.
3161	 */
3162	setX( x ) {
3163
3164		this.x = x;
3165
3166		return this;
3167
3168	}
3169
3170	/**
3171	 * Sets the vector's y component to the given value
3172	 *
3173	 * @param {number} y - The value to set.
3174	 * @return {Vector2} A reference to this vector.
3175	 */
3176	setY( y ) {
3177
3178		this.y = y;
3179
3180		return this;
3181
3182	}
3183
3184	/**
3185	 * Allows to set a vector component with an index.
3186	 *
3187	 * @param {number} index - The component index. `0` equals to x, `1` equals to y.
3188	 * @param {number} value - The value to set.
3189	 * @return {Vector2} A reference to this vector.
3190	 */
3191	setComponent( index, value ) {
3192
3193		switch ( index ) {
3194
3195			case 0: this.x = value; break;
3196			case 1: this.y = value; break;
3197			default: throw new Error( 'THREE.Vector2: index is out of range: ' + index );
3198
3199		}
3200
3201		return this;
3202
3203	}
3204
3205	/**
3206	 * Returns the value of the vector component which matches the given index.
3207	 *
3208	 * @param {number} index - The component index. `0` equals to x, `1` equals to y.
3209	 * @return {number} A vector component value.
3210	 */
3211	getComponent( index ) {
3212
3213		switch ( index ) {
3214
3215			case 0: return this.x;
3216			case 1: return this.y;
3217			default: throw new Error( 'THREE.Vector2: index is out of range: ' + index );
3218
3219		}
3220
3221	}
3222
3223	/**
3224	 * Returns a new vector with copied values from this instance.
3225	 *
3226	 * @return {Vector2} A clone of this instance.
3227	 */
3228	clone() {
3229
3230		return new this.constructor( this.x, this.y );
3231
3232	}
3233
3234	/**
3235	 * Copies the values of the given vector to this instance.
3236	 *
3237	 * @param {Vector2} v - The vector to copy.
3238	 * @return {Vector2} A reference to this vector.
3239	 */
3240	copy( v ) {
3241
3242		this.x = v.x;
3243		this.y = v.y;
3244
3245		return this;
3246
3247	}
3248
3249	/**
3250	 * Adds the given vector to this instance.
3251	 *
3252	 * @param {Vector2} v - The vector to add.
3253	 * @return {Vector2} A reference to this vector.
3254	 */
3255	add( v ) {
3256
3257		this.x += v.x;
3258		this.y += v.y;
3259
3260		return this;
3261
3262	}
3263
3264	/**
3265	 * Adds the given scalar value to all components of this instance.
3266	 *
3267	 * @param {number} s - The scalar to add.
3268	 * @return {Vector2} A reference to this vector.
3269	 */
3270	addScalar( s ) {
3271
3272		this.x += s;
3273		this.y += s;
3274
3275		return this;
3276
3277	}
3278
3279	/**
3280	 * Adds the given vectors and stores the result in this instance.
3281	 *
3282	 * @param {Vector2} a - The first vector.
3283	 * @param {Vector2} b - The second vector.
3284	 * @return {Vector2} A reference to this vector.
3285	 */
3286	addVectors( a, b ) {
3287
3288		this.x = a.x + b.x;
3289		this.y = a.y + b.y;
3290
3291		return this;
3292
3293	}
3294
3295	/**
3296	 * Adds the given vector scaled by the given factor to this instance.
3297	 *
3298	 * @param {Vector2} v - The vector.
3299	 * @param {number} s - The factor that scales `v`.
3300	 * @return {Vector2} A reference to this vector.
3301	 */
3302	addScaledVector( v, s ) {
3303
3304		this.x += v.x * s;
3305		this.y += v.y * s;
3306
3307		return this;
3308
3309	}
3310
3311	/**
3312	 * Subtracts the given vector from this instance.
3313	 *
3314	 * @param {Vector2} v - The vector to subtract.
3315	 * @return {Vector2} A reference to this vector.
3316	 */
3317	sub( v ) {
3318
3319		this.x -= v.x;
3320		this.y -= v.y;
3321
3322		return this;
3323
3324	}
3325
3326	/**
3327	 * Subtracts the given scalar value from all components of this instance.
3328	 *
3329	 * @param {number} s - The scalar to subtract.
3330	 * @return {Vector2} A reference to this vector.
3331	 */
3332	subScalar( s ) {
3333
3334		this.x -= s;
3335		this.y -= s;
3336
3337		return this;
3338
3339	}
3340
3341	/**
3342	 * Subtracts the given vectors and stores the result in this instance.
3343	 *
3344	 * @param {Vector2} a - The first vector.
3345	 * @param {Vector2} b - The second vector.
3346	 * @return {Vector2} A reference to this vector.
3347	 */
3348	subVectors( a, b ) {
3349
3350		this.x = a.x - b.x;
3351		this.y = a.y - b.y;
3352
3353		return this;
3354
3355	}
3356
3357	/**
3358	 * Multiplies the given vector with this instance.
3359	 *
3360	 * @param {Vector2} v - The vector to multiply.
3361	 * @return {Vector2} A reference to this vector.
3362	 */
3363	multiply( v ) {
3364
3365		this.x *= v.x;
3366		this.y *= v.y;
3367
3368		return this;
3369
3370	}
3371
3372	/**
3373	 * Multiplies the given scalar value with all components of this instance.
3374	 *
3375	 * @param {number} scalar - The scalar to multiply.
3376	 * @return {Vector2} A reference to this vector.
3377	 */
3378	multiplyScalar( scalar ) {
3379
3380		this.x *= scalar;
3381		this.y *= scalar;
3382
3383		return this;
3384
3385	}
3386
3387	/**
3388	 * Divides this instance by the given vector.
3389	 *
3390	 * @param {Vector2} v - The vector to divide.
3391	 * @return {Vector2} A reference to this vector.
3392	 */
3393	divide( v ) {
3394
3395		this.x /= v.x;
3396		this.y /= v.y;
3397
3398		return this;
3399
3400	}
3401
3402	/**
3403	 * Divides this vector by the given scalar.
3404	 *
3405	 * @param {number} scalar - The scalar to divide.
3406	 * @return {Vector2} A reference to this vector.
3407	 */
3408	divideScalar( scalar ) {
3409
3410		return this.multiplyScalar( 1 / scalar );
3411
3412	}
3413
3414	/**
3415	 * Multiplies this vector (with an implicit 1 as the 3rd component) by
3416	 * the given 3x3 matrix.
3417	 *
3418	 * @param {Matrix3} m - The matrix to apply.
3419	 * @return {Vector2} A reference to this vector.
3420	 */
3421	applyMatrix3( m ) {
3422
3423		const x = this.x, y = this.y;
3424		const e = m.elements;
3425
3426		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];
3427		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];
3428
3429		return this;
3430
3431	}
3432
3433	/**
3434	 * If this vector's x or y value is greater than the given vector's x or y
3435	 * value, replace that value with the corresponding min value.
3436	 *
3437	 * @param {Vector2} v - The vector.
3438	 * @return {Vector2} A reference to this vector.
3439	 */
3440	min( v ) {
3441
3442		this.x = Math.min( this.x, v.x );
3443		this.y = Math.min( this.y, v.y );
3444
3445		return this;
3446
3447	}
3448
3449	/**
3450	 * If this vector's x or y value is less than the given vector's x or y
3451	 * value, replace that value with the corresponding max value.
3452	 *
3453	 * @param {Vector2} v - The vector.
3454	 * @return {Vector2} A reference to this vector.
3455	 */
3456	max( v ) {
3457
3458		this.x = Math.max( this.x, v.x );
3459		this.y = Math.max( this.y, v.y );
3460
3461		return this;
3462
3463	}
3464
3465	/**
3466	 * If this vector's x or y value is greater than the max vector's x or y
3467	 * value, it is replaced by the corresponding value.
3468	 * If this vector's x or y value is less than the min vector's x or y value,
3469	 * it is replaced by the corresponding value.
3470	 *
3471	 * @param {Vector2} min - The minimum x and y values.
3472	 * @param {Vector2} max - The maximum x and y values in the desired range.
3473	 * @return {Vector2} A reference to this vector.
3474	 */
3475	clamp( min, max ) {
3476
3477		// assumes min < max, componentwise
3478
3479		this.x = clamp( this.x, min.x, max.x );
3480		this.y = clamp( this.y, min.y, max.y );
3481
3482		return this;
3483
3484	}
3485
3486	/**
3487	 * If this vector's x or y values are greater than the max value, they are
3488	 * replaced by the max value.
3489	 * If this vector's x or y values are less than the min value, they are
3490	 * replaced by the min value.
3491	 *
3492	 * @param {number} minVal - The minimum value the components will be clamped to.
3493	 * @param {number} maxVal - The maximum value the components will be clamped to.
3494	 * @return {Vector2} A reference to this vector.
3495	 */
3496	clampScalar( minVal, maxVal ) {
3497
3498		this.x = clamp( this.x, minVal, maxVal );
3499		this.y = clamp( this.y, minVal, maxVal );
3500
3501		return this;
3502
3503	}
3504
3505	/**
3506	 * If this vector's length is greater than the max value, it is replaced by
3507	 * the max value.
3508	 * If this vector's length is less than the min value, it is replaced by the
3509	 * min value.
3510	 *
3511	 * @param {number} min - The minimum value the vector length will be clamped to.
3512	 * @param {number} max - The maximum value the vector length will be clamped to.
3513	 * @return {Vector2} A reference to this vector.
3514	 */
3515	clampLength( min, max ) {
3516
3517		const length = this.length();
3518
3519		return this.divideScalar( length || 1 ).multiplyScalar( clamp( length, min, max ) );
3520
3521	}
3522
3523	/**
3524	 * The components of this vector are rounded down to the nearest integer value.
3525	 *
3526	 * @return {Vector2} A reference to this vector.
3527	 */
3528	floor() {
3529
3530		this.x = Math.floor( this.x );
3531		this.y = Math.floor( this.y );
3532
3533		return this;
3534
3535	}
3536
3537	/**
3538	 * The components of this vector are rounded up to the nearest integer value.
3539	 *
3540	 * @return {Vector2} A reference to this vector.
3541	 */
3542	ceil() {
3543
3544		this.x = Math.ceil( this.x );
3545		this.y = Math.ceil( this.y );
3546
3547		return this;
3548
3549	}
3550
3551	/**
3552	 * The components of this vector are rounded to the nearest integer value
3553	 *
3554	 * @return {Vector2} A reference to this vector.
3555	 */
3556	round() {
3557
3558		this.x = Math.round( this.x );
3559		this.y = Math.round( this.y );
3560
3561		return this;
3562
3563	}
3564
3565	/**
3566	 * The components of this vector are rounded towards zero (up if negative,
3567	 * down if positive) to an integer value.
3568	 *
3569	 * @return {Vector2} A reference to this vector.
3570	 */
3571	roundToZero() {
3572
3573		this.x = Math.trunc( this.x );
3574		this.y = Math.trunc( this.y );
3575
3576		return this;
3577
3578	}
3579
3580	/**
3581	 * Inverts this vector - i.e. sets x = -x and y = -y.
3582	 *
3583	 * @return {Vector2} A reference to this vector.
3584	 */
3585	negate() {
3586
3587		this.x = - this.x;
3588		this.y = - this.y;
3589
3590		return this;
3591
3592	}
3593
3594	/**
3595	 * Calculates the dot product of the given vector with this instance.
3596	 *
3597	 * @param {Vector2} v - The vector to compute the dot product with.
3598	 * @return {number} The result of the dot product.
3599	 */
3600	dot( v ) {
3601
3602		return this.x * v.x + this.y * v.y;
3603
3604	}
3605
3606	/**
3607	 * Calculates the cross product of the given vector with this instance.
3608	 *
3609	 * @param {Vector2} v - The vector to compute the cross product with.
3610	 * @return {number} The result of the cross product.
3611	 */
3612	cross( v ) {
3613
3614		return this.x * v.y - this.y * v.x;
3615
3616	}
3617
3618	/**
3619	 * Computes the square of the Euclidean length (straight-line length) from
3620	 * (0, 0) to (x, y). If you are comparing the lengths of vectors, you should
3621	 * compare the length squared instead as it is slightly more efficient to calculate.
3622	 *
3623	 * @return {number} The square length of this vector.
3624	 */
3625	lengthSq() {
3626
3627		return this.x * this.x + this.y * this.y;
3628
3629	}
3630
3631	/**
3632	 * Computes the  Euclidean length (straight-line length) from (0, 0) to (x, y).
3633	 *
3634	 * @return {number} The length of this vector.
3635	 */
3636	length() {
3637
3638		return Math.sqrt( this.x * this.x + this.y * this.y );
3639
3640	}
3641
3642	/**
3643	 * Computes the Manhattan length of this vector.
3644	 *
3645	 * @return {number} The length of this vector.
3646	 */
3647	manhattanLength() {
3648
3649		return Math.abs( this.x ) + Math.abs( this.y );
3650
3651	}
3652
3653	/**
3654	 * Converts this vector to a unit vector - that is, sets it equal to a vector
3655	 * with the same direction as this one, but with a vector length of `1`.
3656	 *
3657	 * @return {Vector2} A reference to this vector.
3658	 */
3659	normalize() {
3660
3661		return this.divideScalar( this.length() || 1 );
3662
3663	}
3664
3665	/**
3666	 * Computes the angle in radians of this vector with respect to the positive x-axis.
3667	 *
3668	 * @return {number} The angle in radians.
3669	 */
3670	angle() {
3671
3672		const angle = Math.atan2( - this.y, - this.x ) + Math.PI;
3673
3674		return angle;
3675
3676	}
3677
3678	/**
3679	 * Returns the angle between the given vector and this instance in radians.
3680	 *
3681	 * @param {Vector2} v - The vector to compute the angle with.
3682	 * @return {number} The angle in radians.
3683	 */
3684	angleTo( v ) {
3685
3686		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
3687
3688		if ( denominator === 0 ) return Math.PI / 2;
3689
3690		const theta = this.dot( v ) / denominator;
3691
3692		// clamp, to handle numerical problems
3693
3694		return Math.acos( clamp( theta, -1, 1 ) );
3695
3696	}
3697
3698	/**
3699	 * Computes the distance from the given vector to this instance.
3700	 *
3701	 * @param {Vector2} v - The vector to compute the distance to.
3702	 * @return {number} The distance.
3703	 */
3704	distanceTo( v ) {
3705
3706		return Math.sqrt( this.distanceToSquared( v ) );
3707
3708	}
3709
3710	/**
3711	 * Computes the squared distance from the given vector to this instance.
3712	 * If you are just comparing the distance with another distance, you should compare
3713	 * the distance squared instead as it is slightly more efficient to calculate.
3714	 *
3715	 * @param {Vector2} v - The vector to compute the squared distance to.
3716	 * @return {number} The squared distance.
3717	 */
3718	distanceToSquared( v ) {
3719
3720		const dx = this.x - v.x, dy = this.y - v.y;
3721		return dx * dx + dy * dy;
3722
3723	}
3724
3725	/**
3726	 * Computes the Manhattan distance from the given vector to this instance.
3727	 *
3728	 * @param {Vector2} v - The vector to compute the Manhattan distance to.
3729	 * @return {number} The Manhattan distance.
3730	 */
3731	manhattanDistanceTo( v ) {
3732
3733		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
3734
3735	}
3736
3737	/**
3738	 * Sets this vector to a vector with the same direction as this one, but
3739	 * with the specified length.
3740	 *
3741	 * @param {number} length - The new length of this vector.
3742	 * @return {Vector2} A reference to this vector.
3743	 */
3744	setLength( length ) {
3745
3746		return this.normalize().multiplyScalar( length );
3747
3748	}
3749
3750	/**
3751	 * Linearly interpolates between the given vector and this instance, where
3752	 * alpha is the percent distance along the line - alpha = 0 will be this
3753	 * vector, and alpha = 1 will be the given one.
3754	 *
3755	 * @param {Vector2} v - The vector to interpolate towards.
3756	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
3757	 * @return {Vector2} A reference to this vector.
3758	 */
3759	lerp( v, alpha ) {
3760
3761		this.x += ( v.x - this.x ) * alpha;
3762		this.y += ( v.y - this.y ) * alpha;
3763
3764		return this;
3765
3766	}
3767
3768	/**
3769	 * Linearly interpolates between the given vectors, where alpha is the percent
3770	 * distance along the line - alpha = 0 will be first vector, and alpha = 1 will
3771	 * be the second one. The result is stored in this instance.
3772	 *
3773	 * @param {Vector2} v1 - The first vector.
3774	 * @param {Vector2} v2 - The second vector.
3775	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
3776	 * @return {Vector2} A reference to this vector.
3777	 */
3778	lerpVectors( v1, v2, alpha ) {
3779
3780		this.x = v1.x + ( v2.x - v1.x ) * alpha;
3781		this.y = v1.y + ( v2.y - v1.y ) * alpha;
3782
3783		return this;
3784
3785	}
3786
3787	/**
3788	 * Returns `true` if this vector is equal with the given one.
3789	 *
3790	 * @param {Vector2} v - The vector to test for equality.
3791	 * @return {boolean} Whether this vector is equal with the given one.
3792	 */
3793	equals( v ) {
3794
3795		return ( ( v.x === this.x ) && ( v.y === this.y ) );
3796
3797	}
3798
3799	/**
3800	 * Sets this vector's x value to be `array[ offset ]` and y
3801	 * value to be `array[ offset + 1 ]`.
3802	 *
3803	 * @param {Array<number>} array - An array holding the vector component values.
3804	 * @param {number} [offset=0] - The offset into the array.
3805	 * @return {Vector2} A reference to this vector.
3806	 */
3807	fromArray( array, offset = 0 ) {
3808
3809		this.x = array[ offset ];
3810		this.y = array[ offset + 1 ];
3811
3812		return this;
3813
3814	}
3815
3816	/**
3817	 * Writes the components of this vector to the given array. If no array is provided,
3818	 * the method returns a new instance.
3819	 *
3820	 * @param {Array<number>} [array=[]] - The target array holding the vector components.
3821	 * @param {number} [offset=0] - Index of the first element in the array.
3822	 * @return {Array<number>} The vector components.
3823	 */
3824	toArray( array = [], offset = 0 ) {
3825
3826		array[ offset ] = this.x;
3827		array[ offset + 1 ] = this.y;
3828
3829		return array;
3830
3831	}
3832
3833	/**
3834	 * Sets the components of this vector from the given buffer attribute.
3835	 *
3836	 * @param {BufferAttribute} attribute - The buffer attribute holding vector data.
3837	 * @param {number} index - The index into the attribute.
3838	 * @return {Vector2} A reference to this vector.
3839	 */
3840	fromBufferAttribute( attribute, index ) {
3841
3842		this.x = attribute.getX( index );
3843		this.y = attribute.getY( index );
3844
3845		return this;
3846
3847	}
3848
3849	/**
3850	 * Rotates this vector around the given center by the given angle.
3851	 *
3852	 * @param {Vector2} center - The point around which to rotate.
3853	 * @param {number} angle - The angle to rotate, in radians.
3854	 * @return {Vector2} A reference to this vector.
3855	 */
3856	rotateAround( center, angle ) {
3857
3858		const c = Math.cos( angle ), s = Math.sin( angle );
3859
3860		const x = this.x - center.x;
3861		const y = this.y - center.y;
3862
3863		this.x = x * c - y * s + center.x;
3864		this.y = x * s + y * c + center.y;
3865
3866		return this;
3867
3868	}
3869
3870	/**
3871	 * Sets each component of this vector to a pseudo-random value between `0` and
3872	 * `1`, excluding `1`.
3873	 *
3874	 * @return {Vector2} A reference to this vector.
3875	 */
3876	random() {
3877
3878		this.x = Math.random();
3879		this.y = Math.random();
3880
3881		return this;
3882
3883	}
3884
3885	*[ Symbol.iterator ]() {
3886
3887		yield this.x;
3888		yield this.y;
3889
3890	}
3891
3892}
3893
3894/**
3895 * Class for representing a Quaternion. Quaternions are used in three.js to represent rotations.
3896 *
3897 * Iterating through a vector instance will yield its components `(x, y, z, w)` in
3898 * the corresponding order.
3899 *
3900 * Note that three.js expects Quaternions to be normalized.
3901 * ```js
3902 * const quaternion = new THREE.Quaternion();
3903 * quaternion.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 2 );
3904 *
3905 * const vector = new THREE.Vector3( 1, 0, 0 );
3906 * vector.applyQuaternion( quaternion );
3907 * ```
3908 */
3909class Quaternion {
3910
3911	/**
3912	 * Constructs a new quaternion.
3913	 *
3914	 * @param {number} [x=0] - The x value of this quaternion.
3915	 * @param {number} [y=0] - The y value of this quaternion.
3916	 * @param {number} [z=0] - The z value of this quaternion.
3917	 * @param {number} [w=1] - The w value of this quaternion.
3918	 */
3919	constructor( x = 0, y = 0, z = 0, w = 1 ) {
3920
3921		/**
3922		 * This flag can be used for type testing.
3923		 *
3924		 * @type {boolean}
3925		 * @readonly
3926		 * @default true
3927		 */
3928		this.isQuaternion = true;
3929
3930		this._x = x;
3931		this._y = y;
3932		this._z = z;
3933		this._w = w;
3934
3935	}
3936
3937	/**
3938	 * Interpolates between two quaternions via SLERP. This implementation assumes the
3939	 * quaternion data are managed in flat arrays.
3940	 *
3941	 * @param {Array<number>} dst - The destination array.
3942	 * @param {number} dstOffset - An offset into the destination array.
3943	 * @param {Array<number>} src0 - The source array of the first quaternion.
3944	 * @param {number} srcOffset0 - An offset into the first source array.
3945	 * @param {Array<number>} src1 -  The source array of the second quaternion.
3946	 * @param {number} srcOffset1 - An offset into the second source array.
3947	 * @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate.
3948	 * @see {@link Quaternion#slerp}
3949	 */
3950	static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
3951
3952		let x0 = src0[ srcOffset0 + 0 ],
3953			y0 = src0[ srcOffset0 + 1 ],
3954			z0 = src0[ srcOffset0 + 2 ],
3955			w0 = src0[ srcOffset0 + 3 ];
3956
3957		let x1 = src1[ srcOffset1 + 0 ],
3958			y1 = src1[ srcOffset1 + 1 ],
3959			z1 = src1[ srcOffset1 + 2 ],
3960			w1 = src1[ srcOffset1 + 3 ];
3961
3962		if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
3963
3964			let dot = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1;
3965
3966			if ( dot < 0 ) {
3967
3968				x1 = - x1;
3969				y1 = - y1;
3970				z1 = - z1;
3971				w1 = - w1;
3972
3973				dot = - dot;
3974
3975			}
3976
3977			let s = 1 - t;
3978
3979			if ( dot < 0.9995 ) {
3980
3981				// slerp
3982
3983				const theta = Math.acos( dot );
3984				const sin = Math.sin( theta );
3985
3986				s = Math.sin( s * theta ) / sin;
3987				t = Math.sin( t * theta ) / sin;
3988
3989				x0 = x0 * s + x1 * t;
3990				y0 = y0 * s + y1 * t;
3991				z0 = z0 * s + z1 * t;
3992				w0 = w0 * s + w1 * t;
3993
3994			} else {
3995
3996				// for small angles, lerp then normalize
3997
3998				x0 = x0 * s + x1 * t;
3999				y0 = y0 * s + y1 * t;
4000				z0 = z0 * s + z1 * t;
4001				w0 = w0 * s + w1 * t;
4002
4003				const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
4004
4005				x0 *= f;
4006				y0 *= f;
4007				z0 *= f;
4008				w0 *= f;
4009
4010			}
4011
4012		}
4013
4014		dst[ dstOffset ] = x0;
4015		dst[ dstOffset + 1 ] = y0;
4016		dst[ dstOffset + 2 ] = z0;
4017		dst[ dstOffset + 3 ] = w0;
4018
4019	}
4020
4021	/**
4022	 * Multiplies two quaternions. This implementation assumes the quaternion data are managed
4023	 * in flat arrays.
4024	 *
4025	 * @param {Array<number>} dst - The destination array.
4026	 * @param {number} dstOffset - An offset into the destination array.
4027	 * @param {Array<number>} src0 - The source array of the first quaternion.
4028	 * @param {number} srcOffset0 - An offset into the first source array.
4029	 * @param {Array<number>} src1 -  The source array of the second quaternion.
4030	 * @param {number} srcOffset1 - An offset into the second source array.
4031	 * @return {Array<number>} The destination array.
4032	 * @see {@link Quaternion#multiplyQuaternions}.
4033	 */
4034	static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
4035
4036		const x0 = src0[ srcOffset0 ];
4037		const y0 = src0[ srcOffset0 + 1 ];
4038		const z0 = src0[ srcOffset0 + 2 ];
4039		const w0 = src0[ srcOffset0 + 3 ];
4040
4041		const x1 = src1[ srcOffset1 ];
4042		const y1 = src1[ srcOffset1 + 1 ];
4043		const z1 = src1[ srcOffset1 + 2 ];
4044		const w1 = src1[ srcOffset1 + 3 ];
4045
4046		dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
4047		dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
4048		dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
4049		dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
4050
4051		return dst;
4052
4053	}
4054
4055	/**
4056	 * The x value of this quaternion.
4057	 *
4058	 * @type {number}
4059	 * @default 0
4060	 */
4061	get x() {
4062
4063		return this._x;
4064
4065	}
4066
4067	set x( value ) {
4068
4069		this._x = value;
4070		this._onChangeCallback();
4071
4072	}
4073
4074	/**
4075	 * The y value of this quaternion.
4076	 *
4077	 * @type {number}
4078	 * @default 0
4079	 */
4080	get y() {
4081
4082		return this._y;
4083
4084	}
4085
4086	set y( value ) {
4087
4088		this._y = value;
4089		this._onChangeCallback();
4090
4091	}
4092
4093	/**
4094	 * The z value of this quaternion.
4095	 *
4096	 * @type {number}
4097	 * @default 0
4098	 */
4099	get z() {
4100
4101		return this._z;
4102
4103	}
4104
4105	set z( value ) {
4106
4107		this._z = value;
4108		this._onChangeCallback();
4109
4110	}
4111
4112	/**
4113	 * The w value of this quaternion.
4114	 *
4115	 * @type {number}
4116	 * @default 1
4117	 */
4118	get w() {
4119
4120		return this._w;
4121
4122	}
4123
4124	set w( value ) {
4125
4126		this._w = value;
4127		this._onChangeCallback();
4128
4129	}
4130
4131	/**
4132	 * Sets the quaternion components.
4133	 *
4134	 * @param {number} x - The x value of this quaternion.
4135	 * @param {number} y - The y value of this quaternion.
4136	 * @param {number} z - The z value of this quaternion.
4137	 * @param {number} w - The w value of this quaternion.
4138	 * @return {Quaternion} A reference to this quaternion.
4139	 */
4140	set( x, y, z, w ) {
4141
4142		this._x = x;
4143		this._y = y;
4144		this._z = z;
4145		this._w = w;
4146
4147		this._onChangeCallback();
4148
4149		return this;
4150
4151	}
4152
4153	/**
4154	 * Returns a new quaternion with copied values from this instance.
4155	 *
4156	 * @return {Quaternion} A clone of this instance.
4157	 */
4158	clone() {
4159
4160		return new this.constructor( this._x, this._y, this._z, this._w );
4161
4162	}
4163
4164	/**
4165	 * Copies the values of the given quaternion to this instance.
4166	 *
4167	 * @param {Quaternion} quaternion - The quaternion to copy.
4168	 * @return {Quaternion} A reference to this quaternion.
4169	 */
4170	copy( quaternion ) {
4171
4172		this._x = quaternion.x;
4173		this._y = quaternion.y;
4174		this._z = quaternion.z;
4175		this._w = quaternion.w;
4176
4177		this._onChangeCallback();
4178
4179		return this;
4180
4181	}
4182
4183	/**
4184	 * Sets this quaternion from the rotation specified by the given
4185	 * Euler angles.
4186	 *
4187	 * @param {Euler} euler - The Euler angles.
4188	 * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
4189	 * @return {Quaternion} A reference to this quaternion.
4190	 */
4191	setFromEuler( euler, update = true ) {
4192
4193		const x = euler._x, y = euler._y, z = euler._z, order = euler._order;
4194
4195		const cos = Math.cos;
4196		const sin = Math.sin;
4197
4198		const c1 = cos( x / 2 );
4199		const c2 = cos( y / 2 );
4200		const c3 = cos( z / 2 );
4201
4202		const s1 = sin( x / 2 );
4203		const s2 = sin( y / 2 );
4204		const s3 = sin( z / 2 );
4205
4206		switch ( order ) {
4207
4208			case 'XYZ':
4209				this._x = s1 * c2 * c3 + c1 * s2 * s3;
4210				this._y = c1 * s2 * c3 - s1 * c2 * s3;
4211				this._z = c1 * c2 * s3 + s1 * s2 * c3;
4212				this._w = c1 * c2 * c3 - s1 * s2 * s3;
4213				break;
4214
4215			case 'YXZ':
4216				this._x = s1 * c2 * c3 + c1 * s2 * s3;
4217				this._y = c1 * s2 * c3 - s1 * c2 * s3;
4218				this._z = c1 * c2 * s3 - s1 * s2 * c3;
4219				this._w = c1 * c2 * c3 + s1 * s2 * s3;
4220				break;
4221
4222			case 'ZXY':
4223				this._x = s1 * c2 * c3 - c1 * s2 * s3;
4224				this._y = c1 * s2 * c3 + s1 * c2 * s3;
4225				this._z = c1 * c2 * s3 + s1 * s2 * c3;
4226				this._w = c1 * c2 * c3 - s1 * s2 * s3;
4227				break;
4228
4229			case 'ZYX':
4230				this._x = s1 * c2 * c3 - c1 * s2 * s3;
4231				this._y = c1 * s2 * c3 + s1 * c2 * s3;
4232				this._z = c1 * c2 * s3 - s1 * s2 * c3;
4233				this._w = c1 * c2 * c3 + s1 * s2 * s3;
4234				break;
4235
4236			case 'YZX':
4237				this._x = s1 * c2 * c3 + c1 * s2 * s3;
4238				this._y = c1 * s2 * c3 + s1 * c2 * s3;
4239				this._z = c1 * c2 * s3 - s1 * s2 * c3;
4240				this._w = c1 * c2 * c3 - s1 * s2 * s3;
4241				break;
4242
4243			case 'XZY':
4244				this._x = s1 * c2 * c3 - c1 * s2 * s3;
4245				this._y = c1 * s2 * c3 - s1 * c2 * s3;
4246				this._z = c1 * c2 * s3 + s1 * s2 * c3;
4247				this._w = c1 * c2 * c3 + s1 * s2 * s3;
4248				break;
4249
4250			default:
4251				warn( 'Quaternion: .setFromEuler() encountered an unknown order: ' + order );
4252
4253		}
4254
4255		if ( update === true ) this._onChangeCallback();
4256
4257		return this;
4258
4259	}
4260
4261	/**
4262	 * Sets this quaternion from the given axis and angle.
4263	 *
4264	 * @param {Vector3} axis - The normalized axis.
4265	 * @param {number} angle - The angle in radians.
4266	 * @return {Quaternion} A reference to this quaternion.
4267	 */
4268	setFromAxisAngle( axis, angle ) {
4269
4270		const halfAngle = angle / 2, s = Math.sin( halfAngle );
4271
4272		this._x = axis.x * s;
4273		this._y = axis.y * s;
4274		this._z = axis.z * s;
4275		this._w = Math.cos( halfAngle );
4276
4277		this._onChangeCallback();
4278
4279		return this;
4280
4281	}
4282
4283	/**
4284	 * Sets this quaternion from the given rotation matrix.
4285	 *
4286	 * @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).
4287	 * @return {Quaternion} A reference to this quaternion.
4288	 */
4289	setFromRotationMatrix( m ) {
4290
4291		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
4292
4293		const te = m.elements,
4294
4295			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
4296			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
4297			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
4298
4299			trace = m11 + m22 + m33;
4300
4301		if ( trace > 0 ) {
4302
4303			const s = 0.5 / Math.sqrt( trace + 1.0 );
4304
4305			this._w = 0.25 / s;
4306			this._x = ( m32 - m23 ) * s;
4307			this._y = ( m13 - m31 ) * s;
4308			this._z = ( m21 - m12 ) * s;
4309
4310		} else if ( m11 > m22 && m11 > m33 ) {
4311
4312			const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
4313
4314			this._w = ( m32 - m23 ) / s;
4315			this._x = 0.25 * s;
4316			this._y = ( m12 + m21 ) / s;
4317			this._z = ( m13 + m31 ) / s;
4318
4319		} else if ( m22 > m33 ) {
4320
4321			const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
4322
4323			this._w = ( m13 - m31 ) / s;
4324			this._x = ( m12 + m21 ) / s;
4325			this._y = 0.25 * s;
4326			this._z = ( m23 + m32 ) / s;
4327
4328		} else {
4329
4330			const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
4331
4332			this._w = ( m21 - m12 ) / s;
4333			this._x = ( m13 + m31 ) / s;
4334			this._y = ( m23 + m32 ) / s;
4335			this._z = 0.25 * s;
4336
4337		}
4338
4339		this._onChangeCallback();
4340
4341		return this;
4342
4343	}
4344
4345	/**
4346	 * Sets this quaternion to the rotation required to rotate the direction vector
4347	 * `vFrom` to the direction vector `vTo`.
4348	 *
4349	 * @param {Vector3} vFrom - The first (normalized) direction vector.
4350	 * @param {Vector3} vTo - The second (normalized) direction vector.
4351	 * @return {Quaternion} A reference to this quaternion.
4352	 */
4353	setFromUnitVectors( vFrom, vTo ) {
4354
4355		// assumes direction vectors vFrom and vTo are normalized
4356
4357		let r = vFrom.dot( vTo ) + 1;
4358
4359		if ( r < 1e-8 ) { // the epsilon value has been discussed in #31286
4360
4361			// vFrom and vTo point in opposite directions
4362
4363			r = 0;
4364
4365			if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
4366
4367				this._x = - vFrom.y;
4368				this._y = vFrom.x;
4369				this._z = 0;
4370				this._w = r;
4371
4372			} else {
4373
4374				this._x = 0;
4375				this._y = - vFrom.z;
4376				this._z = vFrom.y;
4377				this._w = r;
4378
4379			}
4380
4381		} else {
4382
4383			// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
4384
4385			this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
4386			this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
4387			this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
4388			this._w = r;
4389
4390		}
4391
4392		return this.normalize();
4393
4394	}
4395
4396	/**
4397	 * Returns the angle between this quaternion and the given one in radians.
4398	 *
4399	 * @param {Quaternion} q - The quaternion to compute the angle with.
4400	 * @return {number} The angle in radians.
4401	 */
4402	angleTo( q ) {
4403
4404		return 2 * Math.acos( Math.abs( clamp( this.dot( q ), -1, 1 ) ) );
4405
4406	}
4407
4408	/**
4409	 * Rotates this quaternion by a given angular step to the given quaternion.
4410	 * The method ensures that the final quaternion will not overshoot `q`.
4411	 *
4412	 * @param {Quaternion} q - The target quaternion.
4413	 * @param {number} step - The angular step in radians.
4414	 * @return {Quaternion} A reference to this quaternion.
4415	 */
4416	rotateTowards( q, step ) {
4417
4418		const angle = this.angleTo( q );
4419
4420		if ( angle === 0 ) return this;
4421
4422		const t = Math.min( 1, step / angle );
4423
4424		this.slerp( q, t );
4425
4426		return this;
4427
4428	}
4429
4430	/**
4431	 * Sets this quaternion to the identity quaternion; that is, to the
4432	 * quaternion that represents "no rotation".
4433	 *
4434	 * @return {Quaternion} A reference to this quaternion.
4435	 */
4436	identity() {
4437
4438		return this.set( 0, 0, 0, 1 );
4439
4440	}
4441
4442	/**
4443	 * Inverts this quaternion via {@link Quaternion#conjugate}. The
4444	 * quaternion is assumed to have unit length.
4445	 *
4446	 * @return {Quaternion} A reference to this quaternion.
4447	 */
4448	invert() {
4449
4450		return this.conjugate();
4451
4452	}
4453
4454	/**
4455	 * Returns the rotational conjugate of this quaternion. The conjugate of a
4456	 * quaternion represents the same rotation in the opposite direction about
4457	 * the rotational axis.
4458	 *
4459	 * @return {Quaternion} A reference to this quaternion.
4460	 */
4461	conjugate() {
4462
4463		this._x *= -1;
4464		this._y *= -1;
4465		this._z *= -1;
4466
4467		this._onChangeCallback();
4468
4469		return this;
4470
4471	}
4472
4473	/**
4474	 * Calculates the dot product of this quaternion and the given one.
4475	 *
4476	 * @param {Quaternion} v - The quaternion to compute the dot product with.
4477	 * @return {number} The result of the dot product.
4478	 */
4479	dot( v ) {
4480
4481		return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
4482
4483	}
4484
4485	/**
4486	 * Computes the squared Euclidean length (straight-line length) of this quaternion,
4487	 * considered as a 4 dimensional vector. This can be useful if you are comparing the
4488	 * lengths of two quaternions, as this is a slightly more efficient calculation than
4489	 * {@link Quaternion#length}.
4490	 *
4491	 * @return {number} The squared Euclidean length.
4492	 */
4493	lengthSq() {
4494
4495		return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
4496
4497	}
4498
4499	/**
4500	 * Computes the Euclidean length (straight-line length) of this quaternion,
4501	 * considered as a 4 dimensional vector.
4502	 *
4503	 * @return {number} The Euclidean length.
4504	 */
4505	length() {
4506
4507		return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
4508
4509	}
4510
4511	/**
4512	 * Normalizes this quaternion - that is, calculated the quaternion that performs
4513	 * the same rotation as this one, but has a length equal to `1`.
4514	 *
4515	 * @return {Quaternion} A reference to this quaternion.
4516	 */
4517	normalize() {
4518
4519		let l = this.length();
4520
4521		if ( l === 0 ) {
4522
4523			this._x = 0;
4524			this._y = 0;
4525			this._z = 0;
4526			this._w = 1;
4527
4528		} else {
4529
4530			l = 1 / l;
4531
4532			this._x = this._x * l;
4533			this._y = this._y * l;
4534			this._z = this._z * l;
4535			this._w = this._w * l;
4536
4537		}
4538
4539		this._onChangeCallback();
4540
4541		return this;
4542
4543	}
4544
4545	/**
4546	 * Multiplies this quaternion by the given one.
4547	 *
4548	 * @param {Quaternion} q - The quaternion.
4549	 * @return {Quaternion} A reference to this quaternion.
4550	 */
4551	multiply( q ) {
4552
4553		return this.multiplyQuaternions( this, q );
4554
4555	}
4556
4557	/**
4558	 * Pre-multiplies this quaternion by the given one.
4559	 *
4560	 * @param {Quaternion} q - The quaternion.
4561	 * @return {Quaternion} A reference to this quaternion.
4562	 */
4563	premultiply( q ) {
4564
4565		return this.multiplyQuaternions( q, this );
4566
4567	}
4568
4569	/**
4570	 * Multiplies the given quaternions and stores the result in this instance.
4571	 *
4572	 * @param {Quaternion} a - The first quaternion.
4573	 * @param {Quaternion} b - The second quaternion.
4574	 * @return {Quaternion} A reference to this quaternion.
4575	 */
4576	multiplyQuaternions( a, b ) {
4577
4578		const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;
4579		const qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;
4580
4581		this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
4582		this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
4583		this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
4584		this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
4585
4586		this._onChangeCallback();
4587
4588		return this;
4589
4590	}
4591
4592	/**
4593	 * Performs a spherical linear interpolation between this quaternion and the target quaternion.
4594	 *
4595	 * @param {Quaternion} qb - The target quaternion.
4596	 * @param {number} t - The interpolation factor. A value in the range `[0,1]` will interpolate. A value outside the range `[0,1]` will extrapolate.
4597	 * @return {Quaternion} A reference to this quaternion.
4598	 */
4599	slerp( qb, t ) {
4600
4601		let x = qb._x, y = qb._y, z = qb._z, w = qb._w;
4602
4603		let dot = this.dot( qb );
4604
4605		if ( dot < 0 ) {
4606
4607			x = - x;
4608			y = - y;
4609			z = - z;
4610			w = - w;
4611
4612			dot = - dot;
4613
4614		}
4615
4616		let s = 1 - t;
4617
4618		if ( dot < 0.9995 ) {
4619
4620			// slerp
4621
4622			const theta = Math.acos( dot );
4623			const sin = Math.sin( theta );
4624
4625			s = Math.sin( s * theta ) / sin;
4626			t = Math.sin( t * theta ) / sin;
4627
4628			this._x = this._x * s + x * t;
4629			this._y = this._y * s + y * t;
4630			this._z = this._z * s + z * t;
4631			this._w = this._w * s + w * t;
4632
4633			this._onChangeCallback();
4634
4635		} else {
4636
4637			// for small angles, lerp then normalize
4638
4639			this._x = this._x * s + x * t;
4640			this._y = this._y * s + y * t;
4641			this._z = this._z * s + z * t;
4642			this._w = this._w * s + w * t;
4643
4644			this.normalize(); // normalize calls _onChangeCallback()
4645
4646		}
4647
4648		return this;
4649
4650	}
4651
4652	/**
4653	 * Performs a spherical linear interpolation between the given quaternions
4654	 * and stores the result in this quaternion.
4655	 *
4656	 * @param {Quaternion} qa - The source quaternion.
4657	 * @param {Quaternion} qb - The target quaternion.
4658	 * @param {number} t - The interpolation factor in the closed interval `[0, 1]`.
4659	 * @return {Quaternion} A reference to this quaternion.
4660	 */
4661	slerpQuaternions( qa, qb, t ) {
4662
4663		return this.copy( qa ).slerp( qb, t );
4664
4665	}
4666
4667	/**
4668	 * Sets this quaternion to a uniformly random, normalized quaternion.
4669	 *
4670	 * @return {Quaternion} A reference to this quaternion.
4671	 */
4672	random() {
4673
4674		// Ken Shoemake
4675		// Uniform random rotations
4676		// D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992.
4677
4678		const theta1 = 2 * Math.PI * Math.random();
4679		const theta2 = 2 * Math.PI * Math.random();
4680
4681		const x0 = Math.random();
4682		const r1 = Math.sqrt( 1 - x0 );
4683		const r2 = Math.sqrt( x0 );
4684
4685		return this.set(
4686			r1 * Math.sin( theta1 ),
4687			r1 * Math.cos( theta1 ),
4688			r2 * Math.sin( theta2 ),
4689			r2 * Math.cos( theta2 ),
4690		);
4691
4692	}
4693
4694	/**
4695	 * Returns `true` if this quaternion is equal with the given one.
4696	 *
4697	 * @param {Quaternion} quaternion - The quaternion to test for equality.
4698	 * @return {boolean} Whether this quaternion is equal with the given one.
4699	 */
4700	equals( quaternion ) {
4701
4702		return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
4703
4704	}
4705
4706	/**
4707	 * Sets this quaternion's components from the given array.
4708	 *
4709	 * @param {Array<number>} array - An array holding the quaternion component values.
4710	 * @param {number} [offset=0] - The offset into the array.
4711	 * @return {Quaternion} A reference to this quaternion.
4712	 */
4713	fromArray( array, offset = 0 ) {
4714
4715		this._x = array[ offset ];
4716		this._y = array[ offset + 1 ];
4717		this._z = array[ offset + 2 ];
4718		this._w = array[ offset + 3 ];
4719
4720		this._onChangeCallback();
4721
4722		return this;
4723
4724	}
4725
4726	/**
4727	 * Writes the components of this quaternion to the given array. If no array is provided,
4728	 * the method returns a new instance.
4729	 *
4730	 * @param {Array<number>} [array=[]] - The target array holding the quaternion components.
4731	 * @param {number} [offset=0] - Index of the first element in the array.
4732	 * @return {Array<number>} The quaternion components.
4733	 */
4734	toArray( array = [], offset = 0 ) {
4735
4736		array[ offset ] = this._x;
4737		array[ offset + 1 ] = this._y;
4738		array[ offset + 2 ] = this._z;
4739		array[ offset + 3 ] = this._w;
4740
4741		return array;
4742
4743	}
4744
4745	/**
4746	 * Sets the components of this quaternion from the given buffer attribute.
4747	 *
4748	 * @param {BufferAttribute} attribute - The buffer attribute holding quaternion data.
4749	 * @param {number} index - The index into the attribute.
4750	 * @return {Quaternion} A reference to this quaternion.
4751	 */
4752	fromBufferAttribute( attribute, index ) {
4753
4754		this._x = attribute.getX( index );
4755		this._y = attribute.getY( index );
4756		this._z = attribute.getZ( index );
4757		this._w = attribute.getW( index );
4758
4759		this._onChangeCallback();
4760
4761		return this;
4762
4763	}
4764
4765	/**
4766	 * This methods defines the serialization result of this class. Returns the
4767	 * numerical elements of this quaternion in an array of format `[x, y, z, w]`.
4768	 *
4769	 * @return {Array<number>} The serialized quaternion.
4770	 */
4771	toJSON() {
4772
4773		return this.toArray();
4774
4775	}
4776
4777	_onChange( callback ) {
4778
4779		this._onChangeCallback = callback;
4780
4781		return this;
4782
4783	}
4784
4785	_onChangeCallback() {}
4786
4787	*[ Symbol.iterator ]() {
4788
4789		yield this._x;
4790		yield this._y;
4791		yield this._z;
4792		yield this._w;
4793
4794	}
4795
4796}
4797
4798/**
4799 * Class representing a 3D vector. A 3D vector is an ordered triplet of numbers
4800 * (labeled x, y and z), which can be used to represent a number of things, such as:
4801 *
4802 * - A point in 3D space.
4803 * - A direction and length in 3D space. In three.js the length will
4804 * always be the Euclidean distance(straight-line distance) from `(0, 0, 0)` to `(x, y, z)`
4805 * and the direction is also measured from `(0, 0, 0)` towards `(x, y, z)`.
4806 * - Any arbitrary ordered triplet of numbers.
4807 *
4808 * There are other things a 3D vector can be used to represent, such as
4809 * momentum vectors and so on, however these are the most
4810 * common uses in three.js.
4811 *
4812 * Iterating through a vector instance will yield its components `(x, y, z)` in
4813 * the corresponding order.
4814 * ```js
4815 * const a = new THREE.Vector3( 0, 1, 0 );
4816 *
4817 * //no arguments; will be initialised to (0, 0, 0)
4818 * const b = new THREE.Vector3( );
4819 *
4820 * const d = a.distanceTo( b );
4821 * ```
4822 */
4823class Vector3 {
4824
4825	static {
4826
4827		/**
4828		 * This flag can be used for type testing.
4829		 *
4830		 * @type {boolean}
4831		 * @readonly
4832		 * @default true
4833		 */
4834		Vector3.prototype.isVector3 = true;
4835
4836	}
4837
4838	/**
4839	 * Constructs a new 3D vector.
4840	 *
4841	 * @param {number} [x=0] - The x value of this vector.
4842	 * @param {number} [y=0] - The y value of this vector.
4843	 * @param {number} [z=0] - The z value of this vector.
4844	 */
4845	constructor( x = 0, y = 0, z = 0 ) {
4846
4847		/**
4848		 * The x value of this vector.
4849		 *
4850		 * @type {number}
4851		 */
4852		this.x = x;
4853
4854		/**
4855		 * The y value of this vector.
4856		 *
4857		 * @type {number}
4858		 */
4859		this.y = y;
4860
4861		/**
4862		 * The z value of this vector.
4863		 *
4864		 * @type {number}
4865		 */
4866		this.z = z;
4867
4868	}
4869
4870	/**
4871	 * Sets the vector components.
4872	 *
4873	 * @param {number} x - The value of the x component.
4874	 * @param {number} y - The value of the y component.
4875	 * @param {number} z - The value of the z component.
4876	 * @return {Vector3} A reference to this vector.
4877	 */
4878	set( x, y, z ) {
4879
4880		if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
4881
4882		this.x = x;
4883		this.y = y;
4884		this.z = z;
4885
4886		return this;
4887
4888	}
4889
4890	/**
4891	 * Sets the vector components to the same value.
4892	 *
4893	 * @param {number} scalar - The value to set for all vector components.
4894	 * @return {Vector3} A reference to this vector.
4895	 */
4896	setScalar( scalar ) {
4897
4898		this.x = scalar;
4899		this.y = scalar;
4900		this.z = scalar;
4901
4902		return this;
4903
4904	}
4905
4906	/**
4907	 * Sets the vector's x component to the given value.
4908	 *
4909	 * @param {number} x - The value to set.
4910	 * @return {Vector3} A reference to this vector.
4911	 */
4912	setX( x ) {
4913
4914		this.x = x;
4915
4916		return this;
4917
4918	}
4919
4920	/**
4921	 * Sets the vector's y component to the given value.
4922	 *
4923	 * @param {number} y - The value to set.
4924	 * @return {Vector3} A reference to this vector.
4925	 */
4926	setY( y ) {
4927
4928		this.y = y;
4929
4930		return this;
4931
4932	}
4933
4934	/**
4935	 * Sets the vector's z component to the given value.
4936	 *
4937	 * @param {number} z - The value to set.
4938	 * @return {Vector3} A reference to this vector.
4939	 */
4940	setZ( z ) {
4941
4942		this.z = z;
4943
4944		return this;
4945
4946	}
4947
4948	/**
4949	 * Allows to set a vector component with an index.
4950	 *
4951	 * @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.
4952	 * @param {number} value - The value to set.
4953	 * @return {Vector3} A reference to this vector.
4954	 */
4955	setComponent( index, value ) {
4956
4957		switch ( index ) {
4958
4959			case 0: this.x = value; break;
4960			case 1: this.y = value; break;
4961			case 2: this.z = value; break;
4962			default: throw new Error( 'THREE.Vector3: index is out of range: ' + index );
4963
4964		}
4965
4966		return this;
4967
4968	}
4969
4970	/**
4971	 * Returns the value of the vector component which matches the given index.
4972	 *
4973	 * @param {number} index - The component index. `0` equals to x, `1` equals to y, `2` equals to z.
4974	 * @return {number} A vector component value.
4975	 */
4976	getComponent( index ) {
4977
4978		switch ( index ) {
4979
4980			case 0: return this.x;
4981			case 1: return this.y;
4982			case 2: return this.z;
4983			default: throw new Error( 'THREE.Vector3: index is out of range: ' + index );
4984
4985		}
4986
4987	}
4988
4989	/**
4990	 * Returns a new vector with copied values from this instance.
4991	 *
4992	 * @return {Vector3} A clone of this instance.
4993	 */
4994	clone() {
4995
4996		return new this.constructor( this.x, this.y, this.z );
4997
4998	}
4999
5000	/**
5001	 * Copies the values of the given vector to this instance.
5002	 *
5003	 * @param {Vector3} v - The vector to copy.
5004	 * @return {Vector3} A reference to this vector.
5005	 */
5006	copy( v ) {
5007
5008		this.x = v.x;
5009		this.y = v.y;
5010		this.z = v.z;
5011
5012		return this;
5013
5014	}
5015
5016	/**
5017	 * Adds the given vector to this instance.
5018	 *
5019	 * @param {Vector3} v - The vector to add.
5020	 * @return {Vector3} A reference to this vector.
5021	 */
5022	add( v ) {
5023
5024		this.x += v.x;
5025		this.y += v.y;
5026		this.z += v.z;
5027
5028		return this;
5029
5030	}
5031
5032	/**
5033	 * Adds the given scalar value to all components of this instance.
5034	 *
5035	 * @param {number} s - The scalar to add.
5036	 * @return {Vector3} A reference to this vector.
5037	 */
5038	addScalar( s ) {
5039
5040		this.x += s;
5041		this.y += s;
5042		this.z += s;
5043
5044		return this;
5045
5046	}
5047
5048	/**
5049	 * Adds the given vectors and stores the result in this instance.
5050	 *
5051	 * @param {Vector3} a - The first vector.
5052	 * @param {Vector3} b - The second vector.
5053	 * @return {Vector3} A reference to this vector.
5054	 */
5055	addVectors( a, b ) {
5056
5057		this.x = a.x + b.x;
5058		this.y = a.y + b.y;
5059		this.z = a.z + b.z;
5060
5061		return this;
5062
5063	}
5064
5065	/**
5066	 * Adds the given vector scaled by the given factor to this instance.
5067	 *
5068	 * @param {Vector3|Vector4} v - The vector.
5069	 * @param {number} s - The factor that scales `v`.
5070	 * @return {Vector3} A reference to this vector.
5071	 */
5072	addScaledVector( v, s ) {
5073
5074		this.x += v.x * s;
5075		this.y += v.y * s;
5076		this.z += v.z * s;
5077
5078		return this;
5079
5080	}
5081
5082	/**
5083	 * Subtracts the given vector from this instance.
5084	 *
5085	 * @param {Vector3} v - The vector to subtract.
5086	 * @return {Vector3} A reference to this vector.
5087	 */
5088	sub( v ) {
5089
5090		this.x -= v.x;
5091		this.y -= v.y;
5092		this.z -= v.z;
5093
5094		return this;
5095
5096	}
5097
5098	/**
5099	 * Subtracts the given scalar value from all components of this instance.
5100	 *
5101	 * @param {number} s - The scalar to subtract.
5102	 * @return {Vector3} A reference to this vector.
5103	 */
5104	subScalar( s ) {
5105
5106		this.x -= s;
5107		this.y -= s;
5108		this.z -= s;
5109
5110		return this;
5111
5112	}
5113
5114	/**
5115	 * Subtracts the given vectors and stores the result in this instance.
5116	 *
5117	 * @param {Vector3} a - The first vector.
5118	 * @param {Vector3} b - The second vector.
5119	 * @return {Vector3} A reference to this vector.
5120	 */
5121	subVectors( a, b ) {
5122
5123		this.x = a.x - b.x;
5124		this.y = a.y - b.y;
5125		this.z = a.z - b.z;
5126
5127		return this;
5128
5129	}
5130
5131	/**
5132	 * Multiplies the given vector with this instance.
5133	 *
5134	 * @param {Vector3} v - The vector to multiply.
5135	 * @return {Vector3} A reference to this vector.
5136	 */
5137	multiply( v ) {
5138
5139		this.x *= v.x;
5140		this.y *= v.y;
5141		this.z *= v.z;
5142
5143		return this;
5144
5145	}
5146
5147	/**
5148	 * Multiplies the given scalar value with all components of this instance.
5149	 *
5150	 * @param {number} scalar - The scalar to multiply.
5151	 * @return {Vector3} A reference to this vector.
5152	 */
5153	multiplyScalar( scalar ) {
5154
5155		this.x *= scalar;
5156		this.y *= scalar;
5157		this.z *= scalar;
5158
5159		return this;
5160
5161	}
5162
5163	/**
5164	 * Multiplies the given vectors and stores the result in this instance.
5165	 *
5166	 * @param {Vector3} a - The first vector.
5167	 * @param {Vector3} b - The second vector.
5168	 * @return {Vector3} A reference to this vector.
5169	 */
5170	multiplyVectors( a, b ) {
5171
5172		this.x = a.x * b.x;
5173		this.y = a.y * b.y;
5174		this.z = a.z * b.z;
5175
5176		return this;
5177
5178	}
5179
5180	/**
5181	 * Applies the given Euler rotation to this vector.
5182	 *
5183	 * @param {Euler} euler - The Euler angles.
5184	 * @return {Vector3} A reference to this vector.
5185	 */
5186	applyEuler( euler ) {
5187
5188		return this.applyQuaternion( _quaternion$5.setFromEuler( euler ) );
5189
5190	}
5191
5192	/**
5193	 * Applies a rotation specified by an axis and an angle to this vector.
5194	 *
5195	 * @param {Vector3} axis - A normalized vector representing the rotation axis.
5196	 * @param {number} angle - The angle in radians.
5197	 * @return {Vector3} A reference to this vector.
5198	 */
5199	applyAxisAngle( axis, angle ) {
5200
5201		return this.applyQuaternion( _quaternion$5.setFromAxisAngle( axis, angle ) );
5202
5203	}
5204
5205	/**
5206	 * Multiplies this vector with the given 3x3 matrix.
5207	 *
5208	 * @param {Matrix3} m - The 3x3 matrix.
5209	 * @return {Vector3} A reference to this vector.
5210	 */
5211	applyMatrix3( m ) {
5212
5213		const x = this.x, y = this.y, z = this.z;
5214		const e = m.elements;
5215
5216		this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
5217		this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
5218		this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
5219
5220		return this;
5221
5222	}
5223
5224	/**
5225	 * Multiplies this vector by the given normal matrix and normalizes
5226	 * the result.
5227	 *
5228	 * @param {Matrix3} m - The normal matrix.
5229	 * @return {Vector3} A reference to this vector.
5230	 */
5231	applyNormalMatrix( m ) {
5232
5233		return this.applyMatrix3( m ).normalize();
5234
5235	}
5236
5237	/**
5238	 * Multiplies this vector (with an implicit 1 in the 4th dimension) by m, and
5239	 * divides by perspective.
5240	 *
5241	 * @param {Matrix4} m - The matrix to apply.
5242	 * @return {Vector3} A reference to this vector.
5243	 */
5244	applyMatrix4( m ) {
5245
5246		const x = this.x, y = this.y, z = this.z;
5247		const e = m.elements;
5248
5249		const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );
5250
5251		this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;
5252		this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;
5253		this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;
5254
5255		return this;
5256
5257	}
5258
5259	/**
5260	 * Applies the given Quaternion to this vector.
5261	 *
5262	 * @param {Quaternion} q - The Quaternion.
5263	 * @return {Vector3} A reference to this vector.
5264	 */
5265	applyQuaternion( q ) {
5266
5267		// quaternion q is assumed to have unit length
5268
5269		const vx = this.x, vy = this.y, vz = this.z;
5270		const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
5271
5272		// t = 2 * cross( q.xyz, v );
5273		const tx = 2 * ( qy * vz - qz * vy );
5274		const ty = 2 * ( qz * vx - qx * vz );
5275		const tz = 2 * ( qx * vy - qy * vx );
5276
5277		// v + q.w * t + cross( q.xyz, t );
5278		this.x = vx + qw * tx + qy * tz - qz * ty;
5279		this.y = vy + qw * ty + qz * tx - qx * tz;
5280		this.z = vz + qw * tz + qx * ty - qy * tx;
5281
5282		return this;
5283
5284	}
5285
5286	/**
5287	 * Projects this vector from world space into the camera's normalized
5288	 * device coordinate (NDC) space.
5289	 *
5290	 * @param {Camera} camera - The camera.
5291	 * @return {Vector3} A reference to this vector.
5292	 */
5293	project( camera ) {
5294
5295		return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
5296
5297	}
5298
5299	/**
5300	 * Unprojects this vector from the camera's normalized device coordinate (NDC)
5301	 * space into world space.
5302	 *
5303	 * @param {Camera} camera - The camera.
5304	 * @return {Vector3} A reference to this vector.
5305	 */
5306	unproject( camera ) {
5307
5308		return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
5309
5310	}
5311
5312	/**
5313	 * Transforms this vector by the upper left 3x3 sub-matrix of the given 4x4 matrix,
5314	 * and normalizes the result.
5315	 *
5316	 * @param {Matrix4} m - The matrix.
5317	 * @return {Vector3} A reference to this vector.
5318	 */
5319	transformDirection( m ) {
5320
5321		// input: THREE.Matrix4 affine matrix
5322		// vector interpreted as a direction
5323
5324		const x = this.x, y = this.y, z = this.z;
5325		const e = m.elements;
5326
5327		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
5328		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
5329		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
5330
5331		return this.normalize();
5332
5333	}
5334
5335	/**
5336	 * Divides this instance by the given vector.
5337	 *
5338	 * @param {Vector3} v - The vector to divide.
5339	 * @return {Vector3} A reference to this vector.
5340	 */
5341	divide( v ) {
5342
5343		this.x /= v.x;
5344		this.y /= v.y;
5345		this.z /= v.z;
5346
5347		return this;
5348
5349	}
5350
5351	/**
5352	 * Divides this vector by the given scalar.
5353	 *
5354	 * @param {number} scalar - The scalar to divide.
5355	 * @return {Vector3} A reference to this vector.
5356	 */
5357	divideScalar( scalar ) {
5358
5359		return this.multiplyScalar( 1 / scalar );
5360
5361	}
5362
5363	/**
5364	 * If this vector's x, y or z value is greater than the given vector's x, y or z
5365	 * value, replace that value with the corresponding min value.
5366	 *
5367	 * @param {Vector3} v - The vector.
5368	 * @return {Vector3} A reference to this vector.
5369	 */
5370	min( v ) {
5371
5372		this.x = Math.min( this.x, v.x );
5373		this.y = Math.min( this.y, v.y );
5374		this.z = Math.min( this.z, v.z );
5375
5376		return this;
5377
5378	}
5379
5380	/**
5381	 * If this vector's x, y or z value is less than the given vector's x, y or z
5382	 * value, replace that value with the corresponding max value.
5383	 *
5384	 * @param {Vector3} v - The vector.
5385	 * @return {Vector3} A reference to this vector.
5386	 */
5387	max( v ) {
5388
5389		this.x = Math.max( this.x, v.x );
5390		this.y = Math.max( this.y, v.y );
5391		this.z = Math.max( this.z, v.z );
5392
5393		return this;
5394
5395	}
5396
5397	/**
5398	 * If this vector's x, y or z value is greater than the max vector's x, y or z
5399	 * value, it is replaced by the corresponding value.
5400	 * If this vector's x, y or z value is less than the min vector's x, y or z value,
5401	 * it is replaced by the corresponding value.
5402	 *
5403	 * @param {Vector3} min - The minimum x, y and z values.
5404	 * @param {Vector3} max - The maximum x, y and z values in the desired range.
5405	 * @return {Vector3} A reference to this vector.
5406	 */
5407	clamp( min, max ) {
5408
5409		// assumes min < max, componentwise
5410
5411		this.x = clamp( this.x, min.x, max.x );
5412		this.y = clamp( this.y, min.y, max.y );
5413		this.z = clamp( this.z, min.z, max.z );
5414
5415		return this;
5416
5417	}
5418
5419	/**
5420	 * If this vector's x, y or z values are greater than the max value, they are
5421	 * replaced by the max value.
5422	 * If this vector's x, y or z values are less than the min value, they are
5423	 * replaced by the min value.
5424	 *
5425	 * @param {number} minVal - The minimum value the components will be clamped to.
5426	 * @param {number} maxVal - The maximum value the components will be clamped to.
5427	 * @return {Vector3} A reference to this vector.
5428	 */
5429	clampScalar( minVal, maxVal ) {
5430
5431		this.x = clamp( this.x, minVal, maxVal );
5432		this.y = clamp( this.y, minVal, maxVal );
5433		this.z = clamp( this.z, minVal, maxVal );
5434
5435		return this;
5436
5437	}
5438
5439	/**
5440	 * If this vector's length is greater than the max value, it is replaced by
5441	 * the max value.
5442	 * If this vector's length is less than the min value, it is replaced by the
5443	 * min value.
5444	 *
5445	 * @param {number} min - The minimum value the vector length will be clamped to.
5446	 * @param {number} max - The maximum value the vector length will be clamped to.
5447	 * @return {Vector3} A reference to this vector.
5448	 */
5449	clampLength( min, max ) {
5450
5451		const length = this.length();
5452
5453		return this.divideScalar( length || 1 ).multiplyScalar( clamp( length, min, max ) );
5454
5455	}
5456
5457	/**
5458	 * The components of this vector are rounded down to the nearest integer value.
5459	 *
5460	 * @return {Vector3} A reference to this vector.
5461	 */
5462	floor() {
5463
5464		this.x = Math.floor( this.x );
5465		this.y = Math.floor( this.y );
5466		this.z = Math.floor( this.z );
5467
5468		return this;
5469
5470	}
5471
5472	/**
5473	 * The components of this vector are rounded up to the nearest integer value.
5474	 *
5475	 * @return {Vector3} A reference to this vector.
5476	 */
5477	ceil() {
5478
5479		this.x = Math.ceil( this.x );
5480		this.y = Math.ceil( this.y );
5481		this.z = Math.ceil( this.z );
5482
5483		return this;
5484
5485	}
5486
5487	/**
5488	 * The components of this vector are rounded to the nearest integer value
5489	 *
5490	 * @return {Vector3} A reference to this vector.
5491	 */
5492	round() {
5493
5494		this.x = Math.round( this.x );
5495		this.y = Math.round( this.y );
5496		this.z = Math.round( this.z );
5497
5498		return this;
5499
5500	}
5501
5502	/**
5503	 * The components of this vector are rounded towards zero (up if negative,
5504	 * down if positive) to an integer value.
5505	 *
5506	 * @return {Vector3} A reference to this vector.
5507	 */
5508	roundToZero() {
5509
5510		this.x = Math.trunc( this.x );
5511		this.y = Math.trunc( this.y );
5512		this.z = Math.trunc( this.z );
5513
5514		return this;
5515
5516	}
5517
5518	/**
5519	 * Inverts this vector - i.e. sets x = -x, y = -y and z = -z.
5520	 *
5521	 * @return {Vector3} A reference to this vector.
5522	 */
5523	negate() {
5524
5525		this.x = - this.x;
5526		this.y = - this.y;
5527		this.z = - this.z;
5528
5529		return this;
5530
5531	}
5532
5533	/**
5534	 * Calculates the dot product of the given vector with this instance.
5535	 *
5536	 * @param {Vector3} v - The vector to compute the dot product with.
5537	 * @return {number} The result of the dot product.
5538	 */
5539	dot( v ) {
5540
5541		return this.x * v.x + this.y * v.y + this.z * v.z;
5542
5543	}
5544
5545	/**
5546	 * Computes the square of the Euclidean length (straight-line length) from
5547	 * (0, 0, 0) to (x, y, z). If you are comparing the lengths of vectors, you should
5548	 * compare the length squared instead as it is slightly more efficient to calculate.
5549	 *
5550	 * @return {number} The square length of this vector.
5551	 */
5552	lengthSq() {
5553
5554		return this.x * this.x + this.y * this.y + this.z * this.z;
5555
5556	}
5557
5558	/**
5559	 * Computes the  Euclidean length (straight-line length) from (0, 0, 0) to (x, y, z).
5560	 *
5561	 * @return {number} The length of this vector.
5562	 */
5563	length() {
5564
5565		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
5566
5567	}
5568
5569	/**
5570	 * Computes the Manhattan length of this vector.
5571	 *
5572	 * @return {number} The length of this vector.
5573	 */
5574	manhattanLength() {
5575
5576		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
5577
5578	}
5579
5580	/**
5581	 * Converts this vector to a unit vector - that is, sets it equal to a vector
5582	 * with the same direction as this one, but with a vector length of `1`.
5583	 *
5584	 * @return {Vector3} A reference to this vector.
5585	 */
5586	normalize() {
5587
5588		return this.divideScalar( this.length() || 1 );
5589
5590	}
5591
5592	/**
5593	 * Sets this vector to a vector with the same direction as this one, but
5594	 * with the specified length.
5595	 *
5596	 * @param {number} length - The new length of this vector.
5597	 * @return {Vector3} A reference to this vector.
5598	 */
5599	setLength( length ) {
5600
5601		return this.normalize().multiplyScalar( length );
5602
5603	}
5604
5605	/**
5606	 * Linearly interpolates between the given vector and this instance, where
5607	 * alpha is the percent distance along the line - alpha = 0 will be this
5608	 * vector, and alpha = 1 will be the given one.
5609	 *
5610	 * @param {Vector3} v - The vector to interpolate towards.
5611	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
5612	 * @return {Vector3} A reference to this vector.
5613	 */
5614	lerp( v, alpha ) {
5615
5616		this.x += ( v.x - this.x ) * alpha;
5617		this.y += ( v.y - this.y ) * alpha;
5618		this.z += ( v.z - this.z ) * alpha;
5619
5620		return this;
5621
5622	}
5623
5624	/**
5625	 * Linearly interpolates between the given vectors, where alpha is the percent
5626	 * distance along the line - alpha = 0 will be first vector, and alpha = 1 will
5627	 * be the second one. The result is stored in this instance.
5628	 *
5629	 * @param {Vector3} v1 - The first vector.
5630	 * @param {Vector3} v2 - The second vector.
5631	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
5632	 * @return {Vector3} A reference to this vector.
5633	 */
5634	lerpVectors( v1, v2, alpha ) {
5635
5636		this.x = v1.x + ( v2.x - v1.x ) * alpha;
5637		this.y = v1.y + ( v2.y - v1.y ) * alpha;
5638		this.z = v1.z + ( v2.z - v1.z ) * alpha;
5639
5640		return this;
5641
5642	}
5643
5644	/**
5645	 * Calculates the cross product of the given vector with this instance.
5646	 *
5647	 * @param {Vector3} v - The vector to compute the cross product with.
5648	 * @return {Vector3} The result of the cross product.
5649	 */
5650	cross( v ) {
5651
5652		return this.crossVectors( this, v );
5653
5654	}
5655
5656	/**
5657	 * Calculates the cross product of the given vectors and stores the result
5658	 * in this instance.
5659	 *
5660	 * @param {Vector3} a - The first vector.
5661	 * @param {Vector3} b - The second vector.
5662	 * @return {Vector3} A reference to this vector.
5663	 */
5664	crossVectors( a, b ) {
5665
5666		const ax = a.x, ay = a.y, az = a.z;
5667		const bx = b.x, by = b.y, bz = b.z;
5668
5669		this.x = ay * bz - az * by;
5670		this.y = az * bx - ax * bz;
5671		this.z = ax * by - ay * bx;
5672
5673		return this;
5674
5675	}
5676
5677	/**
5678	 * Projects this vector onto the given one.
5679	 *
5680	 * @param {Vector3} v - The vector to project to.
5681	 * @return {Vector3} A reference to this vector.
5682	 */
5683	projectOnVector( v ) {
5684
5685		const denominator = v.lengthSq();
5686
5687		if ( denominator === 0 ) return this.set( 0, 0, 0 );
5688
5689		const scalar = v.dot( this ) / denominator;
5690
5691		return this.copy( v ).multiplyScalar( scalar );
5692
5693	}
5694
5695	/**
5696	 * Projects this vector onto a plane by subtracting this
5697	 * vector projected onto the plane's normal from this vector.
5698	 *
5699	 * @param {Vector3} planeNormal - The plane normal.
5700	 * @return {Vector3} A reference to this vector.
5701	 */
5702	projectOnPlane( planeNormal ) {
5703
5704		_vector$c.copy( this ).projectOnVector( planeNormal );
5705
5706		return this.sub( _vector$c );
5707
5708	}
5709
5710	/**
5711	 * Reflects this vector off a plane orthogonal to the given normal vector.
5712	 *
5713	 * @param {Vector3} normal - The (normalized) normal vector.
5714	 * @return {Vector3} A reference to this vector.
5715	 */
5716	reflect( normal ) {
5717
5718		return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
5719
5720	}
5721	/**
5722	 * Returns the angle between the given vector and this instance in radians.
5723	 *
5724	 * @param {Vector3} v - The vector to compute the angle with.
5725	 * @return {number} The angle in radians.
5726	 */
5727	angleTo( v ) {
5728
5729		const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );
5730
5731		if ( denominator === 0 ) return Math.PI / 2;
5732
5733		const theta = this.dot( v ) / denominator;
5734
5735		// clamp, to handle numerical problems
5736
5737		return Math.acos( clamp( theta, -1, 1 ) );
5738
5739	}
5740
5741	/**
5742	 * Computes the distance from the given vector to this instance.
5743	 *
5744	 * @param {Vector3} v - The vector to compute the distance to.
5745	 * @return {number} The distance.
5746	 */
5747	distanceTo( v ) {
5748
5749		return Math.sqrt( this.distanceToSquared( v ) );
5750
5751	}
5752
5753	/**
5754	 * Computes the squared distance from the given vector to this instance.
5755	 * If you are just comparing the distance with another distance, you should compare
5756	 * the distance squared instead as it is slightly more efficient to calculate.
5757	 *
5758	 * @param {Vector3} v - The vector to compute the squared distance to.
5759	 * @return {number} The squared distance.
5760	 */
5761	distanceToSquared( v ) {
5762
5763		const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
5764
5765		return dx * dx + dy * dy + dz * dz;
5766
5767	}
5768
5769	/**
5770	 * Computes the Manhattan distance from the given vector to this instance.
5771	 *
5772	 * @param {Vector3} v - The vector to compute the Manhattan distance to.
5773	 * @return {number} The Manhattan distance.
5774	 */
5775	manhattanDistanceTo( v ) {
5776
5777		return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
5778
5779	}
5780
5781	/**
5782	 * Sets the vector components from the given spherical coordinates.
5783	 *
5784	 * @param {Spherical} s - The spherical coordinates.
5785	 * @return {Vector3} A reference to this vector.
5786	 */
5787	setFromSpherical( s ) {
5788
5789		return this.setFromSphericalCoords( s.radius, s.phi, s.theta );
5790
5791	}
5792
5793	/**
5794	 * Sets the vector components from the given spherical coordinates.
5795	 *
5796	 * @param {number} radius - The radius.
5797	 * @param {number} phi - The phi angle in radians.
5798	 * @param {number} theta - The theta angle in radians.
5799	 * @return {Vector3} A reference to this vector.
5800	 */
5801	setFromSphericalCoords( radius, phi, theta ) {
5802
5803		const sinPhiRadius = Math.sin( phi ) * radius;
5804
5805		this.x = sinPhiRadius * Math.sin( theta );
5806		this.y = Math.cos( phi ) * radius;
5807		this.z = sinPhiRadius * Math.cos( theta );
5808
5809		return this;
5810
5811	}
5812
5813	/**
5814	 * Sets the vector components from the given cylindrical coordinates.
5815	 *
5816	 * @param {Cylindrical} c - The cylindrical coordinates.
5817	 * @return {Vector3} A reference to this vector.
5818	 */
5819	setFromCylindrical( c ) {
5820
5821		return this.setFromCylindricalCoords( c.radius, c.theta, c.y );
5822
5823	}
5824
5825	/**
5826	 * Sets the vector components from the given cylindrical coordinates.
5827	 *
5828	 * @param {number} radius - The radius.
5829	 * @param {number} theta - The theta angle in radians.
5830	 * @param {number} y - The y value.
5831	 * @return {Vector3} A reference to this vector.
5832	 */
5833	setFromCylindricalCoords( radius, theta, y ) {
5834
5835		this.x = radius * Math.sin( theta );
5836		this.y = y;
5837		this.z = radius * Math.cos( theta );
5838
5839		return this;
5840
5841	}
5842
5843	/**
5844	 * Sets the vector components to the position elements of the
5845	 * given transformation matrix.
5846	 *
5847	 * @param {Matrix4} m - The 4x4 matrix.
5848	 * @return {Vector3} A reference to this vector.
5849	 */
5850	setFromMatrixPosition( m ) {
5851
5852		const e = m.elements;
5853
5854		this.x = e[ 12 ];
5855		this.y = e[ 13 ];
5856		this.z = e[ 14 ];
5857
5858		return this;
5859
5860	}
5861
5862	/**
5863	 * Sets the vector components to the scale elements of the
5864	 * given transformation matrix.
5865	 *
5866	 * @param {Matrix4} m - The 4x4 matrix.
5867	 * @return {Vector3} A reference to this vector.
5868	 */
5869	setFromMatrixScale( m ) {
5870
5871		const sx = this.setFromMatrixColumn( m, 0 ).length();
5872		const sy = this.setFromMatrixColumn( m, 1 ).length();
5873		const sz = this.setFromMatrixColumn( m, 2 ).length();
5874
5875		this.x = sx;
5876		this.y = sy;
5877		this.z = sz;
5878
5879		return this;
5880
5881	}
5882
5883	/**
5884	 * Sets the vector components from the specified matrix column.
5885	 *
5886	 * @param {Matrix4} m - The 4x4 matrix.
5887	 * @param {number} index - The column index.
5888	 * @return {Vector3} A reference to this vector.
5889	 */
5890	setFromMatrixColumn( m, index ) {
5891
5892		return this.fromArray( m.elements, index * 4 );
5893
5894	}
5895
5896	/**
5897	 * Sets the vector components from the specified matrix column.
5898	 *
5899	 * @param {Matrix3} m - The 3x3 matrix.
5900	 * @param {number} index - The column index.
5901	 * @return {Vector3} A reference to this vector.
5902	 */
5903	setFromMatrix3Column( m, index ) {
5904
5905		return this.fromArray( m.elements, index * 3 );
5906
5907	}
5908
5909	/**
5910	 * Sets the vector components from the given Euler angles.
5911	 *
5912	 * @param {Euler} e - The Euler angles to set.
5913	 * @return {Vector3} A reference to this vector.
5914	 */
5915	setFromEuler( e ) {
5916
5917		this.x = e._x;
5918		this.y = e._y;
5919		this.z = e._z;
5920
5921		return this;
5922
5923	}
5924
5925	/**
5926	 * Sets the vector components from the RGB components of the
5927	 * given color.
5928	 *
5929	 * @param {Color} c - The color to set.
5930	 * @return {Vector3} A reference to this vector.
5931	 */
5932	setFromColor( c ) {
5933
5934		this.x = c.r;
5935		this.y = c.g;
5936		this.z = c.b;
5937
5938		return this;
5939
5940	}
5941
5942	/**
5943	 * Returns `true` if this vector is equal with the given one.
5944	 *
5945	 * @param {Vector3} v - The vector to test for equality.
5946	 * @return {boolean} Whether this vector is equal with the given one.
5947	 */
5948	equals( v ) {
5949
5950		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
5951
5952	}
5953
5954	/**
5955	 * Sets this vector's x value to be `array[ offset ]`, y value to be `array[ offset + 1 ]`
5956	 * and z value to be `array[ offset + 2 ]`.
5957	 *
5958	 * @param {Array<number>} array - An array holding the vector component values.
5959	 * @param {number} [offset=0] - The offset into the array.
5960	 * @return {Vector3} A reference to this vector.
5961	 */
5962	fromArray( array, offset = 0 ) {
5963
5964		this.x = array[ offset ];
5965		this.y = array[ offset + 1 ];
5966		this.z = array[ offset + 2 ];
5967
5968		return this;
5969
5970	}
5971
5972	/**
5973	 * Writes the components of this vector to the given array. If no array is provided,
5974	 * the method returns a new instance.
5975	 *
5976	 * @param {Array<number>} [array=[]] - The target array holding the vector components.
5977	 * @param {number} [offset=0] - Index of the first element in the array.
5978	 * @return {Array<number>} The vector components.
5979	 */
5980	toArray( array = [], offset = 0 ) {
5981
5982		array[ offset ] = this.x;
5983		array[ offset + 1 ] = this.y;
5984		array[ offset + 2 ] = this.z;
5985
5986		return array;
5987
5988	}
5989
5990	/**
5991	 * Sets the components of this vector from the given buffer attribute.
5992	 *
5993	 * @param {BufferAttribute} attribute - The buffer attribute holding vector data.
5994	 * @param {number} index - The index into the attribute.
5995	 * @return {Vector3} A reference to this vector.
5996	 */
5997	fromBufferAttribute( attribute, index ) {
5998
5999		this.x = attribute.getX( index );
6000		this.y = attribute.getY( index );
6001		this.z = attribute.getZ( index );
6002
6003		return this;
6004
6005	}
6006
6007	/**
6008	 * Sets each component of this vector to a pseudo-random value between `0` and
6009	 * `1`, excluding `1`.
6010	 *
6011	 * @return {Vector3} A reference to this vector.
6012	 */
6013	random() {
6014
6015		this.x = Math.random();
6016		this.y = Math.random();
6017		this.z = Math.random();
6018
6019		return this;
6020
6021	}
6022
6023	/**
6024	 * Sets this vector to a uniformly random point on a unit sphere.
6025	 *
6026	 * @return {Vector3} A reference to this vector.
6027	 */
6028	randomDirection() {
6029
6030		// https://mathworld.wolfram.com/SpherePointPicking.html
6031
6032		const theta = Math.random() * Math.PI * 2;
6033		const u = Math.random() * 2 - 1;
6034		const c = Math.sqrt( 1 - u * u );
6035
6036		this.x = c * Math.cos( theta );
6037		this.y = u;
6038		this.z = c * Math.sin( theta );
6039
6040		return this;
6041
6042	}
6043
6044	*[ Symbol.iterator ]() {
6045
6046		yield this.x;
6047		yield this.y;
6048		yield this.z;
6049
6050	}
6051
6052}
6053
6054const _vector$c = /*@__PURE__*/ new Vector3();
6055const _quaternion$5 = /*@__PURE__*/ new Quaternion();
6056
6057/**
6058 * Represents a 3x3 matrix.
6059 *
6060 * A Note on Row-Major and Column-Major Ordering:
6061 *
6062 * The constructor and {@link Matrix3#set} method take arguments in
6063 * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order)
6064 * order, while internally they are stored in the {@link Matrix3#elements} array in column-major order.
6065 * This means that calling:
6066 * ```js
6067 * const m = new THREE.Matrix();
6068 * m.set( 11, 12, 13,
6069 *        21, 22, 23,
6070 *        31, 32, 33 );
6071 * ```
6072 * will result in the elements array containing:
6073 * ```js
6074 * m.elements = [ 11, 21, 31,
6075 *                12, 22, 32,
6076 *                13, 23, 33 ];
6077 * ```
6078 * and internally all calculations are performed using column-major ordering.
6079 * However, as the actual ordering makes no difference mathematically and
6080 * most people are used to thinking about matrices in row-major order, the
6081 * three.js documentation shows matrices in row-major order. Just bear in
6082 * mind that if you are reading the source code, you'll have to take the
6083 * transpose of any matrices outlined here to make sense of the calculations.
6084 */
6085class Matrix3 {
6086
6087	static {
6088
6089		/**
6090		 * This flag can be used for type testing.
6091		 *
6092		 * @type {boolean}
6093		 * @readonly
6094		 * @default true
6095		 */
6096		Matrix3.prototype.isMatrix3 = true;
6097
6098	}
6099
6100	/**
6101	 * Constructs a new 3x3 matrix. The arguments are supposed to be
6102	 * in row-major order. If no arguments are provided, the constructor
6103	 * initializes the matrix as an identity matrix.
6104	 *
6105	 * @param {number} [n11] - 1-1 matrix element.
6106	 * @param {number} [n12] - 1-2 matrix element.
6107	 * @param {number} [n13] - 1-3 matrix element.
6108	 * @param {number} [n21] - 2-1 matrix element.
6109	 * @param {number} [n22] - 2-2 matrix element.
6110	 * @param {number} [n23] - 2-3 matrix element.
6111	 * @param {number} [n31] - 3-1 matrix element.
6112	 * @param {number} [n32] - 3-2 matrix element.
6113	 * @param {number} [n33] - 3-3 matrix element.
6114	 */
6115	constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
6116
6117		/**
6118		 * A column-major list of matrix values.
6119		 *
6120		 * @type {Array<number>}
6121		 */
6122		this.elements = [
6123
6124			1, 0, 0,
6125			0, 1, 0,
6126			0, 0, 1
6127
6128		];
6129
6130		if ( n11 !== undefined ) {
6131
6132			this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 );
6133
6134		}
6135
6136	}
6137
6138	/**
6139	 * Sets the elements of the matrix.The arguments are supposed to be
6140	 * in row-major order.
6141	 *
6142	 * @param {number} [n11] - 1-1 matrix element.
6143	 * @param {number} [n12] - 1-2 matrix element.
6144	 * @param {number} [n13] - 1-3 matrix element.
6145	 * @param {number} [n21] - 2-1 matrix element.
6146	 * @param {number} [n22] - 2-2 matrix element.
6147	 * @param {number} [n23] - 2-3 matrix element.
6148	 * @param {number} [n31] - 3-1 matrix element.
6149	 * @param {number} [n32] - 3-2 matrix element.
6150	 * @param {number} [n33] - 3-3 matrix element.
6151	 * @return {Matrix3} A reference to this matrix.
6152	 */
6153	set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
6154
6155		const te = this.elements;
6156
6157		te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
6158		te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
6159		te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
6160
6161		return this;
6162
6163	}
6164
6165	/**
6166	 * Sets this matrix to the 3x3 identity matrix.
6167	 *
6168	 * @return {Matrix3} A reference to this matrix.
6169	 */
6170	identity() {
6171
6172		this.set(
6173
6174			1, 0, 0,
6175			0, 1, 0,
6176			0, 0, 1
6177
6178		);
6179
6180		return this;
6181
6182	}
6183
6184	/**
6185	 * Copies the values of the given matrix to this instance.
6186	 *
6187	 * @param {Matrix3} m - The matrix to copy.
6188	 * @return {Matrix3} A reference to this matrix.
6189	 */
6190	copy( m ) {
6191
6192		const te = this.elements;
6193		const me = m.elements;
6194
6195		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
6196		te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
6197		te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
6198
6199		return this;
6200
6201	}
6202
6203	/**
6204	 * Extracts the basis of this matrix into the three axis vectors provided.
6205	 *
6206	 * @param {Vector3} xAxis - The basis's x axis.
6207	 * @param {Vector3} yAxis - The basis's y axis.
6208	 * @param {Vector3} zAxis - The basis's z axis.
6209	 * @return {Matrix3} A reference to this matrix.
6210	 */
6211	extractBasis( xAxis, yAxis, zAxis ) {
6212
6213		xAxis.setFromMatrix3Column( this, 0 );
6214		yAxis.setFromMatrix3Column( this, 1 );
6215		zAxis.setFromMatrix3Column( this, 2 );
6216
6217		return this;
6218
6219	}
6220
6221	/**
6222	 * Set this matrix to the upper 3x3 matrix of the given 4x4 matrix.
6223	 *
6224	 * @param {Matrix4} m - The 4x4 matrix.
6225	 * @return {Matrix3} A reference to this matrix.
6226	 */
6227	setFromMatrix4( m ) {
6228
6229		const me = m.elements;
6230
6231		this.set(
6232
6233			me[ 0 ], me[ 4 ], me[ 8 ],
6234			me[ 1 ], me[ 5 ], me[ 9 ],
6235			me[ 2 ], me[ 6 ], me[ 10 ]
6236
6237		);
6238
6239		return this;
6240
6241	}
6242
6243	/**
6244	 * Post-multiplies this matrix by the given 3x3 matrix.
6245	 *
6246	 * @param {Matrix3} m - The matrix to multiply with.
6247	 * @return {Matrix3} A reference to this matrix.
6248	 */
6249	multiply( m ) {
6250
6251		return this.multiplyMatrices( this, m );
6252
6253	}
6254
6255	/**
6256	 * Pre-multiplies this matrix by the given 3x3 matrix.
6257	 *
6258	 * @param {Matrix3} m - The matrix to multiply with.
6259	 * @return {Matrix3} A reference to this matrix.
6260	 */
6261	premultiply( m ) {
6262
6263		return this.multiplyMatrices( m, this );
6264
6265	}
6266
6267	/**
6268	 * Multiples the given 3x3 matrices and stores the result
6269	 * in this matrix.
6270	 *
6271	 * @param {Matrix3} a - The first matrix.
6272	 * @param {Matrix3} b - The second matrix.
6273	 * @return {Matrix3} A reference to this matrix.
6274	 */
6275	multiplyMatrices( a, b ) {
6276
6277		const ae = a.elements;
6278		const be = b.elements;
6279		const te = this.elements;
6280
6281		const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
6282		const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
6283		const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
6284
6285		const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
6286		const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
6287		const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
6288
6289		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
6290		te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
6291		te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
6292
6293		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
6294		te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
6295		te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
6296
6297		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
6298		te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
6299		te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
6300
6301		return this;
6302
6303	}
6304
6305	/**
6306	 * Multiplies every component of the matrix by the given scalar.
6307	 *
6308	 * @param {number} s - The scalar.
6309	 * @return {Matrix3} A reference to this matrix.
6310	 */
6311	multiplyScalar( s ) {
6312
6313		const te = this.elements;
6314
6315		te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
6316		te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
6317		te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
6318
6319		return this;
6320
6321	}
6322
6323	/**
6324	 * Computes and returns the determinant of this matrix.
6325	 *
6326	 * @return {number} The determinant.
6327	 */
6328	determinant() {
6329
6330		const te = this.elements;
6331
6332		const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
6333			d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
6334			g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
6335
6336		return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
6337
6338	}
6339
6340	/**
6341	 * Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution).
6342	 * You can not invert with a determinant of zero. If you attempt this, the method produces
6343	 * a zero matrix instead.
6344	 *
6345	 * @return {Matrix3} A reference to this matrix.
6346	 */
6347	invert() {
6348
6349		const te = this.elements,
6350
6351			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ],
6352			n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ],
6353			n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ],
6354
6355			t11 = n33 * n22 - n32 * n23,
6356			t12 = n32 * n13 - n33 * n12,
6357			t13 = n23 * n12 - n22 * n13,
6358
6359			det = n11 * t11 + n21 * t12 + n31 * t13;
6360
6361		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
6362
6363		const detInv = 1 / det;
6364
6365		te[ 0 ] = t11 * detInv;
6366		te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
6367		te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
6368
6369		te[ 3 ] = t12 * detInv;
6370		te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
6371		te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
6372
6373		te[ 6 ] = t13 * detInv;
6374		te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
6375		te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
6376
6377		return this;
6378
6379	}
6380
6381	/**
6382	 * Transposes this matrix in place.
6383	 *
6384	 * @return {Matrix3} A reference to this matrix.
6385	 */
6386	transpose() {
6387
6388		let tmp;
6389		const m = this.elements;
6390
6391		tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
6392		tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
6393		tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
6394
6395		return this;
6396
6397	}
6398
6399	/**
6400	 * Computes the normal matrix which is the inverse transpose of the upper
6401	 * left 3x3 portion of the given 4x4 matrix.
6402	 *
6403	 * @param {Matrix4} matrix4 - The 4x4 matrix.
6404	 * @return {Matrix3} A reference to this matrix.
6405	 */
6406	getNormalMatrix( matrix4 ) {
6407
6408		return this.setFromMatrix4( matrix4 ).invert().transpose();
6409
6410	}
6411
6412	/**
6413	 * Transposes this matrix into the supplied array, and returns itself unchanged.
6414	 *
6415	 * @param {Array<number>} r - An array to store the transposed matrix elements.
6416	 * @return {Matrix3} A reference to this matrix.
6417	 */
6418	transposeIntoArray( r ) {
6419
6420		const m = this.elements;
6421
6422		r[ 0 ] = m[ 0 ];
6423		r[ 1 ] = m[ 3 ];
6424		r[ 2 ] = m[ 6 ];
6425		r[ 3 ] = m[ 1 ];
6426		r[ 4 ] = m[ 4 ];
6427		r[ 5 ] = m[ 7 ];
6428		r[ 6 ] = m[ 2 ];
6429		r[ 7 ] = m[ 5 ];
6430		r[ 8 ] = m[ 8 ];
6431
6432		return this;
6433
6434	}
6435
6436	/**
6437	 * Sets the UV transform matrix from offset, repeat, rotation, and center.
6438	 *
6439	 * @param {number} tx - Offset x.
6440	 * @param {number} ty - Offset y.
6441	 * @param {number} sx - Repeat x.
6442	 * @param {number} sy - Repeat y.
6443	 * @param {number} rotation - Rotation, in radians. Positive values rotate counterclockwise.
6444	 * @param {number} cx - Center x of rotation.
6445	 * @param {number} cy - Center y of rotation
6446	 * @return {Matrix3} A reference to this matrix.
6447	 */
6448	setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
6449
6450		const c = Math.cos( rotation );
6451		const s = Math.sin( rotation );
6452
6453		this.set(
6454			sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,
6455			- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,
6456			0, 0, 1
6457		);
6458
6459		return this;
6460
6461	}
6462
6463	/**
6464	 * Scales this matrix with the given scalar values.
6465	 *
6466	 * @deprecated
6467	 * @param {number} sx - The amount to scale in the X axis.
6468	 * @param {number} sy - The amount to scale in the Y axis.
6469	 * @return {Matrix3} A reference to this matrix.
6470	 */
6471	scale( sx, sy ) {
6472
6473		warnOnce( 'Matrix3: .scale() is deprecated. Use .makeScale() instead.' ); // @deprecated r185
6474
6475		this.premultiply( _m3.makeScale( sx, sy ) );
6476
6477		return this;
6478
6479	}
6480
6481	/**
6482	 * Rotates this matrix by the given angle.
6483	 *
6484	 * @deprecated
6485	 * @param {number} theta - The rotation in radians.
6486	 * @return {Matrix3} A reference to this matrix.
6487	 */
6488	rotate( theta ) {
6489
6490		warnOnce( 'Matrix3: .rotate() is deprecated. Use .makeRotation() instead.' ); // @deprecated r185
6491
6492		this.premultiply( _m3.makeRotation( - theta ) );
6493
6494		return this;
6495
6496	}
6497
6498	/**
6499	 * Translates this matrix by the given scalar values.
6500	 *
6501	 * @deprecated
6502	 * @param {number} tx - The amount to translate in the X axis.
6503	 * @param {number} ty - The amount to translate in the Y axis.
6504	 * @return {Matrix3} A reference to this matrix.
6505	 */
6506	translate( tx, ty ) {
6507
6508		warnOnce( 'Matrix3: .translate() is deprecated. Use .makeTranslation() instead.' ); // @deprecated r185
6509
6510		this.premultiply( _m3.makeTranslation( tx, ty ) );
6511
6512		return this;
6513
6514	}
6515
6516	// for 2D Transforms
6517
6518	/**
6519	 * Sets this matrix as a 2D translation transform.
6520	 *
6521	 * @param {number|Vector2} x - The amount to translate in the X axis or alternatively a translation vector.
6522	 * @param {number} y - The amount to translate in the Y axis.
6523	 * @return {Matrix3} A reference to this matrix.
6524	 */
6525	makeTranslation( x, y ) {
6526
6527		if ( x.isVector2 ) {
6528
6529			this.set(
6530
6531				1, 0, x.x,
6532				0, 1, x.y,
6533				0, 0, 1
6534
6535			);
6536
6537		} else {
6538
6539			this.set(
6540
6541				1, 0, x,
6542				0, 1, y,
6543				0, 0, 1
6544
6545			);
6546
6547		}
6548
6549		return this;
6550
6551	}
6552
6553	/**
6554	 * Sets this matrix as a 2D rotational transformation.
6555	 *
6556	 * @param {number} theta - The rotation in radians.
6557	 * @return {Matrix3} A reference to this matrix.
6558	 */
6559	makeRotation( theta ) {
6560
6561		// counterclockwise
6562
6563		const c = Math.cos( theta );
6564		const s = Math.sin( theta );
6565
6566		this.set(
6567
6568			c, - s, 0,
6569			s, c, 0,
6570			0, 0, 1
6571
6572		);
6573
6574		return this;
6575
6576	}
6577
6578	/**
6579	 * Sets this matrix as a 2D scale transform.
6580	 *
6581	 * @param {number} x - The amount to scale in the X axis.
6582	 * @param {number} y - The amount to scale in the Y axis.
6583	 * @return {Matrix3} A reference to this matrix.
6584	 */
6585	makeScale( x, y ) {
6586
6587		this.set(
6588
6589			x, 0, 0,
6590			0, y, 0,
6591			0, 0, 1
6592
6593		);
6594
6595		return this;
6596
6597	}
6598
6599	/**
6600	 * Returns `true` if this matrix is equal with the given one.
6601	 *
6602	 * @param {Matrix3} matrix - The matrix to test for equality.
6603	 * @return {boolean} Whether this matrix is equal with the given one.
6604	 */
6605	equals( matrix ) {
6606
6607		const te = this.elements;
6608		const me = matrix.elements;
6609
6610		for ( let i = 0; i < 9; i ++ ) {
6611
6612			if ( te[ i ] !== me[ i ] ) return false;
6613
6614		}
6615
6616		return true;
6617
6618	}
6619
6620	/**
6621	 * Sets the elements of the matrix from the given array.
6622	 *
6623	 * @param {Array<number>} array - The matrix elements in column-major order.
6624	 * @param {number} [offset=0] - Index of the first element in the array.
6625	 * @return {Matrix3} A reference to this matrix.
6626	 */
6627	fromArray( array, offset = 0 ) {
6628
6629		for ( let i = 0; i < 9; i ++ ) {
6630
6631			this.elements[ i ] = array[ i + offset ];
6632
6633		}
6634
6635		return this;
6636
6637	}
6638
6639	/**
6640	 * Writes the elements of this matrix to the given array. If no array is provided,
6641	 * the method returns a new instance.
6642	 *
6643	 * @param {Array<number>} [array=[]] - The target array holding the matrix elements in column-major order.
6644	 * @param {number} [offset=0] - Index of the first element in the array.
6645	 * @return {Array<number>} The matrix elements in column-major order.
6646	 */
6647	toArray( array = [], offset = 0 ) {
6648
6649		const te = this.elements;
6650
6651		array[ offset ] = te[ 0 ];
6652		array[ offset + 1 ] = te[ 1 ];
6653		array[ offset + 2 ] = te[ 2 ];
6654
6655		array[ offset + 3 ] = te[ 3 ];
6656		array[ offset + 4 ] = te[ 4 ];
6657		array[ offset + 5 ] = te[ 5 ];
6658
6659		array[ offset + 6 ] = te[ 6 ];
6660		array[ offset + 7 ] = te[ 7 ];
6661		array[ offset + 8 ] = te[ 8 ];
6662
6663		return array;
6664
6665	}
6666
6667	/**
6668	 * Returns a matrix with copied values from this instance.
6669	 *
6670	 * @return {Matrix3} A clone of this instance.
6671	 */
6672	clone() {
6673
6674		return new this.constructor().fromArray( this.elements );
6675
6676	}
6677
6678}
6679
6680const _m3 = /*@__PURE__*/ new Matrix3();
6681
6682const LINEAR_REC709_TO_XYZ = /*@__PURE__*/ new Matrix3().set(
6683	0.4123908, 0.3575843, 0.1804808,
6684	0.2126390, 0.7151687, 0.0721923,
6685	0.0193308, 0.1191948, 0.9505322
6686);
6687
6688const XYZ_TO_LINEAR_REC709 = /*@__PURE__*/ new Matrix3().set(
6689	3.2409699, -1.5373832, -0.4986108,
6690	-0.9692436, 1.8759675, 0.0415551,
6691	0.0556301, -0.203977, 1.0569715
6692);
6693
6694function createColorManagement() {
6695
6696	const ColorManagement = {
6697
6698		enabled: true,
6699
6700		workingColorSpace: LinearSRGBColorSpace,
6701
6702		/**
6703		 * Implementations of supported color spaces.
6704		 *
6705		 * Required:
6706		 *	- primaries: chromaticity coordinates [ rx ry gx gy bx by ]
6707		 *	- whitePoint: reference white [ x y ]
6708		 *	- transfer: transfer function (pre-defined)
6709		 *	- toXYZ: Matrix3 RGB to XYZ transform
6710		 *	- fromXYZ: Matrix3 XYZ to RGB transform
6711		 *	- luminanceCoefficients: RGB luminance coefficients
6712		 *
6713		 * Optional:
6714		 *  - outputColorSpaceConfig: { drawingBufferColorSpace: ColorSpace, toneMappingMode: 'extended' | 'standard' }
6715		 *  - workingColorSpaceConfig: { unpackColorSpace: ColorSpace }
6716		 *
6717		 * Reference:
6718		 * - https://www.russellcottrell.com/photo/matrixCalculator.htm
6719		 */
6720		spaces: {},
6721
6722		convert: function ( color, sourceColorSpace, targetColorSpace ) {
6723
6724			if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) {
6725
6726				return color;
6727
6728			}
6729
6730			if ( this.spaces[ sourceColorSpace ].transfer === SRGBTransfer ) {
6731
6732				color.r = SRGBToLinear( color.r );
6733				color.g = SRGBToLinear( color.g );
6734				color.b = SRGBToLinear( color.b );
6735
6736			}
6737
6738			if ( this.spaces[ sourceColorSpace ].primaries !== this.spaces[ targetColorSpace ].primaries ) {
6739
6740				color.applyMatrix3( this.spaces[ sourceColorSpace ].toXYZ );
6741				color.applyMatrix3( this.spaces[ targetColorSpace ].fromXYZ );
6742
6743			}
6744
6745			if ( this.spaces[ targetColorSpace ].transfer === SRGBTransfer ) {
6746
6747				color.r = LinearToSRGB( color.r );
6748				color.g = LinearToSRGB( color.g );
6749				color.b = LinearToSRGB( color.b );
6750
6751			}
6752
6753			return color;
6754
6755		},
6756
6757		workingToColorSpace: function ( color, targetColorSpace ) {
6758
6759			return this.convert( color, this.workingColorSpace, targetColorSpace );
6760
6761		},
6762
6763		colorSpaceToWorking: function ( color, sourceColorSpace ) {
6764
6765			return this.convert( color, sourceColorSpace, this.workingColorSpace );
6766
6767		},
6768
6769		getPrimaries: function ( colorSpace ) {
6770
6771			return this.spaces[ colorSpace ].primaries;
6772
6773		},
6774
6775		getTransfer: function ( colorSpace ) {
6776
6777			if ( colorSpace === NoColorSpace ) return LinearTransfer;
6778
6779			return this.spaces[ colorSpace ].transfer;
6780
6781		},
6782
6783		getToneMappingMode: function ( colorSpace ) {
6784
6785			return this.spaces[ colorSpace ].outputColorSpaceConfig.toneMappingMode || 'standard';
6786
6787		},
6788
6789		getLuminanceCoefficients: function ( target, colorSpace = this.workingColorSpace ) {
6790
6791			return target.fromArray( this.spaces[ colorSpace ].luminanceCoefficients );
6792
6793		},
6794
6795		define: function ( colorSpaces ) {
6796
6797			Object.assign( this.spaces, colorSpaces );
6798
6799		},
6800
6801		// Internal APIs
6802
6803		_getMatrix: function ( targetMatrix, sourceColorSpace, targetColorSpace ) {
6804
6805			return targetMatrix
6806				.copy( this.spaces[ sourceColorSpace ].toXYZ )
6807				.multiply( this.spaces[ targetColorSpace ].fromXYZ );
6808
6809		},
6810
6811		_getDrawingBufferColorSpace: function ( colorSpace ) {
6812
6813			return this.spaces[ colorSpace ].outputColorSpaceConfig.drawingBufferColorSpace;
6814
6815		},
6816
6817		_getUnpackColorSpace: function ( colorSpace = this.workingColorSpace ) {
6818
6819			return this.spaces[ colorSpace ].workingColorSpaceConfig.unpackColorSpace;
6820
6821		},
6822
6823		// Deprecated
6824
6825		fromWorkingColorSpace: function ( color, targetColorSpace ) {
6826
6827			warnOnce( 'ColorManagement: .fromWorkingColorSpace() has been renamed to .workingToColorSpace().' ); // @deprecated, r177
6828
6829			return ColorManagement.workingToColorSpace( color, targetColorSpace );
6830
6831		},
6832
6833		toWorkingColorSpace: function ( color, sourceColorSpace ) {
6834
6835			warnOnce( 'ColorManagement: .toWorkingColorSpace() has been renamed to .colorSpaceToWorking().' ); // @deprecated, r177
6836
6837			return ColorManagement.colorSpaceToWorking( color, sourceColorSpace );
6838
6839		},
6840
6841	};
6842
6843	/******************************************************************************
6844	 * sRGB definitions
6845	 */
6846
6847	const REC709_PRIMARIES = [ 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 ];
6848	const REC709_LUMINANCE_COEFFICIENTS = [ 0.2126, 0.7152, 0.0722 ];
6849	const D65 = [ 0.3127, 0.3290 ];
6850
6851	ColorManagement.define( {
6852
6853		[ LinearSRGBColorSpace ]: {
6854			primaries: REC709_PRIMARIES,
6855			whitePoint: D65,
6856			transfer: LinearTransfer,
6857			toXYZ: LINEAR_REC709_TO_XYZ,
6858			fromXYZ: XYZ_TO_LINEAR_REC709,
6859			luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,
6860			workingColorSpaceConfig: { unpackColorSpace: SRGBColorSpace },
6861			outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }
6862		},
6863
6864		[ SRGBColorSpace ]: {
6865			primaries: REC709_PRIMARIES,
6866			whitePoint: D65,
6867			transfer: SRGBTransfer,
6868			toXYZ: LINEAR_REC709_TO_XYZ,
6869			fromXYZ: XYZ_TO_LINEAR_REC709,
6870			luminanceCoefficients: REC709_LUMINANCE_COEFFICIENTS,
6871			outputColorSpaceConfig: { drawingBufferColorSpace: SRGBColorSpace }
6872		},
6873
6874	} );
6875
6876	return ColorManagement;
6877
6878}
6879
6880const ColorManagement = /*@__PURE__*/ createColorManagement();
6881
6882function SRGBToLinear( c ) {
6883
6884	return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );
6885
6886}
6887
6888function LinearToSRGB( c ) {
6889
6890	return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;
6891
6892}
6893
6894let _canvas;
6895
6896/**
6897 * A class containing utility functions for images.
6898 *
6899 * @hideconstructor
6900 */
6901class ImageUtils {
6902
6903	/**
6904	 * Returns a data URI containing a representation of the given image.
6905	 *
6906	 * @param {(HTMLImageElement|HTMLCanvasElement)} image - The image object.
6907	 * @param {string} [type='image/png'] - Indicates the image format.
6908	 * @return {string} The data URI.
6909	 */
6910	static getDataURL( image, type = 'image/png' ) {
6911
6912		if ( /^data:/i.test( image.src ) ) {
6913
6914			return image.src;
6915
6916		}
6917
6918		if ( typeof HTMLCanvasElement === 'undefined' ) {
6919
6920			return image.src;
6921
6922		}
6923
6924		let canvas;
6925
6926		if ( image instanceof HTMLCanvasElement ) {
6927
6928			canvas = image;
6929
6930		} else {
6931
6932			if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' );
6933
6934			_canvas.width = image.width;
6935			_canvas.height = image.height;
6936
6937			const context = _canvas.getContext( '2d' );
6938
6939			if ( image instanceof ImageData ) {
6940
6941				context.putImageData( image, 0, 0 );
6942
6943			} else {
6944
6945				context.drawImage( image, 0, 0, image.width, image.height );
6946
6947			}
6948
6949			canvas = _canvas;
6950
6951		}
6952
6953		return canvas.toDataURL( type );
6954
6955	}
6956
6957	/**
6958	 * Converts the given sRGB image data to linear color space.
6959	 *
6960	 * @param {(HTMLImageElement|HTMLCanvasElement|ImageBitmap|Object)} image - The image object.
6961	 * @return {HTMLCanvasElement|Object} The converted image.
6962	 */
6963	static sRGBToLinear( image ) {
6964
6965		if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
6966			( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
6967			( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
6968
6969			const canvas = createElementNS( 'canvas' );
6970
6971			canvas.width = image.width;
6972			canvas.height = image.height;
6973
6974			const context = canvas.getContext( '2d' );
6975			context.drawImage( image, 0, 0, image.width, image.height );
6976
6977			const imageData = context.getImageData( 0, 0, image.width, image.height );
6978			const data = imageData.data;
6979
6980			for ( let i = 0; i < data.length; i ++ ) {
6981
6982				data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;
6983
6984			}
6985
6986			context.putImageData( imageData, 0, 0 );
6987
6988			return canvas;
6989
6990		} else if ( image.data ) {
6991
6992			const data = image.data.slice( 0 );
6993
6994			for ( let i = 0; i < data.length; i ++ ) {
6995
6996				if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {
6997
6998					data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );
6999
7000				} else {
7001
7002					// assuming float
7003
7004					data[ i ] = SRGBToLinear( data[ i ] );
7005
7006				}
7007
7008			}
7009
7010			return {
7011				data: data,
7012				width: image.width,
7013				height: image.height
7014			};
7015
7016		} else {
7017
7018			warn( 'ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
7019			return image;
7020
7021		}
7022
7023	}
7024
7025}
7026
7027let _sourceId = 0;
7028
7029/**
7030 * Represents the data source of a texture.
7031 *
7032 * The main purpose of this class is to decouple the data definition from the texture
7033 * definition so the same data can be used with multiple texture instances.
7034 */
7035class TextureSource {
7036
7037	/**
7038	 * Constructs a new texture source.
7039	 *
7040	 * @param {any} [data=null] - The data definition of a texture.
7041	 */
7042	constructor( data = null ) {
7043
7044		/**
7045		 * This flag can be used for type testing.
7046		 *
7047		 * @type {boolean}
7048		 * @readonly
7049		 * @default true
7050		 */
7051		this.isTextureSource = true;
7052
7053		/**
7054		 * The ID of the source.
7055		 *
7056		 * @name TextureSource#id
7057		 * @type {number}
7058		 * @readonly
7059		 */
7060		Object.defineProperty( this, 'id', { value: _sourceId ++ } );
7061
7062		/**
7063		 * The UUID of the source.
7064		 *
7065		 * @type {string}
7066		 * @readonly
7067		 */
7068		this.uuid = generateUUID();
7069
7070		/**
7071		 * The data definition of a texture.
7072		 *
7073		 * @type {any}
7074		 */
7075		this.data = data;
7076
7077		/**
7078		 * This property is only relevant when {@link TextureSource#needsUpdate} is set to `true` and
7079		 * provides more control on how texture data should be processed. When `dataReady` is set
7080		 * to `false`, the engine performs the memory allocation (if necessary) but does not transfer
7081		 * the data into the GPU memory.
7082		 *
7083		 * @type {boolean}
7084		 * @default true
7085		 */
7086		this.dataReady = true;
7087
7088		/**
7089		 * This starts at `0` and counts how many times {@link TextureSource#needsUpdate} is set to `true`.
7090		 *
7091		 * @type {number}
7092		 * @readonly
7093		 * @default 0
7094		 */
7095		this.version = 0;
7096
7097	}
7098
7099	/**
7100	 * Returns the dimensions of the source into the given target vector.
7101	 *
7102	 * @param {(Vector2|Vector3)} target - The target object the result is written into.
7103	 * @return {(Vector2|Vector3)} The dimensions of the source.
7104	 */
7105	getSize( target ) {
7106
7107		const data = this.data;
7108
7109		if ( ( typeof HTMLVideoElement !== 'undefined' ) && ( data instanceof HTMLVideoElement ) ) {
7110
7111			target.set( data.videoWidth, data.videoHeight, 0 );
7112
7113		} else if ( ( typeof VideoFrame !== 'undefined' ) && ( data instanceof VideoFrame ) ) {
7114
7115			target.set( data.displayWidth, data.displayHeight, 0 );
7116
7117		} else if ( data !== null ) {
7118
7119			target.set( data.width, data.height, data.depth || 0 );
7120
7121		} else {
7122
7123			target.set( 0, 0, 0 );
7124
7125		}
7126
7127		return target;
7128
7129	}
7130
7131	/**
7132	 * When the property is set to `true`, the engine allocates the memory
7133	 * for the texture (if necessary) and triggers the actual texture upload
7134	 * to the GPU next time the source is used.
7135	 *
7136	 * @type {boolean}
7137	 * @default false
7138	 * @param {boolean} value
7139	 */
7140	set needsUpdate( value ) {
7141
7142		if ( value === true ) this.version ++;
7143
7144	}
7145
7146	/**
7147	 * Serializes the source into JSON.
7148	 *
7149	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
7150	 * @return {Object} A JSON object representing the serialized source.
7151	 * @see {@link ObjectLoader#parse}
7152	 */
7153	toJSON( meta ) {
7154
7155		const isRootObject = ( meta === undefined || typeof meta === 'string' );
7156
7157		if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) {
7158
7159			return meta.images[ this.uuid ];
7160
7161		}
7162
7163		const output = {
7164			uuid: this.uuid,
7165			url: ''
7166		};
7167
7168		const data = this.data;
7169
7170		if ( data !== null ) {
7171
7172			let url;
7173
7174			if ( Array.isArray( data ) ) {
7175
7176				// cube texture
7177
7178				url = [];
7179
7180				for ( let i = 0, l = data.length; i < l; i ++ ) {
7181
7182					if ( data[ i ].isDataTexture ) {
7183
7184						url.push( serializeImage( data[ i ].image ) );
7185
7186					} else {
7187
7188						url.push( serializeImage( data[ i ] ) );
7189
7190					}
7191
7192				}
7193
7194			} else {
7195
7196				// texture
7197
7198				url = serializeImage( data );
7199
7200			}
7201
7202			output.url = url;
7203
7204		}
7205
7206		if ( ! isRootObject ) {
7207
7208			meta.images[ this.uuid ] = output;
7209
7210		}
7211
7212		return output;
7213
7214	}
7215
7216}
7217
7218function serializeImage( image ) {
7219
7220	if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
7221		( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
7222		( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
7223
7224		// default images
7225
7226		return ImageUtils.getDataURL( image );
7227
7228	} else {
7229
7230		if ( image.data ) {
7231
7232			// images of DataTexture
7233
7234			return {
7235				data: Array.from( image.data ),
7236				width: image.width,
7237				height: image.height,
7238				type: image.data.constructor.name
7239			};
7240
7241		} else {
7242
7243			warn( 'Texture: Unable to serialize Texture.' );
7244			return {};
7245
7246		}
7247
7248	}
7249
7250}
7251
7252/**
7253 * @deprecated since r186. Use {@link TextureSource} instead. `Source` has been renamed to `TextureSource`.
7254 */
7255class Source extends TextureSource {
7256
7257	/**
7258	 * Constructs a new texture source.
7259	 *
7260	 * @param {any} [data=null] - The data definition of a texture.
7261	 * @deprecated since r186. Use {@link TextureSource} instead.
7262	 */
7263	constructor( data = null ) {
7264
7265		warnOnce( 'Source: "Source" has been renamed to "TextureSource". Please update your code to use "THREE.TextureSource" instead.' ); // @deprecated, r186
7266
7267		super( data );
7268
7269		/**
7270		 * This flag can be used for type testing.
7271		 *
7272		 * @deprecated since r186. Use {@link TextureSource#isTextureSource} instead.
7273		 * @type {boolean}
7274		 * @readonly
7275		 * @default true
7276		 */
7277		this.isSource = true;
7278
7279	}
7280
7281}
7282
7283let _textureId = 0;
7284
7285const _tempVec3 = /*@__PURE__*/ new Vector3();
7286
7287/**
7288 * Base class for all textures.
7289 *
7290 * Note: After the initial use of a texture, its dimensions, format, and type
7291 * cannot be changed. Instead, call {@link Texture#dispose} on the texture and instantiate a new one.
7292 *
7293 * @augments EventDispatcher
7294 */
7295class Texture extends EventDispatcher {
7296
7297	/**
7298	 * Constructs a new texture.
7299	 *
7300	 * @param {?Object} [image=Texture.DEFAULT_IMAGE] - The image holding the texture data.
7301	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
7302	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
7303	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
7304	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
7305	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
7306	 * @param {number} [format=RGBAFormat] - The texture format.
7307	 * @param {number} [type=UnsignedByteType] - The texture type.
7308	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
7309	 * @param {string} [colorSpace=NoColorSpace] - The color space.
7310	 */
7311	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 ) {
7312
7313		super();
7314
7315		/**
7316		 * This flag can be used for type testing.
7317		 *
7318		 * @type {boolean}
7319		 * @readonly
7320		 * @default true
7321		 */
7322		this.isTexture = true;
7323
7324		/**
7325		 * The ID of the texture.
7326		 *
7327		 * @name Texture#id
7328		 * @type {number}
7329		 * @readonly
7330		 */
7331		Object.defineProperty( this, 'id', { value: _textureId ++ } );
7332
7333		/**
7334		 * The UUID of the texture.
7335		 *
7336		 * @type {string}
7337		 * @readonly
7338		 */
7339		this.uuid = generateUUID();
7340
7341		/**
7342		 * The name of the texture.
7343		 *
7344		 * @type {string}
7345		 */
7346		this.name = '';
7347
7348		/**
7349		 * The data definition of a texture. A reference to the data source can be
7350		 * shared across textures. This is often useful in context of spritesheets
7351		 * where multiple textures render the same data but with different texture
7352		 * transformations.
7353		 *
7354		 * @type {TextureSource}
7355		 */
7356		this.source = new TextureSource( image );
7357
7358		/**
7359		 * An array holding user-defined mipmaps.
7360		 *
7361		 * @type {Array<Object>}
7362		 */
7363		this.mipmaps = [];
7364
7365		/**
7366		 * How the texture is applied to the object. The value `UVMapping`
7367		 * is the default, where texture or uv coordinates are used to apply the map.
7368		 *
7369		 * @type {(UVMapping|CubeReflectionMapping|CubeRefractionMapping|EquirectangularReflectionMapping|EquirectangularRefractionMapping|CubeUVReflectionMapping)}
7370		 * @default UVMapping
7371		*/
7372		this.mapping = mapping;
7373
7374		/**
7375		 * Lets you select the uv attribute to map the texture to. `0` for `uv`,
7376		 * `1` for `uv1`, `2` for `uv2` and `3` for `uv3`.
7377		 *
7378		 * @type {number}
7379		 * @default 0
7380		 */
7381		this.channel = 0;
7382
7383		/**
7384		 * This defines how the texture is wrapped horizontally and corresponds to
7385		 * *U* in UV mapping.
7386		 *
7387		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
7388		 * @default ClampToEdgeWrapping
7389		 */
7390		this.wrapS = wrapS;
7391
7392		/**
7393		 * This defines how the texture is wrapped horizontally and corresponds to
7394		 * *V* in UV mapping.
7395		 *
7396		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
7397		 * @default ClampToEdgeWrapping
7398		 */
7399		this.wrapT = wrapT;
7400
7401		/**
7402		 * How the texture is sampled when a texel covers more than one pixel.
7403		 *
7404		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
7405		 * @default LinearFilter
7406		 */
7407		this.magFilter = magFilter;
7408
7409		/**
7410		 * How the texture is sampled when a texel covers less than one pixel.
7411		 *
7412		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
7413		 * @default LinearMipmapLinearFilter
7414		 */
7415		this.minFilter = minFilter;
7416
7417		/**
7418		 * The number of samples taken along the axis through the pixel that has the
7419		 * highest density of texels. By default, this value is `1`. A higher value
7420		 * gives a less blurry result than a basic mipmap, at the cost of more
7421		 * texture samples being used.
7422		 *
7423		 * @type {number}
7424		 * @default Texture.DEFAULT_ANISOTROPY
7425		 */
7426		this.anisotropy = anisotropy;
7427
7428		/**
7429		 * The format of the texture.
7430		 *
7431		 * @type {number}
7432		 * @default RGBAFormat
7433		 */
7434		this.format = format;
7435
7436		/**
7437		 * The default internal format is derived from {@link Texture#format} and {@link Texture#type} and
7438		 * defines how the texture data is going to be stored on the GPU.
7439		 *
7440		 * This property allows to overwrite the default format.
7441		 *
7442		 * @type {?string}
7443		 * @default null
7444		 */
7445		this.internalFormat = null;
7446
7447		/**
7448		 * The data type of the texture.
7449		 *
7450		 * @type {number}
7451		 * @default UnsignedByteType
7452		 */
7453		this.type = type;
7454
7455		/**
7456		 * How much a single repetition of the texture is offset from the beginning,
7457		 * in each direction U and V. Typical range is `0.0` to `1.0`.
7458		 *
7459		 * @type {Vector2}
7460		 * @default (0,0)
7461		 */
7462		this.offset = new Vector2( 0, 0 );
7463
7464		/**
7465		 * How many times the texture is repeated across the surface, in each
7466		 * direction U and V. If repeat is set greater than `1` in either direction,
7467		 * the corresponding wrap parameter should also be set to `RepeatWrapping`
7468		 * or `MirroredRepeatWrapping` to achieve the desired tiling effect.
7469		 *
7470		 * @type {Vector2}
7471		 * @default (1,1)
7472		 */
7473		this.repeat = new Vector2( 1, 1 );
7474
7475		/**
7476		 * The point around which rotation occurs. A value of `(0.5, 0.5)` corresponds
7477		 * to the center of the texture. Default is `(0, 0)`, the lower left.
7478		 *
7479		 * @type {Vector2}
7480		 * @default (0,0)
7481		 */
7482		this.center = new Vector2( 0, 0 );
7483
7484		/**
7485		 * How much the texture is rotated around the center point, in radians.
7486		 * Positive values are counter-clockwise.
7487		 *
7488		 * @type {number}
7489		 * @default 0
7490		 */
7491		this.rotation = 0;
7492
7493		/**
7494		 * Whether to update the texture's uv-transformation {@link Texture#matrix}
7495		 * from the properties {@link Texture#offset}, {@link Texture#repeat},
7496		 * {@link Texture#rotation}, and {@link Texture#center}.
7497		 *
7498		 * Set this to `false` if you are specifying the uv-transform matrix directly.
7499		 *
7500		 * @type {boolean}
7501		 * @default true
7502		 */
7503		this.matrixAutoUpdate = true;
7504
7505		/**
7506		 * The uv-transformation matrix of the texture.
7507		 *
7508		 * @type {Matrix3}
7509		 */
7510		this.matrix = new Matrix3();
7511
7512		/**
7513		 * Whether to generate mipmaps (if possible) for a texture.
7514		 *
7515		 * Set this to `false` if you are creating mipmaps manually.
7516		 *
7517		 * @type {boolean}
7518		 * @default true
7519		 */
7520		this.generateMipmaps = true;
7521
7522		/**
7523		 * If set to `true`, the alpha channel, if present, is multiplied into the
7524		 * color channels when the texture is uploaded to the GPU.
7525		 *
7526		 * Note that this property has no effect when using `ImageBitmap`. You need to
7527		 * configure premultiply alpha on bitmap creation instead.
7528		 *
7529		 * @type {boolean}
7530		 * @default false
7531		 */
7532		this.premultiplyAlpha = false;
7533
7534		/**
7535		 * If set to `true`, the texture is flipped along the vertical axis when
7536		 * uploaded to the GPU.
7537		 *
7538		 * Note that this property has no effect when using `ImageBitmap`. You need to
7539		 * configure the flip on bitmap creation instead.
7540		 *
7541		 * @type {boolean}
7542		 * @default true
7543		 */
7544		this.flipY = true;
7545
7546		/**
7547		 * Specifies the alignment requirements for the start of each pixel row in memory.
7548		 * The allowable values are `1` (byte-alignment), `2` (rows aligned to even-numbered bytes),
7549		 * `4` (word-alignment), and `8` (rows start on double-word boundaries).
7550		 *
7551		 * @type {number}
7552		 * @default 4
7553		 */
7554		this.unpackAlignment = 4;	// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)
7555
7556		/**
7557		 * Textures containing color data should be annotated with `SRGBColorSpace` or `LinearSRGBColorSpace`.
7558		 *
7559		 * @type {string}
7560		 * @default NoColorSpace
7561		 */
7562		this.colorSpace = colorSpace;
7563
7564		/**
7565		 * An object that can be used to store custom data about the texture. It
7566		 * should not hold references to functions as these will not be cloned.
7567		 *
7568		 * @type {Object}
7569		 */
7570		this.userData = {};
7571
7572		/**
7573		 * This can be used to only update a subregion or specific rows of the texture (for example, just the
7574		 * first 3 rows). Use the `addUpdateRange()` function to add ranges to this array.
7575		 *
7576		 * @type {Array<Object>}
7577		 */
7578		this.updateRanges = [];
7579
7580		/**
7581		 * This starts at `0` and counts how many times {@link Texture#needsUpdate} is set to `true`.
7582		 *
7583		 * @type {number}
7584		 * @readonly
7585		 * @default 0
7586		 */
7587		this.version = 0;
7588
7589		/**
7590		 * A callback function, called when the texture is updated (e.g., when
7591		 * {@link Texture#needsUpdate} has been set to true and then the texture is used).
7592		 *
7593		 * @type {?Function}
7594		 * @default null
7595		 */
7596		this.onUpdate = null;
7597
7598		/**
7599		 * An optional back reference to the textures render target.
7600		 *
7601		 * @type {?(RenderTarget|WebGLRenderTarget)}
7602		 * @default null
7603		 */
7604		this.renderTarget = null;
7605
7606		/**
7607		 * Indicates whether a texture belongs to a render target or not.
7608		 *
7609		 * @type {boolean}
7610		 * @readonly
7611		 * @default false
7612		 */
7613		this.isRenderTargetTexture = false;
7614
7615		/**
7616		 * Indicates if a texture should be handled like a texture array.
7617		 *
7618		 * @type {boolean}
7619		 * @readonly
7620		 * @default false
7621		 */
7622		this.isArrayTexture = image && image.depth && image.depth > 1 ? true : false;
7623
7624		/**
7625		 * Indicates whether this texture should be processed by `PMREMGenerator` or not
7626		 * (only relevant for render target textures).
7627		 *
7628		 * @type {number}
7629		 * @readonly
7630		 * @default 0
7631		 */
7632		this.pmremVersion = 0;
7633
7634		/**
7635		 * Whether the texture should use one of the 16 bit integer formats which are normalized
7636		 * to [0, 1] or [-1, 1] (depending on signed/unsigned) when sampled.
7637		 *
7638		 * @type {boolean}
7639		 * @default false
7640		 */
7641		this.normalized = false;
7642
7643	}
7644
7645	/**
7646	 * The width of the texture in pixels.
7647	 */
7648	get width() {
7649
7650		return this.source.getSize( _tempVec3 ).x;
7651
7652	}
7653
7654	/**
7655	 * The height of the texture in pixels.
7656	 */
7657	get height() {
7658
7659		return this.source.getSize( _tempVec3 ).y;
7660
7661	}
7662
7663	/**
7664	 * The depth of the texture in pixels.
7665	 */
7666	get depth() {
7667
7668		return this.source.getSize( _tempVec3 ).z;
7669
7670	}
7671
7672	/**
7673	 * The image object holding the texture data.
7674	 *
7675	 * @type {?Object}
7676	 */
7677	get image() {
7678
7679		return this.source.data;
7680
7681	}
7682
7683	set image( value ) {
7684
7685		this.source.data = value;
7686
7687	}
7688
7689	/**
7690	 * Updates the texture transformation matrix from the properties {@link Texture#offset},
7691	 * {@link Texture#repeat}, {@link Texture#rotation}, and {@link Texture#center}.
7692	 */
7693	updateMatrix() {
7694
7695		this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );
7696
7697	}
7698
7699	/**
7700	 * Adds a range of data in the data texture to be updated on the GPU.
7701	 *
7702	 * @param {number} start - Position at which to start update.
7703	 * @param {number} count - The number of components to update.
7704	 */
7705	addUpdateRange( start, count ) {
7706
7707		this.updateRanges.push( { start, count } );
7708
7709	}
7710
7711	/**
7712	 * Clears the update ranges.
7713	 */
7714	clearUpdateRanges() {
7715
7716		this.updateRanges.length = 0;
7717
7718	}
7719
7720	/**
7721	 * Returns a new texture with copied values from this instance.
7722	 *
7723	 * @return {Texture} A clone of this instance.
7724	 */
7725	clone() {
7726
7727		return new this.constructor().copy( this );
7728
7729	}
7730
7731	/**
7732	 * Copies the values of the given texture to this instance.
7733	 *
7734	 * @param {Texture} source - The texture to copy.
7735	 * @return {Texture} A reference to this instance.
7736	 */
7737	copy( source ) {
7738
7739		this.name = source.name;
7740
7741		this.source = source.source;
7742		this.mipmaps = source.mipmaps.slice( 0 );
7743
7744		this.mapping = source.mapping;
7745		this.channel = source.channel;
7746
7747		this.wrapS = source.wrapS;
7748		this.wrapT = source.wrapT;
7749
7750		this.magFilter = source.magFilter;
7751		this.minFilter = source.minFilter;
7752
7753		this.anisotropy = source.anisotropy;
7754
7755		this.format = source.format;
7756		this.internalFormat = source.internalFormat;
7757		this.type = source.type;
7758		this.normalized = source.normalized;
7759
7760		this.offset.copy( source.offset );
7761		this.repeat.copy( source.repeat );
7762		this.center.copy( source.center );
7763		this.rotation = source.rotation;
7764
7765		this.matrixAutoUpdate = source.matrixAutoUpdate;
7766		this.matrix.copy( source.matrix );
7767
7768		this.generateMipmaps = source.generateMipmaps;
7769		this.premultiplyAlpha = source.premultiplyAlpha;
7770		this.flipY = source.flipY;
7771		this.unpackAlignment = source.unpackAlignment;
7772		this.colorSpace = source.colorSpace;
7773
7774		this.renderTarget = source.renderTarget;
7775		this.isRenderTargetTexture = source.isRenderTargetTexture;
7776		this.isArrayTexture = source.isArrayTexture;
7777
7778		this.userData = JSON.parse( JSON.stringify( source.userData ) );
7779
7780		this.needsUpdate = true;
7781
7782		return this;
7783
7784	}
7785
7786	/**
7787	 * Sets this texture's properties based on `values`.
7788	 * @param {Object} values - A container with texture parameters.
7789	 */
7790	setValues( values ) {
7791
7792		for ( const key in values ) {
7793
7794			const newValue = values[ key ];
7795
7796			if ( newValue === undefined ) {
7797
7798				warn( `Texture.setValues(): parameter '${ key }' has value of undefined.` );
7799				continue;
7800
7801			}
7802
7803			const currentValue = this[ key ];
7804
7805			if ( currentValue === undefined ) {
7806
7807				warn( `Texture.setValues(): property '${ key }' does not exist.` );
7808				continue;
7809
7810			}
7811
7812			if ( ( currentValue && newValue ) && ( currentValue.isVector2 && newValue.isVector2 ) ) {
7813
7814				currentValue.copy( newValue );
7815
7816			} else if ( ( currentValue && newValue ) && ( currentValue.isVector3 && newValue.isVector3 ) ) {
7817
7818				currentValue.copy( newValue );
7819
7820			} else if ( ( currentValue && newValue ) && ( currentValue.isMatrix3 && newValue.isMatrix3 ) ) {
7821
7822				currentValue.copy( newValue );
7823
7824			} else {
7825
7826				this[ key ] = newValue;
7827
7828			}
7829
7830		}
7831
7832	}
7833
7834	/**
7835	 * Serializes the texture into JSON.
7836	 *
7837	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
7838	 * @return {Object} A JSON object representing the serialized texture.
7839	 * @see {@link ObjectLoader#parse}
7840	 */
7841	toJSON( meta ) {
7842
7843		const isRootObject = ( meta === undefined || typeof meta === 'string' );
7844
7845		if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {
7846
7847			return meta.textures[ this.uuid ];
7848
7849		}
7850
7851		const output = {
7852
7853			metadata: {
7854				version: 4.7,
7855				type: 'Texture',
7856				generator: 'Texture.toJSON'
7857			},
7858
7859			uuid: this.uuid,
7860			name: this.name,
7861
7862			image: this.source.toJSON( meta ).uuid,
7863
7864			mapping: this.mapping,
7865			channel: this.channel,
7866
7867			repeat: [ this.repeat.x, this.repeat.y ],
7868			offset: [ this.offset.x, this.offset.y ],
7869			center: [ this.center.x, this.center.y ],
7870			rotation: this.rotation,
7871
7872			wrap: [ this.wrapS, this.wrapT ],
7873
7874			format: this.format,
7875			internalFormat: this.internalFormat,
7876			type: this.type,
7877			normalized: this.normalized,
7878			colorSpace: this.colorSpace,
7879
7880			minFilter: this.minFilter,
7881			magFilter: this.magFilter,
7882			anisotropy: this.anisotropy,
7883
7884			flipY: this.flipY,
7885
7886			generateMipmaps: this.generateMipmaps,
7887			premultiplyAlpha: this.premultiplyAlpha,
7888			unpackAlignment: this.unpackAlignment
7889
7890		};
7891
7892		if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData;
7893
7894		if ( ! isRootObject ) {
7895
7896			meta.textures[ this.uuid ] = output;
7897
7898		}
7899
7900		return output;
7901
7902	}
7903
7904	/**
7905	 * Frees the GPU-related resources allocated by this instance. Call this
7906	 * method whenever this instance is no longer used in your app.
7907	 *
7908	 * @fires Texture#dispose
7909	 */
7910	dispose() {
7911
7912		/**
7913		 * Fires when the texture has been disposed of.
7914		 *
7915		 * @event Texture#dispose
7916		 * @type {Object}
7917		 */
7918		this.dispatchEvent( { type: 'dispose' } );
7919
7920	}
7921
7922	/**
7923	 * Transforms the given uv vector with the textures uv transformation matrix.
7924	 *
7925	 * @param {Vector2} uv - The uv vector.
7926	 * @return {Vector2} The transformed uv vector.
7927	 */
7928	transformUv( uv ) {
7929
7930		if ( this.mapping !== UVMapping ) return uv;
7931
7932		uv.applyMatrix3( this.matrix );
7933
7934		if ( uv.x < 0 || uv.x > 1 ) {
7935
7936			switch ( this.wrapS ) {
7937
7938				case RepeatWrapping:
7939
7940					uv.x = uv.x - Math.floor( uv.x );
7941					break;
7942
7943				case ClampToEdgeWrapping:
7944
7945					uv.x = uv.x < 0 ? 0 : 1;
7946					break;
7947
7948				case MirroredRepeatWrapping:
7949
7950					if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {
7951
7952						uv.x = Math.ceil( uv.x ) - uv.x;
7953
7954					} else {
7955
7956						uv.x = uv.x - Math.floor( uv.x );
7957
7958					}
7959
7960					break;
7961
7962			}
7963
7964		}
7965
7966		if ( uv.y < 0 || uv.y > 1 ) {
7967
7968			switch ( this.wrapT ) {
7969
7970				case RepeatWrapping:
7971
7972					uv.y = uv.y - Math.floor( uv.y );
7973					break;
7974
7975				case ClampToEdgeWrapping:
7976
7977					uv.y = uv.y < 0 ? 0 : 1;
7978					break;
7979
7980				case MirroredRepeatWrapping:
7981
7982					if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {
7983
7984						uv.y = Math.ceil( uv.y ) - uv.y;
7985
7986					} else {
7987
7988						uv.y = uv.y - Math.floor( uv.y );
7989
7990					}
7991
7992					break;
7993
7994			}
7995
7996		}
7997
7998		if ( this.flipY ) {
7999
8000			uv.y = 1 - uv.y;
8001
8002		}
8003
8004		return uv;
8005
8006	}
8007
8008	/**
8009	 * Setting this property to `true` indicates the engine the texture
8010	 * must be updated in the next render. This triggers a texture upload
8011	 * to the GPU and ensures correct texture parameter configuration.
8012	 *
8013	 * @type {boolean}
8014	 * @default false
8015	 * @param {boolean} value
8016	 */
8017	set needsUpdate( value ) {
8018
8019		if ( value === true ) {
8020
8021			this.version ++;
8022			this.source.needsUpdate = true;
8023
8024		}
8025
8026	}
8027
8028	/**
8029	 * Setting this property to `true` indicates the engine the PMREM
8030	 * must be regenerated.
8031	 *
8032	 * @type {boolean}
8033	 * @default false
8034	 * @param {boolean} value
8035	 */
8036	set needsPMREMUpdate( value ) {
8037
8038		if ( value === true ) {
8039
8040			this.pmremVersion ++;
8041
8042		}
8043
8044	}
8045
8046}
8047
8048/**
8049 * The default image for all textures.
8050 *
8051 * @static
8052 * @type {?Image}
8053 * @default null
8054 */
8055Texture.DEFAULT_IMAGE = null;
8056
8057/**
8058 * The default mapping for all textures.
8059 *
8060 * @static
8061 * @type {number}
8062 * @default UVMapping
8063 */
8064Texture.DEFAULT_MAPPING = UVMapping;
8065
8066/**
8067 * The default anisotropy value for all textures.
8068 *
8069 * @static
8070 * @type {number}
8071 * @default 1
8072 */
8073Texture.DEFAULT_ANISOTROPY = 1;
8074
8075/**
8076 * Class representing a 4D vector. A 4D vector is an ordered quadruplet of numbers
8077 * (labeled x, y, z and w), which can be used to represent a number of things, such as:
8078 *
8079 * - A point in 4D space.
8080 * - A direction and length in 4D space. In three.js the length will
8081 * always be the Euclidean distance(straight-line distance) from `(0, 0, 0, 0)` to `(x, y, z, w)`
8082 * and the direction is also measured from `(0, 0, 0, 0)` towards `(x, y, z, w)`.
8083 * - Any arbitrary ordered quadruplet of numbers.
8084 *
8085 * There are other things a 4D vector can be used to represent, however these
8086 * are the most common uses in *three.js*.
8087 *
8088 * Iterating through a vector instance will yield its components `(x, y, z, w)` in
8089 * the corresponding order.
8090 * ```js
8091 * const a = new THREE.Vector4( 0, 1, 0, 0 );
8092 *
8093 * //no arguments; will be initialised to (0, 0, 0, 1)
8094 * const b = new THREE.Vector4( );
8095 *
8096 * const d = a.dot( b );
8097 * ```
8098 */
8099class Vector4 {
8100
8101	static {
8102
8103		/**
8104		 * This flag can be used for type testing.
8105		 *
8106		 * @type {boolean}
8107		 * @readonly
8108		 * @default true
8109		 */
8110		Vector4.prototype.isVector4 = true;
8111
8112	}
8113
8114	/**
8115	 * Constructs a new 4D vector.
8116	 *
8117	 * @param {number} [x=0] - The x value of this vector.
8118	 * @param {number} [y=0] - The y value of this vector.
8119	 * @param {number} [z=0] - The z value of this vector.
8120	 * @param {number} [w=1] - The w value of this vector.
8121	 */
8122	constructor( x = 0, y = 0, z = 0, w = 1 ) {
8123
8124		/**
8125		 * The x value of this vector.
8126		 *
8127		 * @type {number}
8128		 */
8129		this.x = x;
8130
8131		/**
8132		 * The y value of this vector.
8133		 *
8134		 * @type {number}
8135		 */
8136		this.y = y;
8137
8138		/**
8139		 * The z value of this vector.
8140		 *
8141		 * @type {number}
8142		 */
8143		this.z = z;
8144
8145		/**
8146		 * The w value of this vector.
8147		 *
8148		 * @type {number}
8149		 */
8150		this.w = w;
8151
8152	}
8153
8154	/**
8155	 * Alias for {@link Vector4#z}.
8156	 *
8157	 * @type {number}
8158	 */
8159	get width() {
8160
8161		return this.z;
8162
8163	}
8164
8165	set width( value ) {
8166
8167		this.z = value;
8168
8169	}
8170
8171	/**
8172	 * Alias for {@link Vector4#w}.
8173	 *
8174	 * @type {number}
8175	 */
8176	get height() {
8177
8178		return this.w;
8179
8180	}
8181
8182	set height( value ) {
8183
8184		this.w = value;
8185
8186	}
8187
8188	/**
8189	 * Sets the vector components.
8190	 *
8191	 * @param {number} x - The value of the x component.
8192	 * @param {number} y - The value of the y component.
8193	 * @param {number} z - The value of the z component.
8194	 * @param {number} w - The value of the w component.
8195	 * @return {Vector4} A reference to this vector.
8196	 */
8197	set( x, y, z, w ) {
8198
8199		this.x = x;
8200		this.y = y;
8201		this.z = z;
8202		this.w = w;
8203
8204		return this;
8205
8206	}
8207
8208	/**
8209	 * Sets the vector components to the same value.
8210	 *
8211	 * @param {number} scalar - The value to set for all vector components.
8212	 * @return {Vector4} A reference to this vector.
8213	 */
8214	setScalar( scalar ) {
8215
8216		this.x = scalar;
8217		this.y = scalar;
8218		this.z = scalar;
8219		this.w = scalar;
8220
8221		return this;
8222
8223	}
8224
8225	/**
8226	 * Sets the vector's x component to the given value
8227	 *
8228	 * @param {number} x - The value to set.
8229	 * @return {Vector4} A reference to this vector.
8230	 */
8231	setX( x ) {
8232
8233		this.x = x;
8234
8235		return this;
8236
8237	}
8238
8239	/**
8240	 * Sets the vector's y component to the given value
8241	 *
8242	 * @param {number} y - The value to set.
8243	 * @return {Vector4} A reference to this vector.
8244	 */
8245	setY( y ) {
8246
8247		this.y = y;
8248
8249		return this;
8250
8251	}
8252
8253	/**
8254	 * Sets the vector's z component to the given value
8255	 *
8256	 * @param {number} z - The value to set.
8257	 * @return {Vector4} A reference to this vector.
8258	 */
8259	setZ( z ) {
8260
8261		this.z = z;
8262
8263		return this;
8264
8265	}
8266
8267	/**
8268	 * Sets the vector's w component to the given value
8269	 *
8270	 * @param {number} w - The value to set.
8271	 * @return {Vector4} A reference to this vector.
8272	 */
8273	setW( w ) {
8274
8275		this.w = w;
8276
8277		return this;
8278
8279	}
8280
8281	/**
8282	 * Allows to set a vector component with an index.
8283	 *
8284	 * @param {number} index - The component index. `0` equals to x, `1` equals to y,
8285	 * `2` equals to z, `3` equals to w.
8286	 * @param {number} value - The value to set.
8287	 * @return {Vector4} A reference to this vector.
8288	 */
8289	setComponent( index, value ) {
8290
8291		switch ( index ) {
8292
8293			case 0: this.x = value; break;
8294			case 1: this.y = value; break;
8295			case 2: this.z = value; break;
8296			case 3: this.w = value; break;
8297			default: throw new Error( 'THREE.Vector4: index is out of range: ' + index );
8298
8299		}
8300
8301		return this;
8302
8303	}
8304
8305	/**
8306	 * Returns the value of the vector component which matches the given index.
8307	 *
8308	 * @param {number} index - The component index. `0` equals to x, `1` equals to y,
8309	 * `2` equals to z, `3` equals to w.
8310	 * @return {number} A vector component value.
8311	 */
8312	getComponent( index ) {
8313
8314		switch ( index ) {
8315
8316			case 0: return this.x;
8317			case 1: return this.y;
8318			case 2: return this.z;
8319			case 3: return this.w;
8320			default: throw new Error( 'THREE.Vector4: index is out of range: ' + index );
8321
8322		}
8323
8324	}
8325
8326	/**
8327	 * Returns a new vector with copied values from this instance.
8328	 *
8329	 * @return {Vector4} A clone of this instance.
8330	 */
8331	clone() {
8332
8333		return new this.constructor( this.x, this.y, this.z, this.w );
8334
8335	}
8336
8337	/**
8338	 * Copies the values of the given vector to this instance.
8339	 *
8340	 * @param {Vector3|Vector4} v - The vector to copy.
8341	 * @return {Vector4} A reference to this vector.
8342	 */
8343	copy( v ) {
8344
8345		this.x = v.x;
8346		this.y = v.y;
8347		this.z = v.z;
8348		this.w = ( v.w !== undefined ) ? v.w : 1;
8349
8350		return this;
8351
8352	}
8353
8354	/**
8355	 * Adds the given vector to this instance.
8356	 *
8357	 * @param {Vector4} v - The vector to add.
8358	 * @return {Vector4} A reference to this vector.
8359	 */
8360	add( v ) {
8361
8362		this.x += v.x;
8363		this.y += v.y;
8364		this.z += v.z;
8365		this.w += v.w;
8366
8367		return this;
8368
8369	}
8370
8371	/**
8372	 * Adds the given scalar value to all components of this instance.
8373	 *
8374	 * @param {number} s - The scalar to add.
8375	 * @return {Vector4} A reference to this vector.
8376	 */
8377	addScalar( s ) {
8378
8379		this.x += s;
8380		this.y += s;
8381		this.z += s;
8382		this.w += s;
8383
8384		return this;
8385
8386	}
8387
8388	/**
8389	 * Adds the given vectors and stores the result in this instance.
8390	 *
8391	 * @param {Vector4} a - The first vector.
8392	 * @param {Vector4} b - The second vector.
8393	 * @return {Vector4} A reference to this vector.
8394	 */
8395	addVectors( a, b ) {
8396
8397		this.x = a.x + b.x;
8398		this.y = a.y + b.y;
8399		this.z = a.z + b.z;
8400		this.w = a.w + b.w;
8401
8402		return this;
8403
8404	}
8405
8406	/**
8407	 * Adds the given vector scaled by the given factor to this instance.
8408	 *
8409	 * @param {Vector4} v - The vector.
8410	 * @param {number} s - The factor that scales `v`.
8411	 * @return {Vector4} A reference to this vector.
8412	 */
8413	addScaledVector( v, s ) {
8414
8415		this.x += v.x * s;
8416		this.y += v.y * s;
8417		this.z += v.z * s;
8418		this.w += v.w * s;
8419
8420		return this;
8421
8422	}
8423
8424	/**
8425	 * Subtracts the given vector from this instance.
8426	 *
8427	 * @param {Vector4} v - The vector to subtract.
8428	 * @return {Vector4} A reference to this vector.
8429	 */
8430	sub( v ) {
8431
8432		this.x -= v.x;
8433		this.y -= v.y;
8434		this.z -= v.z;
8435		this.w -= v.w;
8436
8437		return this;
8438
8439	}
8440
8441	/**
8442	 * Subtracts the given scalar value from all components of this instance.
8443	 *
8444	 * @param {number} s - The scalar to subtract.
8445	 * @return {Vector4} A reference to this vector.
8446	 */
8447	subScalar( s ) {
8448
8449		this.x -= s;
8450		this.y -= s;
8451		this.z -= s;
8452		this.w -= s;
8453
8454		return this;
8455
8456	}
8457
8458	/**
8459	 * Subtracts the given vectors and stores the result in this instance.
8460	 *
8461	 * @param {Vector4} a - The first vector.
8462	 * @param {Vector4} b - The second vector.
8463	 * @return {Vector4} A reference to this vector.
8464	 */
8465	subVectors( a, b ) {
8466
8467		this.x = a.x - b.x;
8468		this.y = a.y - b.y;
8469		this.z = a.z - b.z;
8470		this.w = a.w - b.w;
8471
8472		return this;
8473
8474	}
8475
8476	/**
8477	 * Multiplies the given vector with this instance.
8478	 *
8479	 * @param {Vector4} v - The vector to multiply.
8480	 * @return {Vector4} A reference to this vector.
8481	 */
8482	multiply( v ) {
8483
8484		this.x *= v.x;
8485		this.y *= v.y;
8486		this.z *= v.z;
8487		this.w *= v.w;
8488
8489		return this;
8490
8491	}
8492
8493	/**
8494	 * Multiplies the given scalar value with all components of this instance.
8495	 *
8496	 * @param {number} scalar - The scalar to multiply.
8497	 * @return {Vector4} A reference to this vector.
8498	 */
8499	multiplyScalar( scalar ) {
8500
8501		this.x *= scalar;
8502		this.y *= scalar;
8503		this.z *= scalar;
8504		this.w *= scalar;
8505
8506		return this;
8507
8508	}
8509
8510	/**
8511	 * Multiplies this vector with the given 4x4 matrix.
8512	 *
8513	 * @param {Matrix4} m - The 4x4 matrix.
8514	 * @return {Vector4} A reference to this vector.
8515	 */
8516	applyMatrix4( m ) {
8517
8518		const x = this.x, y = this.y, z = this.z, w = this.w;
8519		const e = m.elements;
8520
8521		this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
8522		this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
8523		this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
8524		this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
8525
8526		return this;
8527
8528	}
8529
8530	/**
8531	 * Divides this instance by the given vector.
8532	 *
8533	 * @param {Vector4} v - The vector to divide.
8534	 * @return {Vector4} A reference to this vector.
8535	 */
8536	divide( v ) {
8537
8538		this.x /= v.x;
8539		this.y /= v.y;
8540		this.z /= v.z;
8541		this.w /= v.w;
8542
8543		return this;
8544
8545	}
8546
8547	/**
8548	 * Divides this vector by the given scalar.
8549	 *
8550	 * @param {number} scalar - The scalar to divide.
8551	 * @return {Vector4} A reference to this vector.
8552	 */
8553	divideScalar( scalar ) {
8554
8555		return this.multiplyScalar( 1 / scalar );
8556
8557	}
8558
8559	/**
8560	 * Sets the x, y and z components of this
8561	 * vector to the quaternion's axis and w to the angle.
8562	 *
8563	 * @param {Quaternion} q - The Quaternion to set.
8564	 * @return {Vector4} A reference to this vector.
8565	 */
8566	setAxisAngleFromQuaternion( q ) {
8567
8568		// q is assumed to be normalized
8569
8570		this.w = 2 * Math.acos( q.w );
8571
8572		const s = Math.sqrt( 1 - q.w * q.w );
8573
8574		if ( s < 0.0001 ) {
8575
8576			this.x = 1;
8577			this.y = 0;
8578			this.z = 0;
8579
8580		} else {
8581
8582			this.x = q.x / s;
8583			this.y = q.y / s;
8584			this.z = q.z / s;
8585
8586		}
8587
8588		return this;
8589
8590	}
8591
8592	/**
8593	 * Sets the x, y and z components of this
8594	 * vector to the axis of rotation and w to the angle.
8595	 *
8596	 * @param {Matrix4} m - A 4x4 matrix of which the upper left 3x3 matrix is a pure rotation matrix.
8597	 * @return {Vector4} A reference to this vector.
8598	 */
8599	setAxisAngleFromRotationMatrix( m ) {
8600
8601		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
8602
8603		let angle, x, y, z; // variables for result
8604		const epsilon = 0.01,		// margin to allow for rounding errors
8605			epsilon2 = 0.1,		// margin to distinguish between 0 and 180 degrees
8606
8607			te = m.elements,
8608
8609			m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
8610			m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
8611			m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
8612
8613		if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
8614		     ( Math.abs( m13 - m31 ) < epsilon ) &&
8615		     ( Math.abs( m23 - m32 ) < epsilon ) ) {
8616
8617			// singularity found
8618			// first check for identity matrix which must have +1 for all terms
8619			// in leading diagonal and zero in other terms
8620
8621			if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
8622			     ( Math.abs( m13 + m31 ) < epsilon2 ) &&
8623			     ( Math.abs( m23 + m32 ) < epsilon2 ) &&
8624			     ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
8625
8626				// this singularity is identity matrix so angle = 0
8627
8628				this.set( 1, 0, 0, 0 );
8629
8630				return this; // zero angle, arbitrary axis
8631
8632			}
8633
8634			// otherwise this singularity is angle = 180
8635
8636			angle = Math.PI;
8637
8638			const xx = ( m11 + 1 ) / 2;
8639			const yy = ( m22 + 1 ) / 2;
8640			const zz = ( m33 + 1 ) / 2;
8641			const xy = ( m12 + m21 ) / 4;
8642			const xz = ( m13 + m31 ) / 4;
8643			const yz = ( m23 + m32 ) / 4;
8644
8645			if ( ( xx > yy ) && ( xx > zz ) ) {
8646
8647				// m11 is the largest diagonal term
8648
8649				if ( xx < epsilon ) {
8650
8651					x = 0;
8652					y = 0.707106781;
8653					z = 0.707106781;
8654
8655				} else {
8656
8657					x = Math.sqrt( xx );
8658					y = xy / x;
8659					z = xz / x;
8660
8661				}
8662
8663			} else if ( yy > zz ) {
8664
8665				// m22 is the largest diagonal term
8666
8667				if ( yy < epsilon ) {
8668
8669					x = 0.707106781;
8670					y = 0;
8671					z = 0.707106781;
8672
8673				} else {
8674
8675					y = Math.sqrt( yy );
8676					x = xy / y;
8677					z = yz / y;
8678
8679				}
8680
8681			} else {
8682
8683				// m33 is the largest diagonal term so base result on this
8684
8685				if ( zz < epsilon ) {
8686
8687					x = 0.707106781;
8688					y = 0.707106781;
8689					z = 0;
8690
8691				} else {
8692
8693					z = Math.sqrt( zz );
8694					x = xz / z;
8695					y = yz / z;
8696
8697				}
8698
8699			}
8700
8701			this.set( x, y, z, angle );
8702
8703			return this; // return 180 deg rotation
8704
8705		}
8706
8707		// as we have reached here there are no singularities so we can handle normally
8708
8709		let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
8710			( m13 - m31 ) * ( m13 - m31 ) +
8711			( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
8712
8713		if ( Math.abs( s ) < 0.001 ) s = 1;
8714
8715		// prevent divide by zero, should not happen if matrix is orthogonal and should be
8716		// caught by singularity test above, but I've left it in just in case
8717
8718		this.x = ( m32 - m23 ) / s;
8719		this.y = ( m13 - m31 ) / s;
8720		this.z = ( m21 - m12 ) / s;
8721		this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
8722
8723		return this;
8724
8725	}
8726
8727	/**
8728	 * Sets the vector components to the position elements of the
8729	 * given transformation matrix.
8730	 *
8731	 * @param {Matrix4} m - The 4x4 matrix.
8732	 * @return {Vector4} A reference to this vector.
8733	 */
8734	setFromMatrixPosition( m ) {
8735
8736		const e = m.elements;
8737
8738		this.x = e[ 12 ];
8739		this.y = e[ 13 ];
8740		this.z = e[ 14 ];
8741		this.w = e[ 15 ];
8742
8743		return this;
8744
8745	}
8746
8747	/**
8748	 * If this vector's x, y, z or w value is greater than the given vector's x, y, z or w
8749	 * value, replace that value with the corresponding min value.
8750	 *
8751	 * @param {Vector4} v - The vector.
8752	 * @return {Vector4} A reference to this vector.
8753	 */
8754	min( v ) {
8755
8756		this.x = Math.min( this.x, v.x );
8757		this.y = Math.min( this.y, v.y );
8758		this.z = Math.min( this.z, v.z );
8759		this.w = Math.min( this.w, v.w );
8760
8761		return this;
8762
8763	}
8764
8765	/**
8766	 * If this vector's x, y, z or w value is less than the given vector's x, y, z or w
8767	 * value, replace that value with the corresponding max value.
8768	 *
8769	 * @param {Vector4} v - The vector.
8770	 * @return {Vector4} A reference to this vector.
8771	 */
8772	max( v ) {
8773
8774		this.x = Math.max( this.x, v.x );
8775		this.y = Math.max( this.y, v.y );
8776		this.z = Math.max( this.z, v.z );
8777		this.w = Math.max( this.w, v.w );
8778
8779		return this;
8780
8781	}
8782
8783	/**
8784	 * If this vector's x, y, z or w value is greater than the max vector's x, y, z or w
8785	 * value, it is replaced by the corresponding value.
8786	 * If this vector's x, y, z or w value is less than the min vector's x, y, z or w value,
8787	 * it is replaced by the corresponding value.
8788	 *
8789	 * @param {Vector4} min - The minimum x, y and z values.
8790	 * @param {Vector4} max - The maximum x, y and z values in the desired range.
8791	 * @return {Vector4} A reference to this vector.
8792	 */
8793	clamp( min, max ) {
8794
8795		// assumes min < max, componentwise
8796
8797		this.x = clamp( this.x, min.x, max.x );
8798		this.y = clamp( this.y, min.y, max.y );
8799		this.z = clamp( this.z, min.z, max.z );
8800		this.w = clamp( this.w, min.w, max.w );
8801
8802		return this;
8803
8804	}
8805
8806	/**
8807	 * If this vector's x, y, z or w values are greater than the max value, they are
8808	 * replaced by the max value.
8809	 * If this vector's x, y, z or w values are less than the min value, they are
8810	 * replaced by the min value.
8811	 *
8812	 * @param {number} minVal - The minimum value the components will be clamped to.
8813	 * @param {number} maxVal - The maximum value the components will be clamped to.
8814	 * @return {Vector4} A reference to this vector.
8815	 */
8816	clampScalar( minVal, maxVal ) {
8817
8818		this.x = clamp( this.x, minVal, maxVal );
8819		this.y = clamp( this.y, minVal, maxVal );
8820		this.z = clamp( this.z, minVal, maxVal );
8821		this.w = clamp( this.w, minVal, maxVal );
8822
8823		return this;
8824
8825	}
8826
8827	/**
8828	 * If this vector's length is greater than the max value, it is replaced by
8829	 * the max value.
8830	 * If this vector's length is less than the min value, it is replaced by the
8831	 * min value.
8832	 *
8833	 * @param {number} min - The minimum value the vector length will be clamped to.
8834	 * @param {number} max - The maximum value the vector length will be clamped to.
8835	 * @return {Vector4} A reference to this vector.
8836	 */
8837	clampLength( min, max ) {
8838
8839		const length = this.length();
8840
8841		return this.divideScalar( length || 1 ).multiplyScalar( clamp( length, min, max ) );
8842
8843	}
8844
8845	/**
8846	 * The components of this vector are rounded down to the nearest integer value.
8847	 *
8848	 * @return {Vector4} A reference to this vector.
8849	 */
8850	floor() {
8851
8852		this.x = Math.floor( this.x );
8853		this.y = Math.floor( this.y );
8854		this.z = Math.floor( this.z );
8855		this.w = Math.floor( this.w );
8856
8857		return this;
8858
8859	}
8860
8861	/**
8862	 * The components of this vector are rounded up to the nearest integer value.
8863	 *
8864	 * @return {Vector4} A reference to this vector.
8865	 */
8866	ceil() {
8867
8868		this.x = Math.ceil( this.x );
8869		this.y = Math.ceil( this.y );
8870		this.z = Math.ceil( this.z );
8871		this.w = Math.ceil( this.w );
8872
8873		return this;
8874
8875	}
8876
8877	/**
8878	 * The components of this vector are rounded to the nearest integer value
8879	 *
8880	 * @return {Vector4} A reference to this vector.
8881	 */
8882	round() {
8883
8884		this.x = Math.round( this.x );
8885		this.y = Math.round( this.y );
8886		this.z = Math.round( this.z );
8887		this.w = Math.round( this.w );
8888
8889		return this;
8890
8891	}
8892
8893	/**
8894	 * The components of this vector are rounded towards zero (up if negative,
8895	 * down if positive) to an integer value.
8896	 *
8897	 * @return {Vector4} A reference to this vector.
8898	 */
8899	roundToZero() {
8900
8901		this.x = Math.trunc( this.x );
8902		this.y = Math.trunc( this.y );
8903		this.z = Math.trunc( this.z );
8904		this.w = Math.trunc( this.w );
8905
8906		return this;
8907
8908	}
8909
8910	/**
8911	 * Inverts this vector - i.e. sets x = -x, y = -y, z = -z, w = -w.
8912	 *
8913	 * @return {Vector4} A reference to this vector.
8914	 */
8915	negate() {
8916
8917		this.x = - this.x;
8918		this.y = - this.y;
8919		this.z = - this.z;
8920		this.w = - this.w;
8921
8922		return this;
8923
8924	}
8925
8926	/**
8927	 * Calculates the dot product of the given vector with this instance.
8928	 *
8929	 * @param {Vector4} v - The vector to compute the dot product with.
8930	 * @return {number} The result of the dot product.
8931	 */
8932	dot( v ) {
8933
8934		return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
8935
8936	}
8937
8938	/**
8939	 * Computes the square of the Euclidean length (straight-line length) from
8940	 * (0, 0, 0, 0) to (x, y, z, w). If you are comparing the lengths of vectors, you should
8941	 * compare the length squared instead as it is slightly more efficient to calculate.
8942	 *
8943	 * @return {number} The square length of this vector.
8944	 */
8945	lengthSq() {
8946
8947		return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
8948
8949	}
8950
8951	/**
8952	 * Computes the  Euclidean length (straight-line length) from (0, 0, 0, 0) to (x, y, z, w).
8953	 *
8954	 * @return {number} The length of this vector.
8955	 */
8956	length() {
8957
8958		return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
8959
8960	}
8961
8962	/**
8963	 * Computes the Manhattan length of this vector.
8964	 *
8965	 * @return {number} The length of this vector.
8966	 */
8967	manhattanLength() {
8968
8969		return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
8970
8971	}
8972
8973	/**
8974	 * Converts this vector to a unit vector - that is, sets it equal to a vector
8975	 * with the same direction as this one, but with a vector length of `1`.
8976	 *
8977	 * @return {Vector4} A reference to this vector.
8978	 */
8979	normalize() {
8980
8981		return this.divideScalar( this.length() || 1 );
8982
8983	}
8984
8985	/**
8986	 * Sets this vector to a vector with the same direction as this one, but
8987	 * with the specified length.
8988	 *
8989	 * @param {number} length - The new length of this vector.
8990	 * @return {Vector4} A reference to this vector.
8991	 */
8992	setLength( length ) {
8993
8994		return this.normalize().multiplyScalar( length );
8995
8996	}
8997
8998	/**
8999	 * Linearly interpolates between the given vector and this instance, where
9000	 * alpha is the percent distance along the line - alpha = 0 will be this
9001	 * vector, and alpha = 1 will be the given one.
9002	 *
9003	 * @param {Vector4} v - The vector to interpolate towards.
9004	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
9005	 * @return {Vector4} A reference to this vector.
9006	 */
9007	lerp( v, alpha ) {
9008
9009		this.x += ( v.x - this.x ) * alpha;
9010		this.y += ( v.y - this.y ) * alpha;
9011		this.z += ( v.z - this.z ) * alpha;
9012		this.w += ( v.w - this.w ) * alpha;
9013
9014		return this;
9015
9016	}
9017
9018	/**
9019	 * Linearly interpolates between the given vectors, where alpha is the percent
9020	 * distance along the line - alpha = 0 will be first vector, and alpha = 1 will
9021	 * be the second one. The result is stored in this instance.
9022	 *
9023	 * @param {Vector4} v1 - The first vector.
9024	 * @param {Vector4} v2 - The second vector.
9025	 * @param {number} alpha - The interpolation factor, typically in the closed interval `[0, 1]`.
9026	 * @return {Vector4} A reference to this vector.
9027	 */
9028	lerpVectors( v1, v2, alpha ) {
9029
9030		this.x = v1.x + ( v2.x - v1.x ) * alpha;
9031		this.y = v1.y + ( v2.y - v1.y ) * alpha;
9032		this.z = v1.z + ( v2.z - v1.z ) * alpha;
9033		this.w = v1.w + ( v2.w - v1.w ) * alpha;
9034
9035		return this;
9036
9037	}
9038
9039	/**
9040	 * Returns `true` if this vector is equal with the given one.
9041	 *
9042	 * @param {Vector4} v - The vector to test for equality.
9043	 * @return {boolean} Whether this vector is equal with the given one.
9044	 */
9045	equals( v ) {
9046
9047		return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
9048
9049	}
9050
9051	/**
9052	 * Sets this vector's x value to be `array[ offset ]`, y value to be `array[ offset + 1 ]`,
9053	 * z value to be `array[ offset + 2 ]`, w value to be `array[ offset + 3 ]`.
9054	 *
9055	 * @param {Array<number>} array - An array holding the vector component values.
9056	 * @param {number} [offset=0] - The offset into the array.
9057	 * @return {Vector4} A reference to this vector.
9058	 */
9059	fromArray( array, offset = 0 ) {
9060
9061		this.x = array[ offset ];
9062		this.y = array[ offset + 1 ];
9063		this.z = array[ offset + 2 ];
9064		this.w = array[ offset + 3 ];
9065
9066		return this;
9067
9068	}
9069
9070	/**
9071	 * Writes the components of this vector to the given array. If no array is provided,
9072	 * the method returns a new instance.
9073	 *
9074	 * @param {Array<number>} [array=[]] - The target array holding the vector components.
9075	 * @param {number} [offset=0] - Index of the first element in the array.
9076	 * @return {Array<number>} The vector components.
9077	 */
9078	toArray( array = [], offset = 0 ) {
9079
9080		array[ offset ] = this.x;
9081		array[ offset + 1 ] = this.y;
9082		array[ offset + 2 ] = this.z;
9083		array[ offset + 3 ] = this.w;
9084
9085		return array;
9086
9087	}
9088
9089	/**
9090	 * Sets the components of this vector from the given buffer attribute.
9091	 *
9092	 * @param {BufferAttribute} attribute - The buffer attribute holding vector data.
9093	 * @param {number} index - The index into the attribute.
9094	 * @return {Vector4} A reference to this vector.
9095	 */
9096	fromBufferAttribute( attribute, index ) {
9097
9098		this.x = attribute.getX( index );
9099		this.y = attribute.getY( index );
9100		this.z = attribute.getZ( index );
9101		this.w = attribute.getW( index );
9102
9103		return this;
9104
9105	}
9106
9107	/**
9108	 * Sets each component of this vector to a pseudo-random value between `0` and
9109	 * `1`, excluding `1`.
9110	 *
9111	 * @return {Vector4} A reference to this vector.
9112	 */
9113	random() {
9114
9115		this.x = Math.random();
9116		this.y = Math.random();
9117		this.z = Math.random();
9118		this.w = Math.random();
9119
9120		return this;
9121
9122	}
9123
9124	*[ Symbol.iterator ]() {
9125
9126		yield this.x;
9127		yield this.y;
9128		yield this.z;
9129		yield this.w;
9130
9131	}
9132
9133}
9134
9135/**
9136 * A render target is a buffer where the video card draws pixels for a scene
9137 * that is being rendered in the background. It is used in different effects,
9138 * such as applying postprocessing to a rendered image before displaying it
9139 * on the screen.
9140 *
9141 * @augments EventDispatcher
9142 */
9143class RenderTarget extends EventDispatcher {
9144
9145	/**
9146	 * Render target options.
9147	 *
9148	 * @typedef {Object} RenderTarget~Options
9149	 * @property {boolean} [generateMipmaps=false] - Whether to generate mipmaps or not.
9150	 * @property {number} [magFilter=LinearFilter] - The mag filter.
9151	 * @property {number} [minFilter=LinearFilter] - The min filter.
9152	 * @property {number} [format=RGBAFormat] - The texture format.
9153	 * @property {number} [type=UnsignedByteType] - The texture type.
9154	 * @property {?string} [internalFormat=null] - The texture's internal format.
9155	 * @property {number} [wrapS=ClampToEdgeWrapping] - The texture's uv wrapping mode.
9156	 * @property {number} [wrapT=ClampToEdgeWrapping] - The texture's uv wrapping mode.
9157	 * @property {number} [anisotropy=1] - The texture's anisotropy value.
9158	 * @property {string} [colorSpace=NoColorSpace] - The texture's color space.
9159	 * @property {boolean} [depthBuffer=true] - Whether to allocate a depth buffer or not.
9160	 * @property {boolean} [stencilBuffer=false] - Whether to allocate a stencil buffer or not.
9161	 * @property {boolean} [resolveColorBuffer=true] - Whether to resolve the color buffer or not. Only relevant for multisampled render targets.
9162	 * @property {boolean} [resolveDepthBuffer=true] - Whether to resolve the depth buffer or not. Only relevant for multisampled render targets.
9163	 * @property {boolean} [resolveStencilBuffer=true] - Whether to resolve the stencil buffer or not. Only relevant for multisampled render targets.
9164	 * @property {boolean} [storeMultisampledColorBuffer=true] - Whether to store the multisampled color buffer or not. Setting to `false` saves memory bandwidth when the multisampled data are not needed after a render pass.
9165	 * @property {boolean} [storeMultisampledDepthBuffer=true] - Whether to store the multisampled depth buffer or not. Setting to `false` saves memory bandwidth when the multisampled data are not needed after a render pass.
9166	 * @property {boolean} [storeMultisampledStencilBuffer=true] - Whether to store the multisampled stencil buffer or not. Setting to `false` saves memory bandwidth when the multisampled data are not needed after a render pass.
9167	 * @property {?Texture} [depthTexture=null] - Reference to a depth texture.
9168	 * @property {number} [samples=0] - The MSAA samples count.
9169	 * @property {number} [count=1] - Defines the number of color attachments . Must be at least `1`.
9170	 * @property {number} [depth=1] - The texture depth.
9171	 * @property {boolean} [multiview=false] - Whether this target is used for multiview rendering (WebGL OVR_multiview2 extension).
9172	 * @property {boolean} [useArrayDepthTexture=false] - Whether to create the depth texture as an array texture for per-layer depth testing. This is separate from multiview so layered render targets can use array depth without the multiview extension.
9173	 */
9174
9175	/**
9176	 * Constructs a new render target.
9177	 *
9178	 * @param {number} [width=1] - The width of the render target.
9179	 * @param {number} [height=1] - The height of the render target.
9180	 * @param {RenderTarget~Options} [options] - The configuration object.
9181	 */
9182	constructor( width = 1, height = 1, options = {} ) {
9183
9184		super();
9185
9186		options = Object.assign( {
9187			generateMipmaps: false,
9188			internalFormat: null,
9189			minFilter: LinearFilter,
9190			depthBuffer: true,
9191			stencilBuffer: false,
9192			resolveColorBuffer: true,
9193			resolveDepthBuffer: true,
9194			resolveStencilBuffer: true,
9195			storeMultisampledColorBuffer: true,
9196			storeMultisampledDepthBuffer: true,
9197			storeMultisampledStencilBuffer: true,
9198			depthTexture: null,
9199			samples: 0,
9200			count: 1,
9201			depth: 1,
9202			multiview: false,
9203			useArrayDepthTexture: false
9204		}, options );
9205
9206		/**
9207		 * This flag can be used for type testing.
9208		 *
9209		 * @type {boolean}
9210		 * @readonly
9211		 * @default true
9212		 */
9213		this.isRenderTarget = true;
9214
9215		/**
9216		 * The width of the render target.
9217		 *
9218		 * @type {number}
9219		 * @default 1
9220		 */
9221		this.width = width;
9222
9223		/**
9224		 * The height of the render target.
9225		 *
9226		 * @type {number}
9227		 * @default 1
9228		 */
9229		this.height = height;
9230
9231		/**
9232		 * The depth of the render target.
9233		 *
9234		 * @type {number}
9235		 * @default 1
9236		 */
9237		this.depth = options.depth;
9238
9239		/**
9240		 * A rectangular area inside the render target's viewport. Fragments that are
9241		 * outside the area will be discarded.
9242		 *
9243		 * @type {Vector4}
9244		 * @default (0,0,width,height)
9245		 */
9246		this.scissor = new Vector4( 0, 0, width, height );
9247
9248		/**
9249		 * Indicates whether the scissor test should be enabled when rendering into
9250		 * this render target or not.
9251		 *
9252		 * @type {boolean}
9253		 * @default false
9254		 */
9255		this.scissorTest = false;
9256
9257		/**
9258		 * A rectangular area representing the render target's viewport.
9259		 *
9260		 * @type {Vector4}
9261		 * @default (0,0,width,height)
9262		 */
9263		this.viewport = new Vector4( 0, 0, width, height );
9264
9265		/**
9266		 * An array of textures. Each color attachment is represented as a separate texture.
9267		 * Has at least a single entry for the default color attachment.
9268		 *
9269		 * @type {Array<Texture>}
9270		 */
9271		this.textures = [];
9272
9273		const image = { width: width, height: height, depth: options.depth };
9274		const texture = new Texture( image );
9275
9276		const count = options.count;
9277		for ( let i = 0; i < count; i ++ ) {
9278
9279			this.textures[ i ] = texture.clone();
9280			this.textures[ i ].isRenderTargetTexture = true;
9281			this.textures[ i ].renderTarget = this;
9282
9283		}
9284
9285		this._setTextureOptions( options );
9286
9287		/**
9288		 * Whether to allocate a depth buffer or not.
9289		 *
9290		 * @type {boolean}
9291		 * @default true
9292		 */
9293		this.depthBuffer = options.depthBuffer;
9294
9295		/**
9296		 * Whether to allocate a stencil buffer or not.
9297		 *
9298		 * @type {boolean}
9299		 * @default false
9300		 */
9301		this.stencilBuffer = options.stencilBuffer;
9302
9303		/**
9304		 * Whether to resolve the color buffer or not. When set to `false`, the color
9305		 * attachments do not receive the resolved (single-sampled) output of a render
9306		 * pass and the render target's textures are left untouched. The rendered
9307		 * content is then only accessible within the render pass itself.
9308		 *
9309		 * Only relevant for multisampled render targets.
9310		 *
9311		 * @type {boolean}
9312		 * @default true
9313		 */
9314		this.resolveColorBuffer = options.resolveColorBuffer;
9315
9316		/**
9317		 * Whether to resolve the depth buffer or not. When set to `false`, the depth
9318		 * texture does not receive the resolved depth output of a render pass which
9319		 * saves memory bandwidth. Use this setting when the depth data of a render
9320		 * pass are not required afterwards.
9321		 *
9322		 * Only relevant for multisampled render targets in WebGL. WebGPU does not
9323		 * support depth resolves; sampling the depth texture of a multisampled render
9324		 * target accesses the multisampled data directly, see
9325		 * {@link RenderTarget#storeMultisampledDepthBuffer}.
9326		 *
9327		 * @type {boolean}
9328		 * @default true
9329		 */
9330		this.resolveDepthBuffer = options.resolveDepthBuffer;
9331
9332		/**
9333		 * Whether to resolve the stencil buffer or not. Analogous to
9334		 * {@link RenderTarget#resolveDepthBuffer} but for the stencil aspect.
9335		 *
9336		 * @type {boolean}
9337		 * @default true
9338		 */
9339		this.resolveStencilBuffer = options.resolveStencilBuffer;
9340
9341		/**
9342		 * Whether to store the multisampled color buffer or not. When set to `false`,
9343		 * the multisampled data are discarded at the end of a render pass, right after
9344		 * they have been resolved. This saves memory bandwidth, especially on tile-based
9345		 * GPUs, and is the recommended setting for render targets that are fully redrawn
9346		 * each frame and whose output is only accessed via the resolved textures (e.g.
9347		 * scene passes in post-processing chains).
9348		 *
9349		 * Must be kept `true` when the multisampled data are needed after the render
9350		 * pass ends, e.g. when rendering into the target without clearing or when the
9351		 * scene contains transmissive objects which require a mid-pass framebuffer copy.
9352		 *
9353		 * @type {boolean}
9354		 * @default true
9355		 */
9356		this.storeMultisampledColorBuffer = options.storeMultisampledColorBuffer;
9357
9358		/**
9359		 * Whether to store the multisampled depth buffer or not. When set to `false`,
9360		 * the multisampled depth data are discarded at the end of a render pass which
9361		 * saves memory bandwidth.
9362		 *
9363		 * Must be kept `true` in WebGPU when the depth texture of a multisampled render
9364		 * target is sampled (e.g. by depth-based post-processing effects) since depth
9365		 * is read directly from the multisampled data.
9366		 *
9367		 * @type {boolean}
9368		 * @default true
9369		 */
9370		this.storeMultisampledDepthBuffer = options.storeMultisampledDepthBuffer;
9371
9372		/**
9373		 * Whether to store the multisampled stencil buffer or not. Analogous to
9374		 * {@link RenderTarget#storeMultisampledDepthBuffer} but for the stencil aspect.
9375		 *
9376		 * @type {boolean}
9377		 * @default true
9378		 */
9379		this.storeMultisampledStencilBuffer = options.storeMultisampledStencilBuffer;
9380
9381		this._depthTexture = null;
9382		this.depthTexture = options.depthTexture;
9383
9384		/**
9385		 * The number of MSAA samples.
9386		 *
9387		 * A value of `0` disables MSAA.
9388		 *
9389		 * @type {number}
9390		 * @default 0
9391		 */
9392		this.samples = options.samples;
9393
9394		/**
9395		 * Whether to this target is used in multiview rendering.
9396		 *
9397		 * @type {boolean}
9398		 * @default false
9399		 */
9400		this.multiview = options.multiview;
9401
9402		/**
9403		 * Whether to create the depth texture as an array texture for per-layer depth testing.
9404		 * This is separate from multiview so layered render targets can use array depth without
9405		 * the multiview extension.
9406		 *
9407		 * @type {boolean}
9408		 * @default false
9409		 */
9410		this.useArrayDepthTexture = options.useArrayDepthTexture;
9411
9412	}
9413
9414	_setTextureOptions( options = {} ) {
9415
9416		const values = {
9417			minFilter: LinearFilter,
9418			generateMipmaps: false,
9419			flipY: false,
9420			internalFormat: null
9421		};
9422
9423		if ( options.mapping !== undefined ) values.mapping = options.mapping;
9424		if ( options.wrapS !== undefined ) values.wrapS = options.wrapS;
9425		if ( options.wrapT !== undefined ) values.wrapT = options.wrapT;
9426		if ( options.wrapR !== undefined ) values.wrapR = options.wrapR;
9427		if ( options.magFilter !== undefined ) values.magFilter = options.magFilter;
9428		if ( options.minFilter !== undefined ) values.minFilter = options.minFilter;
9429		if ( options.format !== undefined ) values.format = options.format;
9430		if ( options.type !== undefined ) values.type = options.type;
9431		if ( options.anisotropy !== undefined ) values.anisotropy = options.anisotropy;
9432		if ( options.colorSpace !== undefined ) values.colorSpace = options.colorSpace;
9433		if ( options.flipY !== undefined ) values.flipY = options.flipY;
9434		if ( options.generateMipmaps !== undefined ) values.generateMipmaps = options.generateMipmaps;
9435		if ( options.internalFormat !== undefined ) values.internalFormat = options.internalFormat;
9436
9437		for ( let i = 0; i < this.textures.length; i ++ ) {
9438
9439			const texture = this.textures[ i ];
9440			texture.setValues( values );
9441
9442		}
9443
9444	}
9445
9446	/**
9447	 * The texture representing the default color attachment.
9448	 *
9449	 * @type {Texture}
9450	 */
9451	get texture() {
9452
9453		return this.textures[ 0 ];
9454
9455	}
9456
9457	set texture( value ) {
9458
9459		this.textures[ 0 ] = value;
9460
9461	}
9462
9463	set depthTexture( current ) {
9464
9465		if ( this._depthTexture !== null && this._depthTexture.renderTarget === this ) this._depthTexture.renderTarget = null;
9466		if ( current !== null && current.renderTarget === null ) current.renderTarget = this;
9467
9468		this._depthTexture = current;
9469
9470	}
9471
9472	/**
9473	 * Instead of saving the depth in a renderbuffer, a texture
9474	 * can be used instead which is useful for further processing
9475	 * e.g. in context of post-processing.
9476	 *
9477	 * @type {?DepthTexture}
9478	 * @default null
9479	 */
9480	get depthTexture() {
9481
9482		return this._depthTexture;
9483
9484	}
9485
9486	/**
9487	 * Sets the size of this render target.
9488	 *
9489	 * @param {number} width - The width.
9490	 * @param {number} height - The height.
9491	 * @param {number} [depth=1] - The depth.
9492	 */
9493	setSize( width, height, depth = 1 ) {
9494
9495		if ( this.width !== width || this.height !== height || this.depth !== depth ) {
9496
9497			this.width = width;
9498			this.height = height;
9499			this.depth = depth;
9500
9501			for ( let i = 0, il = this.textures.length; i < il; i ++ ) {
9502
9503				this.textures[ i ].image.width = width;
9504				this.textures[ i ].image.height = height;
9505				this.textures[ i ].image.depth = depth;
9506
9507				if ( this.textures[ i ].isData3DTexture !== true ) { // Fix for #31693
9508
9509					// TODO: Reconsider setting isArrayTexture flag here and in the ctor of Texture.
9510					// Maybe a method `isArrayTexture()` or just a getter could replace a flag since
9511					// both are evaluated on each call?
9512
9513					this.textures[ i ].isArrayTexture = this.textures[ i ].image.depth > 1;
9514
9515				}
9516
9517			}
9518
9519			this.dispose();
9520
9521		}
9522
9523		this.viewport.set( 0, 0, width, height );
9524		this.scissor.set( 0, 0, width, height );
9525
9526	}
9527
9528	/**
9529	 * Returns a new render target with copied values from this instance.
9530	 *
9531	 * @return {RenderTarget} A clone of this instance.
9532	 */
9533	clone() {
9534
9535		return new this.constructor().copy( this );
9536
9537	}
9538
9539	/**
9540	 * Copies the settings of the given render target. This is a structural copy so
9541	 * no resources are shared between render targets after the copy. That includes
9542	 * all MRT textures and the depth texture.
9543	 *
9544	 * @param {RenderTarget} source - The render target to copy.
9545	 * @return {RenderTarget} A reference to this instance.
9546	 */
9547	copy( source ) {
9548
9549		this.width = source.width;
9550		this.height = source.height;
9551		this.depth = source.depth;
9552
9553		this.scissor.copy( source.scissor );
9554		this.scissorTest = source.scissorTest;
9555
9556		this.viewport.copy( source.viewport );
9557
9558		this.textures.length = 0;
9559
9560		for ( let i = 0, il = source.textures.length; i < il; i ++ ) {
9561
9562			this.textures[ i ] = source.textures[ i ].clone();
9563			this.textures[ i ].isRenderTargetTexture = true;
9564			this.textures[ i ].renderTarget = this;
9565
9566			// ensure image object is not shared, see #20328
9567
9568			const image = Object.assign( {}, source.textures[ i ].image );
9569			this.textures[ i ].source = new TextureSource( image );
9570
9571		}
9572
9573		this.depthBuffer = source.depthBuffer;
9574		this.stencilBuffer = source.stencilBuffer;
9575
9576		this.resolveColorBuffer = source.resolveColorBuffer;
9577		this.resolveDepthBuffer = source.resolveDepthBuffer;
9578		this.resolveStencilBuffer = source.resolveStencilBuffer;
9579
9580		this.storeMultisampledColorBuffer = source.storeMultisampledColorBuffer;
9581		this.storeMultisampledDepthBuffer = source.storeMultisampledDepthBuffer;
9582		this.storeMultisampledStencilBuffer = source.storeMultisampledStencilBuffer;
9583
9584		if ( source.depthTexture !== null ) {
9585
9586			if ( source.depthTexture.renderTarget === source ) {
9587
9588				const depthTexture = source.depthTexture.clone();
9589				depthTexture.renderTarget = null;
9590
9591				this.depthTexture = depthTexture;
9592
9593			} else {
9594
9595				this.depthTexture = source.depthTexture;
9596
9597			}
9598
9599		}
9600
9601		this.samples = source.samples;
9602		this.multiview = source.multiview;
9603		this.useArrayDepthTexture = source.useArrayDepthTexture;
9604
9605		return this;
9606
9607	}
9608
9609	/**
9610	 * Frees the GPU-related resources allocated by this instance. Call this
9611	 * method whenever this instance is no longer used in your app.
9612	 *
9613	 * @fires RenderTarget#dispose
9614	 */
9615	dispose() {
9616
9617		this.dispatchEvent( { type: 'dispose' } );
9618
9619	}
9620
9621}
9622
9623/**
9624 * A render target used in context of {@link WebGLRenderer}.
9625 *
9626 * @augments RenderTarget
9627 */
9628class WebGLRenderTarget extends RenderTarget {
9629
9630	/**
9631	 * Constructs a new 3D render target.
9632	 *
9633	 * @param {number} [width=1] - The width of the render target.
9634	 * @param {number} [height=1] - The height of the render target.
9635	 * @param {RenderTarget~Options} [options] - The configuration object.
9636	 */
9637	constructor( width = 1, height = 1, options = {} ) {
9638
9639		super( width, height, options );
9640
9641		/**
9642		 * This flag can be used for type testing.
9643		 *
9644		 * @type {boolean}
9645		 * @readonly
9646		 * @default true
9647		 */
9648		this.isWebGLRenderTarget = true;
9649
9650	}
9651
9652}
9653
9654/**
9655 * Creates an array of textures directly from raw buffer data.
9656 *
9657 * @augments Texture
9658 */
9659class DataArrayTexture extends Texture {
9660
9661	/**
9662	 * Constructs a new data array texture.
9663	 *
9664	 * @param {?TypedArray} [data=null] - The buffer data.
9665	 * @param {number} [width=1] - The width of the texture.
9666	 * @param {number} [height=1] - The height of the texture.
9667	 * @param {number} [depth=1] - The depth of the texture.
9668	 */
9669	constructor( data = null, width = 1, height = 1, depth = 1 ) {
9670
9671		super( null );
9672
9673		/**
9674		 * This flag can be used for type testing.
9675		 *
9676		 * @type {boolean}
9677		 * @readonly
9678		 * @default true
9679		 */
9680		this.isDataArrayTexture = true;
9681
9682		/**
9683		 * The image definition of a data texture.
9684		 *
9685		 * @type {{data:TypedArray,width:number,height:number,depth:number}}
9686		 */
9687		this.image = { data, width, height, depth };
9688
9689		/**
9690		 * How the texture is sampled when a texel covers more than one pixel.
9691		 *
9692		 * Overwritten and set to `NearestFilter` by default.
9693		 *
9694		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9695		 * @default NearestFilter
9696		 */
9697		this.magFilter = NearestFilter;
9698
9699		/**
9700		 * How the texture is sampled when a texel covers less than one pixel.
9701		 *
9702		 * Overwritten and set to `NearestFilter` by default.
9703		 *
9704		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9705		 * @default NearestFilter
9706		 */
9707		this.minFilter = NearestFilter;
9708
9709		/**
9710		 * This defines how the texture is wrapped in the depth and corresponds to
9711		 * *W* in UVW mapping.
9712		 *
9713		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
9714		 * @default ClampToEdgeWrapping
9715		 */
9716		this.wrapR = ClampToEdgeWrapping;
9717
9718		/**
9719		 * Whether to generate mipmaps (if possible) for a texture.
9720		 *
9721		 * Overwritten and set to `false` by default.
9722		 *
9723		 * @type {boolean}
9724		 * @default false
9725		 */
9726		this.generateMipmaps = false;
9727
9728		/**
9729		 * If set to `true`, the texture is flipped along the vertical axis when
9730		 * uploaded to the GPU.
9731		 *
9732		 * Overwritten and set to `false` by default.
9733		 *
9734		 * @type {boolean}
9735		 * @default false
9736		 */
9737		this.flipY = false;
9738
9739		/**
9740		 * Specifies the alignment requirements for the start of each pixel row in memory.
9741		 *
9742		 * Overwritten and set to `1` by default.
9743		 *
9744		 * @type {boolean}
9745		 * @default 1
9746		 */
9747		this.unpackAlignment = 1;
9748
9749		/**
9750		 * A set of all layers which need to be updated in the texture.
9751		 *
9752		 * @type {Set<number>}
9753		 */
9754		this.layerUpdates = new Set();
9755
9756	}
9757
9758	/**
9759	 * Copies the values of the given texture to this instance.
9760	 *
9761	 * @param {DataArrayTexture} source - The texture to copy.
9762	 * @return {DataArrayTexture} A reference to this instance.
9763	 */
9764	copy( source ) {
9765
9766		super.copy( source );
9767
9768		this.wrapR = source.wrapR;
9769
9770		return this;
9771
9772	}
9773
9774	/**
9775	 * Describes that a specific layer of the texture needs to be updated.
9776	 * Normally when {@link Texture#needsUpdate} is set to `true`, the
9777	 * entire data texture array is sent to the GPU. Marking specific
9778	 * layers will only transmit subsets of all mipmaps associated with a
9779	 * specific depth in the array which is often much more performant.
9780	 *
9781	 * @param {number} layerIndex - The layer index that should be updated.
9782	 */
9783	addLayerUpdate( layerIndex ) {
9784
9785		this.layerUpdates.add( layerIndex );
9786
9787	}
9788
9789	/**
9790	 * Resets the layer updates registry.
9791	 */
9792	clearLayerUpdates() {
9793
9794		this.layerUpdates.clear();
9795
9796	}
9797
9798}
9799
9800/**
9801 * An array render target used in context of {@link WebGLRenderer}.
9802 *
9803 * @augments WebGLRenderTarget
9804 */
9805class WebGLArrayRenderTarget extends WebGLRenderTarget {
9806
9807	/**
9808	 * Constructs a new array render target.
9809	 *
9810	 * @param {number} [width=1] - The width of the render target.
9811	 * @param {number} [height=1] - The height of the render target.
9812	 * @param {number} [depth=1] - The height of the render target.
9813	 * @param {RenderTarget~Options} [options] - The configuration object.
9814	 */
9815	constructor( width = 1, height = 1, depth = 1, options = {} ) {
9816
9817		super( width, height, options );
9818
9819		/**
9820		 * This flag can be used for type testing.
9821		 *
9822		 * @type {boolean}
9823		 * @readonly
9824		 * @default true
9825		 */
9826		this.isWebGLArrayRenderTarget = true;
9827
9828		this.depth = depth;
9829
9830		/**
9831		 * Overwritten with a different texture type.
9832		 *
9833		 * @type {DataArrayTexture}
9834		 */
9835		this.texture = new DataArrayTexture( null, width, height, depth );
9836		this._setTextureOptions( options );
9837
9838		this.texture.isRenderTargetTexture = true;
9839
9840	}
9841
9842}
9843
9844/**
9845 * Creates a three-dimensional texture from raw data, with parameters to
9846 * divide it into width, height, and depth.
9847 *
9848 * @augments Texture
9849 */
9850class Data3DTexture extends Texture {
9851
9852	/**
9853	 * Constructs a new data array texture.
9854	 *
9855	 * @param {?TypedArray} [data=null] - The buffer data.
9856	 * @param {number} [width=1] - The width of the texture.
9857	 * @param {number} [height=1] - The height of the texture.
9858	 * @param {number} [depth=1] - The depth of the texture.
9859	 */
9860	constructor( data = null, width = 1, height = 1, depth = 1 ) {
9861
9862		// We're going to add .setXXX() methods for setting properties later.
9863		// Users can still set in Data3DTexture directly.
9864		//
9865		//	const texture = new THREE.Data3DTexture( data, width, height, depth );
9866		// 	texture.anisotropy = 16;
9867		//
9868		// See #14839
9869
9870		super( null );
9871
9872		/**
9873		 * This flag can be used for type testing.
9874		 *
9875		 * @type {boolean}
9876		 * @readonly
9877		 * @default true
9878		 */
9879		this.isData3DTexture = true;
9880
9881		/**
9882		 * The image definition of a data texture.
9883		 *
9884		 * @type {{data:TypedArray,width:number,height:number,depth:number}}
9885		 */
9886		this.image = { data, width, height, depth };
9887
9888		/**
9889		 * How the texture is sampled when a texel covers more than one pixel.
9890		 *
9891		 * Overwritten and set to `NearestFilter` by default.
9892		 *
9893		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9894		 * @default NearestFilter
9895		 */
9896		this.magFilter = NearestFilter;
9897
9898		/**
9899		 * How the texture is sampled when a texel covers less than one pixel.
9900		 *
9901		 * Overwritten and set to `NearestFilter` by default.
9902		 *
9903		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
9904		 * @default NearestFilter
9905		 */
9906		this.minFilter = NearestFilter;
9907
9908		/**
9909		 * This defines how the texture is wrapped in the depth and corresponds to
9910		 * *W* in UVW mapping.
9911		 *
9912		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
9913		 * @default ClampToEdgeWrapping
9914		 */
9915		this.wrapR = ClampToEdgeWrapping;
9916
9917		/**
9918		 * Whether to generate mipmaps (if possible) for a texture.
9919		 *
9920		 * Overwritten and set to `false` by default.
9921		 *
9922		 * @type {boolean}
9923		 * @default false
9924		 */
9925		this.generateMipmaps = false;
9926
9927		/**
9928		 * If set to `true`, the texture is flipped along the vertical axis when
9929		 * uploaded to the GPU.
9930		 *
9931		 * Overwritten and set to `false` by default.
9932		 *
9933		 * @type {boolean}
9934		 * @default false
9935		 */
9936		this.flipY = false;
9937
9938		/**
9939		 * Specifies the alignment requirements for the start of each pixel row in memory.
9940		 *
9941		 * Overwritten and set to `1` by default.
9942		 *
9943		 * @type {boolean}
9944		 * @default 1
9945		 */
9946		this.unpackAlignment = 1;
9947
9948	}
9949
9950	/**
9951	 * Copies the values of the given texture to this instance.
9952	 *
9953	 * @param {Data3DTexture} source - The texture to copy.
9954	 * @return {Data3DTexture} A reference to this instance.
9955	 */
9956	copy( source ) {
9957
9958		super.copy( source );
9959
9960		this.wrapR = source.wrapR;
9961
9962		return this;
9963
9964	}
9965
9966}
9967
9968/**
9969 * A 3D render target used in context of {@link WebGLRenderer}.
9970 *
9971 * @augments WebGLRenderTarget
9972 */
9973class WebGL3DRenderTarget extends WebGLRenderTarget {
9974
9975	/**
9976	 * Constructs a new 3D render target.
9977	 *
9978	 * @param {number} [width=1] - The width of the render target.
9979	 * @param {number} [height=1] - The height of the render target.
9980	 * @param {number} [depth=1] - The height of the render target.
9981	 * @param {RenderTarget~Options} [options] - The configuration object.
9982	 */
9983	constructor( width = 1, height = 1, depth = 1, options = {} ) {
9984
9985		super( width, height, options );
9986
9987		/**
9988		 * This flag can be used for type testing.
9989		 *
9990		 * @type {boolean}
9991		 * @readonly
9992		 * @default true
9993		 */
9994		this.isWebGL3DRenderTarget = true;
9995
9996		this.depth = depth;
9997
9998		/**
9999		 * Overwritten with a different texture type.
10000		 *
10001		 * @type {Data3DTexture}
10002		 */
10003		this.texture = new Data3DTexture( null, width, height, depth );
10004		this._setTextureOptions( options );
10005
10006		this.texture.isRenderTargetTexture = true;
10007
10008	}
10009
10010}
10011
10012/**
10013 * Represents a 4x4 matrix.
10014 *
10015 * The most common use of a 4x4 matrix in 3D computer graphics is as a transformation matrix.
10016 * For an introduction to transformation matrices as used in WebGL, check out [this tutorial](https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices)
10017 *
10018 * This allows a 3D vector representing a point in 3D space to undergo
10019 * transformations such as translation, rotation, shear, scale, reflection,
10020 * orthogonal or perspective projection and so on, by being multiplied by the
10021 * matrix. This is known as `applying` the matrix to the vector.
10022 *
10023 * A Note on Row-Major and Column-Major Ordering:
10024 *
10025 * The constructor and {@link Matrix3#set} method take arguments in
10026 * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order)
10027 * order, while internally they are stored in the {@link Matrix3#elements} array in column-major order.
10028 * This means that calling:
10029 * ```js
10030 * const m = new THREE.Matrix4();
10031 * m.set( 11, 12, 13, 14,
10032 *        21, 22, 23, 24,
10033 *        31, 32, 33, 34,
10034 *        41, 42, 43, 44 );
10035 * ```
10036 * will result in the elements array containing:
10037 * ```js
10038 * m.elements = [ 11, 21, 31, 41,
10039 *                12, 22, 32, 42,
10040 *                13, 23, 33, 43,
10041 *                14, 24, 34, 44 ];
10042 * ```
10043 * and internally all calculations are performed using column-major ordering.
10044 * However, as the actual ordering makes no difference mathematically and
10045 * most people are used to thinking about matrices in row-major order, the
10046 * three.js documentation shows matrices in row-major order. Just bear in
10047 * mind that if you are reading the source code, you'll have to take the
10048 * transpose of any matrices outlined here to make sense of the calculations.
10049 */
10050class Matrix4 {
10051
10052	static {
10053
10054		/**
10055		 * This flag can be used for type testing.
10056		 *
10057		 * @type {boolean}
10058		 * @readonly
10059		 * @default true
10060		 */
10061		Matrix4.prototype.isMatrix4 = true;
10062
10063	}
10064
10065	/**
10066	 * Constructs a new 4x4 matrix. The arguments are supposed to be
10067	 * in row-major order. If no arguments are provided, the constructor
10068	 * initializes the matrix as an identity matrix.
10069	 *
10070	 * @param {number} [n11] - 1-1 matrix element.
10071	 * @param {number} [n12] - 1-2 matrix element.
10072	 * @param {number} [n13] - 1-3 matrix element.
10073	 * @param {number} [n14] - 1-4 matrix element.
10074	 * @param {number} [n21] - 2-1 matrix element.
10075	 * @param {number} [n22] - 2-2 matrix element.
10076	 * @param {number} [n23] - 2-3 matrix element.
10077	 * @param {number} [n24] - 2-4 matrix element.
10078	 * @param {number} [n31] - 3-1 matrix element.
10079	 * @param {number} [n32] - 3-2 matrix element.
10080	 * @param {number} [n33] - 3-3 matrix element.
10081	 * @param {number} [n34] - 3-4 matrix element.
10082	 * @param {number} [n41] - 4-1 matrix element.
10083	 * @param {number} [n42] - 4-2 matrix element.
10084	 * @param {number} [n43] - 4-3 matrix element.
10085	 * @param {number} [n44] - 4-4 matrix element.
10086	 */
10087	constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
10088
10089		/**
10090		 * A column-major list of matrix values.
10091		 *
10092		 * @type {Array<number>}
10093		 */
10094		this.elements = [
10095
10096			1, 0, 0, 0,
10097			0, 1, 0, 0,
10098			0, 0, 1, 0,
10099			0, 0, 0, 1
10100
10101		];
10102
10103		if ( n11 !== undefined ) {
10104
10105			this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 );
10106
10107		}
10108
10109	}
10110
10111	/**
10112	 * Sets the elements of the matrix.The arguments are supposed to be
10113	 * in row-major order.
10114	 *
10115	 * @param {number} [n11] - 1-1 matrix element.
10116	 * @param {number} [n12] - 1-2 matrix element.
10117	 * @param {number} [n13] - 1-3 matrix element.
10118	 * @param {number} [n14] - 1-4 matrix element.
10119	 * @param {number} [n21] - 2-1 matrix element.
10120	 * @param {number} [n22] - 2-2 matrix element.
10121	 * @param {number} [n23] - 2-3 matrix element.
10122	 * @param {number} [n24] - 2-4 matrix element.
10123	 * @param {number} [n31] - 3-1 matrix element.
10124	 * @param {number} [n32] - 3-2 matrix element.
10125	 * @param {number} [n33] - 3-3 matrix element.
10126	 * @param {number} [n34] - 3-4 matrix element.
10127	 * @param {number} [n41] - 4-1 matrix element.
10128	 * @param {number} [n42] - 4-2 matrix element.
10129	 * @param {number} [n43] - 4-3 matrix element.
10130	 * @param {number} [n44] - 4-4 matrix element.
10131	 * @return {Matrix4} A reference to this matrix.
10132	 */
10133	set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
10134
10135		const te = this.elements;
10136
10137		te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
10138		te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
10139		te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
10140		te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
10141
10142		return this;
10143
10144	}
10145
10146	/**
10147	 * Sets this matrix to the 4x4 identity matrix.
10148	 *
10149	 * @return {Matrix4} A reference to this matrix.
10150	 */
10151	identity() {
10152
10153		this.set(
10154
10155			1, 0, 0, 0,
10156			0, 1, 0, 0,
10157			0, 0, 1, 0,
10158			0, 0, 0, 1
10159
10160		);
10161
10162		return this;
10163
10164	}
10165
10166	/**
10167	 * Returns a matrix with copied values from this instance.
10168	 *
10169	 * @return {Matrix4} A clone of this instance.
10170	 */
10171	clone() {
10172
10173		return new Matrix4().fromArray( this.elements );
10174
10175	}
10176
10177	/**
10178	 * Copies the values of the given matrix to this instance.
10179	 *
10180	 * @param {Matrix4} m - The matrix to copy.
10181	 * @return {Matrix4} A reference to this matrix.
10182	 */
10183	copy( m ) {
10184
10185		const te = this.elements;
10186		const me = m.elements;
10187
10188		te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
10189		te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
10190		te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
10191		te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
10192
10193		return this;
10194
10195	}
10196
10197	/**
10198	 * Copies the translation component of the given matrix
10199	 * into this matrix's translation component.
10200	 *
10201	 * @param {Matrix4} m - The matrix to copy the translation component.
10202	 * @return {Matrix4} A reference to this matrix.
10203	 */
10204	copyPosition( m ) {
10205
10206		const te = this.elements, me = m.elements;
10207
10208		te[ 12 ] = me[ 12 ];
10209		te[ 13 ] = me[ 13 ];
10210		te[ 14 ] = me[ 14 ];
10211
10212		return this;
10213
10214	}
10215
10216	/**
10217	 * Set the upper 3x3 elements of this matrix to the values of given 3x3 matrix.
10218	 *
10219	 * @param {Matrix3} m - The 3x3 matrix.
10220	 * @return {Matrix4} A reference to this matrix.
10221	 */
10222	setFromMatrix3( m ) {
10223
10224		const me = m.elements;
10225
10226		this.set(
10227
10228			me[ 0 ], me[ 3 ], me[ 6 ], 0,
10229			me[ 1 ], me[ 4 ], me[ 7 ], 0,
10230			me[ 2 ], me[ 5 ], me[ 8 ], 0,
10231			0, 0, 0, 1
10232
10233		);
10234
10235		return this;
10236
10237	}
10238
10239	/**
10240	 * Extracts the basis vectors of this matrix into the three vectors provided.
10241	 *
10242	 * @param {Vector3} xAxis - The basis's x axis.
10243	 * @param {Vector3} yAxis - The basis's y axis.
10244	 * @param {Vector3} zAxis - The basis's z axis.
10245	 * @return {Matrix4} A reference to this matrix.
10246	 */
10247	extractBasis( xAxis, yAxis, zAxis ) {
10248
10249		if ( this.determinantAffine() === 0 ) {
10250
10251			xAxis.set( 1, 0, 0 );
10252			yAxis.set( 0, 1, 0 );
10253			zAxis.set( 0, 0, 1 );
10254
10255			return this;
10256
10257		}
10258
10259		xAxis.setFromMatrixColumn( this, 0 );
10260		yAxis.setFromMatrixColumn( this, 1 );
10261		zAxis.setFromMatrixColumn( this, 2 );
10262
10263		return this;
10264
10265	}
10266
10267	/**
10268	 * Sets the given basis vectors to this matrix.
10269	 *
10270	 * @param {Vector3} xAxis - The basis's x axis.
10271	 * @param {Vector3} yAxis - The basis's y axis.
10272	 * @param {Vector3} zAxis - The basis's z axis.
10273	 * @return {Matrix4} A reference to this matrix.
10274	 */
10275	makeBasis( xAxis, yAxis, zAxis ) {
10276
10277		this.set(
10278			xAxis.x, yAxis.x, zAxis.x, 0,
10279			xAxis.y, yAxis.y, zAxis.y, 0,
10280			xAxis.z, yAxis.z, zAxis.z, 0,
10281			0, 0, 0, 1
10282		);
10283
10284		return this;
10285
10286	}
10287
10288	/**
10289	 * Extracts the rotation component of the given matrix
10290	 * into this matrix's rotation component.
10291	 *
10292	 * Note: This method does not support reflection matrices.
10293	 *
10294	 * @param {Matrix4} m - The matrix.
10295	 * @return {Matrix4} A reference to this matrix.
10296	 */
10297	extractRotation( m ) {
10298
10299		if ( m.determinantAffine() === 0 ) {
10300
10301			return this.identity();
10302
10303		}
10304
10305		const te = this.elements;
10306		const me = m.elements;
10307
10308		const scaleX = 1 / _v1$7.setFromMatrixColumn( m, 0 ).length();
10309		const scaleY = 1 / _v1$7.setFromMatrixColumn( m, 1 ).length();
10310		const scaleZ = 1 / _v1$7.setFromMatrixColumn( m, 2 ).length();
10311
10312		te[ 0 ] = me[ 0 ] * scaleX;
10313		te[ 1 ] = me[ 1 ] * scaleX;
10314		te[ 2 ] = me[ 2 ] * scaleX;
10315		te[ 3 ] = 0;
10316
10317		te[ 4 ] = me[ 4 ] * scaleY;
10318		te[ 5 ] = me[ 5 ] * scaleY;
10319		te[ 6 ] = me[ 6 ] * scaleY;
10320		te[ 7 ] = 0;
10321
10322		te[ 8 ] = me[ 8 ] * scaleZ;
10323		te[ 9 ] = me[ 9 ] * scaleZ;
10324		te[ 10 ] = me[ 10 ] * scaleZ;
10325		te[ 11 ] = 0;
10326
10327		te[ 12 ] = 0;
10328		te[ 13 ] = 0;
10329		te[ 14 ] = 0;
10330		te[ 15 ] = 1;
10331
10332		return this;
10333
10334	}
10335
10336	/**
10337	 * Sets the rotation component (the upper left 3x3 matrix) of this matrix to
10338	 * the rotation specified by the given Euler angles. The rest of
10339	 * the matrix is set to the identity. Depending on the {@link Euler#order},
10340	 * there are six possible outcomes. See [this page](https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix)
10341	 * for a complete list.
10342	 *
10343	 * @param {Euler} euler - The Euler angles.
10344	 * @return {Matrix4} A reference to this matrix.
10345	 */
10346	makeRotationFromEuler( euler ) {
10347
10348		const te = this.elements;
10349
10350		const x = euler.x, y = euler.y, z = euler.z;
10351		const a = Math.cos( x ), b = Math.sin( x );
10352		const c = Math.cos( y ), d = Math.sin( y );
10353		const e = Math.cos( z ), f = Math.sin( z );
10354
10355		if ( euler.order === 'XYZ' ) {
10356
10357			const ae = a * e, af = a * f, be = b * e, bf = b * f;
10358
10359			te[ 0 ] = c * e;
10360			te[ 4 ] = - c * f;
10361			te[ 8 ] = d;
10362
10363			te[ 1 ] = af + be * d;
10364			te[ 5 ] = ae - bf * d;
10365			te[ 9 ] = - b * c;
10366
10367			te[ 2 ] = bf - ae * d;
10368			te[ 6 ] = be + af * d;
10369			te[ 10 ] = a * c;
10370
10371		} else if ( euler.order === 'YXZ' ) {
10372
10373			const ce = c * e, cf = c * f, de = d * e, df = d * f;
10374
10375			te[ 0 ] = ce + df * b;
10376			te[ 4 ] = de * b - cf;
10377			te[ 8 ] = a * d;
10378
10379			te[ 1 ] = a * f;
10380			te[ 5 ] = a * e;
10381			te[ 9 ] = - b;
10382
10383			te[ 2 ] = cf * b - de;
10384			te[ 6 ] = df + ce * b;
10385			te[ 10 ] = a * c;
10386
10387		} else if ( euler.order === 'ZXY' ) {
10388
10389			const ce = c * e, cf = c * f, de = d * e, df = d * f;
10390
10391			te[ 0 ] = ce - df * b;
10392			te[ 4 ] = - a * f;
10393			te[ 8 ] = de + cf * b;
10394
10395			te[ 1 ] = cf + de * b;
10396			te[ 5 ] = a * e;
10397			te[ 9 ] = df - ce * b;
10398
10399			te[ 2 ] = - a * d;
10400			te[ 6 ] = b;
10401			te[ 10 ] = a * c;
10402
10403		} else if ( euler.order === 'ZYX' ) {
10404
10405			const ae = a * e, af = a * f, be = b * e, bf = b * f;
10406
10407			te[ 0 ] = c * e;
10408			te[ 4 ] = be * d - af;
10409			te[ 8 ] = ae * d + bf;
10410
10411			te[ 1 ] = c * f;
10412			te[ 5 ] = bf * d + ae;
10413			te[ 9 ] = af * d - be;
10414
10415			te[ 2 ] = - d;
10416			te[ 6 ] = b * c;
10417			te[ 10 ] = a * c;
10418
10419		} else if ( euler.order === 'YZX' ) {
10420
10421			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
10422
10423			te[ 0 ] = c * e;
10424			te[ 4 ] = bd - ac * f;
10425			te[ 8 ] = bc * f + ad;
10426
10427			te[ 1 ] = f;
10428			te[ 5 ] = a * e;
10429			te[ 9 ] = - b * e;
10430
10431			te[ 2 ] = - d * e;
10432			te[ 6 ] = ad * f + bc;
10433			te[ 10 ] = ac - bd * f;
10434
10435		} else if ( euler.order === 'XZY' ) {
10436
10437			const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
10438
10439			te[ 0 ] = c * e;
10440			te[ 4 ] = - f;
10441			te[ 8 ] = d * e;
10442
10443			te[ 1 ] = ac * f + bd;
10444			te[ 5 ] = a * e;
10445			te[ 9 ] = ad * f - bc;
10446
10447			te[ 2 ] = bc * f - ad;
10448			te[ 6 ] = b * e;
10449			te[ 10 ] = bd * f + ac;
10450
10451		}
10452
10453		// bottom row
10454		te[ 3 ] = 0;
10455		te[ 7 ] = 0;
10456		te[ 11 ] = 0;
10457
10458		// last column
10459		te[ 12 ] = 0;
10460		te[ 13 ] = 0;
10461		te[ 14 ] = 0;
10462		te[ 15 ] = 1;
10463
10464		return this;
10465
10466	}
10467
10468	/**
10469	 * Sets the rotation component of this matrix to the rotation specified by
10470	 * the given Quaternion as outlined [here](https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion)
10471	 * The rest of the matrix is set to the identity.
10472	 *
10473	 * @param {Quaternion} q - The Quaternion.
10474	 * @return {Matrix4} A reference to this matrix.
10475	 */
10476	makeRotationFromQuaternion( q ) {
10477
10478		return this.compose( _zero, q, _one );
10479
10480	}
10481
10482	/**
10483	 * Sets the rotation component of the transformation matrix, looking from `eye` towards
10484	 * `target`, and oriented by the up-direction.
10485	 *
10486	 * @param {Vector3} eye - The eye vector.
10487	 * @param {Vector3} target - The target vector.
10488	 * @param {Vector3} up - The up vector.
10489	 * @return {Matrix4} A reference to this matrix.
10490	 */
10491	lookAt( eye, target, up ) {
10492
10493		const te = this.elements;
10494
10495		_z.subVectors( eye, target );
10496
10497		if ( _z.lengthSq() === 0 ) {
10498
10499			// eye and target are in the same position
10500
10501			_z.z = 1;
10502
10503		}
10504
10505		_z.normalize();
10506		_x.crossVectors( up, _z );
10507
10508		if ( _x.lengthSq() === 0 ) {
10509
10510			// up and z are parallel
10511
10512			if ( Math.abs( up.z ) === 1 ) {
10513
10514				_z.x += 0.0001;
10515
10516			} else {
10517
10518				_z.z += 0.0001;
10519
10520			}
10521
10522			_z.normalize();
10523			_x.crossVectors( up, _z );
10524
10525		}
10526
10527		_x.normalize();
10528		_y.crossVectors( _z, _x );
10529
10530		te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;
10531		te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;
10532		te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;
10533
10534		return this;
10535
10536	}
10537
10538	/**
10539	 * Post-multiplies this matrix by the given 4x4 matrix.
10540	 *
10541	 * @param {Matrix4} m - The matrix to multiply with.
10542	 * @return {Matrix4} A reference to this matrix.
10543	 */
10544	multiply( m ) {
10545
10546		return this.multiplyMatrices( this, m );
10547
10548	}
10549
10550	/**
10551	 * Pre-multiplies this matrix by the given 4x4 matrix.
10552	 *
10553	 * @param {Matrix4} m - The matrix to multiply with.
10554	 * @return {Matrix4} A reference to this matrix.
10555	 */
10556	premultiply( m ) {
10557
10558		return this.multiplyMatrices( m, this );
10559
10560	}
10561
10562	/**
10563	 * Multiples the given 4x4 matrices and stores the result
10564	 * in this matrix.
10565	 *
10566	 * @param {Matrix4} a - The first matrix.
10567	 * @param {Matrix4} b - The second matrix.
10568	 * @return {Matrix4} A reference to this matrix.
10569	 */
10570	multiplyMatrices( a, b ) {
10571
10572		const ae = a.elements;
10573		const be = b.elements;
10574		const te = this.elements;
10575
10576		const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
10577		const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
10578		const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
10579		const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
10580
10581		const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
10582		const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
10583		const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
10584		const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
10585
10586		te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
10587		te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
10588		te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
10589		te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
10590
10591		te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
10592		te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
10593		te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
10594		te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
10595
10596		te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
10597		te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
10598		te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
10599		te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
10600
10601		te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
10602		te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
10603		te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
10604		te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
10605
10606		return this;
10607
10608	}
10609
10610	/**
10611	 * Multiplies every component of the matrix by the given scalar.
10612	 *
10613	 * @param {number} s - The scalar.
10614	 * @return {Matrix4} A reference to this matrix.
10615	 */
10616	multiplyScalar( s ) {
10617
10618		const te = this.elements;
10619
10620		te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
10621		te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
10622		te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
10623		te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
10624
10625		return this;
10626
10627	}
10628
10629	/**
10630	 * Computes and returns the determinant of this matrix.
10631	 *
10632	 * @return {number} The determinant.
10633	 */
10634	determinant() {
10635
10636		const te = this.elements;
10637
10638		const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
10639		const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
10640		const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
10641		const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
10642
10643		const t11 = n23 * n34 - n24 * n33;
10644		const t12 = n22 * n34 - n24 * n32;
10645		const t13 = n22 * n33 - n23 * n32;
10646
10647		const t21 = n21 * n34 - n24 * n31;
10648		const t22 = n21 * n33 - n23 * n31;
10649		const t23 = n21 * n32 - n22 * n31;
10650
10651		return n11 * ( n42 * t11 - n43 * t12 + n44 * t13 ) -
10652			n12 * ( n41 * t11 - n43 * t21 + n44 * t22 ) +
10653			n13 * ( n41 * t12 - n42 * t21 + n44 * t23 ) -
10654			n14 * ( n41 * t13 - n42 * t22 + n43 * t23 );
10655
10656	}
10657
10658	/**
10659	 * Computes and returns the determinant of the 4x4 matrix, but assumes the
10660	 * matrix is affine, saving some computations.
10661	 *
10662	 * For affine matrices (like an object's world matrix), this value equals the
10663	 * full 4x4 {@link Matrix4#determinant} but is cheaper to compute.
10664	 *
10665	 * Assumes the bottom row is [0, 0, 0, 1].
10666	 *
10667	 * @return {number} The determinant of the matrix.
10668	 */
10669	determinantAffine() {
10670
10671		const te = this.elements;
10672
10673		const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ];
10674		const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ];
10675		const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ];
10676
10677		return n11 * ( n22 * n33 - n23 * n32 ) -
10678			n12 * ( n21 * n33 - n23 * n31 ) +
10679			n13 * ( n21 * n32 - n22 * n31 );
10680
10681	}
10682
10683	/**
10684	 * Transposes this matrix in place.
10685	 *
10686	 * @return {Matrix4} A reference to this matrix.
10687	 */
10688	transpose() {
10689
10690		const te = this.elements;
10691		let tmp;
10692
10693		tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
10694		tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
10695		tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
10696
10697		tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
10698		tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
10699		tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
10700
10701		return this;
10702
10703	}
10704
10705	/**
10706	 * Sets the position component for this matrix from the given vector,
10707	 * without affecting the rest of the matrix.
10708	 *
10709	 * @param {number|Vector3} x - The x component of the vector or alternatively the vector object.
10710	 * @param {number} y - The y component of the vector.
10711	 * @param {number} z - The z component of the vector.
10712	 * @return {Matrix4} A reference to this matrix.
10713	 */
10714	setPosition( x, y, z ) {
10715
10716		const te = this.elements;
10717
10718		if ( x.isVector3 ) {
10719
10720			te[ 12 ] = x.x;
10721			te[ 13 ] = x.y;
10722			te[ 14 ] = x.z;
10723
10724		} else {
10725
10726			te[ 12 ] = x;
10727			te[ 13 ] = y;
10728			te[ 14 ] = z;
10729
10730		}
10731
10732		return this;
10733
10734	}
10735
10736	/**
10737	 * Inverts this matrix, using the [analytic method](https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution).
10738	 * You can not invert with a determinant of zero. If you attempt this, the method produces
10739	 * a zero matrix instead.
10740	 *
10741	 * @return {Matrix4} A reference to this matrix.
10742	 */
10743	invert() {
10744
10745		// based on https://github.com/toji/gl-matrix
10746		const te = this.elements,
10747
10748			n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ],
10749			n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ],
10750			n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ],
10751			n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ],
10752
10753			t1 = n11 * n22 - n21 * n12,
10754			t2 = n11 * n32 - n31 * n12,
10755			t3 = n11 * n42 - n41 * n12,
10756			t4 = n21 * n32 - n31 * n22,
10757			t5 = n21 * n42 - n41 * n22,
10758			t6 = n31 * n42 - n41 * n32,
10759			t7 = n13 * n24 - n23 * n14,
10760			t8 = n13 * n34 - n33 * n14,
10761			t9 = n13 * n44 - n43 * n14,
10762			t10 = n23 * n34 - n33 * n24,
10763			t11 = n23 * n44 - n43 * n24,
10764			t12 = n33 * n44 - n43 * n34;
10765
10766		const det = t1 * t12 - t2 * t11 + t3 * t10 + t4 * t9 - t5 * t8 + t6 * t7;
10767
10768		if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
10769
10770		const detInv = 1 / det;
10771
10772		te[ 0 ] = ( n22 * t12 - n32 * t11 + n42 * t10 ) * detInv;
10773		te[ 1 ] = ( n31 * t11 - n21 * t12 - n41 * t10 ) * detInv;
10774		te[ 2 ] = ( n24 * t6 - n34 * t5 + n44 * t4 ) * detInv;
10775		te[ 3 ] = ( n33 * t5 - n23 * t6 - n43 * t4 ) * detInv;
10776
10777		te[ 4 ] = ( n32 * t9 - n12 * t12 - n42 * t8 ) * detInv;
10778		te[ 5 ] = ( n11 * t12 - n31 * t9 + n41 * t8 ) * detInv;
10779		te[ 6 ] = ( n34 * t3 - n14 * t6 - n44 * t2 ) * detInv;
10780		te[ 7 ] = ( n13 * t6 - n33 * t3 + n43 * t2 ) * detInv;
10781
10782		te[ 8 ] = ( n12 * t11 - n22 * t9 + n42 * t7 ) * detInv;
10783		te[ 9 ] = ( n21 * t9 - n11 * t11 - n41 * t7 ) * detInv;
10784		te[ 10 ] = ( n14 * t5 - n24 * t3 + n44 * t1 ) * detInv;
10785		te[ 11 ] = ( n23 * t3 - n13 * t5 - n43 * t1 ) * detInv;
10786
10787		te[ 12 ] = ( n22 * t8 - n12 * t10 - n32 * t7 ) * detInv;
10788		te[ 13 ] = ( n11 * t10 - n21 * t8 + n31 * t7 ) * detInv;
10789		te[ 14 ] = ( n24 * t2 - n14 * t4 - n34 * t1 ) * detInv;
10790		te[ 15 ] = ( n13 * t4 - n23 * t2 + n33 * t1 ) * detInv;
10791
10792		return this;
10793
10794	}
10795
10796	/**
10797	 * Scales each of the first three columns of this matrix by the corresponding component of the given vector.
10798	 *
10799	 * @param {Vector3} v - The scale vector.
10800	 * @return {Matrix4} A reference to this matrix.
10801	 */
10802	scale( v ) {
10803
10804		const te = this.elements;
10805		const x = v.x, y = v.y, z = v.z;
10806
10807		te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
10808		te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
10809		te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
10810		te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
10811
10812		return this;
10813
10814	}
10815
10816	/**
10817	 * Gets the maximum scale value of the three axes.
10818	 *
10819	 * @return {number} The maximum scale.
10820	 */
10821	getMaxScaleOnAxis() {
10822
10823		const te = this.elements;
10824
10825		const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
10826		const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
10827		const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
10828
10829		return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
10830
10831	}
10832
10833	/**
10834	 * Sets this matrix as a translation transform from the given vector.
10835	 *
10836	 * @param {number|Vector3} x - The amount to translate in the X axis or alternatively a translation vector.
10837	 * @param {number} y - The amount to translate in the Y axis.
10838	 * @param {number} z - The amount to translate in the z axis.
10839	 * @return {Matrix4} A reference to this matrix.
10840	 */
10841	makeTranslation( x, y, z ) {
10842
10843		if ( x.isVector3 ) {
10844
10845			this.set(
10846
10847				1, 0, 0, x.x,
10848				0, 1, 0, x.y,
10849				0, 0, 1, x.z,
10850				0, 0, 0, 1
10851
10852			);
10853
10854		} else {
10855
10856			this.set(
10857
10858				1, 0, 0, x,
10859				0, 1, 0, y,
10860				0, 0, 1, z,
10861				0, 0, 0, 1
10862
10863			);
10864
10865		}
10866
10867		return this;
10868
10869	}
10870
10871	/**
10872	 * Sets this matrix as a rotational transformation around the X axis by
10873	 * the given angle.
10874	 *
10875	 * @param {number} theta - The rotation in radians.
10876	 * @return {Matrix4} A reference to this matrix.
10877	 */
10878	makeRotationX( theta ) {
10879
10880		const c = Math.cos( theta ), s = Math.sin( theta );
10881
10882		this.set(
10883
10884			1, 0, 0, 0,
10885			0, c, - s, 0,
10886			0, s, c, 0,
10887			0, 0, 0, 1
10888
10889		);
10890
10891		return this;
10892
10893	}
10894
10895	/**
10896	 * Sets this matrix as a rotational transformation around the Y axis by
10897	 * the given angle.
10898	 *
10899	 * @param {number} theta - The rotation in radians.
10900	 * @return {Matrix4} A reference to this matrix.
10901	 */
10902	makeRotationY( theta ) {
10903
10904		const c = Math.cos( theta ), s = Math.sin( theta );
10905
10906		this.set(
10907
10908			 c, 0, s, 0,
10909			 0, 1, 0, 0,
10910			- s, 0, c, 0,
10911			 0, 0, 0, 1
10912
10913		);
10914
10915		return this;
10916
10917	}
10918
10919	/**
10920	 * Sets this matrix as a rotational transformation around the Z axis by
10921	 * the given angle.
10922	 *
10923	 * @param {number} theta - The rotation in radians.
10924	 * @return {Matrix4} A reference to this matrix.
10925	 */
10926	makeRotationZ( theta ) {
10927
10928		const c = Math.cos( theta ), s = Math.sin( theta );
10929
10930		this.set(
10931
10932			c, - s, 0, 0,
10933			s, c, 0, 0,
10934			0, 0, 1, 0,
10935			0, 0, 0, 1
10936
10937		);
10938
10939		return this;
10940
10941	}
10942
10943	/**
10944	 * Sets this matrix as a rotational transformation around the given axis by
10945	 * the given angle.
10946	 *
10947	 * @param {Vector3} axis - The normalized rotation axis.
10948	 * @param {number} angle - The rotation in radians.
10949	 * @return {Matrix4} A reference to this matrix.
10950	 */
10951	makeRotationAxis( axis, angle ) {
10952
10953		const c = Math.cos( angle );
10954		const s = Math.sin( angle );
10955		const t = 1 - c;
10956		const x = axis.x, y = axis.y, z = axis.z;
10957		const tx = t * x, ty = t * y;
10958
10959		this.set(
10960
10961			tx * x + c, tx * y - s * z, tx * z + s * y, 0,
10962			tx * y + s * z, ty * y + c, ty * z - s * x, 0,
10963			tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
10964			0, 0, 0, 1
10965
10966		);
10967
10968		return this;
10969
10970	}
10971
10972	/**
10973	 * Sets this matrix as a scale transformation.
10974	 *
10975	 * @param {number} x - The amount to scale in the X axis.
10976	 * @param {number} y - The amount to scale in the Y axis.
10977	 * @param {number} z - The amount to scale in the Z axis.
10978	 * @return {Matrix4} A reference to this matrix.
10979	 */
10980	makeScale( x, y, z ) {
10981
10982		this.set(
10983
10984			x, 0, 0, 0,
10985			0, y, 0, 0,
10986			0, 0, z, 0,
10987			0, 0, 0, 1
10988
10989		);
10990
10991		return this;
10992
10993	}
10994
10995	/**
10996	 * Sets this matrix as a shear transformation.
10997	 *
10998	 * @param {number} xy - The amount to shear X by Y.
10999	 * @param {number} xz - The amount to shear X by Z.
11000	 * @param {number} yx - The amount to shear Y by X.
11001	 * @param {number} yz - The amount to shear Y by Z.
11002	 * @param {number} zx - The amount to shear Z by X.
11003	 * @param {number} zy - The amount to shear Z by Y.
11004	 * @return {Matrix4} A reference to this matrix.
11005	 */
11006	makeShear( xy, xz, yx, yz, zx, zy ) {
11007
11008		this.set(
11009
11010			1, yx, zx, 0,
11011			xy, 1, zy, 0,
11012			xz, yz, 1, 0,
11013			0, 0, 0, 1
11014
11015		);
11016
11017		return this;
11018
11019	}
11020
11021	/**
11022	 * Sets this matrix to the transformation composed of the given position,
11023	 * rotation (Quaternion) and scale.
11024	 *
11025	 * @param {Vector3} position - The position vector.
11026	 * @param {Quaternion} quaternion - The rotation as a Quaternion.
11027	 * @param {Vector3} scale - The scale vector.
11028	 * @return {Matrix4} A reference to this matrix.
11029	 */
11030	compose( position, quaternion, scale ) {
11031
11032		const te = this.elements;
11033
11034		const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
11035		const x2 = x + x,	y2 = y + y, z2 = z + z;
11036		const xx = x * x2, xy = x * y2, xz = x * z2;
11037		const yy = y * y2, yz = y * z2, zz = z * z2;
11038		const wx = w * x2, wy = w * y2, wz = w * z2;
11039
11040		const sx = scale.x, sy = scale.y, sz = scale.z;
11041
11042		te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
11043		te[ 1 ] = ( xy + wz ) * sx;
11044		te[ 2 ] = ( xz - wy ) * sx;
11045		te[ 3 ] = 0;
11046
11047		te[ 4 ] = ( xy - wz ) * sy;
11048		te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
11049		te[ 6 ] = ( yz + wx ) * sy;
11050		te[ 7 ] = 0;
11051
11052		te[ 8 ] = ( xz + wy ) * sz;
11053		te[ 9 ] = ( yz - wx ) * sz;
11054		te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
11055		te[ 11 ] = 0;
11056
11057		te[ 12 ] = position.x;
11058		te[ 13 ] = position.y;
11059		te[ 14 ] = position.z;
11060		te[ 15 ] = 1;
11061
11062		return this;
11063
11064	}
11065
11066	/**
11067	 * Decomposes this matrix into its position, rotation and scale components
11068	 * and provides the result in the given objects.
11069	 *
11070	 * Note: Not all matrices are decomposable in this way. For example, if an
11071	 * object has a non-uniformly scaled parent, then the object's world matrix
11072	 * may not be decomposable, and this method may not be appropriate.
11073	 *
11074	 * @param {Vector3} position - The position vector.
11075	 * @param {Quaternion} quaternion - The rotation as a Quaternion.
11076	 * @param {Vector3} scale - The scale vector.
11077	 * @return {Matrix4} A reference to this matrix.
11078	 */
11079	decompose( position, quaternion, scale ) {
11080
11081		const te = this.elements;
11082
11083		position.x = te[ 12 ];
11084		position.y = te[ 13 ];
11085		position.z = te[ 14 ];
11086
11087		const det = this.determinantAffine();
11088
11089		if ( det === 0 ) {
11090
11091			scale.set( 1, 1, 1 );
11092			quaternion.identity();
11093
11094			return this;
11095
11096		}
11097
11098		let sx = _v1$7.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
11099		const sy = _v1$7.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
11100		const sz = _v1$7.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
11101
11102		// if determinant is negative, we need to invert one scale
11103		if ( det < 0 ) sx = - sx;
11104
11105		// scale the rotation part
11106		_m1$2.copy( this );
11107
11108		const invSX = 1 / sx;
11109		const invSY = 1 / sy;
11110		const invSZ = 1 / sz;
11111
11112		_m1$2.elements[ 0 ] *= invSX;
11113		_m1$2.elements[ 1 ] *= invSX;
11114		_m1$2.elements[ 2 ] *= invSX;
11115
11116		_m1$2.elements[ 4 ] *= invSY;
11117		_m1$2.elements[ 5 ] *= invSY;
11118		_m1$2.elements[ 6 ] *= invSY;
11119
11120		_m1$2.elements[ 8 ] *= invSZ;
11121		_m1$2.elements[ 9 ] *= invSZ;
11122		_m1$2.elements[ 10 ] *= invSZ;
11123
11124		quaternion.setFromRotationMatrix( _m1$2 );
11125
11126		scale.x = sx;
11127		scale.y = sy;
11128		scale.z = sz;
11129
11130		return this;
11131
11132	}
11133
11134	/**
11135	 * Creates a perspective projection matrix. This is used internally by
11136	 * {@link PerspectiveCamera#updateProjectionMatrix}.
11137
11138	 * @param {number} left - Left boundary of the viewing frustum at the near plane.
11139	 * @param {number} right - Right boundary of the viewing frustum at the near plane.
11140	 * @param {number} top - Top boundary of the viewing frustum at the near plane.
11141	 * @param {number} bottom - Bottom boundary of the viewing frustum at the near plane.
11142	 * @param {number} near - The distance from the camera to the near plane.
11143	 * @param {number} far - The distance from the camera to the far plane.
11144	 * @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} [coordinateSystem=WebGLCoordinateSystem] - The coordinate system.
11145	 * @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
11146	 * @return {Matrix4} A reference to this matrix.
11147	 */
11148	makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem, reversedDepth = false ) {
11149
11150		const te = this.elements;
11151
11152		const x = 2 * near / ( right - left );
11153		const y = 2 * near / ( top - bottom );
11154
11155		const a = ( right + left ) / ( right - left );
11156		const b = ( top + bottom ) / ( top - bottom );
11157
11158		let c, d;
11159
11160		if ( reversedDepth ) {
11161
11162			c = near / ( far - near );
11163			d = ( far * near ) / ( far - near );
11164
11165		} else {
11166
11167			if ( coordinateSystem === WebGLCoordinateSystem ) {
11168
11169				c = - ( far + near ) / ( far - near );
11170				d = ( -2 * far * near ) / ( far - near );
11171
11172			} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
11173
11174				c = - far / ( far - near );
11175				d = ( - far * near ) / ( far - near );
11176
11177			} else {
11178
11179				throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
11180
11181			}
11182
11183		}
11184
11185		te[ 0 ] = x;	te[ 4 ] = 0;	te[ 8 ] = a; 	te[ 12 ] = 0;
11186		te[ 1 ] = 0;	te[ 5 ] = y;	te[ 9 ] = b; 	te[ 13 ] = 0;
11187		te[ 2 ] = 0;	te[ 6 ] = 0;	te[ 10 ] = c; 	te[ 14 ] = d;
11188		te[ 3 ] = 0;	te[ 7 ] = 0;	te[ 11 ] = -1;	te[ 15 ] = 0;
11189
11190		return this;
11191
11192	}
11193
11194	/**
11195	 * Creates a orthographic projection matrix. This is used internally by
11196	 * {@link OrthographicCamera#updateProjectionMatrix}.
11197
11198	 * @param {number} left - Left boundary of the viewing frustum at the near plane.
11199	 * @param {number} right - Right boundary of the viewing frustum at the near plane.
11200	 * @param {number} top - Top boundary of the viewing frustum at the near plane.
11201	 * @param {number} bottom - Bottom boundary of the viewing frustum at the near plane.
11202	 * @param {number} near - The distance from the camera to the near plane.
11203	 * @param {number} far - The distance from the camera to the far plane.
11204	 * @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} [coordinateSystem=WebGLCoordinateSystem] - The coordinate system.
11205	 * @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
11206	 * @return {Matrix4} A reference to this matrix.
11207	 */
11208	makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem, reversedDepth = false ) {
11209
11210		const te = this.elements;
11211
11212		const x = 2 / ( right - left );
11213		const y = 2 / ( top - bottom );
11214
11215		const a = - ( right + left ) / ( right - left );
11216		const b = - ( top + bottom ) / ( top - bottom );
11217
11218		let c, d;
11219
11220		if ( reversedDepth ) {
11221
11222			c = 1 / ( far - near );
11223			d = far / ( far - near );
11224
11225		} else {
11226
11227			if ( coordinateSystem === WebGLCoordinateSystem ) {
11228
11229				c = -2 / ( far - near );
11230				d = - ( far + near ) / ( far - near );
11231
11232			} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
11233
11234				c = -1 / ( far - near );
11235				d = - near / ( far - near );
11236
11237			} else {
11238
11239				throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );
11240
11241			}
11242
11243		}
11244
11245		te[ 0 ] = x;		te[ 4 ] = 0;		te[ 8 ] = 0; 		te[ 12 ] = a;
11246		te[ 1 ] = 0; 		te[ 5 ] = y;		te[ 9 ] = 0; 		te[ 13 ] = b;
11247		te[ 2 ] = 0; 		te[ 6 ] = 0;		te[ 10 ] = c;		te[ 14 ] = d;
11248		te[ 3 ] = 0; 		te[ 7 ] = 0;		te[ 11 ] = 0;		te[ 15 ] = 1;
11249
11250		return this;
11251
11252	}
11253
11254	/**
11255	 * Returns `true` if this matrix is equal with the given one.
11256	 *
11257	 * @param {Matrix4} matrix - The matrix to test for equality.
11258	 * @return {boolean} Whether this matrix is equal with the given one.
11259	 */
11260	equals( matrix ) {
11261
11262		const te = this.elements;
11263		const me = matrix.elements;
11264
11265		for ( let i = 0; i < 16; i ++ ) {
11266
11267			if ( te[ i ] !== me[ i ] ) return false;
11268
11269		}
11270
11271		return true;
11272
11273	}
11274
11275	/**
11276	 * Sets the elements of the matrix from the given array.
11277	 *
11278	 * @param {Array<number>} array - The matrix elements in column-major order.
11279	 * @param {number} [offset=0] - Index of the first element in the array.
11280	 * @return {Matrix4} A reference to this matrix.
11281	 */
11282	fromArray( array, offset = 0 ) {
11283
11284		for ( let i = 0; i < 16; i ++ ) {
11285
11286			this.elements[ i ] = array[ i + offset ];
11287
11288		}
11289
11290		return this;
11291
11292	}
11293
11294	/**
11295	 * Writes the elements of this matrix to the given array. If no array is provided,
11296	 * the method returns a new instance.
11297	 *
11298	 * @param {Array<number>} [array=[]] - The target array holding the matrix elements in column-major order.
11299	 * @param {number} [offset=0] - Index of the first element in the array.
11300	 * @return {Array<number>} The matrix elements in column-major order.
11301	 */
11302	toArray( array = [], offset = 0 ) {
11303
11304		const te = this.elements;
11305
11306		array[ offset ] = te[ 0 ];
11307		array[ offset + 1 ] = te[ 1 ];
11308		array[ offset + 2 ] = te[ 2 ];
11309		array[ offset + 3 ] = te[ 3 ];
11310
11311		array[ offset + 4 ] = te[ 4 ];
11312		array[ offset + 5 ] = te[ 5 ];
11313		array[ offset + 6 ] = te[ 6 ];
11314		array[ offset + 7 ] = te[ 7 ];
11315
11316		array[ offset + 8 ] = te[ 8 ];
11317		array[ offset + 9 ] = te[ 9 ];
11318		array[ offset + 10 ] = te[ 10 ];
11319		array[ offset + 11 ] = te[ 11 ];
11320
11321		array[ offset + 12 ] = te[ 12 ];
11322		array[ offset + 13 ] = te[ 13 ];
11323		array[ offset + 14 ] = te[ 14 ];
11324		array[ offset + 15 ] = te[ 15 ];
11325
11326		return array;
11327
11328	}
11329
11330}
11331
11332const _v1$7 = /*@__PURE__*/ new Vector3();
11333const _m1$2 = /*@__PURE__*/ new Matrix4();
11334const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 );
11335const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 );
11336const _x = /*@__PURE__*/ new Vector3();
11337const _y = /*@__PURE__*/ new Vector3();
11338const _z = /*@__PURE__*/ new Vector3();
11339
11340const _matrix$2 = /*@__PURE__*/ new Matrix4();
11341const _quaternion$4 = /*@__PURE__*/ new Quaternion();
11342
11343/**
11344 * A class representing Euler angles.
11345 *
11346 * Euler angles describe a rotational transformation by rotating an object on
11347 * its various axes in specified amounts per axis, and a specified axis
11348 * order.
11349 *
11350 * Iterating through an instance will yield its components (x, y, z,
11351 * order) in the corresponding order.
11352 *
11353 * ```js
11354 * const a = new THREE.Euler( 0, 1, 1.57, 'XYZ' );
11355 * const b = new THREE.Vector3( 1, 0, 1 );
11356 * b.applyEuler(a);
11357 * ```
11358 */
11359class Euler {
11360
11361	/**
11362	 * Constructs a new euler instance.
11363	 *
11364	 * @param {number} [x=0] - The angle of the x axis in radians.
11365	 * @param {number} [y=0] - The angle of the y axis in radians.
11366	 * @param {number} [z=0] - The angle of the z axis in radians.
11367	 * @param {string} [order=Euler.DEFAULT_ORDER] - A string representing the order that the rotations are applied.
11368	 */
11369	constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) {
11370
11371		/**
11372		 * This flag can be used for type testing.
11373		 *
11374		 * @type {boolean}
11375		 * @readonly
11376		 * @default true
11377		 */
11378		this.isEuler = true;
11379
11380		this._x = x;
11381		this._y = y;
11382		this._z = z;
11383		this._order = order;
11384
11385	}
11386
11387	/**
11388	 * The angle of the x axis in radians.
11389	 *
11390	 * @type {number}
11391	 * @default 0
11392	 */
11393	get x() {
11394
11395		return this._x;
11396
11397	}
11398
11399	set x( value ) {
11400
11401		this._x = value;
11402		this._onChangeCallback();
11403
11404	}
11405
11406	/**
11407	 * The angle of the y axis in radians.
11408	 *
11409	 * @type {number}
11410	 * @default 0
11411	 */
11412	get y() {
11413
11414		return this._y;
11415
11416	}
11417
11418	set y( value ) {
11419
11420		this._y = value;
11421		this._onChangeCallback();
11422
11423	}
11424
11425	/**
11426	 * The angle of the z axis in radians.
11427	 *
11428	 * @type {number}
11429	 * @default 0
11430	 */
11431	get z() {
11432
11433		return this._z;
11434
11435	}
11436
11437	set z( value ) {
11438
11439		this._z = value;
11440		this._onChangeCallback();
11441
11442	}
11443
11444	/**
11445	 * A string representing the order that the rotations are applied.
11446	 *
11447	 * @type {string}
11448	 * @default 'XYZ'
11449	 */
11450	get order() {
11451
11452		return this._order;
11453
11454	}
11455
11456	set order( value ) {
11457
11458		this._order = value;
11459		this._onChangeCallback();
11460
11461	}
11462
11463	/**
11464	 * Sets the Euler components.
11465	 *
11466	 * @param {number} x - The angle of the x axis in radians.
11467	 * @param {number} y - The angle of the y axis in radians.
11468	 * @param {number} z - The angle of the z axis in radians.
11469	 * @param {string} [order] - A string representing the order that the rotations are applied.
11470	 * @return {Euler} A reference to this Euler instance.
11471	 */
11472	set( x, y, z, order = this._order ) {
11473
11474		this._x = x;
11475		this._y = y;
11476		this._z = z;
11477		this._order = order;
11478
11479		this._onChangeCallback();
11480
11481		return this;
11482
11483	}
11484
11485	/**
11486	 * Returns a new Euler instance with copied values from this instance.
11487	 *
11488	 * @return {Euler} A clone of this instance.
11489	 */
11490	clone() {
11491
11492		return new this.constructor( this._x, this._y, this._z, this._order );
11493
11494	}
11495
11496	/**
11497	 * Copies the values of the given Euler instance to this instance.
11498	 *
11499	 * @param {Euler} euler - The Euler instance to copy.
11500	 * @return {Euler} A reference to this Euler instance.
11501	 */
11502	copy( euler ) {
11503
11504		this._x = euler._x;
11505		this._y = euler._y;
11506		this._z = euler._z;
11507		this._order = euler._order;
11508
11509		this._onChangeCallback();
11510
11511		return this;
11512
11513	}
11514
11515	/**
11516	 * Sets the angles of this Euler instance from a pure rotation matrix.
11517	 *
11518	 * @param {Matrix4} m - A 4x4 matrix of which the upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled).
11519	 * @param {string} [order] - A string representing the order that the rotations are applied.
11520	 * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
11521	 * @return {Euler} A reference to this Euler instance.
11522	 */
11523	setFromRotationMatrix( m, order = this._order, update = true ) {
11524
11525		const te = m.elements;
11526		const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
11527		const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
11528		const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
11529
11530		switch ( order ) {
11531
11532			case 'XYZ':
11533
11534				this._y = Math.asin( clamp( m13, -1, 1 ) );
11535
11536				if ( Math.abs( m13 ) < 0.9999999 ) {
11537
11538					this._x = Math.atan2( - m23, m33 );
11539					this._z = Math.atan2( - m12, m11 );
11540
11541				} else {
11542
11543					this._x = Math.atan2( m32, m22 );
11544					this._z = 0;
11545
11546				}
11547
11548				break;
11549
11550			case 'YXZ':
11551
11552				this._x = Math.asin( - clamp( m23, -1, 1 ) );
11553
11554				if ( Math.abs( m23 ) < 0.9999999 ) {
11555
11556					this._y = Math.atan2( m13, m33 );
11557					this._z = Math.atan2( m21, m22 );
11558
11559				} else {
11560
11561					this._y = Math.atan2( - m31, m11 );
11562					this._z = 0;
11563
11564				}
11565
11566				break;
11567
11568			case 'ZXY':
11569
11570				this._x = Math.asin( clamp( m32, -1, 1 ) );
11571
11572				if ( Math.abs( m32 ) < 0.9999999 ) {
11573
11574					this._y = Math.atan2( - m31, m33 );
11575					this._z = Math.atan2( - m12, m22 );
11576
11577				} else {
11578
11579					this._y = 0;
11580					this._z = Math.atan2( m21, m11 );
11581
11582				}
11583
11584				break;
11585
11586			case 'ZYX':
11587
11588				this._y = Math.asin( - clamp( m31, -1, 1 ) );
11589
11590				if ( Math.abs( m31 ) < 0.9999999 ) {
11591
11592					this._x = Math.atan2( m32, m33 );
11593					this._z = Math.atan2( m21, m11 );
11594
11595				} else {
11596
11597					this._x = 0;
11598					this._z = Math.atan2( - m12, m22 );
11599
11600				}
11601
11602				break;
11603
11604			case 'YZX':
11605
11606				this._z = Math.asin( clamp( m21, -1, 1 ) );
11607
11608				if ( Math.abs( m21 ) < 0.9999999 ) {
11609
11610					this._x = Math.atan2( - m23, m22 );
11611					this._y = Math.atan2( - m31, m11 );
11612
11613				} else {
11614
11615					this._x = 0;
11616					this._y = Math.atan2( m13, m33 );
11617
11618				}
11619
11620				break;
11621
11622			case 'XZY':
11623
11624				this._z = Math.asin( - clamp( m12, -1, 1 ) );
11625
11626				if ( Math.abs( m12 ) < 0.9999999 ) {
11627
11628					this._x = Math.atan2( m32, m22 );
11629					this._y = Math.atan2( m13, m11 );
11630
11631				} else {
11632
11633					this._x = Math.atan2( - m23, m33 );
11634					this._y = 0;
11635
11636				}
11637
11638				break;
11639
11640			default:
11641
11642				warn( 'Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
11643
11644		}
11645
11646		this._order = order;
11647
11648		if ( update === true ) this._onChangeCallback();
11649
11650		return this;
11651
11652	}
11653
11654	/**
11655	 * Sets the angles of this Euler instance from a normalized quaternion.
11656	 *
11657	 * @param {Quaternion} q - A normalized Quaternion.
11658	 * @param {string} [order] - A string representing the order that the rotations are applied.
11659	 * @param {boolean} [update=true] - Whether the internal `onChange` callback should be executed or not.
11660	 * @return {Euler} A reference to this Euler instance.
11661	 */
11662	setFromQuaternion( q, order, update ) {
11663
11664		_matrix$2.makeRotationFromQuaternion( q );
11665
11666		return this.setFromRotationMatrix( _matrix$2, order, update );
11667
11668	}
11669
11670	/**
11671	 * Sets the angles of this Euler instance from the given vector.
11672	 *
11673	 * @param {Vector3} v - The vector.
11674	 * @param {string} [order] - A string representing the order that the rotations are applied.
11675	 * @return {Euler} A reference to this Euler instance.
11676	 */
11677	setFromVector3( v, order = this._order ) {
11678
11679		return this.set( v.x, v.y, v.z, order );
11680
11681	}
11682
11683	/**
11684	 * Resets the euler angle with a new order by creating a quaternion from this
11685	 * euler angle and then setting this euler angle with the quaternion and the
11686	 * new order.
11687	 *
11688	 * Warning: This discards revolution information.
11689	 *
11690	 * @param {string} [newOrder] - A string representing the new order that the rotations are applied.
11691	 * @return {Euler} A reference to this Euler instance.
11692	 */
11693	reorder( newOrder ) {
11694
11695		_quaternion$4.setFromEuler( this );
11696
11697		return this.setFromQuaternion( _quaternion$4, newOrder );
11698
11699	}
11700
11701	/**
11702	 * Returns `true` if this Euler instance is equal with the given one.
11703	 *
11704	 * @param {Euler} euler - The Euler instance to test for equality.
11705	 * @return {boolean} Whether this Euler instance is equal with the given one.
11706	 */
11707	equals( euler ) {
11708
11709		return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
11710
11711	}
11712
11713	/**
11714	 * Sets this Euler instance's components to values from the given array. The first three
11715	 * entries of the array are assign to the x,y and z components. An optional fourth entry
11716	 * defines the Euler order.
11717	 *
11718	 * @param {Array<number,number,number,?string>} array - An array holding the Euler component values.
11719	 * @return {Euler} A reference to this Euler instance.
11720	 */
11721	fromArray( array ) {
11722
11723		this._x = array[ 0 ];
11724		this._y = array[ 1 ];
11725		this._z = array[ 2 ];
11726		if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
11727
11728		this._onChangeCallback();
11729
11730		return this;
11731
11732	}
11733
11734	/**
11735	 * Writes the components of this Euler instance to the given array. If no array is provided,
11736	 * the method returns a new instance.
11737	 *
11738	 * @param {Array<number,number,number,string>} [array=[]] - The target array holding the Euler components.
11739	 * @param {number} [offset=0] - Index of the first element in the array.
11740	 * @return {Array<number,number,number,string>} The Euler components.
11741	 */
11742	toArray( array = [], offset = 0 ) {
11743
11744		array[ offset ] = this._x;
11745		array[ offset + 1 ] = this._y;
11746		array[ offset + 2 ] = this._z;
11747		array[ offset + 3 ] = this._order;
11748
11749		return array;
11750
11751	}
11752
11753	_onChange( callback ) {
11754
11755		this._onChangeCallback = callback;
11756
11757		return this;
11758
11759	}
11760
11761	_onChangeCallback() {}
11762
11763	*[ Symbol.iterator ]() {
11764
11765		yield this._x;
11766		yield this._y;
11767		yield this._z;
11768		yield this._order;
11769
11770	}
11771
11772}
11773
11774/**
11775 * The default Euler angle order.
11776 *
11777 * @static
11778 * @type {string}
11779 * @default 'XYZ'
11780 */
11781Euler.DEFAULT_ORDER = 'XYZ';
11782
11783/**
11784 * A layers object assigns an 3D object to 1 or more of 32
11785 * layers numbered `0` to `31` - internally the layers are stored as a
11786 * bit mask], and by default all 3D objects are a member of layer `0`.
11787 *
11788 * This can be used to control visibility - an object must share a layer with
11789 * a camera to be visible when that camera's view is
11790 * rendered.
11791 *
11792 * All classes that inherit from {@link Object3D} have an `layers` property which
11793 * is an instance of this class.
11794 */
11795class Layers {
11796
11797	/**
11798	 * Constructs a new layers instance, with membership
11799	 * initially set to layer `0`.
11800	 */
11801	constructor() {
11802
11803		/**
11804		 * A bit mask storing which of the 32 layers this layers object is currently
11805		 * a member of.
11806		 *
11807		 * @type {number}
11808		 */
11809		this.mask = 1 | 0;
11810
11811	}
11812
11813	/**
11814	 * Sets membership to the given layer, and remove membership all other layers.
11815	 *
11816	 * @param {number} layer - The layer to set.
11817	 */
11818	set( layer ) {
11819
11820		this.mask = ( 1 << layer | 0 ) >>> 0;
11821
11822	}
11823
11824	/**
11825	 * Adds membership of the given layer.
11826	 *
11827	 * @param {number} layer - The layer to enable.
11828	 */
11829	enable( layer ) {
11830
11831		this.mask |= 1 << layer | 0;
11832
11833	}
11834
11835	/**
11836	 * Adds membership to all layers.
11837	 */
11838	enableAll() {
11839
11840		this.mask = 0xffffffff | 0;
11841
11842	}
11843
11844	/**
11845	 * Toggles the membership of the given layer.
11846	 *
11847	 * @param {number} layer - The layer to toggle.
11848	 */
11849	toggle( layer ) {
11850
11851		this.mask ^= 1 << layer | 0;
11852
11853	}
11854
11855	/**
11856	 * Removes membership of the given layer.
11857	 *
11858	 * @param {number} layer - The layer to enable.
11859	 */
11860	disable( layer ) {
11861
11862		this.mask &= ~ ( 1 << layer | 0 );
11863
11864	}
11865
11866	/**
11867	 * Removes the membership from all layers.
11868	 */
11869	disableAll() {
11870
11871		this.mask = 0;
11872
11873	}
11874
11875	/**
11876	 * Returns `true` if this and the given layers object have at least one
11877	 * layer in common.
11878	 *
11879	 * @param {Layers} layers - The layers to test.
11880	 * @return {boolean } Whether this and the given layers object have at least one layer in common or not.
11881	 */
11882	test( layers ) {
11883
11884		return ( this.mask & layers.mask ) !== 0;
11885
11886	}
11887
11888	/**
11889	 * Returns `true` if the given layer is enabled.
11890	 *
11891	 * @param {number} layer - The layer to test.
11892	 * @return {boolean } Whether the given layer is enabled or not.
11893	 */
11894	isEnabled( layer ) {
11895
11896		return ( this.mask & ( 1 << layer | 0 ) ) !== 0;
11897
11898	}
11899
11900}
11901
11902let _object3DId = 0;
11903
11904const _v1$6 = /*@__PURE__*/ new Vector3();
11905const _q1 = /*@__PURE__*/ new Quaternion();
11906const _m1$1 = /*@__PURE__*/ new Matrix4();
11907const _target = /*@__PURE__*/ new Vector3();
11908
11909const _position$4 = /*@__PURE__*/ new Vector3();
11910const _scale$3 = /*@__PURE__*/ new Vector3();
11911const _quaternion$3 = /*@__PURE__*/ new Quaternion();
11912
11913const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 );
11914const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 );
11915const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 );
11916
11917/**
11918 * Fires when the object has been added to its parent object.
11919 *
11920 * @event Object3D#added
11921 * @type {Object}
11922 */
11923const _addedEvent = { type: 'added' };
11924
11925/**
11926 * Fires when the object has been removed from its parent object.
11927 *
11928 * @event Object3D#removed
11929 * @type {Object}
11930 */
11931const _removedEvent = { type: 'removed' };
11932
11933/**
11934 * Fires when a new child object has been added.
11935 *
11936 * @event Object3D#childadded
11937 * @type {Object}
11938 */
11939const _childaddedEvent = { type: 'childadded', child: null };
11940
11941/**
11942 * Fires when a child object has been removed.
11943 *
11944 * @event Object3D#childremoved
11945 * @type {Object}
11946 */
11947const _childremovedEvent = { type: 'childremoved', child: null };
11948
11949/**
11950 * This is the base class for most objects in three.js and provides a set of
11951 * properties and methods for manipulating objects in 3D space.
11952 *
11953 * @augments EventDispatcher
11954 */
11955class Object3D extends EventDispatcher {
11956
11957	/**
11958	 * Constructs a new 3D object.
11959	 */
11960	constructor() {
11961
11962		super();
11963
11964		/**
11965		 * This flag can be used for type testing.
11966		 *
11967		 * @type {boolean}
11968		 * @readonly
11969		 * @default true
11970		 */
11971		this.isObject3D = true;
11972
11973		/**
11974		 * The ID of the 3D object.
11975		 *
11976		 * @name Object3D#id
11977		 * @type {number}
11978		 * @readonly
11979		 */
11980		Object.defineProperty( this, 'id', { value: _object3DId ++ } );
11981
11982		/**
11983		 * The UUID of the 3D object.
11984		 *
11985		 * @type {string}
11986		 * @readonly
11987		 */
11988		this.uuid = generateUUID();
11989
11990		/**
11991		 * The name of the 3D object.
11992		 *
11993		 * @type {string}
11994		 */
11995		this.name = '';
11996
11997		/**
11998		 * The type property is used for detecting the object type
11999		 * in context of serialization/deserialization.
12000		 *
12001		 * @type {string}
12002		 * @readonly
12003		 */
12004		this.type = 'Object3D';
12005
12006		/**
12007		 * A reference to the parent object.
12008		 *
12009		 * @type {?Object3D}
12010		 * @default null
12011		 */
12012		this.parent = null;
12013
12014		/**
12015		 * An array holding the child 3D objects of this instance.
12016		 *
12017		 * @type {Array<Object3D>}
12018		 */
12019		this.children = [];
12020
12021		/**
12022		 * Defines the `up` direction of the 3D object which influences
12023		 * the orientation via methods like {@link Object3D#lookAt}.
12024		 *
12025		 * The default values for all 3D objects is defined by `Object3D.DEFAULT_UP`.
12026		 *
12027		 * @type {Vector3}
12028		 */
12029		this.up = Object3D.DEFAULT_UP.clone();
12030
12031		const position = new Vector3();
12032		const rotation = new Euler();
12033		const quaternion = new Quaternion();
12034		const scale = new Vector3( 1, 1, 1 );
12035
12036		function onRotationChange() {
12037
12038			quaternion.setFromEuler( rotation, false );
12039
12040		}
12041
12042		function onQuaternionChange() {
12043
12044			rotation.setFromQuaternion( quaternion, undefined, false );
12045
12046		}
12047
12048		rotation._onChange( onRotationChange );
12049		quaternion._onChange( onQuaternionChange );
12050
12051		Object.defineProperties( this, {
12052			/**
12053			 * Represents the object's local position.
12054			 *
12055			 * @name Object3D#position
12056			 * @type {Vector3}
12057			 * @default (0,0,0)
12058			 */
12059			position: {
12060				configurable: true,
12061				enumerable: true,
12062				value: position
12063			},
12064			/**
12065			 * Represents the object's local rotation as Euler angles, in radians.
12066			 *
12067			 * @name Object3D#rotation
12068			 * @type {Euler}
12069			 * @default (0,0,0)
12070			 */
12071			rotation: {
12072				configurable: true,
12073				enumerable: true,
12074				value: rotation
12075			},
12076			/**
12077			 * Represents the object's local rotation as Quaternions.
12078			 *
12079			 * @name Object3D#quaternion
12080			 * @type {Quaternion}
12081			 */
12082			quaternion: {
12083				configurable: true,
12084				enumerable: true,
12085				value: quaternion
12086			},
12087			/**
12088			 * Represents the object's local scale.
12089			 *
12090			 * @name Object3D#scale
12091			 * @type {Vector3}
12092			 * @default (1,1,1)
12093			 */
12094			scale: {
12095				configurable: true,
12096				enumerable: true,
12097				value: scale
12098			},
12099			/**
12100			 * Represents the object's model-view matrix.
12101			 *
12102			 * @name Object3D#modelViewMatrix
12103			 * @type {Matrix4}
12104			 */
12105			modelViewMatrix: {
12106				value: new Matrix4()
12107			},
12108			/**
12109			 * Represents the object's normal matrix.
12110			 *
12111			 * @name Object3D#normalMatrix
12112			 * @type {Matrix3}
12113			 */
12114			normalMatrix: {
12115				value: new Matrix3()
12116			}
12117		} );
12118
12119		/**
12120		 * Represents the object's transformation matrix in local space.
12121		 *
12122		 * @type {Matrix4}
12123		 */
12124		this.matrix = new Matrix4();
12125
12126		/**
12127		 * Represents the object's transformation matrix in world space.
12128		 * If the 3D object has no parent, then it's identical to the local transformation matrix
12129		 *
12130		 * @type {Matrix4}
12131		 */
12132		this.matrixWorld = new Matrix4();
12133
12134		/**
12135		 * When set to `true`, the engine automatically computes the local matrix from position,
12136		 * rotation and scale every frame. If set to `false`, the app is responsible for recomputing
12137		 * the local matrix by calling `updateMatrix()`.
12138		 *
12139		 * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_AUTO_UPDATE`.
12140		 *
12141		 * @type {boolean}
12142		 * @default true
12143		 */
12144		this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
12145
12146		/**
12147		 * When set to `true`, the engine automatically computes the world matrix from the current local
12148		 * matrix and the object's transformation hierarchy. If set to `false`, the app is responsible for
12149		 * recomputing the world matrix by directly updating the `matrixWorld` property.
12150		 *
12151		 * The default values for all 3D objects is defined by `Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE`.
12152		 *
12153		 * @type {boolean}
12154		 * @default true
12155		 */
12156		this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer
12157
12158		/**
12159		 * When set to `true`, it calculates the world matrix in that frame and resets this property
12160		 * to `false`.
12161		 *
12162		 * @type {boolean}
12163		 * @default false
12164		 */
12165		this.matrixWorldNeedsUpdate = false;
12166
12167		/**
12168		 * The layer membership of the 3D object. The 3D object is only visible if it has
12169		 * at least one layer in common with the camera in use. This property can also be
12170		 * used to filter out unwanted objects in ray-intersection tests when using {@link Raycaster}.
12171		 *
12172		 * @type {Layers}
12173		 */
12174		this.layers = new Layers();
12175
12176		/**
12177		 * When set to `true`, the 3D object gets rendered.
12178		 *
12179		 * @type {boolean}
12180		 * @default true
12181		 */
12182		this.visible = true;
12183
12184		/**
12185		 * When set to `true`, the 3D object gets rendered into shadow maps.
12186		 *
12187		 * @type {boolean}
12188		 * @default false
12189		 */
12190		this.castShadow = false;
12191
12192		/**
12193		 * When set to `true`, the 3D object is affected by shadows in the scene.
12194		 *
12195		 * @type {boolean}
12196		 * @default false
12197		 */
12198		this.receiveShadow = false;
12199
12200		/**
12201		 * When set to `true`, the 3D object is honored by view frustum culling.
12202		 *
12203		 * @type {boolean}
12204		 * @default true
12205		 */
12206		this.frustumCulled = true;
12207
12208		/**
12209		 * This value allows the default rendering order of scene graph objects to be
12210		 * overridden although opaque and transparent objects remain sorted independently.
12211		 * When this property is set for an instance of {@link Group},all descendants
12212		 * objects will be sorted and rendered together. Sorting is from lowest to highest
12213		 * render order.
12214		 *
12215		 * @type {number}
12216		 * @default 0
12217		 */
12218		this.renderOrder = 0;
12219
12220		/**
12221		 * An array holding the animation clips of the 3D object.
12222		 *
12223		 * @type {Array<AnimationClip>}
12224		 */
12225		this.animations = [];
12226
12227		/**
12228		 * Custom depth material to be used when rendering to the depth map. Can only be used
12229		 * in context of meshes. When shadow-casting with a {@link DirectionalLight} or {@link SpotLight},
12230		 * if you are modifying vertex positions in the vertex shader you must specify a custom depth
12231		 * material for proper shadows.
12232		 *
12233		 * Only relevant in context of {@link WebGLRenderer}.
12234		 *
12235		 * @type {(Material|undefined)}
12236		 * @default undefined
12237		 */
12238		this.customDepthMaterial = undefined;
12239
12240		/**
12241		 * Same as {@link Object3D#customDepthMaterial}, but used with {@link PointLight}.
12242		 *
12243		 * Only relevant in context of {@link WebGLRenderer}.
12244		 *
12245		 * @type {(Material|undefined)}
12246		 * @default undefined
12247		 */
12248		this.customDistanceMaterial = undefined;
12249
12250		/**
12251		 * Whether the 3D object is supposed to be static or not. If set to `true`, it means
12252		 * the 3D object is not going to be changed after the initial renderer. This includes
12253		 * geometry and material settings. A static 3D object can be processed by the renderer
12254		 * slightly faster since certain state checks can be bypassed.
12255		 *
12256		 * Only relevant in context of {@link WebGPURenderer}.
12257		 *
12258		 * @type {boolean}
12259		 * @default false
12260		 */
12261		this.static = false;
12262
12263		/**
12264		 * An object that can be used to store custom data about the 3D object. It
12265		 * should not hold references to functions as these will not be cloned.
12266		 *
12267		 * @type {Object}
12268		 */
12269		this.userData = {};
12270
12271		/**
12272		 * The pivot point for rotation and scale transformations.
12273		 * When set, rotation and scale are applied around this point
12274		 * instead of the object's origin.
12275		 *
12276		 * @type {?Vector3}
12277		 * @default null
12278		 */
12279		this.pivot = null;
12280
12281	}
12282
12283	/**
12284	 * A callback that is executed immediately before a 3D object is rendered to a shadow map.
12285	 *
12286	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12287	 * @param {Object3D} object - The 3D object.
12288	 * @param {Camera} camera - The camera that is used to render the scene.
12289	 * @param {Camera} shadowCamera - The shadow camera.
12290	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12291	 * @param {Material} depthMaterial - The depth material.
12292	 * @param {Object} group - The geometry group data.
12293	 */
12294	onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
12295
12296	/**
12297	 * A callback that is executed immediately after a 3D object is rendered to a shadow map.
12298	 *
12299	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12300	 * @param {Object3D} object - The 3D object.
12301	 * @param {Camera} camera - The camera that is used to render the scene.
12302	 * @param {Camera} shadowCamera - The shadow camera.
12303	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12304	 * @param {Material} depthMaterial - The depth material.
12305	 * @param {Object} group - The geometry group data.
12306	 */
12307	onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {}
12308
12309	/**
12310	 * A callback that is executed immediately before a 3D object is rendered.
12311	 *
12312	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12313	 * @param {Object3D} object - The 3D object.
12314	 * @param {Camera} camera - The camera that is used to render the scene.
12315	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12316	 * @param {Material} material - The 3D object's material.
12317	 * @param {Object} group - The geometry group data.
12318	 */
12319	onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {}
12320
12321	/**
12322	 * A callback that is executed immediately after a 3D object is rendered.
12323	 *
12324	 * @param {Renderer|WebGLRenderer} renderer - The renderer.
12325	 * @param {Object3D} object - The 3D object.
12326	 * @param {Camera} camera - The camera that is used to render the scene.
12327	 * @param {BufferGeometry} geometry - The 3D object's geometry.
12328	 * @param {Material} material - The 3D object's material.
12329	 * @param {Object} group - The geometry group data.
12330	 */
12331	onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {}
12332
12333	/**
12334	 * Applies the given transformation matrix to the object and updates the object's position,
12335	 * rotation and scale.
12336	 *
12337	 * @param {Matrix4} matrix - The transformation matrix.
12338	 */
12339	applyMatrix4( matrix ) {
12340
12341		if ( this.matrixAutoUpdate ) this.updateMatrix();
12342
12343		this.matrix.premultiply( matrix );
12344
12345		this.matrix.decompose( this.position, this.quaternion, this.scale );
12346
12347	}
12348
12349	/**
12350	 * Applies a rotation represented by given the quaternion to the 3D object.
12351	 *
12352	 * @param {Quaternion} q - The quaternion.
12353	 * @return {Object3D} A reference to this instance.
12354	 */
12355	applyQuaternion( q ) {
12356
12357		this.quaternion.premultiply( q );
12358
12359		return this;
12360
12361	}
12362
12363	/**
12364	 * Sets the given rotation represented as an axis/angle couple to the 3D object.
12365	 *
12366	 * @param {Vector3} axis - The (normalized) axis vector.
12367	 * @param {number} angle - The angle in radians.
12368	 */
12369	setRotationFromAxisAngle( axis, angle ) {
12370
12371		// assumes axis is normalized
12372
12373		this.quaternion.setFromAxisAngle( axis, angle );
12374
12375	}
12376
12377	/**
12378	 * Sets the given rotation represented as Euler angles to the 3D object.
12379	 *
12380	 * @param {Euler} euler - The Euler angles.
12381	 */
12382	setRotationFromEuler( euler ) {
12383
12384		this.quaternion.setFromEuler( euler, true );
12385
12386	}
12387
12388	/**
12389	 * Sets the given rotation represented as rotation matrix to the 3D object.
12390	 *
12391	 * @param {Matrix4} m - Although a 4x4 matrix is expected, the upper 3x3 portion must be
12392	 * a pure rotation matrix (i.e, unscaled).
12393	 */
12394	setRotationFromMatrix( m ) {
12395
12396		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
12397
12398		this.quaternion.setFromRotationMatrix( m );
12399
12400	}
12401
12402	/**
12403	 * Sets the given rotation represented as a Quaternion to the 3D object.
12404	 *
12405	 * @param {Quaternion} q - The Quaternion
12406	 */
12407	setRotationFromQuaternion( q ) {
12408
12409		// assumes q is normalized
12410
12411		this.quaternion.copy( q );
12412
12413	}
12414
12415	/**
12416	 * Rotates the 3D object along an axis in local space.
12417	 *
12418	 * @param {Vector3} axis - The (normalized) axis vector.
12419	 * @param {number} angle - The angle in radians.
12420	 * @return {Object3D} A reference to this instance.
12421	 */
12422	rotateOnAxis( axis, angle ) {
12423
12424		// rotate object on axis in object space
12425		// axis is assumed to be normalized
12426
12427		_q1.setFromAxisAngle( axis, angle );
12428
12429		this.quaternion.multiply( _q1 );
12430
12431		return this;
12432
12433	}
12434
12435	/**
12436	 * Rotates the 3D object along an axis in world space.
12437	 *
12438	 * @param {Vector3} axis - The (normalized) axis vector.
12439	 * @param {number} angle - The angle in radians.
12440	 * @return {Object3D} A reference to this instance.
12441	 */
12442	rotateOnWorldAxis( axis, angle ) {
12443
12444		// rotate object on axis in world space
12445		// axis is assumed to be normalized
12446		// method assumes no rotated parent
12447
12448		_q1.setFromAxisAngle( axis, angle );
12449
12450		this.quaternion.premultiply( _q1 );
12451
12452		return this;
12453
12454	}
12455
12456	/**
12457	 * Rotates the 3D object around its X axis in local space.
12458	 *
12459	 * @param {number} angle - The angle in radians.
12460	 * @return {Object3D} A reference to this instance.
12461	 */
12462	rotateX( angle ) {
12463
12464		return this.rotateOnAxis( _xAxis, angle );
12465
12466	}
12467
12468	/**
12469	 * Rotates the 3D object around its Y axis in local space.
12470	 *
12471	 * @param {number} angle - The angle in radians.
12472	 * @return {Object3D} A reference to this instance.
12473	 */
12474	rotateY( angle ) {
12475
12476		return this.rotateOnAxis( _yAxis, angle );
12477
12478	}
12479
12480	/**
12481	 * Rotates the 3D object around its Z axis in local space.
12482	 *
12483	 * @param {number} angle - The angle in radians.
12484	 * @return {Object3D} A reference to this instance.
12485	 */
12486	rotateZ( angle ) {
12487
12488		return this.rotateOnAxis( _zAxis, angle );
12489
12490	}
12491
12492	/**
12493	 * Translate the 3D object by a distance along the given axis in local space.
12494	 *
12495	 * @param {Vector3} axis - The (normalized) axis vector.
12496	 * @param {number} distance - The distance in world units.
12497	 * @return {Object3D} A reference to this instance.
12498	 */
12499	translateOnAxis( axis, distance ) {
12500
12501		// translate object by distance along axis in object space
12502		// axis is assumed to be normalized
12503
12504		_v1$6.copy( axis ).applyQuaternion( this.quaternion );
12505
12506		this.position.add( _v1$6.multiplyScalar( distance ) );
12507
12508		return this;
12509
12510	}
12511
12512	/**
12513	 * Translate the 3D object by a distance along its X-axis in local space.
12514	 *
12515	 * @param {number} distance - The distance in world units.
12516	 * @return {Object3D} A reference to this instance.
12517	 */
12518	translateX( distance ) {
12519
12520		return this.translateOnAxis( _xAxis, distance );
12521
12522	}
12523
12524	/**
12525	 * Translate the 3D object by a distance along its Y-axis in local space.
12526	 *
12527	 * @param {number} distance - The distance in world units.
12528	 * @return {Object3D} A reference to this instance.
12529	 */
12530	translateY( distance ) {
12531
12532		return this.translateOnAxis( _yAxis, distance );
12533
12534	}
12535
12536	/**
12537	 * Translate the 3D object by a distance along its Z-axis in local space.
12538	 *
12539	 * @param {number} distance - The distance in world units.
12540	 * @return {Object3D} A reference to this instance.
12541	 */
12542	translateZ( distance ) {
12543
12544		return this.translateOnAxis( _zAxis, distance );
12545
12546	}
12547
12548	/**
12549	 * Converts the given vector from this 3D object's local space to world space.
12550	 *
12551	 * @param {Vector3} vector - The vector to convert.
12552	 * @return {Vector3} The converted vector.
12553	 */
12554	localToWorld( vector ) {
12555
12556		this.updateWorldMatrix( true, false );
12557
12558		return vector.applyMatrix4( this.matrixWorld );
12559
12560	}
12561
12562	/**
12563	 * Converts the given vector from this 3D object's world space to local space.
12564	 *
12565	 * @param {Vector3} vector - The vector to convert.
12566	 * @return {Vector3} The converted vector.
12567	 */
12568	worldToLocal( vector ) {
12569
12570		this.updateWorldMatrix( true, false );
12571
12572		return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() );
12573
12574	}
12575
12576	/**
12577	 * Rotates the object to face a point in world space.
12578	 *
12579	 * This method does not support objects having non-uniformly-scaled parent(s).
12580	 *
12581	 * @param {number|Vector3} x - The x coordinate in world space. Alternatively, a vector representing a position in world space
12582	 * @param {number} [y] - The y coordinate in world space.
12583	 * @param {number} [z] - The z coordinate in world space.
12584	 */
12585	lookAt( x, y, z ) {
12586
12587		// This method does not support objects having non-uniformly-scaled parent(s)
12588
12589		if ( x.isVector3 ) {
12590
12591			_target.copy( x );
12592
12593		} else {
12594
12595			_target.set( x, y, z );
12596
12597		}
12598
12599		const parent = this.parent;
12600
12601		this.updateWorldMatrix( true, false );
12602
12603		_position$4.setFromMatrixPosition( this.matrixWorld );
12604
12605		if ( this.isCamera || this.isLight ) {
12606
12607			_m1$1.lookAt( _position$4, _target, this.up );
12608
12609		} else {
12610
12611			_m1$1.lookAt( _target, _position$4, this.up );
12612
12613		}
12614
12615		this.quaternion.setFromRotationMatrix( _m1$1 );
12616
12617		if ( parent ) {
12618
12619			_m1$1.extractRotation( parent.matrixWorld );
12620			_q1.setFromRotationMatrix( _m1$1 );
12621			this.quaternion.premultiply( _q1.invert() );
12622
12623		}
12624
12625	}
12626
12627	/**
12628	 * Adds the given 3D object as a child to this 3D object. An arbitrary number of
12629	 * objects may be added. Any current parent on an object passed in here will be
12630	 * removed, since an object can have at most one parent.
12631	 *
12632	 * @fires Object3D#added
12633	 * @fires Object3D#childadded
12634	 * @param {Object3D} object - The 3D object to add.
12635	 * @return {Object3D} A reference to this instance.
12636	 */
12637	add( object ) {
12638
12639		if ( arguments.length > 1 ) {
12640
12641			for ( let i = 0; i < arguments.length; i ++ ) {
12642
12643				this.add( arguments[ i ] );
12644
12645			}
12646
12647			return this;
12648
12649		}
12650
12651		if ( object === this ) {
12652
12653			error( 'Object3D.add: object can\'t be added as a child of itself.', object );
12654			return this;
12655
12656		}
12657
12658		if ( object && object.isObject3D ) {
12659
12660			object.removeFromParent();
12661			object.parent = this;
12662			this.children.push( object );
12663
12664			object.dispatchEvent( _addedEvent );
12665
12666			_childaddedEvent.child = object;
12667			this.dispatchEvent( _childaddedEvent );
12668			_childaddedEvent.child = null;
12669
12670		} else {
12671
12672			error( 'Object3D.add: object not an instance of THREE.Object3D.', object );
12673
12674		}
12675
12676		return this;
12677
12678	}
12679
12680	/**
12681	 * Removes the given 3D object as child from this 3D object.
12682	 * An arbitrary number of objects may be removed.
12683	 *
12684	 * @fires Object3D#removed
12685	 * @fires Object3D#childremoved
12686	 * @param {Object3D} object - The 3D object to remove.
12687	 * @return {Object3D} A reference to this instance.
12688	 */
12689	remove( object ) {
12690
12691		if ( arguments.length > 1 ) {
12692
12693			for ( let i = 0; i < arguments.length; i ++ ) {
12694
12695				this.remove( arguments[ i ] );
12696
12697			}
12698
12699			return this;
12700
12701		}
12702
12703		const index = this.children.indexOf( object );
12704
12705		if ( index !== -1 ) {
12706
12707			object.parent = null;
12708			this.children.splice( index, 1 );
12709
12710			object.dispatchEvent( _removedEvent );
12711
12712			_childremovedEvent.child = object;
12713			this.dispatchEvent( _childremovedEvent );
12714			_childremovedEvent.child = null;
12715
12716		}
12717
12718		return this;
12719
12720	}
12721
12722	/**
12723	 * Removes this 3D object from its current parent.
12724	 *
12725	 * @fires Object3D#removed
12726	 * @fires Object3D#childremoved
12727	 * @return {Object3D} A reference to this instance.
12728	 */
12729	removeFromParent() {
12730
12731		const parent = this.parent;
12732
12733		if ( parent !== null ) {
12734
12735			parent.remove( this );
12736
12737		}
12738
12739		return this;
12740
12741	}
12742
12743	/**
12744	 * Removes all child objects.
12745	 *
12746	 * @fires Object3D#removed
12747	 * @fires Object3D#childremoved
12748	 * @return {Object3D} A reference to this instance.
12749	 */
12750	clear() {
12751
12752		return this.remove( ... this.children );
12753
12754	}
12755
12756	/**
12757	 * Adds the given 3D object as a child of this 3D object, while maintaining the object's world
12758	 * transform. This method does not support scene graphs having non-uniformly-scaled nodes(s).
12759	 *
12760	 * @fires Object3D#added
12761	 * @fires Object3D#childadded
12762	 * @param {Object3D} object - The 3D object to attach.
12763	 * @return {Object3D} A reference to this instance.
12764	 */
12765	attach( object ) {
12766
12767		// adds object as a child of this, while maintaining the object's world transform
12768
12769		// Note: This method does not support scene graphs having non-uniformly-scaled nodes(s)
12770
12771		this.updateWorldMatrix( true, false );
12772
12773		_m1$1.copy( this.matrixWorld ).invert();
12774
12775		if ( object.parent !== null ) {
12776
12777			object.parent.updateWorldMatrix( true, false );
12778
12779			_m1$1.multiply( object.parent.matrixWorld );
12780
12781		}
12782
12783		object.applyMatrix4( _m1$1 );
12784
12785		object.removeFromParent();
12786		object.parent = this;
12787		this.children.push( object );
12788
12789		object.updateWorldMatrix( false, true );
12790
12791		object.dispatchEvent( _addedEvent );
12792
12793		_childaddedEvent.child = object;
12794		this.dispatchEvent( _childaddedEvent );
12795		_childaddedEvent.child = null;
12796
12797		return this;
12798
12799	}
12800
12801	/**
12802	 * Searches through the 3D object and its children, starting with the 3D object
12803	 * itself, and returns the first with a matching ID.
12804	 *
12805	 * @param {number} id - The id.
12806	 * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
12807	 */
12808	getObjectById( id ) {
12809
12810		return this.getObjectByProperty( 'id', id );
12811
12812	}
12813
12814	/**
12815	 * Searches through the 3D object and its children, starting with the 3D object
12816	 * itself, and returns the first with a matching name.
12817	 *
12818	 * @param {string} name - The name.
12819	 * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
12820	 */
12821	getObjectByName( name ) {
12822
12823		return this.getObjectByProperty( 'name', name );
12824
12825	}
12826
12827	/**
12828	 * Searches through the 3D object and its children, starting with the 3D object
12829	 * itself, and returns the first with a matching property value.
12830	 *
12831	 * @param {string} name - The name of the property.
12832	 * @param {any} value - The value.
12833	 * @return {Object3D|undefined} The found 3D object. Returns `undefined` if no 3D object has been found.
12834	 */
12835	getObjectByProperty( name, value ) {
12836
12837		if ( this[ name ] === value ) return this;
12838
12839		for ( let i = 0, l = this.children.length; i < l; i ++ ) {
12840
12841			const child = this.children[ i ];
12842			const object = child.getObjectByProperty( name, value );
12843
12844			if ( object !== undefined ) {
12845
12846				return object;
12847
12848			}
12849
12850		}
12851
12852		return undefined;
12853
12854	}
12855
12856	/**
12857	 * Searches through the 3D object and its children, starting with the 3D object
12858	 * itself, and returns all 3D objects with a matching property value.
12859	 *
12860	 * @param {string} name - The name of the property.
12861	 * @param {any} value - The value.
12862	 * @param {Array<Object3D>} result - The method stores the result in this array.
12863	 * @return {Array<Object3D>} The found 3D objects.
12864	 */
12865	getObjectsByProperty( name, value, result = [] ) {
12866
12867		if ( this[ name ] === value ) result.push( this );
12868
12869		const children = this.children;
12870
12871		for ( let i = 0, l = children.length; i < l; i ++ ) {
12872
12873			children[ i ].getObjectsByProperty( name, value, result );
12874
12875		}
12876
12877		return result;
12878
12879	}
12880
12881	/**
12882	 * Returns a vector representing the position of the 3D object in world space.
12883	 *
12884	 * @param {Vector3} target - The target vector the result is stored to.
12885	 * @return {Vector3} The 3D object's position in world space.
12886	 */
12887	getWorldPosition( target ) {
12888
12889		this.updateWorldMatrix( true, false );
12890
12891		return target.setFromMatrixPosition( this.matrixWorld );
12892
12893	}
12894
12895	/**
12896	 * Returns a Quaternion representing the position of the 3D object in world space.
12897	 *
12898	 * @param {Quaternion} target - The target Quaternion the result is stored to.
12899	 * @return {Quaternion} The 3D object's rotation in world space.
12900	 */
12901	getWorldQuaternion( target ) {
12902
12903		this.updateWorldMatrix( true, false );
12904
12905		this.matrixWorld.decompose( _position$4, target, _scale$3 );
12906
12907		return target;
12908
12909	}
12910
12911	/**
12912	 * Returns a vector representing the scale of the 3D object in world space.
12913	 *
12914	 * @param {Vector3} target - The target vector the result is stored to.
12915	 * @return {Vector3} The 3D object's scale in world space.
12916	 */
12917	getWorldScale( target ) {
12918
12919		this.updateWorldMatrix( true, false );
12920
12921		this.matrixWorld.decompose( _position$4, _quaternion$3, target );
12922
12923		return target;
12924
12925	}
12926
12927	/**
12928	 * Returns a vector representing the ("look") direction of the 3D object in world space.
12929	 *
12930	 * @param {Vector3} target - The target vector the result is stored to.
12931	 * @return {Vector3} The 3D object's direction in world space.
12932	 */
12933	getWorldDirection( target ) {
12934
12935		this.updateWorldMatrix( true, false );
12936
12937		const e = this.matrixWorld.elements;
12938
12939		return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
12940
12941	}
12942
12943	/**
12944	 * Abstract method to get intersections between a casted ray and this
12945	 * 3D object. Renderable 3D objects such as {@link Mesh}, {@link Line} or {@link Points}
12946	 * implement this method in order to use raycasting.
12947	 *
12948	 * @abstract
12949	 * @param {Raycaster} raycaster - The raycaster.
12950	 * @param {Array<Object>} intersects - An array holding the result of the method.
12951	 */
12952	raycast( /* raycaster, intersects */ ) {}
12953
12954	/**
12955	 * Abstract method to test whether this 3D object intersects the given frustum.
12956	 * Renderable 3D objects such as {@link Mesh}, {@link Line} or {@link Points}
12957	 * implement this method in order to use frustum culling.
12958	 *
12959	 * @abstract
12960	 * @param {Frustum|FrustumArray} frustum - The frustum to test.
12961	 * @return {boolean|undefined} Whether this 3D object intersects the given frustum or not.
12962	 */
12963	intersectsFrustum( /* frustum */ ) {}
12964
12965	/**
12966	 * Executes the callback on this 3D object and all descendants.
12967	 *
12968	 * Note: Modifying the scene graph inside the callback is discouraged.
12969	 *
12970	 * @param {Function} callback - A callback function that allows to process the current 3D object.
12971	 */
12972	traverse( callback ) {
12973
12974		callback( this );
12975
12976		const children = this.children;
12977
12978		for ( let i = 0, l = children.length; i < l; i ++ ) {
12979
12980			children[ i ].traverse( callback );
12981
12982		}
12983
12984	}
12985
12986	/**
12987	 * Like {@link Object3D#traverse}, but the callback will only be executed for visible 3D objects.
12988	 * Descendants of invisible 3D objects are not traversed.
12989	 *
12990	 * Note: Modifying the scene graph inside the callback is discouraged.
12991	 *
12992	 * @param {Function} callback - A callback function that allows to process the current 3D object.
12993	 */
12994	traverseVisible( callback ) {
12995
12996		if ( this.visible === false ) return;
12997
12998		callback( this );
12999
13000		const children = this.children;
13001
13002		for ( let i = 0, l = children.length; i < l; i ++ ) {
13003
13004			children[ i ].traverseVisible( callback );
13005
13006		}
13007
13008	}
13009
13010	/**
13011	 * Like {@link Object3D#traverse}, but the callback will only be executed for all ancestors.
13012	 *
13013	 * Note: Modifying the scene graph inside the callback is discouraged.
13014	 *
13015	 * @param {Function} callback - A callback function that allows to process the current 3D object.
13016	 */
13017	traverseAncestors( callback ) {
13018
13019		const parent = this.parent;
13020
13021		if ( parent !== null ) {
13022
13023			callback( parent );
13024
13025			parent.traverseAncestors( callback );
13026
13027		}
13028
13029	}
13030
13031	/**
13032	 * Updates the transformation matrix in local space by computing it from the current
13033	 * position, rotation and scale values.
13034	 */
13035	updateMatrix() {
13036
13037		this.matrix.compose( this.position, this.quaternion, this.scale );
13038
13039		const pivot = this.pivot;
13040
13041		if ( pivot !== null ) {
13042
13043			const px = pivot.x, py = pivot.y, pz = pivot.z;
13044			const te = this.matrix.elements;
13045
13046			te[ 12 ] += px - te[ 0 ] * px - te[ 4 ] * py - te[ 8 ] * pz;
13047			te[ 13 ] += py - te[ 1 ] * px - te[ 5 ] * py - te[ 9 ] * pz;
13048			te[ 14 ] += pz - te[ 2 ] * px - te[ 6 ] * py - te[ 10 ] * pz;
13049
13050		}
13051
13052		this.matrixWorldNeedsUpdate = true;
13053
13054	}
13055
13056	/**
13057	 * Updates the transformation matrix in world space of this 3D objects and its descendants.
13058	 *
13059	 * To ensure correct results, this method also recomputes the 3D object's transformation matrix in
13060	 * local space. The computation of the local and world matrix can be controlled with the
13061	 * {@link Object3D#matrixAutoUpdate} and {@link Object3D#matrixWorldAutoUpdate} flags which are both
13062	 * `true` by default.  Set these flags to `false` if you need more control over the update matrix process.
13063	 *
13064	 * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
13065	 * when {@link Object3D#matrixWorldNeedsUpdate} is `false`.
13066	 */
13067	updateMatrixWorld( force ) {
13068
13069		if ( this.matrixAutoUpdate ) this.updateMatrix();
13070
13071		if ( this.matrixWorldNeedsUpdate || force ) {
13072
13073			if ( this.matrixWorldAutoUpdate === true ) {
13074
13075				if ( this.parent === null ) {
13076
13077					this.matrixWorld.copy( this.matrix );
13078
13079				} else {
13080
13081					this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
13082
13083				}
13084
13085			}
13086
13087			this.matrixWorldNeedsUpdate = false;
13088
13089			force = true;
13090
13091		}
13092
13093		// make sure descendants are updated if required
13094
13095		const children = this.children;
13096
13097		for ( let i = 0, l = children.length; i < l; i ++ ) {
13098
13099			const child = children[ i ];
13100
13101			child.updateMatrixWorld( force );
13102
13103		}
13104
13105	}
13106
13107	/**
13108	 * An alternative version of {@link Object3D#updateMatrixWorld} with more control over the
13109	 * update of ancestor and descendant nodes.
13110	 *
13111	 * @param {boolean} [updateParents=false] Whether ancestor nodes should be updated or not.
13112	 * @param {boolean} [updateChildren=false] Whether descendant nodes should be updated or not.
13113	 * @param {boolean} [force=false] - When set to `true`, a recomputation of world matrices is forced even
13114	 * when {@link Object3D#matrixWorldNeedsUpdate} is `false`.
13115	 */
13116	updateWorldMatrix( updateParents, updateChildren, force = false ) {
13117
13118		const parent = this.parent;
13119
13120		if ( updateParents === true && parent !== null ) {
13121
13122			parent.updateWorldMatrix( true, false );
13123
13124		}
13125
13126		if ( this.matrixAutoUpdate ) this.updateMatrix();
13127
13128		if ( this.matrixWorldNeedsUpdate || force ) {
13129
13130			if ( this.matrixWorldAutoUpdate === true ) {
13131
13132				if ( this.parent === null ) {
13133
13134					this.matrixWorld.copy( this.matrix );
13135
13136				} else {
13137
13138					this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
13139
13140				}
13141
13142			}
13143
13144			this.matrixWorldNeedsUpdate = false;
13145
13146			force = true;
13147
13148		}
13149
13150		// make sure descendants are updated
13151
13152		if ( updateChildren === true ) {
13153
13154			const children = this.children;
13155
13156			for ( let i = 0, l = children.length; i < l; i ++ ) {
13157
13158				const child = children[ i ];
13159
13160				child.updateWorldMatrix( false, true, force );
13161
13162			}
13163
13164		}
13165
13166	}
13167
13168	/**
13169	 * Serializes the 3D object into JSON.
13170	 *
13171	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
13172	 * @return {Object} A JSON object representing the serialized 3D object.
13173	 * @see {@link ObjectLoader#parse}
13174	 */
13175	toJSON( meta ) {
13176
13177		// meta is a string when called from JSON.stringify
13178		const isRootObject = ( meta === undefined || typeof meta === 'string' );
13179
13180		const output = {};
13181
13182		// meta is a hash used to collect geometries, materials.
13183		// not providing it implies that this is the root object
13184		// being serialized.
13185		if ( isRootObject ) {
13186
13187			// initialize meta obj
13188			meta = {
13189				geometries: {},
13190				materials: {},
13191				textures: {},
13192				images: {},
13193				shapes: {},
13194				skeletons: {},
13195				animations: {},
13196				nodes: {}
13197			};
13198
13199			output.metadata = {
13200				version: 4.7,
13201				type: 'Object',
13202				generator: 'Object3D.toJSON'
13203			};
13204
13205		}
13206
13207		// standard Object3D serialization
13208
13209		const object = {};
13210
13211		object.uuid = this.uuid;
13212		object.type = this.type;
13213
13214		object.name = this.name;
13215		object.castShadow = this.castShadow;
13216		object.receiveShadow = this.receiveShadow;
13217		object.visible = this.visible;
13218		object.frustumCulled = this.frustumCulled;
13219		object.renderOrder = this.renderOrder;
13220		object.static = this.static;
13221		object.matrixAutoUpdate = this.matrixAutoUpdate;
13222
13223		if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData;
13224
13225		object.layers = this.layers.mask;
13226		object.matrix = this.matrix.toArray();
13227		object.up = this.up.toArray();
13228
13229		if ( this.pivot !== null ) object.pivot = this.pivot.toArray();
13230
13231		if ( this.morphTargetDictionary !== undefined ) object.morphTargetDictionary = Object.assign( {}, this.morphTargetDictionary );
13232		if ( this.morphTargetInfluences !== undefined ) object.morphTargetInfluences = this.morphTargetInfluences.slice();
13233
13234		// object specific properties
13235
13236		if ( this.isInstancedMesh ) {
13237
13238			object.type = 'InstancedMesh';
13239			object.count = this.count;
13240			object.instanceMatrix = this.instanceMatrix.toJSON();
13241			if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON();
13242
13243		}
13244
13245		if ( this.isBatchedMesh ) {
13246
13247			object.type = 'BatchedMesh';
13248			object.perObjectFrustumCulled = this.perObjectFrustumCulled;
13249			object.sortObjects = this.sortObjects;
13250
13251			object.drawRanges = this._drawRanges;
13252			object.reservedRanges = this._reservedRanges;
13253
13254			object.geometryInfo = this._geometryInfo.map( info => ( {
13255				...info,
13256				boundingBox: info.boundingBox ? info.boundingBox.toJSON() : undefined,
13257				boundingSphere: info.boundingSphere ? info.boundingSphere.toJSON() : undefined
13258			} ) );
13259			object.instanceInfo = this._instanceInfo.map( info => ( { ...info } ) );
13260
13261			object.availableInstanceIds = this._availableInstanceIds.slice();
13262			object.availableGeometryIds = this._availableGeometryIds.slice();
13263
13264			object.nextIndexStart = this._nextIndexStart;
13265			object.nextVertexStart = this._nextVertexStart;
13266			object.geometryCount = this._geometryCount;
13267
13268			object.maxInstanceCount = this._maxInstanceCount;
13269			object.maxVertexCount = this._maxVertexCount;
13270			object.maxIndexCount = this._maxIndexCount;
13271
13272			object.geometryInitialized = this._geometryInitialized;
13273
13274			object.matricesTexture = this._matricesTexture.toJSON( meta );
13275
13276			object.indirectTexture = this._indirectTexture.toJSON( meta );
13277
13278			if ( this._colorsTexture !== null ) {
13279
13280				object.colorsTexture = this._colorsTexture.toJSON( meta );
13281
13282			}
13283
13284			if ( this.boundingSphere !== null ) {
13285
13286				object.boundingSphere = this.boundingSphere.toJSON();
13287
13288			}
13289
13290			if ( this.boundingBox !== null ) {
13291
13292				object.boundingBox = this.boundingBox.toJSON();
13293
13294			}
13295
13296		}
13297
13298		//
13299
13300		function serialize( library, element ) {
13301
13302			if ( library[ element.uuid ] === undefined ) {
13303
13304				library[ element.uuid ] = element.toJSON( meta );
13305
13306			}
13307
13308			return element.uuid;
13309
13310		}
13311
13312		if ( this.isScene ) {
13313
13314			if ( this.background ) {
13315
13316				if ( this.background.isColor ) {
13317
13318					object.background = this.background.toJSON();
13319
13320				} else if ( this.background.isTexture ) {
13321
13322					object.background = this.background.toJSON( meta ).uuid;
13323
13324				}
13325
13326			}
13327
13328			if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) {
13329
13330				object.environment = this.environment.toJSON( meta ).uuid;
13331
13332			}
13333
13334		} else if ( this.isMesh || this.isLine || this.isPoints ) {
13335
13336			object.geometry = serialize( meta.geometries, this.geometry );
13337
13338			const parameters = this.geometry.parameters;
13339
13340			if ( parameters !== undefined && parameters.shapes !== undefined ) {
13341
13342				const shapes = parameters.shapes;
13343
13344				if ( Array.isArray( shapes ) ) {
13345
13346					for ( let i = 0, l = shapes.length; i < l; i ++ ) {
13347
13348						const shape = shapes[ i ];
13349
13350						serialize( meta.shapes, shape );
13351
13352					}
13353
13354				} else {
13355
13356					serialize( meta.shapes, shapes );
13357
13358				}
13359
13360			}
13361
13362		}
13363
13364		if ( this.isSkinnedMesh ) {
13365
13366			object.bindMode = this.bindMode;
13367			object.bindMatrix = this.bindMatrix.toArray();
13368
13369			if ( this.skeleton !== undefined ) {
13370
13371				serialize( meta.skeletons, this.skeleton );
13372
13373				object.skeleton = this.skeleton.uuid;
13374
13375			}
13376
13377		}
13378
13379		if ( this.material !== undefined ) {
13380
13381			if ( Array.isArray( this.material ) ) {
13382
13383				const uuids = [];
13384
13385				for ( let i = 0, l = this.material.length; i < l; i ++ ) {
13386
13387					uuids.push( serialize( meta.materials, this.material[ i ] ) );
13388
13389				}
13390
13391				object.material = uuids;
13392
13393			} else {
13394
13395				object.material = serialize( meta.materials, this.material );
13396
13397			}
13398
13399		}
13400
13401		//
13402
13403		if ( this.children.length > 0 ) {
13404
13405			object.children = [];
13406
13407			for ( let i = 0; i < this.children.length; i ++ ) {
13408
13409				object.children.push( this.children[ i ].toJSON( meta ).object );
13410
13411			}
13412
13413		}
13414
13415		//
13416
13417		if ( this.animations.length > 0 ) {
13418
13419			object.animations = [];
13420
13421			for ( let i = 0; i < this.animations.length; i ++ ) {
13422
13423				const animation = this.animations[ i ];
13424
13425				object.animations.push( serialize( meta.animations, animation ) );
13426
13427			}
13428
13429		}
13430
13431		if ( isRootObject ) {
13432
13433			const geometries = extractFromCache( meta.geometries );
13434			const materials = extractFromCache( meta.materials );
13435			const textures = extractFromCache( meta.textures );
13436			const images = extractFromCache( meta.images );
13437			const shapes = extractFromCache( meta.shapes );
13438			const skeletons = extractFromCache( meta.skeletons );
13439			const animations = extractFromCache( meta.animations );
13440			const nodes = extractFromCache( meta.nodes );
13441
13442			if ( geometries.length > 0 ) output.geometries = geometries;
13443			if ( materials.length > 0 ) output.materials = materials;
13444			if ( textures.length > 0 ) output.textures = textures;
13445			if ( images.length > 0 ) output.images = images;
13446			if ( shapes.length > 0 ) output.shapes = shapes;
13447			if ( skeletons.length > 0 ) output.skeletons = skeletons;
13448			if ( animations.length > 0 ) output.animations = animations;
13449			if ( nodes.length > 0 ) output.nodes = nodes;
13450
13451		}
13452
13453		output.object = object;
13454
13455		return output;
13456
13457		// extract data from the cache hash
13458		// remove metadata on each item
13459		// and return as array
13460		function extractFromCache( cache ) {
13461
13462			const values = [];
13463			for ( const key in cache ) {
13464
13465				const data = cache[ key ];
13466				delete data.metadata;
13467				values.push( data );
13468
13469			}
13470
13471			return values;
13472
13473		}
13474
13475	}
13476
13477	/**
13478	 * Returns a new 3D object with copied values from this instance.
13479	 *
13480	 * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are also cloned.
13481	 * @return {Object3D} A clone of this instance.
13482	 */
13483	clone( recursive ) {
13484
13485		return new this.constructor().copy( this, recursive );
13486
13487	}
13488
13489	/**
13490	 * Copies the values of the given 3D object to this instance.
13491	 *
13492	 * @param {Object3D} source - The 3D object to copy.
13493	 * @param {boolean} [recursive=true] - When set to `true`, descendants of the 3D object are cloned.
13494	 * @return {Object3D} A reference to this instance.
13495	 */
13496	copy( source, recursive = true ) {
13497
13498		this.name = source.name;
13499
13500		this.up.copy( source.up );
13501
13502		this.position.copy( source.position );
13503		this.rotation.order = source.rotation.order;
13504		this.quaternion.copy( source.quaternion );
13505		this.scale.copy( source.scale );
13506
13507		this.pivot = ( source.pivot !== null ) ? source.pivot.clone() : null;
13508
13509		this.matrix.copy( source.matrix );
13510		this.matrixWorld.copy( source.matrixWorld );
13511
13512		this.matrixAutoUpdate = source.matrixAutoUpdate;
13513
13514		this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
13515		this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
13516
13517		this.layers.mask = source.layers.mask;
13518		this.visible = source.visible;
13519
13520		this.castShadow = source.castShadow;
13521		this.receiveShadow = source.receiveShadow;
13522
13523		this.frustumCulled = source.frustumCulled;
13524		this.renderOrder = source.renderOrder;
13525
13526		this.static = source.static;
13527
13528		this.animations = source.animations.slice();
13529
13530		this.userData = JSON.parse( JSON.stringify( source.userData ) );
13531
13532		if ( recursive === true ) {
13533
13534			for ( let i = 0; i < source.children.length; i ++ ) {
13535
13536				const child = source.children[ i ];
13537				this.add( child.clone() );
13538
13539			}
13540
13541		}
13542
13543		return this;
13544
13545	}
13546
13547	/**
13548	 * Frees the GPU-related resources allocated by this instance. Call this
13549	 * method whenever this instance is no longer used in your app.
13550	 *
13551	 * Geometries, materials and textures are potentially shared with other
13552	 * 3D objects and must be disposed of separately.
13553	 *
13554	 * @fires Object3D#dispose
13555	 */
13556	dispose() {
13557
13558		/**
13559		 * Fires when the 3D object has been disposed of.
13560		 *
13561		 * @event Object3D#dispose
13562		 * @type {Object}
13563		 */
13564		this.dispatchEvent( { type: 'dispose' } );
13565
13566	}
13567
13568}
13569
13570/**
13571 * The default up direction for objects, also used as the default
13572 * position for {@link DirectionalLight} and {@link HemisphereLight}.
13573 *
13574 * @static
13575 * @type {Vector3}
13576 * @default (0,1,0)
13577 */
13578Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 );
13579
13580/**
13581 * The default setting for {@link Object3D#matrixAutoUpdate} for
13582 * newly created 3D objects.
13583 *
13584 * @static
13585 * @type {boolean}
13586 * @default true
13587 */
13588Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true;
13589
13590/**
13591 * The default setting for {@link Object3D#matrixWorldAutoUpdate} for
13592 * newly created 3D objects.
13593 *
13594 * @static
13595 * @type {boolean}
13596 * @default true
13597 */
13598Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true;
13599
13600/**
13601 * This is almost identical to an {@link Object3D}. Its purpose is to
13602 * make working with groups of objects syntactically clearer.
13603 *
13604 * ```js
13605 * // Create a group and add the two cubes.
13606 * // These cubes can now be rotated / scaled etc as a group.
13607 * const group = new THREE.Group();
13608 *
13609 * group.add( meshA );
13610 * group.add( meshB );
13611 *
13612 * scene.add( group );
13613 * ```
13614 *
13615 * @augments Object3D
13616 */
13617class Group extends Object3D {
13618
13619	constructor() {
13620
13621		super();
13622
13623		/**
13624		 * This flag can be used for type testing.
13625		 *
13626		 * @type {boolean}
13627		 * @readonly
13628		 * @default true
13629		 */
13630		this.isGroup = true;
13631
13632		this.type = 'Group';
13633
13634	}
13635
13636}
13637
13638const _moveEvent = { type: 'move' };
13639
13640/**
13641 * Class for representing a XR controller with its
13642 * different coordinate systems.
13643 *
13644 * @private
13645 */
13646class WebXRController {
13647
13648	/**
13649	 * Constructs a new XR controller.
13650	 */
13651	constructor() {
13652
13653		/**
13654		 * A group representing the target ray space
13655		 * of the XR controller.
13656		 *
13657		 * @private
13658		 * @type {?Group}
13659		 * @default null
13660		 */
13661		this._targetRay = null;
13662
13663		/**
13664		 * A group representing the grip space
13665		 * of the XR controller.
13666		 *
13667		 * @private
13668		 * @type {?Group}
13669		 * @default null
13670		 */
13671		this._grip = null;
13672
13673		/**
13674		 * A group representing the hand space
13675		 * of the XR controller.
13676		 *
13677		 * @private
13678		 * @type {?Group}
13679		 * @default null
13680		 */
13681		this._hand = null;
13682
13683	}
13684
13685	/**
13686	 * Returns a group representing the hand space of the XR controller.
13687	 *
13688	 * @return {Group} A group representing the hand space of the XR controller.
13689	 */
13690	getHandSpace() {
13691
13692		if ( this._hand === null ) {
13693
13694			this._hand = new Group();
13695			this._hand.matrixAutoUpdate = false;
13696			this._hand.visible = false;
13697
13698			this._hand.joints = {};
13699			this._hand.inputState = { pinching: false };
13700
13701		}
13702
13703		return this._hand;
13704
13705	}
13706
13707	/**
13708	 * Returns a group representing the target ray space of the XR controller.
13709	 *
13710	 * @return {Group} A group representing the target ray space of the XR controller.
13711	 */
13712	getTargetRaySpace() {
13713
13714		if ( this._targetRay === null ) {
13715
13716			this._targetRay = new Group();
13717			this._targetRay.matrixAutoUpdate = false;
13718			this._targetRay.visible = false;
13719			this._targetRay.hasLinearVelocity = false;
13720			this._targetRay.linearVelocity = new Vector3();
13721			this._targetRay.hasAngularVelocity = false;
13722			this._targetRay.angularVelocity = new Vector3();
13723
13724		}
13725
13726		return this._targetRay;
13727
13728	}
13729
13730	/**
13731	 * Returns a group representing the grip space of the XR controller.
13732	 *
13733	 * @return {Group} A group representing the grip space of the XR controller.
13734	 */
13735	getGripSpace() {
13736
13737		if ( this._grip === null ) {
13738
13739			this._grip = new Group();
13740			this._grip.matrixAutoUpdate = false;
13741			this._grip.visible = false;
13742			this._grip.hasLinearVelocity = false;
13743			this._grip.linearVelocity = new Vector3();
13744			this._grip.hasAngularVelocity = false;
13745			this._grip.angularVelocity = new Vector3();
13746			this._grip.eventsEnabled = false;
13747
13748		}
13749
13750		return this._grip;
13751
13752	}
13753
13754	/**
13755	 * Dispatches the given event to the groups representing
13756	 * the different coordinate spaces of the XR controller.
13757	 *
13758	 * @param {Object} event - The event to dispatch.
13759	 * @return {WebXRController} A reference to this instance.
13760	 */
13761	dispatchEvent( event ) {
13762
13763		if ( this._targetRay !== null ) {
13764
13765			this._targetRay.dispatchEvent( event );
13766
13767		}
13768
13769		if ( this._grip !== null ) {
13770
13771			this._grip.dispatchEvent( event );
13772
13773		}
13774
13775		if ( this._hand !== null ) {
13776
13777			this._hand.dispatchEvent( event );
13778
13779		}
13780
13781		return this;
13782
13783	}
13784
13785	/**
13786	 * Connects the controller with the given XR input source.
13787	 *
13788	 * @param {XRInputSource} inputSource - The input source.
13789	 * @return {WebXRController} A reference to this instance.
13790	 */
13791	connect( inputSource ) {
13792
13793		if ( inputSource && inputSource.hand ) {
13794
13795			const hand = this._hand;
13796
13797			if ( hand ) {
13798
13799				for ( const inputjoint of inputSource.hand.values() ) {
13800
13801					// Initialize hand with joints when connected
13802					this._getHandJoint( hand, inputjoint );
13803
13804				}
13805
13806			}
13807
13808		}
13809
13810		this.dispatchEvent( { type: 'connected', data: inputSource } );
13811
13812		return this;
13813
13814	}
13815
13816	/**
13817	 * Disconnects the controller from the given XR input source.
13818	 *
13819	 * @param {XRInputSource} inputSource - The input source.
13820	 * @return {WebXRController} A reference to this instance.
13821	 */
13822	disconnect( inputSource ) {
13823
13824		this.dispatchEvent( { type: 'disconnected', data: inputSource } );
13825
13826		if ( this._targetRay !== null ) {
13827
13828			this._targetRay.visible = false;
13829
13830		}
13831
13832		if ( this._grip !== null ) {
13833
13834			this._grip.visible = false;
13835
13836		}
13837
13838		if ( this._hand !== null ) {
13839
13840			this._hand.visible = false;
13841
13842		}
13843
13844		return this;
13845
13846	}
13847
13848	/**
13849	 * Updates the controller with the given input source, XR frame and reference space.
13850	 * This updates the transformations of the groups that represent the different
13851	 * coordinate systems of the controller.
13852	 *
13853	 * @param {XRInputSource} inputSource - The input source.
13854	 * @param {XRFrame} frame - The XR frame.
13855	 * @param {XRReferenceSpace} referenceSpace - The reference space.
13856	 * @return {WebXRController} A reference to this instance.
13857	 */
13858	update( inputSource, frame, referenceSpace ) {
13859
13860		let inputPose = null;
13861		let gripPose = null;
13862		let handPose = null;
13863
13864		const targetRay = this._targetRay;
13865		const grip = this._grip;
13866		const hand = this._hand;
13867
13868		if ( inputSource && frame.session.visibilityState !== 'visible-blurred' ) {
13869
13870			if ( hand && inputSource.hand ) {
13871
13872				handPose = true;
13873
13874				for ( const inputjoint of inputSource.hand.values() ) {
13875
13876					// Update the joints groups with the XRJoint poses
13877					const jointPose = frame.getJointPose( inputjoint, referenceSpace );
13878
13879					// The transform of this joint will be updated with the joint pose on each frame
13880					const joint = this._getHandJoint( hand, inputjoint );
13881
13882					if ( jointPose !== null ) {
13883
13884						joint.matrix.fromArray( jointPose.transform.matrix );
13885						joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
13886						joint.matrixWorldNeedsUpdate = true;
13887						joint.jointRadius = jointPose.radius;
13888
13889					}
13890
13891					joint.visible = jointPose !== null;
13892
13893				}
13894
13895				// Custom events
13896
13897				// Check pinchz
13898				const indexTip = hand.joints[ 'index-finger-tip' ];
13899				const thumbTip = hand.joints[ 'thumb-tip' ];
13900				const distance = indexTip.position.distanceTo( thumbTip.position );
13901
13902				const distanceToPinch = 0.02;
13903				const threshold = 0.005;
13904
13905				if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
13906
13907					hand.inputState.pinching = false;
13908					this.dispatchEvent( {
13909						type: 'pinchend',
13910						handedness: inputSource.handedness,
13911						target: this
13912					} );
13913
13914				} else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
13915
13916					hand.inputState.pinching = true;
13917					this.dispatchEvent( {
13918						type: 'pinchstart',
13919						handedness: inputSource.handedness,
13920						target: this
13921					} );
13922
13923				}
13924
13925			} else {
13926
13927				if ( grip !== null && inputSource.gripSpace ) {
13928
13929					gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
13930
13931					if ( gripPose !== null ) {
13932
13933						grip.matrix.fromArray( gripPose.transform.matrix );
13934						grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
13935						grip.matrixWorldNeedsUpdate = true;
13936
13937						if ( gripPose.linearVelocity ) {
13938
13939							grip.hasLinearVelocity = true;
13940							grip.linearVelocity.copy( gripPose.linearVelocity );
13941
13942						} else {
13943
13944							grip.hasLinearVelocity = false;
13945
13946						}
13947
13948						if ( gripPose.angularVelocity ) {
13949
13950							grip.hasAngularVelocity = true;
13951							grip.angularVelocity.copy( gripPose.angularVelocity );
13952
13953						} else {
13954
13955							grip.hasAngularVelocity = false;
13956
13957						}
13958
13959						// grip update event if enabled
13960						if ( grip.eventsEnabled ) {
13961
13962							grip.dispatchEvent( {
13963								type: 'gripUpdated',
13964								data: inputSource,
13965								target: this
13966							} );
13967
13968						}
13969
13970					}
13971
13972				}
13973
13974			}
13975
13976			if ( targetRay !== null ) {
13977
13978				inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
13979
13980				// Some runtimes (namely Vive Cosmos with Vive OpenXR Runtime) have only grip space and ray space is equal to it
13981				if ( inputPose === null && gripPose !== null ) {
13982
13983					inputPose = gripPose;
13984
13985				}
13986
13987				if ( inputPose !== null ) {
13988
13989					targetRay.matrix.fromArray( inputPose.transform.matrix );
13990					targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
13991					targetRay.matrixWorldNeedsUpdate = true;
13992
13993					if ( inputPose.linearVelocity ) {
13994
13995						targetRay.hasLinearVelocity = true;
13996						targetRay.linearVelocity.copy( inputPose.linearVelocity );
13997
13998					} else {
13999
14000						targetRay.hasLinearVelocity = false;
14001
14002					}
14003
14004					if ( inputPose.angularVelocity ) {
14005
14006						targetRay.hasAngularVelocity = true;
14007						targetRay.angularVelocity.copy( inputPose.angularVelocity );
14008
14009					} else {
14010
14011						targetRay.hasAngularVelocity = false;
14012
14013					}
14014
14015					this.dispatchEvent( _moveEvent );
14016
14017				}
14018
14019			}
14020
14021
14022		}
14023
14024		if ( targetRay !== null ) {
14025
14026			targetRay.visible = ( inputPose !== null );
14027
14028		}
14029
14030		if ( grip !== null ) {
14031
14032			grip.visible = ( gripPose !== null );
14033
14034		}
14035
14036		if ( hand !== null ) {
14037
14038			hand.visible = ( handPose !== null );
14039
14040		}
14041
14042		return this;
14043
14044	}
14045
14046	/**
14047	 * Returns a group representing the hand joint for the given input joint.
14048	 *
14049	 * @private
14050	 * @param {Group} hand - The group representing the hand space.
14051	 * @param {XRJointSpace} inputjoint - The hand joint data.
14052	 * @return {Group} A group representing the hand joint for the given input joint.
14053	 */
14054	_getHandJoint( hand, inputjoint ) {
14055
14056		if ( hand.joints[ inputjoint.jointName ] === undefined ) {
14057
14058			const joint = new Group();
14059			joint.matrixAutoUpdate = false;
14060			joint.visible = false;
14061			hand.joints[ inputjoint.jointName ] = joint;
14062
14063			hand.add( joint );
14064
14065		}
14066
14067		return hand.joints[ inputjoint.jointName ];
14068
14069	}
14070
14071}
14072
14073const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,
14074	'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,
14075	'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,
14076	'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,
14077	'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,
14078	'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,
14079	'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,
14080	'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,
14081	'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,
14082	'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,
14083	'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,
14084	'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,
14085	'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,
14086	'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,
14087	'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,
14088	'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,
14089	'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,
14090	'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,
14091	'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,
14092	'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,
14093	'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,
14094	'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,
14095	'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,
14096	'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };
14097
14098const _hslA = { h: 0, s: 0, l: 0 };
14099const _hslB = { h: 0, s: 0, l: 0 };
14100
14101function hue2rgb( p, q, t ) {
14102
14103	if ( t < 0 ) t += 1;
14104	if ( t > 1 ) t -= 1;
14105	if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
14106	if ( t < 1 / 2 ) return q;
14107	if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
14108	return p;
14109
14110}
14111
14112/**
14113 * A Color instance is represented by RGB components in the linear <i>working
14114 * color space</i>, which defaults to `LinearSRGBColorSpace`. Inputs
14115 * conventionally using `SRGBColorSpace` (such as hexadecimals and CSS
14116 * strings) are converted to the working color space automatically.
14117 *
14118 * ```js
14119 * // converted automatically from SRGBColorSpace to LinearSRGBColorSpace
14120 * const color = new THREE.Color().setHex( 0x112233 );
14121 * ```
14122 * Source color spaces may be specified explicitly, to ensure correct conversions.
14123 * ```js
14124 * // assumed already LinearSRGBColorSpace; no conversion
14125 * const color = new THREE.Color().setRGB( 0.5, 0.5, 0.5 );
14126 *
14127 * // converted explicitly from SRGBColorSpace to LinearSRGBColorSpace
14128 * const color = new THREE.Color().setRGB( 0.5, 0.5, 0.5, SRGBColorSpace );
14129 * ```
14130 * If THREE.ColorManagement is disabled, no conversions occur. For details,
14131 * see <i>Color management</i>. Iterating through a Color instance will yield
14132 * its components (r, g, b) in the corresponding order. A Color can be initialised
14133 * in any of the following ways:
14134 * ```js
14135 * //empty constructor - will default white
14136 * const color1 = new THREE.Color();
14137 *
14138 * //Hexadecimal color (recommended)
14139 * const color2 = new THREE.Color( 0xff0000 );
14140 *
14141 * //RGB string
14142 * const color3 = new THREE.Color("rgb(255, 0, 0)");
14143 * const color4 = new THREE.Color("rgb(100%, 0%, 0%)");
14144 *
14145 * //X11 color name - all 140 color names are supported.
14146 * //Note the lack of CamelCase in the name
14147 * const color5 = new THREE.Color( 'skyblue' );
14148 * //HSL string
14149 * const color6 = new THREE.Color("hsl(0, 100%, 50%)");
14150 *
14151 * //Separate RGB values between 0 and 1
14152 * const color7 = new THREE.Color( 1, 0, 0 );
14153 * ```
14154 */
14155class Color {
14156
14157	/**
14158	 * Constructs a new color.
14159	 *
14160	 * Note that standard method of specifying color in three.js is with a hexadecimal triplet,
14161	 * and that method is used throughout the rest of the documentation.
14162	 *
14163	 * @param {(number|string|Color)} [r] - The red component of the color. If `g` and `b` are
14164	 * not provided, it can be hexadecimal triplet, a CSS-style string or another `Color` instance.
14165	 * @param {number} [g] - The green component.
14166	 * @param {number} [b] - The blue component.
14167	 */
14168	constructor( r, g, b ) {
14169
14170		/**
14171		 * This flag can be used for type testing.
14172		 *
14173		 * @type {boolean}
14174		 * @readonly
14175		 * @default true
14176		 */
14177		this.isColor = true;
14178
14179		/**
14180		 * The red component.
14181		 *
14182		 * @type {number}
14183		 * @default 1
14184		 */
14185		this.r = 1;
14186
14187		/**
14188		 * The green component.
14189		 *
14190		 * @type {number}
14191		 * @default 1
14192		 */
14193		this.g = 1;
14194
14195		/**
14196		 * The blue component.
14197		 *
14198		 * @type {number}
14199		 * @default 1
14200		 */
14201		this.b = 1;
14202
14203		return this.set( r, g, b );
14204
14205	}
14206
14207	/**
14208	 * Sets the colors's components from the given values.
14209	 *
14210	 * @param {(number|string|Color)} [r] - The red component of the color. If `g` and `b` are
14211	 * not provided, it can be hexadecimal triplet, a CSS-style string or another `Color` instance.
14212	 * @param {number} [g] - The green component.
14213	 * @param {number} [b] - The blue component.
14214	 * @return {Color} A reference to this color.
14215	 */
14216	set( r, g, b ) {
14217
14218		if ( g === undefined && b === undefined ) {
14219
14220			// r is THREE.Color, hex or string
14221
14222			const value = r;
14223
14224			if ( value && value.isColor ) {
14225
14226				this.copy( value );
14227
14228			} else if ( typeof value === 'number' ) {
14229
14230				this.setHex( value );
14231
14232			} else if ( typeof value === 'string' ) {
14233
14234				this.setStyle( value );
14235
14236			}
14237
14238		} else {
14239
14240			this.setRGB( r, g, b );
14241
14242		}
14243
14244		return this;
14245
14246	}
14247
14248	/**
14249	 * Sets the colors's components to the given scalar value.
14250	 *
14251	 * @param {number} scalar - The scalar value.
14252	 * @return {Color} A reference to this color.
14253	 */
14254	setScalar( scalar ) {
14255
14256		this.r = scalar;
14257		this.g = scalar;
14258		this.b = scalar;
14259
14260		return this;
14261
14262	}
14263
14264	/**
14265	 * Sets this color from a hexadecimal value.
14266	 *
14267	 * @param {number} hex - The hexadecimal value.
14268	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14269	 * @return {Color} A reference to this color.
14270	 */
14271	setHex( hex, colorSpace = SRGBColorSpace ) {
14272
14273		hex = Math.floor( hex );
14274
14275		this.r = ( hex >> 16 & 255 ) / 255;
14276		this.g = ( hex >> 8 & 255 ) / 255;
14277		this.b = ( hex & 255 ) / 255;
14278
14279		ColorManagement.colorSpaceToWorking( this, colorSpace );
14280
14281		return this;
14282
14283	}
14284
14285	/**
14286	 * Sets this color from RGB values.
14287	 *
14288	 * @param {number} r - Red channel value between `0.0` and `1.0`.
14289	 * @param {number} g - Green channel value between `0.0` and `1.0`.
14290	 * @param {number} b - Blue channel value between `0.0` and `1.0`.
14291	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14292	 * @return {Color} A reference to this color.
14293	 */
14294	setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) {
14295
14296		this.r = r;
14297		this.g = g;
14298		this.b = b;
14299
14300		ColorManagement.colorSpaceToWorking( this, colorSpace );
14301
14302		return this;
14303
14304	}
14305
14306	/**
14307	 * Sets this color from RGB values.
14308	 *
14309	 * @param {number} h - Hue value between `0.0` and `1.0`.
14310	 * @param {number} s - Saturation value between `0.0` and `1.0`.
14311	 * @param {number} l - Lightness value between `0.0` and `1.0`.
14312	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14313	 * @return {Color} A reference to this color.
14314	 */
14315	setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) {
14316
14317		// h,s,l ranges are in 0.0 - 1.0
14318		h = euclideanModulo( h, 1 );
14319		s = clamp( s, 0, 1 );
14320		l = clamp( l, 0, 1 );
14321
14322		if ( s === 0 ) {
14323
14324			this.r = this.g = this.b = l;
14325
14326		} else {
14327
14328			const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
14329			const q = ( 2 * l ) - p;
14330
14331			this.r = hue2rgb( q, p, h + 1 / 3 );
14332			this.g = hue2rgb( q, p, h );
14333			this.b = hue2rgb( q, p, h - 1 / 3 );
14334
14335		}
14336
14337		ColorManagement.colorSpaceToWorking( this, colorSpace );
14338
14339		return this;
14340
14341	}
14342
14343	/**
14344	 * Sets this color from a CSS-style string. For example, `rgb(250, 0,0)`,
14345	 * `rgb(100%, 0%, 0%)`, `hsl(0, 100%, 50%)`, `#ff0000`, `#f00`, or `red` ( or
14346	 * any [X11 color name](https://en.wikipedia.org/wiki/X11_color_names#Color_name_chart) -
14347	 * all 140 color names are supported).
14348	 *
14349	 * @param {string} style - Color as a CSS-style string.
14350	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14351	 * @return {Color} A reference to this color.
14352	 */
14353	setStyle( style, colorSpace = SRGBColorSpace ) {
14354
14355		function handleAlpha( string ) {
14356
14357			if ( string === undefined ) return;
14358
14359			if ( parseFloat( string ) < 1 ) {
14360
14361				warn( 'Color: Alpha component of ' + style + ' will be ignored.' );
14362
14363			}
14364
14365		}
14366
14367
14368		let m;
14369
14370		if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) {
14371
14372			// rgb / hsl
14373
14374			let color;
14375			const name = m[ 1 ];
14376			const components = m[ 2 ];
14377
14378			switch ( name ) {
14379
14380				case 'rgb':
14381				case 'rgba':
14382
14383					if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
14384
14385						// rgb(255,0,0) rgba(255,0,0,0.5)
14386
14387						handleAlpha( color[ 4 ] );
14388
14389						return this.setRGB(
14390							Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255,
14391							Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255,
14392							Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255,
14393							colorSpace
14394						);
14395
14396					}
14397
14398					if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
14399
14400						// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)
14401
14402						handleAlpha( color[ 4 ] );
14403
14404						return this.setRGB(
14405							Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100,
14406							Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100,
14407							Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100,
14408							colorSpace
14409						);
14410
14411					}
14412
14413					break;
14414
14415				case 'hsl':
14416				case 'hsla':
14417
14418					if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) {
14419
14420						// hsl(120,50%,50%) hsla(120,50%,50%,0.5)
14421
14422						handleAlpha( color[ 4 ] );
14423
14424						return this.setHSL(
14425							parseFloat( color[ 1 ] ) / 360,
14426							parseFloat( color[ 2 ] ) / 100,
14427							parseFloat( color[ 3 ] ) / 100,
14428							colorSpace
14429						);
14430
14431					}
14432
14433					break;
14434
14435				default:
14436
14437					warn( 'Color: Unknown color model ' + style );
14438
14439			}
14440
14441		} else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) {
14442
14443			// hex color
14444
14445			const hex = m[ 1 ];
14446			const size = hex.length;
14447
14448			if ( size === 3 ) {
14449
14450				// #ff0
14451				return this.setRGB(
14452					parseInt( hex.charAt( 0 ), 16 ) / 15,
14453					parseInt( hex.charAt( 1 ), 16 ) / 15,
14454					parseInt( hex.charAt( 2 ), 16 ) / 15,
14455					colorSpace
14456				);
14457
14458			} else if ( size === 6 ) {
14459
14460				// #ff0000
14461				return this.setHex( parseInt( hex, 16 ), colorSpace );
14462
14463			} else {
14464
14465				warn( 'Color: Invalid hex color ' + style );
14466
14467			}
14468
14469		} else if ( style && style.length > 0 ) {
14470
14471			return this.setColorName( style, colorSpace );
14472
14473		}
14474
14475		return this;
14476
14477	}
14478
14479	/**
14480	 * Sets this color from a color name. Faster than {@link Color#setStyle} if
14481	 * you don't need the other CSS-style formats.
14482	 *
14483	 * For convenience, the list of names is exposed in `Color.NAMES` as a hash.
14484	 * ```js
14485	 * Color.NAMES.aliceblue // returns 0xF0F8FF
14486	 * ```
14487	 *
14488	 * @param {string} style - The color name.
14489	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14490	 * @return {Color} A reference to this color.
14491	 */
14492	setColorName( style, colorSpace = SRGBColorSpace ) {
14493
14494		// color keywords
14495		const hex = _colorKeywords[ style.toLowerCase() ];
14496
14497		if ( hex !== undefined ) {
14498
14499			// red
14500			this.setHex( hex, colorSpace );
14501
14502		} else {
14503
14504			// unknown color
14505			warn( 'Color: Unknown color ' + style );
14506
14507		}
14508
14509		return this;
14510
14511	}
14512
14513	/**
14514	 * Returns a new color with copied values from this instance.
14515	 *
14516	 * @return {Color} A clone of this instance.
14517	 */
14518	clone() {
14519
14520		return new this.constructor( this.r, this.g, this.b );
14521
14522	}
14523
14524	/**
14525	 * Copies the values of the given color to this instance.
14526	 *
14527	 * @param {Color} color - The color to copy.
14528	 * @return {Color} A reference to this color.
14529	 */
14530	copy( color ) {
14531
14532		this.r = color.r;
14533		this.g = color.g;
14534		this.b = color.b;
14535
14536		return this;
14537
14538	}
14539
14540	/**
14541	 * Copies the given color into this color, and then converts this color from
14542	 * `SRGBColorSpace` to `LinearSRGBColorSpace`.
14543	 *
14544	 * @param {Color} color - The color to copy/convert.
14545	 * @return {Color} A reference to this color.
14546	 */
14547	copySRGBToLinear( color ) {
14548
14549		this.r = SRGBToLinear( color.r );
14550		this.g = SRGBToLinear( color.g );
14551		this.b = SRGBToLinear( color.b );
14552
14553		return this;
14554
14555	}
14556
14557	/**
14558	 * Copies the given color into this color, and then converts this color from
14559	 * `LinearSRGBColorSpace` to `SRGBColorSpace`.
14560	 *
14561	 * @param {Color} color - The color to copy/convert.
14562	 * @return {Color} A reference to this color.
14563	 */
14564	copyLinearToSRGB( color ) {
14565
14566		this.r = LinearToSRGB( color.r );
14567		this.g = LinearToSRGB( color.g );
14568		this.b = LinearToSRGB( color.b );
14569
14570		return this;
14571
14572	}
14573
14574	/**
14575	 * Converts this color from `SRGBColorSpace` to `LinearSRGBColorSpace`.
14576	 *
14577	 * @return {Color} A reference to this color.
14578	 */
14579	convertSRGBToLinear() {
14580
14581		this.copySRGBToLinear( this );
14582
14583		return this;
14584
14585	}
14586
14587	/**
14588	 * Converts this color from `LinearSRGBColorSpace` to `SRGBColorSpace`.
14589	 *
14590	 * @return {Color} A reference to this color.
14591	 */
14592	convertLinearToSRGB() {
14593
14594		this.copyLinearToSRGB( this );
14595
14596		return this;
14597
14598	}
14599
14600	/**
14601	 * Returns the hexadecimal value of this color.
14602	 *
14603	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14604	 * @return {number} The hexadecimal value.
14605	 */
14606	getHex( colorSpace = SRGBColorSpace ) {
14607
14608		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14609
14610		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 ) );
14611
14612	}
14613
14614	/**
14615	 * Returns the hexadecimal value of this color as a string (for example, 'FFFFFF').
14616	 *
14617	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14618	 * @return {string} The hexadecimal value as a string.
14619	 */
14620	getHexString( colorSpace = SRGBColorSpace ) {
14621
14622		return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( -6 );
14623
14624	}
14625
14626	/**
14627	 * Converts the colors RGB values into the HSL format and stores them into the
14628	 * given target object.
14629	 *
14630	 * @param {{h:number,s:number,l:number}} target - The target object that is used to store the method's result.
14631	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14632	 * @return {{h:number,s:number,l:number}} The HSL representation of this color.
14633	 */
14634	getHSL( target, colorSpace = ColorManagement.workingColorSpace ) {
14635
14636		// h,s,l ranges are in 0.0 - 1.0
14637
14638		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14639
14640		const r = _color.r, g = _color.g, b = _color.b;
14641
14642		const max = Math.max( r, g, b );
14643		const min = Math.min( r, g, b );
14644
14645		let hue, saturation;
14646		const lightness = ( min + max ) / 2.0;
14647
14648		if ( min === max ) {
14649
14650			hue = 0;
14651			saturation = 0;
14652
14653		} else {
14654
14655			const delta = max - min;
14656
14657			saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
14658
14659			switch ( max ) {
14660
14661				case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
14662				case g: hue = ( b - r ) / delta + 2; break;
14663				case b: hue = ( r - g ) / delta + 4; break;
14664
14665			}
14666
14667			hue /= 6;
14668
14669		}
14670
14671		target.h = hue;
14672		target.s = saturation;
14673		target.l = lightness;
14674
14675		return target;
14676
14677	}
14678
14679	/**
14680	 * Returns the RGB values of this color and stores them into the given target object.
14681	 *
14682	 * @param {Color} target - The target color that is used to store the method's result.
14683	 * @param {string} [colorSpace=ColorManagement.workingColorSpace] - The color space.
14684	 * @return {Color} The RGB representation of this color.
14685	 */
14686	getRGB( target, colorSpace = ColorManagement.workingColorSpace ) {
14687
14688		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14689
14690		target.r = _color.r;
14691		target.g = _color.g;
14692		target.b = _color.b;
14693
14694		return target;
14695
14696	}
14697
14698	/**
14699	 * Returns the value of this color as a CSS style string. Example: `rgb(255,0,0)`.
14700	 *
14701	 * @param {string} [colorSpace=SRGBColorSpace] - The color space.
14702	 * @return {string} The CSS representation of this color.
14703	 */
14704	getStyle( colorSpace = SRGBColorSpace ) {
14705
14706		ColorManagement.workingToColorSpace( _color.copy( this ), colorSpace );
14707
14708		const r = _color.r, g = _color.g, b = _color.b;
14709
14710		if ( colorSpace !== SRGBColorSpace ) {
14711
14712			// Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/).
14713			return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`;
14714
14715		}
14716
14717		return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`;
14718
14719	}
14720
14721	/**
14722	 * Adds the given HSL values to this color's values.
14723	 * Internally, this converts the color's RGB values to HSL, adds HSL
14724	 * and then converts the color back to RGB.
14725	 *
14726	 * @param {number} h - Hue value between `0.0` and `1.0`.
14727	 * @param {number} s - Saturation value between `0.0` and `1.0`.
14728	 * @param {number} l - Lightness value between `0.0` and `1.0`.
14729	 * @return {Color} A reference to this color.
14730	 */
14731	offsetHSL( h, s, l ) {
14732
14733		this.getHSL( _hslA );
14734
14735		return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l );
14736
14737	}
14738
14739	/**
14740	 * Adds the RGB values of the given color to the RGB values of this color.
14741	 *
14742	 * @param {Color} color - The color to add.
14743	 * @return {Color} A reference to this color.
14744	 */
14745	add( color ) {
14746
14747		this.r += color.r;
14748		this.g += color.g;
14749		this.b += color.b;
14750
14751		return this;
14752
14753	}
14754
14755	/**
14756	 * Adds the RGB values of the given colors and stores the result in this instance.
14757	 *
14758	 * @param {Color} color1 - The first color.
14759	 * @param {Color} color2 - The second color.
14760	 * @return {Color} A reference to this color.
14761	 */
14762	addColors( color1, color2 ) {
14763
14764		this.r = color1.r + color2.r;
14765		this.g = color1.g + color2.g;
14766		this.b = color1.b + color2.b;
14767
14768		return this;
14769
14770	}
14771
14772	/**
14773	 * Adds the given scalar value to the RGB values of this color.
14774	 *
14775	 * @param {number} s - The scalar to add.
14776	 * @return {Color} A reference to this color.
14777	 */
14778	addScalar( s ) {
14779
14780		this.r += s;
14781		this.g += s;
14782		this.b += s;
14783
14784		return this;
14785
14786	}
14787
14788	/**
14789	 * Subtracts the RGB values of the given color from the RGB values of this color.
14790	 *
14791	 * @param {Color} color - The color to subtract.
14792	 * @return {Color} A reference to this color.
14793	 */
14794	sub( color ) {
14795
14796		this.r = Math.max( 0, this.r - color.r );
14797		this.g = Math.max( 0, this.g - color.g );
14798		this.b = Math.max( 0, this.b - color.b );
14799
14800		return this;
14801
14802	}
14803
14804	/**
14805	 * Multiplies the RGB values of the given color with the RGB values of this color.
14806	 *
14807	 * @param {Color} color - The color to multiply.
14808	 * @return {Color} A reference to this color.
14809	 */
14810	multiply( color ) {
14811
14812		this.r *= color.r;
14813		this.g *= color.g;
14814		this.b *= color.b;
14815
14816		return this;
14817
14818	}
14819
14820	/**
14821	 * Multiplies the given scalar value with the RGB values of this color.
14822	 *
14823	 * @param {number} s - The scalar to multiply.
14824	 * @return {Color} A reference to this color.
14825	 */
14826	multiplyScalar( s ) {
14827
14828		this.r *= s;
14829		this.g *= s;
14830		this.b *= s;
14831
14832		return this;
14833
14834	}
14835
14836	/**
14837	 * Linearly interpolates this color's RGB values toward the RGB values of the
14838	 * given color. The alpha argument can be thought of as the ratio between
14839	 * the two colors, where `0.0` is this color and `1.0` is the first argument.
14840	 *
14841	 * @param {Color} color - The color to converge on.
14842	 * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.
14843	 * @return {Color} A reference to this color.
14844	 */
14845	lerp( color, alpha ) {
14846
14847		this.r += ( color.r - this.r ) * alpha;
14848		this.g += ( color.g - this.g ) * alpha;
14849		this.b += ( color.b - this.b ) * alpha;
14850
14851		return this;
14852
14853	}
14854
14855	/**
14856	 * Linearly interpolates between the given colors and stores the result in this instance.
14857	 * The alpha argument can be thought of as the ratio between the two colors, where `0.0`
14858	 * is the first and `1.0` is the second color.
14859	 *
14860	 * @param {Color} color1 - The first color.
14861	 * @param {Color} color2 - The second color.
14862	 * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.
14863	 * @return {Color} A reference to this color.
14864	 */
14865	lerpColors( color1, color2, alpha ) {
14866
14867		this.r = color1.r + ( color2.r - color1.r ) * alpha;
14868		this.g = color1.g + ( color2.g - color1.g ) * alpha;
14869		this.b = color1.b + ( color2.b - color1.b ) * alpha;
14870
14871		return this;
14872
14873	}
14874
14875	/**
14876	 * Linearly interpolates this color's HSL values toward the HSL values of the
14877	 * given color. It differs from {@link Color#lerp} by not interpolating straight
14878	 * from one color to the other, but instead going through all the hues in between
14879	 * those two colors. The alpha argument can be thought of as the ratio between
14880	 * the two colors, where 0.0 is this color and 1.0 is the first argument.
14881	 *
14882	 * @param {Color} color - The color to converge on.
14883	 * @param {number} alpha - The interpolation factor in the closed interval `[0,1]`.
14884	 * @return {Color} A reference to this color.
14885	 */
14886	lerpHSL( color, alpha ) {
14887
14888		this.getHSL( _hslA );
14889		color.getHSL( _hslB );
14890
14891		const h = lerp( _hslA.h, _hslB.h, alpha );
14892		const s = lerp( _hslA.s, _hslB.s, alpha );
14893		const l = lerp( _hslA.l, _hslB.l, alpha );
14894
14895		this.setHSL( h, s, l );
14896
14897		return this;
14898
14899	}
14900
14901	/**
14902	 * Sets the color's RGB components from the given 3D vector.
14903	 *
14904	 * @param {Vector3} v - The vector to set.
14905	 * @return {Color} A reference to this color.
14906	 */
14907	setFromVector3( v ) {
14908
14909		this.r = v.x;
14910		this.g = v.y;
14911		this.b = v.z;
14912
14913		return this;
14914
14915	}
14916
14917	/**
14918	 * Transforms this color with the given 3x3 matrix.
14919	 *
14920	 * @param {Matrix3} m - The matrix.
14921	 * @return {Color} A reference to this color.
14922	 */
14923	applyMatrix3( m ) {
14924
14925		const r = this.r, g = this.g, b = this.b;
14926		const e = m.elements;
14927
14928		this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b;
14929		this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b;
14930		this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b;
14931
14932		return this;
14933
14934	}
14935
14936	/**
14937	 * Returns `true` if this color is equal with the given one.
14938	 *
14939	 * @param {Color} c - The color to test for equality.
14940	 * @return {boolean} Whether this bounding color is equal with the given one.
14941	 */
14942	equals( c ) {
14943
14944		return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
14945
14946	}
14947
14948	/**
14949	 * Sets this color's RGB components from the given array.
14950	 *
14951	 * @param {Array<number>} array - An array holding the RGB values.
14952	 * @param {number} [offset=0] - The offset into the array.
14953	 * @return {Color} A reference to this color.
14954	 */
14955	fromArray( array, offset = 0 ) {
14956
14957		this.r = array[ offset ];
14958		this.g = array[ offset + 1 ];
14959		this.b = array[ offset + 2 ];
14960
14961		return this;
14962
14963	}
14964
14965	/**
14966	 * Writes the RGB components of this color to the given array. If no array is provided,
14967	 * the method returns a new instance.
14968	 *
14969	 * @param {Array<number>} [array=[]] - The target array holding the color components.
14970	 * @param {number} [offset=0] - Index of the first element in the array.
14971	 * @return {Array<number>} The color components.
14972	 */
14973	toArray( array = [], offset = 0 ) {
14974
14975		array[ offset ] = this.r;
14976		array[ offset + 1 ] = this.g;
14977		array[ offset + 2 ] = this.b;
14978
14979		return array;
14980
14981	}
14982
14983	/**
14984	 * Sets the components of this color from the given buffer attribute.
14985	 *
14986	 * @param {BufferAttribute} attribute - The buffer attribute holding color data.
14987	 * @param {number} index - The index into the attribute.
14988	 * @return {Color} A reference to this color.
14989	 */
14990	fromBufferAttribute( attribute, index ) {
14991
14992		this.r = attribute.getX( index );
14993		this.g = attribute.getY( index );
14994		this.b = attribute.getZ( index );
14995
14996		return this;
14997
14998	}
14999
15000	/**
15001	 * This methods defines the serialization result of this class. Returns the color
15002	 * as a hexadecimal value.
15003	 *
15004	 * @return {number} The hexadecimal value.
15005	 */
15006	toJSON() {
15007
15008		return this.getHex();
15009
15010	}
15011
15012	*[ Symbol.iterator ]() {
15013
15014		yield this.r;
15015		yield this.g;
15016		yield this.b;
15017
15018	}
15019
15020}
15021
15022const _color = /*@__PURE__*/ new Color();
15023
15024/**
15025 * A dictionary with X11 color names.
15026 *
15027 * Note that multiple words such as Dark Orange become the string 'darkorange'.
15028 *
15029 * @static
15030 * @type {Object}
15031 */
15032Color.NAMES = _colorKeywords;
15033
15034/**
15035 * This class can be used to define an exponential squared fog,
15036 * which gives a clear view near the camera and a faster than exponentially
15037 * densening fog farther from the camera.
15038 *
15039 * ```js
15040 * const scene = new THREE.Scene();
15041 * scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
15042 * ```
15043 */
15044class FogExp2 {
15045
15046	/**
15047	 * Constructs a new fog.
15048	 *
15049	 * @param {number|Color} color - The fog's color.
15050	 * @param {number} [density=0.00025] - Defines how fast the fog will grow dense.
15051	 */
15052	constructor( color, density = 0.00025 ) {
15053
15054		/**
15055		 * This flag can be used for type testing.
15056		 *
15057		 * @type {boolean}
15058		 * @readonly
15059		 * @default true
15060		 */
15061		this.isFogExp2 = true;
15062
15063		/**
15064		 * The name of the fog.
15065		 *
15066		 * @type {string}
15067		 */
15068		this.name = '';
15069
15070		/**
15071		 * The fog's color.
15072		 *
15073		 * @type {Color}
15074		 */
15075		this.color = new Color( color );
15076
15077		/**
15078		 *  Defines how fast the fog will grow dense.
15079		 *
15080		 * @type {number}
15081		 * @default 0.00025
15082		 */
15083		this.density = density;
15084
15085	}
15086
15087	/**
15088	 * Returns a new fog with copied values from this instance.
15089	 *
15090	 * @return {FogExp2} A clone of this instance.
15091	 */
15092	clone() {
15093
15094		return new FogExp2( this.color, this.density );
15095
15096	}
15097
15098	/**
15099	 * Serializes the fog into JSON.
15100	 *
15101	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
15102	 * @return {Object} A JSON object representing the serialized fog
15103	 */
15104	toJSON( /* meta */ ) {
15105
15106		return {
15107			type: 'FogExp2',
15108			name: this.name,
15109			color: this.color.getHex(),
15110			density: this.density
15111		};
15112
15113	}
15114
15115}
15116
15117/**
15118 * This class can be used to define a linear fog that grows linearly denser
15119 * with the distance.
15120 *
15121 * ```js
15122 * const scene = new THREE.Scene();
15123 * scene.fog = new THREE.Fog( 0xcccccc, 10, 15 );
15124 * ```
15125 */
15126class Fog {
15127
15128	/**
15129	 * Constructs a new fog.
15130	 *
15131	 * @param {number|Color} color - The fog's color.
15132	 * @param {number} [near=1] - The minimum distance to start applying fog.
15133	 * @param {number} [far=1000] - The maximum distance at which fog stops being calculated and applied.
15134	 */
15135	constructor( color, near = 1, far = 1000 ) {
15136
15137		/**
15138		 * This flag can be used for type testing.
15139		 *
15140		 * @type {boolean}
15141		 * @readonly
15142		 * @default true
15143		 */
15144		this.isFog = true;
15145
15146		/**
15147		 * The name of the fog.
15148		 *
15149		 * @type {string}
15150		 */
15151		this.name = '';
15152
15153		/**
15154		 * The fog's color.
15155		 *
15156		 * @type {Color}
15157		 */
15158		this.color = new Color( color );
15159
15160		/**
15161		 * The minimum distance to start applying fog. Objects that are less than
15162		 * `near` units from the active camera won't be affected by fog.
15163		 *
15164		 * @type {number}
15165		 * @default 1
15166		 */
15167		this.near = near;
15168
15169		/**
15170		 * The maximum distance at which fog stops being calculated and applied.
15171		 * Objects that are more than `far` units away from the active camera won't
15172		 * be affected by fog.
15173		 *
15174		 * @type {number}
15175		 * @default 1000
15176		 */
15177		this.far = far;
15178
15179	}
15180
15181	/**
15182	 * Returns a new fog with copied values from this instance.
15183	 *
15184	 * @return {Fog} A clone of this instance.
15185	 */
15186	clone() {
15187
15188		return new Fog( this.color, this.near, this.far );
15189
15190	}
15191
15192	/**
15193	 * Serializes the fog into JSON.
15194	 *
15195	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
15196	 * @return {Object} A JSON object representing the serialized fog
15197	 */
15198	toJSON( /* meta */ ) {
15199
15200		return {
15201			type: 'Fog',
15202			name: this.name,
15203			color: this.color.getHex(),
15204			near: this.near,
15205			far: this.far
15206		};
15207
15208	}
15209
15210}
15211
15212/**
15213 * Scenes allow you to set up what is to be rendered and where by three.js.
15214 * This is where you place 3D objects like meshes, lines or lights.
15215 *
15216 * @augments Object3D
15217 */
15218class Scene extends Object3D {
15219
15220	/**
15221	 * Constructs a new scene.
15222	 */
15223	constructor() {
15224
15225		super();
15226
15227		/**
15228		 * This flag can be used for type testing.
15229		 *
15230		 * @type {boolean}
15231		 * @readonly
15232		 * @default true
15233		 */
15234		this.isScene = true;
15235
15236		this.type = 'Scene';
15237
15238		/**
15239		 * Defines the background of the scene. Valid inputs are:
15240		 *
15241		 * - A color for defining a uniform colored background.
15242		 * - A texture for defining a (flat) textured background.
15243		 * - Cube textures or equirectangular textures for defining a skybox.
15244		 *
15245		 * @type {?(Color|Texture)}
15246		 * @default null
15247		 */
15248		this.background = null;
15249
15250		/**
15251		 * Sets the environment map for all physical materials in the scene. However,
15252		 * it's not possible to overwrite an existing texture assigned to the `envMap`
15253		 * material property.
15254		 *
15255		 * @type {?Texture}
15256		 * @default null
15257		 */
15258		this.environment = null;
15259
15260		/**
15261		 * A fog instance defining the type of fog that affects everything
15262		 * rendered in the scene.
15263		 *
15264		 * @type {?(Fog|FogExp2)}
15265		 * @default null
15266		 */
15267		this.fog = null;
15268
15269		/**
15270		 * Sets the blurriness of the background. Only influences environment maps
15271		 * assigned to {@link Scene#background}. Valid input is a float between `0`
15272		 * and `1`.
15273		 *
15274		 * @type {number}
15275		 * @default 0
15276		 */
15277		this.backgroundBlurriness = 0;
15278
15279		/**
15280		 * Attenuates the color of the background. Only applies to background textures.
15281		 *
15282		 * @type {number}
15283		 * @default 1
15284		 */
15285		this.backgroundIntensity = 1;
15286
15287		/**
15288		 * The rotation of the background in radians. Only influences environment maps
15289		 * assigned to {@link Scene#background}.
15290		 *
15291		 * @type {Euler}
15292		 * @default (0,0,0)
15293		 */
15294		this.backgroundRotation = new Euler();
15295
15296		/**
15297		 * Attenuates the color of the environment. Only influences environment maps
15298		 * assigned to {@link Scene#environment}.
15299		 *
15300		 * @type {number}
15301		 * @default 1
15302		 */
15303		this.environmentIntensity = 1;
15304
15305		/**
15306		 * The rotation of the environment map in radians. Only influences physical materials
15307		 * in the scene when {@link Scene#environment} is used.
15308		 *
15309		 * @type {Euler}
15310		 * @default (0,0,0)
15311		 */
15312		this.environmentRotation = new Euler();
15313
15314		/**
15315		 * Forces everything in the scene to be rendered with the defined material. It is possible
15316		 * to exclude materials from override by setting {@link Material#allowOverride} to `false`.
15317		 *
15318		 * @type {?Material}
15319		 * @default null
15320		 */
15321		this.overrideMaterial = null;
15322
15323		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
15324
15325			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
15326
15327		}
15328
15329	}
15330
15331	copy( source, recursive ) {
15332
15333		super.copy( source, recursive );
15334
15335		if ( source.background !== null ) this.background = source.background.clone();
15336		if ( source.environment !== null ) this.environment = source.environment.clone();
15337		if ( source.fog !== null ) this.fog = source.fog.clone();
15338
15339		this.backgroundBlurriness = source.backgroundBlurriness;
15340		this.backgroundIntensity = source.backgroundIntensity;
15341		this.backgroundRotation.copy( source.backgroundRotation );
15342
15343		this.environmentIntensity = source.environmentIntensity;
15344		this.environmentRotation.copy( source.environmentRotation );
15345
15346		if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();
15347
15348		this.matrixAutoUpdate = source.matrixAutoUpdate;
15349
15350		return this;
15351
15352	}
15353
15354	toJSON( meta ) {
15355
15356		const data = super.toJSON( meta );
15357
15358		if ( this.fog !== null ) data.object.fog = this.fog.toJSON();
15359
15360		data.object.backgroundBlurriness = this.backgroundBlurriness;
15361		data.object.backgroundIntensity = this.backgroundIntensity;
15362		data.object.backgroundRotation = this.backgroundRotation.toArray();
15363
15364		data.object.environmentIntensity = this.environmentIntensity;
15365		data.object.environmentRotation = this.environmentRotation.toArray();
15366
15367		return data;
15368
15369	}
15370
15371}
15372
15373const _v0$2 = /*@__PURE__*/ new Vector3();
15374const _v1$5 = /*@__PURE__*/ new Vector3();
15375const _v2$4 = /*@__PURE__*/ new Vector3();
15376const _v3$2 = /*@__PURE__*/ new Vector3();
15377
15378const _vab = /*@__PURE__*/ new Vector3();
15379const _vac = /*@__PURE__*/ new Vector3();
15380const _vbc = /*@__PURE__*/ new Vector3();
15381const _vap = /*@__PURE__*/ new Vector3();
15382const _vbp = /*@__PURE__*/ new Vector3();
15383const _vcp = /*@__PURE__*/ new Vector3();
15384
15385const _v40 = /*@__PURE__*/ new Vector4();
15386const _v41 = /*@__PURE__*/ new Vector4();
15387const _v42 = /*@__PURE__*/ new Vector4();
15388
15389/**
15390 * A geometric triangle as defined by three vectors representing its three corners.
15391 */
15392class Triangle {
15393
15394	/**
15395	 * Constructs a new triangle.
15396	 *
15397	 * @param {Vector3} [a=(0,0,0)] - The first corner of the triangle.
15398	 * @param {Vector3} [b=(0,0,0)] - The second corner of the triangle.
15399	 * @param {Vector3} [c=(0,0,0)] - The third corner of the triangle.
15400	 */
15401	constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) {
15402
15403		/**
15404		 * The first corner of the triangle.
15405		 *
15406		 * @type {Vector3}
15407		 */
15408		this.a = a;
15409
15410		/**
15411		 * The second corner of the triangle.
15412		 *
15413		 * @type {Vector3}
15414		 */
15415		this.b = b;
15416
15417		/**
15418		 * The third corner of the triangle.
15419		 *
15420		 * @type {Vector3}
15421		 */
15422		this.c = c;
15423
15424	}
15425
15426	/**
15427	 * Computes the normal vector of a triangle.
15428	 *
15429	 * @param {Vector3} a - The first corner of the triangle.
15430	 * @param {Vector3} b - The second corner of the triangle.
15431	 * @param {Vector3} c - The third corner of the triangle.
15432	 * @param {Vector3} target - The target vector that is used to store the method's result.
15433	 * @return {Vector3} The triangle's normal.
15434	 */
15435	static getNormal( a, b, c, target ) {
15436
15437		target.subVectors( c, b );
15438		_v0$2.subVectors( a, b );
15439		target.cross( _v0$2 );
15440
15441		const targetLengthSq = target.lengthSq();
15442		if ( targetLengthSq > 0 ) {
15443
15444			return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );
15445
15446		}
15447
15448		return target.set( 0, 0, 0 );
15449
15450	}
15451
15452	/**
15453	 * Computes a barycentric coordinates from the given vector.
15454	 * Returns `null` if the triangle is degenerate.
15455	 *
15456	 * @param {Vector3} point - A point in 3D space.
15457	 * @param {Vector3} a - The first corner of the triangle.
15458	 * @param {Vector3} b - The second corner of the triangle.
15459	 * @param {Vector3} c - The third corner of the triangle.
15460	 * @param {Vector3} target - The target vector that is used to store the method's result.
15461	 * @return {?Vector3} The barycentric coordinates for the given point
15462	 */
15463	static getBarycoord( point, a, b, c, target ) {
15464
15465		_v0$2.subVectors( c, a );
15466		_v1$5.subVectors( b, a );
15467		_v2$4.subVectors( point, a );
15468
15469		const dot00 = _v0$2.dot( _v0$2 );
15470		const dot01 = _v0$2.dot( _v1$5 );
15471		const dot02 = _v0$2.dot( _v2$4 );
15472		const dot11 = _v1$5.dot( _v1$5 );
15473		const dot12 = _v1$5.dot( _v2$4 );
15474
15475		const denom = ( dot00 * dot11 - dot01 * dot01 );
15476
15477		// collinear or singular triangle
15478		if ( denom === 0 ) {
15479
15480			target.set( 0, 0, 0 );
15481			return null;
15482
15483		}
15484
15485		const invDenom = 1 / denom;
15486		const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
15487		const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
15488
15489		// barycentric coordinates must always sum to 1
15490		return target.set( 1 - u - v, v, u );
15491
15492	}
15493
15494	/**
15495	 * Returns `true` if the given point, when projected onto the plane of the
15496	 * triangle, lies within the triangle.
15497	 *
15498	 * @param {Vector3} point - The point in 3D space to test.
15499	 * @param {Vector3} a - The first corner of the triangle.
15500	 * @param {Vector3} b - The second corner of the triangle.
15501	 * @param {Vector3} c - The third corner of the triangle.
15502	 * @return {boolean} Whether the given point, when projected onto the plane of the
15503	 * triangle, lies within the triangle or not.
15504	 */
15505	static containsPoint( point, a, b, c ) {
15506
15507		// if the triangle is degenerate then we can't contain a point
15508		if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) {
15509
15510			return false;
15511
15512		}
15513
15514		return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 );
15515
15516	}
15517
15518	/**
15519	 * Computes the value barycentrically interpolated for the given point on the
15520	 * triangle. Returns `null` if the triangle is degenerate.
15521	 *
15522	 * @param {Vector3} point - Position of interpolated point.
15523	 * @param {Vector3} p1 - The first corner of the triangle.
15524	 * @param {Vector3} p2 - The second corner of the triangle.
15525	 * @param {Vector3} p3 - The third corner of the triangle.
15526	 * @param {Vector3} v1 - Value to interpolate of first vertex.
15527	 * @param {Vector3} v2 - Value to interpolate of second vertex.
15528	 * @param {Vector3} v3 - Value to interpolate of third vertex.
15529	 * @param {Vector3} target - The target vector that is used to store the method's result.
15530	 * @return {?Vector3} The interpolated value.
15531	 */
15532	static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) {
15533
15534		if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) {
15535
15536			target.x = 0;
15537			target.y = 0;
15538			if ( 'z' in target ) target.z = 0;
15539			if ( 'w' in target ) target.w = 0;
15540			return null;
15541
15542		}
15543
15544		target.setScalar( 0 );
15545		target.addScaledVector( v1, _v3$2.x );
15546		target.addScaledVector( v2, _v3$2.y );
15547		target.addScaledVector( v3, _v3$2.z );
15548
15549		return target;
15550
15551	}
15552
15553	/**
15554	 * Computes the value barycentrically interpolated for the given attribute and indices.
15555	 *
15556	 * @param {BufferAttribute} attr - The attribute to interpolate.
15557	 * @param {number} i1 - Index of first vertex.
15558	 * @param {number} i2 - Index of second vertex.
15559	 * @param {number} i3 - Index of third vertex.
15560	 * @param {Vector3} barycoord - The barycoordinate value to use to interpolate.
15561	 * @param {Vector3} target - The target vector that is used to store the method's result.
15562	 * @return {Vector3} The interpolated attribute value.
15563	 */
15564	static getInterpolatedAttribute( attr, i1, i2, i3, barycoord, target ) {
15565
15566		_v40.setScalar( 0 );
15567		_v41.setScalar( 0 );
15568		_v42.setScalar( 0 );
15569
15570		_v40.fromBufferAttribute( attr, i1 );
15571		_v41.fromBufferAttribute( attr, i2 );
15572		_v42.fromBufferAttribute( attr, i3 );
15573
15574		target.setScalar( 0 );
15575		target.addScaledVector( _v40, barycoord.x );
15576		target.addScaledVector( _v41, barycoord.y );
15577		target.addScaledVector( _v42, barycoord.z );
15578
15579		return target;
15580
15581	}
15582
15583	/**
15584	 * Returns `true` if the triangle is oriented towards the given direction.
15585	 *
15586	 * @param {Vector3} a - The first corner of the triangle.
15587	 * @param {Vector3} b - The second corner of the triangle.
15588	 * @param {Vector3} c - The third corner of the triangle.
15589	 * @param {Vector3} direction - The (normalized) direction vector.
15590	 * @return {boolean} Whether the triangle is oriented towards the given direction or not.
15591	 */
15592	static isFrontFacing( a, b, c, direction ) {
15593
15594		_v0$2.subVectors( c, b );
15595		_v1$5.subVectors( a, b );
15596
15597		// strictly front facing
15598		return _v0$2.cross( _v1$5 ).dot( direction ) < 0;
15599
15600	}
15601
15602	/**
15603	 * Sets the triangle's vertices by copying the given values.
15604	 *
15605	 * @param {Vector3} a - The first corner of the triangle.
15606	 * @param {Vector3} b - The second corner of the triangle.
15607	 * @param {Vector3} c - The third corner of the triangle.
15608	 * @return {Triangle} A reference to this triangle.
15609	 */
15610	set( a, b, c ) {
15611
15612		this.a.copy( a );
15613		this.b.copy( b );
15614		this.c.copy( c );
15615
15616		return this;
15617
15618	}
15619
15620	/**
15621	 * Sets the triangle's vertices by copying the given array values.
15622	 *
15623	 * @param {Array<Vector3>} points - An array with 3D points.
15624	 * @param {number} i0 - The array index representing the first corner of the triangle.
15625	 * @param {number} i1 - The array index representing the second corner of the triangle.
15626	 * @param {number} i2 - The array index representing the third corner of the triangle.
15627	 * @return {Triangle} A reference to this triangle.
15628	 */
15629	setFromPointsAndIndices( points, i0, i1, i2 ) {
15630
15631		this.a.copy( points[ i0 ] );
15632		this.b.copy( points[ i1 ] );
15633		this.c.copy( points[ i2 ] );
15634
15635		return this;
15636
15637	}
15638
15639	/**
15640	 * Sets the triangle's vertices by copying the given attribute values.
15641	 *
15642	 * @param {BufferAttribute} attribute - A buffer attribute with 3D points data.
15643	 * @param {number} i0 - The attribute index representing the first corner of the triangle.
15644	 * @param {number} i1 - The attribute index representing the second corner of the triangle.
15645	 * @param {number} i2 - The attribute index representing the third corner of the triangle.
15646	 * @return {Triangle} A reference to this triangle.
15647	 */
15648	setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
15649
15650		this.a.fromBufferAttribute( attribute, i0 );
15651		this.b.fromBufferAttribute( attribute, i1 );
15652		this.c.fromBufferAttribute( attribute, i2 );
15653
15654		return this;
15655
15656	}
15657
15658	/**
15659	 * Returns a new triangle with copied values from this instance.
15660	 *
15661	 * @return {Triangle} A clone of this instance.
15662	 */
15663	clone() {
15664
15665		return new this.constructor().copy( this );
15666
15667	}
15668
15669	/**
15670	 * Copies the values of the given triangle to this instance.
15671	 *
15672	 * @param {Triangle} triangle - The triangle to copy.
15673	 * @return {Triangle} A reference to this triangle.
15674	 */
15675	copy( triangle ) {
15676
15677		this.a.copy( triangle.a );
15678		this.b.copy( triangle.b );
15679		this.c.copy( triangle.c );
15680
15681		return this;
15682
15683	}
15684
15685	/**
15686	 * Computes the area of the triangle.
15687	 *
15688	 * @return {number} The triangle's area.
15689	 */
15690	getArea() {
15691
15692		_v0$2.subVectors( this.c, this.b );
15693		_v1$5.subVectors( this.a, this.b );
15694
15695		return _v0$2.cross( _v1$5 ).length() * 0.5;
15696
15697	}
15698
15699	/**
15700	 * Computes the midpoint of the triangle.
15701	 *
15702	 * @param {Vector3} target - The target vector that is used to store the method's result.
15703	 * @return {Vector3} The triangle's midpoint.
15704	 */
15705	getMidpoint( target ) {
15706
15707		return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );
15708
15709	}
15710
15711	/**
15712	 * Computes the normal of the triangle.
15713	 *
15714	 * @param {Vector3} target - The target vector that is used to store the method's result.
15715	 * @return {Vector3} The triangle's normal.
15716	 */
15717	getNormal( target ) {
15718
15719		return Triangle.getNormal( this.a, this.b, this.c, target );
15720
15721	}
15722
15723	/**
15724	 * Computes a plane the triangle lies within.
15725	 *
15726	 * @param {Plane} target - The target vector that is used to store the method's result.
15727	 * @return {Plane} The plane the triangle lies within.
15728	 */
15729	getPlane( target ) {
15730
15731		return target.setFromCoplanarPoints( this.a, this.b, this.c );
15732
15733	}
15734
15735	/**
15736	 * Computes a barycentric coordinates from the given vector.
15737	 * Returns `null` if the triangle is degenerate.
15738	 *
15739	 * @param {Vector3} point - A point in 3D space.
15740	 * @param {Vector3} target - The target vector that is used to store the method's result.
15741	 * @return {?Vector3} The barycentric coordinates for the given point
15742	 */
15743	getBarycoord( point, target ) {
15744
15745		return Triangle.getBarycoord( point, this.a, this.b, this.c, target );
15746
15747	}
15748
15749	/**
15750	 * Computes the value barycentrically interpolated for the given point on the
15751	 * triangle. Returns `null` if the triangle is degenerate.
15752	 *
15753	 * @param {Vector3} point - Position of interpolated point.
15754	 * @param {Vector3} v1 - Value to interpolate of first vertex.
15755	 * @param {Vector3} v2 - Value to interpolate of second vertex.
15756	 * @param {Vector3} v3 - Value to interpolate of third vertex.
15757	 * @param {Vector3} target - The target vector that is used to store the method's result.
15758	 * @return {?Vector3} The interpolated value.
15759	 */
15760	getInterpolation( point, v1, v2, v3, target ) {
15761
15762		return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target );
15763
15764	}
15765
15766	/**
15767	 * Returns `true` if the given point, when projected onto the plane of the
15768	 * triangle, lies within the triangle.
15769	 *
15770	 * @param {Vector3} point - The point in 3D space to test.
15771	 * @return {boolean} Whether the given point, when projected onto the plane of the
15772	 * triangle, lies within the triangle or not.
15773	 */
15774	containsPoint( point ) {
15775
15776		return Triangle.containsPoint( point, this.a, this.b, this.c );
15777
15778	}
15779
15780	/**
15781	 * Returns `true` if the triangle is oriented towards the given direction.
15782	 *
15783	 * @param {Vector3} direction - The (normalized) direction vector.
15784	 * @return {boolean} Whether the triangle is oriented towards the given direction or not.
15785	 */
15786	isFrontFacing( direction ) {
15787
15788		return Triangle.isFrontFacing( this.a, this.b, this.c, direction );
15789
15790	}
15791
15792	/**
15793	 * Returns `true` if this triangle intersects with the given box.
15794	 *
15795	 * @param {Box3} box - The box to intersect.
15796	 * @return {boolean} Whether this triangle intersects with the given box or not.
15797	 */
15798	intersectsBox( box ) {
15799
15800		return box.intersectsTriangle( this );
15801
15802	}
15803
15804	/**
15805	 * Returns the closest point on the triangle to the given point.
15806	 *
15807	 * @param {Vector3} p - The point to compute the closest point for.
15808	 * @param {Vector3} target - The target vector that is used to store the method's result.
15809	 * @return {Vector3} The closest point on the triangle.
15810	 */
15811	closestPointToPoint( p, target ) {
15812
15813		const a = this.a, b = this.b, c = this.c;
15814		let v, w;
15815
15816		// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
15817		// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
15818		// under the accompanying license; see chapter 5.1.5 for detailed explanation.
15819		// basically, we're distinguishing which of the voronoi regions of the triangle
15820		// the point lies in with the minimum amount of redundant computation.
15821
15822		_vab.subVectors( b, a );
15823		_vac.subVectors( c, a );
15824		_vap.subVectors( p, a );
15825		const d1 = _vab.dot( _vap );
15826		const d2 = _vac.dot( _vap );
15827		if ( d1 <= 0 && d2 <= 0 ) {
15828
15829			// vertex region of A; barycentric coords (1, 0, 0)
15830			return target.copy( a );
15831
15832		}
15833
15834		_vbp.subVectors( p, b );
15835		const d3 = _vab.dot( _vbp );
15836		const d4 = _vac.dot( _vbp );
15837		if ( d3 >= 0 && d4 <= d3 ) {
15838
15839			// vertex region of B; barycentric coords (0, 1, 0)
15840			return target.copy( b );
15841
15842		}
15843
15844		const vc = d1 * d4 - d3 * d2;
15845		if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
15846
15847			v = d1 / ( d1 - d3 );
15848			// edge region of AB; barycentric coords (1-v, v, 0)
15849			return target.copy( a ).addScaledVector( _vab, v );
15850
15851		}
15852
15853		_vcp.subVectors( p, c );
15854		const d5 = _vab.dot( _vcp );
15855		const d6 = _vac.dot( _vcp );
15856		if ( d6 >= 0 && d5 <= d6 ) {
15857
15858			// vertex region of C; barycentric coords (0, 0, 1)
15859			return target.copy( c );
15860
15861		}
15862
15863		const vb = d5 * d2 - d1 * d6;
15864		if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
15865
15866			w = d2 / ( d2 - d6 );
15867			// edge region of AC; barycentric coords (1-w, 0, w)
15868			return target.copy( a ).addScaledVector( _vac, w );
15869
15870		}
15871
15872		const va = d3 * d6 - d5 * d4;
15873		if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
15874
15875			_vbc.subVectors( c, b );
15876			w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
15877			// edge region of BC; barycentric coords (0, 1-w, w)
15878			return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC
15879
15880		}
15881
15882		// face region
15883		const denom = 1 / ( va + vb + vc );
15884		// u = va * denom
15885		v = vb * denom;
15886		w = vc * denom;
15887
15888		return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );
15889
15890	}
15891
15892	/**
15893	 * Returns `true` if this triangle is equal with the given one.
15894	 *
15895	 * @param {Triangle} triangle - The triangle to test for equality.
15896	 * @return {boolean} Whether this triangle is equal with the given one.
15897	 */
15898	equals( triangle ) {
15899
15900		return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );
15901
15902	}
15903
15904}
15905
15906/**
15907 * Represents an axis-aligned bounding box (AABB) in 3D space.
15908 */
15909class Box3 {
15910
15911	/**
15912	 * Constructs a new bounding box.
15913	 *
15914	 * @param {Vector3} [min=(Infinity,Infinity,Infinity)] - A vector representing the lower boundary of the box.
15915	 * @param {Vector3} [max=(-Infinity,-Infinity,-Infinity)] - A vector representing the upper boundary of the box.
15916	 */
15917	constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) {
15918
15919		/**
15920		 * This flag can be used for type testing.
15921		 *
15922		 * @type {boolean}
15923		 * @readonly
15924		 * @default true
15925		 */
15926		this.isBox3 = true;
15927
15928		/**
15929		 * The lower boundary of the box.
15930		 *
15931		 * @type {Vector3}
15932		 */
15933		this.min = min;
15934
15935		/**
15936		 * The upper boundary of the box.
15937		 *
15938		 * @type {Vector3}
15939		 */
15940		this.max = max;
15941
15942	}
15943
15944	/**
15945	 * Sets the lower and upper boundaries of this box.
15946	 * Please note that this method only copies the values from the given objects.
15947	 *
15948	 * @param {Vector3} min - The lower boundary of the box.
15949	 * @param {Vector3} max - The upper boundary of the box.
15950	 * @return {Box3} A reference to this bounding box.
15951	 */
15952	set( min, max ) {
15953
15954		this.min.copy( min );
15955		this.max.copy( max );
15956
15957		return this;
15958
15959	}
15960
15961	/**
15962	 * Sets the upper and lower bounds of this box so it encloses the position data
15963	 * in the given array.
15964	 *
15965	 * @param {Array<number>} array - An array holding 3D position data.
15966	 * @return {Box3} A reference to this bounding box.
15967	 */
15968	setFromArray( array ) {
15969
15970		this.makeEmpty();
15971
15972		for ( let i = 0, il = array.length; i < il; i += 3 ) {
15973
15974			this.expandByPoint( _vector$b.fromArray( array, i ) );
15975
15976		}
15977
15978		return this;
15979
15980	}
15981
15982	/**
15983	 * Sets the upper and lower bounds of this box so it encloses the position data
15984	 * in the given buffer attribute.
15985	 *
15986	 * @param {BufferAttribute} attribute - A buffer attribute holding 3D position data.
15987	 * @return {Box3} A reference to this bounding box.
15988	 */
15989	setFromBufferAttribute( attribute ) {
15990
15991		this.makeEmpty();
15992
15993		for ( let i = 0, il = attribute.count; i < il; i ++ ) {
15994
15995			this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) );
15996
15997		}
15998
15999		return this;
16000
16001	}
16002
16003	/**
16004	 * Sets the upper and lower bounds of this box so it encloses the position data
16005	 * in the given array.
16006	 *
16007	 * @param {Array<Vector3>} points - An array holding 3D position data as instances of {@link Vector3}.
16008	 * @return {Box3} A reference to this bounding box.
16009	 */
16010	setFromPoints( points ) {
16011
16012		this.makeEmpty();
16013
16014		for ( let i = 0, il = points.length; i < il; i ++ ) {
16015
16016			this.expandByPoint( points[ i ] );
16017
16018		}
16019
16020		return this;
16021
16022	}
16023
16024	/**
16025	 * Centers this box on the given center vector and sets this box's width, height and
16026	 * depth to the given size values.
16027	 *
16028	 * @param {Vector3} center - The center of the box.
16029	 * @param {Vector3} size - The x, y and z dimensions of the box.
16030	 * @return {Box3} A reference to this bounding box.
16031	 */
16032	setFromCenterAndSize( center, size ) {
16033
16034		const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 );
16035
16036		this.min.copy( center ).sub( halfSize );
16037		this.max.copy( center ).add( halfSize );
16038
16039		return this;
16040
16041	}
16042
16043	/**
16044	 * Computes the world-axis-aligned bounding box for the given 3D object
16045	 * (including its children), accounting for the object's, and children's,
16046	 * world transforms. The function may result in a larger box than strictly necessary.
16047	 *
16048	 * Note: To compute the correct bounding box, make sure the given 3D object
16049	 * has an up-to-date world matrix that reflects the current transformation of its
16050	 * ancestor nodes. Call `object.updateWorldMatrix( true, false )` beforehand if
16051	 * you're unsure.
16052	 *
16053	 * @param {Object3D} object - The 3D object to compute the bounding box for.
16054	 * @param {boolean} [precise=false] - If set to `true`, the method computes the smallest
16055	 * world-axis-aligned bounding box at the expense of more computation.
16056	 * @return {Box3} A reference to this bounding box.
16057	 */
16058	setFromObject( object, precise = false ) {
16059
16060		this.makeEmpty();
16061
16062		return this.expandByObject( object, precise );
16063
16064	}
16065
16066	/**
16067	 * Returns a new box with copied values from this instance.
16068	 *
16069	 * @return {Box3} A clone of this instance.
16070	 */
16071	clone() {
16072
16073		return new this.constructor().copy( this );
16074
16075	}
16076
16077	/**
16078	 * Copies the values of the given box to this instance.
16079	 *
16080	 * @param {Box3} box - The box to copy.
16081	 * @return {Box3} A reference to this bounding box.
16082	 */
16083	copy( box ) {
16084
16085		this.min.copy( box.min );
16086		this.max.copy( box.max );
16087
16088		return this;
16089
16090	}
16091
16092	/**
16093	 * Makes this box empty which means in encloses a zero space in 3D.
16094	 *
16095	 * @return {Box3} A reference to this bounding box.
16096	 */
16097	makeEmpty() {
16098
16099		this.min.x = this.min.y = this.min.z = + Infinity;
16100		this.max.x = this.max.y = this.max.z = - Infinity;
16101
16102		return this;
16103
16104	}
16105
16106	/**
16107	 * Returns true if this box includes zero points within its bounds.
16108	 * Note that a box with equal lower and upper bounds still includes one
16109	 * point, the one both bounds share.
16110	 *
16111	 * @return {boolean} Whether this box is empty or not.
16112	 */
16113	isEmpty() {
16114
16115		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
16116
16117		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );
16118
16119	}
16120
16121	/**
16122	 * Returns the center point of this box.
16123	 *
16124	 * @param {Vector3} target - The target vector that is used to store the method's result.
16125	 * @return {Vector3} The center point.
16126	 */
16127	getCenter( target ) {
16128
16129		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
16130
16131	}
16132
16133	/**
16134	 * Returns the dimensions of this box.
16135	 *
16136	 * @param {Vector3} target - The target vector that is used to store the method's result.
16137	 * @return {Vector3} The size.
16138	 */
16139	getSize( target ) {
16140
16141		return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );
16142
16143	}
16144
16145	/**
16146	 * Expands the boundaries of this box to include the given point.
16147	 *
16148	 * @param {Vector3} point - The point that should be included by the bounding box.
16149	 * @return {Box3} A reference to this bounding box.
16150	 */
16151	expandByPoint( point ) {
16152
16153		this.min.min( point );
16154		this.max.max( point );
16155
16156		return this;
16157
16158	}
16159
16160	/**
16161	 * Expands this box equilaterally by the given vector. The width of this
16162	 * box will be expanded by the x component of the vector in both
16163	 * directions. The height of this box will be expanded by the y component of
16164	 * the vector in both directions. The depth of this box will be
16165	 * expanded by the z component of the vector in both directions.
16166	 *
16167	 * @param {Vector3} vector - The vector that should expand the bounding box.
16168	 * @return {Box3} A reference to this bounding box.
16169	 */
16170	expandByVector( vector ) {
16171
16172		this.min.sub( vector );
16173		this.max.add( vector );
16174
16175		return this;
16176
16177	}
16178
16179	/**
16180	 * Expands each dimension of the box by the given scalar. If negative, the
16181	 * dimensions of the box will be contracted.
16182	 *
16183	 * @param {number} scalar - The scalar value that should expand the bounding box.
16184	 * @return {Box3} A reference to this bounding box.
16185	 */
16186	expandByScalar( scalar ) {
16187
16188		this.min.addScalar( - scalar );
16189		this.max.addScalar( scalar );
16190
16191		return this;
16192
16193	}
16194
16195	/**
16196	 * Expands the boundaries of this box to include the given 3D object and
16197	 * its children, accounting for the object's, and children's, world
16198	 * transforms. The function may result in a larger box than strictly
16199	 * necessary (unless the precise parameter is set to true).
16200	 *
16201	 * @param {Object3D} object - The 3D object that should expand the bounding box.
16202	 * @param {boolean} precise - If set to `true`, the method expands the bounding box
16203	 * as little as necessary at the expense of more computation.
16204	 * @return {Box3} A reference to this bounding box.
16205	 */
16206	expandByObject( object, precise = false ) {
16207
16208		// Computes the world-axis-aligned bounding box of an object (including its children),
16209		// accounting for both the object's, and children's, world transforms
16210
16211		object.updateWorldMatrix( false, false );
16212
16213		const geometry = object.geometry;
16214
16215		if ( geometry !== undefined ) {
16216
16217			const positionAttribute = geometry.getAttribute( 'position' );
16218
16219			// precise AABB computation based on vertex data requires at least a position attribute.
16220			// instancing isn't supported so far and uses the normal (conservative) code path.
16221
16222			if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) {
16223
16224				for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) {
16225
16226					if ( object.isMesh === true ) {
16227
16228						object.getVertexPosition( i, _vector$b );
16229
16230					} else {
16231
16232						_vector$b.fromBufferAttribute( positionAttribute, i );
16233
16234					}
16235
16236					_vector$b.applyMatrix4( object.matrixWorld );
16237					this.expandByPoint( _vector$b );
16238
16239				}
16240
16241			} else {
16242
16243				if ( object.boundingBox !== undefined ) {
16244
16245					// object-level bounding box
16246
16247					if ( object.boundingBox === null ) {
16248
16249						object.computeBoundingBox();
16250
16251					}
16252
16253					_box$4.copy( object.boundingBox );
16254
16255
16256				} else {
16257
16258					// geometry-level bounding box
16259
16260					if ( geometry.boundingBox === null ) {
16261
16262						geometry.computeBoundingBox();
16263
16264					}
16265
16266					_box$4.copy( geometry.boundingBox );
16267
16268				}
16269
16270				_box$4.applyMatrix4( object.matrixWorld );
16271
16272				this.union( _box$4 );
16273
16274			}
16275
16276		}
16277
16278		const children = object.children;
16279
16280		for ( let i = 0, l = children.length; i < l; i ++ ) {
16281
16282			this.expandByObject( children[ i ], precise );
16283
16284		}
16285
16286		return this;
16287
16288	}
16289
16290	/**
16291	 * Returns `true` if the given point lies within or on the boundaries of this box.
16292	 *
16293	 * @param {Vector3} point - The point to test.
16294	 * @return {boolean} Whether the bounding box contains the given point or not.
16295	 */
16296	containsPoint( point ) {
16297
16298		return point.x >= this.min.x && point.x <= this.max.x &&
16299			point.y >= this.min.y && point.y <= this.max.y &&
16300			point.z >= this.min.z && point.z <= this.max.z;
16301
16302	}
16303
16304	/**
16305	 * Returns `true` if this bounding box includes the entirety of the given bounding box.
16306	 * If this box and the given one are identical, this function also returns `true`.
16307	 *
16308	 * @param {Box3} box - The bounding box to test.
16309	 * @return {boolean} Whether the bounding box contains the given bounding box or not.
16310	 */
16311	containsBox( box ) {
16312
16313		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
16314			this.min.y <= box.min.y && box.max.y <= this.max.y &&
16315			this.min.z <= box.min.z && box.max.z <= this.max.z;
16316
16317	}
16318
16319	/**
16320	 * Returns a point as a proportion of this box's width, height and depth.
16321	 *
16322	 * @param {Vector3} point - A point in 3D space.
16323	 * @param {Vector3} target - The target vector that is used to store the method's result.
16324	 * @return {Vector3} A point as a proportion of this box's width, height and depth.
16325	 */
16326	getParameter( point, target ) {
16327
16328		// This can potentially have a divide by zero if the box
16329		// has a size dimension of 0.
16330
16331		return target.set(
16332			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
16333			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
16334			( point.z - this.min.z ) / ( this.max.z - this.min.z )
16335		);
16336
16337	}
16338
16339	/**
16340	 * Returns `true` if the given bounding box intersects with this bounding box.
16341	 *
16342	 * @param {Box3} box - The bounding box to test.
16343	 * @return {boolean} Whether the given bounding box intersects with this bounding box.
16344	 */
16345	intersectsBox( box ) {
16346
16347		// using 6 splitting planes to rule out intersections.
16348		return box.max.x >= this.min.x && box.min.x <= this.max.x &&
16349			box.max.y >= this.min.y && box.min.y <= this.max.y &&
16350			box.max.z >= this.min.z && box.min.z <= this.max.z;
16351
16352	}
16353
16354	/**
16355	 * Returns `true` if the given bounding sphere intersects with this bounding box.
16356	 *
16357	 * @param {Sphere} sphere - The bounding sphere to test.
16358	 * @return {boolean} Whether the given bounding sphere intersects with this bounding box.
16359	 */
16360	intersectsSphere( sphere ) {
16361
16362		// Find the point on the AABB closest to the sphere center.
16363		this.clampPoint( sphere.center, _vector$b );
16364
16365		// If that point is inside the sphere, the AABB and sphere intersect.
16366		return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
16367
16368	}
16369
16370	/**
16371	 * Returns `true` if the given plane intersects with this bounding box.
16372	 *
16373	 * @param {Plane} plane - The plane to test.
16374	 * @return {boolean} Whether the given plane intersects with this bounding box.
16375	 */
16376	intersectsPlane( plane ) {
16377
16378		// We compute the minimum and maximum dot product values. If those values
16379		// are on the same side (back or front) of the plane, then there is no intersection.
16380
16381		let min, max;
16382
16383		if ( plane.normal.x > 0 ) {
16384
16385			min = plane.normal.x * this.min.x;
16386			max = plane.normal.x * this.max.x;
16387
16388		} else {
16389
16390			min = plane.normal.x * this.max.x;
16391			max = plane.normal.x * this.min.x;
16392
16393		}
16394
16395		if ( plane.normal.y > 0 ) {
16396
16397			min += plane.normal.y * this.min.y;
16398			max += plane.normal.y * this.max.y;
16399
16400		} else {
16401
16402			min += plane.normal.y * this.max.y;
16403			max += plane.normal.y * this.min.y;
16404
16405		}
16406
16407		if ( plane.normal.z > 0 ) {
16408
16409			min += plane.normal.z * this.min.z;
16410			max += plane.normal.z * this.max.z;
16411
16412		} else {
16413
16414			min += plane.normal.z * this.max.z;
16415			max += plane.normal.z * this.min.z;
16416
16417		}
16418
16419		return ( min <= - plane.constant && max >= - plane.constant );
16420
16421	}
16422
16423	/**
16424	 * Returns `true` if the given triangle intersects with this bounding box.
16425	 *
16426	 * @param {Triangle} triangle - The triangle to test.
16427	 * @return {boolean} Whether the given triangle intersects with this bounding box.
16428	 */
16429	intersectsTriangle( triangle ) {
16430
16431		if ( this.isEmpty() ) {
16432
16433			return false;
16434
16435		}
16436
16437		// compute box center and extents
16438		this.getCenter( _center );
16439		_extents.subVectors( this.max, _center );
16440
16441		// translate triangle to aabb origin
16442		_v0$1.subVectors( triangle.a, _center );
16443		_v1$4.subVectors( triangle.b, _center );
16444		_v2$3.subVectors( triangle.c, _center );
16445
16446		// compute edge vectors for triangle
16447		_f0.subVectors( _v1$4, _v0$1 );
16448		_f1.subVectors( _v2$3, _v1$4 );
16449		_f2.subVectors( _v0$1, _v2$3 );
16450
16451		// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb
16452		// 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
16453		// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)
16454		let axes = [
16455			0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
16456			_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
16457			- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
16458		];
16459		if ( ! satForAxes( axes, _v0$1, _v1$4, _v2$3, _extents ) ) {
16460
16461			return false;
16462
16463		}
16464
16465		// test 3 face normals from the aabb
16466		axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
16467		if ( ! satForAxes( axes, _v0$1, _v1$4, _v2$3, _extents ) ) {
16468
16469			return false;
16470
16471		}
16472
16473		// finally testing the face normal of the triangle
16474		// use already existing triangle edge vectors here
16475		_triangleNormal.crossVectors( _f0, _f1 );
16476		axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
16477
16478		return satForAxes( axes, _v0$1, _v1$4, _v2$3, _extents );
16479
16480	}
16481
16482	/**
16483	 * Clamps the given point within the bounds of this box.
16484	 *
16485	 * @param {Vector3} point - The point to clamp.
16486	 * @param {Vector3} target - The target vector that is used to store the method's result.
16487	 * @return {Vector3} The clamped point.
16488	 */
16489	clampPoint( point, target ) {
16490
16491		return target.copy( point ).clamp( this.min, this.max );
16492
16493	}
16494
16495	/**
16496	 * Returns the euclidean distance from any edge of this box to the specified point. If
16497	 * the given point lies inside of this box, the distance will be `0`.
16498	 *
16499	 * @param {Vector3} point - The point to compute the distance to.
16500	 * @return {number} The euclidean distance.
16501	 */
16502	distanceToPoint( point ) {
16503
16504		return this.clampPoint( point, _vector$b ).distanceTo( point );
16505
16506	}
16507
16508	/**
16509	 * Returns a bounding sphere that encloses this bounding box.
16510	 *
16511	 * @param {Sphere} target - The target sphere that is used to store the method's result.
16512	 * @return {Sphere} The bounding sphere that encloses this bounding box.
16513	 */
16514	getBoundingSphere( target ) {
16515
16516		if ( this.isEmpty() ) {
16517
16518			target.makeEmpty();
16519
16520		} else {
16521
16522			this.getCenter( target.center );
16523
16524			target.radius = this.getSize( _vector$b ).length() * 0.5;
16525
16526		}
16527
16528		return target;
16529
16530	}
16531
16532	/**
16533	 * Computes the intersection of this bounding box and the given one, setting the upper
16534	 * bound of this box to the lesser of the two boxes' upper bounds and the
16535	 * lower bound of this box to the greater of the two boxes' lower bounds. If
16536	 * there's no overlap, makes this box empty.
16537	 *
16538	 * @param {Box3} box - The bounding box to intersect with.
16539	 * @return {Box3} A reference to this bounding box.
16540	 */
16541	intersect( box ) {
16542
16543		this.min.max( box.min );
16544		this.max.min( box.max );
16545
16546		// 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.
16547		if ( this.isEmpty() ) this.makeEmpty();
16548
16549		return this;
16550
16551	}
16552
16553	/**
16554	 * Computes the union of this box and another and the given one, setting the upper
16555	 * bound of this box to the greater of the two boxes' upper bounds and the
16556	 * lower bound of this box to the lesser of the two boxes' lower bounds.
16557	 *
16558	 * @param {Box3} box - The bounding box that will be unioned with this instance.
16559	 * @return {Box3} A reference to this bounding box.
16560	 */
16561	union( box ) {
16562
16563		this.min.min( box.min );
16564		this.max.max( box.max );
16565
16566		return this;
16567
16568	}
16569
16570	/**
16571	 * Transforms this bounding box by the given 4x4 transformation matrix.
16572	 *
16573	 * @param {Matrix4} matrix - The transformation matrix.
16574	 * @return {Box3} A reference to this bounding box.
16575	 */
16576	applyMatrix4( matrix ) {
16577
16578		// transform of empty box is an empty box.
16579		if ( this.isEmpty() ) return this;
16580
16581		// NOTE: I am using a binary pattern to specify all 2^3 combinations below
16582		_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000
16583		_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001
16584		_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010
16585		_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011
16586		_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100
16587		_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101
16588		_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110
16589		_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111
16590
16591		this.setFromPoints( _points );
16592
16593		return this;
16594
16595	}
16596
16597	/**
16598	 * Adds the given offset to both the upper and lower bounds of this bounding box,
16599	 * effectively moving it in 3D space.
16600	 *
16601	 * @param {Vector3} offset - The offset that should be used to translate the bounding box.
16602	 * @return {Box3} A reference to this bounding box.
16603	 */
16604	translate( offset ) {
16605
16606		this.min.add( offset );
16607		this.max.add( offset );
16608
16609		return this;
16610
16611	}
16612
16613	/**
16614	 * Returns `true` if this bounding box is equal with the given one.
16615	 *
16616	 * @param {Box3} box - The box to test for equality.
16617	 * @return {boolean} Whether this bounding box is equal with the given one.
16618	 */
16619	equals( box ) {
16620
16621		return box.min.equals( this.min ) && box.max.equals( this.max );
16622
16623	}
16624
16625	/**
16626	 * Returns a serialized structure of the bounding box.
16627	 *
16628	 * @return {Object} Serialized structure with fields representing the object state.
16629	 */
16630	toJSON() {
16631
16632		return {
16633			min: this.min.toArray(),
16634			max: this.max.toArray()
16635		};
16636
16637	}
16638
16639	/**
16640	 * Returns a serialized structure of the bounding box.
16641	 *
16642	 * @param {Object} json - The serialized json to set the box from.
16643	 * @return {Box3} A reference to this bounding box.
16644	 */
16645	fromJSON( json ) {
16646
16647		this.min.fromArray( json.min );
16648		this.max.fromArray( json.max );
16649		return this;
16650
16651	}
16652
16653}
16654
16655const _points = [
16656	/*@__PURE__*/ new Vector3(),
16657	/*@__PURE__*/ new Vector3(),
16658	/*@__PURE__*/ new Vector3(),
16659	/*@__PURE__*/ new Vector3(),
16660	/*@__PURE__*/ new Vector3(),
16661	/*@__PURE__*/ new Vector3(),
16662	/*@__PURE__*/ new Vector3(),
16663	/*@__PURE__*/ new Vector3()
16664];
16665
16666const _vector$b = /*@__PURE__*/ new Vector3();
16667
16668const _box$4 = /*@__PURE__*/ new Box3();
16669
16670// triangle centered vertices
16671
16672const _v0$1 = /*@__PURE__*/ new Vector3();
16673const _v1$4 = /*@__PURE__*/ new Vector3();
16674const _v2$3 = /*@__PURE__*/ new Vector3();
16675
16676// triangle edge vectors
16677
16678const _f0 = /*@__PURE__*/ new Vector3();
16679const _f1 = /*@__PURE__*/ new Vector3();
16680const _f2 = /*@__PURE__*/ new Vector3();
16681
16682const _center = /*@__PURE__*/ new Vector3();
16683const _extents = /*@__PURE__*/ new Vector3();
16684const _triangleNormal = /*@__PURE__*/ new Vector3();
16685const _testAxis = /*@__PURE__*/ new Vector3();
16686
16687function satForAxes( axes, v0, v1, v2, extents ) {
16688
16689	for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) {
16690
16691		_testAxis.fromArray( axes, i );
16692		// project the aabb onto the separating axis
16693		const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );
16694		// project all 3 vertices of the triangle onto the separating axis
16695		const p0 = v0.dot( _testAxis );
16696		const p1 = v1.dot( _testAxis );
16697		const p2 = v2.dot( _testAxis );
16698		// actual test, basically see if either of the most extreme of the triangle points intersects r
16699		if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {
16700
16701			// points of the projected triangle are outside the projected half-length of the aabb
16702			// the axis is separating and we can exit
16703			return false;
16704
16705		}
16706
16707	}
16708
16709	return true;
16710
16711}
16712
16713// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
16714
16715const _tables = /*@__PURE__*/ _generateTables();
16716
16717function _generateTables() {
16718
16719	// float32 to float16 helpers
16720
16721	const buffer = new ArrayBuffer( 4 );
16722	const floatView = new Float32Array( buffer );
16723	const uint32View = new Uint32Array( buffer );
16724
16725	const baseTable = new Uint32Array( 512 );
16726	const shiftTable = new Uint32Array( 512 );
16727
16728	for ( let i = 0; i < 256; ++ i ) {
16729
16730		const e = i - 127;
16731
16732		// very small number (0, -0)
16733
16734		if ( e < -27 ) {
16735
16736			baseTable[ i ] = 0x0000;
16737			baseTable[ i | 0x100 ] = 0x8000;
16738			shiftTable[ i ] = 24;
16739			shiftTable[ i | 0x100 ] = 24;
16740
16741			// small number (denorm)
16742
16743		} else if ( e < -14 ) {
16744
16745			baseTable[ i ] = 0x0400 >> ( - e - 14 );
16746			baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000;
16747			shiftTable[ i ] = - e - 1;
16748			shiftTable[ i | 0x100 ] = - e - 1;
16749
16750			// normal number
16751
16752		} else if ( e <= 15 ) {
16753
16754			baseTable[ i ] = ( e + 15 ) << 10;
16755			baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000;
16756			shiftTable[ i ] = 13;
16757			shiftTable[ i | 0x100 ] = 13;
16758
16759			// large number (Infinity, -Infinity)
16760
16761		} else if ( e < 128 ) {
16762
16763			baseTable[ i ] = 0x7c00;
16764			baseTable[ i | 0x100 ] = 0xfc00;
16765			shiftTable[ i ] = 24;
16766			shiftTable[ i | 0x100 ] = 24;
16767
16768			// stay (NaN, Infinity, -Infinity)
16769
16770		} else {
16771
16772			baseTable[ i ] = 0x7c00;
16773			baseTable[ i | 0x100 ] = 0xfc00;
16774			shiftTable[ i ] = 13;
16775			shiftTable[ i | 0x100 ] = 13;
16776
16777		}
16778
16779	}
16780
16781	// float16 to float32 helpers
16782
16783	const mantissaTable = new Uint32Array( 2048 );
16784	const exponentTable = new Uint32Array( 64 );
16785	const offsetTable = new Uint32Array( 64 );
16786
16787	for ( let i = 1; i < 1024; ++ i ) {
16788
16789		let m = i << 13; // zero pad mantissa bits
16790		let e = 0; // zero exponent
16791
16792		// normalized
16793		while ( ( m & 0x00800000 ) === 0 ) {
16794
16795			m <<= 1;
16796			e -= 0x00800000; // decrement exponent
16797
16798		}
16799
16800		m &= -8388609; // clear leading 1 bit
16801		e += 0x38800000; // adjust bias
16802
16803		mantissaTable[ i ] = m | e;
16804
16805	}
16806
16807	for ( let i = 1024; i < 2048; ++ i ) {
16808
16809		mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 );
16810
16811	}
16812
16813	for ( let i = 1; i < 31; ++ i ) {
16814
16815		exponentTable[ i ] = i << 23;
16816
16817	}
16818
16819	exponentTable[ 31 ] = 0x47800000;
16820	exponentTable[ 32 ] = 0x80000000;
16821
16822	for ( let i = 33; i < 63; ++ i ) {
16823
16824		exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 );
16825
16826	}
16827
16828	exponentTable[ 63 ] = 0xc7800000;
16829
16830	for ( let i = 1; i < 64; ++ i ) {
16831
16832		if ( i !== 32 ) {
16833
16834			offsetTable[ i ] = 1024;
16835
16836		}
16837
16838	}
16839
16840	return {
16841		floatView: floatView,
16842		uint32View: uint32View,
16843		baseTable: baseTable,
16844		shiftTable: shiftTable,
16845		mantissaTable: mantissaTable,
16846		exponentTable: exponentTable,
16847		offsetTable: offsetTable
16848	};
16849
16850}
16851
16852/**
16853 * Returns a half precision floating point value (FP16) from the given single
16854 * precision floating point value (FP32).
16855 *
16856 * @param {number} val - A single precision floating point value.
16857 * @return {number} The FP16 value.
16858 */
16859function toHalfFloat( val ) {
16860
16861	if ( Math.abs( val ) > 65504 ) warn( 'DataUtils.toHalfFloat(): Value out of range.' );
16862
16863	val = clamp( val, -65504, 65504 );
16864
16865	_tables.floatView[ 0 ] = val;
16866	const f = _tables.uint32View[ 0 ];
16867	const e = ( f >> 23 ) & 0x1ff;
16868	return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] );
16869
16870}
16871
16872/**
16873 * Returns a single precision floating point value (FP32) from the given half
16874 * precision floating point value (FP16).
16875 *
16876 * @param {number} val - A half precision floating point value.
16877 * @return {number} The FP32 value.
16878 */
16879function fromHalfFloat( val ) {
16880
16881	const m = val >> 10;
16882	_tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ];
16883	return _tables.floatView[ 0 ];
16884
16885}
16886
16887/**
16888 * A class containing utility functions for data.
16889 *
16890 * @hideconstructor
16891 */
16892class DataUtils {
16893
16894	/**
16895	 * Returns a half precision floating point value (FP16) from the given single
16896	 * precision floating point value (FP32).
16897	 *
16898	 * @param {number} val - A single precision floating point value.
16899	 * @return {number} The FP16 value.
16900	 */
16901	static toHalfFloat( val ) {
16902
16903		return toHalfFloat( val );
16904
16905	}
16906
16907	/**
16908	 * Returns a single precision floating point value (FP32) from the given half
16909	 * precision floating point value (FP16).
16910	 *
16911	 * @param {number} val - A half precision floating point value.
16912	 * @return {number} The FP32 value.
16913	 */
16914	static fromHalfFloat( val ) {
16915
16916		return fromHalfFloat( val );
16917
16918	}
16919
16920}
16921
16922const _vector$a = /*@__PURE__*/ new Vector3();
16923const _vector2$1 = /*@__PURE__*/ new Vector2();
16924
16925let _id$2 = 0;
16926
16927/**
16928 * This class stores data for an attribute (such as vertex positions, face
16929 * indices, normals, colors, UVs, and any custom attributes ) associated with
16930 * a geometry, which allows for more efficient passing of data to the GPU.
16931 *
16932 * When working with vector-like data, the `fromBufferAttribute( attribute, index )`
16933 * helper methods on vector and color class might be helpful. E.g. {@link Vector3#fromBufferAttribute}.
16934 */
16935class BufferAttribute extends EventDispatcher {
16936
16937	/**
16938	 * Constructs a new buffer attribute.
16939	 *
16940	 * @param {TypedArray} array - The array holding the attribute data.
16941	 * @param {number} itemSize - The item size.
16942	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
16943	 */
16944	constructor( array, itemSize, normalized = false ) {
16945
16946		super();
16947
16948		if ( Array.isArray( array ) ) {
16949
16950			throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );
16951
16952		}
16953
16954		/**
16955		 * This flag can be used for type testing.
16956		 *
16957		 * @type {boolean}
16958		 * @readonly
16959		 * @default true
16960		 */
16961		this.isBufferAttribute = true;
16962
16963		/**
16964		 * The ID of the buffer attribute.
16965		 *
16966		 * @name BufferAttribute#id
16967		 * @type {number}
16968		 * @readonly
16969		 */
16970		Object.defineProperty( this, 'id', { value: _id$2 ++ } );
16971
16972		/**
16973		 * The name of the buffer attribute.
16974		 *
16975		 * @type {string}
16976		 */
16977		this.name = '';
16978
16979		/**
16980		 * The array holding the attribute data. It should have `itemSize * numVertices`
16981		 * elements, where `numVertices` is the number of vertices in the associated geometry.
16982		 *
16983		 * @type {TypedArray}
16984		 */
16985		this.array = array;
16986
16987		/**
16988		 * The number of values of the array that should be associated with a particular vertex.
16989		 * For instance, if this attribute is storing a 3-component vector (such as a position,
16990		 * normal, or color), then the value should be `3`.
16991		 *
16992		 * @type {number}
16993		 */
16994		this.itemSize = itemSize;
16995
16996		/**
16997		 * Represents the number of items this buffer attribute stores. It is internally computed
16998		 * by dividing the `array` length by the `itemSize`.
16999		 *
17000		 * @type {number}
17001		 * @readonly
17002		 */
17003		this.count = array !== undefined ? array.length / itemSize : 0;
17004
17005		/**
17006		 * Applies to integer data only. Indicates how the underlying data in the buffer maps to
17007		 * the values in the GLSL code. For instance, if `array` is an instance of `UInt16Array`,
17008		 * and `normalized` is `true`, the values `0 - +65535` in the array data will be mapped to
17009		 * `0.0f - +1.0f` in the GLSL attribute. If `normalized` is `false`, the values will be converted
17010		 * to floats unmodified, i.e. `65535` becomes `65535.0f`.
17011		 *
17012		 * @type {boolean}
17013		 */
17014		this.normalized = normalized;
17015
17016		/**
17017		 * Defines the intended usage pattern of the data store for optimization purposes.
17018		 *
17019		 * Note: After the initial use of a buffer, its usage cannot be changed. Instead,
17020		 * instantiate a new one and set the desired usage before the next render.
17021		 *
17022		 * @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
17023		 * @default StaticDrawUsage
17024		 */
17025		this.usage = StaticDrawUsage;
17026
17027		/**
17028		 * This can be used to only update some components of stored vectors (for example, just the
17029		 * component related to color). Use the `addUpdateRange()` function to add ranges to this array.
17030		 *
17031		 * @type {Array<Object>}
17032		 */
17033		this.updateRanges = [];
17034
17035		/**
17036		 * Configures the bound GPU type for use in shaders.
17037		 *
17038		 * Note: this only has an effect for integer arrays and is not configurable for float arrays.
17039		 * For lower precision float types, use `Float16BufferAttribute`.
17040		 *
17041		 * @type {(FloatType|IntType)}
17042		 * @default FloatType
17043		 */
17044		this.gpuType = FloatType;
17045
17046		/**
17047		 * A version number, incremented every time the `needsUpdate` is set to `true`.
17048		 *
17049		 * @type {number}
17050		 */
17051		this.version = 0;
17052
17053	}
17054
17055	/**
17056	 * A callback function that is executed after the renderer has transferred the attribute
17057	 * array data to the GPU.
17058	 */
17059	onUploadCallback() {}
17060
17061	/**
17062	 * Flag to indicate that this attribute has changed and should be re-sent to
17063	 * the GPU. Set this to `true` when you modify the value of the array.
17064	 *
17065	 * @type {number}
17066	 * @default false
17067	 * @param {boolean} value
17068	 */
17069	set needsUpdate( value ) {
17070
17071		if ( value === true ) this.version ++;
17072
17073	}
17074
17075	/**
17076	 * Sets the usage of this buffer attribute.
17077	 *
17078	 * @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
17079	 * @return {BufferAttribute} A reference to this buffer attribute.
17080	 */
17081	setUsage( value ) {
17082
17083		this.usage = value;
17084
17085		return this;
17086
17087	}
17088
17089	/**
17090	 * Adds a range of data in the data array to be updated on the GPU.
17091	 *
17092	 * @param {number} start - Position at which to start update.
17093	 * @param {number} count - The number of components to update.
17094	 */
17095	addUpdateRange( start, count ) {
17096
17097		this.updateRanges.push( { start, count } );
17098
17099	}
17100
17101	/**
17102	 * Clears the update ranges.
17103	 */
17104	clearUpdateRanges() {
17105
17106		this.updateRanges.length = 0;
17107
17108	}
17109
17110	/**
17111	 * Copies the values of the given buffer attribute to this instance.
17112	 *
17113	 * @param {BufferAttribute} source - The buffer attribute to copy.
17114	 * @return {BufferAttribute} A reference to this instance.
17115	 */
17116	copy( source ) {
17117
17118		this.name = source.name;
17119		this.array = new source.array.constructor( source.array );
17120		this.itemSize = source.itemSize;
17121		this.count = source.count;
17122		this.normalized = source.normalized;
17123
17124		this.usage = source.usage;
17125		this.gpuType = source.gpuType;
17126
17127		return this;
17128
17129	}
17130
17131	/**
17132	 * Copies a vector from the given buffer attribute to this one. The start
17133	 * and destination position in the attribute buffers are represented by the
17134	 * given indices.
17135	 *
17136	 * @param {number} index1 - The destination index into this buffer attribute.
17137	 * @param {BufferAttribute} attribute - The buffer attribute to copy from.
17138	 * @param {number} index2 - The source index into the given buffer attribute.
17139	 * @return {BufferAttribute} A reference to this instance.
17140	 */
17141	copyAt( index1, attribute, index2 ) {
17142
17143		index1 *= this.itemSize;
17144		index2 *= attribute.itemSize;
17145
17146		for ( let i = 0, l = this.itemSize; i < l; i ++ ) {
17147
17148			this.array[ index1 + i ] = attribute.array[ index2 + i ];
17149
17150		}
17151
17152		return this;
17153
17154	}
17155
17156	/**
17157	 * Copies the given array data into this buffer attribute.
17158	 *
17159	 * @param {(TypedArray|Array)} array - The array to copy.
17160	 * @return {BufferAttribute} A reference to this instance.
17161	 */
17162	copyArray( array ) {
17163
17164		this.array.set( array );
17165
17166		return this;
17167
17168	}
17169
17170	/**
17171	 * Applies the given 3x3 matrix to the given attribute. Works with
17172	 * item size `2` and `3`.
17173	 *
17174	 * @param {Matrix3} m - The matrix to apply.
17175	 * @return {BufferAttribute} A reference to this instance.
17176	 */
17177	applyMatrix3( m ) {
17178
17179		if ( this.itemSize === 2 ) {
17180
17181			for ( let i = 0, l = this.count; i < l; i ++ ) {
17182
17183				_vector2$1.fromBufferAttribute( this, i );
17184				_vector2$1.applyMatrix3( m );
17185
17186				this.setXY( i, _vector2$1.x, _vector2$1.y );
17187
17188			}
17189
17190		} else if ( this.itemSize === 3 ) {
17191
17192			for ( let i = 0, l = this.count; i < l; i ++ ) {
17193
17194				_vector$a.fromBufferAttribute( this, i );
17195				_vector$a.applyMatrix3( m );
17196
17197				this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
17198
17199			}
17200
17201		}
17202
17203		return this;
17204
17205	}
17206
17207	/**
17208	 * Applies the given 4x4 matrix to the given attribute. Only works with
17209	 * item size `3`.
17210	 *
17211	 * @param {Matrix4} m - The matrix to apply.
17212	 * @return {BufferAttribute} A reference to this instance.
17213	 */
17214	applyMatrix4( m ) {
17215
17216		for ( let i = 0, l = this.count; i < l; i ++ ) {
17217
17218			_vector$a.fromBufferAttribute( this, i );
17219
17220			_vector$a.applyMatrix4( m );
17221
17222			this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
17223
17224		}
17225
17226		return this;
17227
17228	}
17229
17230	/**
17231	 * Applies the given 3x3 normal matrix to the given attribute. Only works with
17232	 * item size `3`.
17233	 *
17234	 * @param {Matrix3} m - The normal matrix to apply.
17235	 * @return {BufferAttribute} A reference to this instance.
17236	 */
17237	applyNormalMatrix( m ) {
17238
17239		for ( let i = 0, l = this.count; i < l; i ++ ) {
17240
17241			_vector$a.fromBufferAttribute( this, i );
17242
17243			_vector$a.applyNormalMatrix( m );
17244
17245			this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
17246
17247		}
17248
17249		return this;
17250
17251	}
17252
17253	/**
17254	 * Applies the given 4x4 matrix to the given attribute. Only works with
17255	 * item size `3` and with direction vectors.
17256	 *
17257	 * @param {Matrix4} m - The matrix to apply.
17258	 * @return {BufferAttribute} A reference to this instance.
17259	 */
17260	transformDirection( m ) {
17261
17262		for ( let i = 0, l = this.count; i < l; i ++ ) {
17263
17264			_vector$a.fromBufferAttribute( this, i );
17265
17266			_vector$a.transformDirection( m );
17267
17268			this.setXYZ( i, _vector$a.x, _vector$a.y, _vector$a.z );
17269
17270		}
17271
17272		return this;
17273
17274	}
17275
17276	/**
17277	 * Sets the given array data in the buffer attribute.
17278	 *
17279	 * @param {(TypedArray|Array)} value - The array data to set.
17280	 * @param {number} [offset=0] - The offset in this buffer attribute's array.
17281	 * @return {BufferAttribute} A reference to this instance.
17282	 */
17283	set( value, offset = 0 ) {
17284
17285		// Matching BufferAttribute constructor, do not normalize the array.
17286		this.array.set( value, offset );
17287
17288		return this;
17289
17290	}
17291
17292	/**
17293	 * Returns the given component of the vector at the given index.
17294	 *
17295	 * @param {number} index - The index into the buffer attribute.
17296	 * @param {number} component - The component index.
17297	 * @return {number} The returned value.
17298	 */
17299	getComponent( index, component ) {
17300
17301		let value = this.array[ index * this.itemSize + component ];
17302
17303		if ( this.normalized ) value = denormalize( value, this.array );
17304
17305		return value;
17306
17307	}
17308
17309	/**
17310	 * Sets the given value to the given component of the vector at the given index.
17311	 *
17312	 * @param {number} index - The index into the buffer attribute.
17313	 * @param {number} component - The component index.
17314	 * @param {number} value - The value to set.
17315	 * @return {BufferAttribute} A reference to this instance.
17316	 */
17317	setComponent( index, component, value ) {
17318
17319		if ( this.normalized ) value = normalize( value, this.array );
17320
17321		this.array[ index * this.itemSize + component ] = value;
17322
17323		return this;
17324
17325	}
17326
17327	/**
17328	 * Returns the x component of the vector at the given index.
17329	 *
17330	 * @param {number} index - The index into the buffer attribute.
17331	 * @return {number} The x component.
17332	 */
17333	getX( index ) {
17334
17335		let x = this.array[ index * this.itemSize ];
17336
17337		if ( this.normalized ) x = denormalize( x, this.array );
17338
17339		return x;
17340
17341	}
17342
17343	/**
17344	 * Sets the x component of the vector at the given index.
17345	 *
17346	 * @param {number} index - The index into the buffer attribute.
17347	 * @param {number} x - The value to set.
17348	 * @return {BufferAttribute} A reference to this instance.
17349	 */
17350	setX( index, x ) {
17351
17352		if ( this.normalized ) x = normalize( x, this.array );
17353
17354		this.array[ index * this.itemSize ] = x;
17355
17356		return this;
17357
17358	}
17359
17360	/**
17361	 * Returns the y component of the vector at the given index.
17362	 *
17363	 * @param {number} index - The index into the buffer attribute.
17364	 * @return {number} The y component.
17365	 */
17366	getY( index ) {
17367
17368		let y = this.array[ index * this.itemSize + 1 ];
17369
17370		if ( this.normalized ) y = denormalize( y, this.array );
17371
17372		return y;
17373
17374	}
17375
17376	/**
17377	 * Sets the y component of the vector at the given index.
17378	 *
17379	 * @param {number} index - The index into the buffer attribute.
17380	 * @param {number} y - The value to set.
17381	 * @return {BufferAttribute} A reference to this instance.
17382	 */
17383	setY( index, y ) {
17384
17385		if ( this.normalized ) y = normalize( y, this.array );
17386
17387		this.array[ index * this.itemSize + 1 ] = y;
17388
17389		return this;
17390
17391	}
17392
17393	/**
17394	 * Returns the z component of the vector at the given index.
17395	 *
17396	 * @param {number} index - The index into the buffer attribute.
17397	 * @return {number} The z component.
17398	 */
17399	getZ( index ) {
17400
17401		let z = this.array[ index * this.itemSize + 2 ];
17402
17403		if ( this.normalized ) z = denormalize( z, this.array );
17404
17405		return z;
17406
17407	}
17408
17409	/**
17410	 * Sets the z component of the vector at the given index.
17411	 *
17412	 * @param {number} index - The index into the buffer attribute.
17413	 * @param {number} z - The value to set.
17414	 * @return {BufferAttribute} A reference to this instance.
17415	 */
17416	setZ( index, z ) {
17417
17418		if ( this.normalized ) z = normalize( z, this.array );
17419
17420		this.array[ index * this.itemSize + 2 ] = z;
17421
17422		return this;
17423
17424	}
17425
17426	/**
17427	 * Returns the w component of the vector at the given index.
17428	 *
17429	 * @param {number} index - The index into the buffer attribute.
17430	 * @return {number} The w component.
17431	 */
17432	getW( index ) {
17433
17434		let w = this.array[ index * this.itemSize + 3 ];
17435
17436		if ( this.normalized ) w = denormalize( w, this.array );
17437
17438		return w;
17439
17440	}
17441
17442	/**
17443	 * Sets the w component of the vector at the given index.
17444	 *
17445	 * @param {number} index - The index into the buffer attribute.
17446	 * @param {number} w - The value to set.
17447	 * @return {BufferAttribute} A reference to this instance.
17448	 */
17449	setW( index, w ) {
17450
17451		if ( this.normalized ) w = normalize( w, this.array );
17452
17453		this.array[ index * this.itemSize + 3 ] = w;
17454
17455		return this;
17456
17457	}
17458
17459	/**
17460	 * Sets the x and y component of the vector at the given index.
17461	 *
17462	 * @param {number} index - The index into the buffer attribute.
17463	 * @param {number} x - The value for the x component to set.
17464	 * @param {number} y - The value for the y component to set.
17465	 * @return {BufferAttribute} A reference to this instance.
17466	 */
17467	setXY( index, x, y ) {
17468
17469		index *= this.itemSize;
17470
17471		if ( this.normalized ) {
17472
17473			x = normalize( x, this.array );
17474			y = normalize( y, this.array );
17475
17476		}
17477
17478		this.array[ index + 0 ] = x;
17479		this.array[ index + 1 ] = y;
17480
17481		return this;
17482
17483	}
17484
17485	/**
17486	 * Sets the x, y and z component of the vector at the given index.
17487	 *
17488	 * @param {number} index - The index into the buffer attribute.
17489	 * @param {number} x - The value for the x component to set.
17490	 * @param {number} y - The value for the y component to set.
17491	 * @param {number} z - The value for the z component to set.
17492	 * @return {BufferAttribute} A reference to this instance.
17493	 */
17494	setXYZ( index, x, y, z ) {
17495
17496		index *= this.itemSize;
17497
17498		if ( this.normalized ) {
17499
17500			x = normalize( x, this.array );
17501			y = normalize( y, this.array );
17502			z = normalize( z, this.array );
17503
17504		}
17505
17506		this.array[ index + 0 ] = x;
17507		this.array[ index + 1 ] = y;
17508		this.array[ index + 2 ] = z;
17509
17510		return this;
17511
17512	}
17513
17514	/**
17515	 * Sets the x, y, z and w component of the vector at the given index.
17516	 *
17517	 * @param {number} index - The index into the buffer attribute.
17518	 * @param {number} x - The value for the x component to set.
17519	 * @param {number} y - The value for the y component to set.
17520	 * @param {number} z - The value for the z component to set.
17521	 * @param {number} w - The value for the w component to set.
17522	 * @return {BufferAttribute} A reference to this instance.
17523	 */
17524	setXYZW( index, x, y, z, w ) {
17525
17526		index *= this.itemSize;
17527
17528		if ( this.normalized ) {
17529
17530			x = normalize( x, this.array );
17531			y = normalize( y, this.array );
17532			z = normalize( z, this.array );
17533			w = normalize( w, this.array );
17534
17535		}
17536
17537		this.array[ index + 0 ] = x;
17538		this.array[ index + 1 ] = y;
17539		this.array[ index + 2 ] = z;
17540		this.array[ index + 3 ] = w;
17541
17542		return this;
17543
17544	}
17545
17546	/**
17547	 * Sets the given callback function that is executed after the Renderer has transferred
17548	 * the attribute array data to the GPU. Can be used to perform clean-up operations after
17549	 * the upload when attribute data are not needed anymore on the CPU side.
17550	 *
17551	 * @param {Function} callback - The `onUpload()` callback.
17552	 * @return {BufferAttribute} A reference to this instance.
17553	 */
17554	onUpload( callback ) {
17555
17556		this.onUploadCallback = callback;
17557
17558		return this;
17559
17560	}
17561
17562	/**
17563	 * Returns a new buffer attribute with copied values from this instance.
17564	 *
17565	 * @return {BufferAttribute} A clone of this instance.
17566	 */
17567	clone() {
17568
17569		return new this.constructor( this.array, this.itemSize ).copy( this );
17570
17571	}
17572
17573	/**
17574	 * Serializes the buffer attribute into JSON.
17575	 *
17576	 * @return {Object} A JSON object representing the serialized buffer attribute.
17577	 */
17578	toJSON() {
17579
17580		const data = {
17581			itemSize: this.itemSize,
17582			type: this.array.constructor.name,
17583			array: Array.from( this.array ),
17584			normalized: this.normalized
17585		};
17586
17587		data.name = this.name;
17588		data.usage = this.usage;
17589		data.gpuType = this.gpuType;
17590
17591		return data;
17592
17593	}
17594
17595	/**
17596	 * Disposes of the buffer attribute. Available only in {@link WebGPURenderer}.
17597	 */
17598	dispose() {
17599
17600		this.dispatchEvent( { type: 'dispose' } );
17601
17602	}
17603
17604}
17605
17606/**
17607 * Convenient class that can be used when creating a `Int8` buffer attribute with
17608 * a plain `Array` instance.
17609 *
17610 * @augments BufferAttribute
17611 */
17612class Int8BufferAttribute extends BufferAttribute {
17613
17614	/**
17615	 * Constructs a new buffer attribute.
17616	 *
17617	 * @param {(Array<number>|Int8Array)} array - The array holding the attribute data.
17618	 * @param {number} itemSize - The item size.
17619	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17620	 */
17621	constructor( array, itemSize, normalized ) {
17622
17623		super( new Int8Array( array ), itemSize, normalized );
17624
17625	}
17626
17627}
17628
17629/**
17630 * Convenient class that can be used when creating a `UInt8` buffer attribute with
17631 * a plain `Array` instance.
17632 *
17633 * @augments BufferAttribute
17634 */
17635class Uint8BufferAttribute extends BufferAttribute {
17636
17637	/**
17638	 * Constructs a new buffer attribute.
17639	 *
17640	 * @param {(Array<number>|Uint8Array)} array - The array holding the attribute data.
17641	 * @param {number} itemSize - The item size.
17642	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17643	 */
17644	constructor( array, itemSize, normalized ) {
17645
17646		super( new Uint8Array( array ), itemSize, normalized );
17647
17648	}
17649
17650}
17651
17652/**
17653 * Convenient class that can be used when creating a `UInt8Clamped` buffer attribute with
17654 * a plain `Array` instance.
17655 *
17656 * @augments BufferAttribute
17657 */
17658class Uint8ClampedBufferAttribute extends BufferAttribute {
17659
17660	/**
17661	 * Constructs a new buffer attribute.
17662	 *
17663	 * @param {(Array<number>|Uint8ClampedArray)} array - The array holding the attribute data.
17664	 * @param {number} itemSize - The item size.
17665	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17666	 */
17667	constructor( array, itemSize, normalized ) {
17668
17669		super( new Uint8ClampedArray( array ), itemSize, normalized );
17670
17671	}
17672
17673}
17674
17675/**
17676 * Convenient class that can be used when creating a `Int16` buffer attribute with
17677 * a plain `Array` instance.
17678 *
17679 * @augments BufferAttribute
17680 */
17681class Int16BufferAttribute extends BufferAttribute {
17682
17683	/**
17684	 * Constructs a new buffer attribute.
17685	 *
17686	 * @param {(Array<number>|Int16Array)} array - The array holding the attribute data.
17687	 * @param {number} itemSize - The item size.
17688	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17689	 */
17690	constructor( array, itemSize, normalized ) {
17691
17692		super( new Int16Array( array ), itemSize, normalized );
17693
17694	}
17695
17696}
17697
17698/**
17699 * Convenient class that can be used when creating a `UInt16` buffer attribute with
17700 * a plain `Array` instance.
17701 *
17702 * @augments BufferAttribute
17703 */
17704class Uint16BufferAttribute extends BufferAttribute {
17705
17706	/**
17707	 * Constructs a new buffer attribute.
17708	 *
17709	 * @param {(Array<number>|Uint16Array)} array - The array holding the attribute data.
17710	 * @param {number} itemSize - The item size.
17711	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17712	 */
17713	constructor( array, itemSize, normalized ) {
17714
17715		super( new Uint16Array( array ), itemSize, normalized );
17716
17717	}
17718
17719}
17720
17721/**
17722 * Convenient class that can be used when creating a `Int32` buffer attribute with
17723 * a plain `Array` instance.
17724 *
17725 * @augments BufferAttribute
17726 */
17727class Int32BufferAttribute extends BufferAttribute {
17728
17729	/**
17730	 * Constructs a new buffer attribute.
17731	 *
17732	 * @param {(Array<number>|Int32Array)} array - The array holding the attribute data.
17733	 * @param {number} itemSize - The item size.
17734	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17735	 */
17736	constructor( array, itemSize, normalized ) {
17737
17738		super( new Int32Array( array ), itemSize, normalized );
17739
17740	}
17741
17742}
17743
17744/**
17745 * Convenient class that can be used when creating a `UInt32` buffer attribute with
17746 * a plain `Array` instance.
17747 *
17748 * @augments BufferAttribute
17749 */
17750class Uint32BufferAttribute extends BufferAttribute {
17751
17752	/**
17753	 * Constructs a new buffer attribute.
17754	 *
17755	 * @param {(Array<number>|Uint32Array)} array - The array holding the attribute data.
17756	 * @param {number} itemSize - The item size.
17757	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17758	 */
17759	constructor( array, itemSize, normalized ) {
17760
17761		super( new Uint32Array( array ), itemSize, normalized );
17762
17763	}
17764
17765}
17766
17767/**
17768 * Convenient class that can be used when creating a `Float16` buffer attribute with
17769 * a plain `Array` instance.
17770 *
17771 * This class automatically converts to and from FP16 via `Uint16Array` since `Float16Array`
17772 * browser support is still problematic.
17773 *
17774 * @augments BufferAttribute
17775 */
17776class Float16BufferAttribute extends BufferAttribute {
17777
17778	/**
17779	 * Constructs a new buffer attribute.
17780	 *
17781	 * @param {(Array<number>|Uint16Array)} array - The array holding the attribute data.
17782	 * @param {number} itemSize - The item size.
17783	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17784	 */
17785	constructor( array, itemSize, normalized ) {
17786
17787		super( new Uint16Array( array ), itemSize, normalized );
17788
17789		this.isFloat16BufferAttribute = true;
17790
17791	}
17792
17793	getX( index ) {
17794
17795		let x = fromHalfFloat( this.array[ index * this.itemSize ] );
17796
17797		if ( this.normalized ) x = denormalize( x, this.array );
17798
17799		return x;
17800
17801	}
17802
17803	setX( index, x ) {
17804
17805		if ( this.normalized ) x = normalize( x, this.array );
17806
17807		this.array[ index * this.itemSize ] = toHalfFloat( x );
17808
17809		return this;
17810
17811	}
17812
17813	getY( index ) {
17814
17815		let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] );
17816
17817		if ( this.normalized ) y = denormalize( y, this.array );
17818
17819		return y;
17820
17821	}
17822
17823	setY( index, y ) {
17824
17825		if ( this.normalized ) y = normalize( y, this.array );
17826
17827		this.array[ index * this.itemSize + 1 ] = toHalfFloat( y );
17828
17829		return this;
17830
17831	}
17832
17833	getZ( index ) {
17834
17835		let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] );
17836
17837		if ( this.normalized ) z = denormalize( z, this.array );
17838
17839		return z;
17840
17841	}
17842
17843	setZ( index, z ) {
17844
17845		if ( this.normalized ) z = normalize( z, this.array );
17846
17847		this.array[ index * this.itemSize + 2 ] = toHalfFloat( z );
17848
17849		return this;
17850
17851	}
17852
17853	getW( index ) {
17854
17855		let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] );
17856
17857		if ( this.normalized ) w = denormalize( w, this.array );
17858
17859		return w;
17860
17861	}
17862
17863	setW( index, w ) {
17864
17865		if ( this.normalized ) w = normalize( w, this.array );
17866
17867		this.array[ index * this.itemSize + 3 ] = toHalfFloat( w );
17868
17869		return this;
17870
17871	}
17872
17873	setXY( index, x, y ) {
17874
17875		index *= this.itemSize;
17876
17877		if ( this.normalized ) {
17878
17879			x = normalize( x, this.array );
17880			y = normalize( y, this.array );
17881
17882		}
17883
17884		this.array[ index + 0 ] = toHalfFloat( x );
17885		this.array[ index + 1 ] = toHalfFloat( y );
17886
17887		return this;
17888
17889	}
17890
17891	setXYZ( index, x, y, z ) {
17892
17893		index *= this.itemSize;
17894
17895		if ( this.normalized ) {
17896
17897			x = normalize( x, this.array );
17898			y = normalize( y, this.array );
17899			z = normalize( z, this.array );
17900
17901		}
17902
17903		this.array[ index + 0 ] = toHalfFloat( x );
17904		this.array[ index + 1 ] = toHalfFloat( y );
17905		this.array[ index + 2 ] = toHalfFloat( z );
17906
17907		return this;
17908
17909	}
17910
17911	setXYZW( index, x, y, z, w ) {
17912
17913		index *= this.itemSize;
17914
17915		if ( this.normalized ) {
17916
17917			x = normalize( x, this.array );
17918			y = normalize( y, this.array );
17919			z = normalize( z, this.array );
17920			w = normalize( w, this.array );
17921
17922		}
17923
17924		this.array[ index + 0 ] = toHalfFloat( x );
17925		this.array[ index + 1 ] = toHalfFloat( y );
17926		this.array[ index + 2 ] = toHalfFloat( z );
17927		this.array[ index + 3 ] = toHalfFloat( w );
17928
17929		return this;
17930
17931	}
17932
17933}
17934
17935/**
17936 * Convenient class that can be used when creating a `Float32` buffer attribute with
17937 * a plain `Array` instance.
17938 *
17939 * @augments BufferAttribute
17940 */
17941class Float32BufferAttribute extends BufferAttribute {
17942
17943	/**
17944	 * Constructs a new buffer attribute.
17945	 *
17946	 * @param {(Array<number>|Float32Array)} array - The array holding the attribute data.
17947	 * @param {number} itemSize - The item size.
17948	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
17949	 */
17950	constructor( array, itemSize, normalized ) {
17951
17952		super( new Float32Array( array ), itemSize, normalized );
17953
17954	}
17955
17956}
17957
17958const _box$3 = /*@__PURE__*/ new Box3();
17959const _v1$3 = /*@__PURE__*/ new Vector3();
17960const _v2$2 = /*@__PURE__*/ new Vector3();
17961
17962/**
17963 * An analytical 3D sphere defined by a center and radius. This class is mainly
17964 * used as a Bounding Sphere for 3D objects.
17965 */
17966class Sphere {
17967
17968	/**
17969	 * Constructs a new sphere.
17970	 *
17971	 * @param {Vector3} [center=(0,0,0)] - The center of the sphere
17972	 * @param {number} [radius=-1] - The radius of the sphere.
17973	 */
17974	constructor( center = new Vector3(), radius = -1 ) {
17975
17976		/**
17977		 * This flag can be used for type testing.
17978		 *
17979		 * @type {boolean}
17980		 * @readonly
17981		 * @default true
17982		 */
17983		this.isSphere = true;
17984
17985		/**
17986		 * The center of the sphere
17987		 *
17988		 * @type {Vector3}
17989		 */
17990		this.center = center;
17991
17992		/**
17993		 * The radius of the sphere.
17994		 *
17995		 * @type {number}
17996		 */
17997		this.radius = radius;
17998
17999	}
18000
18001	/**
18002	 * Sets the sphere's components by copying the given values.
18003	 *
18004	 * @param {Vector3} center - The center.
18005	 * @param {number} radius - The radius.
18006	 * @return {Sphere} A reference to this sphere.
18007	 */
18008	set( center, radius ) {
18009
18010		this.center.copy( center );
18011		this.radius = radius;
18012
18013		return this;
18014
18015	}
18016
18017	/**
18018	 * Computes the minimum bounding sphere for list of points.
18019	 * If the optional center point is given, it is used as the sphere's
18020	 * center. Otherwise, the center of the axis-aligned bounding box
18021	 * encompassing the points is calculated.
18022	 *
18023	 * @param {Array<Vector3>} points - A list of points in 3D space.
18024	 * @param {Vector3} [optionalCenter] - The center of the sphere.
18025	 * @return {Sphere} A reference to this sphere.
18026	 */
18027	setFromPoints( points, optionalCenter ) {
18028
18029		const center = this.center;
18030
18031		if ( optionalCenter !== undefined ) {
18032
18033			center.copy( optionalCenter );
18034
18035		} else {
18036
18037			_box$3.setFromPoints( points ).getCenter( center );
18038
18039		}
18040
18041		let maxRadiusSq = 0;
18042
18043		for ( let i = 0, il = points.length; i < il; i ++ ) {
18044
18045			maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );
18046
18047		}
18048
18049		this.radius = Math.sqrt( maxRadiusSq );
18050
18051		return this;
18052
18053	}
18054
18055	/**
18056	 * Copies the values of the given sphere to this instance.
18057	 *
18058	 * @param {Sphere} sphere - The sphere to copy.
18059	 * @return {Sphere} A reference to this sphere.
18060	 */
18061	copy( sphere ) {
18062
18063		this.center.copy( sphere.center );
18064		this.radius = sphere.radius;
18065
18066		return this;
18067
18068	}
18069
18070	/**
18071	 * Returns `true` if the sphere is empty (the radius set to a negative number).
18072	 *
18073	 * Spheres with a radius of `0` contain only their center point and are not
18074	 * considered to be empty.
18075	 *
18076	 * @return {boolean} Whether this sphere is empty or not.
18077	 */
18078	isEmpty() {
18079
18080		return ( this.radius < 0 );
18081
18082	}
18083
18084	/**
18085	 * Makes this sphere empty which means in encloses a zero space in 3D.
18086	 *
18087	 * @return {Sphere} A reference to this sphere.
18088	 */
18089	makeEmpty() {
18090
18091		this.center.set( 0, 0, 0 );
18092		this.radius = -1;
18093
18094		return this;
18095
18096	}
18097
18098	/**
18099	 * Returns `true` if this sphere contains the given point inclusive of
18100	 * the surface of the sphere.
18101	 *
18102	 * @param {Vector3} point - The point to check.
18103	 * @return {boolean} Whether this sphere contains the given point or not.
18104	 */
18105	containsPoint( point ) {
18106
18107		return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );
18108
18109	}
18110
18111	/**
18112	 * Returns the closest distance from the boundary of the sphere to the
18113	 * given point. If the sphere contains the point, the distance will
18114	 * be negative.
18115	 *
18116	 * @param {Vector3} point - The point to compute the distance to.
18117	 * @return {number} The distance to the point.
18118	 */
18119	distanceToPoint( point ) {
18120
18121		return ( point.distanceTo( this.center ) - this.radius );
18122
18123	}
18124
18125	/**
18126	 * Returns `true` if this sphere intersects with the given one.
18127	 *
18128	 * @param {Sphere} sphere - The sphere to test.
18129	 * @return {boolean} Whether this sphere intersects with the given one or not.
18130	 */
18131	intersectsSphere( sphere ) {
18132
18133		const radiusSum = this.radius + sphere.radius;
18134
18135		return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
18136
18137	}
18138
18139	/**
18140	 * Returns `true` if this sphere intersects with the given box.
18141	 *
18142	 * @param {Box3} box - The box to test.
18143	 * @return {boolean} Whether this sphere intersects with the given box or not.
18144	 */
18145	intersectsBox( box ) {
18146
18147		return box.intersectsSphere( this );
18148
18149	}
18150
18151	/**
18152	 * Returns `true` if this sphere intersects with the given plane.
18153	 *
18154	 * @param {Plane} plane - The plane to test.
18155	 * @return {boolean} Whether this sphere intersects with the given plane or not.
18156	 */
18157	intersectsPlane( plane ) {
18158
18159		return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;
18160
18161	}
18162
18163	/**
18164	 * Clamps a point within the sphere. If the point is outside the sphere, it
18165	 * will clamp it to the closest point on the edge of the sphere. Points
18166	 * already inside the sphere will not be affected.
18167	 *
18168	 * @param {Vector3} point - The plane to clamp.
18169	 * @param {Vector3} target - The target vector that is used to store the method's result.
18170	 * @return {Vector3} The clamped point.
18171	 */
18172	clampPoint( point, target ) {
18173
18174		const deltaLengthSq = this.center.distanceToSquared( point );
18175
18176		target.copy( point );
18177
18178		if ( deltaLengthSq > ( this.radius * this.radius ) ) {
18179
18180			target.sub( this.center ).normalize();
18181			target.multiplyScalar( this.radius ).add( this.center );
18182
18183		}
18184
18185		return target;
18186
18187	}
18188
18189	/**
18190	 * Returns a bounding box that encloses this sphere.
18191	 *
18192	 * @param {Box3} target - The target box that is used to store the method's result.
18193	 * @return {Box3} The bounding box that encloses this sphere.
18194	 */
18195	getBoundingBox( target ) {
18196
18197		if ( this.isEmpty() ) {
18198
18199			// Empty sphere produces empty bounding box
18200			target.makeEmpty();
18201			return target;
18202
18203		}
18204
18205		target.set( this.center, this.center );
18206		target.expandByScalar( this.radius );
18207
18208		return target;
18209
18210	}
18211
18212	/**
18213	 * Transforms this sphere with the given 4x4 transformation matrix.
18214	 *
18215	 * @param {Matrix4} matrix - The transformation matrix.
18216	 * @return {Sphere} A reference to this sphere.
18217	 */
18218	applyMatrix4( matrix ) {
18219
18220		this.center.applyMatrix4( matrix );
18221		this.radius = this.radius * matrix.getMaxScaleOnAxis();
18222
18223		return this;
18224
18225	}
18226
18227	/**
18228	 * Translates the sphere's center by the given offset.
18229	 *
18230	 * @param {Vector3} offset - The offset.
18231	 * @return {Sphere} A reference to this sphere.
18232	 */
18233	translate( offset ) {
18234
18235		this.center.add( offset );
18236
18237		return this;
18238
18239	}
18240
18241	/**
18242	 * Expands the boundaries of this sphere to include the given point.
18243	 *
18244	 * @param {Vector3} point - The point to include.
18245	 * @return {Sphere} A reference to this sphere.
18246	 */
18247	expandByPoint( point ) {
18248
18249		if ( this.isEmpty() ) {
18250
18251			this.center.copy( point );
18252
18253			this.radius = 0;
18254
18255			return this;
18256
18257		}
18258
18259		_v1$3.subVectors( point, this.center );
18260
18261		const lengthSq = _v1$3.lengthSq();
18262
18263		if ( lengthSq > ( this.radius * this.radius ) ) {
18264
18265			// calculate the minimal sphere
18266
18267			const length = Math.sqrt( lengthSq );
18268
18269			const delta = ( length - this.radius ) * 0.5;
18270
18271			this.center.addScaledVector( _v1$3, delta / length );
18272
18273			this.radius += delta;
18274
18275		}
18276
18277		return this;
18278
18279	}
18280
18281	/**
18282	 * Expands this sphere to enclose both the original sphere and the given sphere.
18283	 *
18284	 * @param {Sphere} sphere - The sphere to include.
18285	 * @return {Sphere} A reference to this sphere.
18286	 */
18287	union( sphere ) {
18288
18289		if ( sphere.isEmpty() ) {
18290
18291			return this;
18292
18293		}
18294
18295		if ( this.isEmpty() ) {
18296
18297			this.copy( sphere );
18298
18299			return this;
18300
18301		}
18302
18303		if ( this.center.equals( sphere.center ) === true ) {
18304
18305			 this.radius = Math.max( this.radius, sphere.radius );
18306
18307		} else {
18308
18309			_v2$2.subVectors( sphere.center, this.center ).setLength( sphere.radius );
18310
18311			this.expandByPoint( _v1$3.copy( sphere.center ).add( _v2$2 ) );
18312
18313			this.expandByPoint( _v1$3.copy( sphere.center ).sub( _v2$2 ) );
18314
18315		}
18316
18317		return this;
18318
18319	}
18320
18321	/**
18322	 * Returns `true` if this sphere is equal with the given one.
18323	 *
18324	 * @param {Sphere} sphere - The sphere to test for equality.
18325	 * @return {boolean} Whether this bounding sphere is equal with the given one.
18326	 */
18327	equals( sphere ) {
18328
18329		return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
18330
18331	}
18332
18333	/**
18334	 * Returns a new sphere with copied values from this instance.
18335	 *
18336	 * @return {Sphere} A clone of this instance.
18337	 */
18338	clone() {
18339
18340		return new this.constructor().copy( this );
18341
18342	}
18343
18344	/**
18345	 * Returns a serialized structure of the bounding sphere.
18346	 *
18347	 * @return {Object} Serialized structure with fields representing the object state.
18348	 */
18349	toJSON() {
18350
18351		return {
18352			radius: this.radius,
18353			center: this.center.toArray()
18354		};
18355
18356	}
18357
18358	/**
18359	 * Returns a serialized structure of the bounding sphere.
18360	 *
18361	 * @param {Object} json - The serialized json to set the sphere from.
18362	 * @return {Sphere} A reference to this bounding sphere.
18363	 */
18364	fromJSON( json ) {
18365
18366		this.radius = json.radius;
18367		this.center.fromArray( json.center );
18368		return this;
18369
18370	}
18371
18372}
18373
18374let _id$1 = 0;
18375
18376const _m1 = /*@__PURE__*/ new Matrix4();
18377const _obj = /*@__PURE__*/ new Object3D();
18378const _offset = /*@__PURE__*/ new Vector3();
18379const _box$2 = /*@__PURE__*/ new Box3();
18380const _boxMorphTargets = /*@__PURE__*/ new Box3();
18381const _vector$9 = /*@__PURE__*/ new Vector3();
18382
18383/**
18384 * A representation of mesh, line, or point geometry. Includes vertex
18385 * positions, face indices, normals, colors, UVs, and custom attributes
18386 * within buffers, reducing the cost of passing all this data to the GPU.
18387 *
18388 * ```js
18389 * const geometry = new THREE.BufferGeometry();
18390 * // create a simple square shape. We duplicate the top left and bottom right
18391 * // vertices because each vertex needs to appear once per triangle.
18392 * const vertices = new Float32Array( [
18393 * 	-1.0, -1.0,  1.0, // v0
18394 * 	 1.0, -1.0,  1.0, // v1
18395 * 	 1.0,  1.0,  1.0, // v2
18396 *
18397 * 	 1.0,  1.0,  1.0, // v3
18398 * 	-1.0,  1.0,  1.0, // v4
18399 * 	-1.0, -1.0,  1.0  // v5
18400 * ] );
18401 * // itemSize = 3 because there are 3 values (components) per vertex
18402 * geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
18403 * const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
18404 * const mesh = new THREE.Mesh( geometry, material );
18405 * ```
18406 *
18407 * @augments EventDispatcher
18408 */
18409class BufferGeometry extends EventDispatcher {
18410
18411	/**
18412	 * Constructs a new geometry.
18413	 */
18414	constructor() {
18415
18416		super();
18417
18418		/**
18419		 * This flag can be used for type testing.
18420		 *
18421		 * @type {boolean}
18422		 * @readonly
18423		 * @default true
18424		 */
18425		this.isBufferGeometry = true;
18426
18427		/**
18428		 * The ID of the geometry.
18429		 *
18430		 * @name BufferGeometry#id
18431		 * @type {number}
18432		 * @readonly
18433		 */
18434		Object.defineProperty( this, 'id', { value: _id$1 ++ } );
18435
18436		/**
18437		 * The UUID of the geometry.
18438		 *
18439		 * @type {string}
18440		 * @readonly
18441		 */
18442		this.uuid = generateUUID();
18443
18444		/**
18445		 * The name of the geometry.
18446		 *
18447		 * @type {string}
18448		 */
18449		this.name = '';
18450		this.type = 'BufferGeometry';
18451
18452		/**
18453		 * Allows for vertices to be re-used across multiple triangles; this is
18454		 * called using "indexed triangles". Each triangle is associated with the
18455		 * indices of three vertices. This attribute therefore stores the index of
18456		 * each vertex for each triangular face. If this attribute is not set, the
18457		 * renderer assumes that each three contiguous positions represent a single triangle.
18458		 *
18459		 * @type {?BufferAttribute}
18460		 * @default null
18461		 */
18462		this.index = null;
18463
18464		/**
18465		 * A (storage) buffer attribute which was generated with a compute shader and
18466		 * now defines indirect draw calls.
18467		 *
18468		 * Can only be used with {@link WebGPURenderer} and a WebGPU backend.
18469		 *
18470		 * @type {?BufferAttribute}
18471		 * @default null
18472		 */
18473		this.indirect = null;
18474
18475		/**
18476		 * The offset, in bytes, into the indirect drawing buffer where the value data begins. If an array is provided, multiple indirect draw calls will be made for each offset.
18477		 *
18478		 * Can only be used with {@link WebGPURenderer} and a WebGPU backend.
18479		 *
18480		 * @type {number|Array<number>}
18481		 * @default 0
18482		 */
18483		this.indirectOffset = 0;
18484
18485		/**
18486		 * This dictionary has as id the name of the attribute to be set and as value
18487		 * the buffer attribute to set it to. Rather than accessing this property directly,
18488		 * use `setAttribute()` and `getAttribute()` to access attributes of this geometry.
18489		 *
18490		 * @type {Object<string,(BufferAttribute|InterleavedBufferAttribute)>}
18491		 */
18492		this.attributes = {};
18493
18494		/**
18495		 * This dictionary holds the morph targets of the geometry.
18496		 *
18497		 * Note: Once the geometry has been rendered, the morph attribute data cannot
18498		 * be changed. You will have to call `dispose()`, and create a new geometry instance.
18499		 *
18500		 * @type {Object}
18501		 */
18502		this.morphAttributes = {};
18503
18504		/**
18505		 * Used to control the morph target behavior; when set to `true`, the morph
18506		 * target data is treated as relative offsets, rather than as absolute
18507		 * positions/normals.
18508		 *
18509		 * @type {boolean}
18510		 * @default false
18511		 */
18512		this.morphTargetsRelative = false;
18513
18514		/**
18515		 * Split the geometry into groups, each of which will be rendered in a
18516		 * separate draw call. This allows an array of materials to be used with the geometry.
18517		 *
18518		 * Use `addGroup()` and `clearGroups()` to edit groups, rather than modifying this array directly.
18519		 *
18520		 * Every vertex and index must belong to exactly one group — groups must not share vertices or
18521		 * indices, and must not leave vertices or indices unused.
18522		 *
18523		 * @type {Array<Object>}
18524		 */
18525		this.groups = [];
18526
18527		/**
18528		 * Bounding box for the geometry which can be calculated with `computeBoundingBox()`.
18529		 *
18530		 * @type {?Box3}
18531		 * @default null
18532		 */
18533		this.boundingBox = null;
18534
18535		/**
18536		 * Bounding sphere for the geometry which can be calculated with `computeBoundingSphere()`.
18537		 *
18538		 * @type {?Sphere}
18539		 * @default null
18540		 */
18541		this.boundingSphere = null;
18542
18543		/**
18544		 * Determines the part of the geometry to render. This should not be set directly,
18545		 * instead use `setDrawRange()`.
18546		 *
18547		 * @type {{start:number,count:number}}
18548		 */
18549		this.drawRange = { start: 0, count: Infinity };
18550
18551		/**
18552		 * An object that can be used to store custom data about the geometry.
18553		 * It should not hold references to functions as these will not be cloned.
18554		 *
18555		 * @type {Object}
18556		 */
18557		this.userData = {};
18558
18559		/**
18560		 * `true` when the geometry has been transformed since construction
18561		 * (e.g. via {@link BufferGeometry#applyMatrix4}). Only relevant for
18562		 * geometry generators (subclasses that populate `parameters`): when set,
18563		 * {@link BufferGeometry#toJSON} omits `parameters` since they no longer
18564		 * describe the geometry.
18565		 *
18566		 * @private
18567		 * @type {boolean}
18568		 * @default false
18569		 */
18570		this._transformed = false;
18571
18572	}
18573
18574	/**
18575	 * Returns the index of this geometry.
18576	 *
18577	 * @return {?BufferAttribute} The index. Returns `null` if no index is defined.
18578	 */
18579	getIndex() {
18580
18581		return this.index;
18582
18583	}
18584
18585	/**
18586	 * Sets the given index to this geometry.
18587	 *
18588	 * @param {Array<number>|BufferAttribute} index - The index to set.
18589	 * @return {BufferGeometry} A reference to this instance.
18590	 */
18591	setIndex( index ) {
18592
18593		if ( Array.isArray( index ) ) {
18594
18595			this.index = new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
18596
18597		} else {
18598
18599			this.index = index;
18600
18601		}
18602
18603		return this;
18604
18605	}
18606
18607	/**
18608	 * Sets the given indirect attribute to this geometry.
18609	 *
18610	 * @param {BufferAttribute} indirect - The attribute holding indirect draw calls.
18611	 * @param {number|Array<number>} [indirectOffset=0] - The offset, in bytes, into the indirect drawing buffer where the value data begins. If an array is provided, multiple indirect draw calls will be made for each offset.
18612	 * @return {BufferGeometry} A reference to this instance.
18613	 */
18614	setIndirect( indirect, indirectOffset = 0 ) {
18615
18616		this.indirect = indirect;
18617		this.indirectOffset = indirectOffset;
18618
18619		return this;
18620
18621	}
18622
18623	/**
18624	 * Returns the indirect attribute of this geometry.
18625	 *
18626	 * @return {?BufferAttribute} The indirect attribute. Returns `null` if no indirect attribute is defined.
18627	 */
18628	getIndirect() {
18629
18630		return this.indirect;
18631
18632	}
18633
18634	/**
18635	 * Returns the buffer attribute for the given name.
18636	 *
18637	 * @param {string} name - The attribute name.
18638	 * @return {BufferAttribute|InterleavedBufferAttribute|undefined} The buffer attribute.
18639	 * Returns `undefined` if not attribute has been found.
18640	 */
18641	getAttribute( name ) {
18642
18643		return this.attributes[ name ];
18644
18645	}
18646
18647	/**
18648	 * Sets the given attribute for the given name.
18649	 *
18650	 * @param {string} name - The attribute name.
18651	 * @param {BufferAttribute|InterleavedBufferAttribute} attribute - The attribute to set.
18652	 * @return {BufferGeometry} A reference to this instance.
18653	 */
18654	setAttribute( name, attribute ) {
18655
18656		this.attributes[ name ] = attribute;
18657
18658		return this;
18659
18660	}
18661
18662	/**
18663	 * Deletes the attribute for the given name.
18664	 *
18665	 * @param {string} name - The attribute name to delete.
18666	 * @return {BufferGeometry} A reference to this instance.
18667	 */
18668	deleteAttribute( name ) {
18669
18670		delete this.attributes[ name ];
18671
18672		return this;
18673
18674	}
18675
18676	/**
18677	 * Returns `true` if this geometry has an attribute for the given name.
18678	 *
18679	 * @param {string} name - The attribute name.
18680	 * @return {boolean} Whether this geometry has an attribute for the given name or not.
18681	 */
18682	hasAttribute( name ) {
18683
18684		return this.attributes[ name ] !== undefined;
18685
18686	}
18687
18688	/**
18689	 * Adds a group to this geometry.
18690	 *
18691	 * @param {number} start - The first element in this draw call. That is the first
18692	 * vertex for non-indexed geometry, otherwise the first triangle index.
18693	 * @param {number} count - Specifies how many vertices (or indices) are part of this group.
18694	 * @param {number} [materialIndex=0] - The material array index to use.
18695	 */
18696	addGroup( start, count, materialIndex = 0 ) {
18697
18698		this.groups.push( {
18699
18700			start: start,
18701			count: count,
18702			materialIndex: materialIndex
18703
18704		} );
18705
18706	}
18707
18708	/**
18709	 * Clears all groups.
18710	 */
18711	clearGroups() {
18712
18713		this.groups = [];
18714
18715	}
18716
18717	/**
18718	 * Sets the draw range for this geometry.
18719	 *
18720	 * @param {number} start - The first vertex for non-indexed geometry, otherwise the first triangle index.
18721	 * @param {number} count - For non-indexed BufferGeometry, `count` is the number of vertices to render.
18722	 * For indexed BufferGeometry, `count` is the number of indices to render.
18723	 */
18724	setDrawRange( start, count ) {
18725
18726		this.drawRange.start = start;
18727		this.drawRange.count = count;
18728
18729	}
18730
18731	/**
18732	 * Applies the given 4x4 transformation matrix to the geometry.
18733	 *
18734	 * @param {Matrix4} matrix - The matrix to apply.
18735	 * @return {BufferGeometry} A reference to this instance.
18736	 */
18737	applyMatrix4( matrix ) {
18738
18739		const position = this.attributes.position;
18740
18741		if ( position !== undefined ) {
18742
18743			position.applyMatrix4( matrix );
18744
18745			position.needsUpdate = true;
18746
18747		}
18748
18749		const normal = this.attributes.normal;
18750
18751		if ( normal !== undefined ) {
18752
18753			const normalMatrix = new Matrix3().getNormalMatrix( matrix );
18754
18755			normal.applyNormalMatrix( normalMatrix );
18756
18757			normal.needsUpdate = true;
18758
18759		}
18760
18761		const tangent = this.attributes.tangent;
18762
18763		if ( tangent !== undefined ) {
18764
18765			tangent.transformDirection( matrix );
18766
18767			tangent.needsUpdate = true;
18768
18769		}
18770
18771		if ( this.boundingBox !== null ) {
18772
18773			this.computeBoundingBox();
18774
18775		}
18776
18777		if ( this.boundingSphere !== null ) {
18778
18779			this.computeBoundingSphere();
18780
18781		}
18782
18783		this._transformed = true;
18784
18785		return this;
18786
18787	}
18788
18789	/**
18790	 * Applies the rotation represented by the Quaternion to the geometry.
18791	 *
18792	 * @param {Quaternion} q - The Quaternion to apply.
18793	 * @return {BufferGeometry} A reference to this instance.
18794	 */
18795	applyQuaternion( q ) {
18796
18797		_m1.makeRotationFromQuaternion( q );
18798
18799		this.applyMatrix4( _m1 );
18800
18801		return this;
18802
18803	}
18804
18805	/**
18806	 * Rotates the geometry about the X axis. This is typically done as a one time
18807	 * operation, and not during a loop. Use {@link Object3D#rotation} for typical
18808	 * real-time mesh rotation.
18809	 *
18810	 * @param {number} angle - The angle in radians.
18811	 * @return {BufferGeometry} A reference to this instance.
18812	 */
18813	rotateX( angle ) {
18814
18815		// rotate geometry around world x-axis
18816
18817		_m1.makeRotationX( angle );
18818
18819		this.applyMatrix4( _m1 );
18820
18821		return this;
18822
18823	}
18824
18825	/**
18826	 * Rotates the geometry about the Y axis. This is typically done as a one time
18827	 * operation, and not during a loop. Use {@link Object3D#rotation} for typical
18828	 * real-time mesh rotation.
18829	 *
18830	 * @param {number} angle - The angle in radians.
18831	 * @return {BufferGeometry} A reference to this instance.
18832	 */
18833	rotateY( angle ) {
18834
18835		// rotate geometry around world y-axis
18836
18837		_m1.makeRotationY( angle );
18838
18839		this.applyMatrix4( _m1 );
18840
18841		return this;
18842
18843	}
18844
18845	/**
18846	 * Rotates the geometry about the Z axis. This is typically done as a one time
18847	 * operation, and not during a loop. Use {@link Object3D#rotation} for typical
18848	 * real-time mesh rotation.
18849	 *
18850	 * @param {number} angle - The angle in radians.
18851	 * @return {BufferGeometry} A reference to this instance.
18852	 */
18853	rotateZ( angle ) {
18854
18855		// rotate geometry around world z-axis
18856
18857		_m1.makeRotationZ( angle );
18858
18859		this.applyMatrix4( _m1 );
18860
18861		return this;
18862
18863	}
18864
18865	/**
18866	 * Translates the geometry. This is typically done as a one time
18867	 * operation, and not during a loop. Use {@link Object3D#position} for typical
18868	 * real-time mesh rotation.
18869	 *
18870	 * @param {number} x - The x offset.
18871	 * @param {number} y - The y offset.
18872	 * @param {number} z - The z offset.
18873	 * @return {BufferGeometry} A reference to this instance.
18874	 */
18875	translate( x, y, z ) {
18876
18877		// translate geometry
18878
18879		_m1.makeTranslation( x, y, z );
18880
18881		this.applyMatrix4( _m1 );
18882
18883		return this;
18884
18885	}
18886
18887	/**
18888	 * Scales the geometry. This is typically done as a one time
18889	 * operation, and not during a loop. Use {@link Object3D#scale} for typical
18890	 * real-time mesh rotation.
18891	 *
18892	 * @param {number} x - The x scale.
18893	 * @param {number} y - The y scale.
18894	 * @param {number} z - The z scale.
18895	 * @return {BufferGeometry} A reference to this instance.
18896	 */
18897	scale( x, y, z ) {
18898
18899		// scale geometry
18900
18901		_m1.makeScale( x, y, z );
18902
18903		this.applyMatrix4( _m1 );
18904
18905		return this;
18906
18907	}
18908
18909	/**
18910	 * Rotates the geometry to face a point in 3D space. This is typically done as a one time
18911	 * operation, and not during a loop. Use {@link Object3D#lookAt} for typical
18912	 * real-time mesh rotation.
18913	 *
18914	 * @param {Vector3} vector - The target point.
18915	 * @return {BufferGeometry} A reference to this instance.
18916	 */
18917	lookAt( vector ) {
18918
18919		_obj.lookAt( vector );
18920
18921		_obj.updateMatrix();
18922
18923		this.applyMatrix4( _obj.matrix );
18924
18925		return this;
18926
18927	}
18928
18929	/**
18930	 * Center the geometry based on its bounding box.
18931	 *
18932	 * @return {BufferGeometry} A reference to this instance.
18933	 */
18934	center() {
18935
18936		this.computeBoundingBox();
18937
18938		this.boundingBox.getCenter( _offset ).negate();
18939
18940		this.translate( _offset.x, _offset.y, _offset.z );
18941
18942		return this;
18943
18944	}
18945
18946	/**
18947	 * Defines a geometry by creating a `position` attribute based on the given array of points. The array
18948	 * can hold 2D or 3D vectors. When using two-dimensional data, the `z` coordinate for all vertices is
18949	 * set to `0`.
18950	 *
18951	 * If the method is used with an existing `position` attribute, the vertex data are overwritten with the
18952	 * data from the array. The length of the array must match the vertex count.
18953	 *
18954	 * @param {Array<Vector2>|Array<Vector3>} points - The points.
18955	 * @return {BufferGeometry} A reference to this instance.
18956	 */
18957	setFromPoints( points ) {
18958
18959		const positionAttribute = this.getAttribute( 'position' );
18960
18961		if ( positionAttribute === undefined ) {
18962
18963			const position = [];
18964
18965			for ( let i = 0, l = points.length; i < l; i ++ ) {
18966
18967				const point = points[ i ];
18968				position.push( point.x, point.y, point.z || 0 );
18969
18970			}
18971
18972			this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
18973
18974		} else {
18975
18976			const l = Math.min( points.length, positionAttribute.count ); // make sure data do not exceed buffer size
18977
18978			for ( let i = 0; i < l; i ++ ) {
18979
18980				const point = points[ i ];
18981				positionAttribute.setXYZ( i, point.x, point.y, point.z || 0 );
18982
18983			}
18984
18985			if ( points.length > positionAttribute.count ) {
18986
18987				warn( 'BufferGeometry: Buffer size too small for points data. Use .dispose() and create a new geometry.' );
18988
18989			}
18990
18991			positionAttribute.needsUpdate = true;
18992
18993		}
18994
18995		return this;
18996
18997	}
18998
18999	/**
19000	 * Computes the bounding box of the geometry, and updates the `boundingBox` member.
19001	 * The bounding box is not computed by the engine; it must be computed by your app.
19002	 * You may need to recompute the bounding box if the geometry vertices are modified.
19003	 */
19004	computeBoundingBox() {
19005
19006		if ( this.boundingBox === null ) {
19007
19008			this.boundingBox = new Box3();
19009
19010		}
19011
19012		const position = this.attributes.position;
19013		const morphAttributesPosition = this.morphAttributes.position;
19014
19015		if ( position && position.isGLBufferAttribute ) {
19016
19017			error( 'BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this );
19018
19019			this.boundingBox.set(
19020				new Vector3( - Infinity, - Infinity, - Infinity ),
19021				new Vector3( + Infinity, + Infinity, + Infinity )
19022			);
19023
19024			return;
19025
19026		}
19027
19028		if ( position !== undefined ) {
19029
19030			this.boundingBox.setFromBufferAttribute( position );
19031
19032			// process morph attributes if present
19033
19034			if ( morphAttributesPosition ) {
19035
19036				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
19037
19038					const morphAttribute = morphAttributesPosition[ i ];
19039					_box$2.setFromBufferAttribute( morphAttribute );
19040
19041					if ( this.morphTargetsRelative ) {
19042
19043						_vector$9.addVectors( this.boundingBox.min, _box$2.min );
19044						this.boundingBox.expandByPoint( _vector$9 );
19045
19046						_vector$9.addVectors( this.boundingBox.max, _box$2.max );
19047						this.boundingBox.expandByPoint( _vector$9 );
19048
19049					} else {
19050
19051						this.boundingBox.expandByPoint( _box$2.min );
19052						this.boundingBox.expandByPoint( _box$2.max );
19053
19054					}
19055
19056				}
19057
19058			}
19059
19060		} else {
19061
19062			this.boundingBox.makeEmpty();
19063
19064		}
19065
19066		if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
19067
19068			error( 'BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this );
19069
19070		}
19071
19072	}
19073
19074	/**
19075	 * Computes the bounding sphere of the geometry, and updates the `boundingSphere` member.
19076	 * The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling.
19077	 * You may need to recompute the bounding sphere if the geometry vertices are modified.
19078	 */
19079	computeBoundingSphere() {
19080
19081		if ( this.boundingSphere === null ) {
19082
19083			this.boundingSphere = new Sphere();
19084
19085		}
19086
19087		const position = this.attributes.position;
19088		const morphAttributesPosition = this.morphAttributes.position;
19089
19090		if ( position && position.isGLBufferAttribute ) {
19091
19092			error( 'BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this );
19093
19094			this.boundingSphere.set( new Vector3(), Infinity );
19095
19096			return;
19097
19098		}
19099
19100		if ( position ) {
19101
19102			// first, find the center of the bounding sphere
19103
19104			const center = this.boundingSphere.center;
19105
19106			_box$2.setFromBufferAttribute( position );
19107
19108			// process morph attributes if present
19109
19110			if ( morphAttributesPosition ) {
19111
19112				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
19113
19114					const morphAttribute = morphAttributesPosition[ i ];
19115					_boxMorphTargets.setFromBufferAttribute( morphAttribute );
19116
19117					if ( this.morphTargetsRelative ) {
19118
19119						_vector$9.addVectors( _box$2.min, _boxMorphTargets.min );
19120						_box$2.expandByPoint( _vector$9 );
19121
19122						_vector$9.addVectors( _box$2.max, _boxMorphTargets.max );
19123						_box$2.expandByPoint( _vector$9 );
19124
19125					} else {
19126
19127						_box$2.expandByPoint( _boxMorphTargets.min );
19128						_box$2.expandByPoint( _boxMorphTargets.max );
19129
19130					}
19131
19132				}
19133
19134			}
19135
19136			_box$2.getCenter( center );
19137
19138			// second, try to find a boundingSphere with a radius smaller than the
19139			// boundingSphere of the boundingBox: sqrt(3) smaller in the best case
19140
19141			let maxRadiusSq = 0;
19142
19143			for ( let i = 0, il = position.count; i < il; i ++ ) {
19144
19145				_vector$9.fromBufferAttribute( position, i );
19146
19147				maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$9 ) );
19148
19149			}
19150
19151			// process morph attributes if present
19152
19153			if ( morphAttributesPosition ) {
19154
19155				for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {
19156
19157					const morphAttribute = morphAttributesPosition[ i ];
19158					const morphTargetsRelative = this.morphTargetsRelative;
19159
19160					for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) {
19161
19162						_vector$9.fromBufferAttribute( morphAttribute, j );
19163
19164						if ( morphTargetsRelative ) {
19165
19166							_offset.fromBufferAttribute( position, j );
19167							_vector$9.add( _offset );
19168
19169						}
19170
19171						maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$9 ) );
19172
19173					}
19174
19175				}
19176
19177			}
19178
19179			this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
19180
19181			if ( isNaN( this.boundingSphere.radius ) ) {
19182
19183				error( 'BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this );
19184
19185			}
19186
19187		}
19188
19189	}
19190
19191	/**
19192	 * Calculates and adds a tangent attribute to this geometry.
19193	 *
19194	 * The computation is only supported for indexed geometries and if position, normal, and uv attributes
19195	 * are defined. When using a tangent space normal map, prefer the MikkTSpace algorithm provided by
19196	 * {@link BufferGeometryUtils#computeMikkTSpaceTangents} instead.
19197	 */
19198	computeTangents() {
19199
19200		const index = this.index;
19201		const attributes = this.attributes;
19202
19203		// based on http://www.terathon.com/code/tangent.html
19204		// (per vertex tangents)
19205
19206		if ( index === null ||
19207			 attributes.position === undefined ||
19208			 attributes.normal === undefined ||
19209			 attributes.uv === undefined ) {
19210
19211			error( 'BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
19212			return;
19213
19214		}
19215
19216		const positionAttribute = attributes.position;
19217		const normalAttribute = attributes.normal;
19218		const uvAttribute = attributes.uv;
19219
19220		let tangentAttribute = this.getAttribute( 'tangent' );
19221
19222		if ( tangentAttribute === undefined || tangentAttribute.count !== positionAttribute.count ) {
19223
19224			tangentAttribute = new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 );
19225			this.setAttribute( 'tangent', tangentAttribute );
19226
19227		}
19228
19229		const tan1 = [], tan2 = [];
19230
19231		for ( let i = 0; i < positionAttribute.count; i ++ ) {
19232
19233			tan1[ i ] = new Vector3();
19234			tan2[ i ] = new Vector3();
19235
19236		}
19237
19238		const vA = new Vector3(),
19239			vB = new Vector3(),
19240			vC = new Vector3(),
19241
19242			uvA = new Vector2(),
19243			uvB = new Vector2(),
19244			uvC = new Vector2(),
19245
19246			sdir = new Vector3(),
19247			tdir = new Vector3();
19248
19249		function handleTriangle( a, b, c ) {
19250
19251			vA.fromBufferAttribute( positionAttribute, a );
19252			vB.fromBufferAttribute( positionAttribute, b );
19253			vC.fromBufferAttribute( positionAttribute, c );
19254
19255			uvA.fromBufferAttribute( uvAttribute, a );
19256			uvB.fromBufferAttribute( uvAttribute, b );
19257			uvC.fromBufferAttribute( uvAttribute, c );
19258
19259			vB.sub( vA );
19260			vC.sub( vA );
19261
19262			uvB.sub( uvA );
19263			uvC.sub( uvA );
19264
19265			const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
19266
19267			// silently ignore degenerate uv triangles having coincident or colinear vertices
19268
19269			if ( ! isFinite( r ) ) return;
19270
19271			sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r );
19272			tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r );
19273
19274			tan1[ a ].add( sdir );
19275			tan1[ b ].add( sdir );
19276			tan1[ c ].add( sdir );
19277
19278			tan2[ a ].add( tdir );
19279			tan2[ b ].add( tdir );
19280			tan2[ c ].add( tdir );
19281
19282		}
19283
19284		let groups = this.groups;
19285
19286		if ( groups.length === 0 ) {
19287
19288			groups = [ {
19289				start: 0,
19290				count: index.count
19291			} ];
19292
19293		}
19294
19295		for ( let i = 0, il = groups.length; i < il; ++ i ) {
19296
19297			const group = groups[ i ];
19298
19299			const start = group.start;
19300			const count = group.count;
19301
19302			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
19303
19304				handleTriangle(
19305					index.getX( j + 0 ),
19306					index.getX( j + 1 ),
19307					index.getX( j + 2 )
19308				);
19309
19310			}
19311
19312		}
19313
19314		const tmp = new Vector3(), tmp2 = new Vector3();
19315		const n = new Vector3(), n2 = new Vector3();
19316
19317		function handleVertex( v ) {
19318
19319			n.fromBufferAttribute( normalAttribute, v );
19320			n2.copy( n );
19321
19322			const t = tan1[ v ];
19323
19324			// Gram-Schmidt orthogonalize
19325
19326			tmp.copy( t );
19327			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
19328
19329			// Calculate handedness
19330
19331			tmp2.crossVectors( n2, t );
19332			const test = tmp2.dot( tan2[ v ] );
19333			const w = ( test < 0.0 ) ? -1 : 1.0;
19334
19335			tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w );
19336
19337		}
19338
19339		for ( let i = 0, il = groups.length; i < il; ++ i ) {
19340
19341			const group = groups[ i ];
19342
19343			const start = group.start;
19344			const count = group.count;
19345
19346			for ( let j = start, jl = start + count; j < jl; j += 3 ) {
19347
19348				handleVertex( index.getX( j + 0 ) );
19349				handleVertex( index.getX( j + 1 ) );
19350				handleVertex( index.getX( j + 2 ) );
19351
19352			}
19353
19354		}
19355
19356		this._transformed = true;
19357
19358	}
19359
19360	/**
19361	 * Computes vertex normals for the given vertex data. For indexed geometries, the method sets
19362	 * each vertex normal to be the average of the face normals of the faces that share that vertex.
19363	 * For non-indexed geometries, vertices are not shared, and the method sets each vertex normal
19364	 * to be the same as the face normal.
19365	 */
19366	computeVertexNormals() {
19367
19368		const index = this.index;
19369		const positionAttribute = this.getAttribute( 'position' );
19370
19371		if ( positionAttribute !== undefined ) {
19372
19373			let normalAttribute = this.getAttribute( 'normal' );
19374
19375			if ( normalAttribute === undefined || normalAttribute.count !== positionAttribute.count ) {
19376
19377				normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 );
19378				this.setAttribute( 'normal', normalAttribute );
19379
19380			} else {
19381
19382				// reset existing normals to zero
19383
19384				for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) {
19385
19386					normalAttribute.setXYZ( i, 0, 0, 0 );
19387
19388				}
19389
19390			}
19391
19392			const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
19393			const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
19394			const cb = new Vector3(), ab = new Vector3();
19395
19396			// indexed elements
19397
19398			if ( index ) {
19399
19400				for ( let i = 0, il = index.count; i < il; i += 3 ) {
19401
19402					const vA = index.getX( i + 0 );
19403					const vB = index.getX( i + 1 );
19404					const vC = index.getX( i + 2 );
19405
19406					pA.fromBufferAttribute( positionAttribute, vA );
19407					pB.fromBufferAttribute( positionAttribute, vB );
19408					pC.fromBufferAttribute( positionAttribute, vC );
19409
19410					cb.subVectors( pC, pB );
19411					ab.subVectors( pA, pB );
19412					cb.cross( ab );
19413
19414					nA.fromBufferAttribute( normalAttribute, vA );
19415					nB.fromBufferAttribute( normalAttribute, vB );
19416					nC.fromBufferAttribute( normalAttribute, vC );
19417
19418					nA.add( cb );
19419					nB.add( cb );
19420					nC.add( cb );
19421
19422					normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
19423					normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
19424					normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
19425
19426				}
19427
19428			} else {
19429
19430				// non-indexed elements (unconnected triangle soup)
19431
19432				for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) {
19433
19434					pA.fromBufferAttribute( positionAttribute, i + 0 );
19435					pB.fromBufferAttribute( positionAttribute, i + 1 );
19436					pC.fromBufferAttribute( positionAttribute, i + 2 );
19437
19438					cb.subVectors( pC, pB );
19439					ab.subVectors( pA, pB );
19440					cb.cross( ab );
19441
19442					normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z );
19443					normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z );
19444					normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z );
19445
19446				}
19447
19448			}
19449
19450			this.normalizeNormals();
19451
19452			normalAttribute.needsUpdate = true;
19453
19454		}
19455
19456	}
19457
19458	/**
19459	 * Ensures every normal vector in a geometry will have a magnitude of `1`. This will
19460	 * correct lighting on the geometry surfaces.
19461	 */
19462	normalizeNormals() {
19463
19464		const normals = this.attributes.normal;
19465
19466		for ( let i = 0, il = normals.count; i < il; i ++ ) {
19467
19468			_vector$9.fromBufferAttribute( normals, i );
19469
19470			_vector$9.normalize();
19471
19472			normals.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z );
19473
19474		}
19475
19476	}
19477
19478	/**
19479	 * Return a new non-index version of this indexed geometry. If the geometry
19480	 * is already non-indexed, the method is a NOOP.
19481	 *
19482	 * @return {BufferGeometry} The non-indexed version of this indexed geometry.
19483	 */
19484	toNonIndexed() {
19485
19486		function convertBufferAttribute( attribute, indices ) {
19487
19488			const array = attribute.array;
19489			const itemSize = attribute.itemSize;
19490			const normalized = attribute.normalized;
19491
19492			const array2 = new array.constructor( indices.length * itemSize );
19493
19494			let index = 0, index2 = 0;
19495
19496			for ( let i = 0, l = indices.length; i < l; i ++ ) {
19497
19498				if ( attribute.isInterleavedBufferAttribute ) {
19499
19500					index = indices[ i ] * attribute.data.stride + attribute.offset;
19501
19502				} else {
19503
19504					index = indices[ i ] * itemSize;
19505
19506				}
19507
19508				for ( let j = 0; j < itemSize; j ++ ) {
19509
19510					array2[ index2 ++ ] = array[ index ++ ];
19511
19512				}
19513
19514			}
19515
19516			return new BufferAttribute( array2, itemSize, normalized );
19517
19518		}
19519
19520		//
19521
19522		if ( this.index === null ) {
19523
19524			warn( 'BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
19525			return this;
19526
19527		}
19528
19529		const geometry2 = new BufferGeometry();
19530
19531		const indices = this.index.array;
19532		const attributes = this.attributes;
19533
19534		// attributes
19535
19536		for ( const name in attributes ) {
19537
19538			const attribute = attributes[ name ];
19539
19540			const newAttribute = convertBufferAttribute( attribute, indices );
19541
19542			geometry2.setAttribute( name, newAttribute );
19543
19544		}
19545
19546		// morph attributes
19547
19548		const morphAttributes = this.morphAttributes;
19549
19550		for ( const name in morphAttributes ) {
19551
19552			const morphArray = [];
19553			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
19554
19555			for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) {
19556
19557				const attribute = morphAttribute[ i ];
19558
19559				const newAttribute = convertBufferAttribute( attribute, indices );
19560
19561				morphArray.push( newAttribute );
19562
19563			}
19564
19565			geometry2.morphAttributes[ name ] = morphArray;
19566
19567		}
19568
19569		geometry2.morphTargetsRelative = this.morphTargetsRelative;
19570
19571		// groups
19572
19573		const groups = this.groups;
19574
19575		for ( let i = 0, l = groups.length; i < l; i ++ ) {
19576
19577			const group = groups[ i ];
19578			geometry2.addGroup( group.start, group.count, group.materialIndex );
19579
19580		}
19581
19582		return geometry2;
19583
19584	}
19585
19586	/**
19587	 * Serializes the geometry into JSON.
19588	 *
19589	 * @return {Object} A JSON object representing the serialized geometry.
19590	 */
19591	toJSON() {
19592
19593		const data = {
19594			metadata: {
19595				version: 4.7,
19596				type: 'BufferGeometry',
19597				generator: 'BufferGeometry.toJSON'
19598			}
19599		};
19600
19601		// standard BufferGeometry serialization
19602
19603		data.uuid = this.uuid;
19604		data.type = ( this.parameters !== undefined && this._transformed === true ) ? 'BufferGeometry' : this.type;
19605		data.name = this.name;
19606		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
19607
19608		if ( this.parameters !== undefined && this._transformed !== true ) {
19609
19610			const parameters = this.parameters;
19611
19612			for ( const key in parameters ) {
19613
19614				if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];
19615
19616			}
19617
19618			return data;
19619
19620		}
19621
19622		// for simplicity the code assumes attributes are not shared across geometries, see #15811
19623
19624		data.data = { attributes: {} };
19625
19626		const index = this.index;
19627
19628		if ( index !== null ) {
19629
19630			data.data.index = {
19631				type: index.array.constructor.name,
19632				array: Array.prototype.slice.call( index.array )
19633			};
19634
19635		}
19636
19637		const attributes = this.attributes;
19638
19639		for ( const key in attributes ) {
19640
19641			const attribute = attributes[ key ];
19642
19643			data.data.attributes[ key ] = attribute.toJSON( data.data );
19644
19645		}
19646
19647		const morphAttributes = {};
19648		let hasMorphAttributes = false;
19649
19650		for ( const key in this.morphAttributes ) {
19651
19652			const attributeArray = this.morphAttributes[ key ];
19653
19654			const array = [];
19655
19656			for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
19657
19658				const attribute = attributeArray[ i ];
19659
19660				array.push( attribute.toJSON( data.data ) );
19661
19662			}
19663
19664			if ( array.length > 0 ) {
19665
19666				morphAttributes[ key ] = array;
19667
19668				hasMorphAttributes = true;
19669
19670			}
19671
19672		}
19673
19674		if ( hasMorphAttributes ) {
19675
19676			data.data.morphAttributes = morphAttributes;
19677			data.data.morphTargetsRelative = this.morphTargetsRelative;
19678
19679		}
19680
19681		const groups = this.groups;
19682
19683		if ( groups.length > 0 ) {
19684
19685			data.data.groups = JSON.parse( JSON.stringify( groups ) );
19686
19687		}
19688
19689		const boundingSphere = this.boundingSphere;
19690
19691		if ( boundingSphere !== null ) {
19692
19693			data.data.boundingSphere = boundingSphere.toJSON();
19694
19695		}
19696
19697		return data;
19698
19699	}
19700
19701	/**
19702	 * Returns a new geometry with copied values from this instance.
19703	 *
19704	 * @return {BufferGeometry} A clone of this instance.
19705	 */
19706	clone() {
19707
19708		return new this.constructor().copy( this );
19709
19710	}
19711
19712	/**
19713	 * Copies the values of the given geometry to this instance.
19714	 *
19715	 * @param {BufferGeometry} source - The geometry to copy.
19716	 * @return {BufferGeometry} A reference to this instance.
19717	 */
19718	copy( source ) {
19719
19720		// reset
19721
19722		this.index = null;
19723		this.attributes = {};
19724		this.morphAttributes = {};
19725		this.groups = [];
19726		this.boundingBox = null;
19727		this.boundingSphere = null;
19728
19729		// used for storing cloned, shared data
19730
19731		const data = {};
19732
19733		// name
19734
19735		this.name = source.name;
19736
19737		// index
19738
19739		const index = source.index;
19740
19741		if ( index !== null ) {
19742
19743			this.setIndex( index.clone() );
19744
19745		}
19746
19747		// attributes
19748
19749		const attributes = source.attributes;
19750
19751		for ( const name in attributes ) {
19752
19753			const attribute = attributes[ name ];
19754			this.setAttribute( name, attribute.clone( data ) );
19755
19756		}
19757
19758		// morph attributes
19759
19760		const morphAttributes = source.morphAttributes;
19761
19762		for ( const name in morphAttributes ) {
19763
19764			const array = [];
19765			const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes
19766
19767			for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) {
19768
19769				array.push( morphAttribute[ i ].clone( data ) );
19770
19771			}
19772
19773			this.morphAttributes[ name ] = array;
19774
19775		}
19776
19777		this.morphTargetsRelative = source.morphTargetsRelative;
19778
19779		// groups
19780
19781		const groups = source.groups;
19782
19783		for ( let i = 0, l = groups.length; i < l; i ++ ) {
19784
19785			const group = groups[ i ];
19786			this.addGroup( group.start, group.count, group.materialIndex );
19787
19788		}
19789
19790		// bounding box
19791
19792		const boundingBox = source.boundingBox;
19793
19794		if ( boundingBox !== null ) {
19795
19796			this.boundingBox = boundingBox.clone();
19797
19798		}
19799
19800		// bounding sphere
19801
19802		const boundingSphere = source.boundingSphere;
19803
19804		if ( boundingSphere !== null ) {
19805
19806			this.boundingSphere = boundingSphere.clone();
19807
19808		}
19809
19810		// draw range
19811
19812		this.drawRange.start = source.drawRange.start;
19813		this.drawRange.count = source.drawRange.count;
19814
19815		// user data
19816
19817		this.userData = source.userData;
19818
19819		// transformed flag
19820
19821		this._transformed = source._transformed;
19822
19823		return this;
19824
19825	}
19826
19827	/**
19828	 * Frees the GPU-related resources allocated by this instance. Call this
19829	 * method whenever this instance is no longer used in your app.
19830	 *
19831	 * @fires BufferGeometry#dispose
19832	 */
19833	dispose() {
19834
19835		this.dispatchEvent( { type: 'dispose' } );
19836
19837	}
19838
19839}
19840
19841/**
19842 * "Interleaved" means that multiple attributes, possibly of different types,
19843 * (e.g., position, normal, uv, color) are packed into a single array buffer.
19844 *
19845 * An introduction into interleaved arrays can be found here: [Interleaved array basics](https://blog.tojicode.com/2011/05/interleaved-array-basics.html)
19846 */
19847class InterleavedBuffer {
19848
19849	/**
19850	 * Constructs a new interleaved buffer.
19851	 *
19852	 * @param {TypedArray} array - A typed array with a shared buffer storing attribute data.
19853	 * @param {number} stride - The number of typed-array elements per vertex.
19854	 */
19855	constructor( array, stride ) {
19856
19857		/**
19858		 * This flag can be used for type testing.
19859		 *
19860		 * @type {boolean}
19861		 * @readonly
19862		 * @default true
19863		 */
19864		this.isInterleavedBuffer = true;
19865
19866		/**
19867		 * A typed array with a shared buffer storing attribute data.
19868		 *
19869		 * @type {TypedArray}
19870		 */
19871		this.array = array;
19872
19873		/**
19874		 * The number of typed-array elements per vertex.
19875		 *
19876		 * @type {number}
19877		 */
19878		this.stride = stride;
19879
19880		/**
19881		 * The total number of elements in the array
19882		 *
19883		 * @type {number}
19884		 * @readonly
19885		 */
19886		this.count = array !== undefined ? array.length / stride : 0;
19887
19888		/**
19889		 * Defines the intended usage pattern of the data store for optimization purposes.
19890		 *
19891		 * Note: After the initial use of a buffer, its usage cannot be changed. Instead,
19892		 * instantiate a new one and set the desired usage before the next render.
19893		 *
19894		 * @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
19895		 * @default StaticDrawUsage
19896		 */
19897		this.usage = StaticDrawUsage;
19898
19899		/**
19900		 * This can be used to only update some components of stored vectors (for example, just the
19901		 * component related to color). Use the `addUpdateRange()` function to add ranges to this array.
19902		 *
19903		 * @type {Array<Object>}
19904		 */
19905		this.updateRanges = [];
19906
19907		/**
19908		 * A version number, incremented every time the `needsUpdate` is set to `true`.
19909		 *
19910		 * @type {number}
19911		 */
19912		this.version = 0;
19913
19914		/**
19915		 * The UUID of the interleaved buffer.
19916		 *
19917		 * @type {string}
19918		 * @readonly
19919		 */
19920		this.uuid = generateUUID();
19921
19922	}
19923
19924	/**
19925	 * A callback function that is executed after the renderer has transferred the attribute array
19926	 * data to the GPU.
19927	 */
19928	onUploadCallback() {}
19929
19930	/**
19931	 * Flag to indicate that this attribute has changed and should be re-sent to
19932	 * the GPU. Set this to `true` when you modify the value of the array.
19933	 *
19934	 * @type {number}
19935	 * @default false
19936	 * @param {boolean} value
19937	 */
19938	set needsUpdate( value ) {
19939
19940		if ( value === true ) this.version ++;
19941
19942	}
19943
19944	/**
19945	 * Sets the usage of this interleaved buffer.
19946	 *
19947	 * @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
19948	 * @return {InterleavedBuffer} A reference to this interleaved buffer.
19949	 */
19950	setUsage( value ) {
19951
19952		this.usage = value;
19953
19954		return this;
19955
19956	}
19957
19958	/**
19959	 * Adds a range of data in the data array to be updated on the GPU.
19960	 *
19961	 * @param {number} start - Position at which to start update.
19962	 * @param {number} count - The number of components to update.
19963	 */
19964	addUpdateRange( start, count ) {
19965
19966		this.updateRanges.push( { start, count } );
19967
19968	}
19969
19970	/**
19971	 * Clears the update ranges.
19972	 */
19973	clearUpdateRanges() {
19974
19975		this.updateRanges.length = 0;
19976
19977	}
19978
19979	/**
19980	 * Copies the values of the given interleaved buffer to this instance.
19981	 *
19982	 * @param {InterleavedBuffer} source - The interleaved buffer to copy.
19983	 * @return {InterleavedBuffer} A reference to this instance.
19984	 */
19985	copy( source ) {
19986
19987		this.array = new source.array.constructor( source.array );
19988		this.count = source.count;
19989		this.stride = source.stride;
19990		this.usage = source.usage;
19991
19992		return this;
19993
19994	}
19995
19996	/**
19997	 * Copies a vector from the given interleaved buffer to this one. The start
19998	 * and destination position in the attribute buffers are represented by the
19999	 * given indices.
20000	 *
20001	 * @param {number} index1 - The destination index into this interleaved buffer.
20002	 * @param {InterleavedBuffer} interleavedBuffer - The interleaved buffer to copy from.
20003	 * @param {number} index2 - The source index into the given interleaved buffer.
20004	 * @return {InterleavedBuffer} A reference to this instance.
20005	 */
20006	copyAt( index1, interleavedBuffer, index2 ) {
20007
20008		index1 *= this.stride;
20009		index2 *= interleavedBuffer.stride;
20010
20011		for ( let i = 0, l = this.stride; i < l; i ++ ) {
20012
20013			this.array[ index1 + i ] = interleavedBuffer.array[ index2 + i ];
20014
20015		}
20016
20017		return this;
20018
20019	}
20020
20021	/**
20022	 * Sets the given array data in the interleaved buffer.
20023	 *
20024	 * @param {(TypedArray|Array)} value - The array data to set.
20025	 * @param {number} [offset=0] - The offset in this interleaved buffer's array.
20026	 * @return {InterleavedBuffer} A reference to this instance.
20027	 */
20028	set( value, offset = 0 ) {
20029
20030		this.array.set( value, offset );
20031
20032		return this;
20033
20034	}
20035
20036	/**
20037	 * Returns a new interleaved buffer with copied values from this instance.
20038	 *
20039	 * @param {Object} [data] - An object with shared array buffers that allows to retain shared structures.
20040	 * @return {InterleavedBuffer} A clone of this instance.
20041	 */
20042	clone( data ) {
20043
20044		if ( data.arrayBuffers === undefined ) {
20045
20046			data.arrayBuffers = {};
20047
20048		}
20049
20050		if ( this.array.buffer._uuid === undefined ) {
20051
20052			this.array.buffer._uuid = generateUUID();
20053
20054		}
20055
20056		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
20057
20058			data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
20059
20060		}
20061
20062		const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] );
20063
20064		const ib = new this.constructor( array, this.stride );
20065		ib.setUsage( this.usage );
20066
20067		return ib;
20068
20069	}
20070
20071	/**
20072	 * Sets the given callback function that is executed after the Renderer has transferred
20073	 * the array data to the GPU. Can be used to perform clean-up operations after
20074	 * the upload when data are not needed anymore on the CPU side.
20075	 *
20076	 * @param {Function} callback - The `onUpload()` callback.
20077	 * @return {InterleavedBuffer} A reference to this instance.
20078	 */
20079	onUpload( callback ) {
20080
20081		this.onUploadCallback = callback;
20082
20083		return this;
20084
20085	}
20086
20087	/**
20088	 * Serializes the interleaved buffer into JSON.
20089	 *
20090	 * @param {Object} [data] - An optional value holding meta information about the serialization.
20091	 * @return {Object} A JSON object representing the serialized interleaved buffer.
20092	 */
20093	toJSON( data ) {
20094
20095		if ( data.arrayBuffers === undefined ) {
20096
20097			data.arrayBuffers = {};
20098
20099		}
20100
20101		// generate UUID for array buffer if necessary
20102
20103		if ( this.array.buffer._uuid === undefined ) {
20104
20105			this.array.buffer._uuid = generateUUID();
20106
20107		}
20108
20109		if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) {
20110
20111			data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) );
20112
20113		}
20114
20115		//
20116
20117		const json = {
20118			uuid: this.uuid,
20119			buffer: this.array.buffer._uuid,
20120			type: this.array.constructor.name,
20121			stride: this.stride
20122		};
20123
20124		json.usage = this.usage;
20125
20126		return json;
20127
20128	}
20129
20130}
20131
20132const _vector$8 = /*@__PURE__*/ new Vector3();
20133
20134/**
20135 * An alternative version of a buffer attribute with interleaved data. Interleaved
20136 * attributes share a common interleaved data storage ({@link InterleavedBuffer}) and refer with
20137 * different offsets into the buffer.
20138 */
20139class InterleavedBufferAttribute {
20140
20141	/**
20142	 * Constructs a new interleaved buffer attribute.
20143	 *
20144	 * @param {InterleavedBuffer} interleavedBuffer - The buffer holding the interleaved data.
20145	 * @param {number} itemSize - The item size.
20146	 * @param {number} offset - The attribute offset into the buffer.
20147	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
20148	 */
20149	constructor( interleavedBuffer, itemSize, offset, normalized = false ) {
20150
20151		/**
20152		 * This flag can be used for type testing.
20153		 *
20154		 * @type {boolean}
20155		 * @readonly
20156		 * @default true
20157		 */
20158		this.isInterleavedBufferAttribute = true;
20159
20160		/**
20161		 * The name of the buffer attribute.
20162		 *
20163		 * @type {string}
20164		 */
20165		this.name = '';
20166
20167		/**
20168		 * The buffer holding the interleaved data.
20169		 *
20170		 * @type {InterleavedBuffer}
20171		 */
20172		this.data = interleavedBuffer;
20173
20174		/**
20175		 * The item size, see {@link BufferAttribute#itemSize}.
20176		 *
20177		 * @type {number}
20178		 */
20179		this.itemSize = itemSize;
20180
20181		/**
20182		 * The attribute offset into the buffer.
20183		 *
20184		 * @type {number}
20185		 */
20186		this.offset = offset;
20187
20188		/**
20189		 * Whether the data are normalized or not, see {@link BufferAttribute#normalized}
20190		 *
20191		 * @type {InterleavedBuffer}
20192		 */
20193		this.normalized = normalized;
20194
20195	}
20196
20197	/**
20198	 * The item count of this buffer attribute.
20199	 *
20200	 * @type {number}
20201	 * @readonly
20202	 */
20203	get count() {
20204
20205		return this.data.count;
20206
20207	}
20208
20209	/**
20210	 * The array holding the interleaved buffer attribute data.
20211	 *
20212	 * @type {TypedArray}
20213	 */
20214	get array() {
20215
20216		return this.data.array;
20217
20218	}
20219
20220	/**
20221	 * Flag to indicate that this attribute has changed and should be re-sent to
20222	 * the GPU. Set this to `true` when you modify the value of the array.
20223	 *
20224	 * @type {number}
20225	 * @default false
20226	 * @param {boolean} value
20227	 */
20228	set needsUpdate( value ) {
20229
20230		this.data.needsUpdate = value;
20231
20232	}
20233
20234	/**
20235	 * Applies the given 4x4 matrix to the given attribute. Only works with
20236	 * item size `3`.
20237	 *
20238	 * @param {Matrix4} m - The matrix to apply.
20239	 * @return {InterleavedBufferAttribute} A reference to this instance.
20240	 */
20241	applyMatrix4( m ) {
20242
20243		for ( let i = 0, l = this.data.count; i < l; i ++ ) {
20244
20245			_vector$8.fromBufferAttribute( this, i );
20246
20247			_vector$8.applyMatrix4( m );
20248
20249			this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
20250
20251		}
20252
20253		return this;
20254
20255	}
20256
20257	/**
20258	 * Applies the given 3x3 normal matrix to the given attribute. Only works with
20259	 * item size `3`.
20260	 *
20261	 * @param {Matrix3} m - The normal matrix to apply.
20262	 * @return {InterleavedBufferAttribute} A reference to this instance.
20263	 */
20264	applyNormalMatrix( m ) {
20265
20266		for ( let i = 0, l = this.count; i < l; i ++ ) {
20267
20268			_vector$8.fromBufferAttribute( this, i );
20269
20270			_vector$8.applyNormalMatrix( m );
20271
20272			this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
20273
20274		}
20275
20276		return this;
20277
20278	}
20279
20280	/**
20281	 * Applies the given 4x4 matrix to the given attribute. Only works with
20282	 * item size `3` and with direction vectors.
20283	 *
20284	 * @param {Matrix4} m - The matrix to apply.
20285	 * @return {InterleavedBufferAttribute} A reference to this instance.
20286	 */
20287	transformDirection( m ) {
20288
20289		for ( let i = 0, l = this.count; i < l; i ++ ) {
20290
20291			_vector$8.fromBufferAttribute( this, i );
20292
20293			_vector$8.transformDirection( m );
20294
20295			this.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z );
20296
20297		}
20298
20299		return this;
20300
20301	}
20302
20303	/**
20304	 * Returns the given component of the vector at the given index.
20305	 *
20306	 * @param {number} index - The index into the buffer attribute.
20307	 * @param {number} component - The component index.
20308	 * @return {number} The returned value.
20309	 */
20310	getComponent( index, component ) {
20311
20312		let value = this.array[ index * this.data.stride + this.offset + component ];
20313
20314		if ( this.normalized ) value = denormalize( value, this.array );
20315
20316		return value;
20317
20318	}
20319
20320	/**
20321	 * Sets the given value to the given component of the vector at the given index.
20322	 *
20323	 * @param {number} index - The index into the buffer attribute.
20324	 * @param {number} component - The component index.
20325	 * @param {number} value - The value to set.
20326	 * @return {InterleavedBufferAttribute} A reference to this instance.
20327	 */
20328	setComponent( index, component, value ) {
20329
20330		if ( this.normalized ) value = normalize( value, this.array );
20331
20332		this.data.array[ index * this.data.stride + this.offset + component ] = value;
20333
20334		return this;
20335
20336	}
20337
20338	/**
20339	 * Sets the x component of the vector at the given index.
20340	 *
20341	 * @param {number} index - The index into the buffer attribute.
20342	 * @param {number} x - The value to set.
20343	 * @return {InterleavedBufferAttribute} A reference to this instance.
20344	 */
20345	setX( index, x ) {
20346
20347		if ( this.normalized ) x = normalize( x, this.array );
20348
20349		this.data.array[ index * this.data.stride + this.offset ] = x;
20350
20351		return this;
20352
20353	}
20354
20355	/**
20356	 * Sets the y component of the vector at the given index.
20357	 *
20358	 * @param {number} index - The index into the buffer attribute.
20359	 * @param {number} y - The value to set.
20360	 * @return {InterleavedBufferAttribute} A reference to this instance.
20361	 */
20362	setY( index, y ) {
20363
20364		if ( this.normalized ) y = normalize( y, this.array );
20365
20366		this.data.array[ index * this.data.stride + this.offset + 1 ] = y;
20367
20368		return this;
20369
20370	}
20371
20372	/**
20373	 * Sets the z component of the vector at the given index.
20374	 *
20375	 * @param {number} index - The index into the buffer attribute.
20376	 * @param {number} z - The value to set.
20377	 * @return {InterleavedBufferAttribute} A reference to this instance.
20378	 */
20379	setZ( index, z ) {
20380
20381		if ( this.normalized ) z = normalize( z, this.array );
20382
20383		this.data.array[ index * this.data.stride + this.offset + 2 ] = z;
20384
20385		return this;
20386
20387	}
20388
20389	/**
20390	 * Sets the w component of the vector at the given index.
20391	 *
20392	 * @param {number} index - The index into the buffer attribute.
20393	 * @param {number} w - The value to set.
20394	 * @return {InterleavedBufferAttribute} A reference to this instance.
20395	 */
20396	setW( index, w ) {
20397
20398		if ( this.normalized ) w = normalize( w, this.array );
20399
20400		this.data.array[ index * this.data.stride + this.offset + 3 ] = w;
20401
20402		return this;
20403
20404	}
20405
20406	/**
20407	 * Returns the x component of the vector at the given index.
20408	 *
20409	 * @param {number} index - The index into the buffer attribute.
20410	 * @return {number} The x component.
20411	 */
20412	getX( index ) {
20413
20414		let x = this.data.array[ index * this.data.stride + this.offset ];
20415
20416		if ( this.normalized ) x = denormalize( x, this.array );
20417
20418		return x;
20419
20420	}
20421
20422	/**
20423	 * Returns the y component of the vector at the given index.
20424	 *
20425	 * @param {number} index - The index into the buffer attribute.
20426	 * @return {number} The y component.
20427	 */
20428	getY( index ) {
20429
20430		let y = this.data.array[ index * this.data.stride + this.offset + 1 ];
20431
20432		if ( this.normalized ) y = denormalize( y, this.array );
20433
20434		return y;
20435
20436	}
20437
20438	/**
20439	 * Returns the z component of the vector at the given index.
20440	 *
20441	 * @param {number} index - The index into the buffer attribute.
20442	 * @return {number} The z component.
20443	 */
20444	getZ( index ) {
20445
20446		let z = this.data.array[ index * this.data.stride + this.offset + 2 ];
20447
20448		if ( this.normalized ) z = denormalize( z, this.array );
20449
20450		return z;
20451
20452	}
20453
20454	/**
20455	 * Returns the w component of the vector at the given index.
20456	 *
20457	 * @param {number} index - The index into the buffer attribute.
20458	 * @return {number} The w component.
20459	 */
20460	getW( index ) {
20461
20462		let w = this.data.array[ index * this.data.stride + this.offset + 3 ];
20463
20464		if ( this.normalized ) w = denormalize( w, this.array );
20465
20466		return w;
20467
20468	}
20469
20470	/**
20471	 * Sets the x and y component of the vector at the given index.
20472	 *
20473	 * @param {number} index - The index into the buffer attribute.
20474	 * @param {number} x - The value for the x component to set.
20475	 * @param {number} y - The value for the y component to set.
20476	 * @return {InterleavedBufferAttribute} A reference to this instance.
20477	 */
20478	setXY( index, x, y ) {
20479
20480		index = index * this.data.stride + this.offset;
20481
20482		if ( this.normalized ) {
20483
20484			x = normalize( x, this.array );
20485			y = normalize( y, this.array );
20486
20487		}
20488
20489		this.data.array[ index + 0 ] = x;
20490		this.data.array[ index + 1 ] = y;
20491
20492		return this;
20493
20494	}
20495
20496	/**
20497	 * Sets the x, y and z component of the vector at the given index.
20498	 *
20499	 * @param {number} index - The index into the buffer attribute.
20500	 * @param {number} x - The value for the x component to set.
20501	 * @param {number} y - The value for the y component to set.
20502	 * @param {number} z - The value for the z component to set.
20503	 * @return {InterleavedBufferAttribute} A reference to this instance.
20504	 */
20505	setXYZ( index, x, y, z ) {
20506
20507		index = index * this.data.stride + this.offset;
20508
20509		if ( this.normalized ) {
20510
20511			x = normalize( x, this.array );
20512			y = normalize( y, this.array );
20513			z = normalize( z, this.array );
20514
20515		}
20516
20517		this.data.array[ index + 0 ] = x;
20518		this.data.array[ index + 1 ] = y;
20519		this.data.array[ index + 2 ] = z;
20520
20521		return this;
20522
20523	}
20524
20525	/**
20526	 * Sets the x, y, z and w component of the vector at the given index.
20527	 *
20528	 * @param {number} index - The index into the buffer attribute.
20529	 * @param {number} x - The value for the x component to set.
20530	 * @param {number} y - The value for the y component to set.
20531	 * @param {number} z - The value for the z component to set.
20532	 * @param {number} w - The value for the w component to set.
20533	 * @return {InterleavedBufferAttribute} A reference to this instance.
20534	 */
20535	setXYZW( index, x, y, z, w ) {
20536
20537		index = index * this.data.stride + this.offset;
20538
20539		if ( this.normalized ) {
20540
20541			x = normalize( x, this.array );
20542			y = normalize( y, this.array );
20543			z = normalize( z, this.array );
20544			w = normalize( w, this.array );
20545
20546		}
20547
20548		this.data.array[ index + 0 ] = x;
20549		this.data.array[ index + 1 ] = y;
20550		this.data.array[ index + 2 ] = z;
20551		this.data.array[ index + 3 ] = w;
20552
20553		return this;
20554
20555	}
20556
20557	/**
20558	 * Returns a new buffer attribute with copied values from this instance.
20559	 *
20560	 * If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data.
20561	 *
20562	 * @param {Object} [data] - An object with interleaved buffers that allows to retain the interleaved property.
20563	 * @return {BufferAttribute|InterleavedBufferAttribute} A clone of this instance.
20564	 */
20565	clone( data ) {
20566
20567		if ( data === undefined ) {
20568
20569			log( 'InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' );
20570
20571			const array = [];
20572
20573			for ( let i = 0; i < this.count; i ++ ) {
20574
20575				const index = i * this.data.stride + this.offset;
20576
20577				for ( let j = 0; j < this.itemSize; j ++ ) {
20578
20579					array.push( this.data.array[ index + j ] );
20580
20581				}
20582
20583			}
20584
20585			return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized );
20586
20587		} else {
20588
20589			if ( data.interleavedBuffers === undefined ) {
20590
20591				data.interleavedBuffers = {};
20592
20593			}
20594
20595			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
20596
20597				data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
20598
20599			}
20600
20601			return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized );
20602
20603		}
20604
20605	}
20606
20607	/**
20608	 * Serializes the buffer attribute into JSON.
20609	 *
20610	 * If no parameter is provided, cloning an interleaved buffer attribute will de-interleave buffer data.
20611	 *
20612	 * @param {Object} [data] - An optional value holding meta information about the serialization.
20613	 * @return {Object} A JSON object representing the serialized buffer attribute.
20614	 */
20615	toJSON( data ) {
20616
20617		if ( data === undefined ) {
20618
20619			log( 'InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' );
20620
20621			const array = [];
20622
20623			for ( let i = 0; i < this.count; i ++ ) {
20624
20625				const index = i * this.data.stride + this.offset;
20626
20627				for ( let j = 0; j < this.itemSize; j ++ ) {
20628
20629					array.push( this.data.array[ index + j ] );
20630
20631				}
20632
20633			}
20634
20635			// de-interleave data and save it as an ordinary buffer attribute for now
20636
20637			return {
20638				itemSize: this.itemSize,
20639				type: this.array.constructor.name,
20640				array: array,
20641				normalized: this.normalized
20642			};
20643
20644		} else {
20645
20646			// save as true interleaved attribute
20647
20648			if ( data.interleavedBuffers === undefined ) {
20649
20650				data.interleavedBuffers = {};
20651
20652			}
20653
20654			if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) {
20655
20656				data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
20657
20658			}
20659
20660			return {
20661				isInterleavedBufferAttribute: true,
20662				itemSize: this.itemSize,
20663				data: this.data.uuid,
20664				offset: this.offset,
20665				normalized: this.normalized
20666			};
20667
20668		}
20669
20670	}
20671
20672}
20673
20674const _vector1 = /*@__PURE__*/ new Vector3();
20675const _vector2 = /*@__PURE__*/ new Vector3();
20676const _normalMatrix = /*@__PURE__*/ new Matrix3();
20677
20678/**
20679 * A two dimensional surface that extends infinitely in 3D space, represented
20680 * in [Hessian normal form](https://mathworld.wolfram.com/HessianNormalForm.html)
20681 * by a unit length normal vector and a constant.
20682 */
20683class Plane {
20684
20685	/**
20686	 * Constructs a new plane.
20687	 *
20688	 * @param {Vector3} [normal=(1,0,0)] - A unit length vector defining the normal of the plane.
20689	 * @param {number} [constant=0] - The signed distance from the origin to the plane.
20690	 */
20691	constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) {
20692
20693		/**
20694		 * This flag can be used for type testing.
20695		 *
20696		 * @type {boolean}
20697		 * @readonly
20698		 * @default true
20699		 */
20700		this.isPlane = true;
20701
20702		/**
20703		 * A unit length vector defining the normal of the plane.
20704		 *
20705		 * @type {Vector3}
20706		 */
20707		this.normal = normal;
20708
20709		/**
20710		 * The signed distance from the origin to the plane.
20711		 *
20712		 * @type {number}
20713		 * @default 0
20714		 */
20715		this.constant = constant;
20716
20717	}
20718
20719	/**
20720	 * Sets the plane components by copying the given values.
20721	 *
20722	 * @param {Vector3} normal - The normal.
20723	 * @param {number} constant - The constant.
20724	 * @return {Plane} A reference to this plane.
20725	 */
20726	set( normal, constant ) {
20727
20728		this.normal.copy( normal );
20729		this.constant = constant;
20730
20731		return this;
20732
20733	}
20734
20735	/**
20736	 * Sets the plane components by defining `x`, `y`, `z` as the
20737	 * plane normal and `w` as the constant.
20738	 *
20739	 * @param {number} x - The value for the normal's x component.
20740	 * @param {number} y - The value for the normal's y component.
20741	 * @param {number} z - The value for the normal's z component.
20742	 * @param {number} w - The constant value.
20743	 * @return {Plane} A reference to this plane.
20744	 */
20745	setComponents( x, y, z, w ) {
20746
20747		this.normal.set( x, y, z );
20748		this.constant = w;
20749
20750		return this;
20751
20752	}
20753
20754	/**
20755	 * Sets the plane from the given normal and coplanar point (that is a point
20756	 * that lies onto the plane).
20757	 *
20758	 * @param {Vector3} normal - The normal.
20759	 * @param {Vector3} point - A coplanar point.
20760	 * @return {Plane} A reference to this plane.
20761	 */
20762	setFromNormalAndCoplanarPoint( normal, point ) {
20763
20764		this.normal.copy( normal );
20765		this.constant = - point.dot( this.normal );
20766
20767		return this;
20768
20769	}
20770
20771	/**
20772	 * Sets the plane from three coplanar points. The winding order is
20773	 * assumed to be counter-clockwise, and determines the direction of
20774	 * the plane normal.
20775	 *
20776	 * @param {Vector3} a - The first coplanar point.
20777	 * @param {Vector3} b - The second coplanar point.
20778	 * @param {Vector3} c - The third coplanar point.
20779	 * @return {Plane} A reference to this plane.
20780	 */
20781	setFromCoplanarPoints( a, b, c ) {
20782
20783		const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();
20784
20785		// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
20786
20787		this.setFromNormalAndCoplanarPoint( normal, a );
20788
20789		return this;
20790
20791	}
20792
20793	/**
20794	 * Copies the values of the given plane to this instance.
20795	 *
20796	 * @param {Plane} plane - The plane to copy.
20797	 * @return {Plane} A reference to this plane.
20798	 */
20799	copy( plane ) {
20800
20801		this.normal.copy( plane.normal );
20802		this.constant = plane.constant;
20803
20804		return this;
20805
20806	}
20807
20808	/**
20809	 * Normalizes the plane normal and adjusts the constant accordingly.
20810	 *
20811	 * @return {Plane} A reference to this plane.
20812	 */
20813	normalize() {
20814
20815		// Note: will lead to a divide by zero if the plane is invalid.
20816
20817		const inverseNormalLength = 1.0 / this.normal.length();
20818		this.normal.multiplyScalar( inverseNormalLength );
20819		this.constant *= inverseNormalLength;
20820
20821		return this;
20822
20823	}
20824
20825	/**
20826	 * Negates both the plane normal and the constant.
20827	 *
20828	 * @return {Plane} A reference to this plane.
20829	 */
20830	negate() {
20831
20832		this.constant *= -1;
20833		this.normal.negate();
20834
20835		return this;
20836
20837	}
20838
20839	/**
20840	 * Returns the signed distance from the given point to this plane.
20841	 *
20842	 * @param {Vector3} point - The point to compute the distance for.
20843	 * @return {number} The signed distance.
20844	 */
20845	distanceToPoint( point ) {
20846
20847		return this.normal.dot( point ) + this.constant;
20848
20849	}
20850
20851	/**
20852	 * Returns the signed distance from the given sphere to this plane.
20853	 *
20854	 * @param {Sphere} sphere - The sphere to compute the distance for.
20855	 * @return {number} The signed distance.
20856	 */
20857	distanceToSphere( sphere ) {
20858
20859		return this.distanceToPoint( sphere.center ) - sphere.radius;
20860
20861	}
20862
20863	/**
20864	 * Projects a the given point onto the plane.
20865	 *
20866	 * @param {Vector3} point - The point to project.
20867	 * @param {Vector3} target - The target vector that is used to store the method's result.
20868	 * @return {Vector3} The projected point on the plane.
20869	 */
20870	projectPoint( point, target ) {
20871
20872		return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) );
20873
20874	}
20875
20876	/**
20877	 * Returns the intersection point of the passed line and the plane. Returns
20878	 * `null` if the line does not intersect. Returns the line's starting point if
20879	 * the line is coplanar with the plane.
20880	 *
20881	 * @param {Line3} line - The line to compute the intersection for.
20882	 * @param {Vector3} target - The target vector that is used to store the method's result.
20883	 * @param {boolean} [clampToLine=true] - Whether to clamp the intersection to the line segment.
20884	 * @return {?Vector3} The intersection point. Returns `null` if no intersection is detected.
20885	 */
20886	intersectLine( line, target, clampToLine = true ) {
20887
20888		const direction = line.delta( _vector1 );
20889
20890		const denominator = this.normal.dot( direction );
20891
20892		if ( denominator === 0 ) {
20893
20894			// line is coplanar, return origin
20895			if ( this.distanceToPoint( line.start ) === 0 ) {
20896
20897				return target.copy( line.start );
20898
20899			}
20900
20901			// Unsure if this is the correct method to handle this case.
20902			return null;
20903
20904		}
20905
20906		const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;
20907
20908		if ( ( clampToLine === true ) && ( t < 0 || t > 1 ) ) {
20909
20910			return null;
20911
20912		}
20913
20914		return target.copy( line.start ).addScaledVector( direction, t );
20915
20916	}
20917
20918	/**
20919	 * Returns `true` if the given line segment intersects with (passes through) the plane.
20920	 *
20921	 * @param {Line3} line - The line to test.
20922	 * @return {boolean} Whether the given line segment intersects with the plane or not.
20923	 */
20924	intersectsLine( line ) {
20925
20926		// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.
20927
20928		const startSign = this.distanceToPoint( line.start );
20929		const endSign = this.distanceToPoint( line.end );
20930
20931		return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
20932
20933	}
20934
20935	/**
20936	 * Returns `true` if the given bounding box intersects with the plane.
20937	 *
20938	 * @param {Box3} box - The bounding box to test.
20939	 * @return {boolean} Whether the given bounding box intersects with the plane or not.
20940	 */
20941	intersectsBox( box ) {
20942
20943		return box.intersectsPlane( this );
20944
20945	}
20946
20947	/**
20948	 * Returns `true` if the given bounding sphere intersects with the plane.
20949	 *
20950	 * @param {Sphere} sphere - The bounding sphere to test.
20951	 * @return {boolean} Whether the given bounding sphere intersects with the plane or not.
20952	 */
20953	intersectsSphere( sphere ) {
20954
20955		return sphere.intersectsPlane( this );
20956
20957	}
20958
20959	/**
20960	 * Returns a coplanar vector to the plane, by calculating the
20961	 * projection of the normal at the origin onto the plane.
20962	 *
20963	 * @param {Vector3} target - The target vector that is used to store the method's result.
20964	 * @return {Vector3} The coplanar point.
20965	 */
20966	coplanarPoint( target ) {
20967
20968		return target.copy( this.normal ).multiplyScalar( - this.constant );
20969
20970	}
20971
20972	/**
20973	 * Apply a 4x4 matrix to the plane. The matrix must be an affine, homogeneous transform.
20974	 *
20975	 * The optional normal matrix can be pre-computed like so:
20976	 * ```js
20977	 * const optionalNormalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
20978	 * ```
20979	 *
20980	 * @param {Matrix4} matrix - The transformation matrix.
20981	 * @param {Matrix4} [optionalNormalMatrix] - A pre-computed normal matrix.
20982	 * @return {Plane} A reference to this plane.
20983	 */
20984	applyMatrix4( matrix, optionalNormalMatrix ) {
20985
20986		const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
20987
20988		const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
20989
20990		const normal = this.normal.applyMatrix3( normalMatrix ).normalize();
20991
20992		this.constant = - referencePoint.dot( normal );
20993
20994		return this;
20995
20996	}
20997
20998	/**
20999	 * Translates the plane by the distance defined by the given offset vector.
21000	 * Note that this only affects the plane constant and will not affect the normal vector.
21001	 *
21002	 * @param {Vector3} offset - The offset vector.
21003	 * @return {Plane} A reference to this plane.
21004	 */
21005	translate( offset ) {
21006
21007		this.constant -= offset.dot( this.normal );
21008
21009		return this;
21010
21011	}
21012
21013	/**
21014	 * Returns `true` if this plane is equal with the given one.
21015	 *
21016	 * @param {Plane} plane - The plane to test for equality.
21017	 * @return {boolean} Whether this plane is equal with the given one.
21018	 */
21019	equals( plane ) {
21020
21021		return plane.normal.equals( this.normal ) && ( plane.constant === this.constant );
21022
21023	}
21024
21025	/**
21026	 * Returns a new plane with copied values from this instance.
21027	 *
21028	 * @return {Plane} A clone of this instance.
21029	 */
21030	clone() {
21031
21032		return new this.constructor().copy( this );
21033
21034	}
21035
21036	/**
21037	 * Returns a serialized structure of the plane.
21038	 *
21039	 * @return {Object} Serialized structure with fields representing the object state.
21040	 */
21041	toJSON() {
21042
21043		return {
21044			normal: this.normal.toArray(),
21045			constant: this.constant
21046		};
21047
21048	}
21049
21050	/**
21051	 * Sets the plane properties from the given JSON.
21052	 *
21053	 * @param {Object} json - The serialized json to set the plane from.
21054	 * @return {Plane} A reference to this plane.
21055	 */
21056	fromJSON( json ) {
21057
21058		this.normal.fromArray( json.normal );
21059		this.constant = json.constant;
21060
21061		return this;
21062
21063	}
21064
21065}
21066
21067let _materialId = 0;
21068
21069/**
21070 * Abstract base class for materials.
21071 *
21072 * Materials define the appearance of renderable 3D objects.
21073 *
21074 * @abstract
21075 * @augments EventDispatcher
21076 */
21077class Material extends EventDispatcher {
21078
21079	/**
21080	 * Constructs a new material.
21081	 */
21082	constructor() {
21083
21084		super();
21085
21086		/**
21087		 * This flag can be used for type testing.
21088		 *
21089		 * @type {boolean}
21090		 * @readonly
21091		 * @default true
21092		 */
21093		this.isMaterial = true;
21094
21095		/**
21096		 * The ID of the material.
21097		 *
21098		 * @name Material#id
21099		 * @type {number}
21100		 * @readonly
21101		 */
21102		Object.defineProperty( this, 'id', { value: _materialId ++ } );
21103
21104		/**
21105		 * The UUID of the material.
21106		 *
21107		 * @type {string}
21108		 * @readonly
21109		 */
21110		this.uuid = generateUUID();
21111
21112		/**
21113		 * The name of the material.
21114		 *
21115		 * @type {string}
21116		 */
21117		this.name = '';
21118
21119		/**
21120		 * The type property is used for detecting the object type
21121		 * in context of serialization/deserialization.
21122		 *
21123		 * @type {string}
21124		 * @readonly
21125		 */
21126		this.type = 'Material';
21127
21128		/**
21129		 * Defines the blending type of the material.
21130		 *
21131		 * It must be set to `CustomBlending` if custom blending properties like
21132		 * {@link Material#blendSrc}, {@link Material#blendDst} or {@link Material#blendEquation}
21133		 * should have any effect.
21134		 *
21135		 * @type {(NoBlending|NormalBlending|AdditiveBlending|SubtractiveBlending|MultiplyBlending|CustomBlending)}
21136		 * @default NormalBlending
21137		 */
21138		this.blending = NormalBlending;
21139
21140		/**
21141		 * Defines which side of faces will be rendered - front, back or both.
21142		 *
21143		 * @type {(FrontSide|BackSide|DoubleSide)}
21144		 * @default FrontSide
21145		 */
21146		this.side = FrontSide;
21147
21148		/**
21149		 * If set to `true`, vertex colors should be used.
21150		 *
21151		 * The engine supports RGB and RGBA vertex colors depending on whether a three (RGB) or
21152		 * four (RGBA) component color buffer attribute is used.
21153		 *
21154		 * @type {boolean}
21155		 * @default false
21156		 */
21157		this.vertexColors = false;
21158
21159		/**
21160		 * Defines how transparent the material is.
21161		 * A value of `0.0` indicates fully transparent, `1.0` is fully opaque.
21162		 *
21163		 * If the {@link Material#transparent} is not set to `true`,
21164		 * the material will remain fully opaque and this value will only affect its color.
21165		 *
21166		 * @type {number}
21167		 * @default 1
21168		 */
21169		this.opacity = 1;
21170
21171		/**
21172		 * Defines whether this material is transparent. This has an effect on
21173		 * rendering as transparent objects need special treatment and are rendered
21174		 * after non-transparent objects.
21175		 *
21176		 * When set to true, the extent to which the material is transparent is
21177		 * controlled by {@link Material#opacity}.
21178		 *
21179		 * @type {boolean}
21180		 * @default false
21181		 */
21182		this.transparent = false;
21183
21184		/**
21185		 * Enables alpha hashed transparency, an alternative to {@link Material#transparent} or
21186		 * {@link Material#alphaTest}. The material will not be rendered if opacity is lower than
21187		 * a random threshold. Randomization introduces some grain or noise, but approximates alpha
21188		 * blending without the associated problems of sorting. Using TAA can reduce the resulting noise.
21189		 *
21190		 * @type {boolean}
21191		 * @default false
21192		 */
21193		this.alphaHash = false;
21194
21195		/**
21196		 * Defines the blending source factor.
21197		 *
21198		 * @type {(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
21199		 * @default SrcAlphaFactor
21200		 */
21201		this.blendSrc = SrcAlphaFactor;
21202
21203		/**
21204		 * Defines the blending destination factor.
21205		 *
21206		 * @type {(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
21207		 * @default OneMinusSrcAlphaFactor
21208		 */
21209		this.blendDst = OneMinusSrcAlphaFactor;
21210
21211		/**
21212		 * Defines the blending equation.
21213		 *
21214		 * @type {(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
21215		 * @default AddEquation
21216		 */
21217		this.blendEquation = AddEquation;
21218
21219		/**
21220		 * Defines the blending source alpha factor.
21221		 *
21222		 * @type {?(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
21223		 * @default null
21224		 */
21225		this.blendSrcAlpha = null;
21226
21227		/**
21228		 * Defines the blending destination alpha factor.
21229		 *
21230		 * @type {?(ZeroFactor|OneFactor|SrcColorFactor|OneMinusSrcColorFactor|SrcAlphaFactor|OneMinusSrcAlphaFactor|DstAlphaFactor|OneMinusDstAlphaFactor|DstColorFactor|OneMinusDstColorFactor|SrcAlphaSaturateFactor|ConstantColorFactor|OneMinusConstantColorFactor|ConstantAlphaFactor|OneMinusConstantAlphaFactor)}
21231		 * @default null
21232		 */
21233		this.blendDstAlpha = null;
21234
21235		/**
21236		 * Defines the blending equation of the alpha channel.
21237		 *
21238		 * @type {?(AddEquation|SubtractEquation|ReverseSubtractEquation|MinEquation|MaxEquation)}
21239		 * @default null
21240		 */
21241		this.blendEquationAlpha = null;
21242
21243		/**
21244		 * Represents the RGB values of the constant blend color.
21245		 *
21246		 * This property has only an effect when using custom blending with `ConstantColor` or `OneMinusConstantColor`.
21247		 *
21248		 * @type {Color}
21249		 * @default (0,0,0)
21250		 */
21251		this.blendColor = new Color( 0, 0, 0 );
21252
21253		/**
21254		 * Represents the alpha value of the constant blend color.
21255		 *
21256		 * This property has only an effect when using custom blending with `ConstantAlpha` or `OneMinusConstantAlpha`.
21257		 *
21258		 * @type {number}
21259		 * @default 0
21260		 */
21261		this.blendAlpha = 0;
21262
21263		/**
21264		 * Defines the depth function.
21265		 *
21266		 * @type {(NeverDepth|AlwaysDepth|LessDepth|LessEqualDepth|EqualDepth|GreaterEqualDepth|GreaterDepth|NotEqualDepth)}
21267		 * @default LessEqualDepth
21268		 */
21269		this.depthFunc = LessEqualDepth;
21270
21271		/**
21272		 * Whether to have depth test enabled when rendering this material.
21273		 * When the depth test is disabled, the depth write will also be implicitly disabled.
21274		 *
21275		 * @type {boolean}
21276		 * @default true
21277		 */
21278		this.depthTest = true;
21279
21280		/**
21281		 * Whether rendering this material has any effect on the depth buffer.
21282		 *
21283		 * When drawing 2D overlays it can be useful to disable the depth writing in
21284		 * order to layer several things together without creating z-index artifacts.
21285		 *
21286		 * @type {boolean}
21287		 * @default true
21288		 */
21289		this.depthWrite = true;
21290
21291		/**
21292		 * The bit mask to use when writing to the stencil buffer.
21293		 *
21294		 * @type {number}
21295		 * @default 0xff
21296		 */
21297		this.stencilWriteMask = 0xff;
21298
21299		/**
21300		 * The stencil comparison function to use.
21301		 *
21302		 * @type {NeverStencilFunc|LessStencilFunc|EqualStencilFunc|LessEqualStencilFunc|GreaterStencilFunc|NotEqualStencilFunc|GreaterEqualStencilFunc|AlwaysStencilFunc}
21303		 * @default AlwaysStencilFunc
21304		 */
21305		this.stencilFunc = AlwaysStencilFunc;
21306
21307		/**
21308		 * The value to use when performing stencil comparisons or stencil operations.
21309		 *
21310		 * @type {number}
21311		 * @default 0
21312		 */
21313		this.stencilRef = 0;
21314
21315		/**
21316		 * The bit mask to use when comparing against the stencil buffer.
21317		 *
21318		 * @type {number}
21319		 * @default 0xff
21320		 */
21321		this.stencilFuncMask = 0xff;
21322
21323		/**
21324		 * Which stencil operation to perform when the comparison function returns `false`.
21325		 *
21326		 * @type {ZeroStencilOp|KeepStencilOp|ReplaceStencilOp|IncrementStencilOp|DecrementStencilOp|IncrementWrapStencilOp|DecrementWrapStencilOp|InvertStencilOp}
21327		 * @default KeepStencilOp
21328		 */
21329		this.stencilFail = KeepStencilOp;
21330
21331		/**
21332		 * Which stencil operation to perform when the comparison function returns
21333		 * `true` but the depth test fails.
21334		 *
21335		 * @type {ZeroStencilOp|KeepStencilOp|ReplaceStencilOp|IncrementStencilOp|DecrementStencilOp|IncrementWrapStencilOp|DecrementWrapStencilOp|InvertStencilOp}
21336		 * @default KeepStencilOp
21337		 */
21338		this.stencilZFail = KeepStencilOp;
21339
21340		/**
21341		 * Which stencil operation to perform when the comparison function returns
21342		 * `true` and the depth test passes.
21343		 *
21344		 * @type {ZeroStencilOp|KeepStencilOp|ReplaceStencilOp|IncrementStencilOp|DecrementStencilOp|IncrementWrapStencilOp|DecrementWrapStencilOp|InvertStencilOp}
21345		 * @default KeepStencilOp
21346		 */
21347		this.stencilZPass = KeepStencilOp;
21348
21349		/**
21350		 * Whether stencil operations are performed against the stencil buffer. In
21351		 * order to perform writes or comparisons against the stencil buffer this
21352		 * value must be `true`.
21353		 *
21354		 * @type {boolean}
21355		 * @default false
21356		 */
21357		this.stencilWrite = false;
21358
21359		/**
21360		 * User-defined clipping planes specified as THREE.Plane objects in world
21361		 * space. These planes apply to the objects this material is attached to.
21362		 * Points in space whose signed distance to the plane is negative are clipped
21363		 * (not rendered). This requires {@link WebGLRenderer#localClippingEnabled} to
21364		 * be `true`.
21365		 *
21366		 * @type {?Array<Plane>}
21367		 * @default null
21368		 */
21369		this.clippingPlanes = null;
21370
21371		/**
21372		 * Changes the behavior of clipping planes so that only their intersection is
21373		 * clipped, rather than their union.
21374		 *
21375		 * @type {boolean}
21376		 * @default false
21377		 */
21378		this.clipIntersection = false;
21379
21380		/**
21381		 * Defines whether to clip shadows according to the clipping planes specified
21382		 * on this material.
21383		 *
21384		 * @type {boolean}
21385		 * @default false
21386		 */
21387		this.clipShadows = false;
21388
21389		/**
21390		 * Defines which side of faces cast shadows. If `null`, the side casting shadows
21391		 * is determined as follows:
21392		 *
21393		 * - When {@link Material#side} is set to `FrontSide`, the back side cast shadows.
21394		 * - When {@link Material#side} is set to `BackSide`, the front side cast shadows.
21395		 * - When {@link Material#side} is set to `DoubleSide`, both sides cast shadows.
21396		 *
21397		 * @type {?(FrontSide|BackSide|DoubleSide)}
21398		 * @default null
21399		 */
21400		this.shadowSide = null;
21401
21402		/**
21403		 * Whether to render the material's color.
21404		 *
21405		 * This can be used in conjunction with {@link Object3D#renderOder} to create invisible
21406		 * objects that occlude other objects.
21407		 *
21408		 * @type {boolean}
21409		 * @default true
21410		 */
21411		this.colorWrite = true;
21412
21413		/**
21414		 * Override the renderer's default precision for this material.
21415		 *
21416		 * @type {?('highp'|'mediump'|'lowp')}
21417		 * @default null
21418		 */
21419		this.precision = null;
21420
21421		/**
21422		 * Whether to use polygon offset or not. When enabled, each fragment's depth value will
21423		 * be offset after it is interpolated from the depth values of the appropriate vertices.
21424		 * The offset is added before the depth test is performed and before the value is written
21425		 * into the depth buffer.
21426		 *
21427		 * Can be useful for rendering hidden-line images, for applying decals to surfaces, and for
21428		 * rendering solids with highlighted edges.
21429		 *
21430		 * @type {boolean}
21431		 * @default false
21432		 */
21433		this.polygonOffset = false;
21434
21435		/**
21436		 * Specifies a scale factor that is used to create a variable depth offset for each polygon.
21437		 *
21438		 * @type {number}
21439		 * @default 0
21440		 */
21441		this.polygonOffsetFactor = 0;
21442
21443		/**
21444		 * Is multiplied by an implementation-specific value to create a constant depth offset.
21445		 *
21446		 * @type {number}
21447		 * @default 0
21448		 */
21449		this.polygonOffsetUnits = 0;
21450
21451		/**
21452		 * Whether to apply dithering to the color to remove the appearance of banding.
21453		 *
21454		 * @type {boolean}
21455		 * @default false
21456		 */
21457		this.dithering = false;
21458
21459		/**
21460		 * Whether alpha to coverage should be enabled or not. Can only be used with MSAA-enabled contexts
21461		 * (meaning when the renderer was created with *antialias* parameter set to `true`). Enabling this
21462		 * will smooth aliasing on clip plane edges and alphaTest-clipped edges.
21463		 *
21464		 * @type {boolean}
21465		 * @default false
21466		 */
21467		this.alphaToCoverage = false;
21468
21469		/**
21470		 * Whether to premultiply the alpha (transparency) value.
21471		 *
21472		 * @type {boolean}
21473		 * @default false
21474		 */
21475		this.premultipliedAlpha = false;
21476
21477		/**
21478		 * Whether double-sided, transparent objects should be rendered with a single pass or not.
21479		 *
21480		 * The engine renders double-sided, transparent objects with two draw calls (back faces first,
21481		 * then front faces) to mitigate transparency artifacts. There are scenarios however where this
21482		 * approach produces no quality gains but still doubles draw calls e.g. when rendering flat
21483		 * vegetation like grass sprites. In these cases, set the `forceSinglePass` flag to `true` to
21484		 * disable the two pass rendering to avoid performance issues.
21485		 *
21486		 * @type {boolean}
21487		 * @default false
21488		 */
21489		this.forceSinglePass = false;
21490
21491		/**
21492		 * Whether it's possible to override the material with {@link Scene#overrideMaterial} or not.
21493		 *
21494		 * @type {boolean}
21495		 * @default true
21496		 */
21497		this.allowOverride = true;
21498
21499		/**
21500		 * Defines whether 3D objects using this material are visible.
21501		 *
21502		 * @type {boolean}
21503		 * @default true
21504		 */
21505		this.visible = true;
21506
21507		/**
21508		 * Defines whether this material is tone mapped according to the renderer's tone mapping setting.
21509		 *
21510		 * It is ignored when rendering to a render target or using post processing or when using
21511		 * `WebGPURenderer`. In all these cases, all materials are honored by tone mapping.
21512		 *
21513		 * @type {boolean}
21514		 * @default true
21515		 */
21516		this.toneMapped = true;
21517
21518		/**
21519		 * An object that can be used to store custom data about the Material. It
21520		 * should not hold references to functions as these will not be cloned.
21521		 *
21522		 * @type {Object}
21523		 */
21524		this.userData = {};
21525
21526		/**
21527		 * This starts at `0` and counts how many times {@link Material#needsUpdate} is set to `true`.
21528		 *
21529		 * @type {number}
21530		 * @readonly
21531		 * @default 0
21532		 */
21533		this.version = 0;
21534
21535		this._alphaTest = 0;
21536
21537	}
21538
21539	/**
21540	 * Sets the alpha value to be used when running an alpha test. The material
21541	 * will not be rendered if the opacity is lower than this value.
21542	 *
21543	 * @type {number}
21544	 * @readonly
21545	 * @default 0
21546	 */
21547	get alphaTest() {
21548
21549		return this._alphaTest;
21550
21551	}
21552
21553	set alphaTest( value ) {
21554
21555		if ( this._alphaTest > 0 !== value > 0 ) {
21556
21557			this.version ++;
21558
21559		}
21560
21561		this._alphaTest = value;
21562
21563	}
21564
21565	/**
21566	 * An optional callback that is executed immediately before the material is used to render a 3D object.
21567	 *
21568	 * This method can only be used when rendering with {@link WebGLRenderer}.
21569	 *
21570	 * @param {WebGLRenderer} renderer - The renderer.
21571	 * @param {Scene} scene - The scene.
21572	 * @param {Camera} camera - The camera that is used to render the scene.
21573	 * @param {BufferGeometry} geometry - The 3D object's geometry.
21574	 * @param {Object3D} object - The 3D object.
21575	 * @param {Object} group - The geometry group data.
21576	 */
21577	onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {}
21578
21579	/**
21580	 * An optional callback that is executed immediately before the shader
21581	 * program is compiled. This function is called with the shader source code
21582	 * as a parameter. Useful for the modification of built-in materials.
21583	 *
21584	 * This method can only be used when rendering with {@link WebGLRenderer}. The
21585	 * recommended approach when customizing materials is to use `WebGPURenderer` with the new
21586	 * Node Material system and [TSL](https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language).
21587	 *
21588	 * @param {{vertexShader:string,fragmentShader:string,uniforms:Object}} shaderobject - The object holds the uniforms and the vertex and fragment shader source.
21589	 * @param {WebGLRenderer} renderer - A reference to the renderer.
21590	 */
21591	onBeforeCompile( /* shaderobject, renderer */ ) {}
21592
21593	/**
21594	 * In case {@link Material#onBeforeCompile} is used, this callback can be used to identify
21595	 * values of settings used in `onBeforeCompile()`, so three.js can reuse a cached
21596	 * shader or recompile the shader for this material as needed.
21597	 *
21598	 * This method can only be used when rendering with {@link WebGLRenderer}.
21599	 *
21600	 * @return {string} The custom program cache key.
21601	 */
21602	customProgramCacheKey() {
21603
21604		return this.onBeforeCompile.toString();
21605
21606	}
21607
21608	/**
21609	 * This method can be used to set default values from parameter objects.
21610	 * It is a generic implementation so it can be used with different types
21611	 * of materials.
21612	 *
21613	 * @param {Object} [values] - The material values to set.
21614	 */
21615	setValues( values ) {
21616
21617		if ( values === undefined ) return;
21618
21619		for ( const key in values ) {
21620
21621			const newValue = values[ key ];
21622
21623			if ( newValue === undefined ) {
21624
21625				warn( `Material: parameter '${ key }' has value of undefined.` );
21626				continue;
21627
21628			}
21629
21630			const currentValue = this[ key ];
21631
21632			if ( currentValue === undefined ) {
21633
21634				warn( `Material: '${ key }' is not a property of THREE.${ this.type }.` );
21635				continue;
21636
21637			}
21638
21639			if ( currentValue && currentValue.isColor ) {
21640
21641				currentValue.set( newValue );
21642
21643			} else if (
21644				( ( currentValue && currentValue.isVector2 ) && ( newValue && newValue.isVector2 ) ) ||
21645				( ( currentValue && currentValue.isEuler ) && ( newValue && newValue.isEuler ) ) ||
21646				( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) )
21647			) {
21648
21649				currentValue.copy( newValue );
21650
21651			} else {
21652
21653				this[ key ] = newValue;
21654
21655			}
21656
21657		}
21658
21659	}
21660
21661	/**
21662	 * Serializes the material into JSON.
21663	 *
21664	 * @param {?(Object|string)} meta - An optional value holding meta information about the serialization.
21665	 * @return {Object} A JSON object representing the serialized material.
21666	 * @see {@link ObjectLoader#parse}
21667	 */
21668	toJSON( meta ) {
21669
21670		const isRootObject = ( meta === undefined || typeof meta === 'string' );
21671
21672		if ( isRootObject ) {
21673
21674			meta = {
21675				textures: {},
21676				images: {}
21677			};
21678
21679		}
21680
21681		const data = {
21682			metadata: {
21683				version: 4.7,
21684				type: 'Material',
21685				generator: 'Material.toJSON'
21686			}
21687		};
21688
21689		// standard Material serialization
21690
21691		data.uuid = this.uuid;
21692		data.type = this.type;
21693
21694		data.blending = this.blending;
21695		data.side = this.side;
21696		data.shadowSide = this.shadowSide;
21697		data.vertexColors = this.vertexColors;
21698
21699		data.opacity = this.opacity;
21700		data.transparent = this.transparent;
21701
21702		data.blendSrc = this.blendSrc;
21703		data.blendDst = this.blendDst;
21704		data.blendEquation = this.blendEquation;
21705		data.blendSrcAlpha = this.blendSrcAlpha;
21706		data.blendDstAlpha = this.blendDstAlpha;
21707		data.blendEquationAlpha = this.blendEquationAlpha;
21708		data.blendColor = this.blendColor.getHex();
21709		data.blendAlpha = this.blendAlpha;
21710
21711		data.depthFunc = this.depthFunc;
21712		data.depthTest = this.depthTest;
21713		data.depthWrite = this.depthWrite;
21714		data.colorWrite = this.colorWrite;
21715
21716		data.clipIntersection = this.clipIntersection;
21717		data.clipShadows = this.clipShadows;
21718
21719		data.stencilWriteMask = this.stencilWriteMask;
21720		data.stencilFunc = this.stencilFunc;
21721		data.stencilRef = this.stencilRef;
21722		data.stencilFuncMask = this.stencilFuncMask;
21723		data.stencilFail = this.stencilFail;
21724		data.stencilZFail = this.stencilZFail;
21725		data.stencilZPass = this.stencilZPass;
21726		data.stencilWrite = this.stencilWrite;
21727
21728		data.polygonOffset = this.polygonOffset;
21729		data.polygonOffsetFactor = this.polygonOffsetFactor;
21730		data.polygonOffsetUnits = this.polygonOffsetUnits;
21731
21732		data.dithering = this.dithering;
21733
21734		data.alphaTest = this.alphaTest;
21735		data.alphaHash = this.alphaHash;
21736		data.alphaToCoverage = this.alphaToCoverage;
21737		data.premultipliedAlpha = this.premultipliedAlpha;
21738		data.forceSinglePass = this.forceSinglePass;
21739		data.allowOverride = this.allowOverride;
21740
21741		data.visible = this.visible;
21742		data.toneMapped = this.toneMapped;
21743
21744		data.name = this.name;
21745
21746		if ( this.color && this.color.isColor ) data.color = this.color.getHex();
21747
21748		if ( this.roughness !== undefined ) data.roughness = this.roughness;
21749		if ( this.metalness !== undefined ) data.metalness = this.metalness;
21750
21751		if ( this.sheen !== undefined ) data.sheen = this.sheen;
21752		if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
21753		if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness;
21754		if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
21755		if ( this.emissiveIntensity !== undefined ) data.emissiveIntensity = this.emissiveIntensity;
21756
21757		if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
21758		if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity;
21759		if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
21760		if ( this.shininess !== undefined ) data.shininess = this.shininess;
21761		if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;
21762		if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
21763
21764		if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
21765
21766			data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
21767
21768		}
21769
21770		if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
21771
21772			data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
21773
21774		}
21775
21776		if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
21777
21778			data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
21779			data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
21780
21781		}
21782
21783		if ( this.sheenColorMap && this.sheenColorMap.isTexture ) {
21784
21785			data.sheenColorMap = this.sheenColorMap.toJSON( meta ).uuid;
21786
21787		}
21788
21789		if ( this.sheenRoughnessMap && this.sheenRoughnessMap.isTexture ) {
21790
21791			data.sheenRoughnessMap = this.sheenRoughnessMap.toJSON( meta ).uuid;
21792
21793		}
21794
21795		if ( this.dispersion !== undefined ) data.dispersion = this.dispersion;
21796		if ( this.retroreflectivity !== undefined ) data.retroreflectivity = this.retroreflectivity;
21797
21798		if ( this.iridescence !== undefined ) data.iridescence = this.iridescence;
21799		if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR;
21800		if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
21801
21802		if ( this.iridescenceMap && this.iridescenceMap.isTexture ) {
21803
21804			data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid;
21805
21806		}
21807
21808		if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) {
21809
21810			data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid;
21811
21812		}
21813
21814		if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy;
21815		if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation;
21816
21817		if ( this.anisotropyMap && this.anisotropyMap.isTexture ) {
21818
21819			data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid;
21820
21821		}
21822
21823		if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
21824		if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
21825		if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
21826
21827		if ( this.lightMap && this.lightMap.isTexture ) {
21828
21829			data.lightMap = this.lightMap.toJSON( meta ).uuid;
21830			data.lightMapIntensity = this.lightMapIntensity;
21831
21832		}
21833
21834		if ( this.aoMap && this.aoMap.isTexture ) {
21835
21836			data.aoMap = this.aoMap.toJSON( meta ).uuid;
21837			data.aoMapIntensity = this.aoMapIntensity;
21838
21839		}
21840
21841		if ( this.bumpMap && this.bumpMap.isTexture ) {
21842
21843			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
21844			data.bumpScale = this.bumpScale;
21845
21846		}
21847
21848		if ( this.normalMap && this.normalMap.isTexture ) {
21849
21850			data.normalMap = this.normalMap.toJSON( meta ).uuid;
21851			data.normalMapType = this.normalMapType;
21852			data.normalScale = this.normalScale.toArray();
21853
21854		}
21855
21856		if ( this.displacementMap && this.displacementMap.isTexture ) {
21857
21858			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
21859			data.displacementScale = this.displacementScale;
21860			data.displacementBias = this.displacementBias;
21861
21862		}
21863
21864		if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
21865		if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
21866
21867		if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
21868		if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
21869		if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
21870		if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
21871
21872		if ( this.envMap && this.envMap.isTexture ) {
21873
21874			data.envMap = this.envMap.toJSON( meta ).uuid;
21875
21876			if ( this.combine !== undefined ) data.combine = this.combine;
21877
21878		}
21879
21880		if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray();
21881		if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;
21882		if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity;
21883		if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio;
21884
21885		if ( this.gradientMap && this.gradientMap.isTexture ) {
21886
21887			data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
21888
21889		}
21890
21891		if ( this.transmission !== undefined ) data.transmission = this.transmission;
21892		if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
21893		if ( this.thickness !== undefined ) data.thickness = this.thickness;
21894		if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
21895		if ( this.attenuationDistance !== undefined ) data.attenuationDistance = this.attenuationDistance;
21896		if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex();
21897
21898		if ( this.size !== undefined ) data.size = this.size;
21899		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;
21900
21901		if ( Array.isArray( this.clippingPlanes ) && this.clippingPlanes.length > 0 ) {
21902
21903			data.clippingPlanes = this.clippingPlanes.map( plane => plane.toJSON() );
21904
21905		}
21906
21907		// rotation (SpriteMaterial)
21908		if ( this.rotation !== undefined ) data.rotation = this.rotation;
21909
21910		// depthPacking (MeshDepthMaterial)
21911		if ( this.depthPacking !== undefined ) data.depthPacking = this.depthPacking;
21912
21913		if ( this.linewidth !== undefined ) data.linewidth = this.linewidth;
21914		if ( this.linecap !== undefined ) data.linecap = this.linecap;
21915		if ( this.linejoin !== undefined ) data.linejoin = this.linejoin;
21916		if ( this.dashSize !== undefined ) data.dashSize = this.dashSize;
21917		if ( this.gapSize !== undefined ) data.gapSize = this.gapSize;
21918		if ( this.scale !== undefined ) data.scale = this.scale;
21919
21920		if ( this.wireframe !== undefined ) data.wireframe = this.wireframe;
21921		if ( this.wireframeLinewidth !== undefined ) data.wireframeLinewidth = this.wireframeLinewidth;
21922		if ( this.wireframeLinecap !== undefined ) data.wireframeLinecap = this.wireframeLinecap;
21923		if ( this.wireframeLinejoin !== undefined ) data.wireframeLinejoin = this.wireframeLinejoin;
21924
21925		if ( this.flatShading !== undefined ) data.flatShading = this.flatShading;
21926
21927		if ( this.fog !== undefined ) data.fog = this.fog;
21928
21929		if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;
21930
21931		// TODO: Copied from Object3D.toJSON
21932
21933		function extractFromCache( cache ) {
21934
21935			const values = [];
21936
21937			for ( const key in cache ) {
21938
21939				const data = cache[ key ];
21940				delete data.metadata;
21941				values.push( data );
21942
21943			}
21944
21945			return values;
21946
21947		}
21948
21949		if ( isRootObject ) {
21950
21951			const textures = extractFromCache( meta.textures );
21952			const images = extractFromCache( meta.images );
21953
21954			if ( textures.length > 0 ) data.textures = textures;
21955			if ( images.length > 0 ) data.images = images;
21956
21957		}
21958
21959		return data;
21960
21961	}
21962
21963	/**
21964	 * Deserializes the material from the given JSON.
21965	 *
21966	 * @param {Object} json - The JSON holding the serialized material.
21967	 * @param {Object<string,Texture>} textures - A dictionary holding textures referenced by the material.
21968	 * @return {Material} A reference to this material.
21969	 */
21970	fromJSON( json, textures ) {
21971
21972		if ( json.uuid !== undefined ) this.uuid = json.uuid;
21973		if ( json.name !== undefined ) this.name = json.name;
21974		if ( json.color !== undefined && this.color !== undefined ) this.color.setHex( json.color );
21975		if ( json.roughness !== undefined ) this.roughness = json.roughness;
21976		if ( json.metalness !== undefined ) this.metalness = json.metalness;
21977		if ( json.sheen !== undefined ) this.sheen = json.sheen;
21978		if ( json.sheenColor !== undefined ) this.sheenColor = new Color().setHex( json.sheenColor );
21979		if ( json.sheenRoughness !== undefined ) this.sheenRoughness = json.sheenRoughness;
21980		if ( json.emissive !== undefined && this.emissive !== undefined ) this.emissive.setHex( json.emissive );
21981		if ( json.specular !== undefined && this.specular !== undefined ) this.specular.setHex( json.specular );
21982		if ( json.specularIntensity !== undefined ) this.specularIntensity = json.specularIntensity;
21983		if ( json.specularColor !== undefined && this.specularColor !== undefined ) this.specularColor.setHex( json.specularColor );
21984		if ( json.shininess !== undefined ) this.shininess = json.shininess;
21985		if ( json.clearcoat !== undefined ) this.clearcoat = json.clearcoat;
21986		if ( json.clearcoatRoughness !== undefined ) this.clearcoatRoughness = json.clearcoatRoughness;
21987		if ( json.dispersion !== undefined ) this.dispersion = json.dispersion;
21988		if ( json.retroreflectivity !== undefined ) this.retroreflectivity = json.retroreflectivity;
21989		if ( json.iridescence !== undefined ) this.iridescence = json.iridescence;
21990		if ( json.iridescenceIOR !== undefined ) this.iridescenceIOR = json.iridescenceIOR;
21991		if ( json.iridescenceThicknessRange !== undefined ) this.iridescenceThicknessRange = json.iridescenceThicknessRange;
21992		if ( json.transmission !== undefined ) this.transmission = json.transmission;
21993		if ( json.thickness !== undefined ) this.thickness = json.thickness;
21994		if ( json.attenuationDistance !== undefined ) this.attenuationDistance = json.attenuationDistance;
21995		if ( json.attenuationColor !== undefined && this.attenuationColor !== undefined ) this.attenuationColor.setHex( json.attenuationColor );
21996		if ( json.anisotropy !== undefined ) this.anisotropy = json.anisotropy;
21997		if ( json.anisotropyRotation !== undefined ) this.anisotropyRotation = json.anisotropyRotation;
21998		if ( json.fog !== undefined ) this.fog = json.fog;
21999		if ( json.flatShading !== undefined ) this.flatShading = json.flatShading;
22000		if ( json.blending !== undefined ) this.blending = json.blending;
22001		if ( json.combine !== undefined ) this.combine = json.combine;
22002		if ( json.side !== undefined ) this.side = json.side;
22003		if ( json.shadowSide !== undefined ) this.shadowSide = json.shadowSide;
22004		if ( json.opacity !== undefined ) this.opacity = json.opacity;
22005		if ( json.transparent !== undefined ) this.transparent = json.transparent;
22006		if ( json.alphaTest !== undefined ) this.alphaTest = json.alphaTest;
22007		if ( json.alphaHash !== undefined ) this.alphaHash = json.alphaHash;
22008		if ( json.depthFunc !== undefined ) this.depthFunc = json.depthFunc;
22009		if ( json.depthTest !== undefined ) this.depthTest = json.depthTest;
22010		if ( json.depthWrite !== undefined ) this.depthWrite = json.depthWrite;
22011		if ( json.colorWrite !== undefined ) this.colorWrite = json.colorWrite;
22012		if ( json.clippingPlanes !== undefined ) this.clippingPlanes = json.clippingPlanes.map( plane => new Plane().fromJSON( plane ) );
22013		if ( json.clipIntersection !== undefined ) this.clipIntersection = json.clipIntersection;
22014		if ( json.clipShadows !== undefined ) this.clipShadows = json.clipShadows;
22015		if ( json.depthPacking !== undefined ) this.depthPacking = json.depthPacking;
22016		if ( json.blendSrc !== undefined ) this.blendSrc = json.blendSrc;
22017		if ( json.blendDst !== undefined ) this.blendDst = json.blendDst;
22018		if ( json.blendEquation !== undefined ) this.blendEquation = json.blendEquation;
22019		if ( json.blendSrcAlpha !== undefined ) this.blendSrcAlpha = json.blendSrcAlpha;
22020		if ( json.blendDstAlpha !== undefined ) this.blendDstAlpha = json.blendDstAlpha;
22021		if ( json.blendEquationAlpha !== undefined ) this.blendEquationAlpha = json.blendEquationAlpha;
22022		if ( json.blendColor !== undefined && this.blendColor !== undefined ) this.blendColor.setHex( json.blendColor );
22023		if ( json.blendAlpha !== undefined ) this.blendAlpha = json.blendAlpha;
22024		if ( json.stencilWriteMask !== undefined ) this.stencilWriteMask = json.stencilWriteMask;
22025		if ( json.stencilFunc !== undefined ) this.stencilFunc = json.stencilFunc;
22026		if ( json.stencilRef !== undefined ) this.stencilRef = json.stencilRef;
22027		if ( json.stencilFuncMask !== undefined ) this.stencilFuncMask = json.stencilFuncMask;
22028		if ( json.stencilFail !== undefined ) this.stencilFail = json.stencilFail;
22029		if ( json.stencilZFail !== undefined ) this.stencilZFail = json.stencilZFail;
22030		if ( json.stencilZPass !== undefined ) this.stencilZPass = json.stencilZPass;
22031		if ( json.stencilWrite !== undefined ) this.stencilWrite = json.stencilWrite;
22032
22033		if ( json.wireframe !== undefined ) this.wireframe = json.wireframe;
22034		if ( json.wireframeLinewidth !== undefined ) this.wireframeLinewidth = json.wireframeLinewidth;
22035		if ( json.wireframeLinecap !== undefined ) this.wireframeLinecap = json.wireframeLinecap;
22036		if ( json.wireframeLinejoin !== undefined ) this.wireframeLinejoin = json.wireframeLinejoin;
22037
22038		if ( json.rotation !== undefined ) this.rotation = json.rotation;
22039
22040		if ( json.linewidth !== undefined ) this.linewidth = json.linewidth;
22041		if ( json.linecap !== undefined ) this.linecap = json.linecap;
22042		if ( json.linejoin !== undefined ) this.linejoin = json.linejoin;
22043		if ( json.dashSize !== undefined ) this.dashSize = json.dashSize;
22044		if ( json.gapSize !== undefined ) this.gapSize = json.gapSize;
22045		if ( json.scale !== undefined ) this.scale = json.scale;
22046
22047		if ( json.polygonOffset !== undefined ) this.polygonOffset = json.polygonOffset;
22048		if ( json.polygonOffsetFactor !== undefined ) this.polygonOffsetFactor = json.polygonOffsetFactor;
22049		if ( json.polygonOffsetUnits !== undefined ) this.polygonOffsetUnits = json.polygonOffsetUnits;
22050
22051		if ( json.dithering !== undefined ) this.dithering = json.dithering;
22052
22053		if ( json.alphaToCoverage !== undefined ) this.alphaToCoverage = json.alphaToCoverage;
22054		if ( json.premultipliedAlpha !== undefined ) this.premultipliedAlpha = json.premultipliedAlpha;
22055		if ( json.forceSinglePass !== undefined ) this.forceSinglePass = json.forceSinglePass;
22056		if ( json.allowOverride !== undefined ) this.allowOverride = json.allowOverride;
22057
22058		if ( json.visible !== undefined ) this.visible = json.visible;
22059
22060		if ( json.toneMapped !== undefined ) this.toneMapped = json.toneMapped;
22061
22062		if ( json.userData !== undefined ) this.userData = json.userData;
22063
22064		if ( json.vertexColors !== undefined ) {
22065
22066			if ( typeof json.vertexColors === 'number' ) {
22067
22068				this.vertexColors = json.vertexColors > 0;
22069
22070			} else {
22071
22072				this.vertexColors = json.vertexColors;
22073
22074			}
22075
22076		}
22077
22078		// for PointsMaterial
22079
22080		if ( json.size !== undefined ) this.size = json.size;
22081		if ( json.sizeAttenuation !== undefined ) this.sizeAttenuation = json.sizeAttenuation;
22082
22083		// maps
22084
22085		if ( json.map !== undefined ) this.map = textures[ json.map ] || null;
22086		if ( json.matcap !== undefined ) this.matcap = textures[ json.matcap ] || null;
22087
22088		if ( json.alphaMap !== undefined ) this.alphaMap = textures[ json.alphaMap ] || null;
22089
22090		if ( json.bumpMap !== undefined ) this.bumpMap = textures[ json.bumpMap ] || null;
22091		if ( json.bumpScale !== undefined ) this.bumpScale = json.bumpScale;
22092
22093		if ( json.normalMap !== undefined ) this.normalMap = textures[ json.normalMap ] || null;
22094		if ( json.normalMapType !== undefined ) this.normalMapType = json.normalMapType;
22095		if ( json.normalScale !== undefined ) {
22096
22097			let normalScale = json.normalScale;
22098
22099			if ( Array.isArray( normalScale ) === false ) {
22100
22101				// Blender exporter used to export a scalar. See #7459
22102
22103				normalScale = [ normalScale, normalScale ];
22104
22105			}
22106
22107			this.normalScale = new Vector2().fromArray( normalScale );
22108
22109		}
22110
22111		if ( json.displacementMap !== undefined ) this.displacementMap = textures[ json.displacementMap ] || null;
22112		if ( json.displacementScale !== undefined ) this.displacementScale = json.displacementScale;
22113		if ( json.displacementBias !== undefined ) this.displacementBias = json.displacementBias;
22114
22115		if ( json.roughnessMap !== undefined ) this.roughnessMap = textures[ json.roughnessMap ] || null;
22116		if ( json.metalnessMap !== undefined ) this.metalnessMap = textures[ json.metalnessMap ] || null;
22117
22118		if ( json.emissiveMap !== undefined ) this.emissiveMap = textures[ json.emissiveMap ] || null;
22119		if ( json.emissiveIntensity !== undefined ) this.emissiveIntensity = json.emissiveIntensity;
22120
22121		if ( json.specularMap !== undefined ) this.specularMap = textures[ json.specularMap ] || null;
22122		if ( json.specularIntensityMap !== undefined ) this.specularIntensityMap = textures[ json.specularIntensityMap ] || null;
22123		if ( json.specularColorMap !== undefined ) this.specularColorMap = textures[ json.specularColorMap ] || null;
22124
22125		if ( json.envMap !== undefined ) this.envMap = textures[ json.envMap ] || null;
22126		if ( json.envMapRotation !== undefined ) this.envMapRotation.fromArray( json.envMapRotation );
22127		if ( json.envMapIntensity !== undefined ) this.envMapIntensity = json.envMapIntensity;
22128
22129		if ( json.reflectivity !== undefined ) this.reflectivity = json.reflectivity;
22130		if ( json.refractionRatio !== undefined ) this.refractionRatio = json.refractionRatio;
22131
22132		if ( json.lightMap !== undefined ) this.lightMap = textures[ json.lightMap ] || null;
22133		if ( json.lightMapIntensity !== undefined ) this.lightMapIntensity = json.lightMapIntensity;
22134
22135		if ( json.aoMap !== undefined ) this.aoMap = textures[ json.aoMap ] || null;
22136		if ( json.aoMapIntensity !== undefined ) this.aoMapIntensity = json.aoMapIntensity;
22137
22138		if ( json.gradientMap !== undefined ) this.gradientMap = textures[ json.gradientMap ] || null;
22139
22140		if ( json.clearcoatMap !== undefined ) this.clearcoatMap = textures[ json.clearcoatMap ] || null;
22141		if ( json.clearcoatRoughnessMap !== undefined ) this.clearcoatRoughnessMap = textures[ json.clearcoatRoughnessMap ] || null;
22142		if ( json.clearcoatNormalMap !== undefined ) this.clearcoatNormalMap = textures[ json.clearcoatNormalMap ] || null;
22143		if ( json.clearcoatNormalScale !== undefined ) this.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
22144
22145		if ( json.iridescenceMap !== undefined ) this.iridescenceMap = textures[ json.iridescenceMap ] || null;
22146		if ( json.iridescenceThicknessMap !== undefined ) this.iridescenceThicknessMap = textures[ json.iridescenceThicknessMap ] || null;
22147
22148		if ( json.transmissionMap !== undefined ) this.transmissionMap = textures[ json.transmissionMap ] || null;
22149		if ( json.thicknessMap !== undefined ) this.thicknessMap = textures[ json.thicknessMap ] || null;
22150
22151		if ( json.anisotropyMap !== undefined ) this.anisotropyMap = textures[ json.anisotropyMap ] || null;
22152
22153		if ( json.sheenColorMap !== undefined ) this.sheenColorMap = textures[ json.sheenColorMap ] || null;
22154		if ( json.sheenRoughnessMap !== undefined ) this.sheenRoughnessMap = textures[ json.sheenRoughnessMap ] || null;
22155
22156		return this;
22157
22158	}
22159
22160	/**
22161	 * Returns a new material with copied values from this instance.
22162	 *
22163	 * @return {Material} A clone of this instance.
22164	 */
22165	clone() {
22166
22167		return new this.constructor().copy( this );
22168
22169	}
22170
22171	/**
22172	 * Copies the values of the given material to this instance.
22173	 *
22174	 * @param {Material} source - The material to copy.
22175	 * @return {Material} A reference to this instance.
22176	 */
22177	copy( source ) {
22178
22179		this.name = source.name;
22180
22181		this.blending = source.blending;
22182		this.side = source.side;
22183		this.vertexColors = source.vertexColors;
22184
22185		this.opacity = source.opacity;
22186		this.transparent = source.transparent;
22187
22188		this.blendSrc = source.blendSrc;
22189		this.blendDst = source.blendDst;
22190		this.blendEquation = source.blendEquation;
22191		this.blendSrcAlpha = source.blendSrcAlpha;
22192		this.blendDstAlpha = source.blendDstAlpha;
22193		this.blendEquationAlpha = source.blendEquationAlpha;
22194		this.blendColor.copy( source.blendColor );
22195		this.blendAlpha = source.blendAlpha;
22196
22197		this.depthFunc = source.depthFunc;
22198		this.depthTest = source.depthTest;
22199		this.depthWrite = source.depthWrite;
22200
22201		this.stencilWriteMask = source.stencilWriteMask;
22202		this.stencilFunc = source.stencilFunc;
22203		this.stencilRef = source.stencilRef;
22204		this.stencilFuncMask = source.stencilFuncMask;
22205		this.stencilFail = source.stencilFail;
22206		this.stencilZFail = source.stencilZFail;
22207		this.stencilZPass = source.stencilZPass;
22208		this.stencilWrite = source.stencilWrite;
22209
22210		const srcPlanes = source.clippingPlanes;
22211		let dstPlanes = null;
22212
22213		if ( srcPlanes !== null ) {
22214
22215			const n = srcPlanes.length;
22216			dstPlanes = new Array( n );
22217
22218			for ( let i = 0; i !== n; ++ i ) {
22219
22220				dstPlanes[ i ] = srcPlanes[ i ].clone();
22221
22222			}
22223
22224		}
22225
22226		this.clippingPlanes = dstPlanes;
22227		this.clipIntersection = source.clipIntersection;
22228		this.clipShadows = source.clipShadows;
22229
22230		this.shadowSide = source.shadowSide;
22231
22232		this.colorWrite = source.colorWrite;
22233
22234		this.precision = source.precision;
22235
22236		this.polygonOffset = source.polygonOffset;
22237		this.polygonOffsetFactor = source.polygonOffsetFactor;
22238		this.polygonOffsetUnits = source.polygonOffsetUnits;
22239
22240		this.dithering = source.dithering;
22241
22242		this.alphaTest = source.alphaTest;
22243		this.alphaHash = source.alphaHash;
22244		this.alphaToCoverage = source.alphaToCoverage;
22245		this.premultipliedAlpha = source.premultipliedAlpha;
22246		this.forceSinglePass = source.forceSinglePass;
22247		this.allowOverride = source.allowOverride;
22248
22249		this.visible = source.visible;
22250
22251		this.toneMapped = source.toneMapped;
22252
22253		this.userData = JSON.parse( JSON.stringify( source.userData ) );
22254
22255		return this;
22256
22257	}
22258
22259	/**
22260	 * Frees the GPU-related resources allocated by this instance. Call this
22261	 * method whenever this instance is no longer used in your app.
22262	 *
22263	 * @fires Material#dispose
22264	 */
22265	dispose() {
22266
22267		/**
22268		 * Fires when the material has been disposed of.
22269		 *
22270		 * @event Material#dispose
22271		 * @type {Object}
22272		 */
22273		this.dispatchEvent( { type: 'dispose' } );
22274
22275	}
22276
22277	/**
22278	 * Setting this property to `true` indicates the engine the material
22279	 * needs to be recompiled.
22280	 *
22281	 * @type {boolean}
22282	 * @default false
22283	 * @param {boolean} value
22284	 */
22285	set needsUpdate( value ) {
22286
22287		if ( value === true ) this.version ++;
22288
22289	}
22290
22291}
22292
22293/**
22294 * A material for rendering instances of {@link Sprite}.
22295 *
22296 * ```js
22297 * const map = new THREE.TextureLoader().load( 'textures/sprite.png' );
22298 * const material = new THREE.SpriteMaterial( { map: map, color: 0xffffff } );
22299 *
22300 * const sprite = new THREE.Sprite( material );
22301 * sprite.scale.set(200, 200, 1)
22302 * scene.add( sprite );
22303 * ```
22304 *
22305 * @augments Material
22306 */
22307class SpriteMaterial extends Material {
22308
22309	/**
22310	 * Constructs a new sprite material.
22311	 *
22312	 * @param {Object} [parameters] - An object with one or more properties
22313	 * defining the material's appearance. Any property of the material
22314	 * (including any property from inherited materials) can be passed
22315	 * in here. Color values can be passed any type of value accepted
22316	 * by {@link Color#set}.
22317	 */
22318	constructor( parameters ) {
22319
22320		super();
22321
22322		/**
22323		 * This flag can be used for type testing.
22324		 *
22325		 * @type {boolean}
22326		 * @readonly
22327		 * @default true
22328		 */
22329		this.isSpriteMaterial = true;
22330
22331		this.type = 'SpriteMaterial';
22332
22333		/**
22334		 * Color of the material.
22335		 *
22336		 * @type {Color}
22337		 * @default (1,1,1)
22338		 */
22339		this.color = new Color( 0xffffff );
22340
22341		/**
22342		 * The color map. May optionally include an alpha channel, typically combined
22343		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
22344		 * color is modulated by the diffuse `color`.
22345		 *
22346		 * `map` represents color data, and the texture must be assigned a
22347		 * {@link Texture#colorSpace}. Most `map` textures set
22348		 * `texture.colorSpace = SRGBColorSpace`.
22349		 *
22350		 * @type {?Texture}
22351		 * @default null
22352		 */
22353		this.map = null;
22354
22355		/**
22356		 * The alpha map is a grayscale texture that controls the opacity across the
22357		 * surface (black: fully transparent; white: fully opaque).
22358		 *
22359		 * Only the color of the texture is used, ignoring the alpha channel if one
22360		 * exists. For RGB and RGBA textures, the renderer will use the green channel
22361		 * when sampling this texture due to the extra bit of precision provided for
22362		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
22363		 * luminance/alpha textures will also still work as expected.
22364		 *
22365		 * `alphaMap` represents non-color data. Any texture assigned must have
22366		 * `texture.colorSpace = NoColorSpace` (default).
22367		 *
22368		 * @type {?Texture}
22369		 * @default null
22370		 */
22371		this.alphaMap = null;
22372
22373		/**
22374		 * The rotation of the sprite in radians.
22375		 *
22376		 * @type {number}
22377		 * @default 0
22378		 */
22379		this.rotation = 0;
22380
22381		/**
22382		 * Specifies whether size of the sprite is attenuated by the camera depth (perspective camera only).
22383		 *
22384		 * @type {boolean}
22385		 * @default true
22386		 */
22387		this.sizeAttenuation = true;
22388
22389		/**
22390		 * Overwritten since sprite materials are transparent
22391		 * by default.
22392		 *
22393		 * @type {boolean}
22394		 * @default true
22395		 */
22396		this.transparent = true;
22397
22398		/**
22399		 * Whether the material is affected by fog or not.
22400		 *
22401		 * @type {boolean}
22402		 * @default true
22403		 */
22404		this.fog = true;
22405
22406		this.setValues( parameters );
22407
22408	}
22409
22410	copy( source ) {
22411
22412		super.copy( source );
22413
22414		this.color.copy( source.color );
22415
22416		this.map = source.map;
22417
22418		this.alphaMap = source.alphaMap;
22419
22420		this.rotation = source.rotation;
22421
22422		this.sizeAttenuation = source.sizeAttenuation;
22423
22424		this.fog = source.fog;
22425
22426		return this;
22427
22428	}
22429
22430}
22431
22432let _geometry;
22433
22434const _intersectPoint = /*@__PURE__*/ new Vector3();
22435const _worldScale = /*@__PURE__*/ new Vector3();
22436const _mvPosition = /*@__PURE__*/ new Vector3();
22437
22438const _alignedPosition = /*@__PURE__*/ new Vector2();
22439const _rotatedPosition = /*@__PURE__*/ new Vector2();
22440const _viewWorldMatrix = /*@__PURE__*/ new Matrix4();
22441
22442const _vA$1 = /*@__PURE__*/ new Vector3();
22443const _vB$1 = /*@__PURE__*/ new Vector3();
22444const _vC$1 = /*@__PURE__*/ new Vector3();
22445
22446const _uvA = /*@__PURE__*/ new Vector2();
22447const _uvB = /*@__PURE__*/ new Vector2();
22448const _uvC = /*@__PURE__*/ new Vector2();
22449
22450/**
22451 * A sprite is a plane that always faces towards the camera, generally with a
22452 * partially transparent texture applied.
22453 *
22454 * Sprites do not cast shadows, setting {@link Object3D#castShadow} to `true` will
22455 * have no effect.
22456 *
22457 * ```js
22458 * const map = new THREE.TextureLoader().load( 'sprite.png' );
22459 * const material = new THREE.SpriteMaterial( { map: map } );
22460 *
22461 * const sprite = new THREE.Sprite( material );
22462 * scene.add( sprite );
22463 * ```
22464 *
22465 * @augments Object3D
22466 */
22467class Sprite extends Object3D {
22468
22469	/**
22470	 * Constructs a new sprite.
22471	 *
22472	 * @param {(SpriteMaterial|SpriteNodeMaterial)} [material] - The sprite material.
22473	 */
22474	constructor( material = new SpriteMaterial() ) {
22475
22476		super();
22477
22478		/**
22479		 * This flag can be used for type testing.
22480		 *
22481		 * @type {boolean}
22482		 * @readonly
22483		 * @default true
22484		 */
22485		this.isSprite = true;
22486
22487		this.type = 'Sprite';
22488
22489		if ( _geometry === undefined ) {
22490
22491			_geometry = new BufferGeometry();
22492
22493			const float32Array = new Float32Array( [
22494				-0.5, -0.5, 0, 0, 0,
22495				0.5, -0.5, 0, 1, 0,
22496				0.5, 0.5, 0, 1, 1,
22497				-0.5, 0.5, 0, 0, 1
22498			] );
22499
22500			const interleavedBuffer = new InterleavedBuffer( float32Array, 5 );
22501
22502			_geometry.setIndex( [ 0, 1, 2,	0, 2, 3 ] );
22503			_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );
22504			_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );
22505
22506		}
22507
22508		/**
22509		 * The sprite geometry.
22510		 *
22511		 * @type {BufferGeometry}
22512		 */
22513		this.geometry = _geometry;
22514
22515		/**
22516		 * The sprite material.
22517		 *
22518		 * @type {(SpriteMaterial|SpriteNodeMaterial)}
22519		 */
22520		this.material = material;
22521
22522		/**
22523		 * The sprite's anchor point, and the point around which the sprite rotates.
22524		 * A value of `(0.5, 0.5)` corresponds to the midpoint of the sprite. A value
22525		 * of `(0, 0)` corresponds to the lower left corner of the sprite.
22526		 *
22527		 * @type {Vector2}
22528		 * @default (0.5,0.5)
22529		 */
22530		this.center = new Vector2( 0.5, 0.5 );
22531
22532		/**
22533		 * The number of instances of this sprite.
22534		 * Can only be used with {@link WebGPURenderer}.
22535		 *
22536		 * @type {number}
22537		 * @default 1
22538		 */
22539		this.count = 1;
22540
22541	}
22542
22543	/**
22544	 * Returns `true` if this sprite intersects the given frustum.
22545	 *
22546	 * @param {Frustum|FrustumArray} frustum - The frustum to test.
22547	 * @return {boolean} Whether this sprite intersects the given frustum or not.
22548	 */
22549	intersectsFrustum( frustum ) {
22550
22551		return frustum.intersectsSprite( this );
22552
22553	}
22554
22555	/**
22556	 * Computes intersection points between a casted ray and this sprite.
22557	 *
22558	 * @param {Raycaster} raycaster - The raycaster.
22559	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
22560	 */
22561	raycast( raycaster, intersects ) {
22562
22563		if ( raycaster.camera === null ) {
22564
22565			error( 'Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
22566
22567		}
22568
22569		_worldScale.setFromMatrixScale( this.matrixWorld );
22570
22571		_viewWorldMatrix.copy( raycaster.camera.matrixWorld );
22572		this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );
22573
22574		_mvPosition.setFromMatrixPosition( this.modelViewMatrix );
22575
22576		if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {
22577
22578			_worldScale.multiplyScalar( - _mvPosition.z );
22579
22580		}
22581
22582		const rotation = this.material.rotation;
22583		let sin, cos;
22584
22585		if ( rotation !== 0 ) {
22586
22587			cos = Math.cos( rotation );
22588			sin = Math.sin( rotation );
22589
22590		}
22591
22592		const center = this.center;
22593
22594		transformVertex( _vA$1.set( -0.5, -0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
22595		transformVertex( _vB$1.set( 0.5, -0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
22596		transformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
22597
22598		_uvA.set( 0, 0 );
22599		_uvB.set( 1, 0 );
22600		_uvC.set( 1, 1 );
22601
22602		// check first triangle
22603		let intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );
22604
22605		if ( intersect === null ) {
22606
22607			// check second triangle
22608			transformVertex( _vB$1.set( -0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
22609			_uvB.set( 0, 1 );
22610
22611			intersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );
22612			if ( intersect === null ) {
22613
22614				return;
22615
22616			}
22617
22618		}
22619
22620		const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
22621
22622		if ( distance < raycaster.near || distance > raycaster.far ) return;
22623
22624		intersects.push( {
22625
22626			distance: distance,
22627			point: _intersectPoint.clone(),
22628			uv: Triangle.getInterpolation( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA, _uvB, _uvC, new Vector2() ),
22629			face: null,
22630			object: this
22631
22632		} );
22633
22634	}
22635
22636	copy( source, recursive ) {
22637
22638		super.copy( source, recursive );
22639
22640		if ( source.center !== undefined ) this.center.copy( source.center );
22641
22642		this.material = source.material;
22643
22644		return this;
22645
22646	}
22647
22648}
22649
22650function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
22651
22652	// compute position in camera space
22653	_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
22654
22655	// to check if rotation is not zero
22656	if ( sin !== undefined ) {
22657
22658		_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
22659		_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
22660
22661	} else {
22662
22663		_rotatedPosition.copy( _alignedPosition );
22664
22665	}
22666
22667
22668	vertexPosition.copy( mvPosition );
22669	vertexPosition.x += _rotatedPosition.x;
22670	vertexPosition.y += _rotatedPosition.y;
22671
22672	// transform to world space
22673	vertexPosition.applyMatrix4( _viewWorldMatrix );
22674
22675}
22676
22677const _v1$2 = /*@__PURE__*/ new Vector3();
22678const _v2$1 = /*@__PURE__*/ new Vector3();
22679
22680/**
22681 * A component for providing a basic Level of Detail (LOD) mechanism.
22682 *
22683 * Every LOD level is associated with an object, and rendering can be switched
22684 * between them at the distances specified. Typically you would create, say,
22685 * three meshes, one for far away (low detail), one for mid range (medium
22686 * detail) and one for close up (high detail).
22687 *
22688 * ```js
22689 * const lod = new THREE.LOD();
22690 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
22691 *
22692 * //Create spheres with 3 levels of detail and create new LOD levels for them
22693 * for( let i = 0; i < 3; i++ ) {
22694 *
22695 * 	const geometry = new THREE.IcosahedronGeometry( 10, 3 - i );
22696 * 	const mesh = new THREE.Mesh( geometry, material );
22697 * 	lod.addLevel( mesh, i * 75 );
22698 *
22699 * }
22700 *
22701 * scene.add( lod );
22702 * ```
22703 *
22704 * @augments Object3D
22705 */
22706class LOD extends Object3D {
22707
22708	/**
22709	 * Constructs a new LOD.
22710	 */
22711	constructor() {
22712
22713		super();
22714
22715		/**
22716		 * This flag can be used for type testing.
22717		 *
22718		 * @type {boolean}
22719		 * @readonly
22720		 * @default true
22721		 */
22722		this.isLOD = true;
22723
22724		/**
22725		 * The current LOD index.
22726		 *
22727		 * @private
22728		 * @type {number}
22729		 * @default 0
22730		 */
22731		this._currentLevel = 0;
22732
22733		this.type = 'LOD';
22734
22735		Object.defineProperties( this, {
22736			/**
22737			 * This array holds the LOD levels.
22738			 *
22739			 * @name LOD#levels
22740			 * @type {Array<{object:Object3D,distance:number,hysteresis:number}>}
22741			 */
22742			levels: {
22743				enumerable: true,
22744				value: []
22745			}
22746		} );
22747
22748		/**
22749		 * Whether the LOD object is updated automatically by the renderer per frame
22750		 * or not. If set to `false`, you have to call {@link LOD#update} in the
22751		 * render loop by yourself.
22752		 *
22753		 * @type {boolean}
22754		 * @default true
22755		 */
22756		this.autoUpdate = true;
22757
22758	}
22759
22760	copy( source ) {
22761
22762		super.copy( source, false );
22763
22764		const levels = source.levels;
22765
22766		for ( let i = 0, l = levels.length; i < l; i ++ ) {
22767
22768			const level = levels[ i ];
22769
22770			this.addLevel( level.object.clone(), level.distance, level.hysteresis );
22771
22772		}
22773
22774		this.autoUpdate = source.autoUpdate;
22775
22776		return this;
22777
22778	}
22779
22780	/**
22781	 * Adds a mesh that will display at a certain distance and greater. Typically
22782	 * the further away the distance, the lower the detail on the mesh.
22783	 *
22784	 * @param {Object3D} object - The 3D object to display at this level.
22785	 * @param {number} [distance=0] - The distance at which to display this level of detail.
22786	 * @param {number} [hysteresis=0] - Threshold used to avoid flickering at LOD boundaries, as a fraction of distance.
22787	 * @return {LOD} A reference to this instance.
22788	 */
22789	addLevel( object, distance = 0, hysteresis = 0 ) {
22790
22791		distance = Math.abs( distance );
22792
22793		const levels = this.levels;
22794
22795		let l;
22796
22797		for ( l = 0; l < levels.length; l ++ ) {
22798
22799			if ( distance < levels[ l ].distance ) {
22800
22801				break;
22802
22803			}
22804
22805		}
22806
22807		levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } );
22808
22809		this.add( object );
22810
22811		return this;
22812
22813	}
22814
22815	/**
22816	 * Removes an existing level, based on the distance from the camera.
22817	 * Returns `true` when the level has been removed. Otherwise `false`.
22818	 *
22819	 * @param {number} distance - Distance of the level to remove.
22820	 * @return {boolean} Whether the level has been removed or not.
22821	 */
22822	removeLevel( distance ) {
22823
22824		const levels = this.levels;
22825
22826		for ( let i = 0; i < levels.length; i ++ ) {
22827
22828			if ( levels[ i ].distance === distance ) {
22829
22830				const removedElements = levels.splice( i, 1 );
22831				this.remove( removedElements[ 0 ].object );
22832
22833				return true;
22834
22835			}
22836
22837		}
22838
22839		return false;
22840
22841	}
22842
22843	/**
22844	 * Returns the currently active LOD level index.
22845	 *
22846	 * @return {number} The current active LOD level index.
22847	 */
22848	getCurrentLevel() {
22849
22850		return this._currentLevel;
22851
22852	}
22853
22854	/**
22855	 * Returns a reference to the first 3D object that is greater than
22856	 * the given distance.
22857	 *
22858	 * @param {number} distance - The LOD distance.
22859	 * @return {?Object3D} The found 3D object. `null` if no 3D object has been found.
22860	 */
22861	getObjectForDistance( distance ) {
22862
22863		const levels = this.levels;
22864
22865		if ( levels.length > 0 ) {
22866
22867			let i, l;
22868
22869			for ( i = 1, l = levels.length; i < l; i ++ ) {
22870
22871				let levelDistance = levels[ i ].distance;
22872
22873				if ( levels[ i ].object.visible ) {
22874
22875					levelDistance -= levelDistance * levels[ i ].hysteresis;
22876
22877				}
22878
22879				if ( distance < levelDistance ) {
22880
22881					break;
22882
22883				}
22884
22885			}
22886
22887			return levels[ i - 1 ].object;
22888
22889		}
22890
22891		return null;
22892
22893	}
22894
22895	/**
22896	 * Computes intersection points between a casted ray and this LOD.
22897	 *
22898	 * @param {Raycaster} raycaster - The raycaster.
22899	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
22900	 */
22901	raycast( raycaster, intersects ) {
22902
22903		const levels = this.levels;
22904
22905		if ( levels.length > 0 ) {
22906
22907			_v1$2.setFromMatrixPosition( this.matrixWorld );
22908
22909			const distance = raycaster.ray.origin.distanceTo( _v1$2 );
22910
22911			this.getObjectForDistance( distance ).raycast( raycaster, intersects );
22912
22913		}
22914
22915	}
22916
22917	/**
22918	 * Updates the LOD by computing which LOD level should be visible according
22919	 * to the current distance of the given camera.
22920	 *
22921	 * @param {Camera} camera - The camera the scene is rendered with.
22922	 */
22923	update( camera ) {
22924
22925		const levels = this.levels;
22926
22927		if ( levels.length > 1 ) {
22928
22929			_v1$2.setFromMatrixPosition( camera.matrixWorld );
22930			_v2$1.setFromMatrixPosition( this.matrixWorld );
22931
22932			const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom;
22933
22934			levels[ 0 ].object.visible = true;
22935
22936			let i, l;
22937
22938			for ( i = 1, l = levels.length; i < l; i ++ ) {
22939
22940				let levelDistance = levels[ i ].distance;
22941
22942				if ( levels[ i ].object.visible ) {
22943
22944					levelDistance -= levelDistance * levels[ i ].hysteresis;
22945
22946				}
22947
22948				if ( distance >= levelDistance ) {
22949
22950					levels[ i - 1 ].object.visible = false;
22951					levels[ i ].object.visible = true;
22952
22953				} else {
22954
22955					break;
22956
22957				}
22958
22959			}
22960
22961			this._currentLevel = i - 1;
22962
22963			for ( ; i < l; i ++ ) {
22964
22965				levels[ i ].object.visible = false;
22966
22967			}
22968
22969		}
22970
22971	}
22972
22973	toJSON( meta ) {
22974
22975		const data = super.toJSON( meta );
22976
22977		data.object.autoUpdate = this.autoUpdate;
22978
22979		data.object.levels = [];
22980
22981		const levels = this.levels;
22982
22983		for ( let i = 0, l = levels.length; i < l; i ++ ) {
22984
22985			const level = levels[ i ];
22986
22987			data.object.levels.push( {
22988				object: level.object.uuid,
22989				distance: level.distance,
22990				hysteresis: level.hysteresis
22991			} );
22992
22993		}
22994
22995		return data;
22996
22997	}
22998
22999}
23000
23001const _vector$7 = /*@__PURE__*/ new Vector3();
23002const _segCenter = /*@__PURE__*/ new Vector3();
23003const _segDir = /*@__PURE__*/ new Vector3();
23004const _diff = /*@__PURE__*/ new Vector3();
23005
23006/**
23007 * A ray that emits from an origin in a certain direction. The class is used by
23008 * {@link Raycaster} to assist with raycasting. Raycasting is used for
23009 * mouse picking (working out what objects in the 3D space the mouse is over)
23010 * amongst other things.
23011 */
23012class Ray {
23013
23014	/**
23015	 * Constructs a new ray.
23016	 *
23017	 * @param {Vector3} [origin=(0,0,0)] - The origin of the ray.
23018	 * @param {Vector3} [direction=(0,0,-1)] - The (normalized) direction of the ray.
23019	 */
23020	constructor( origin = new Vector3(), direction = new Vector3( 0, 0, -1 ) ) {
23021
23022		/**
23023		 * The origin of the ray.
23024		 *
23025		 * @type {Vector3}
23026		 */
23027		this.origin = origin;
23028
23029		/**
23030		 * The (normalized) direction of the ray.
23031		 *
23032		 * @type {Vector3}
23033		 */
23034		this.direction = direction;
23035
23036	}
23037
23038	/**
23039	 * Sets the ray's components by copying the given values.
23040	 *
23041	 * @param {Vector3} origin - The origin.
23042	 * @param {Vector3} direction - The direction.
23043	 * @return {Ray} A reference to this ray.
23044	 */
23045	set( origin, direction ) {
23046
23047		this.origin.copy( origin );
23048		this.direction.copy( direction );
23049
23050		return this;
23051
23052	}
23053
23054	/**
23055	 * Copies the values of the given ray to this instance.
23056	 *
23057	 * @param {Ray} ray - The ray to copy.
23058	 * @return {Ray} A reference to this ray.
23059	 */
23060	copy( ray ) {
23061
23062		this.origin.copy( ray.origin );
23063		this.direction.copy( ray.direction );
23064
23065		return this;
23066
23067	}
23068
23069	/**
23070	 * Returns a vector that is located at a given distance along this ray.
23071	 *
23072	 * @param {number} t - The distance along the ray to retrieve a position for.
23073	 * @param {Vector3} target - The target vector that is used to store the method's result.
23074	 * @return {Vector3} A position on the ray.
23075	 */
23076	at( t, target ) {
23077
23078		return target.copy( this.origin ).addScaledVector( this.direction, t );
23079
23080	}
23081
23082	/**
23083	 * Adjusts the direction of the ray to point at the given vector in world space.
23084	 *
23085	 * @param {Vector3} v - The target position.
23086	 * @return {Ray} A reference to this ray.
23087	 */
23088	lookAt( v ) {
23089
23090		this.direction.copy( v ).sub( this.origin ).normalize();
23091
23092		return this;
23093
23094	}
23095
23096	/**
23097	 * Shift the origin of this ray along its direction by the given distance.
23098	 *
23099	 * @param {number} t - The distance along the ray to interpolate.
23100	 * @return {Ray} A reference to this ray.
23101	 */
23102	recast( t ) {
23103
23104		this.origin.copy( this.at( t, _vector$7 ) );
23105
23106		return this;
23107
23108	}
23109
23110	/**
23111	 * Returns the point along this ray that is closest to the given point.
23112	 *
23113	 * @param {Vector3} point - A point in 3D space to get the closet location on the ray for.
23114	 * @param {Vector3} target - The target vector that is used to store the method's result.
23115	 * @return {Vector3} The closest point on this ray.
23116	 */
23117	closestPointToPoint( point, target ) {
23118
23119		target.subVectors( point, this.origin );
23120
23121		const directionDistance = target.dot( this.direction );
23122
23123		if ( directionDistance < 0 ) {
23124
23125			return target.copy( this.origin );
23126
23127		}
23128
23129		return target.copy( this.origin ).addScaledVector( this.direction, directionDistance );
23130
23131	}
23132
23133	/**
23134	 * Returns the distance of the closest approach between this ray and the given point.
23135	 *
23136	 * @param {Vector3} point - A point in 3D space to compute the distance to.
23137	 * @return {number} The distance.
23138	 */
23139	distanceToPoint( point ) {
23140
23141		return Math.sqrt( this.distanceSqToPoint( point ) );
23142
23143	}
23144
23145	/**
23146	 * Returns the squared distance of the closest approach between this ray and the given point.
23147	 *
23148	 * @param {Vector3} point - A point in 3D space to compute the distance to.
23149	 * @return {number} The squared distance.
23150	 */
23151	distanceSqToPoint( point ) {
23152
23153		const directionDistance = _vector$7.subVectors( point, this.origin ).dot( this.direction );
23154
23155		// point behind the ray
23156
23157		if ( directionDistance < 0 ) {
23158
23159			return this.origin.distanceToSquared( point );
23160
23161		}
23162
23163		_vector$7.copy( this.origin ).addScaledVector( this.direction, directionDistance );
23164
23165		return _vector$7.distanceToSquared( point );
23166
23167	}
23168
23169	/**
23170	 * Returns the squared distance between this ray and the given line segment.
23171	 *
23172	 * @param {Vector3} v0 - The start point of the line segment.
23173	 * @param {Vector3} v1 - The end point of the line segment.
23174	 * @param {Vector3} [optionalPointOnRay] - When provided, it receives the point on this ray that is closest to the segment.
23175	 * @param {Vector3} [optionalPointOnSegment] - When provided, it receives the point on the line segment that is closest to this ray.
23176	 * @return {number} The squared distance.
23177	 */
23178	distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {
23179
23180		// from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h
23181		// It returns the min distance between the ray and the segment
23182		// defined by v0 and v1
23183		// It can also set two optional targets :
23184		// - The closest point on the ray
23185		// - The closest point on the segment
23186
23187		_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );
23188		_segDir.copy( v1 ).sub( v0 ).normalize();
23189		_diff.copy( this.origin ).sub( _segCenter );
23190
23191		const segExtent = v0.distanceTo( v1 ) * 0.5;
23192		const a01 = - this.direction.dot( _segDir );
23193		const b0 = _diff.dot( this.direction );
23194		const b1 = - _diff.dot( _segDir );
23195		const c = _diff.lengthSq();
23196		const det = Math.abs( 1 - a01 * a01 );
23197		let s0, s1, sqrDist, extDet;
23198
23199		if ( det > 0 ) {
23200
23201			// The ray and segment are not parallel.
23202
23203			s0 = a01 * b1 - b0;
23204			s1 = a01 * b0 - b1;
23205			extDet = segExtent * det;
23206
23207			if ( s0 >= 0 ) {
23208
23209				if ( s1 >= - extDet ) {
23210
23211					if ( s1 <= extDet ) {
23212
23213						// region 0
23214						// Minimum at interior points of ray and segment.
23215
23216						const invDet = 1 / det;
23217						s0 *= invDet;
23218						s1 *= invDet;
23219						sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;
23220
23221					} else {
23222
23223						// region 1
23224
23225						s1 = segExtent;
23226						s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
23227						sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
23228
23229					}
23230
23231				} else {
23232
23233					// region 5
23234
23235					s1 = - segExtent;
23236					s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
23237					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
23238
23239				}
23240
23241			} else {
23242
23243				if ( s1 <= - extDet ) {
23244
23245					// region 4
23246
23247					s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );
23248					s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
23249					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
23250
23251				} else if ( s1 <= extDet ) {
23252
23253					// region 3
23254
23255					s0 = 0;
23256					s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );
23257					sqrDist = s1 * ( s1 + 2 * b1 ) + c;
23258
23259				} else {
23260
23261					// region 2
23262
23263					s0 = Math.max( 0, - ( a01 * segExtent + b0 ) );
23264					s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );
23265					sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
23266
23267				}
23268
23269			}
23270
23271		} else {
23272
23273			// Ray and segment are parallel.
23274
23275			s1 = ( a01 > 0 ) ? - segExtent : segExtent;
23276			s0 = Math.max( 0, - ( a01 * s1 + b0 ) );
23277			sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;
23278
23279		}
23280
23281		if ( optionalPointOnRay ) {
23282
23283			optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 );
23284
23285		}
23286
23287		if ( optionalPointOnSegment ) {
23288
23289			optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 );
23290
23291		}
23292
23293		return sqrDist;
23294
23295	}
23296
23297	/**
23298	 * Intersects this ray with the given sphere, returning the intersection
23299	 * point or `null` if there is no intersection.
23300	 *
23301	 * @param {Sphere} sphere - The sphere to intersect.
23302	 * @param {Vector3} target - The target vector that is used to store the method's result.
23303	 * @return {?Vector3} The intersection point.
23304	 */
23305	intersectSphere( sphere, target ) {
23306
23307		if ( sphere.radius < 0 ) return null; // handle empty spheres, see #31187
23308
23309		_vector$7.subVectors( sphere.center, this.origin );
23310		const tca = _vector$7.dot( this.direction );
23311		const d2 = _vector$7.dot( _vector$7 ) - tca * tca;
23312		const radius2 = sphere.radius * sphere.radius;
23313
23314		if ( d2 > radius2 ) return null;
23315
23316		const thc = Math.sqrt( radius2 - d2 );
23317
23318		// t0 = first intersect point - entrance on front of sphere
23319		const t0 = tca - thc;
23320
23321		// t1 = second intersect point - exit point on back of sphere
23322		const t1 = tca + thc;
23323
23324		// test to see if t1 is behind the ray - if so, return null
23325		if ( t1 < 0 ) return null;
23326
23327		// test to see if t0 is behind the ray:
23328		// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,
23329		// in order to always return an intersect point that is in front of the ray.
23330		if ( t0 < 0 ) return this.at( t1, target );
23331
23332		// else t0 is in front of the ray, so return the first collision point scaled by t0
23333		return this.at( t0, target );
23334
23335	}
23336
23337	/**
23338	 * Returns `true` if this ray intersects with the given sphere.
23339	 *
23340	 * @param {Sphere} sphere - The sphere to intersect.
23341	 * @return {boolean} Whether this ray intersects with the given sphere or not.
23342	 */
23343	intersectsSphere( sphere ) {
23344
23345		if ( sphere.radius < 0 ) return false; // handle empty spheres, see #31187
23346
23347		return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
23348
23349	}
23350
23351	/**
23352	 * Computes the distance from the ray's origin to the given plane. Returns `null` if the ray
23353	 * does not intersect with the plane.
23354	 *
23355	 * @param {Plane} plane - The plane to compute the distance to.
23356	 * @return {?number} Whether this ray intersects with the given sphere or not.
23357	 */
23358	distanceToPlane( plane ) {
23359
23360		const denominator = plane.normal.dot( this.direction );
23361
23362		if ( denominator === 0 ) {
23363
23364			// line is coplanar, return origin
23365			if ( plane.distanceToPoint( this.origin ) === 0 ) {
23366
23367				return 0;
23368
23369			}
23370
23371			// Null is preferable to undefined since undefined means.... it is undefined
23372
23373			return null;
23374
23375		}
23376
23377		const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
23378
23379		// Return if the ray never intersects the plane
23380
23381		return t >= 0 ? t : null;
23382
23383	}
23384
23385	/**
23386	 * Intersects this ray with the given plane, returning the intersection
23387	 * point or `null` if there is no intersection.
23388	 *
23389	 * @param {Plane} plane - The plane to intersect.
23390	 * @param {Vector3} target - The target vector that is used to store the method's result.
23391	 * @return {?Vector3} The intersection point.
23392	 */
23393	intersectPlane( plane, target ) {
23394
23395		const t = this.distanceToPlane( plane );
23396
23397		if ( t === null ) {
23398
23399			return null;
23400
23401		}
23402
23403		return this.at( t, target );
23404
23405	}
23406
23407	/**
23408	 * Returns `true` if this ray intersects with the given plane.
23409	 *
23410	 * @param {Plane} plane - The plane to intersect.
23411	 * @return {boolean} Whether this ray intersects with the given plane or not.
23412	 */
23413	intersectsPlane( plane ) {
23414
23415		// check if the ray lies on the plane first
23416
23417		const distToPoint = plane.distanceToPoint( this.origin );
23418
23419		if ( distToPoint === 0 ) {
23420
23421			return true;
23422
23423		}
23424
23425		const denominator = plane.normal.dot( this.direction );
23426
23427		if ( denominator * distToPoint < 0 ) {
23428
23429			return true;
23430
23431		}
23432
23433		// ray origin is behind the plane (and is pointing behind it)
23434
23435		return false;
23436
23437	}
23438
23439	/**
23440	 * Intersects this ray with the given bounding box, returning the intersection
23441	 * point or `null` if there is no intersection.
23442	 *
23443	 * @param {Box3} box - The box to intersect.
23444	 * @param {Vector3} target - The target vector that is used to store the method's result.
23445	 * @return {?Vector3} The intersection point.
23446	 */
23447	intersectBox( box, target ) {
23448
23449		let tmin, tmax, tymin, tymax, tzmin, tzmax;
23450
23451		const invdirx = 1 / this.direction.x,
23452			invdiry = 1 / this.direction.y,
23453			invdirz = 1 / this.direction.z;
23454
23455		const origin = this.origin;
23456
23457		if ( invdirx >= 0 ) {
23458
23459			tmin = ( box.min.x - origin.x ) * invdirx;
23460			tmax = ( box.max.x - origin.x ) * invdirx;
23461
23462		} else {
23463
23464			tmin = ( box.max.x - origin.x ) * invdirx;
23465			tmax = ( box.min.x - origin.x ) * invdirx;
23466
23467		}
23468
23469		if ( invdiry >= 0 ) {
23470
23471			tymin = ( box.min.y - origin.y ) * invdiry;
23472			tymax = ( box.max.y - origin.y ) * invdiry;
23473
23474		} else {
23475
23476			tymin = ( box.max.y - origin.y ) * invdiry;
23477			tymax = ( box.min.y - origin.y ) * invdiry;
23478
23479		}
23480
23481		if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;
23482
23483		if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin;
23484
23485		if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax;
23486
23487		if ( invdirz >= 0 ) {
23488
23489			tzmin = ( box.min.z - origin.z ) * invdirz;
23490			tzmax = ( box.max.z - origin.z ) * invdirz;
23491
23492		} else {
23493
23494			tzmin = ( box.max.z - origin.z ) * invdirz;
23495			tzmax = ( box.min.z - origin.z ) * invdirz;
23496
23497		}
23498
23499		if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;
23500
23501		if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
23502
23503		if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
23504
23505		//return point closest to the ray (positive side)
23506
23507		if ( tmax < 0 ) return null;
23508
23509		return this.at( tmin >= 0 ? tmin : tmax, target );
23510
23511	}
23512
23513	/**
23514	 * Returns `true` if this ray intersects with the given box.
23515	 *
23516	 * @param {Box3} box - The box to intersect.
23517	 * @return {boolean} Whether this ray intersects with the given box or not.
23518	 */
23519	intersectsBox( box ) {
23520
23521		return this.intersectBox( box, _vector$7 ) !== null;
23522
23523	}
23524
23525	/**
23526	 * Intersects this ray with the given triangle, returning the intersection
23527	 * point or `null` if there is no intersection.
23528	 *
23529	 * @param {Vector3} a - The first vertex of the triangle.
23530	 * @param {Vector3} b - The second vertex of the triangle.
23531	 * @param {Vector3} c - The third vertex of the triangle.
23532	 * @param {boolean} backfaceCulling - Whether to use backface culling or not.
23533	 * @param {Vector3} target - The target vector that is used to store the method's result.
23534	 * @return {?Vector3} The intersection point.
23535	 */
23536	intersectTriangle( a, b, c, backfaceCulling, target ) {
23537
23538		// Watertight ray/triangle intersection. Reference: Woop, Benthin, Wald,
23539		// "Watertight Ray/Triangle Intersection", JCGT vol. 2 no. 1 (2013), Appendix A.
23540		// https://jcgt.org/published/0002/01/05/
23541
23542		const origin = this.origin;
23543		const direction = this.direction;
23544
23545		const dx = direction.x;
23546		const dy = direction.y;
23547		const dz = direction.z;
23548
23549		// triangle vertices relative to the ray origin
23550
23551		const aox = a.x - origin.x, aoy = a.y - origin.y, aoz = a.z - origin.z;
23552		const box = b.x - origin.x, boy = b.y - origin.y, boz = b.z - origin.z;
23553		const cox = c.x - origin.x, coy = c.y - origin.y, coz = c.z - origin.z;
23554
23555		// Use the dimension where the ray direction is maximal as the projection
23556		// axis (kz) and read every component already permuted into (kx, ky, kz).
23557		// kx and ky are swapped when the direction's kz component is negative, to
23558		// preserve the winding order of triangles.
23559
23560		const adx = Math.abs( dx ), ady = Math.abs( dy ), adz = Math.abs( dz );
23561
23562		let dkx, dky, dkz;
23563		let akx, aky, akz, bkx, bky, bkz, ckx, cky, ckz;
23564
23565		if ( adx >= ady && adx >= adz ) {
23566
23567			dkz = dx; akz = aox; bkz = box; ckz = cox;
23568
23569			if ( dx >= 0 ) {
23570
23571				dkx = dy; dky = dz;
23572				akx = aoy; aky = aoz; bkx = boy; bky = boz; ckx = coy; cky = coz;
23573
23574			} else {
23575
23576				dkx = dz; dky = dy;
23577				akx = aoz; aky = aoy; bkx = boz; bky = boy; ckx = coz; cky = coy;
23578
23579			}
23580
23581		} else if ( ady >= adz ) {
23582
23583			dkz = dy; akz = aoy; bkz = boy; ckz = coy;
23584
23585			if ( dy >= 0 ) {
23586
23587				dkx = dz; dky = dx;
23588				akx = aoz; aky = aox; bkx = boz; bky = box; ckx = coz; cky = cox;
23589
23590			} else {
23591
23592				dkx = dx; dky = dz;
23593				akx = aox; aky = aoz; bkx = box; bky = boz; ckx = cox; cky = coz;
23594
23595			}
23596
23597		} else {
23598
23599			dkz = dz; akz = aoz; bkz = boz; ckz = coz;
23600
23601			if ( dz >= 0 ) {
23602
23603				dkx = dx; dky = dy;
23604				akx = aox; aky = aoy; bkx = box; bky = boy; ckx = cox; cky = coy;
23605
23606			} else {
23607
23608				dkx = dy; dky = dx;
23609				akx = aoy; aky = aox; bkx = boy; bky = box; ckx = coy; cky = cox;
23610
23611			}
23612
23613		}
23614
23615		// a zero direction has no maximal axis and cannot intersect
23616
23617		if ( dkz === 0 ) return null;
23618
23619		// shear constants that align the ray with the +kz axis
23620
23621		const sx = dkx / dkz, sy = dky / dkz, sz = 1 / dkz;
23622
23623		// sheared and scaled vertices
23624
23625		const ax = akx - sx * akz, ay = aky - sy * akz;
23626		const bx = bkx - sx * bkz, by = bky - sy * bkz;
23627		const cx = ckx - sx * ckz, cy = cky - sy * ckz;
23628
23629		// scaled barycentric coordinates (signed edge functions); the shear makes a
23630		// shared edge evaluate identically for both adjacent triangles, so the ray
23631		// can never fall between them
23632
23633		const u = cx * by - cy * bx;
23634		const v = ax * cy - ay * cx;
23635		const w = bx * ay - by * ax;
23636
23637		if ( backfaceCulling ) {
23638
23639			if ( u < 0 || v < 0 || w < 0 ) return null;
23640
23641		} else {
23642
23643			if ( ( u < 0 || v < 0 || w < 0 ) && ( u > 0 || v > 0 || w > 0 ) ) return null;
23644
23645		}
23646
23647		const det = u + v + w;
23648
23649		// ray is co-planar with the triangle
23650
23651		if ( det === 0 ) return null;
23652
23653		// scaled hit distance; t = tScaled / det must lie in front of the origin
23654
23655		const tScaled = sz * ( u * akz + v * bkz + w * ckz );
23656
23657		if ( det > 0 ? tScaled < 0 : tScaled > 0 ) return null;
23658
23659		return this.at( tScaled / det, target );
23660
23661	}
23662
23663	/**
23664	 * Transforms this ray with the given 4x4 transformation matrix.
23665	 *
23666	 * @param {Matrix4} matrix4 - The transformation matrix.
23667	 * @return {Ray} A reference to this ray.
23668	 */
23669	applyMatrix4( matrix4 ) {
23670
23671		this.origin.applyMatrix4( matrix4 );
23672		this.direction.transformDirection( matrix4 );
23673
23674		return this;
23675
23676	}
23677
23678	/**
23679	 * Returns `true` if this ray is equal with the given one.
23680	 *
23681	 * @param {Ray} ray - The ray to test for equality.
23682	 * @return {boolean} Whether this ray is equal with the given one.
23683	 */
23684	equals( ray ) {
23685
23686		return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
23687
23688	}
23689
23690	/**
23691	 * Returns a new ray with copied values from this instance.
23692	 *
23693	 * @return {Ray} A clone of this instance.
23694	 */
23695	clone() {
23696
23697		return new this.constructor().copy( this );
23698
23699	}
23700
23701}
23702
23703/**
23704 * A material for drawing geometries in a simple shaded (flat or wireframe) way.
23705 *
23706 * This material is not affected by lights.
23707 *
23708 * @augments Material
23709 * @demo scenes/material-browser.html#MeshBasicMaterial
23710 */
23711class MeshBasicMaterial extends Material {
23712
23713	/**
23714	 * Constructs a new mesh basic material.
23715	 *
23716	 * @param {Object} [parameters] - An object with one or more properties
23717	 * defining the material's appearance. Any property of the material
23718	 * (including any property from inherited materials) can be passed
23719	 * in here. Color values can be passed any type of value accepted
23720	 * by {@link Color#set}.
23721	 */
23722	constructor( parameters ) {
23723
23724		super();
23725
23726		/**
23727		 * This flag can be used for type testing.
23728		 *
23729		 * @type {boolean}
23730		 * @readonly
23731		 * @default true
23732		 */
23733		this.isMeshBasicMaterial = true;
23734
23735		this.type = 'MeshBasicMaterial';
23736
23737		/**
23738		 * Color of the material.
23739		 *
23740		 * @type {Color}
23741		 * @default (1,1,1)
23742		 */
23743		this.color = new Color( 0xffffff ); // diffuse
23744
23745		/**
23746		 * The color map. May optionally include an alpha channel, typically combined
23747		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
23748		 * color is modulated by the diffuse `color`.
23749		 *
23750		 * `map` represents color data, and the texture must be assigned a
23751		 * {@link Texture#colorSpace}. Most `map` textures set
23752		 * `texture.colorSpace = SRGBColorSpace`.
23753		 *
23754		 * @type {?Texture}
23755		 * @default null
23756		 */
23757		this.map = null;
23758
23759		/**
23760		 * The light map. Requires a second set of UVs.
23761		 *
23762		 * `lightMap` represents pre-baked illuminance data, and the texture must be assigned
23763		 * a {@link Texture#colorSpace}. Most `lightMap` textures set
23764		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
23765		 * such as `.exr` or `.hdr`.
23766		 *
23767		 * @type {?Texture}
23768		 * @default null
23769		 */
23770		this.lightMap = null;
23771
23772		/**
23773		 * Intensity of the baked light.
23774		 *
23775		 * @type {number}
23776		 * @default 1
23777		 */
23778		this.lightMapIntensity = 1.0;
23779
23780		/**
23781		 * The red channel of this texture is used as the ambient occlusion map.
23782		 * Requires a second set of UVs.
23783		 *
23784		 * `aoMap` represents non-color data. Any texture assigned must have
23785		 * `texture.colorSpace = NoColorSpace` (default).
23786		 *
23787		 * @type {?Texture}
23788		 * @default null
23789		 */
23790		this.aoMap = null;
23791
23792		/**
23793		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
23794		 * disables ambient occlusion. Where intensity is `1` and the AO map's
23795		 * red channel is also `1`, ambient light is fully occluded on a surface.
23796		 *
23797		 * @type {number}
23798		 * @default 1
23799		 */
23800		this.aoMapIntensity = 1.0;
23801
23802		/**
23803		 * Specular map used by the material.
23804		 *
23805		 * `specularMap` represents color data, and the texture must be assigned a
23806		 * {@link Texture#colorSpace}. Most `specularMap` textures set
23807		 * `texture.colorSpace = SRGBColorSpace`.
23808		 *
23809		 * @type {?Texture}
23810		 * @default null
23811		 */
23812		this.specularMap = null;
23813
23814		/**
23815		 * The alpha map is a grayscale texture that controls the opacity across the
23816		 * surface (black: fully transparent; white: fully opaque).
23817		 *
23818		 * Only the color of the texture is used, ignoring the alpha channel if one
23819		 * exists. For RGB and RGBA textures, the renderer will use the green channel
23820		 * when sampling this texture due to the extra bit of precision provided for
23821		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
23822		 * luminance/alpha textures will also still work as expected.
23823		 *
23824		 * `alphaMap` represents non-color data. Any texture assigned must have
23825		 * `texture.colorSpace = NoColorSpace` (default).
23826		 *
23827		 * @type {?Texture}
23828		 * @default null
23829		 */
23830		this.alphaMap = null;
23831
23832		/**
23833		 * The environment map.
23834		 *
23835		 * `envMap` represents luminance data, and the texture must be assigned
23836		 * a {@link Texture#colorSpace}. Most `envMap` textures set
23837		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
23838		 * such as `.exr` or `.hdr`.
23839		 *
23840		 * @type {?Texture}
23841		 * @default null
23842		 */
23843		this.envMap = null;
23844
23845		/**
23846		 * The rotation of the environment map in radians.
23847		 *
23848		 * @type {Euler}
23849		 * @default (0,0,0)
23850		 */
23851		this.envMapRotation = new Euler();
23852
23853		/**
23854		 * How to combine the result of the surface's color with the environment map, if any.
23855		 *
23856		 * When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
23857		 * blend between the two colors.
23858		 *
23859		 * @type {(MultiplyOperation|MixOperation|AddOperation)}
23860		 * @default MultiplyOperation
23861		 */
23862		this.combine = MultiplyOperation;
23863
23864		/**
23865		 * How much the environment map affects the surface.
23866		 * The valid range is between `0` (no reflections) and `1` (full reflections).
23867		 *
23868		 * @type {number}
23869		 * @default 1
23870		 */
23871		this.reflectivity = 1;
23872
23873		/**
23874		 * The index of refraction (IOR) of air (approximately 1) divided by the
23875		 * index of refraction of the material. It is used with environment mapping
23876		 * modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
23877		 * The refraction ratio should not exceed `1`.
23878		 *
23879		 * @type {number}
23880		 * @default 0.98
23881		 */
23882		this.refractionRatio = 0.98;
23883
23884		/**
23885		 * Renders the geometry as a wireframe.
23886		 *
23887		 * @type {boolean}
23888		 * @default false
23889		 */
23890		this.wireframe = false;
23891
23892		/**
23893		 * Controls the thickness of the wireframe.
23894		 *
23895		 * Can only be used with {@link SVGRenderer}.
23896		 *
23897		 * @type {number}
23898		 * @default 1
23899		 */
23900		this.wireframeLinewidth = 1;
23901
23902		/**
23903		 * Defines appearance of wireframe ends.
23904		 *
23905		 * Can only be used with {@link SVGRenderer}.
23906		 *
23907		 * @type {('round'|'bevel'|'miter')}
23908		 * @default 'round'
23909		 */
23910		this.wireframeLinecap = 'round';
23911
23912		/**
23913		 * Defines appearance of wireframe joints.
23914		 *
23915		 * Can only be used with {@link SVGRenderer}.
23916		 *
23917		 * @type {('round'|'bevel'|'miter')}
23918		 * @default 'round'
23919		 */
23920		this.wireframeLinejoin = 'round';
23921
23922		/**
23923		 * Whether the material is affected by fog or not.
23924		 *
23925		 * @type {boolean}
23926		 * @default true
23927		 */
23928		this.fog = true;
23929
23930		this.setValues( parameters );
23931
23932	}
23933
23934	copy( source ) {
23935
23936		super.copy( source );
23937
23938		this.color.copy( source.color );
23939
23940		this.map = source.map;
23941
23942		this.lightMap = source.lightMap;
23943		this.lightMapIntensity = source.lightMapIntensity;
23944
23945		this.aoMap = source.aoMap;
23946		this.aoMapIntensity = source.aoMapIntensity;
23947
23948		this.specularMap = source.specularMap;
23949
23950		this.alphaMap = source.alphaMap;
23951
23952		this.envMap = source.envMap;
23953		this.envMapRotation.copy( source.envMapRotation );
23954		this.combine = source.combine;
23955		this.reflectivity = source.reflectivity;
23956		this.refractionRatio = source.refractionRatio;
23957
23958		this.wireframe = source.wireframe;
23959		this.wireframeLinewidth = source.wireframeLinewidth;
23960		this.wireframeLinecap = source.wireframeLinecap;
23961		this.wireframeLinejoin = source.wireframeLinejoin;
23962
23963		this.fog = source.fog;
23964
23965		return this;
23966
23967	}
23968
23969}
23970
23971const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4();
23972const _ray$3 = /*@__PURE__*/ new Ray();
23973const _sphere$6 = /*@__PURE__*/ new Sphere();
23974const _sphereHitAt = /*@__PURE__*/ new Vector3();
23975
23976const _vA = /*@__PURE__*/ new Vector3();
23977const _vB = /*@__PURE__*/ new Vector3();
23978const _vC = /*@__PURE__*/ new Vector3();
23979
23980const _tempA = /*@__PURE__*/ new Vector3();
23981const _morphA = /*@__PURE__*/ new Vector3();
23982
23983const _intersectionPoint = /*@__PURE__*/ new Vector3();
23984const _intersectionPointWorld = /*@__PURE__*/ new Vector3();
23985
23986/**
23987 * Class representing triangular polygon mesh based objects.
23988 *
23989 * ```js
23990 * const geometry = new THREE.BoxGeometry( 1, 1, 1 );
23991 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
23992 * const mesh = new THREE.Mesh( geometry, material );
23993 * scene.add( mesh );
23994 * ```
23995 *
23996 * @augments Object3D
23997 */
23998class Mesh extends Object3D {
23999
24000	/**
24001	 * Constructs a new mesh.
24002	 *
24003	 * @param {BufferGeometry} [geometry] - The mesh geometry.
24004	 * @param {Material|Array<Material>} [material] - The mesh material.
24005	 */
24006	constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) {
24007
24008		super();
24009
24010		/**
24011		 * This flag can be used for type testing.
24012		 *
24013		 * @type {boolean}
24014		 * @readonly
24015		 * @default true
24016		 */
24017		this.isMesh = true;
24018
24019		this.type = 'Mesh';
24020
24021		/**
24022		 * The mesh geometry.
24023		 *
24024		 * @type {BufferGeometry}
24025		 */
24026		this.geometry = geometry;
24027
24028		/**
24029		 * The mesh material.
24030		 *
24031		 * @type {Material|Array<Material>}
24032		 * @default MeshBasicMaterial
24033		 */
24034		this.material = material;
24035
24036		/**
24037		 * A dictionary representing the morph targets in the geometry. The key is the
24038		 * morph targets name, the value its attribute index. This member is `undefined`
24039		 * by default and only set when morph targets are detected in the geometry.
24040		 *
24041		 * @type {Object<string,number>|undefined}
24042		 * @default undefined
24043		 */
24044		this.morphTargetDictionary = undefined;
24045
24046		/**
24047		 * An array of weights typically in the range `[0,1]` that specify how much of the morph
24048		 * is applied. This member is `undefined` by default and only set when morph targets are
24049		 * detected in the geometry.
24050		 *
24051		 * @type {Array<number>|undefined}
24052		 * @default undefined
24053		 */
24054		this.morphTargetInfluences = undefined;
24055
24056		/**
24057		 * The number of instances of this mesh.
24058		 * Can only be used with {@link WebGPURenderer}.
24059		 *
24060		 * @type {number}
24061		 * @default 1
24062		 */
24063		this.count = 1;
24064
24065		this.updateMorphTargets();
24066
24067	}
24068
24069	copy( source, recursive ) {
24070
24071		super.copy( source, recursive );
24072
24073		if ( source.morphTargetInfluences !== undefined ) {
24074
24075			this.morphTargetInfluences = source.morphTargetInfluences.slice();
24076
24077		}
24078
24079		if ( source.morphTargetDictionary !== undefined ) {
24080
24081			this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
24082
24083		}
24084
24085		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
24086		this.geometry = source.geometry;
24087
24088		return this;
24089
24090	}
24091
24092	/**
24093	 * Sets the values of {@link Mesh#morphTargetDictionary} and {@link Mesh#morphTargetInfluences}
24094	 * to make sure existing morph targets can influence this 3D object.
24095	 */
24096	updateMorphTargets() {
24097
24098		const geometry = this.geometry;
24099
24100		const morphAttributes = geometry.morphAttributes;
24101		const keys = Object.keys( morphAttributes );
24102
24103		if ( keys.length > 0 ) {
24104
24105			const morphAttribute = morphAttributes[ keys[ 0 ] ];
24106
24107			if ( morphAttribute !== undefined ) {
24108
24109				this.morphTargetInfluences = [];
24110				this.morphTargetDictionary = {};
24111
24112				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
24113
24114					const name = morphAttribute[ m ].name || String( m );
24115
24116					this.morphTargetInfluences.push( 0 );
24117					this.morphTargetDictionary[ name ] = m;
24118
24119				}
24120
24121			}
24122
24123		}
24124
24125	}
24126
24127	/**
24128	 * Returns the local-space position of the vertex at the given index, taking into
24129	 * account the current animation state of both morph targets and skinning.
24130	 *
24131	 * @param {number} index - The vertex index.
24132	 * @param {Vector3} target - The target object that is used to store the method's result.
24133	 * @return {Vector3} The vertex position in local space.
24134	 */
24135	getVertexPosition( index, target ) {
24136
24137		const geometry = this.geometry;
24138		const position = geometry.attributes.position;
24139		const morphPosition = geometry.morphAttributes.position;
24140		const morphTargetsRelative = geometry.morphTargetsRelative;
24141
24142		target.fromBufferAttribute( position, index );
24143
24144		const morphInfluences = this.morphTargetInfluences;
24145
24146		if ( morphPosition && morphInfluences ) {
24147
24148			_morphA.set( 0, 0, 0 );
24149
24150			for ( let i = 0, il = morphPosition.length; i < il; i ++ ) {
24151
24152				const influence = morphInfluences[ i ];
24153				const morphAttribute = morphPosition[ i ];
24154
24155				if ( influence === 0 ) continue;
24156
24157				_tempA.fromBufferAttribute( morphAttribute, index );
24158
24159				if ( morphTargetsRelative ) {
24160
24161					_morphA.addScaledVector( _tempA, influence );
24162
24163				} else {
24164
24165					_morphA.addScaledVector( _tempA.sub( target ), influence );
24166
24167				}
24168
24169			}
24170
24171			target.add( _morphA );
24172
24173		}
24174
24175		return target;
24176
24177	}
24178
24179	/**
24180	 * Returns `true` if this mesh intersects the given frustum.
24181	 *
24182	 * @param {Frustum|FrustumArray} frustum - The frustum to test.
24183	 * @return {boolean} Whether this mesh intersects the given frustum or not.
24184	 */
24185	intersectsFrustum( frustum ) {
24186
24187		return frustum.intersectsObject( this );
24188
24189	}
24190
24191	/**
24192	 * Computes intersection points between a casted ray and this line.
24193	 *
24194	 * @param {Raycaster} raycaster - The raycaster.
24195	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
24196	 */
24197	raycast( raycaster, intersects ) {
24198
24199		const geometry = this.geometry;
24200		const material = this.material;
24201		const matrixWorld = this.matrixWorld;
24202
24203		if ( material === undefined ) return;
24204
24205		// test with bounding sphere in world space
24206
24207		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
24208
24209		_sphere$6.copy( geometry.boundingSphere );
24210		_sphere$6.applyMatrix4( matrixWorld );
24211
24212		// check distance from ray origin to bounding sphere
24213
24214		_ray$3.copy( raycaster.ray ).recast( raycaster.near );
24215
24216		if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) {
24217
24218			if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return;
24219
24220			if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return;
24221
24222		}
24223
24224		// convert ray to local space of mesh
24225
24226		_inverseMatrix$3.copy( matrixWorld ).invert();
24227		_ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 );
24228
24229		// test with bounding box in local space
24230
24231		if ( geometry.boundingBox !== null ) {
24232
24233			if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return;
24234
24235		}
24236
24237		// test for intersections with geometry
24238
24239		this._computeIntersections( raycaster, intersects, _ray$3 );
24240
24241	}
24242
24243	_computeIntersections( raycaster, intersects, rayLocalSpace ) {
24244
24245		let intersection;
24246
24247		const geometry = this.geometry;
24248		const material = this.material;
24249
24250		const index = geometry.index;
24251		const position = geometry.attributes.position;
24252		const uv = geometry.attributes.uv;
24253		const uv1 = geometry.attributes.uv1;
24254		const normal = geometry.attributes.normal;
24255		const groups = geometry.groups;
24256		const drawRange = geometry.drawRange;
24257
24258		if ( index !== null ) {
24259
24260			// indexed buffer geometry
24261
24262			if ( Array.isArray( material ) ) {
24263
24264				for ( let i = 0, il = groups.length; i < il; i ++ ) {
24265
24266					const group = groups[ i ];
24267					const groupMaterial = material[ group.materialIndex ];
24268
24269					const start = Math.max( group.start, drawRange.start );
24270					const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
24271
24272					for ( let j = start, jl = end; j < jl; j += 3 ) {
24273
24274						const a = index.getX( j );
24275						const b = index.getX( j + 1 );
24276						const c = index.getX( j + 2 );
24277
24278						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
24279
24280						if ( intersection ) {
24281
24282							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics
24283							intersection.face.materialIndex = group.materialIndex;
24284							intersects.push( intersection );
24285
24286						}
24287
24288					}
24289
24290				}
24291
24292			} else {
24293
24294				const start = Math.max( 0, drawRange.start );
24295				const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
24296
24297				for ( let i = start, il = end; i < il; i += 3 ) {
24298
24299					const a = index.getX( i );
24300					const b = index.getX( i + 1 );
24301					const c = index.getX( i + 2 );
24302
24303					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
24304
24305					if ( intersection ) {
24306
24307						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics
24308						intersects.push( intersection );
24309
24310					}
24311
24312				}
24313
24314			}
24315
24316		} else if ( position !== undefined ) {
24317
24318			// non-indexed buffer geometry
24319
24320			if ( Array.isArray( material ) ) {
24321
24322				for ( let i = 0, il = groups.length; i < il; i ++ ) {
24323
24324					const group = groups[ i ];
24325					const groupMaterial = material[ group.materialIndex ];
24326
24327					const start = Math.max( group.start, drawRange.start );
24328					const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
24329
24330					for ( let j = start, jl = end; j < jl; j += 3 ) {
24331
24332						const a = j;
24333						const b = j + 1;
24334						const c = j + 2;
24335
24336						intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
24337
24338						if ( intersection ) {
24339
24340							intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics
24341							intersection.face.materialIndex = group.materialIndex;
24342							intersects.push( intersection );
24343
24344						}
24345
24346					}
24347
24348				}
24349
24350			} else {
24351
24352				const start = Math.max( 0, drawRange.start );
24353				const end = Math.min( position.count, ( drawRange.start + drawRange.count ) );
24354
24355				for ( let i = start, il = end; i < il; i += 3 ) {
24356
24357					const a = i;
24358					const b = i + 1;
24359					const c = i + 2;
24360
24361					intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c );
24362
24363					if ( intersection ) {
24364
24365						intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics
24366						intersects.push( intersection );
24367
24368					}
24369
24370				}
24371
24372			}
24373
24374		}
24375
24376	}
24377
24378}
24379
24380function checkIntersection$1( object, material, raycaster, ray, pA, pB, pC, point ) {
24381
24382	let intersect;
24383
24384	if ( material.side === BackSide ) {
24385
24386		intersect = ray.intersectTriangle( pC, pB, pA, true, point );
24387
24388	} else {
24389
24390		intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point );
24391
24392	}
24393
24394	if ( intersect === null ) return null;
24395
24396	_intersectionPointWorld.copy( point );
24397	_intersectionPointWorld.applyMatrix4( object.matrixWorld );
24398
24399	const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
24400
24401	if ( distance < raycaster.near || distance > raycaster.far ) return null;
24402
24403	return {
24404		distance: distance,
24405		point: _intersectionPointWorld.clone(),
24406		object: object
24407	};
24408
24409}
24410
24411function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) {
24412
24413	object.getVertexPosition( a, _vA );
24414	object.getVertexPosition( b, _vB );
24415	object.getVertexPosition( c, _vC );
24416
24417	const intersection = checkIntersection$1( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );
24418
24419	if ( intersection ) {
24420
24421		const barycoord = new Vector3();
24422		Triangle.getBarycoord( _intersectionPoint, _vA, _vB, _vC, barycoord );
24423
24424		if ( uv ) {
24425
24426			intersection.uv = Triangle.getInterpolatedAttribute( uv, a, b, c, barycoord, new Vector2() );
24427
24428		}
24429
24430		if ( uv1 ) {
24431
24432			intersection.uv1 = Triangle.getInterpolatedAttribute( uv1, a, b, c, barycoord, new Vector2() );
24433
24434		}
24435
24436		if ( normal ) {
24437
24438			intersection.normal = Triangle.getInterpolatedAttribute( normal, a, b, c, barycoord, new Vector3() );
24439
24440			if ( intersection.normal.dot( ray.direction ) > 0 ) {
24441
24442				intersection.normal.multiplyScalar( -1 );
24443
24444			}
24445
24446		}
24447
24448		const face = {
24449			a: a,
24450			b: b,
24451			c: c,
24452			normal: new Vector3(),
24453			materialIndex: 0
24454		};
24455
24456		Triangle.getNormal( _vA, _vB, _vC, face.normal );
24457
24458		intersection.face = face;
24459		intersection.barycoord = barycoord;
24460
24461	}
24462
24463	return intersection;
24464
24465}
24466
24467const _baseVector = /*@__PURE__*/ new Vector4();
24468
24469const _skinIndex = /*@__PURE__*/ new Vector4();
24470const _skinWeight = /*@__PURE__*/ new Vector4();
24471
24472const _vector4 = /*@__PURE__*/ new Vector4();
24473const _matrix4 = /*@__PURE__*/ new Matrix4();
24474const _vertex = /*@__PURE__*/ new Vector3();
24475
24476const _sphere$5 = /*@__PURE__*/ new Sphere();
24477const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4();
24478const _ray$2 = /*@__PURE__*/ new Ray();
24479
24480/**
24481 * A mesh that has a {@link Skeleton} that can then be used to animate the
24482 * vertices of the geometry with skinning/skeleton animation.
24483 *
24484 * Next to a valid skeleton, the skinned mesh requires skin indices and weights
24485 * as buffer attributes in its geometry. These attribute define which bones affect a single
24486 * vertex to a certain extend.
24487 *
24488 * Typically skinned meshes are not created manually but loaders like {@link GLTFLoader}
24489 * or {@link FBXLoader } import respective models.
24490 *
24491 * @augments Mesh
24492 * @demo scenes/bones-browser.html
24493 */
24494class SkinnedMesh extends Mesh {
24495
24496	/**
24497	 * Constructs a new skinned mesh.
24498	 *
24499	 * @param {BufferGeometry} [geometry] - The mesh geometry.
24500	 * @param {Material|Array<Material>} [material] - The mesh material.
24501	 */
24502	constructor( geometry, material ) {
24503
24504		super( geometry, material );
24505
24506		/**
24507		 * This flag can be used for type testing.
24508		 *
24509		 * @type {boolean}
24510		 * @readonly
24511		 * @default true
24512		 */
24513		this.isSkinnedMesh = true;
24514
24515		this.type = 'SkinnedMesh';
24516
24517		/**
24518		 * `AttachedBindMode` means the skinned mesh shares the same world space as the skeleton.
24519		 * This is not true when using `DetachedBindMode` which is useful when sharing a skeleton
24520		 * across multiple skinned meshes.
24521		 *
24522		 * @type {(AttachedBindMode|DetachedBindMode)}
24523		 * @default AttachedBindMode
24524		 */
24525		this.bindMode = AttachedBindMode;
24526
24527		/**
24528		 * The base matrix that is used for the bound bone transforms.
24529		 *
24530		 * @type {Matrix4}
24531		 */
24532		this.bindMatrix = new Matrix4();
24533
24534		/**
24535		 * The base matrix that is used for resetting the bound bone transforms.
24536		 *
24537		 * @type {Matrix4}
24538		 */
24539		this.bindMatrixInverse = new Matrix4();
24540
24541		/**
24542		 * The bounding box of the skinned mesh. Can be computed via {@link SkinnedMesh#computeBoundingBox}.
24543		 *
24544		 * @type {?Box3}
24545		 * @default null
24546		 */
24547		this.boundingBox = null;
24548
24549		/**
24550		 * The bounding sphere of the skinned mesh. Can be computed via {@link SkinnedMesh#computeBoundingSphere}.
24551		 *
24552		 * @type {?Sphere}
24553		 * @default null
24554		 */
24555		this.boundingSphere = null;
24556
24557	}
24558
24559	/**
24560	 * Computes the bounding box of the skinned mesh, and updates {@link SkinnedMesh#boundingBox}.
24561	 * The bounding box is not automatically computed by the engine; this method must be called by your app.
24562	 * If the skinned mesh is animated, the bounding box should be recomputed per frame in order to reflect
24563	 * the current animation state.
24564	 */
24565	computeBoundingBox() {
24566
24567		const geometry = this.geometry;
24568
24569		if ( this.boundingBox === null ) {
24570
24571			this.boundingBox = new Box3();
24572
24573		}
24574
24575		this.boundingBox.makeEmpty();
24576
24577		const positionAttribute = geometry.getAttribute( 'position' );
24578
24579		for ( let i = 0; i < positionAttribute.count; i ++ ) {
24580
24581			this.getVertexPosition( i, _vertex );
24582			this.boundingBox.expandByPoint( _vertex );
24583
24584		}
24585
24586	}
24587
24588	/**
24589	 * Computes the bounding sphere of the skinned mesh, and updates {@link SkinnedMesh#boundingSphere}.
24590	 * The bounding sphere is automatically computed by the engine once when it is needed, e.g., for ray casting
24591	 * and view frustum culling. If the skinned mesh is animated, the bounding sphere should be recomputed
24592	 * per frame in order to reflect the current animation state.
24593	 */
24594	computeBoundingSphere() {
24595
24596		const geometry = this.geometry;
24597
24598		if ( this.boundingSphere === null ) {
24599
24600			this.boundingSphere = new Sphere();
24601
24602		}
24603
24604		this.boundingSphere.makeEmpty();
24605
24606		const positionAttribute = geometry.getAttribute( 'position' );
24607
24608		for ( let i = 0; i < positionAttribute.count; i ++ ) {
24609
24610			this.getVertexPosition( i, _vertex );
24611			this.boundingSphere.expandByPoint( _vertex );
24612
24613		}
24614
24615	}
24616
24617	copy( source, recursive ) {
24618
24619		super.copy( source, recursive );
24620
24621		this.bindMode = source.bindMode;
24622		this.bindMatrix.copy( source.bindMatrix );
24623		this.bindMatrixInverse.copy( source.bindMatrixInverse );
24624
24625		this.skeleton = source.skeleton;
24626
24627		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
24628		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
24629
24630		return this;
24631
24632	}
24633
24634	raycast( raycaster, intersects ) {
24635
24636		const material = this.material;
24637		const matrixWorld = this.matrixWorld;
24638
24639		if ( material === undefined ) return;
24640
24641		// test with bounding sphere in world space
24642
24643		if ( this.boundingSphere === null ) this.computeBoundingSphere();
24644
24645		_sphere$5.copy( this.boundingSphere );
24646		_sphere$5.applyMatrix4( matrixWorld );
24647
24648		if ( raycaster.ray.intersectsSphere( _sphere$5 ) === false ) return;
24649
24650		// convert ray to local space of skinned mesh
24651
24652		_inverseMatrix$2.copy( matrixWorld ).invert();
24653		_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
24654
24655		// test with bounding box in local space
24656
24657		if ( this.boundingBox !== null ) {
24658
24659			if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return;
24660
24661		}
24662
24663		// test for intersections with geometry
24664
24665		this._computeIntersections( raycaster, intersects, _ray$2 );
24666
24667	}
24668
24669	getVertexPosition( index, target ) {
24670
24671		super.getVertexPosition( index, target );
24672
24673		this.applyBoneTransform( index, target );
24674
24675		return target;
24676
24677	}
24678
24679	/**
24680	 * Binds the given skeleton to the skinned mesh.
24681	 *
24682	 * @param {Skeleton} skeleton - The skeleton to bind.
24683	 * @param {Matrix4} [bindMatrix] - The bind matrix. If no bind matrix is provided,
24684	 * the skinned mesh's world matrix will be used instead.
24685	 */
24686	bind( skeleton, bindMatrix ) {
24687
24688		this.skeleton = skeleton;
24689
24690		if ( bindMatrix === undefined ) {
24691
24692			this.updateMatrixWorld( true );
24693
24694			this.skeleton.calculateInverses();
24695
24696			bindMatrix = this.matrixWorld;
24697
24698		}
24699
24700		this.bindMatrix.copy( bindMatrix );
24701		this.bindMatrixInverse.copy( bindMatrix ).invert();
24702
24703	}
24704
24705	/**
24706	 * This method sets the skinned mesh in the rest pose).
24707	 */
24708	pose() {
24709
24710		this.skeleton.pose();
24711
24712	}
24713
24714	/**
24715	 * Normalizes the skin weights which are defined as a buffer attribute
24716	 * in the skinned mesh's geometry.
24717	 */
24718	normalizeSkinWeights() {
24719
24720		const vector = new Vector4();
24721
24722		const skinWeight = this.geometry.attributes.skinWeight;
24723
24724		for ( let i = 0, l = skinWeight.count; i < l; i ++ ) {
24725
24726			vector.fromBufferAttribute( skinWeight, i );
24727
24728			const scale = 1.0 / vector.manhattanLength();
24729
24730			if ( scale !== Infinity ) {
24731
24732				vector.multiplyScalar( scale );
24733
24734			} else {
24735
24736				vector.set( 1, 0, 0, 0 ); // do something reasonable
24737
24738			}
24739
24740			skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
24741
24742		}
24743
24744	}
24745
24746	updateMatrixWorld( force ) {
24747
24748		super.updateMatrixWorld( force );
24749
24750		if ( this.bindMode === AttachedBindMode ) {
24751
24752			this.bindMatrixInverse.copy( this.matrixWorld ).invert();
24753
24754		} else if ( this.bindMode === DetachedBindMode ) {
24755
24756			this.bindMatrixInverse.copy( this.bindMatrix ).invert();
24757
24758		} else {
24759
24760			warn( 'SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
24761
24762		}
24763
24764	}
24765
24766	/**
24767	 * Applies the bone transform associated with the given index to the given
24768	 * vector. Can be used to transform positions or direction vectors by providing
24769	 * a Vector4 with 1 or 0 in the w component respectively. Returns the updated vector.
24770	 *
24771	 * @param {number} index - The vertex index.
24772	 * @param {Vector3|Vector4} target - The target object that is used to store the method's result.
24773	 * @return {Vector3|Vector4} The updated vertex attribute data.
24774	 */
24775	applyBoneTransform( index, target ) {
24776
24777		const skeleton = this.skeleton;
24778		const geometry = this.geometry;
24779
24780		_skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
24781		_skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
24782
24783		if ( target.isVector4 ) {
24784
24785			_baseVector.copy( target );
24786			target.set( 0, 0, 0, 0 );
24787
24788		} else {
24789
24790			_baseVector.set( ...target, 1 );
24791			target.set( 0, 0, 0 );
24792
24793		}
24794
24795		_baseVector.applyMatrix4( this.bindMatrix );
24796
24797		for ( let i = 0; i < 4; i ++ ) {
24798
24799			const weight = _skinWeight.getComponent( i );
24800
24801			if ( weight !== 0 ) {
24802
24803				const boneIndex = _skinIndex.getComponent( i );
24804
24805				_matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
24806
24807				target.addScaledVector( _vector4.copy( _baseVector ).applyMatrix4( _matrix4 ), weight );
24808
24809			}
24810
24811		}
24812
24813		if ( target.isVector4 ) {
24814
24815			// ensure the homogenous coordinate remains unchanged after vector operations
24816			target.w = _baseVector.w;
24817
24818		}
24819
24820		return target.applyMatrix4( this.bindMatrixInverse );
24821
24822	}
24823
24824}
24825
24826/**
24827 * A bone which is part of a {@link Skeleton}. The skeleton in turn is used by
24828 * the {@link SkinnedMesh}.
24829 *
24830 * ```js
24831 * const root = new THREE.Bone();
24832 * const child = new THREE.Bone();
24833 *
24834 * root.add( child );
24835 * child.position.y = 5;
24836 * ```
24837 *
24838 * @augments Object3D
24839 */
24840class Bone extends Object3D {
24841
24842	/**
24843	 * Constructs a new bone.
24844	 */
24845	constructor() {
24846
24847		super();
24848
24849		/**
24850		 * This flag can be used for type testing.
24851		 *
24852		 * @type {boolean}
24853		 * @readonly
24854		 * @default true
24855		 */
24856		this.isBone = true;
24857
24858		this.type = 'Bone';
24859
24860	}
24861
24862}
24863
24864/**
24865 * Creates a texture directly from raw buffer data.
24866 *
24867 * The interpretation of the data depends on type and format: If the type is
24868 * `UnsignedByteType`, a `Uint8Array` will be useful for addressing the
24869 * texel data. If the format is `RGBAFormat`, data needs four values for
24870 * one texel; Red, Green, Blue and Alpha (typically the opacity).
24871 *
24872 * @augments Texture
24873 */
24874class DataTexture extends Texture {
24875
24876	/**
24877	 * Constructs a new data texture.
24878	 *
24879	 * @param {?TypedArray} [data=null] - The buffer data.
24880	 * @param {number} [width=1] - The width of the texture.
24881	 * @param {number} [height=1] - The height of the texture.
24882	 * @param {number} [format=RGBAFormat] - The texture format.
24883	 * @param {number} [type=UnsignedByteType] - The texture type.
24884	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
24885	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
24886	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
24887	 * @param {number} [magFilter=NearestFilter] - The mag filter value.
24888	 * @param {number} [minFilter=NearestFilter] - The min filter value.
24889	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
24890	 * @param {string} [colorSpace=NoColorSpace] - The color space.
24891	 */
24892	constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) {
24893
24894		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
24895
24896		/**
24897		 * This flag can be used for type testing.
24898		 *
24899		 * @type {boolean}
24900		 * @readonly
24901		 * @default true
24902		 */
24903		this.isDataTexture = true;
24904
24905		/**
24906		 * The image definition of a data texture.
24907		 *
24908		 * @type {{data:TypedArray,width:number,height:number}}
24909		 */
24910		this.image = { data: data, width: width, height: height };
24911
24912		/**
24913		 * Whether to generate mipmaps (if possible) for a texture.
24914		 *
24915		 * Overwritten and set to `false` by default.
24916		 *
24917		 * @type {boolean}
24918		 * @default false
24919		 */
24920		this.generateMipmaps = false;
24921
24922		/**
24923		 * If set to `true`, the texture is flipped along the vertical axis when
24924		 * uploaded to the GPU.
24925		 *
24926		 * Overwritten and set to `false` by default.
24927		 *
24928		 * @type {boolean}
24929		 * @default false
24930		 */
24931		this.flipY = false;
24932
24933		/**
24934		 * Specifies the alignment requirements for the start of each pixel row in memory.
24935		 *
24936		 * Overwritten and set to `1` by default.
24937		 *
24938		 * @type {boolean}
24939		 * @default 1
24940		 */
24941		this.unpackAlignment = 1;
24942
24943	}
24944
24945}
24946
24947const _offsetMatrix = /*@__PURE__*/ new Matrix4();
24948const _identityMatrix = /*@__PURE__*/ new Matrix4();
24949
24950/**
24951 * Class for representing the armatures in `three.js`. The skeleton
24952 * is defined by a hierarchy of bones.
24953 *
24954 * ```js
24955 * const bones = [];
24956 *
24957 * const shoulder = new THREE.Bone();
24958 * const elbow = new THREE.Bone();
24959 * const hand = new THREE.Bone();
24960 *
24961 * shoulder.add( elbow );
24962 * elbow.add( hand );
24963 *
24964 * bones.push( shoulder , elbow, hand);
24965 *
24966 * shoulder.position.y = -5;
24967 * elbow.position.y = 0;
24968 * hand.position.y = 5;
24969 *
24970 * const armSkeleton = new THREE.Skeleton( bones );
24971 * ```
24972 */
24973class Skeleton {
24974
24975	/**
24976	 * Constructs a new skeleton.
24977	 *
24978	 * @param {Array<Bone>} [bones] - An array of bones.
24979	 * @param {Array<Matrix4>} [boneInverses] - An array of bone inverse matrices.
24980	 * If not provided, these matrices will be computed automatically via {@link Skeleton#calculateInverses}.
24981	 */
24982	constructor( bones = [], boneInverses = [] ) {
24983
24984		this.uuid = generateUUID();
24985
24986		/**
24987		 * An array of bones defining the skeleton.
24988		 *
24989		 * @type {Array<Bone>}
24990		 */
24991		this.bones = bones.slice( 0 );
24992
24993		/**
24994		 * An array of bone inverse matrices.
24995		 *
24996		 * @type {Array<Matrix4>}
24997		 */
24998		this.boneInverses = boneInverses;
24999
25000		/**
25001		 * An array buffer holding the bone data.
25002		 * Input data for {@link Skeleton#boneTexture}.
25003		 *
25004		 * @type {?Float32Array}
25005		 * @default null
25006		 */
25007		this.boneMatrices = null;
25008
25009		/**
25010		 * A texture holding the bone data for use
25011		 * in the vertex shader.
25012		 *
25013		 * @type {?DataTexture}
25014		 * @default null
25015		 */
25016		this.boneTexture = null;
25017
25018		this.init();
25019
25020	}
25021
25022	/**
25023	 * Initializes the skeleton. This method gets automatically called by the constructor
25024	 * but depending on how the skeleton is created it might be necessary to call this method
25025	 * manually.
25026	 */
25027	init() {
25028
25029		const bones = this.bones;
25030		const boneInverses = this.boneInverses;
25031
25032		this.boneMatrices = new Float32Array( bones.length * 16 );
25033
25034		// calculate inverse bone matrices if necessary
25035
25036		if ( boneInverses.length === 0 ) {
25037
25038			this.calculateInverses();
25039
25040		} else {
25041
25042			// handle special case
25043
25044			if ( bones.length !== boneInverses.length ) {
25045
25046				warn( 'Skeleton: Number of inverse bone matrices does not match amount of bones.' );
25047
25048				this.boneInverses = [];
25049
25050				for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
25051
25052					this.boneInverses.push( new Matrix4() );
25053
25054				}
25055
25056			}
25057
25058		}
25059
25060	}
25061
25062	/**
25063	 * Computes the bone inverse matrices. This method resets {@link Skeleton#boneInverses}
25064	 * and fills it with new matrices.
25065	 */
25066	calculateInverses() {
25067
25068		this.boneInverses.length = 0;
25069
25070		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
25071
25072			const inverse = new Matrix4();
25073
25074			if ( this.bones[ i ] ) {
25075
25076				inverse.copy( this.bones[ i ].matrixWorld ).invert();
25077
25078			}
25079
25080			this.boneInverses.push( inverse );
25081
25082		}
25083
25084	}
25085
25086	/**
25087	 * Resets the skeleton to the base pose.
25088	 */
25089	pose() {
25090
25091		// recover the bind-time world matrices
25092
25093		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
25094
25095			const bone = this.bones[ i ];
25096
25097			if ( bone ) {
25098
25099				bone.matrixWorld.copy( this.boneInverses[ i ] ).invert();
25100
25101			}
25102
25103		}
25104
25105		// compute the local matrices, positions, rotations and scales
25106
25107		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
25108
25109			const bone = this.bones[ i ];
25110
25111			if ( bone ) {
25112
25113				if ( bone.parent && bone.parent.isBone ) {
25114
25115					bone.matrix.copy( bone.parent.matrixWorld ).invert();
25116					bone.matrix.multiply( bone.matrixWorld );
25117
25118				} else {
25119
25120					bone.matrix.copy( bone.matrixWorld );
25121
25122				}
25123
25124				bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
25125
25126			}
25127
25128		}
25129
25130	}
25131
25132	/**
25133	 * Resets the skeleton to the base pose.
25134	 */
25135	update() {
25136
25137		const bones = this.bones;
25138		const boneInverses = this.boneInverses;
25139		const boneMatrices = this.boneMatrices;
25140		const boneTexture = this.boneTexture;
25141
25142		// flatten bone matrices to array
25143
25144		for ( let i = 0, il = bones.length; i < il; i ++ ) {
25145
25146			// compute the offset between the current and the original transform
25147
25148			const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;
25149
25150			_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
25151			_offsetMatrix.toArray( boneMatrices, i * 16 );
25152
25153		}
25154
25155		if ( boneTexture !== null ) {
25156
25157			boneTexture.needsUpdate = true;
25158
25159		}
25160
25161	}
25162
25163	/**
25164	 * Returns a new skeleton with copied values from this instance.
25165	 *
25166	 * @return {Skeleton} A clone of this instance.
25167	 */
25168	clone() {
25169
25170		return new Skeleton( this.bones, this.boneInverses );
25171
25172	}
25173
25174	/**
25175	 * Computes a data texture for passing bone data to the vertex shader.
25176	 *
25177	 * @return {Skeleton} A reference of this instance.
25178	 */
25179	computeBoneTexture() {
25180
25181		// layout (1 matrix = 4 pixels)
25182		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
25183		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
25184		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
25185		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
25186		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
25187
25188		let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix
25189		size = Math.ceil( size / 4 ) * 4;
25190		size = Math.max( size, 4 );
25191
25192		const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
25193		boneMatrices.set( this.boneMatrices ); // copy current values
25194
25195		const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );
25196		boneTexture.needsUpdate = true;
25197
25198		this.boneMatrices = boneMatrices;
25199		this.boneTexture = boneTexture;
25200
25201		return this;
25202
25203	}
25204
25205	/**
25206	 * Searches through the skeleton's bone array and returns the first with a
25207	 * matching name.
25208	 *
25209	 * @param {string} name - The name of the bone.
25210	 * @return {Bone|undefined} The found bone. `undefined` if no bone has been found.
25211	 */
25212	getBoneByName( name ) {
25213
25214		for ( let i = 0, il = this.bones.length; i < il; i ++ ) {
25215
25216			const bone = this.bones[ i ];
25217
25218			if ( bone.name === name ) {
25219
25220				return bone;
25221
25222			}
25223
25224		}
25225
25226		return undefined;
25227
25228	}
25229
25230	/**
25231	 * Frees the GPU-related resources allocated by this instance. Call this
25232	 * method whenever this instance is no longer used in your app.
25233	 */
25234	dispose( ) {
25235
25236		if ( this.boneTexture !== null ) {
25237
25238			this.boneTexture.dispose();
25239
25240			this.boneTexture = null;
25241
25242		}
25243
25244	}
25245
25246	/**
25247	 * Setups the skeleton by the given JSON and bones.
25248	 *
25249	 * @param {Object} json - The skeleton as serialized JSON.
25250	 * @param {Object<string, Bone>} bones - An array of bones.
25251	 * @return {Skeleton} A reference of this instance.
25252	 */
25253	fromJSON( json, bones ) {
25254
25255		this.uuid = json.uuid;
25256
25257		for ( let i = 0, l = json.bones.length; i < l; i ++ ) {
25258
25259			const uuid = json.bones[ i ];
25260			let bone = bones[ uuid ];
25261
25262			if ( bone === undefined ) {
25263
25264				warn( 'Skeleton: No bone found with UUID:', uuid );
25265				bone = new Bone();
25266
25267			}
25268
25269			this.bones.push( bone );
25270			this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) );
25271
25272		}
25273
25274		this.init();
25275
25276		return this;
25277
25278	}
25279
25280	/**
25281	 * Serializes the skeleton into JSON.
25282	 *
25283	 * @return {Object} A JSON object representing the serialized skeleton.
25284	 * @see {@link ObjectLoader#parse}
25285	 */
25286	toJSON() {
25287
25288		const data = {
25289			metadata: {
25290				version: 4.7,
25291				type: 'Skeleton',
25292				generator: 'Skeleton.toJSON'
25293			},
25294			bones: [],
25295			boneInverses: []
25296		};
25297
25298		data.uuid = this.uuid;
25299
25300		const bones = this.bones;
25301		const boneInverses = this.boneInverses;
25302
25303		for ( let i = 0, l = bones.length; i < l; i ++ ) {
25304
25305			const bone = bones[ i ];
25306			data.bones.push( bone.uuid );
25307
25308			const boneInverse = boneInverses[ i ];
25309			data.boneInverses.push( boneInverse.toArray() );
25310
25311		}
25312
25313		return data;
25314
25315	}
25316
25317}
25318
25319/**
25320 * An instanced version of a buffer attribute.
25321 *
25322 * @augments BufferAttribute
25323 */
25324class InstancedBufferAttribute extends BufferAttribute {
25325
25326	/**
25327	 * Constructs a new instanced buffer attribute.
25328	 *
25329	 * @param {TypedArray} array - The array holding the attribute data.
25330	 * @param {number} itemSize - The item size.
25331	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
25332	 * @param {number} [meshPerAttribute=1] - How often a value of this buffer attribute should be repeated.
25333	 */
25334	constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {
25335
25336		super( array, itemSize, normalized );
25337
25338		/**
25339		 * This flag can be used for type testing.
25340		 *
25341		 * @type {boolean}
25342		 * @readonly
25343		 * @default true
25344		 */
25345		this.isInstancedBufferAttribute = true;
25346
25347		/**
25348		 * Defines how often a value of this buffer attribute should be repeated. A
25349		 * value of one means that each value of the instanced attribute is used for
25350		 * a single instance. A value of two means that each value is used for two
25351		 * consecutive instances (and so on).
25352		 *
25353		 * @type {number}
25354		 * @default 1
25355		 */
25356		this.meshPerAttribute = meshPerAttribute;
25357
25358	}
25359
25360	copy( source ) {
25361
25362		super.copy( source );
25363
25364		this.meshPerAttribute = source.meshPerAttribute;
25365
25366		return this;
25367
25368	}
25369
25370	toJSON() {
25371
25372		const data = super.toJSON();
25373
25374		data.meshPerAttribute = this.meshPerAttribute;
25375
25376		data.isInstancedBufferAttribute = true;
25377
25378		return data;
25379
25380	}
25381
25382}
25383
25384const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4();
25385const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4();
25386
25387const _instanceIntersects = [];
25388
25389const _box3 = /*@__PURE__*/ new Box3();
25390const _identity = /*@__PURE__*/ new Matrix4();
25391const _mesh$1 = /*@__PURE__*/ new Mesh();
25392const _sphere$4 = /*@__PURE__*/ new Sphere();
25393
25394/**
25395 * A special version of a mesh with instanced rendering support. Use
25396 * this class if you have to render a large number of objects with the same
25397 * geometry and material(s) but with different world transformations. The usage
25398 * of 'InstancedMesh' will help you to reduce the number of draw calls and thus
25399 * improve the overall rendering performance in your application.
25400 *
25401 * @augments Mesh
25402 */
25403class InstancedMesh extends Mesh {
25404
25405	/**
25406	 * Constructs a new instanced mesh.
25407	 *
25408	 * @param {BufferGeometry} [geometry] - The mesh geometry.
25409	 * @param {Material|Array<Material>} [material] - The mesh material.
25410	 * @param {number} count - The number of instances.
25411	 */
25412	constructor( geometry, material, count ) {
25413
25414		super( geometry, material );
25415
25416		/**
25417		 * This flag can be used for type testing.
25418		 *
25419		 * @type {boolean}
25420		 * @readonly
25421		 * @default true
25422		 */
25423		this.isInstancedMesh = true;
25424
25425		/**
25426		 * Represents the local transformation of all instances. You have to set its
25427		 * {@link BufferAttribute#needsUpdate} flag to true if you modify instanced data
25428		 * via {@link InstancedMesh#setMatrixAt}.
25429		 *
25430		 * @type {InstancedBufferAttribute}
25431		 */
25432		this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 );
25433
25434		/**
25435		 * Represents the color of all instances. You have to set its
25436		 * {@link BufferAttribute#needsUpdate} flag to true if you modify instanced data
25437		 * via {@link InstancedMesh#setColorAt}.
25438		 *
25439		 * @type {?InstancedBufferAttribute}
25440		 * @default null
25441		 */
25442		this.instanceColor = null;
25443
25444		/**
25445		 * Represents the morph target weights of all instances. You have to set its
25446		 * {@link Texture#needsUpdate} flag to true if you modify instanced data
25447		 * via {@link InstancedMesh#setMorphAt}.
25448		 *
25449		 * @type {?DataTexture}
25450		 * @default null
25451		 */
25452		this.morphTexture = null;
25453
25454		/**
25455		 * The number of instances.
25456		 *
25457		 * @type {number}
25458		 */
25459		this.count = count;
25460
25461		/**
25462		 * The bounding box of the instanced mesh. Can be computed via {@link InstancedMesh#computeBoundingBox}.
25463		 *
25464		 * @type {?Box3}
25465		 * @default null
25466		 */
25467		this.boundingBox = null;
25468
25469		/**
25470		 * The bounding sphere of the instanced mesh. Can be computed via {@link InstancedMesh#computeBoundingSphere}.
25471		 *
25472		 * @type {?Sphere}
25473		 * @default null
25474		 */
25475		this.boundingSphere = null;
25476
25477		for ( let i = 0; i < count; i ++ ) {
25478
25479			this.setMatrixAt( i, _identity );
25480
25481		}
25482
25483	}
25484
25485	/**
25486	 * Computes the bounding box of the instanced mesh, and updates {@link InstancedMesh#boundingBox}.
25487	 * The bounding box is not automatically computed by the engine; this method must be called by your app.
25488	 * You may need to recompute the bounding box if an instance is transformed via {@link InstancedMesh#setMatrixAt}.
25489	 */
25490	computeBoundingBox() {
25491
25492		const geometry = this.geometry;
25493		const count = this.count;
25494
25495		if ( this.boundingBox === null ) {
25496
25497			this.boundingBox = new Box3();
25498
25499		}
25500
25501		if ( geometry.boundingBox === null ) {
25502
25503			geometry.computeBoundingBox();
25504
25505		}
25506
25507		this.boundingBox.makeEmpty();
25508
25509		for ( let i = 0; i < count; i ++ ) {
25510
25511			this.getMatrixAt( i, _instanceLocalMatrix );
25512
25513			_box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix );
25514
25515			this.boundingBox.union( _box3 );
25516
25517		}
25518
25519	}
25520
25521	/**
25522	 * Computes the bounding sphere of the instanced mesh, and updates {@link InstancedMesh#boundingSphere}
25523	 * The engine automatically computes the bounding sphere when it is needed, e.g., for ray casting or view frustum culling.
25524	 * You may need to recompute the bounding sphere if an instance is transformed via {@link InstancedMesh#setMatrixAt}.
25525	 */
25526	computeBoundingSphere() {
25527
25528		const geometry = this.geometry;
25529		const count = this.count;
25530
25531		if ( this.boundingSphere === null ) {
25532
25533			this.boundingSphere = new Sphere();
25534
25535		}
25536
25537		if ( geometry.boundingSphere === null ) {
25538
25539			geometry.computeBoundingSphere();
25540
25541		}
25542
25543		this.boundingSphere.makeEmpty();
25544
25545		for ( let i = 0; i < count; i ++ ) {
25546
25547			this.getMatrixAt( i, _instanceLocalMatrix );
25548
25549			_sphere$4.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix );
25550
25551			this.boundingSphere.union( _sphere$4 );
25552
25553		}
25554
25555	}
25556
25557	copy( source, recursive ) {
25558
25559		super.copy( source, recursive );
25560
25561		this.instanceMatrix.copy( source.instanceMatrix );
25562
25563		if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone();
25564		if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone();
25565
25566		this.count = source.count;
25567
25568		if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone();
25569		if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone();
25570
25571		return this;
25572
25573	}
25574
25575	/**
25576	 * Gets the color of the defined instance.
25577	 *
25578	 * @param {number} index - The instance index.
25579	 * @param {Color} color - The target object that is used to store the method's result.
25580	 * @return {Color} A reference to the target color.
25581	 */
25582	getColorAt( index, color ) {
25583
25584		if ( this.instanceColor === null ) {
25585
25586			return color.setRGB( 1, 1, 1 );
25587
25588		} else {
25589
25590			return color.fromArray( this.instanceColor.array, index * 3 );
25591
25592		}
25593
25594	}
25595
25596	/**
25597	 * Gets the local transformation matrix of the defined instance.
25598	 *
25599	 * @param {number} index - The instance index.
25600	 * @param {Matrix4} matrix - The target object that is used to store the method's result.
25601	 * @return {Matrix4} A reference to the target matrix.
25602	 */
25603	getMatrixAt( index, matrix ) {
25604
25605		return matrix.fromArray( this.instanceMatrix.array, index * 16 );
25606
25607	}
25608
25609	/**
25610	 * Gets the morph target weights of the defined instance.
25611	 *
25612	 * @param {number} index - The instance index.
25613	 * @param {Mesh} object - The target object that is used to store the method's result.
25614	 */
25615	getMorphAt( index, object ) {
25616
25617		const objectInfluences = object.morphTargetInfluences;
25618
25619		const array = this.morphTexture.source.data.data;
25620
25621		const len = objectInfluences.length + 1; // All influences + the baseInfluenceSum
25622
25623		const dataIndex = index * len + 1; // Skip the baseInfluenceSum at the beginning
25624
25625		for ( let i = 0; i < objectInfluences.length; i ++ ) {
25626
25627			objectInfluences[ i ] = array[ dataIndex + i ];
25628
25629		}
25630
25631	}
25632
25633	raycast( raycaster, intersects ) {
25634
25635		const matrixWorld = this.matrixWorld;
25636		const raycastTimes = this.count;
25637
25638		_mesh$1.geometry = this.geometry;
25639		_mesh$1.material = this.material;
25640
25641		if ( _mesh$1.material === undefined ) return;
25642
25643		// test with bounding sphere first
25644
25645		if ( this.boundingSphere === null ) this.computeBoundingSphere();
25646
25647		_sphere$4.copy( this.boundingSphere );
25648		_sphere$4.applyMatrix4( matrixWorld );
25649
25650		if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return;
25651
25652		// now test each instance
25653
25654		for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
25655
25656			// calculate the world matrix for each instance
25657
25658			this.getMatrixAt( instanceId, _instanceLocalMatrix );
25659
25660			_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
25661
25662			// the mesh represents this single instance
25663
25664			_mesh$1.matrixWorld = _instanceWorldMatrix;
25665
25666			_mesh$1.raycast( raycaster, _instanceIntersects );
25667
25668			// process the result of raycast
25669
25670			for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) {
25671
25672				const intersect = _instanceIntersects[ i ];
25673				intersect.instanceId = instanceId;
25674				intersect.object = this;
25675				intersects.push( intersect );
25676
25677			}
25678
25679			_instanceIntersects.length = 0;
25680
25681		}
25682
25683	}
25684
25685	/**
25686	 * Sets the given color to the defined instance. Make sure you set the `needsUpdate` flag of
25687	 * {@link InstancedMesh#instanceColor} to `true` after updating all the colors.
25688	 *
25689	 * @param {number} index - The instance index.
25690	 * @param {Color} color - The instance color.
25691	 * @return {InstancedMesh} A reference to this instanced mesh.
25692	 */
25693	setColorAt( index, color ) {
25694
25695		if ( this.instanceColor === null ) {
25696
25697			this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ).fill( 1 ), 3 );
25698
25699		}
25700
25701		color.toArray( this.instanceColor.array, index * 3 );
25702		return this;
25703
25704	}
25705
25706	/**
25707	 * Sets the given local transformation matrix to the defined instance. Make sure you set the `needsUpdate` flag of
25708	 * {@link InstancedMesh#instanceMatrix} to `true` after updating all the matrices.
25709	 *
25710	 * @param {number} index - The instance index.
25711	 * @param {Matrix4} matrix - The local transformation.
25712	 * @return {InstancedMesh} A reference to this instanced mesh.
25713	 */
25714	setMatrixAt( index, matrix ) {
25715
25716		matrix.toArray( this.instanceMatrix.array, index * 16 );
25717		return this;
25718
25719	}
25720
25721	/**
25722	 * Sets the morph target weights to the defined instance. Make sure you set the `needsUpdate` flag of
25723	 * {@link InstancedMesh#morphTexture} to `true` after updating all the influences.
25724	 *
25725	 * @param {number} index - The instance index.
25726	 * @param {Mesh} object -  A mesh which `morphTargetInfluences` property containing the morph target weights
25727	 * of a single instance.
25728	 * @return {InstancedMesh} A reference to this instanced mesh.
25729	 */
25730	setMorphAt( index, object ) {
25731
25732		const objectInfluences = object.morphTargetInfluences;
25733
25734		const len = objectInfluences.length + 1; // morphBaseInfluence + all influences
25735
25736		if ( this.morphTexture === null ) {
25737
25738			this.morphTexture = new DataTexture( new Float32Array( len * this.count ), len, this.count, RedFormat, FloatType );
25739
25740		}
25741
25742		const array = this.morphTexture.source.data.data;
25743
25744		let morphInfluencesSum = 0;
25745
25746		for ( let i = 0; i < objectInfluences.length; i ++ ) {
25747
25748			morphInfluencesSum += objectInfluences[ i ];
25749
25750		}
25751
25752		const morphBaseInfluence = this.geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
25753
25754		const dataIndex = len * index;
25755
25756		array[ dataIndex ] = morphBaseInfluence;
25757
25758		array.set( objectInfluences, dataIndex + 1 );
25759		return this;
25760
25761	}
25762
25763	updateMorphTargets() {
25764
25765	}
25766
25767	/**
25768	 * Frees the GPU-related resources allocated by this instance. Call this
25769	 * method whenever this instance is no longer used in your app.
25770	 */
25771	dispose() {
25772
25773		super.dispose();
25774
25775		if ( this.morphTexture !== null ) {
25776
25777			this.morphTexture.dispose();
25778			this.morphTexture = null;
25779
25780		}
25781
25782	}
25783
25784}
25785
25786const _sphere$3 = /*@__PURE__*/ new Sphere();
25787const _defaultSpriteCenter = /*@__PURE__*/ new Vector2( 0.5, 0.5 );
25788const _vector$6 = /*@__PURE__*/ new Vector3();
25789
25790/**
25791 * Frustums are used to determine what is inside the camera's field of view.
25792 * They help speed up the rendering process - objects which lie outside a camera's
25793 * frustum can safely be excluded from rendering.
25794 *
25795 * This class is mainly intended for use internally by a renderer.
25796 */
25797class Frustum {
25798
25799	/**
25800	 * Constructs a new frustum.
25801	 *
25802	 * @param {Plane} [p0] - The first plane that encloses the frustum.
25803	 * @param {Plane} [p1] - The second plane that encloses the frustum.
25804	 * @param {Plane} [p2] - The third plane that encloses the frustum.
25805	 * @param {Plane} [p3] - The fourth plane that encloses the frustum.
25806	 * @param {Plane} [p4] - The fifth plane that encloses the frustum.
25807	 * @param {Plane} [p5] - The sixth plane that encloses the frustum.
25808	 */
25809	constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) {
25810
25811		/**
25812		 * This array holds the planes that enclose the frustum.
25813		 *
25814		 * @type {Array<Plane>}
25815		 */
25816		this.planes = [ p0, p1, p2, p3, p4, p5 ];
25817
25818	}
25819
25820	/**
25821	 * Sets the frustum planes by copying the given planes.
25822	 *
25823	 * @param {Plane} [p0] - The first plane that encloses the frustum.
25824	 * @param {Plane} [p1] - The second plane that encloses the frustum.
25825	 * @param {Plane} [p2] - The third plane that encloses the frustum.
25826	 * @param {Plane} [p3] - The fourth plane that encloses the frustum.
25827	 * @param {Plane} [p4] - The fifth plane that encloses the frustum.
25828	 * @param {Plane} [p5] - The sixth plane that encloses the frustum.
25829	 * @return {Frustum} A reference to this frustum.
25830	 */
25831	set( p0, p1, p2, p3, p4, p5 ) {
25832
25833		const planes = this.planes;
25834
25835		planes[ 0 ].copy( p0 );
25836		planes[ 1 ].copy( p1 );
25837		planes[ 2 ].copy( p2 );
25838		planes[ 3 ].copy( p3 );
25839		planes[ 4 ].copy( p4 );
25840		planes[ 5 ].copy( p5 );
25841
25842		return this;
25843
25844	}
25845
25846	/**
25847	 * Copies the values of the given frustum to this instance.
25848	 *
25849	 * @param {Frustum} frustum - The frustum to copy.
25850	 * @return {Frustum} A reference to this frustum.
25851	 */
25852	copy( frustum ) {
25853
25854		const planes = this.planes;
25855
25856		for ( let i = 0; i < 6; i ++ ) {
25857
25858			planes[ i ].copy( frustum.planes[ i ] );
25859
25860		}
25861
25862		return this;
25863
25864	}
25865
25866	/**
25867	 * Sets the frustum planes from the given projection matrix.
25868	 *
25869	 * @param {Matrix4} m - The projection matrix.
25870	 * @param {(WebGLCoordinateSystem|WebGPUCoordinateSystem)} coordinateSystem - The coordinate system.
25871	 * @param {boolean} [reversedDepth=false] - Whether to use a reversed depth.
25872	 * @return {Frustum} A reference to this frustum.
25873	 */
25874	setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem, reversedDepth = false ) {
25875
25876		const planes = this.planes;
25877		const me = m.elements;
25878		const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
25879		const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
25880		const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
25881		const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
25882
25883		planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
25884		planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
25885		planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
25886		planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
25887
25888		if ( reversedDepth ) {
25889
25890			planes[ 4 ].setComponents( me2, me6, me10, me14 ).normalize(); // far
25891			planes[ 5 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); // near
25892
25893		} else {
25894
25895			planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); // far
25896
25897			if ( coordinateSystem === WebGLCoordinateSystem ) {
25898
25899				planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); // near
25900
25901			} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
25902
25903				planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); // near
25904
25905			} else {
25906
25907				throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
25908
25909			}
25910
25911		}
25912
25913		return this;
25914
25915	}
25916
25917	/**
25918	 * Returns `true` if the 3D object's bounding sphere is intersecting this frustum.
25919	 *
25920	 * Note that the 3D object must have a geometry so that the bounding sphere can be calculated.
25921	 *
25922	 * @param {Object3D} object - The 3D object to test.
25923	 * @return {boolean} Whether the 3D object's bounding sphere is intersecting this frustum or not.
25924	 */
25925	intersectsObject( object ) {
25926
25927		if ( object.boundingSphere !== undefined ) {
25928
25929			if ( object.boundingSphere === null ) object.computeBoundingSphere();
25930
25931			_sphere$3.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld );
25932
25933		} else {
25934
25935			const geometry = object.geometry;
25936
25937			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
25938
25939			_sphere$3.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );
25940
25941		}
25942
25943		return this.intersectsSphere( _sphere$3 );
25944
25945	}
25946
25947	/**
25948	 * Returns `true` if the given sprite is intersecting this frustum.
25949	 *
25950	 * @param {Sprite} sprite - The sprite to test.
25951	 * @return {boolean} Whether the sprite is intersecting this frustum or not.
25952	 */
25953	intersectsSprite( sprite ) {
25954
25955		_sphere$3.center.set( 0, 0, 0 );
25956
25957		const offset = _defaultSpriteCenter.distanceTo( sprite.center );
25958
25959		_sphere$3.radius = 0.7071067811865476 + offset;
25960		_sphere$3.applyMatrix4( sprite.matrixWorld );
25961
25962		return this.intersectsSphere( _sphere$3 );
25963
25964	}
25965
25966	/**
25967	 * Returns `true` if the given bounding sphere is intersecting this frustum.
25968	 *
25969	 * This is a fast, conservative test that favors performance over precision. It can
25970	 * report false positives for spheres that lie outside the frustum but are not separated
25971	 * by a single frustum plane. It never reports false negatives, so it is safe for culling.
25972	 *
25973	 * @param {Sphere} sphere - The bounding sphere to test.
25974	 * @return {boolean} Whether the bounding sphere is intersecting this frustum or not.
25975	 */
25976	intersectsSphere( sphere ) {
25977
25978		const planes = this.planes;
25979		const center = sphere.center;
25980		const negRadius = - sphere.radius;
25981
25982		for ( let i = 0; i < 6; i ++ ) {
25983
25984			const distance = planes[ i ].distanceToPoint( center );
25985
25986			if ( distance < negRadius ) {
25987
25988				return false;
25989
25990			}
25991
25992		}
25993
25994		return true;
25995
25996	}
25997
25998	/**
25999	 * Returns `true` if the given bounding box is intersecting this frustum.
26000	 *
26001	 * This is a fast, conservative test that favors performance over precision. It can
26002	 * report false positives for large boxes that lie outside the frustum but are not
26003	 * separated by a single frustum plane. It never reports false negatives, so it is
26004	 * safe for culling.
26005	 *
26006	 * @param {Box3} box - The bounding box to test.
26007	 * @return {boolean} Whether the bounding box is intersecting this frustum or not.
26008	 */
26009	intersectsBox( box ) {
26010
26011		const planes = this.planes;
26012
26013		for ( let i = 0; i < 6; i ++ ) {
26014
26015			const plane = planes[ i ];
26016
26017			// corner at max distance
26018
26019			_vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x;
26020			_vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y;
26021			_vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z;
26022
26023			if ( plane.distanceToPoint( _vector$6 ) < 0 ) {
26024
26025				return false;
26026
26027			}
26028
26029		}
26030
26031		return true;
26032
26033	}
26034
26035	/**
26036	 * Returns `true` if the given point lies within the frustum.
26037	 *
26038	 * @param {Vector3} point - The point to test.
26039	 * @return {boolean} Whether the point lies within this frustum or not.
26040	 */
26041	containsPoint( point ) {
26042
26043		const planes = this.planes;
26044
26045		for ( let i = 0; i < 6; i ++ ) {
26046
26047			if ( planes[ i ].distanceToPoint( point ) < 0 ) {
26048
26049				return false;
26050
26051			}
26052
26053		}
26054
26055		return true;
26056
26057	}
26058
26059	/**
26060	 * Returns a new frustum with copied values from this instance.
26061	 *
26062	 * @return {Frustum} A clone of this instance.
26063	 */
26064	clone() {
26065
26066		return new this.constructor().copy( this );
26067
26068	}
26069
26070}
26071
26072const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
26073
26074/**
26075 * FrustumArray is used to determine if an object is visible in at least one camera
26076 * from an array of cameras. This is particularly useful for multi-view renderers.
26077*/
26078class FrustumArray {
26079
26080	/**
26081	 * Constructs a new frustum array.
26082	 *
26083	 */
26084	constructor() {
26085
26086		/**
26087		 * The coordinate system to use.
26088		 *
26089		 * @type {WebGLCoordinateSystem|WebGPUCoordinateSystem}
26090		 * @default WebGLCoordinateSystem
26091		 */
26092		this.coordinateSystem = WebGLCoordinateSystem;
26093
26094		/**
26095		 * A pool of frustum instances. It may hold more entries than are
26096		 * currently in use; surplus instances are kept for reuse to avoid
26097		 * reallocating when array cameras of different lengths are rendered.
26098		 *
26099		 * @private
26100		 * @type {Array<Frustum>}
26101		 */
26102		this._frustums = [];
26103
26104		/**
26105		 * The number of frustums in {@link FrustumArray#_frustums} that are currently
26106		 * in use.
26107		 *
26108		 * @private
26109		 * @type {number}
26110		 * @default 0
26111		 */
26112		this._count = 0;
26113
26114	}
26115
26116	/**
26117	 * Computes and caches a frustum for each camera of the given array camera.
26118	 *
26119	 * @param {ArrayCamera} cameraArray - The array camera whose sub-cameras define the frustums.
26120	 * @return {FrustumArray} A reference to this frustum array.
26121	 */
26122	setFromArrayCamera( cameraArray ) {
26123
26124		const cameras = cameraArray.cameras;
26125		const frustums = this._frustums;
26126
26127		for ( let i = 0; i < cameras.length; i ++ ) {
26128
26129			const camera = cameras[ i ];
26130
26131			_projScreenMatrix$1.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
26132
26133			if ( frustums[ i ] === undefined ) frustums[ i ] = new Frustum();
26134
26135			frustums[ i ].setFromProjectionMatrix( _projScreenMatrix$1, camera.coordinateSystem, camera.reversedDepth );
26136
26137		}
26138
26139		this._count = cameras.length;
26140
26141		return this;
26142
26143	}
26144
26145	/**
26146	 * Returns `true` if the 3D object's bounding sphere is intersecting any cached frustum.
26147	 *
26148	 * {@link FrustumArray#setFromArrayCamera} must be called once per render before this method.
26149	 *
26150	 * @param {Object3D} object - The 3D object to test.
26151	 * @return {boolean} Whether the 3D object is visible in any camera.
26152	 */
26153	intersectsObject( object ) {
26154
26155		const frustums = this._frustums;
26156
26157		for ( let i = 0; i < this._count; i ++ ) {
26158
26159			if ( frustums[ i ].intersectsObject( object ) ) return true;
26160
26161		}
26162
26163		return false;
26164
26165	}
26166
26167	/**
26168	 * Returns `true` if the given sprite is intersecting any cached frustum.
26169	 *
26170	 * {@link FrustumArray#setFromArrayCamera} must be called once per render before this method.
26171	 *
26172	 * @param {Sprite} sprite - The sprite to test.
26173	 * @return {boolean} Whether the sprite is visible in any camera.
26174	 */
26175	intersectsSprite( sprite ) {
26176
26177		const frustums = this._frustums;
26178
26179		for ( let i = 0; i < this._count; i ++ ) {
26180
26181			if ( frustums[ i ].intersectsSprite( sprite ) ) return true;
26182
26183		}
26184
26185		return false;
26186
26187	}
26188
26189	/**
26190	 * Returns `true` if the given bounding sphere is intersecting any cached frustum.
26191	 *
26192	 * {@link FrustumArray#setFromArrayCamera} must be called once per render before this method.
26193	 *
26194	 * @param {Sphere} sphere - The bounding sphere to test.
26195	 * @return {boolean} Whether the sphere is visible in any camera.
26196	 */
26197	intersectsSphere( sphere ) {
26198
26199		const frustums = this._frustums;
26200
26201		for ( let i = 0; i < this._count; i ++ ) {
26202
26203			if ( frustums[ i ].intersectsSphere( sphere ) ) return true;
26204
26205		}
26206
26207		return false;
26208
26209	}
26210
26211	/**
26212	 * Returns `true` if the given bounding box is intersecting any cached frustum.
26213	 *
26214	 * {@link FrustumArray#setFromArrayCamera} must be called once per render before this method.
26215	 *
26216	 * @param {Box3} box - The bounding box to test.
26217	 * @return {boolean} Whether the box is visible in any camera.
26218	 */
26219	intersectsBox( box ) {
26220
26221		const frustums = this._frustums;
26222
26223		for ( let i = 0; i < this._count; i ++ ) {
26224
26225			if ( frustums[ i ].intersectsBox( box ) ) return true;
26226
26227		}
26228
26229		return false;
26230
26231	}
26232
26233	/**
26234	 * Returns `true` if the given point lies within any cached frustum.
26235	 *
26236	 * {@link FrustumArray#setFromArrayCamera} must be called once per render before this method.
26237	 *
26238	 * @param {Vector3} point - The point to test.
26239	 * @return {boolean} Whether the point is visible in any camera.
26240	 */
26241	containsPoint( point ) {
26242
26243		const frustums = this._frustums;
26244
26245		for ( let i = 0; i < this._count; i ++ ) {
26246
26247			if ( frustums[ i ].containsPoint( point ) ) return true;
26248
26249		}
26250
26251		return false;
26252
26253	}
26254
26255	/**
26256	 * Copies the values of the given frustum array to this instance.
26257	 *
26258	 * @param {FrustumArray} source - The frustum array to copy.
26259	 * @return {FrustumArray} A reference to this frustum array.
26260	 */
26261	copy( source ) {
26262
26263		this.coordinateSystem = source.coordinateSystem;
26264
26265		const frustums = this._frustums;
26266		const sourceFrustums = source._frustums;
26267
26268		for ( let i = 0; i < source._count; i ++ ) {
26269
26270			if ( frustums[ i ] === undefined ) frustums[ i ] = new Frustum();
26271
26272			frustums[ i ].copy( sourceFrustums[ i ] );
26273
26274		}
26275
26276		this._count = source._count;
26277
26278		return this;
26279
26280	}
26281
26282	/**
26283	 * Returns a new frustum array with copied values from this instance.
26284	 *
26285	 * @return {FrustumArray} A clone of this instance.
26286	 */
26287	clone() {
26288
26289		return new FrustumArray().copy( this );
26290
26291	}
26292
26293}
26294
26295function ascIdSort( a, b ) {
26296
26297	return a - b;
26298
26299}
26300
26301function sortOpaque( a, b ) {
26302
26303	return a.z - b.z;
26304
26305}
26306
26307function sortTransparent( a, b ) {
26308
26309	return b.z - a.z;
26310
26311}
26312
26313class MultiDrawRenderList {
26314
26315	constructor() {
26316
26317		this.index = 0;
26318		this.pool = [];
26319		this.list = [];
26320
26321	}
26322
26323	push( start, count, z, index ) {
26324
26325		const pool = this.pool;
26326		const list = this.list;
26327		if ( this.index >= pool.length ) {
26328
26329			pool.push( {
26330
26331				start: -1,
26332				count: -1,
26333				z: -1,
26334				index: -1,
26335
26336			} );
26337
26338		}
26339
26340		const item = pool[ this.index ];
26341		list.push( item );
26342		this.index ++;
26343
26344		item.start = start;
26345		item.count = count;
26346		item.z = z;
26347		item.index = index;
26348
26349	}
26350
26351	reset() {
26352
26353		this.list.length = 0;
26354		this.index = 0;
26355
26356	}
26357
26358}
26359
26360const _matrix$1 = /*@__PURE__*/ new Matrix4();
26361const _whiteColor = /*@__PURE__*/ new Color( 1, 1, 1 );
26362const _frustum = /*@__PURE__*/ new Frustum();
26363const _frustumArray = /*@__PURE__*/ new FrustumArray();
26364const _box$1 = /*@__PURE__*/ new Box3();
26365const _sphere$2 = /*@__PURE__*/ new Sphere();
26366const _vector$5 = /*@__PURE__*/ new Vector3();
26367const _forward$1 = /*@__PURE__*/ new Vector3();
26368const _temp = /*@__PURE__*/ new Vector3();
26369const _renderList = /*@__PURE__*/ new MultiDrawRenderList();
26370const _mesh = /*@__PURE__*/ new Mesh();
26371const _batchIntersects = [];
26372
26373// copies data from attribute "src" into "target" starting at "targetOffset"
26374function copyAttributeData( src, target, targetOffset = 0 ) {
26375
26376	const itemSize = target.itemSize;
26377	if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) {
26378
26379		// use the component getters and setters if the array data cannot
26380		// be copied directly
26381		const vertexCount = src.count;
26382		for ( let i = 0; i < vertexCount; i ++ ) {
26383
26384			for ( let c = 0; c < itemSize; c ++ ) {
26385
26386				target.setComponent( i + targetOffset, c, src.getComponent( i, c ) );
26387
26388			}
26389
26390		}
26391
26392	} else {
26393
26394		// faster copy approach using typed array set function
26395		target.array.set( src.array, targetOffset * itemSize );
26396
26397	}
26398
26399	target.needsUpdate = true;
26400
26401}
26402
26403// safely copies array contents to a potentially smaller array
26404function copyArrayContents( src, target ) {
26405
26406	if ( src.constructor !== target.constructor ) {
26407
26408		// if arrays are of a different type (eg due to index size increasing) then data must be per-element copied
26409		const len = Math.min( src.length, target.length );
26410		for ( let i = 0; i < len; i ++ ) {
26411
26412			target[ i ] = src[ i ];
26413
26414		}
26415
26416	} else {
26417
26418		// if the arrays use the same data layout we can use a fast block copy
26419		const len = Math.min( src.length, target.length );
26420		target.set( new src.constructor( src.buffer, 0, len ) );
26421
26422	}
26423
26424}
26425
26426/**
26427 * A special version of a mesh with multi draw batch rendering support. Use
26428 * this class if you have to render a large number of objects with the same
26429 * material but with different geometries or world transformations. The usage of
26430 * `BatchedMesh` will help you to reduce the number of draw calls and thus improve the overall
26431 * rendering performance in your application.
26432 *
26433 * ```js
26434 * const box = new THREE.BoxGeometry( 1, 1, 1 );
26435 * const sphere = new THREE.SphereGeometry( 1, 12, 12 );
26436 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
26437 *
26438 * // initialize and add geometries into the batched mesh
26439 * const batchedMesh = new BatchedMesh( 10, 5000, 10000, material );
26440 * const boxGeometryId = batchedMesh.addGeometry( box );
26441 * const sphereGeometryId = batchedMesh.addGeometry( sphere );
26442 *
26443 * // create instances of those geometries
26444 * const boxInstancedId1 = batchedMesh.addInstance( boxGeometryId );
26445 * const boxInstancedId2 = batchedMesh.addInstance( boxGeometryId );
26446 *
26447 * const sphereInstancedId1 = batchedMesh.addInstance( sphereGeometryId );
26448 * const sphereInstancedId2 = batchedMesh.addInstance( sphereGeometryId );
26449 *
26450 * // position the geometries
26451 * batchedMesh.setMatrixAt( boxInstancedId1, boxMatrix1 );
26452 * batchedMesh.setMatrixAt( boxInstancedId2, boxMatrix2 );
26453 *
26454 * batchedMesh.setMatrixAt( sphereInstancedId1, sphereMatrix1 );
26455 * batchedMesh.setMatrixAt( sphereInstancedId2, sphereMatrix2 );
26456 *
26457 * scene.add( batchedMesh );
26458 * ```
26459 *
26460 * @augments Mesh
26461 */
26462class BatchedMesh extends Mesh {
26463
26464	/**
26465	 * Constructs a new batched mesh.
26466	 *
26467	 * @param {number} maxInstanceCount - The maximum number of individual instances planned to be added and rendered.
26468	 * @param {number} maxVertexCount - The maximum number of vertices to be used by all unique geometries.
26469	 * @param {number} [maxIndexCount=maxVertexCount*2] - The maximum number of indices to be used by all unique geometries
26470	 * @param {Material|Array<Material>} [material] - The mesh material.
26471	 */
26472	constructor( maxInstanceCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) {
26473
26474		super( new BufferGeometry(), material );
26475
26476		/**
26477		 * This flag can be used for type testing.
26478		 *
26479		 * @type {boolean}
26480		 * @readonly
26481		 * @default true
26482		 */
26483		this.isBatchedMesh = true;
26484
26485		/**
26486		 * When set ot `true`, the individual objects of a batch are frustum culled.
26487		 *
26488		 * @type {boolean}
26489		 * @default true
26490		 */
26491		this.perObjectFrustumCulled = true;
26492
26493		/**
26494		 * When set to `true`, the individual objects of a batch are sorted to improve overdraw-related artifacts.
26495		 * If the material is marked as "transparent" objects are rendered back to front and if not then they are
26496		 * rendered front to back.
26497		 *
26498		 * @type {boolean}
26499		 * @default true
26500		 */
26501		this.sortObjects = true;
26502
26503		/**
26504		 * The bounding box of the batched mesh. Can be computed via {@link BatchedMesh#computeBoundingBox}.
26505		 *
26506		 * @type {?Box3}
26507		 * @default null
26508		 */
26509		this.boundingBox = null;
26510
26511		/**
26512		 * The bounding sphere of the batched mesh. Can be computed via {@link BatchedMesh#computeBoundingSphere}.
26513		 *
26514		 * @type {?Sphere}
26515		 * @default null
26516		 */
26517		this.boundingSphere = null;
26518
26519		/**
26520		 * Takes a sort a function that is run before render. The function takes a list of instances to
26521		 * sort and a camera. The objects in the list include a "z" field to perform a depth-ordered
26522		 * sort with.
26523		 *
26524		 * @type {?Function}
26525		 * @default null
26526		 */
26527		this.customSort = null;
26528
26529		// stores visible, active, and geometry id per instance and reserved buffer ranges for geometries
26530		this._instanceInfo = [];
26531		this._geometryInfo = [];
26532
26533		// instance, geometry ids that have been set as inactive, and are available to be overwritten
26534		this._availableInstanceIds = [];
26535		this._availableGeometryIds = [];
26536
26537		// used to track where the next point is that geometry should be inserted
26538		this._nextIndexStart = 0;
26539		this._nextVertexStart = 0;
26540		this._geometryCount = 0;
26541
26542		// flags
26543		this._visibilityChanged = true;
26544		this._geometryInitialized = false;
26545
26546		// cached user options
26547		this._maxInstanceCount = maxInstanceCount;
26548		this._maxVertexCount = maxVertexCount;
26549		this._maxIndexCount = maxIndexCount;
26550
26551		// buffers for multi draw
26552		this._multiDrawCounts = new Int32Array( maxInstanceCount );
26553		this._multiDrawStarts = new Int32Array( maxInstanceCount );
26554		this._multiDrawCount = 0;
26555		this._multiDrawBytesPerElement = 1;
26556
26557		// Local matrix per geometry by using data texture
26558		this._matricesTexture = null;
26559		this._indirectTexture = null;
26560		this._colorsTexture = null;
26561
26562		this._initMatricesTexture();
26563		this._initIndirectTexture();
26564
26565	}
26566
26567	/**
26568	 * The maximum number of individual instances that can be stored in the batch.
26569	 *
26570	 * @type {number}
26571	 * @readonly
26572	 */
26573	get maxInstanceCount() {
26574
26575		return this._maxInstanceCount;
26576
26577	}
26578
26579	/**
26580	 * The instance count.
26581	 *
26582	 * @type {number}
26583	 * @readonly
26584	 */
26585	get instanceCount() {
26586
26587		return this._instanceInfo.length - this._availableInstanceIds.length;
26588
26589	}
26590
26591	/**
26592	 * The number of unused vertices.
26593	 *
26594	 * @type {number}
26595	 * @readonly
26596	 */
26597	get unusedVertexCount() {
26598
26599		return this._maxVertexCount - this._nextVertexStart;
26600
26601	}
26602
26603	/**
26604	 * The number of unused indices.
26605	 *
26606	 * @type {number}
26607	 * @readonly
26608	 */
26609	get unusedIndexCount() {
26610
26611		return this._maxIndexCount - this._nextIndexStart;
26612
26613	}
26614
26615	_initMatricesTexture() {
26616
26617		// layout (1 matrix = 4 pixels)
26618		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
26619		//  with  8x8  pixel texture max   16 matrices * 4 pixels =  (8 * 8)
26620		//       16x16 pixel texture max   64 matrices * 4 pixels = (16 * 16)
26621		//       32x32 pixel texture max  256 matrices * 4 pixels = (32 * 32)
26622		//       64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64)
26623
26624		let size = Math.sqrt( this._maxInstanceCount * 4 ); // 4 pixels needed for 1 matrix
26625		size = Math.ceil( size / 4 ) * 4;
26626		size = Math.max( size, 4 );
26627
26628		const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel
26629		const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType );
26630
26631		this._matricesTexture = matricesTexture;
26632
26633	}
26634
26635	_initIndirectTexture() {
26636
26637		let size = Math.sqrt( this._maxInstanceCount );
26638		size = Math.ceil( size );
26639
26640		const indirectArray = new Uint32Array( size * size );
26641		const indirectTexture = new DataTexture( indirectArray, size, size, RedIntegerFormat, UnsignedIntType );
26642
26643		this._indirectTexture = indirectTexture;
26644
26645	}
26646
26647	_initColorsTexture() {
26648
26649		let size = Math.sqrt( this._maxInstanceCount );
26650		size = Math.ceil( size );
26651
26652		// 4 floats per RGBA pixel initialized to white
26653		const colorsArray = new Float32Array( size * size * 4 ).fill( 1 );
26654		const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType );
26655		colorsTexture.colorSpace = ColorManagement.workingColorSpace;
26656
26657		this._colorsTexture = colorsTexture;
26658
26659	}
26660
26661	_initializeGeometry( reference ) {
26662
26663		const geometry = this.geometry;
26664		const maxVertexCount = this._maxVertexCount;
26665		const maxIndexCount = this._maxIndexCount;
26666		if ( this._geometryInitialized === false ) {
26667
26668			for ( const attributeName in reference.attributes ) {
26669
26670				const srcAttribute = reference.getAttribute( attributeName );
26671				const { array, itemSize, normalized } = srcAttribute;
26672
26673				const dstArray = new array.constructor( maxVertexCount * itemSize );
26674				const dstAttribute = new BufferAttribute( dstArray, itemSize, normalized );
26675
26676				geometry.setAttribute( attributeName, dstAttribute );
26677
26678			}
26679
26680			if ( reference.getIndex() !== null ) {
26681
26682				// Reserve last u16 index for primitive restart.
26683				const indexArray = maxVertexCount > 65535
26684					? new Uint32Array( maxIndexCount )
26685					: new Uint16Array( maxIndexCount );
26686
26687				geometry.setIndex( new BufferAttribute( indexArray, 1 ) );
26688
26689			}
26690
26691			this._geometryInitialized = true;
26692
26693		}
26694
26695	}
26696
26697	// Make sure the geometry is compatible with the existing combined geometry attributes
26698	_validateGeometry( geometry ) {
26699
26700		// check to ensure the geometries are using consistent attributes and indices
26701		const batchGeometry = this.geometry;
26702		if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
26703
26704			throw new Error( 'THREE.BatchedMesh: All geometries must consistently have "index".' );
26705
26706		}
26707
26708		for ( const attributeName in batchGeometry.attributes ) {
26709
26710			if ( ! geometry.hasAttribute( attributeName ) ) {
26711
26712				throw new Error( `THREE.BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` );
26713
26714			}
26715
26716			const srcAttribute = geometry.getAttribute( attributeName );
26717			const dstAttribute = batchGeometry.getAttribute( attributeName );
26718			if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
26719
26720				throw new Error( 'THREE.BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
26721
26722			}
26723
26724		}
26725
26726	}
26727
26728	/**
26729	 * Validates the instance defined by the given ID.
26730	 *
26731	 * @param {number} instanceId - The instance to validate.
26732	 */
26733	validateInstanceId( instanceId ) {
26734
26735		const instanceInfo = this._instanceInfo;
26736		if ( instanceId < 0 || instanceId >= instanceInfo.length || instanceInfo[ instanceId ].active === false ) {
26737
26738			throw new Error( `THREE.BatchedMesh: Invalid instanceId ${instanceId}. Instance is either out of range or has been deleted.` );
26739
26740		}
26741
26742	}
26743
26744	/**
26745	 * Validates the geometry defined by the given ID.
26746	 *
26747	 * @param {number} geometryId - The geometry to validate.
26748	 */
26749	validateGeometryId( geometryId ) {
26750
26751		const geometryInfoList = this._geometryInfo;
26752		if ( geometryId < 0 || geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
26753
26754			throw new Error( `THREE.BatchedMesh: Invalid geometryId ${geometryId}. Geometry is either out of range or has been deleted.` );
26755
26756		}
26757
26758	}
26759
26760	/**
26761	 * Takes a sort a function that is run before render. The function takes a list of instances to
26762	 * sort and a camera. The objects in the list include a "z" field to perform a depth-ordered sort with.
26763	 *
26764	 * @param {Function} func - The custom sort function.
26765	 * @return {BatchedMesh} A reference to this batched mesh.
26766	 */
26767	setCustomSort( func ) {
26768
26769		this.customSort = func;
26770		return this;
26771
26772	}
26773
26774	/**
26775	 * Computes the bounding box, updating {@link BatchedMesh#boundingBox}.
26776	 * Bounding boxes aren't computed by default. They need to be explicitly computed,
26777	 * otherwise they are `null`.
26778	 */
26779	computeBoundingBox() {
26780
26781		if ( this.boundingBox === null ) {
26782
26783			this.boundingBox = new Box3();
26784
26785		}
26786
26787		const boundingBox = this.boundingBox;
26788		const instanceInfo = this._instanceInfo;
26789
26790		boundingBox.makeEmpty();
26791		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
26792
26793			if ( instanceInfo[ i ].active === false ) continue;
26794
26795			const geometryId = instanceInfo[ i ].geometryIndex;
26796			this.getMatrixAt( i, _matrix$1 );
26797			this.getBoundingBoxAt( geometryId, _box$1 ).applyMatrix4( _matrix$1 );
26798			boundingBox.union( _box$1 );
26799
26800		}
26801
26802	}
26803
26804	/**
26805	 * Computes the bounding sphere, updating {@link BatchedMesh#boundingSphere}.
26806	 * Bounding spheres aren't computed by default. They need to be explicitly computed,
26807	 * otherwise they are `null`.
26808	 */
26809	computeBoundingSphere() {
26810
26811		if ( this.boundingSphere === null ) {
26812
26813			this.boundingSphere = new Sphere();
26814
26815		}
26816
26817		const boundingSphere = this.boundingSphere;
26818		const instanceInfo = this._instanceInfo;
26819
26820		boundingSphere.makeEmpty();
26821		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
26822
26823			if ( instanceInfo[ i ].active === false ) continue;
26824
26825			const geometryId = instanceInfo[ i ].geometryIndex;
26826			this.getMatrixAt( i, _matrix$1 );
26827			this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 );
26828			boundingSphere.union( _sphere$2 );
26829
26830		}
26831
26832	}
26833
26834	/**
26835	 * Adds a new instance to the batch using the geometry of the given ID and returns
26836	 * a new id referring to the new instance to be used by other functions.
26837	 *
26838	 * @param {number} geometryId - The ID of a previously added geometry via {@link BatchedMesh#addGeometry}.
26839	 * @return {number} The instance ID.
26840	 */
26841	addInstance( geometryId ) {
26842
26843		const atCapacity = this._instanceInfo.length >= this.maxInstanceCount;
26844
26845		// ensure we're not over geometry
26846		if ( atCapacity && this._availableInstanceIds.length === 0 ) {
26847
26848			throw new Error( 'THREE.BatchedMesh: Maximum item count reached.' );
26849
26850		}
26851
26852		const instanceInfo = {
26853			visible: true,
26854			active: true,
26855			geometryIndex: geometryId,
26856		};
26857
26858		let drawId = null;
26859
26860		// Prioritize using previously freed instance ids
26861		if ( this._availableInstanceIds.length > 0 ) {
26862
26863			this._availableInstanceIds.sort( ascIdSort );
26864
26865			drawId = this._availableInstanceIds.shift();
26866			this._instanceInfo[ drawId ] = instanceInfo;
26867
26868		} else {
26869
26870			drawId = this._instanceInfo.length;
26871			this._instanceInfo.push( instanceInfo );
26872
26873		}
26874
26875		const matricesTexture = this._matricesTexture;
26876		_matrix$1.identity().toArray( matricesTexture.image.data, drawId * 16 );
26877		matricesTexture.needsUpdate = true;
26878
26879		const colorsTexture = this._colorsTexture;
26880		if ( colorsTexture ) {
26881
26882			_whiteColor.toArray( colorsTexture.image.data, drawId * 4 );
26883			colorsTexture.needsUpdate = true;
26884
26885		}
26886
26887		this._visibilityChanged = true;
26888		return drawId;
26889
26890	}
26891
26892	/**
26893	 * Adds the given geometry to the batch and returns the associated
26894	 * geometry id referring to it to be used in other functions.
26895	 *
26896	 * @param {BufferGeometry} geometry - The geometry to add.
26897	 * @param {number} [reservedVertexCount=-1] - Optional parameter specifying the amount of
26898	 * vertex buffer space to reserve for the added geometry. This is necessary if it is planned
26899	 * to set a new geometry at this index at a later time that is larger than the original geometry.
26900	 * Defaults to the length of the given geometry vertex buffer.
26901	 * @param {number} [reservedIndexCount=-1] - Optional parameter specifying the amount of index
26902	 * buffer space to reserve for the added geometry. This is necessary if it is planned to set a
26903	 * new geometry at this index at a later time that is larger than the original geometry. Defaults to
26904	 * the length of the given geometry index buffer.
26905	 * @return {number} The geometry ID.
26906	 */
26907	addGeometry( geometry, reservedVertexCount = -1, reservedIndexCount = -1 ) {
26908
26909		this._initializeGeometry( geometry );
26910
26911		this._validateGeometry( geometry );
26912
26913		const geometryInfo = {
26914			// geometry information
26915			vertexStart: -1,
26916			vertexCount: -1,
26917			reservedVertexCount: -1,
26918
26919			indexStart: -1,
26920			indexCount: -1,
26921			reservedIndexCount: -1,
26922
26923			// draw range information
26924			start: -1,
26925			count: -1,
26926
26927			// state
26928			boundingBox: null,
26929			boundingSphere: null,
26930			active: true,
26931		};
26932
26933		const geometryInfoList = this._geometryInfo;
26934		geometryInfo.vertexStart = this._nextVertexStart;
26935		geometryInfo.reservedVertexCount = reservedVertexCount === -1 ? geometry.getAttribute( 'position' ).count : reservedVertexCount;
26936
26937		const index = geometry.getIndex();
26938		const hasIndex = index !== null;
26939		if ( hasIndex ) {
26940
26941			geometryInfo.indexStart = this._nextIndexStart;
26942			geometryInfo.reservedIndexCount = reservedIndexCount === -1 ? index.count : reservedIndexCount;
26943
26944		}
26945
26946		if (
26947			geometryInfo.indexStart !== -1 &&
26948			geometryInfo.indexStart + geometryInfo.reservedIndexCount > this._maxIndexCount ||
26949			geometryInfo.vertexStart + geometryInfo.reservedVertexCount > this._maxVertexCount
26950		) {
26951
26952			throw new Error( 'THREE.BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
26953
26954		}
26955
26956		// update id
26957		let geometryId;
26958		if ( this._availableGeometryIds.length > 0 ) {
26959
26960			this._availableGeometryIds.sort( ascIdSort );
26961
26962			geometryId = this._availableGeometryIds.shift();
26963			geometryInfoList[ geometryId ] = geometryInfo;
26964
26965
26966		} else {
26967
26968			geometryId = this._geometryCount;
26969			this._geometryCount ++;
26970			geometryInfoList.push( geometryInfo );
26971
26972		}
26973
26974		// update the geometry
26975		this.setGeometryAt( geometryId, geometry );
26976
26977		// increment the next geometry position
26978		this._nextIndexStart = geometryInfo.indexStart + geometryInfo.reservedIndexCount;
26979		this._nextVertexStart = geometryInfo.vertexStart + geometryInfo.reservedVertexCount;
26980
26981		return geometryId;
26982
26983	}
26984
26985	/**
26986	 * Replaces the geometry at the given ID with the provided geometry. Throws an error if there
26987	 * is not enough space reserved for geometry. Calling this will change all instances that are
26988	 * rendering that geometry.
26989	 *
26990	 * @param {number} geometryId - The ID of the geometry that should be replaced with the given geometry.
26991	 * @param {BufferGeometry} geometry - The new geometry.
26992	 * @return {number} The geometry ID.
26993	 */
26994	setGeometryAt( geometryId, geometry ) {
26995
26996		if ( geometryId >= this._geometryCount ) {
26997
26998			throw new Error( 'THREE.BatchedMesh: Maximum geometry count reached.' );
26999
27000		}
27001
27002		this._validateGeometry( geometry );
27003
27004		const batchGeometry = this.geometry;
27005		const hasIndex = batchGeometry.getIndex() !== null;
27006		const dstIndex = batchGeometry.getIndex();
27007		const srcIndex = geometry.getIndex();
27008		const geometryInfo = this._geometryInfo[ geometryId ];
27009		if (
27010			hasIndex &&
27011			srcIndex.count > geometryInfo.reservedIndexCount ||
27012			geometry.attributes.position.count > geometryInfo.reservedVertexCount
27013		) {
27014
27015			throw new Error( 'THREE.BatchedMesh: Reserved space not large enough for provided geometry.' );
27016
27017		}
27018
27019		// copy geometry buffer data over
27020		const vertexStart = geometryInfo.vertexStart;
27021		const reservedVertexCount = geometryInfo.reservedVertexCount;
27022		geometryInfo.vertexCount = geometry.getAttribute( 'position' ).count;
27023
27024		for ( const attributeName in batchGeometry.attributes ) {
27025
27026			// copy attribute data
27027			const srcAttribute = geometry.getAttribute( attributeName );
27028			const dstAttribute = batchGeometry.getAttribute( attributeName );
27029			copyAttributeData( srcAttribute, dstAttribute, vertexStart );
27030
27031			// fill the rest in with zeroes
27032			const itemSize = srcAttribute.itemSize;
27033			for ( let i = srcAttribute.count, l = reservedVertexCount; i < l; i ++ ) {
27034
27035				const index = vertexStart + i;
27036				for ( let c = 0; c < itemSize; c ++ ) {
27037
27038					dstAttribute.setComponent( index, c, 0 );
27039
27040				}
27041
27042			}
27043
27044			dstAttribute.needsUpdate = true;
27045			dstAttribute.addUpdateRange( vertexStart * itemSize, reservedVertexCount * itemSize );
27046
27047		}
27048
27049		// copy index
27050		if ( hasIndex ) {
27051
27052			const indexStart = geometryInfo.indexStart;
27053			const reservedIndexCount = geometryInfo.reservedIndexCount;
27054			geometryInfo.indexCount = geometry.getIndex().count;
27055
27056			// copy index data over
27057			for ( let i = 0; i < srcIndex.count; i ++ ) {
27058
27059				dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) );
27060
27061			}
27062
27063			// fill the rest in with zeroes
27064			for ( let i = srcIndex.count, l = reservedIndexCount; i < l; i ++ ) {
27065
27066				dstIndex.setX( indexStart + i, vertexStart );
27067
27068			}
27069
27070			dstIndex.needsUpdate = true;
27071			dstIndex.addUpdateRange( indexStart, geometryInfo.reservedIndexCount );
27072
27073		}
27074
27075		// update the draw range
27076		geometryInfo.start = hasIndex ? geometryInfo.indexStart : geometryInfo.vertexStart;
27077		geometryInfo.count = hasIndex ? geometryInfo.indexCount : geometryInfo.vertexCount;
27078
27079		// store the bounding boxes
27080		geometryInfo.boundingBox = null;
27081		if ( geometry.boundingBox !== null ) {
27082
27083			geometryInfo.boundingBox = geometry.boundingBox.clone();
27084
27085		}
27086
27087		geometryInfo.boundingSphere = null;
27088		if ( geometry.boundingSphere !== null ) {
27089
27090			geometryInfo.boundingSphere = geometry.boundingSphere.clone();
27091
27092		}
27093
27094		this._visibilityChanged = true;
27095		return geometryId;
27096
27097	}
27098
27099	/**
27100	 * Deletes the geometry defined by the given ID from this batch. Any instances referencing
27101	 * this geometry will also be removed as a side effect.
27102	 *
27103	 * @param {number} geometryId - The ID of the geometry to remove from the batch.
27104	 * @return {BatchedMesh} A reference to this batched mesh.
27105	 */
27106	deleteGeometry( geometryId ) {
27107
27108		const geometryInfoList = this._geometryInfo;
27109		if ( geometryId >= geometryInfoList.length || geometryInfoList[ geometryId ].active === false ) {
27110
27111			return this;
27112
27113		}
27114
27115		// delete any instances associated with this geometry
27116		const instanceInfo = this._instanceInfo;
27117		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
27118
27119			if ( instanceInfo[ i ].active && instanceInfo[ i ].geometryIndex === geometryId ) {
27120
27121				this.deleteInstance( i );
27122
27123			}
27124
27125		}
27126
27127		geometryInfoList[ geometryId ].active = false;
27128		this._availableGeometryIds.push( geometryId );
27129		this._visibilityChanged = true;
27130
27131		return this;
27132
27133	}
27134
27135	/**
27136	 * Deletes an existing instance from the batch using the given ID.
27137	 *
27138	 * @param {number} instanceId - The ID of the instance to remove from the batch.
27139	 * @return {BatchedMesh} A reference to this batched mesh.
27140	 */
27141	deleteInstance( instanceId ) {
27142
27143		this.validateInstanceId( instanceId );
27144
27145		this._instanceInfo[ instanceId ].active = false;
27146		this._availableInstanceIds.push( instanceId );
27147		this._visibilityChanged = true;
27148
27149		return this;
27150
27151	}
27152
27153	/**
27154	 * Repacks the sub geometries in BatchedMesh to remove any unused space remaining from
27155	 * previously deleted geometry, freeing up space to add new geometry.
27156	 *
27157	 * @return {BatchedMesh} A reference to this batched mesh.
27158	 */
27159	optimize() {
27160
27161		// track the next indices to copy data to
27162		let nextVertexStart = 0;
27163		let nextIndexStart = 0;
27164
27165		// Iterate over all geometry ranges in order sorted from earliest in the geometry buffer to latest
27166		// in the geometry buffer. Because draw range objects can be reused there is no guarantee of their order.
27167		const geometryInfoList = this._geometryInfo;
27168		const indices = geometryInfoList
27169			.map( ( e, i ) => i )
27170			.sort( ( a, b ) => {
27171
27172				return geometryInfoList[ a ].vertexStart - geometryInfoList[ b ].vertexStart;
27173
27174			} );
27175
27176		const geometry = this.geometry;
27177		for ( let i = 0, l = geometryInfoList.length; i < l; i ++ ) {
27178
27179			// if a geometry range is inactive then don't copy anything
27180			const index = indices[ i ];
27181			const geometryInfo = geometryInfoList[ index ];
27182			if ( geometryInfo.active === false ) {
27183
27184				continue;
27185
27186			}
27187
27188			// if a geometry contains an index buffer then shift it, as well
27189			if ( geometry.index !== null ) {
27190
27191				if ( geometryInfo.indexStart !== nextIndexStart ) {
27192
27193					const { indexStart, vertexStart, reservedIndexCount } = geometryInfo;
27194					const index = geometry.index;
27195					const array = index.array;
27196
27197					// shift the index pointers based on how the vertex data will shift
27198					// adjusting the index must happen first so the original vertex start value is available
27199					const elementDelta = nextVertexStart - vertexStart;
27200					for ( let j = indexStart; j < indexStart + reservedIndexCount; j ++ ) {
27201
27202						array[ j ] = array[ j ] + elementDelta;
27203
27204					}
27205
27206					index.array.copyWithin( nextIndexStart, indexStart, indexStart + reservedIndexCount );
27207					index.addUpdateRange( nextIndexStart, reservedIndexCount );
27208					index.needsUpdate = true;
27209
27210					geometryInfo.indexStart = nextIndexStart;
27211
27212				}
27213
27214				nextIndexStart += geometryInfo.reservedIndexCount;
27215
27216			}
27217
27218			// if a geometry needs to be moved then copy attribute data to overwrite unused space
27219			if ( geometryInfo.vertexStart !== nextVertexStart ) {
27220
27221				const { vertexStart, reservedVertexCount } = geometryInfo;
27222				const attributes = geometry.attributes;
27223				for ( const key in attributes ) {
27224
27225					const attribute = attributes[ key ];
27226					const { array, itemSize } = attribute;
27227					array.copyWithin( nextVertexStart * itemSize, vertexStart * itemSize, ( vertexStart + reservedVertexCount ) * itemSize );
27228					attribute.addUpdateRange( nextVertexStart * itemSize, reservedVertexCount * itemSize );
27229					attribute.needsUpdate = true;
27230
27231				}
27232
27233				geometryInfo.vertexStart = nextVertexStart;
27234
27235			}
27236
27237			nextVertexStart += geometryInfo.reservedVertexCount;
27238			geometryInfo.start = geometry.index ? geometryInfo.indexStart : geometryInfo.vertexStart;
27239
27240		}
27241
27242		this._nextIndexStart = nextIndexStart;
27243		this._nextVertexStart = nextVertexStart;
27244		this._visibilityChanged = true;
27245
27246		return this;
27247
27248	}
27249
27250	/**
27251	 * Returns the bounding box for the given geometry.
27252	 *
27253	 * @param {number} geometryId - The ID of the geometry to return the bounding box for.
27254	 * @param {Box3} target - The target object that is used to store the method's result.
27255	 * @return {?Box3} The geometry's bounding box. Returns `null` if no geometry has been found for the given ID.
27256	 */
27257	getBoundingBoxAt( geometryId, target ) {
27258
27259		if ( geometryId >= this._geometryCount ) {
27260
27261			return null;
27262
27263		}
27264
27265		// compute bounding box
27266		const geometry = this.geometry;
27267		const geometryInfo = this._geometryInfo[ geometryId ];
27268		if ( geometryInfo.boundingBox === null ) {
27269
27270			const box = new Box3();
27271			const index = geometry.index;
27272			const position = geometry.attributes.position;
27273			for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
27274
27275				let iv = i;
27276				if ( index ) {
27277
27278					iv = index.getX( iv );
27279
27280				}
27281
27282				box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) );
27283
27284			}
27285
27286			geometryInfo.boundingBox = box;
27287
27288		}
27289
27290		target.copy( geometryInfo.boundingBox );
27291		return target;
27292
27293	}
27294
27295	/**
27296	 * Returns the bounding sphere for the given geometry.
27297	 *
27298	 * @param {number} geometryId - The ID of the geometry to return the bounding sphere for.
27299	 * @param {Sphere} target - The target object that is used to store the method's result.
27300	 * @return {?Sphere} The geometry's bounding sphere. Returns `null` if no geometry has been found for the given ID.
27301	 */
27302	getBoundingSphereAt( geometryId, target ) {
27303
27304		if ( geometryId >= this._geometryCount ) {
27305
27306			return null;
27307
27308		}
27309
27310		// compute bounding sphere
27311		const geometry = this.geometry;
27312		const geometryInfo = this._geometryInfo[ geometryId ];
27313		if ( geometryInfo.boundingSphere === null ) {
27314
27315			const sphere = new Sphere();
27316			this.getBoundingBoxAt( geometryId, _box$1 );
27317			_box$1.getCenter( sphere.center );
27318
27319			const index = geometry.index;
27320			const position = geometry.attributes.position;
27321
27322			let maxRadiusSq = 0;
27323			for ( let i = geometryInfo.start, l = geometryInfo.start + geometryInfo.count; i < l; i ++ ) {
27324
27325				let iv = i;
27326				if ( index ) {
27327
27328					iv = index.getX( iv );
27329
27330				}
27331
27332				_vector$5.fromBufferAttribute( position, iv );
27333				maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) );
27334
27335			}
27336
27337			sphere.radius = Math.sqrt( maxRadiusSq );
27338			geometryInfo.boundingSphere = sphere;
27339
27340		}
27341
27342		target.copy( geometryInfo.boundingSphere );
27343		return target;
27344
27345	}
27346
27347	/**
27348	 * Sets the given local transformation matrix to the defined instance.
27349	 * Negatively scaled matrices are not supported.
27350	 *
27351	 * @param {number} instanceId - The ID of an instance to set the matrix of.
27352	 * @param {Matrix4} matrix - A 4x4 matrix representing the local transformation of a single instance.
27353	 * @return {BatchedMesh} A reference to this batched mesh.
27354	 */
27355	setMatrixAt( instanceId, matrix ) {
27356
27357		this.validateInstanceId( instanceId );
27358
27359		const matricesTexture = this._matricesTexture;
27360		const matricesArray = this._matricesTexture.image.data;
27361		matrix.toArray( matricesArray, instanceId * 16 );
27362		matricesTexture.needsUpdate = true;
27363
27364		return this;
27365
27366	}
27367
27368	/**
27369	 * Returns the local transformation matrix of the defined instance.
27370	 *
27371	 * @param {number} instanceId - The ID of an instance to get the matrix of.
27372	 * @param {Matrix4} matrix - The target object that is used to store the method's result.
27373	 * @return {Matrix4} The instance's local transformation matrix.
27374	 */
27375	getMatrixAt( instanceId, matrix ) {
27376
27377		this.validateInstanceId( instanceId );
27378		return matrix.fromArray( this._matricesTexture.image.data, instanceId * 16 );
27379
27380	}
27381
27382	/**
27383	 * Sets the given color to the defined instance.
27384	 *
27385	 * @param {number} instanceId - The ID of an instance to set the color of.
27386	 * @param {Color|Vector4} color - The color to set the instance to. Use a `Vector4` to also define alpha.
27387	 * @return {BatchedMesh} A reference to this batched mesh.
27388	 */
27389	setColorAt( instanceId, color ) {
27390
27391		this.validateInstanceId( instanceId );
27392
27393		if ( this._colorsTexture === null ) {
27394
27395			this._initColorsTexture();
27396
27397		}
27398
27399		color.toArray( this._colorsTexture.image.data, instanceId * 4 );
27400		this._colorsTexture.needsUpdate = true;
27401
27402		return this;
27403
27404	}
27405
27406	/**
27407	 * Returns the color of the defined instance.
27408	 *
27409	 * @param {number} instanceId - The ID of an instance to get the color of.
27410	 * @param {Color|Vector4} color - The target object that is used to store the method's result.
27411	 * @return {Color|Vector4} The instance's color.  Use a `Vector4` to also retrieve alpha.
27412	 */
27413	getColorAt( instanceId, color ) {
27414
27415		this.validateInstanceId( instanceId );
27416		if ( this._colorsTexture === null ) {
27417
27418			if ( color.isVector4 ) {
27419
27420				return color.set( 1, 1, 1, 1 );
27421
27422			} else {
27423
27424				return color.setRGB( 1, 1, 1 );
27425
27426			}
27427
27428		} else {
27429
27430			return color.fromArray( this._colorsTexture.image.data, instanceId * 4 );
27431
27432		}
27433
27434	}
27435
27436	/**
27437	 * Sets the visibility of the instance.
27438	 *
27439	 * @param {number} instanceId - The id of the instance to set the visibility of.
27440	 * @param {boolean} visible - Whether the instance is visible or not.
27441	 * @return {BatchedMesh} A reference to this batched mesh.
27442	 */
27443	setVisibleAt( instanceId, visible ) {
27444
27445		this.validateInstanceId( instanceId );
27446
27447		if ( this._instanceInfo[ instanceId ].visible === visible ) {
27448
27449			return this;
27450
27451		}
27452
27453		this._instanceInfo[ instanceId ].visible = visible;
27454		this._visibilityChanged = true;
27455
27456		return this;
27457
27458	}
27459
27460	/**
27461	 * Returns the visibility state of the defined instance.
27462	 *
27463	 * @param {number} instanceId - The ID of an instance to get the visibility state of.
27464	 * @return {boolean} Whether the instance is visible or not.
27465	 */
27466	getVisibleAt( instanceId ) {
27467
27468		this.validateInstanceId( instanceId );
27469
27470		return this._instanceInfo[ instanceId ].visible;
27471
27472	}
27473
27474	/**
27475	 * Sets the geometry ID of the instance at the given index.
27476	 *
27477	 * @param {number} instanceId - The ID of the instance to set the geometry ID of.
27478	 * @param {number} geometryId - The geometry ID to be use by the instance.
27479	 * @return {BatchedMesh} A reference to this batched mesh.
27480	 */
27481	setGeometryIdAt( instanceId, geometryId ) {
27482
27483		this.validateInstanceId( instanceId );
27484		this.validateGeometryId( geometryId );
27485
27486		this._instanceInfo[ instanceId ].geometryIndex = geometryId;
27487		this._visibilityChanged = true;
27488
27489		return this;
27490
27491	}
27492
27493	/**
27494	 * Returns the geometry ID of the defined instance.
27495	 *
27496	 * @param {number} instanceId - The ID of an instance to get the geometry ID of.
27497	 * @return {number} The instance's geometry ID.
27498	 */
27499	getGeometryIdAt( instanceId ) {
27500
27501		this.validateInstanceId( instanceId );
27502
27503		return this._instanceInfo[ instanceId ].geometryIndex;
27504
27505	}
27506
27507	/**
27508	 * Get the range representing the subset of triangles related to the attached geometry,
27509	 * indicating the starting offset and count, or `null` if invalid.
27510	 *
27511	 * @param {number} geometryId - The id of the geometry to get the range of.
27512	 * @param {Object} [target] - The target object that is used to store the method's result.
27513	 * @return {{
27514	 * 	vertexStart:number,vertexCount:number,reservedVertexCount:number,
27515	 * 	indexStart:number,indexCount:number,reservedIndexCount:number,
27516	 * 	start:number,count:number
27517	 * }} The result object with range data.
27518	 */
27519	getGeometryRangeAt( geometryId, target = {} ) {
27520
27521		this.validateGeometryId( geometryId );
27522
27523		const geometryInfo = this._geometryInfo[ geometryId ];
27524		target.vertexStart = geometryInfo.vertexStart;
27525		target.vertexCount = geometryInfo.vertexCount;
27526		target.reservedVertexCount = geometryInfo.reservedVertexCount;
27527
27528		target.indexStart = geometryInfo.indexStart;
27529		target.indexCount = geometryInfo.indexCount;
27530		target.reservedIndexCount = geometryInfo.reservedIndexCount;
27531
27532		target.start = geometryInfo.start;
27533		target.count = geometryInfo.count;
27534
27535		return target;
27536
27537	}
27538
27539	/**
27540	 * Resizes the necessary buffers to support the provided number of instances.
27541	 * If the provided arguments shrink the number of instances but there are not enough
27542	 * unused Ids at the end of the list then an error is thrown.
27543	 *
27544	 * @param {number} maxInstanceCount - The max number of individual instances that can be added and rendered by the batch.
27545	*/
27546	setInstanceCount( maxInstanceCount ) {
27547
27548		// shrink the available instances as much as possible
27549		const availableInstanceIds = this._availableInstanceIds;
27550		const instanceInfo = this._instanceInfo;
27551		availableInstanceIds.sort( ascIdSort );
27552		while ( availableInstanceIds[ availableInstanceIds.length - 1 ] === instanceInfo.length - 1 ) {
27553
27554			instanceInfo.pop();
27555			availableInstanceIds.pop();
27556
27557		}
27558
27559		// throw an error if it can't be shrunk to the desired size
27560		if ( maxInstanceCount < instanceInfo.length ) {
27561
27562			throw new Error( `THREE.BatchedMesh: Instance ids outside the range ${ maxInstanceCount } are being used. Cannot shrink instance count.` );
27563
27564		}
27565
27566		// copy the multi draw counts
27567		const multiDrawCounts = new Int32Array( maxInstanceCount );
27568		const multiDrawStarts = new Int32Array( maxInstanceCount );
27569		copyArrayContents( this._multiDrawCounts, multiDrawCounts );
27570		copyArrayContents( this._multiDrawStarts, multiDrawStarts );
27571
27572		this._multiDrawCounts = multiDrawCounts;
27573		this._multiDrawStarts = multiDrawStarts;
27574		this._maxInstanceCount = maxInstanceCount;
27575
27576		// update texture data for instance sampling
27577		const indirectTexture = this._indirectTexture;
27578		const matricesTexture = this._matricesTexture;
27579		const colorsTexture = this._colorsTexture;
27580
27581		indirectTexture.dispose();
27582		this._initIndirectTexture();
27583		copyArrayContents( indirectTexture.image.data, this._indirectTexture.image.data );
27584
27585		matricesTexture.dispose();
27586		this._initMatricesTexture();
27587		copyArrayContents( matricesTexture.image.data, this._matricesTexture.image.data );
27588
27589		if ( colorsTexture ) {
27590
27591			colorsTexture.dispose();
27592			this._initColorsTexture();
27593			copyArrayContents( colorsTexture.image.data, this._colorsTexture.image.data );
27594
27595		}
27596
27597	}
27598
27599	/**
27600	 * Resizes the available space in the batch's vertex and index buffer attributes to the provided sizes.
27601	 * If the provided arguments shrink the geometry buffers but there is not enough unused space at the
27602	 * end of the geometry attributes then an error is thrown.
27603	 *
27604	 * @param {number} maxVertexCount - The maximum number of vertices to be used by all unique geometries to resize to.
27605	 * @param {number} maxIndexCount - The maximum number of indices to be used by all unique geometries to resize to.
27606	*/
27607	setGeometrySize( maxVertexCount, maxIndexCount ) {
27608
27609		// Check if we can shrink to the requested vertex attribute size
27610		const validRanges = [ ...this._geometryInfo ].filter( info => info.active );
27611		const requiredVertexLength = Math.max( ...validRanges.map( range => range.vertexStart + range.reservedVertexCount ) );
27612		if ( requiredVertexLength > maxVertexCount ) {
27613
27614			throw new Error( `THREE.BatchedMesh: Geometry vertex values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
27615
27616		}
27617
27618		// Check if we can shrink to the requested index attribute size
27619		if ( this.geometry.index ) {
27620
27621			const requiredIndexLength = Math.max( ...validRanges.map( range => range.indexStart + range.reservedIndexCount ) );
27622			if ( requiredIndexLength > maxIndexCount ) {
27623
27624				throw new Error( `THREE.BatchedMesh: Geometry index values are being used outside the range ${ maxIndexCount }. Cannot shrink further.` );
27625
27626			}
27627
27628		}
27629
27630		//
27631
27632		// dispose of the previous geometry
27633		const oldGeometry = this.geometry;
27634		oldGeometry.dispose();
27635
27636		// recreate the geometry needed based on the previous variant
27637		this._maxVertexCount = maxVertexCount;
27638		this._maxIndexCount = maxIndexCount;
27639
27640		if ( this._geometryInitialized ) {
27641
27642			this._geometryInitialized = false;
27643			this.geometry = new BufferGeometry();
27644			this._initializeGeometry( oldGeometry );
27645
27646		}
27647
27648		// copy data from the previous geometry
27649		const geometry = this.geometry;
27650		if ( oldGeometry.index ) {
27651
27652			copyArrayContents( oldGeometry.index.array, geometry.index.array );
27653
27654		}
27655
27656		for ( const key in oldGeometry.attributes ) {
27657
27658			copyArrayContents( oldGeometry.attributes[ key ].array, geometry.attributes[ key ].array );
27659
27660		}
27661
27662	}
27663
27664	raycast( raycaster, intersects ) {
27665
27666		const instanceInfo = this._instanceInfo;
27667		const geometryInfoList = this._geometryInfo;
27668		const matrixWorld = this.matrixWorld;
27669		const batchGeometry = this.geometry;
27670
27671		// iterate over each geometry
27672		_mesh.material = this.material;
27673		_mesh.geometry.index = batchGeometry.index;
27674		_mesh.geometry.attributes = batchGeometry.attributes;
27675		if ( _mesh.geometry.boundingBox === null ) {
27676
27677			_mesh.geometry.boundingBox = new Box3();
27678
27679		}
27680
27681		if ( _mesh.geometry.boundingSphere === null ) {
27682
27683			_mesh.geometry.boundingSphere = new Sphere();
27684
27685		}
27686
27687		for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
27688
27689			if ( ! instanceInfo[ i ].visible || ! instanceInfo[ i ].active ) {
27690
27691				continue;
27692
27693			}
27694
27695			const geometryId = instanceInfo[ i ].geometryIndex;
27696			const geometryInfo = geometryInfoList[ geometryId ];
27697			_mesh.geometry.setDrawRange( geometryInfo.start, geometryInfo.count );
27698
27699			// get the intersects
27700			this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld );
27701			this.getBoundingBoxAt( geometryId, _mesh.geometry.boundingBox );
27702			this.getBoundingSphereAt( geometryId, _mesh.geometry.boundingSphere );
27703			_mesh.raycast( raycaster, _batchIntersects );
27704
27705			// add batch id to the intersects
27706			for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) {
27707
27708				const intersect = _batchIntersects[ j ];
27709				intersect.object = this;
27710				intersect.batchId = i;
27711				intersects.push( intersect );
27712
27713			}
27714
27715			_batchIntersects.length = 0;
27716
27717		}
27718
27719		_mesh.material = null;
27720		_mesh.geometry.index = null;
27721		_mesh.geometry.attributes = {};
27722		_mesh.geometry.setDrawRange( 0, Infinity );
27723
27724	}
27725
27726	copy( source ) {
27727
27728		super.copy( source );
27729
27730		this.geometry = source.geometry.clone();
27731		this.perObjectFrustumCulled = source.perObjectFrustumCulled;
27732		this.sortObjects = source.sortObjects;
27733		this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null;
27734		this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null;
27735
27736		this._geometryInfo = source._geometryInfo.map( info => ( {
27737			...info,
27738
27739			boundingBox: info.boundingBox !== null ? info.boundingBox.clone() : null,
27740			boundingSphere: info.boundingSphere !== null ? info.boundingSphere.clone() : null,
27741		} ) );
27742		this._instanceInfo = source._instanceInfo.map( info => ( { ...info } ) );
27743
27744		this._availableInstanceIds = source._availableInstanceIds.slice();
27745		this._availableGeometryIds = source._availableGeometryIds.slice();
27746
27747		this._nextIndexStart = source._nextIndexStart;
27748		this._nextVertexStart = source._nextVertexStart;
27749		this._geometryCount = source._geometryCount;
27750
27751		this._maxInstanceCount = source._maxInstanceCount;
27752		this._maxVertexCount = source._maxVertexCount;
27753		this._maxIndexCount = source._maxIndexCount;
27754
27755		this._geometryInitialized = source._geometryInitialized;
27756		this._multiDrawCounts = source._multiDrawCounts.slice();
27757		this._multiDrawStarts = source._multiDrawStarts.slice();
27758		this._multiDrawBytesPerElement = source._multiDrawBytesPerElement;
27759
27760		this._indirectTexture = source._indirectTexture.clone();
27761		this._indirectTexture.image.data = this._indirectTexture.image.data.slice();
27762
27763		this._matricesTexture = source._matricesTexture.clone();
27764		this._matricesTexture.image.data = this._matricesTexture.image.data.slice();
27765
27766		if ( this._colorsTexture !== null ) {
27767
27768			this._colorsTexture = source._colorsTexture.clone();
27769			this._colorsTexture.image.data = this._colorsTexture.image.data.slice();
27770
27771		}
27772
27773		return this;
27774
27775	}
27776
27777	/**
27778	 * Frees the GPU-related resources allocated by this instance. Call this
27779	 * method whenever this instance is no longer used in your app.
27780	 */
27781	dispose() {
27782
27783		super.dispose();
27784
27785		// Assuming the geometry is not shared with other meshes
27786		this.geometry.dispose();
27787
27788		this._matricesTexture.dispose();
27789		this._matricesTexture = null;
27790
27791		this._indirectTexture.dispose();
27792		this._indirectTexture = null;
27793
27794		if ( this._colorsTexture !== null ) {
27795
27796			this._colorsTexture.dispose();
27797			this._colorsTexture = null;
27798
27799		}
27800
27801	}
27802
27803	onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) {
27804
27805		// if visibility has not changed and frustum culling and object sorting is not required
27806		// then skip iterating over all items
27807		if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) {
27808
27809			return;
27810
27811		}
27812
27813		// the indexed version of the multi draw function requires specifying the start
27814		// offset in bytes.
27815		const index = geometry.getIndex();
27816		let bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT;
27817
27818
27819		// the "wireframe" attribute implicitly creates a line attribute in the renderer, which is double
27820		// the vertices to draw (3 lines per triangle) so we multiply the draw counts / starts and make
27821		// assumptions about the index buffer byte size.
27822		let multiDrawMultiplier = 1;
27823		if ( material.wireframe ) {
27824
27825			multiDrawMultiplier = 2;
27826			bytesPerElement = geometry.attributes.position.count > 65535 ? 4 : 2;
27827
27828		}
27829
27830		const instanceInfo = this._instanceInfo;
27831		const multiDrawStarts = this._multiDrawStarts;
27832		const multiDrawCounts = this._multiDrawCounts;
27833		const geometryInfoList = this._geometryInfo;
27834		const perObjectFrustumCulled = this.perObjectFrustumCulled;
27835		const indirectTexture = this._indirectTexture;
27836		const indirectArray = indirectTexture.image.data;
27837
27838		const frustum = camera.isArrayCamera ? _frustumArray : _frustum;
27839		// prepare the frustum in the local frame
27840		if ( perObjectFrustumCulled ) {
27841
27842			if ( camera.isArrayCamera ) {
27843
27844				frustum.setFromArrayCamera( camera );
27845
27846			} else {
27847
27848				_matrix$1
27849					.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse )
27850					.multiply( this.matrixWorld );
27851
27852				frustum.setFromProjectionMatrix(
27853					_matrix$1,
27854					camera.coordinateSystem,
27855					camera.reversedDepth
27856				);
27857
27858			}
27859
27860		}
27861
27862		let multiDrawCount = 0;
27863		if ( this.sortObjects ) {
27864
27865			// get the camera position in the local frame
27866			_matrix$1.copy( this.matrixWorld ).invert();
27867			_vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _matrix$1 );
27868			_forward$1.set( 0, 0, -1 ).transformDirection( camera.matrixWorld ).transformDirection( _matrix$1 );
27869
27870			for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
27871
27872				if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
27873
27874					const geometryId = instanceInfo[ i ].geometryIndex;
27875
27876					// get the bounds in world space
27877					this.getMatrixAt( i, _matrix$1 );
27878					this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 );
27879
27880					// determine whether the batched geometry is within the frustum
27881					let culled = false;
27882					if ( perObjectFrustumCulled ) {
27883
27884						culled = ! frustum.intersectsSphere( _sphere$2 );
27885
27886					}
27887
27888					if ( ! culled ) {
27889
27890						// get the distance from camera used for sorting
27891						const geometryInfo = geometryInfoList[ geometryId ];
27892						const z = _temp.subVectors( _sphere$2.center, _vector$5 ).dot( _forward$1 );
27893						_renderList.push( geometryInfo.start, geometryInfo.count, z, i );
27894
27895					}
27896
27897				}
27898
27899			}
27900
27901			// Sort the draw ranges and prep for rendering
27902			const list = _renderList.list;
27903			const customSort = this.customSort;
27904			if ( customSort === null ) {
27905
27906				list.sort( material.transparent ? sortTransparent : sortOpaque );
27907
27908			} else {
27909
27910				customSort.call( this, list, camera );
27911
27912			}
27913
27914			for ( let i = 0, l = list.length; i < l; i ++ ) {
27915
27916				const item = list[ i ];
27917				multiDrawStarts[ multiDrawCount ] = item.start * bytesPerElement * multiDrawMultiplier;
27918				multiDrawCounts[ multiDrawCount ] = item.count * multiDrawMultiplier;
27919				indirectArray[ multiDrawCount ] = item.index;
27920				multiDrawCount ++;
27921
27922			}
27923
27924			_renderList.reset();
27925
27926		} else {
27927
27928			for ( let i = 0, l = instanceInfo.length; i < l; i ++ ) {
27929
27930				if ( instanceInfo[ i ].visible && instanceInfo[ i ].active ) {
27931
27932					const geometryId = instanceInfo[ i ].geometryIndex;
27933
27934					// determine whether the batched geometry is within the frustum
27935					let culled = false;
27936					if ( perObjectFrustumCulled ) {
27937
27938						// get the bounds in world space
27939						this.getMatrixAt( i, _matrix$1 );
27940						this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 );
27941						culled = ! frustum.intersectsSphere( _sphere$2 );
27942
27943					}
27944
27945					if ( ! culled ) {
27946
27947						const geometryInfo = geometryInfoList[ geometryId ];
27948						multiDrawStarts[ multiDrawCount ] = geometryInfo.start * bytesPerElement * multiDrawMultiplier;
27949						multiDrawCounts[ multiDrawCount ] = geometryInfo.count * multiDrawMultiplier;
27950						indirectArray[ multiDrawCount ] = i;
27951						multiDrawCount ++;
27952
27953					}
27954
27955				}
27956
27957			}
27958
27959		}
27960
27961		indirectTexture.needsUpdate = true;
27962		this._multiDrawCount = multiDrawCount;
27963		this._multiDrawBytesPerElement = bytesPerElement;
27964		this._visibilityChanged = false;
27965
27966	}
27967
27968	onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) {
27969
27970		this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial );
27971
27972	}
27973
27974}
27975
27976/**
27977 * A material for rendering line primitives.
27978 *
27979 * Materials define the appearance of renderable 3D objects.
27980 *
27981 * ```js
27982 * const material = new THREE.LineBasicMaterial( { color: 0xffffff } );
27983 * ```
27984 *
27985 * @augments Material
27986 */
27987class LineBasicMaterial extends Material {
27988
27989	/**
27990	 * Constructs a new line basic material.
27991	 *
27992	 * @param {Object} [parameters] - An object with one or more properties
27993	 * defining the material's appearance. Any property of the material
27994	 * (including any property from inherited materials) can be passed
27995	 * in here. Color values can be passed any type of value accepted
27996	 * by {@link Color#set}.
27997	 */
27998	constructor( parameters ) {
27999
28000		super();
28001
28002		/**
28003		 * This flag can be used for type testing.
28004		 *
28005		 * @type {boolean}
28006		 * @readonly
28007		 * @default true
28008		 */
28009		this.isLineBasicMaterial = true;
28010
28011		this.type = 'LineBasicMaterial';
28012
28013		/**
28014		 * Color of the material.
28015		 *
28016		 * @type {Color}
28017		 * @default (1,1,1)
28018		 */
28019		this.color = new Color( 0xffffff );
28020
28021		/**
28022		 * Sets the color of the lines using data from a texture. The texture map
28023		 * color is modulated by the diffuse `color`.
28024		 *
28025		 * `map` represents color data, and the texture must be assigned a
28026		 * {@link Texture#colorSpace}. Most `map` textures set
28027		 * `texture.colorSpace = SRGBColorSpace`.
28028		 *
28029		 * @type {?Texture}
28030		 * @default null
28031		 */
28032		this.map = null;
28033
28034		/**
28035		 * Controls line thickness or lines.
28036		 *
28037		 * Can only be used with {@link SVGRenderer}. WebGL and WebGPU
28038		 * ignore this setting and always render line primitives with a
28039		 * width of one pixel.
28040		 *
28041		 * @type {number}
28042		 * @default 1
28043		 */
28044		this.linewidth = 1;
28045
28046		/**
28047		 * Defines appearance of line ends.
28048		 *
28049		 * Can only be used with {@link SVGRenderer}.
28050		 *
28051		 * @type {('butt'|'round'|'square')}
28052		 * @default 'round'
28053		 */
28054		this.linecap = 'round';
28055
28056		/**
28057		 * Defines appearance of line joints.
28058		 *
28059		 * Can only be used with {@link SVGRenderer}.
28060		 *
28061		 * @type {('round'|'bevel'|'miter')}
28062		 * @default 'round'
28063		 */
28064		this.linejoin = 'round';
28065
28066		/**
28067		 * Whether the material is affected by fog or not.
28068		 *
28069		 * @type {boolean}
28070		 * @default true
28071		 */
28072		this.fog = true;
28073
28074		this.setValues( parameters );
28075
28076	}
28077
28078	copy( source ) {
28079
28080		super.copy( source );
28081
28082		this.color.copy( source.color );
28083
28084		this.map = source.map;
28085
28086		this.linewidth = source.linewidth;
28087		this.linecap = source.linecap;
28088		this.linejoin = source.linejoin;
28089
28090		this.fog = source.fog;
28091
28092		return this;
28093
28094	}
28095
28096}
28097
28098const _vStart = /*@__PURE__*/ new Vector3();
28099const _vEnd = /*@__PURE__*/ new Vector3();
28100
28101const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4();
28102const _ray$1 = /*@__PURE__*/ new Ray();
28103const _sphere$1 = /*@__PURE__*/ new Sphere();
28104
28105const _intersectPointOnRay = /*@__PURE__*/ new Vector3();
28106const _intersectPointOnSegment = /*@__PURE__*/ new Vector3();
28107
28108/**
28109 * A continuous line. The line are rendered by connecting consecutive
28110 * vertices with straight lines.
28111 *
28112 * ```js
28113 * const material = new THREE.LineBasicMaterial( { color: 0x0000ff } );
28114 *
28115 * const points = [];
28116 * points.push( new THREE.Vector3( - 10, 0, 0 ) );
28117 * points.push( new THREE.Vector3( 0, 10, 0 ) );
28118 * points.push( new THREE.Vector3( 10, 0, 0 ) );
28119 *
28120 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
28121 *
28122 * const line = new THREE.Line( geometry, material );
28123 * scene.add( line );
28124 * ```
28125 *
28126 * @augments Object3D
28127 */
28128class Line extends Object3D {
28129
28130	/**
28131	 * Constructs a new line.
28132	 *
28133	 * @param {BufferGeometry} [geometry] - The line geometry.
28134	 * @param {Material|Array<Material>} [material] - The line material.
28135	 */
28136	constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) {
28137
28138		super();
28139
28140		/**
28141		 * This flag can be used for type testing.
28142		 *
28143		 * @type {boolean}
28144		 * @readonly
28145		 * @default true
28146		 */
28147		this.isLine = true;
28148
28149		this.type = 'Line';
28150
28151		/**
28152		 * The line geometry.
28153		 *
28154		 * @type {BufferGeometry}
28155		 */
28156		this.geometry = geometry;
28157
28158		/**
28159		 * The line material.
28160		 *
28161		 * @type {Material|Array<Material>}
28162		 * @default LineBasicMaterial
28163		 */
28164		this.material = material;
28165
28166		/**
28167		 * A dictionary representing the morph targets in the geometry. The key is the
28168		 * morph targets name, the value its attribute index. This member is `undefined`
28169		 * by default and only set when morph targets are detected in the geometry.
28170		 *
28171		 * @type {Object<string,number>|undefined}
28172		 * @default undefined
28173		 */
28174		this.morphTargetDictionary = undefined;
28175
28176		/**
28177		 * An array of weights typically in the range `[0,1]` that specify how much of the morph
28178		 * is applied. This member is `undefined` by default and only set when morph targets are
28179		 * detected in the geometry.
28180		 *
28181		 * @type {Array<number>|undefined}
28182		 * @default undefined
28183		 */
28184		this.morphTargetInfluences = undefined;
28185
28186		this.updateMorphTargets();
28187
28188	}
28189
28190	copy( source, recursive ) {
28191
28192		super.copy( source, recursive );
28193
28194		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
28195		this.geometry = source.geometry;
28196
28197		return this;
28198
28199	}
28200
28201	/**
28202	 * Computes an array of distance values which are necessary for rendering dashed lines.
28203	 * For each vertex in the geometry, the method calculates the cumulative length from the
28204	 * current point to the very beginning of the line.
28205	 *
28206	 * @return {Line} A reference to this line.
28207	 */
28208	computeLineDistances() {
28209
28210		const geometry = this.geometry;
28211
28212		// we assume non-indexed geometry
28213
28214		if ( geometry.index === null ) {
28215
28216			const positionAttribute = geometry.attributes.position;
28217			const lineDistances = [ 0 ];
28218
28219			for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) {
28220
28221				_vStart.fromBufferAttribute( positionAttribute, i - 1 );
28222				_vEnd.fromBufferAttribute( positionAttribute, i );
28223
28224				lineDistances[ i ] = lineDistances[ i - 1 ];
28225				lineDistances[ i ] += _vStart.distanceTo( _vEnd );
28226
28227			}
28228
28229			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
28230
28231		} else {
28232
28233			warn( 'Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
28234
28235		}
28236
28237		return this;
28238
28239	}
28240
28241	/**
28242	 * Returns `true` if this line intersects the given frustum.
28243	 *
28244	 * @param {Frustum|FrustumArray} frustum - The frustum to test.
28245	 * @return {boolean} Whether this line intersects the given frustum or not.
28246	 */
28247	intersectsFrustum( frustum ) {
28248
28249		return frustum.intersectsObject( this );
28250
28251	}
28252
28253	/**
28254	 * Computes intersection points between a casted ray and this line.
28255	 *
28256	 * @param {Raycaster} raycaster - The raycaster.
28257	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
28258	 */
28259	raycast( raycaster, intersects ) {
28260
28261		const geometry = this.geometry;
28262		const matrixWorld = this.matrixWorld;
28263		const threshold = raycaster.params.Line.threshold;
28264		const drawRange = geometry.drawRange;
28265
28266		// Checking boundingSphere distance to ray
28267
28268		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
28269
28270		_sphere$1.copy( geometry.boundingSphere );
28271		_sphere$1.applyMatrix4( matrixWorld );
28272		_sphere$1.radius += threshold;
28273
28274		if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return;
28275
28276		//
28277
28278		_inverseMatrix$1.copy( matrixWorld ).invert();
28279		_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
28280
28281		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
28282		const localThresholdSq = localThreshold * localThreshold;
28283
28284		const step = this.isLineSegments ? 2 : 1;
28285
28286		const index = geometry.index;
28287		const attributes = geometry.attributes;
28288		const positionAttribute = attributes.position;
28289
28290		if ( index !== null ) {
28291
28292			const start = Math.max( 0, drawRange.start );
28293			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
28294
28295			for ( let i = start, l = end - 1; i < l; i += step ) {
28296
28297				const a = index.getX( i );
28298				const b = index.getX( i + 1 );
28299
28300				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b, i );
28301
28302				if ( intersect ) {
28303
28304					intersects.push( intersect );
28305
28306				}
28307
28308			}
28309
28310			if ( this.isLineLoop ) {
28311
28312				const a = index.getX( end - 1 );
28313				const b = index.getX( start );
28314
28315				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b, end - 1 );
28316
28317				if ( intersect ) {
28318
28319					intersects.push( intersect );
28320
28321				}
28322
28323			}
28324
28325		} else {
28326
28327			const start = Math.max( 0, drawRange.start );
28328			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
28329
28330			for ( let i = start, l = end - 1; i < l; i += step ) {
28331
28332				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1, i );
28333
28334				if ( intersect ) {
28335
28336					intersects.push( intersect );
28337
28338				}
28339
28340			}
28341
28342			if ( this.isLineLoop ) {
28343
28344				const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start, end - 1 );
28345
28346				if ( intersect ) {
28347
28348					intersects.push( intersect );
28349
28350				}
28351
28352			}
28353
28354		}
28355
28356	}
28357
28358	/**
28359	 * Sets the values of {@link Line#morphTargetDictionary} and {@link Line#morphTargetInfluences}
28360	 * to make sure existing morph targets can influence this 3D object.
28361	 */
28362	updateMorphTargets() {
28363
28364		const geometry = this.geometry;
28365
28366		const morphAttributes = geometry.morphAttributes;
28367		const keys = Object.keys( morphAttributes );
28368
28369		if ( keys.length > 0 ) {
28370
28371			const morphAttribute = morphAttributes[ keys[ 0 ] ];
28372
28373			if ( morphAttribute !== undefined ) {
28374
28375				this.morphTargetInfluences = [];
28376				this.morphTargetDictionary = {};
28377
28378				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
28379
28380					const name = morphAttribute[ m ].name || String( m );
28381
28382					this.morphTargetInfluences.push( 0 );
28383					this.morphTargetDictionary[ name ] = m;
28384
28385				}
28386
28387			}
28388
28389		}
28390
28391	}
28392
28393}
28394
28395function checkIntersection( object, raycaster, ray, thresholdSq, a, b, i ) {
28396
28397	const positionAttribute = object.geometry.attributes.position;
28398
28399	_vStart.fromBufferAttribute( positionAttribute, a );
28400	_vEnd.fromBufferAttribute( positionAttribute, b );
28401
28402	const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment );
28403
28404	if ( distSq > thresholdSq ) return;
28405
28406	_intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation
28407
28408	const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay );
28409
28410	if ( distance < raycaster.near || distance > raycaster.far ) return;
28411
28412	return {
28413
28414		distance: distance,
28415		// What do we want? intersection point on the ray or on the segment??
28416		// point: raycaster.ray.at( distance ),
28417		point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ),
28418		index: i,
28419		face: null,
28420		faceIndex: null,
28421		barycoord: null,
28422		object: object
28423
28424	};
28425
28426}
28427
28428const _start = /*@__PURE__*/ new Vector3();
28429const _end = /*@__PURE__*/ new Vector3();
28430
28431/**
28432 * A series of lines drawn between pairs of vertices.
28433 *
28434 * @augments Line
28435 */
28436class LineSegments extends Line {
28437
28438	/**
28439	 * Constructs a new line segments.
28440	 *
28441	 * @param {BufferGeometry} [geometry] - The line geometry.
28442	 * @param {Material|Array<Material>} [material] - The line material.
28443	 */
28444	constructor( geometry, material ) {
28445
28446		super( geometry, material );
28447
28448		/**
28449		 * This flag can be used for type testing.
28450		 *
28451		 * @type {boolean}
28452		 * @readonly
28453		 * @default true
28454		 */
28455		this.isLineSegments = true;
28456
28457		this.type = 'LineSegments';
28458
28459	}
28460
28461	computeLineDistances() {
28462
28463		const geometry = this.geometry;
28464
28465		// we assume non-indexed geometry
28466
28467		if ( geometry.index === null ) {
28468
28469			const positionAttribute = geometry.attributes.position;
28470			const lineDistances = [];
28471
28472			for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) {
28473
28474				_start.fromBufferAttribute( positionAttribute, i );
28475				_end.fromBufferAttribute( positionAttribute, i + 1 );
28476
28477				lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];
28478				lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end );
28479
28480			}
28481
28482			geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );
28483
28484		} else {
28485
28486			warn( 'LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
28487
28488		}
28489
28490		return this;
28491
28492	}
28493
28494}
28495
28496/**
28497 * A continuous line. This is nearly the same as {@link Line} the only difference
28498 * is that the last vertex is connected with the first vertex in order to close
28499 * the line to form a loop.
28500 *
28501 * @augments Line
28502 */
28503class LineLoop extends Line {
28504
28505	/**
28506	 * Constructs a new line loop.
28507	 *
28508	 * @param {BufferGeometry} [geometry] - The line geometry.
28509	 * @param {Material|Array<Material>} [material] - The line material.
28510	 */
28511	constructor( geometry, material ) {
28512
28513		super( geometry, material );
28514
28515		/**
28516		 * This flag can be used for type testing.
28517		 *
28518		 * @type {boolean}
28519		 * @readonly
28520		 * @default true
28521		 */
28522		this.isLineLoop = true;
28523
28524		this.type = 'LineLoop';
28525
28526	}
28527
28528}
28529
28530/**
28531 * A material for rendering point primitives.
28532 *
28533 * Materials define the appearance of renderable 3D objects.
28534 *
28535 * ```js
28536 * const vertices = [];
28537 *
28538 * for ( let i = 0; i < 10000; i ++ ) {
28539 * 	const x = THREE.MathUtils.randFloatSpread( 2000 );
28540 * 	const y = THREE.MathUtils.randFloatSpread( 2000 );
28541 * 	const z = THREE.MathUtils.randFloatSpread( 2000 );
28542 *
28543 * 	vertices.push( x, y, z );
28544 * }
28545 *
28546 * const geometry = new THREE.BufferGeometry();
28547 * geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
28548 * const material = new THREE.PointsMaterial( { color: 0x888888 } );
28549 * const points = new THREE.Points( geometry, material );
28550 * scene.add( points );
28551 * ```
28552 *
28553 * @augments Material
28554 */
28555class PointsMaterial extends Material {
28556
28557	/**
28558	 * Constructs a new points material.
28559	 *
28560	 * @param {Object} [parameters] - An object with one or more properties
28561	 * defining the material's appearance. Any property of the material
28562	 * (including any property from inherited materials) can be passed
28563	 * in here. Color values can be passed any type of value accepted
28564	 * by {@link Color#set}.
28565	 */
28566	constructor( parameters ) {
28567
28568		super();
28569
28570		/**
28571		 * This flag can be used for type testing.
28572		 *
28573		 * @type {boolean}
28574		 * @readonly
28575		 * @default true
28576		 */
28577		this.isPointsMaterial = true;
28578
28579		this.type = 'PointsMaterial';
28580
28581		/**
28582		 * Color of the material.
28583		 *
28584		 * @type {Color}
28585		 * @default (1,1,1)
28586		 */
28587		this.color = new Color( 0xffffff );
28588
28589		/**
28590		 * The color map. May optionally include an alpha channel, typically combined
28591		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
28592		 * color is modulated by the diffuse `color`.
28593		 *
28594		 * `map` represents color data, and the texture must be assigned a
28595		 * {@link Texture#colorSpace}. Most `map` textures set
28596		 * `texture.colorSpace = SRGBColorSpace`.
28597		 *
28598		 * @type {?Texture}
28599		 * @default null
28600		 */
28601		this.map = null;
28602
28603		/**
28604		 * The alpha map is a grayscale texture that controls the opacity across the
28605		 * surface (black: fully transparent; white: fully opaque).
28606		 *
28607		 * Only the color of the texture is used, ignoring the alpha channel if one
28608		 * exists. For RGB and RGBA textures, the renderer will use the green channel
28609		 * when sampling this texture due to the extra bit of precision provided for
28610		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
28611		 * luminance/alpha textures will also still work as expected.
28612		 *
28613		 * `alphaMap` represents non-color data. Any texture assigned must have
28614		 * `texture.colorSpace = NoColorSpace` (default).
28615		 *
28616		 * @type {?Texture}
28617		 * @default null
28618		 */
28619		this.alphaMap = null;
28620
28621		/**
28622		 * Defines the size of the points in pixels.
28623		 *
28624		 * Might be capped if the value exceeds hardware dependent parameters like [gl.ALIASED_POINT_SIZE_RANGE](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParamete).
28625		 *
28626		 * @type {number}
28627		 * @default 1
28628		 */
28629		this.size = 1;
28630
28631		/**
28632		 * Specifies whether size of individual points is attenuated by the camera depth (perspective camera only).
28633		 *
28634		 * @type {boolean}
28635		 * @default true
28636		 */
28637		this.sizeAttenuation = true;
28638
28639		/**
28640		 * Whether the material is affected by fog or not.
28641		 *
28642		 * @type {boolean}
28643		 * @default true
28644		 */
28645		this.fog = true;
28646
28647		this.setValues( parameters );
28648
28649	}
28650
28651	copy( source ) {
28652
28653		super.copy( source );
28654
28655		this.color.copy( source.color );
28656
28657		this.map = source.map;
28658
28659		this.alphaMap = source.alphaMap;
28660
28661		this.size = source.size;
28662		this.sizeAttenuation = source.sizeAttenuation;
28663
28664		this.fog = source.fog;
28665
28666		return this;
28667
28668	}
28669
28670}
28671
28672const _inverseMatrix = /*@__PURE__*/ new Matrix4();
28673const _ray = /*@__PURE__*/ new Ray();
28674const _sphere = /*@__PURE__*/ new Sphere();
28675const _position$3 = /*@__PURE__*/ new Vector3();
28676
28677/**
28678 * A class for displaying points or point clouds.
28679 *
28680 * @augments Object3D
28681 */
28682class Points extends Object3D {
28683
28684	/**
28685	 * Constructs a new point cloud.
28686	 *
28687	 * @param {BufferGeometry} [geometry] - The points geometry.
28688	 * @param {Material|Array<Material>} [material] - The points material.
28689	 */
28690	constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) {
28691
28692		super();
28693
28694		/**
28695		 * This flag can be used for type testing.
28696		 *
28697		 * @type {boolean}
28698		 * @readonly
28699		 * @default true
28700		 */
28701		this.isPoints = true;
28702
28703		this.type = 'Points';
28704
28705		/**
28706		 * The points geometry.
28707		 *
28708		 * @type {BufferGeometry}
28709		 */
28710		this.geometry = geometry;
28711
28712		/**
28713		 * The line material.
28714		 *
28715		 * @type {Material|Array<Material>}
28716		 * @default PointsMaterial
28717		 */
28718		this.material = material;
28719
28720		/**
28721		 * A dictionary representing the morph targets in the geometry. The key is the
28722		 * morph targets name, the value its attribute index. This member is `undefined`
28723		 * by default and only set when morph targets are detected in the geometry.
28724		 *
28725		 * @type {Object<string,number>|undefined}
28726		 * @default undefined
28727		 */
28728		this.morphTargetDictionary = undefined;
28729
28730		/**
28731		 * An array of weights typically in the range `[0,1]` that specify how much of the morph
28732		 * is applied. This member is `undefined` by default and only set when morph targets are
28733		 * detected in the geometry.
28734		 *
28735		 * @type {Array<number>|undefined}
28736		 * @default undefined
28737		 */
28738		this.morphTargetInfluences = undefined;
28739
28740		this.updateMorphTargets();
28741
28742	}
28743
28744	copy( source, recursive ) {
28745
28746		super.copy( source, recursive );
28747
28748		this.material = Array.isArray( source.material ) ? source.material.slice() : source.material;
28749		this.geometry = source.geometry;
28750
28751		return this;
28752
28753	}
28754
28755	/**
28756	 * Returns `true` if this point cloud intersects the given frustum.
28757	 *
28758	 * @param {Frustum|FrustumArray} frustum - The frustum to test.
28759	 * @return {boolean} Whether this point cloud intersects the given frustum or not.
28760	 */
28761	intersectsFrustum( frustum ) {
28762
28763		return frustum.intersectsObject( this );
28764
28765	}
28766
28767	/**
28768	 * Computes intersection points between a casted ray and this point cloud.
28769	 *
28770	 * @param {Raycaster} raycaster - The raycaster.
28771	 * @param {Array<Object>} intersects - The target array that holds the intersection points.
28772	 */
28773	raycast( raycaster, intersects ) {
28774
28775		const geometry = this.geometry;
28776		const matrixWorld = this.matrixWorld;
28777		const threshold = raycaster.params.Points.threshold;
28778		const drawRange = geometry.drawRange;
28779
28780		// Checking boundingSphere distance to ray
28781
28782		if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
28783
28784		_sphere.copy( geometry.boundingSphere );
28785		_sphere.applyMatrix4( matrixWorld );
28786		_sphere.radius += threshold;
28787
28788		if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;
28789
28790		//
28791
28792		_inverseMatrix.copy( matrixWorld ).invert();
28793		_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
28794
28795		const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
28796		const localThresholdSq = localThreshold * localThreshold;
28797
28798		const index = geometry.index;
28799		const attributes = geometry.attributes;
28800		const positionAttribute = attributes.position;
28801
28802		if ( index !== null ) {
28803
28804			const start = Math.max( 0, drawRange.start );
28805			const end = Math.min( index.count, ( drawRange.start + drawRange.count ) );
28806
28807			for ( let i = start, il = end; i < il; i ++ ) {
28808
28809				const a = index.getX( i );
28810
28811				_position$3.fromBufferAttribute( positionAttribute, a );
28812
28813				testPoint( _position$3, a, localThresholdSq, matrixWorld, raycaster, intersects, this );
28814
28815			}
28816
28817		} else {
28818
28819			const start = Math.max( 0, drawRange.start );
28820			const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
28821
28822			for ( let i = start, l = end; i < l; i ++ ) {
28823
28824				_position$3.fromBufferAttribute( positionAttribute, i );
28825
28826				testPoint( _position$3, i, localThresholdSq, matrixWorld, raycaster, intersects, this );
28827
28828			}
28829
28830		}
28831
28832	}
28833
28834	/**
28835	 * Sets the values of {@link Points#morphTargetDictionary} and {@link Points#morphTargetInfluences}
28836	 * to make sure existing morph targets can influence this 3D object.
28837	 */
28838	updateMorphTargets() {
28839
28840		const geometry = this.geometry;
28841
28842		const morphAttributes = geometry.morphAttributes;
28843		const keys = Object.keys( morphAttributes );
28844
28845		if ( keys.length > 0 ) {
28846
28847			const morphAttribute = morphAttributes[ keys[ 0 ] ];
28848
28849			if ( morphAttribute !== undefined ) {
28850
28851				this.morphTargetInfluences = [];
28852				this.morphTargetDictionary = {};
28853
28854				for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) {
28855
28856					const name = morphAttribute[ m ].name || String( m );
28857
28858					this.morphTargetInfluences.push( 0 );
28859					this.morphTargetDictionary[ name ] = m;
28860
28861				}
28862
28863			}
28864
28865		}
28866
28867	}
28868
28869}
28870
28871function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {
28872
28873	const rayPointDistanceSq = _ray.distanceSqToPoint( point );
28874
28875	if ( rayPointDistanceSq < localThresholdSq ) {
28876
28877		const intersectPoint = new Vector3();
28878
28879		_ray.closestPointToPoint( point, intersectPoint );
28880		intersectPoint.applyMatrix4( matrixWorld );
28881
28882		const distance = raycaster.ray.origin.distanceTo( intersectPoint );
28883
28884		if ( distance < raycaster.near || distance > raycaster.far ) return;
28885
28886		intersects.push( {
28887
28888			distance: distance,
28889			distanceToRay: Math.sqrt( rayPointDistanceSq ),
28890			point: intersectPoint,
28891			index: index,
28892			face: null,
28893			faceIndex: null,
28894			barycoord: null,
28895			object: object
28896
28897		} );
28898
28899	}
28900
28901}
28902
28903/**
28904 * A texture for use with a video.
28905 *
28906 * ```js
28907 * // assuming you have created a HTML video element with id="video"
28908 * const video = document.getElementById( 'video' );
28909 * const texture = new THREE.VideoTexture( video );
28910 * ```
28911 *
28912 * Note: When using video textures with {@link WebGPURenderer}, {@link Texture#colorSpace} must be
28913 * set to THREE.SRGBColorSpace.
28914 *
28915 * Note: After the initial use of a texture, its dimensions, format, and type
28916 * cannot be changed. Instead, call {@link Texture#dispose} on the texture and instantiate a new one.
28917 *
28918 * @augments Texture
28919 */
28920class VideoTexture extends Texture {
28921
28922	/**
28923	 * Constructs a new video texture.
28924	 *
28925	 * @param {HTMLVideoElement} video - The video element to use as a data source for the texture.
28926	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
28927	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
28928	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
28929	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
28930	 * @param {number} [minFilter=LinearFilter] - The min filter value.
28931	 * @param {number} [format=RGBAFormat] - The texture format.
28932	 * @param {number} [type=UnsignedByteType] - The texture type.
28933	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
28934	 */
28935	constructor( video, mapping, wrapS, wrapT, magFilter = LinearFilter, minFilter = LinearFilter, format, type, anisotropy ) {
28936
28937		super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
28938
28939		/**
28940		 * This flag can be used for type testing.
28941		 *
28942		 * @type {boolean}
28943		 * @readonly
28944		 * @default true
28945		 */
28946		this.isVideoTexture = true;
28947
28948		/**
28949		 * Whether to generate mipmaps (if possible) for a texture.
28950		 *
28951		 * Overwritten and set to `false` by default.
28952		 *
28953		 * @type {boolean}
28954		 * @default false
28955		 */
28956		this.generateMipmaps = false;
28957
28958		/**
28959		 * The video frame request callback identifier, which is a positive integer.
28960		 *
28961		 * Value of 0 represents no scheduled rVFC.
28962		 *
28963		 * @private
28964		 * @type {number}
28965		 */
28966		this._requestVideoFrameCallbackId = 0;
28967
28968		const scope = this;
28969
28970		function updateVideo() {
28971
28972			scope.needsUpdate = true;
28973			scope._requestVideoFrameCallbackId = video.requestVideoFrameCallback( updateVideo );
28974
28975		}
28976
28977		if ( 'requestVideoFrameCallback' in video ) {
28978
28979			this._requestVideoFrameCallbackId = video.requestVideoFrameCallback( updateVideo );
28980
28981		}
28982
28983	}
28984
28985	clone() {
28986
28987		return new this.constructor( this.image ).copy( this );
28988
28989	}
28990
28991	/**
28992	 * This method is called automatically by the renderer and sets {@link Texture#needsUpdate}
28993	 * to `true` every time a new frame is available.
28994	 *
28995	 * Only relevant if `requestVideoFrameCallback` is not supported in the browser.
28996	 */
28997	update() {
28998
28999		const video = this.image;
29000		const hasVideoFrameCallback = 'requestVideoFrameCallback' in video;
29001
29002		if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) {
29003
29004			this.needsUpdate = true;
29005
29006		}
29007
29008	}
29009
29010	dispose() {
29011
29012		if ( this._requestVideoFrameCallbackId !== 0 ) {
29013
29014			this.source.data.cancelVideoFrameCallback( this._requestVideoFrameCallbackId );
29015
29016			this._requestVideoFrameCallbackId = 0;
29017
29018		}
29019
29020		super.dispose();
29021
29022	}
29023
29024}
29025
29026/**
29027 * This class can be used as an alternative way to define video data. Instead of using
29028 * an instance of `HTMLVideoElement` like with `VideoTexture`, `VideoFrameTexture` expects each frame is
29029 * defined manually via {@link VideoFrameTexture#setFrame}. A typical use case for this module is when
29030 * video frames are decoded with the WebCodecs API.
29031 *
29032 * ```js
29033 * const texture = new THREE.VideoFrameTexture();
29034 * texture.setFrame( frame );
29035 * ```
29036 *
29037 * @augments VideoTexture
29038 */
29039class VideoFrameTexture extends VideoTexture {
29040
29041	/**
29042	 * Constructs a new video frame texture.
29043	 *
29044	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
29045	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29046	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29047	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
29048	 * @param {number} [minFilter=LinearFilter] - The min filter value.
29049	 * @param {number} [format=RGBAFormat] - The texture format.
29050	 * @param {number} [type=UnsignedByteType] - The texture type.
29051	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29052	 */
29053	constructor( mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
29054
29055		super( {}, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
29056
29057		/**
29058		 * This flag can be used for type testing.
29059		 *
29060		 * @type {boolean}
29061		 * @readonly
29062		 * @default true
29063		 */
29064		this.isVideoFrameTexture = true;
29065
29066	}
29067
29068	/**
29069	 * This method overwritten with an empty implementation since
29070	 * this type of texture is updated via `setFrame()`.
29071	 */
29072	update() {}
29073
29074	clone() {
29075
29076		return new this.constructor().copy( this ); // restoring Texture.clone()
29077
29078	}
29079
29080	/**
29081	 * Sets the current frame of the video. This will automatically update the texture
29082	 * so the data can be used for rendering.
29083	 *
29084	 * @param {VideoFrame} frame - The video frame.
29085	 */
29086	setFrame( frame ) {
29087
29088		this.image = frame;
29089		this.needsUpdate = true;
29090
29091	}
29092
29093}
29094
29095/**
29096 * This class can only be used in combination with `copyFramebufferToTexture()` methods
29097 * of renderers. It extracts the contents of the current bound framebuffer and provides it
29098 * as a texture for further usage.
29099 *
29100 * ```js
29101 * const pixelRatio = window.devicePixelRatio;
29102 * const textureSize = 128 * pixelRatio;
29103 *
29104 * const frameTexture = new FramebufferTexture( textureSize, textureSize );
29105 *
29106 * // calculate start position for copying part of the frame data
29107 * const vector = new Vector2();
29108 * vector.x = ( window.innerWidth * pixelRatio / 2 ) - ( textureSize / 2 );
29109 * vector.y = ( window.innerHeight * pixelRatio / 2 ) - ( textureSize / 2 );
29110 *
29111 * renderer.render( scene, camera );
29112 *
29113 * // copy part of the rendered frame into the framebuffer texture
29114 * renderer.copyFramebufferToTexture( frameTexture, vector );
29115 * ```
29116 *
29117 * @augments Texture
29118 */
29119class FramebufferTexture extends Texture {
29120
29121	/**
29122	 * Constructs a new framebuffer texture.
29123	 *
29124	 * @param {number} [width] - The width of the texture.
29125	 * @param {number} [height] - The height of the texture.
29126	 */
29127	constructor( width, height ) {
29128
29129		super( { width, height } );
29130
29131		/**
29132		 * This flag can be used for type testing.
29133		 *
29134		 * @type {boolean}
29135		 * @readonly
29136		 * @default true
29137		 */
29138		this.isFramebufferTexture = true;
29139
29140		/**
29141		 * How the texture is sampled when a texel covers more than one pixel.
29142		 *
29143		 * Overwritten and set to `NearestFilter` by default to disable filtering.
29144		 *
29145		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
29146		 * @default NearestFilter
29147		 */
29148		this.magFilter = NearestFilter;
29149
29150		/**
29151		 * How the texture is sampled when a texel covers less than one pixel.
29152		 *
29153		 * Overwritten and set to `NearestFilter` by default to disable filtering.
29154		 *
29155		 * @type {(NearestFilter|NearestMipmapNearestFilter|NearestMipmapLinearFilter|LinearFilter|LinearMipmapNearestFilter|LinearMipmapLinearFilter)}
29156		 * @default NearestFilter
29157		 */
29158		this.minFilter = NearestFilter;
29159
29160		/**
29161		 * Whether to generate mipmaps (if possible) for a texture.
29162		 *
29163		 * Overwritten and set to `false` by default.
29164		 *
29165		 * @type {boolean}
29166		 * @default false
29167		 */
29168		this.generateMipmaps = false;
29169
29170		this.needsUpdate = true;
29171
29172	}
29173
29174}
29175
29176/**
29177 * Creates a texture based on data in compressed form.
29178 *
29179 * These texture are usually loaded with {@link CompressedTextureLoader}.
29180 *
29181 * @augments Texture
29182 */
29183class CompressedTexture extends Texture {
29184
29185	/**
29186	 * Constructs a new compressed texture.
29187	 *
29188	 * @param {Array<Object>} mipmaps - This array holds for all mipmaps (including the bases mip)
29189	 * the data and dimensions.
29190	 * @param {number} width - The width of the texture.
29191	 * @param {number} height - The height of the texture.
29192	 * @param {number} [format=RGBAFormat] - The texture format.
29193	 * @param {number} [type=UnsignedByteType] - The texture type.
29194	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
29195	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29196	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29197	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
29198	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
29199	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29200	 * @param {string} [colorSpace=NoColorSpace] - The color space.
29201	 */
29202	constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) {
29203
29204		super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
29205
29206		/**
29207		 * This flag can be used for type testing.
29208		 *
29209		 * @type {boolean}
29210		 * @readonly
29211		 * @default true
29212		 */
29213		this.isCompressedTexture = true;
29214
29215		/**
29216		 * The image property of a compressed texture just defines its dimensions.
29217		 *
29218		 * @type {{width:number,height:number}}
29219		 */
29220		this.image = { width: width, height: height };
29221
29222		/**
29223		 * This array holds for all mipmaps (including the bases mip) the data and dimensions.
29224		 *
29225		 * @type {Array<Object>}
29226		 */
29227		this.mipmaps = mipmaps;
29228
29229		/**
29230		 * If set to `true`, the texture is flipped along the vertical axis when
29231		 * uploaded to the GPU.
29232		 *
29233		 * Overwritten and set to `false` by default since it is not possible to
29234		 * flip compressed textures.
29235		 *
29236		 * @type {boolean}
29237		 * @default false
29238		 * @readonly
29239		 */
29240		this.flipY = false;
29241
29242		/**
29243		 * Whether to generate mipmaps (if possible) for a texture.
29244		 *
29245		 * Overwritten and set to `false` by default since it is not
29246		 * possible to generate mipmaps for compressed data. Mipmaps
29247		 * must be embedded in the compressed texture file.
29248		 *
29249		 * @type {boolean}
29250		 * @default false
29251		 * @readonly
29252		 */
29253		this.generateMipmaps = false;
29254
29255	}
29256
29257}
29258
29259/**
29260 * Creates a texture 2D array based on data in compressed form.
29261 *
29262 * These texture are usually loaded with {@link CompressedTextureLoader}.
29263 *
29264 * @augments CompressedTexture
29265 */
29266class CompressedArrayTexture extends CompressedTexture {
29267
29268	/**
29269	 * Constructs a new compressed array texture.
29270	 *
29271	 * @param {Array<Object>} mipmaps - This array holds for all mipmaps (including the bases mip)
29272	 * the data and dimensions.
29273	 * @param {number} width - The width of the texture.
29274	 * @param {number} height - The height of the texture.
29275	 * @param {number} depth - The depth of the texture.
29276	 * @param {number} [format=RGBAFormat] - The min filter value.
29277	 * @param {number} [type=UnsignedByteType] - The min filter value.
29278	 */
29279	constructor( mipmaps, width, height, depth, format, type ) {
29280
29281		super( mipmaps, width, height, format, type );
29282
29283		/**
29284		 * This flag can be used for type testing.
29285		 *
29286		 * @type {boolean}
29287		 * @readonly
29288		 * @default true
29289		 */
29290		this.isCompressedArrayTexture = true;
29291
29292		/**
29293		 * The image property of a compressed texture just defines its dimensions.
29294		 *
29295		 * @name CompressedArrayTexture#image
29296		 * @type {{width:number,height:number,depth:number}}
29297		 */
29298		this.image.depth = depth;
29299
29300		/**
29301		 * This defines how the texture is wrapped in the depth and corresponds to
29302		 * *W* in UVW mapping.
29303		 *
29304		 * @type {(RepeatWrapping|ClampToEdgeWrapping|MirroredRepeatWrapping)}
29305		 * @default ClampToEdgeWrapping
29306		 */
29307		this.wrapR = ClampToEdgeWrapping;
29308
29309		/**
29310		 * A set of all layers which need to be updated in the texture.
29311		 *
29312		 * @type {Set<number>}
29313		 */
29314		this.layerUpdates = new Set();
29315
29316	}
29317
29318	/**
29319	 * Copies the values of the given texture to this instance.
29320	 *
29321	 * @param {CompressedArrayTexture} source - The texture to copy.
29322	 * @return {CompressedArrayTexture} A reference to this instance.
29323	 */
29324	copy( source ) {
29325
29326		super.copy( source );
29327
29328		this.wrapR = source.wrapR;
29329
29330		return this;
29331
29332	}
29333
29334	/**
29335	 * Describes that a specific layer of the texture needs to be updated.
29336	 * Normally when {@link Texture#needsUpdate} is set to `true`, the
29337	 * entire compressed texture array is sent to the GPU. Marking specific
29338	 * layers will only transmit subsets of all mipmaps associated with a
29339	 * specific depth in the array which is often much more performant.
29340	 *
29341	 * @param {number} layerIndex - The layer index that should be updated.
29342	 */
29343	addLayerUpdate( layerIndex ) {
29344
29345		this.layerUpdates.add( layerIndex );
29346
29347	}
29348
29349	/**
29350	 * Resets the layer updates registry.
29351	 */
29352	clearLayerUpdates() {
29353
29354		this.layerUpdates.clear();
29355
29356	}
29357
29358}
29359
29360/**
29361 * Creates a cube texture based on data in compressed form.
29362 *
29363 * These texture are usually loaded with {@link CompressedTextureLoader}.
29364 *
29365 * @augments CompressedTexture
29366 */
29367class CompressedCubeTexture extends CompressedTexture {
29368
29369	/**
29370	 * Constructs a new compressed texture.
29371	 *
29372	 * @param {Array<CompressedTexture>} images - An array of compressed textures.
29373	 * @param {number} [format=RGBAFormat] - The texture format.
29374	 * @param {number} [type=UnsignedByteType] - The texture type.
29375	 */
29376	constructor( images, format, type ) {
29377
29378		super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping );
29379
29380		/**
29381		 * This flag can be used for type testing.
29382		 *
29383		 * @type {boolean}
29384		 * @readonly
29385		 * @default true
29386		 */
29387		this.isCompressedCubeTexture = true;
29388
29389		/**
29390		 * This flag can be used for type testing.
29391		 *
29392		 * @type {boolean}
29393		 * @readonly
29394		 * @default true
29395		 */
29396		this.isCubeTexture = true;
29397
29398		this.image = images;
29399
29400	}
29401
29402}
29403
29404/**
29405 * Creates a cube texture made up of six images.
29406 *
29407 * ```js
29408 * const loader = new THREE.CubeTextureLoader();
29409 * loader.setPath( 'textures/cube/pisa/' );
29410 *
29411 * const textureCube = loader.load( [
29412 * 	'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'
29413 * ] );
29414 *
29415 * const material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } );
29416 * ```
29417 *
29418 * @augments Texture
29419 */
29420class CubeTexture extends Texture {
29421
29422	/**
29423	 * Constructs a new cube texture.
29424	 *
29425	 * @param {Array<Image>} [images=[]] - An array holding a image for each side of a cube.
29426	 * @param {number} [mapping=CubeReflectionMapping] - The texture mapping.
29427	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29428	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29429	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
29430	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
29431	 * @param {number} [format=RGBAFormat] - The texture format.
29432	 * @param {number} [type=UnsignedByteType] - The texture type.
29433	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29434	 * @param {string} [colorSpace=NoColorSpace] - The color space value.
29435	 */
29436	constructor( images = [], mapping = CubeReflectionMapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
29437
29438		super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
29439
29440		/**
29441		 * This flag can be used for type testing.
29442		 *
29443		 * @type {boolean}
29444		 * @readonly
29445		 * @default true
29446		 */
29447		this.isCubeTexture = true;
29448
29449		/**
29450		 * If set to `true`, the texture is flipped along the vertical axis when
29451		 * uploaded to the GPU.
29452		 *
29453		 * Overwritten and set to `false` by default.
29454		 *
29455		 * @type {boolean}
29456		 * @default false
29457		 */
29458		this.flipY = false;
29459
29460	}
29461
29462	/**
29463	 * Alias for {@link CubeTexture#image}.
29464	 *
29465	 * @type {Array<Image>}
29466	 */
29467	get images() {
29468
29469		return this.image;
29470
29471	}
29472
29473	set images( value ) {
29474
29475		this.image = value;
29476
29477	}
29478
29479}
29480
29481/**
29482 * Creates a texture from a canvas element.
29483 *
29484 * This is almost the same as the base texture class, except that it sets {@link Texture#needsUpdate}
29485 * to `true` immediately since a canvas can directly be used for rendering.
29486 *
29487 * @augments Texture
29488 */
29489class CanvasTexture extends Texture {
29490
29491	/**
29492	 * Constructs a new texture.
29493	 *
29494	 * @param {HTMLCanvasElement} [canvas] - The HTML canvas element.
29495	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
29496	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29497	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29498	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
29499	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
29500	 * @param {number} [format=RGBAFormat] - The texture format.
29501	 * @param {number} [type=UnsignedByteType] - The texture type.
29502	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29503	 */
29504	constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
29505
29506		super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
29507
29508		/**
29509		 * This flag can be used for type testing.
29510		 *
29511		 * @type {boolean}
29512		 * @readonly
29513		 * @default true
29514		 */
29515		this.isCanvasTexture = true;
29516
29517		this.needsUpdate = true;
29518
29519	}
29520
29521}
29522
29523/**
29524 * Creates a texture from an HTML element.
29525 *
29526 * This is almost the same as the base texture class, except that it sets {@link Texture#needsUpdate}
29527 * to `true` immediately and listens for the parent canvas's paint events to trigger updates.
29528 *
29529 * @augments Texture
29530 */
29531class HTMLTexture extends Texture {
29532
29533	/**
29534	 * Constructs a new texture.
29535	 *
29536	 * @param {HTMLElement} [element] - The HTML element.
29537	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
29538	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29539	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29540	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
29541	 * @param {number} [minFilter=LinearMipmapLinearFilter] - The min filter value.
29542	 * @param {number} [format=RGBAFormat] - The texture format.
29543	 * @param {number} [type=UnsignedByteType] - The texture type.
29544	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29545	 */
29546	constructor( element, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
29547
29548		super( element, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
29549
29550		/**
29551		 * This flag can be used for type testing.
29552		 *
29553		 * @type {boolean}
29554		 * @readonly
29555		 * @default true
29556		 */
29557		this.isHTMLTexture = true;
29558		this.generateMipmaps = false;
29559
29560		this.needsUpdate = true;
29561
29562		const parent = element ? element.parentNode : null;
29563
29564		if ( parent !== null && 'requestPaint' in parent ) {
29565
29566			parent.onpaint = () => {
29567
29568				this.needsUpdate = true;
29569
29570			};
29571
29572			parent.requestPaint();
29573
29574		}
29575
29576	}
29577
29578	dispose() {
29579
29580		const parent = this.image ? this.image.parentNode : null;
29581
29582		if ( parent !== null && 'onpaint' in parent ) {
29583
29584			parent.onpaint = null;
29585
29586		}
29587
29588		super.dispose();
29589
29590	}
29591
29592}
29593
29594/**
29595 * This class can be used to automatically save the depth information of a
29596 * rendering into a texture.
29597 *
29598 * @augments Texture
29599 */
29600class DepthTexture extends Texture {
29601
29602	/**
29603	 * Constructs a new depth texture.
29604	 *
29605	 * @param {number} width - The width of the texture.
29606	 * @param {number} height - The height of the texture.
29607	 * @param {number} [type=UnsignedIntType] - The texture type.
29608	 * @param {number} [mapping=Texture.DEFAULT_MAPPING] - The texture mapping.
29609	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29610	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29611	 * @param {number} [magFilter=LinearFilter] - The mag filter value.
29612	 * @param {number} [minFilter=LinearFilter] - The min filter value.
29613	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29614	 * @param {number} [format=DepthFormat] - The texture format.
29615	 * @param {number} [depth=1] - The depth of the texture.
29616	 */
29617	constructor( width, height, type = UnsignedIntType, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, format = DepthFormat, depth = 1 ) {
29618
29619		if ( format !== DepthFormat && format !== DepthStencilFormat ) {
29620
29621			throw new Error( 'THREE.DepthTexture: format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
29622
29623		}
29624
29625		const image = { width: width, height: height, depth: depth };
29626
29627		super( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
29628
29629		/**
29630		 * This flag can be used for type testing.
29631		 *
29632		 * @type {boolean}
29633		 * @readonly
29634		 * @default true
29635		 */
29636		this.isDepthTexture = true;
29637
29638		/**
29639		 * If set to `true`, the texture is flipped along the vertical axis when
29640		 * uploaded to the GPU.
29641		 *
29642		 * Overwritten and set to `false` by default.
29643		 *
29644		 * @type {boolean}
29645		 * @default false
29646		 */
29647		this.flipY = false;
29648
29649		/**
29650		 * Whether to generate mipmaps (if possible) for a texture.
29651		 *
29652		 * Overwritten and set to `false` by default.
29653		 *
29654		 * @type {boolean}
29655		 * @default false
29656		 */
29657		this.generateMipmaps = false;
29658
29659		/**
29660		 * Code corresponding to the depth compare function.
29661		 *
29662		 * @type {?(NeverCompare|LessCompare|EqualCompare|LessEqualCompare|GreaterCompare|NotEqualCompare|GreaterEqualCompare|AlwaysCompare)}
29663		 * @default null
29664		 */
29665		this.compareFunction = null;
29666
29667	}
29668
29669
29670	copy( source ) {
29671
29672		super.copy( source );
29673
29674		this.source = new TextureSource( Object.assign( {}, source.image ) ); // see #30540
29675		this.compareFunction = source.compareFunction;
29676
29677		return this;
29678
29679	}
29680
29681	toJSON( meta ) {
29682
29683		const data = super.toJSON( meta );
29684
29685		data.compareFunction = this.compareFunction;
29686
29687		return data;
29688
29689	}
29690
29691}
29692
29693/**
29694 * This class can be used to automatically save the depth information of a
29695 * cube rendering into a cube texture with depth format. Used for PointLight shadows.
29696 *
29697 * @augments DepthTexture
29698 */
29699class CubeDepthTexture extends DepthTexture {
29700
29701	/**
29702	 * Constructs a new cube depth texture.
29703	 *
29704	 * @param {number} size - The size (width and height) of each cube face.
29705	 * @param {number} [type=UnsignedIntType] - The texture type.
29706	 * @param {number} [mapping=CubeReflectionMapping] - The texture mapping.
29707	 * @param {number} [wrapS=ClampToEdgeWrapping] - The wrapS value.
29708	 * @param {number} [wrapT=ClampToEdgeWrapping] - The wrapT value.
29709	 * @param {number} [magFilter=NearestFilter] - The mag filter value.
29710	 * @param {number} [minFilter=NearestFilter] - The min filter value.
29711	 * @param {number} [anisotropy=Texture.DEFAULT_ANISOTROPY] - The anisotropy value.
29712	 * @param {number} [format=DepthFormat] - The texture format.
29713	 */
29714	constructor( size, type = UnsignedIntType, mapping = CubeReflectionMapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, format = DepthFormat ) {
29715
29716		// Create 6 identical image descriptors for the cube faces
29717		const image = { width: size, height: size, depth: 1 };
29718		const images = [ image, image, image, image, image, image ];
29719
29720		// Call DepthTexture constructor with width, height
29721		super( size, size, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format );
29722
29723		// Replace the single image with the array of 6 images
29724		this.image = images;
29725
29726		/**
29727		 * This flag can be used for type testing.
29728		 *
29729		 * @type {boolean}
29730		 * @readonly
29731		 * @default true
29732		 */
29733		this.isCubeDepthTexture = true;
29734
29735		/**
29736		 * Set to true for cube texture handling in WebGLTextures.
29737		 *
29738		 * @type {boolean}
29739		 * @readonly
29740		 * @default true
29741		 */
29742		this.isCubeTexture = true;
29743
29744	}
29745
29746	/**
29747	 * Alias for {@link CubeDepthTexture#image}.
29748	 *
29749	 * @type {Array<Image>}
29750	 */
29751	get images() {
29752
29753		return this.image;
29754
29755	}
29756
29757	set images( value ) {
29758
29759		this.image = value;
29760
29761	}
29762
29763}
29764
29765/**
29766 * Represents a texture created externally with the same renderer context.
29767 *
29768 * This may be a texture from a protected media stream, device camera feed,
29769 * or other data feeds like a depth sensor.
29770 *
29771 * @augments Texture
29772 */
29773class ExternalTexture extends Texture {
29774
29775	/**
29776	 * Creates a new raw texture.
29777	 *
29778	 * @param {?(WebGLTexture|GPUTexture)} [sourceTexture=null] - The external texture.
29779	 */
29780	constructor( sourceTexture = null ) {
29781
29782		super();
29783
29784		/**
29785		 * The external source texture.
29786		 *
29787		 * @type {?(WebGLTexture|GPUTexture)}
29788		 * @default null
29789		 */
29790		this.sourceTexture = sourceTexture;
29791
29792		/**
29793		 * This flag can be used for type testing.
29794		 *
29795		 * @type {boolean}
29796		 * @readonly
29797		 * @default true
29798		 */
29799		this.isExternalTexture = true;
29800
29801	}
29802
29803	copy( source ) {
29804
29805		super.copy( source );
29806
29807		this.sourceTexture = source.sourceTexture;
29808
29809		return this;
29810
29811	}
29812
29813}
29814
29815/**
29816 * A geometry class for a rectangular cuboid with a given width, height, and depth.
29817 * On creation, the cuboid is centred on the origin, with each edge parallel to one
29818 * of the axes.
29819 *
29820 * ```js
29821 * const geometry = new THREE.BoxGeometry( 1, 1, 1 );
29822 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
29823 * const cube = new THREE.Mesh( geometry, material );
29824 * scene.add( cube );
29825 * ```
29826 *
29827 * @augments BufferGeometry
29828 * @demo scenes/geometry-browser.html#BoxGeometry
29829 */
29830class BoxGeometry extends BufferGeometry {
29831
29832	/**
29833	 * Constructs a new box geometry.
29834	 *
29835	 * @param {number} [width=1] - The width. That is, the length of the edges parallel to the X axis.
29836	 * @param {number} [height=1] - The height. That is, the length of the edges parallel to the Y axis.
29837	 * @param {number} [depth=1] - The depth. That is, the length of the edges parallel to the Z axis.
29838	 * @param {number} [widthSegments=1] - Number of segmented rectangular faces along the width of the sides.
29839	 * @param {number} [heightSegments=1] - Number of segmented rectangular faces along the height of the sides.
29840	 * @param {number} [depthSegments=1] - Number of segmented rectangular faces along the depth of the sides.
29841	 */
29842	constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
29843
29844		super();
29845
29846		this.type = 'BoxGeometry';
29847
29848		/**
29849		 * Holds the constructor parameters that have been
29850		 * used to generate the geometry. Any modification
29851		 * after instantiation does not change the geometry.
29852		 *
29853		 * @type {Object}
29854		 */
29855		this.parameters = {
29856			width: width,
29857			height: height,
29858			depth: depth,
29859			widthSegments: widthSegments,
29860			heightSegments: heightSegments,
29861			depthSegments: depthSegments
29862		};
29863
29864		const scope = this;
29865
29866		// segments
29867
29868		widthSegments = Math.floor( widthSegments );
29869		heightSegments = Math.floor( heightSegments );
29870		depthSegments = Math.floor( depthSegments );
29871
29872		// buffers
29873
29874		const indices = [];
29875		const vertices = [];
29876		const normals = [];
29877		const uvs = [];
29878
29879		// helper variables
29880
29881		let numberOfVertices = 0;
29882		let groupStart = 0;
29883
29884		// build each side of the box geometry
29885
29886		buildPlane( 'z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0 ); // px
29887		buildPlane( 'z', 'y', 'x', 1, -1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
29888		buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
29889		buildPlane( 'x', 'z', 'y', 1, -1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
29890		buildPlane( 'x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
29891		buildPlane( 'x', 'y', 'z', -1, -1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz
29892
29893		// build geometry
29894
29895		this.setIndex( indices );
29896		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
29897		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
29898		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
29899
29900		function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
29901
29902			const segmentWidth = width / gridX;
29903			const segmentHeight = height / gridY;
29904
29905			const widthHalf = width / 2;
29906			const heightHalf = height / 2;
29907			const depthHalf = depth / 2;
29908
29909			const gridX1 = gridX + 1;
29910			const gridY1 = gridY + 1;
29911
29912			let vertexCounter = 0;
29913			let groupCount = 0;
29914
29915			const vector = new Vector3();
29916
29917			// generate vertices, normals and uvs
29918
29919			for ( let iy = 0; iy < gridY1; iy ++ ) {
29920
29921				const y = iy * segmentHeight - heightHalf;
29922
29923				for ( let ix = 0; ix < gridX1; ix ++ ) {
29924
29925					const x = ix * segmentWidth - widthHalf;
29926
29927					// set values to correct vector component
29928
29929					vector[ u ] = x * udir;
29930					vector[ v ] = y * vdir;
29931					vector[ w ] = depthHalf;
29932
29933					// now apply vector to vertex buffer
29934
29935					vertices.push( vector.x, vector.y, vector.z );
29936
29937					// set values to correct vector component
29938
29939					vector[ u ] = 0;
29940					vector[ v ] = 0;
29941					vector[ w ] = depth > 0 ? 1 : -1;
29942
29943					// now apply vector to normal buffer
29944
29945					normals.push( vector.x, vector.y, vector.z );
29946
29947					// uvs
29948
29949					uvs.push( ix / gridX );
29950					uvs.push( 1 - ( iy / gridY ) );
29951
29952					// counters
29953
29954					vertexCounter += 1;
29955
29956				}
29957
29958			}
29959
29960			// indices
29961
29962			// 1. you need three indices to draw a single face
29963			// 2. a single segment consists of two faces
29964			// 3. so we need to generate six (2*3) indices per segment
29965
29966			for ( let iy = 0; iy < gridY; iy ++ ) {
29967
29968				for ( let ix = 0; ix < gridX; ix ++ ) {
29969
29970					const a = numberOfVertices + ix + gridX1 * iy;
29971					const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
29972					const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
29973					const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
29974
29975					// faces
29976
29977					indices.push( a, b, d );
29978					indices.push( b, c, d );
29979
29980					// increase counter
29981
29982					groupCount += 6;
29983
29984				}
29985
29986			}
29987
29988			// add a group to the geometry. this will ensure multi material support
29989
29990			scope.addGroup( groupStart, groupCount, materialIndex );
29991
29992			// calculate new start value for groups
29993
29994			groupStart += groupCount;
29995
29996			// update total number of vertices
29997
29998			numberOfVertices += vertexCounter;
29999
30000		}
30001
30002	}
30003
30004	copy( source ) {
30005
30006		super.copy( source );
30007
30008		this.parameters = Object.assign( {}, source.parameters );
30009
30010		return this;
30011
30012	}
30013
30014	/**
30015	 * Factory method for creating an instance of this class from the given
30016	 * JSON object.
30017	 *
30018	 * @param {Object} data - A JSON object representing the serialized geometry.
30019	 * @return {BoxGeometry} A new instance.
30020	 */
30021	static fromJSON( data ) {
30022
30023		return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
30024
30025	}
30026
30027}
30028
30029/**
30030 * A geometry class for representing a capsule.
30031 *
30032 * ```js
30033 * const geometry = new THREE.CapsuleGeometry( 1, 1, 4, 8, 1 );
30034 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
30035 * const capsule = new THREE.Mesh( geometry, material );
30036 * scene.add( capsule );
30037 * ```
30038 *
30039 * @augments BufferGeometry
30040 * @demo scenes/geometry-browser.html#CapsuleGeometry
30041 */
30042class CapsuleGeometry extends BufferGeometry {
30043
30044	/**
30045	 * Constructs a new capsule geometry.
30046	 *
30047	 * @param {number} [radius=1] - Radius of the capsule.
30048	 * @param {number} [height=1] - Height of the middle section.
30049	 * @param {number} [capSegments=4] - Number of curve segments used to build each cap.
30050	 * @param {number} [radialSegments=8] - Number of segmented faces around the circumference of the capsule. Must be an integer >= 3.
30051	 * @param {number} [heightSegments=1] - Number of rows of faces along the height of the middle section. Must be an integer >= 1.
30052	 */
30053	constructor( radius = 1, height = 1, capSegments = 4, radialSegments = 8, heightSegments = 1 ) {
30054
30055		super();
30056
30057		this.type = 'CapsuleGeometry';
30058
30059		/**
30060		 * Holds the constructor parameters that have been
30061		 * used to generate the geometry. Any modification
30062		 * after instantiation does not change the geometry.
30063		 *
30064		 * @type {Object}
30065		 */
30066		this.parameters = {
30067			radius: radius,
30068			height: height,
30069			capSegments: capSegments,
30070			radialSegments: radialSegments,
30071			heightSegments: heightSegments,
30072		};
30073
30074		height = Math.max( 0, height );
30075		capSegments = Math.max( 1, Math.floor( capSegments ) );
30076		radialSegments = Math.max( 3, Math.floor( radialSegments ) );
30077		heightSegments = Math.max( 1, Math.floor( heightSegments ) );
30078
30079		// buffers
30080
30081		const indices = [];
30082		const vertices = [];
30083		const normals = [];
30084		const uvs = [];
30085
30086		// helper variables
30087
30088		const halfHeight = height / 2;
30089		const capArcLength = ( Math.PI / 2 ) * radius;
30090		const cylinderPartLength = height;
30091		const totalArcLength = 2 * capArcLength + cylinderPartLength;
30092
30093		const numVerticalSegments = capSegments * 2 + heightSegments;
30094		const verticesPerRow = radialSegments + 1;
30095
30096		const normal = new Vector3();
30097		const vertex = new Vector3();
30098
30099		// generate vertices, normals, and uvs
30100
30101		for ( let iy = 0; iy <= numVerticalSegments; iy ++ ) {
30102
30103			let currentArcLength = 0;
30104			let profileY = 0;
30105			let profileRadius = 0;
30106			let normalYComponent = 0;
30107
30108			if ( iy <= capSegments ) {
30109
30110				// bottom cap
30111				const segmentProgress = iy / capSegments;
30112				const angle = ( segmentProgress * Math.PI ) / 2;
30113				profileY = - halfHeight - radius * Math.cos( angle );
30114				profileRadius = radius * Math.sin( angle );
30115				normalYComponent = - radius * Math.cos( angle );
30116				currentArcLength = segmentProgress * capArcLength;
30117
30118			} else if ( iy <= capSegments + heightSegments ) {
30119
30120				// middle section
30121				const segmentProgress = ( iy - capSegments ) / heightSegments;
30122				profileY = - halfHeight + segmentProgress * height;
30123				profileRadius = radius;
30124				normalYComponent = 0;
30125				currentArcLength = capArcLength + segmentProgress * cylinderPartLength;
30126
30127			} else {
30128
30129				// top cap
30130				const segmentProgress =
30131					( iy - capSegments - heightSegments ) / capSegments;
30132				const angle = ( segmentProgress * Math.PI ) / 2;
30133				profileY = halfHeight + radius * Math.sin( angle );
30134				profileRadius = radius * Math.cos( angle );
30135				normalYComponent = radius * Math.sin( angle );
30136				currentArcLength =
30137					capArcLength + cylinderPartLength + segmentProgress * capArcLength;
30138
30139			}
30140
30141			const v = Math.max( 0, Math.min( 1, currentArcLength / totalArcLength ) );
30142
30143
30144			// special case for the poles
30145
30146			let uOffset = 0;
30147
30148			if ( iy === 0 ) {
30149
30150				uOffset = 0.5 / radialSegments;
30151
30152			} else if ( iy === numVerticalSegments ) {
30153
30154				uOffset = -0.5 / radialSegments;
30155
30156			}
30157
30158			for ( let ix = 0; ix <= radialSegments; ix ++ ) {
30159
30160				const u = ix / radialSegments;
30161				const theta = u * Math.PI * 2;
30162
30163				const sinTheta = Math.sin( theta );
30164				const cosTheta = Math.cos( theta );
30165
30166				// vertex
30167
30168				vertex.x = - profileRadius * cosTheta;
30169				vertex.y = profileY;
30170				vertex.z = profileRadius * sinTheta;
30171				vertices.push( vertex.x, vertex.y, vertex.z );
30172
30173				// normal
30174
30175				normal.set(
30176					- profileRadius * cosTheta,
30177					normalYComponent,
30178					profileRadius * sinTheta
30179				);
30180				normal.normalize();
30181				normals.push( normal.x, normal.y, normal.z );
30182
30183				// uv
30184
30185				uvs.push( u + uOffset, v );
30186
30187			}
30188
30189			if ( iy > 0 ) {
30190
30191				const prevIndexRow = ( iy - 1 ) * verticesPerRow;
30192				for ( let ix = 0; ix < radialSegments; ix ++ ) {
30193
30194					const i1 = prevIndexRow + ix;
30195					const i2 = prevIndexRow + ix + 1;
30196					const i3 = iy * verticesPerRow + ix;
30197					const i4 = iy * verticesPerRow + ix + 1;
30198
30199					indices.push( i1, i2, i3 );
30200					indices.push( i2, i4, i3 );
30201
30202				}
30203
30204			}
30205
30206		}
30207
30208		// build geometry
30209
30210		this.setIndex( indices );
30211		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30212		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30213		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30214
30215	}
30216
30217	copy( source ) {
30218
30219		super.copy( source );
30220
30221		this.parameters = Object.assign( {}, source.parameters );
30222
30223		return this;
30224
30225	}
30226
30227	/**
30228	 * Factory method for creating an instance of this class from the given
30229	 * JSON object.
30230	 *
30231	 * @param {Object} data - A JSON object representing the serialized geometry.
30232	 * @return {CapsuleGeometry} A new instance.
30233	 */
30234	static fromJSON( data ) {
30235
30236		return new CapsuleGeometry( data.radius, data.height, data.capSegments, data.radialSegments, data.heightSegments );
30237
30238	}
30239
30240}
30241
30242/**
30243 * A simple shape of Euclidean geometry. It is constructed from a
30244 * number of triangular segments that are oriented around a central point and
30245 * extend as far out as a given radius. It is built counter-clockwise from a
30246 * start angle and a given central angle. It can also be used to create
30247 * regular polygons, where the number of segments determines the number of
30248 * sides.
30249 *
30250 * ```js
30251 * const geometry = new THREE.CircleGeometry( 5, 32 );
30252 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
30253 * const circle = new THREE.Mesh( geometry, material );
30254 * scene.add( circle )
30255 * ```
30256 *
30257 * @augments BufferGeometry
30258 * @demo scenes/geometry-browser.html#CircleGeometry
30259 */
30260class CircleGeometry extends BufferGeometry {
30261
30262	/**
30263	 * Constructs a new circle geometry.
30264	 *
30265	 * @param {number} [radius=1] - Radius of the circle.
30266	 * @param {number} [segments=32] - Number of segments (triangles), minimum = `3`.
30267	 * @param {number} [thetaStart=0] - Start angle for first segment in radians.
30268	 * @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta,
30269	 * of the circular sector in radians. The default value results in a complete circle.
30270	 */
30271	constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) {
30272
30273		super();
30274
30275		this.type = 'CircleGeometry';
30276
30277		/**
30278		 * Holds the constructor parameters that have been
30279		 * used to generate the geometry. Any modification
30280		 * after instantiation does not change the geometry.
30281		 *
30282		 * @type {Object}
30283		 */
30284		this.parameters = {
30285			radius: radius,
30286			segments: segments,
30287			thetaStart: thetaStart,
30288			thetaLength: thetaLength
30289		};
30290
30291		segments = Math.max( 3, segments );
30292
30293		// buffers
30294
30295		const indices = [];
30296		const vertices = [];
30297		const normals = [];
30298		const uvs = [];
30299
30300		// helper variables
30301
30302		const vertex = new Vector3();
30303		const uv = new Vector2();
30304
30305		// center point
30306
30307		vertices.push( 0, 0, 0 );
30308		normals.push( 0, 0, 1 );
30309		uvs.push( 0.5, 0.5 );
30310
30311		for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) {
30312
30313			const segment = thetaStart + s / segments * thetaLength;
30314
30315			// vertex
30316
30317			vertex.x = radius * Math.cos( segment );
30318			vertex.y = radius * Math.sin( segment );
30319
30320			vertices.push( vertex.x, vertex.y, vertex.z );
30321
30322			// normal
30323
30324			normals.push( 0, 0, 1 );
30325
30326			// uvs
30327
30328			uv.x = ( vertices[ i ] / radius + 1 ) / 2;
30329			uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;
30330
30331			uvs.push( uv.x, uv.y );
30332
30333		}
30334
30335		// indices
30336
30337		for ( let i = 1; i <= segments; i ++ ) {
30338
30339			indices.push( i, i + 1, 0 );
30340
30341		}
30342
30343		// build geometry
30344
30345		this.setIndex( indices );
30346		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30347		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30348		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30349
30350	}
30351
30352	copy( source ) {
30353
30354		super.copy( source );
30355
30356		this.parameters = Object.assign( {}, source.parameters );
30357
30358		return this;
30359
30360	}
30361
30362	/**
30363	 * Factory method for creating an instance of this class from the given
30364	 * JSON object.
30365	 *
30366	 * @param {Object} data - A JSON object representing the serialized geometry.
30367	 * @return {CircleGeometry} A new instance.
30368	 */
30369	static fromJSON( data ) {
30370
30371		return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength );
30372
30373	}
30374
30375}
30376
30377/**
30378 * A geometry class for representing a cylinder.
30379 *
30380 * ```js
30381 * const geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 );
30382 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
30383 * const cylinder = new THREE.Mesh( geometry, material );
30384 * scene.add( cylinder );
30385 * ```
30386 *
30387 * @augments BufferGeometry
30388 * @demo scenes/geometry-browser.html#CylinderGeometry
30389 */
30390class CylinderGeometry extends BufferGeometry {
30391
30392	/**
30393	 * Constructs a new cylinder geometry.
30394	 *
30395	 * @param {number} [radiusTop=1] - Radius of the cylinder at the top.
30396	 * @param {number} [radiusBottom=1] - Radius of the cylinder at the bottom.
30397	 * @param {number} [height=1] - Height of the cylinder.
30398	 * @param {number} [radialSegments=32] - Number of segmented faces around the circumference of the cylinder.
30399	 * @param {number} [heightSegments=1] - Number of rows of faces along the height of the cylinder.
30400	 * @param {boolean} [openEnded=false] - Whether the base of the cylinder is open or capped.
30401	 * @param {number} [thetaStart=0] - Start angle for first segment, in radians.
30402	 * @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
30403	 * The default value results in a complete cylinder.
30404	 */
30405	constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
30406
30407		super();
30408
30409		this.type = 'CylinderGeometry';
30410
30411		/**
30412		 * Holds the constructor parameters that have been
30413		 * used to generate the geometry. Any modification
30414		 * after instantiation does not change the geometry.
30415		 *
30416		 * @type {Object}
30417		 */
30418		this.parameters = {
30419			radiusTop: radiusTop,
30420			radiusBottom: radiusBottom,
30421			height: height,
30422			radialSegments: radialSegments,
30423			heightSegments: heightSegments,
30424			openEnded: openEnded,
30425			thetaStart: thetaStart,
30426			thetaLength: thetaLength
30427		};
30428
30429		const scope = this;
30430
30431		radialSegments = Math.floor( radialSegments );
30432		heightSegments = Math.floor( heightSegments );
30433
30434		// buffers
30435
30436		const indices = [];
30437		const vertices = [];
30438		const normals = [];
30439		const uvs = [];
30440
30441		// helper variables
30442
30443		let index = 0;
30444		const indexArray = [];
30445		const halfHeight = height / 2;
30446		let groupStart = 0;
30447
30448		// generate geometry
30449
30450		generateTorso();
30451
30452		if ( openEnded === false ) {
30453
30454			if ( radiusTop > 0 ) generateCap( true );
30455			if ( radiusBottom > 0 ) generateCap( false );
30456
30457		}
30458
30459		// build geometry
30460
30461		this.setIndex( indices );
30462		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
30463		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
30464		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
30465
30466		function generateTorso() {
30467
30468			const normal = new Vector3();
30469			const vertex = new Vector3();
30470
30471			let groupCount = 0;
30472
30473			// this will be used to calculate the normal
30474			const slope = ( radiusBottom - radiusTop ) / height;
30475
30476			// generate vertices, normals and uvs
30477
30478			for ( let y = 0; y <= heightSegments; y ++ ) {
30479
30480				const indexRow = [];
30481
30482				const v = y / heightSegments;
30483
30484				// calculate the radius of the current row
30485
30486				const radius = v * ( radiusBottom - radiusTop ) + radiusTop;
30487
30488				for ( let x = 0; x <= radialSegments; x ++ ) {
30489
30490					const u = x / radialSegments;
30491
30492					const theta = u * thetaLength + thetaStart;
30493
30494					const sinTheta = Math.sin( theta );
30495					const cosTheta = Math.cos( theta );
30496
30497					// vertex
30498
30499					vertex.x = radius * sinTheta;
30500					vertex.y = - v * height + halfHeight;
30501					vertex.z = radius * cosTheta;
30502					vertices.push( vertex.x, vertex.y, vertex.z );
30503
30504					// normal
30505
30506					normal.set( sinTheta, slope, cosTheta ).normalize();
30507					normals.push( normal.x, normal.y, normal.z );
30508
30509					// uv
30510
30511					uvs.push( u, 1 - v );
30512
30513					// save index of vertex in respective row
30514
30515					indexRow.push( index ++ );
30516
30517				}
30518
30519				// now save vertices of the row in our index array
30520
30521				indexArray.push( indexRow );
30522
30523			}
30524
30525			// generate indices
30526
30527			for ( let x = 0; x < radialSegments; x ++ ) {
30528
30529				for ( let y = 0; y < heightSegments; y ++ ) {
30530
30531					// we use the index array to access the correct indices
30532
30533					const a = indexArray[ y ][ x ];
30534					const b = indexArray[ y + 1 ][ x ];
30535					const c = indexArray[ y + 1 ][ x + 1 ];
30536					const d = indexArray[ y ][ x + 1 ];
30537
30538					// faces
30539
30540					if ( radiusTop > 0 || y !== 0 ) {
30541
30542						indices.push( a, b, d );
30543						groupCount += 3;
30544
30545					}
30546
30547					if ( radiusBottom > 0 || y !== heightSegments - 1 ) {
30548
30549						indices.push( b, c, d );
30550						groupCount += 3;
30551
30552					}
30553
30554				}
30555
30556			}
30557
30558			// add a group to the geometry. this will ensure multi material support
30559
30560			scope.addGroup( groupStart, groupCount, 0 );
30561
30562			// calculate new start value for groups
30563
30564			groupStart += groupCount;
30565
30566		}
30567
30568		function generateCap( top ) {
30569
30570			// save the index of the first center vertex
30571			const centerIndexStart = index;
30572
30573			const uv = new Vector2();
30574			const vertex = new Vector3();
30575
30576			let groupCount = 0;
30577
30578			const radius = ( top === true ) ? radiusTop : radiusBottom;
30579			const sign = ( top === true ) ? 1 : -1;
30580
30581			// first we generate the center vertex data of the cap.
30582			// because the geometry needs one set of uvs per face,
30583			// we must generate a center vertex per face/segment
30584
30585			for ( let x = 1; x <= radialSegments; x ++ ) {
30586
30587				// vertex
30588
30589				vertices.push( 0, halfHeight * sign, 0 );
30590
30591				// normal
30592
30593				normals.push( 0, sign, 0 );
30594
30595				// uv
30596
30597				uvs.push( 0.5, 0.5 );
30598
30599				// increase index
30600
30601				index ++;
30602
30603			}
30604
30605			// save the index of the last center vertex
30606			const centerIndexEnd = index;
30607
30608			// now we generate the surrounding vertices, normals and uvs
30609
30610			for ( let x = 0; x <= radialSegments; x ++ ) {
30611
30612				const u = x / radialSegments;
30613				const theta = u * thetaLength + thetaStart;
30614
30615				const cosTheta = Math.cos( theta );
30616				const sinTheta = Math.sin( theta );
30617
30618				// vertex
30619
30620				vertex.x = radius * sinTheta;
30621				vertex.y = halfHeight * sign;
30622				vertex.z = radius * cosTheta;
30623				vertices.push( vertex.x, vertex.y, vertex.z );
30624
30625				// normal
30626
30627				normals.push( 0, sign, 0 );
30628
30629				// uv
30630
30631				uv.x = ( cosTheta * 0.5 ) + 0.5;
30632				uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
30633				uvs.push( uv.x, uv.y );
30634
30635				// increase index
30636
30637				index ++;
30638
30639			}
30640
30641			// generate indices
30642
30643			for ( let x = 0; x < radialSegments; x ++ ) {
30644
30645				const c = centerIndexStart + x;
30646				const i = centerIndexEnd + x;
30647
30648				if ( top === true ) {
30649
30650					// face top
30651
30652					indices.push( i, i + 1, c );
30653
30654				} else {
30655
30656					// face bottom
30657
30658					indices.push( i + 1, i, c );
30659
30660				}
30661
30662				groupCount += 3;
30663
30664			}
30665
30666			// add a group to the geometry. this will ensure multi material support
30667
30668			scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );
30669
30670			// calculate new start value for groups
30671
30672			groupStart += groupCount;
30673
30674		}
30675
30676	}
30677
30678	copy( source ) {
30679
30680		super.copy( source );
30681
30682		this.parameters = Object.assign( {}, source.parameters );
30683
30684		return this;
30685
30686	}
30687
30688	/**
30689	 * Factory method for creating an instance of this class from the given
30690	 * JSON object.
30691	 *
30692	 * @param {Object} data - A JSON object representing the serialized geometry.
30693	 * @return {CylinderGeometry} A new instance.
30694	 */
30695	static fromJSON( data ) {
30696
30697		return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
30698
30699	}
30700
30701}
30702
30703/**
30704 * A geometry class for representing a cone.
30705 *
30706 * ```js
30707 * const geometry = new THREE.ConeGeometry( 5, 20, 32 );
30708 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
30709 * const cone = new THREE.Mesh(geometry, material );
30710 * scene.add( cone );
30711 * ```
30712 *
30713 * @augments CylinderGeometry
30714 * @demo scenes/geometry-browser.html#ConeGeometry
30715 */
30716class ConeGeometry extends CylinderGeometry {
30717
30718	/**
30719	 * Constructs a new cone geometry.
30720	 *
30721	 * @param {number} [radius=1] - Radius of the cone base.
30722	 * @param {number} [height=1] - Height of the cone.
30723	 * @param {number} [radialSegments=32] - Number of segmented faces around the circumference of the cone.
30724	 * @param {number} [heightSegments=1] - Number of rows of faces along the height of the cone.
30725	 * @param {boolean} [openEnded=false] - Whether the base of the cone is open or capped.
30726	 * @param {number} [thetaStart=0] - Start angle for first segment, in radians.
30727	 * @param {number} [thetaLength=Math.PI*2] - The central angle, often called theta, of the circular sector, in radians.
30728	 * The default value results in a complete cone.
30729	 */
30730	constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) {
30731
30732		super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
30733
30734		this.type = 'ConeGeometry';
30735
30736		/**
30737		 * Holds the constructor parameters that have been
30738		 * used to generate the geometry. Any modification
30739		 * after instantiation does not change the geometry.
30740		 *
30741		 * @type {Object}
30742		 */
30743		this.parameters = {
30744			radius: radius,
30745			height: height,
30746			radialSegments: radialSegments,
30747			heightSegments: heightSegments,
30748			openEnded: openEnded,
30749			thetaStart: thetaStart,
30750			thetaLength: thetaLength
30751		};
30752
30753	}
30754
30755	/**
30756	 * Factory method for creating an instance of this class from the given
30757	 * JSON object.
30758	 *
30759	 * @param {Object} data - A JSON object representing the serialized geometry.
30760	 * @return {ConeGeometry} A new instance.
30761	 */
30762	static fromJSON( data ) {
30763
30764		return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
30765
30766	}
30767
30768}
30769
30770/**
30771 * A polyhedron is a solid in three dimensions with flat faces. This class
30772 * will take an array of vertices, project them onto a sphere, and then
30773 * divide them up to the desired level of detail.
30774 *
30775 * @augments BufferGeometry
30776 */
30777class PolyhedronGeometry extends BufferGeometry {
30778
30779	/**
30780	 * Constructs a new polyhedron geometry.
30781	 *
30782	 * @param {Array<number>} [vertices] - A flat array of vertices describing the base shape.
30783	 * @param {Array<number>} [indices] - A flat array of indices describing the base shape.
30784	 * @param {number} [radius=1] - The radius of the shape.
30785	 * @param {number} [detail=0] - How many levels to subdivide the geometry. The more detail, the smoother the shape.
30786	 */
30787	constructor( vertices = [], indices = [], radius = 1, detail = 0 ) {
30788
30789		super();
30790
30791		this.type = 'PolyhedronGeometry';
30792
30793		/**
30794		 * Holds the constructor parameters that have been
30795		 * used to generate the geometry. Any modification
30796		 * after instantiation does not change the geometry.
30797		 *
30798		 * @type {Object}
30799		 */
30800		this.parameters = {
30801			vertices: vertices,
30802			indices: indices,
30803			radius: radius,
30804			detail: detail
30805		};
30806
30807		// default buffer data
30808
30809		const vertexBuffer = [];
30810		const uvBuffer = [];
30811
30812		// the subdivision creates the vertex buffer data
30813
30814		subdivide( detail );
30815
30816		// all vertices should lie on a conceptual sphere with a given radius
30817
30818		applyRadius( radius );
30819
30820		// finally, create the uv data
30821
30822		generateUVs();
30823
30824		// build non-indexed geometry
30825
30826		this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
30827		this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
30828		this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
30829
30830		if ( detail === 0 ) {
30831
30832			this.computeVertexNormals(); // flat normals
30833
30834		} else {
30835
30836			this.normalizeNormals(); // smooth normals
30837
30838		}
30839
30840		// helper functions
30841
30842		function subdivide( detail ) {
30843
30844			const a = new Vector3();
30845			const b = new Vector3();
30846			const c = new Vector3();
30847
30848			// iterate over all faces and apply a subdivision with the given detail value
30849
30850			for ( let i = 0; i < indices.length; i += 3 ) {
30851
30852				// get the vertices of the face
30853
30854				getVertexByIndex( indices[ i + 0 ], a );
30855				getVertexByIndex( indices[ i + 1 ], b );
30856				getVertexByIndex( indices[ i + 2 ], c );
30857
30858				// perform subdivision
30859
30860				subdivideFace( a, b, c, detail );
30861
30862			}
30863
30864		}
30865
30866		function subdivideFace( a, b, c, detail ) {
30867
30868			const cols = detail + 1;
30869
30870			// we use this multidimensional array as a data structure for creating the subdivision
30871
30872			const v = [];
30873
30874			// construct all of the vertices for this subdivision
30875
30876			for ( let i = 0; i <= cols; i ++ ) {
30877
30878				v[ i ] = [];
30879
30880				const aj = a.clone().lerp( c, i / cols );
30881				const bj = b.clone().lerp( c, i / cols );
30882
30883				const rows = cols - i;
30884
30885				for ( let j = 0; j <= rows; j ++ ) {
30886
30887					if ( j === 0 && i === cols ) {
30888
30889						v[ i ][ j ] = aj;
30890
30891					} else {
30892
30893						v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
30894
30895					}
30896
30897				}
30898
30899			}
30900
30901			// construct all of the faces
30902
30903			for ( let i = 0; i < cols; i ++ ) {
30904
30905				for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
30906
30907					const k = Math.floor( j / 2 );
30908
30909					if ( j % 2 === 0 ) {
30910
30911						pushVertex( v[ i ][ k + 1 ] );
30912						pushVertex( v[ i + 1 ][ k ] );
30913						pushVertex( v[ i ][ k ] );
30914
30915					} else {
30916
30917						pushVertex( v[ i ][ k + 1 ] );
30918						pushVertex( v[ i + 1 ][ k + 1 ] );
30919						pushVertex( v[ i + 1 ][ k ] );
30920
30921					}
30922
30923				}
30924
30925			}
30926
30927		}
30928
30929		function applyRadius( radius ) {
30930
30931			const vertex = new Vector3();
30932
30933			// iterate over the entire buffer and apply the radius to each vertex
30934
30935			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
30936
30937				vertex.x = vertexBuffer[ i + 0 ];
30938				vertex.y = vertexBuffer[ i + 1 ];
30939				vertex.z = vertexBuffer[ i + 2 ];
30940
30941				vertex.normalize().multiplyScalar( radius );
30942
30943				vertexBuffer[ i + 0 ] = vertex.x;
30944				vertexBuffer[ i + 1 ] = vertex.y;
30945				vertexBuffer[ i + 2 ] = vertex.z;
30946
30947			}
30948
30949		}
30950
30951		function generateUVs() {
30952
30953			const vertex = new Vector3();
30954
30955			for ( let i = 0; i < vertexBuffer.length; i += 3 ) {
30956
30957				vertex.x = vertexBuffer[ i + 0 ];
30958				vertex.y = vertexBuffer[ i + 1 ];
30959				vertex.z = vertexBuffer[ i + 2 ];
30960
30961				const u = azimuth( vertex ) / 2 / Math.PI + 0.5;
30962				const v = inclination( vertex ) / Math.PI + 0.5;
30963				uvBuffer.push( u, 1 - v );
30964
30965			}
30966
30967			correctUVs();
30968
30969			correctSeam();
30970
30971		}
30972
30973		function correctSeam() {
30974
30975			// handle case when face straddles the seam, see #3269
30976
30977			for ( let i = 0; i < uvBuffer.length; i += 6 ) {
30978
30979				// uv data of a single face
30980
30981				const x0 = uvBuffer[ i + 0 ];
30982				const x1 = uvBuffer[ i + 2 ];
30983				const x2 = uvBuffer[ i + 4 ];
30984
30985				const max = Math.max( x0, x1, x2 );
30986				const min = Math.min( x0, x1, x2 );
30987
30988				// 0.9 is somewhat arbitrary
30989
30990				if ( max > 0.9 && min < 0.1 ) {
30991
30992					if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
30993					if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
30994					if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
30995
30996				}
30997
30998			}
30999
31000		}
31001
31002		function pushVertex( vertex ) {
31003
31004			vertexBuffer.push( vertex.x, vertex.y, vertex.z );
31005
31006		}
31007
31008		function getVertexByIndex( index, vertex ) {
31009
31010			const stride = index * 3;
31011
31012			vertex.x = vertices[ stride + 0 ];
31013			vertex.y = vertices[ stride + 1 ];
31014			vertex.z = vertices[ stride + 2 ];
31015
31016		}
31017
31018		function correctUVs() {
31019
31020			const a = new Vector3();
31021			const b = new Vector3();
31022			const c = new Vector3();
31023
31024			const centroid = new Vector3();
31025
31026			const uvA = new Vector2();
31027			const uvB = new Vector2();
31028			const uvC = new Vector2();
31029
31030			for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
31031
31032				a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
31033				b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
31034				c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
31035
31036				uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
31037				uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
31038				uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
31039
31040				centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
31041
31042				const azi = azimuth( centroid );
31043
31044				correctUV( uvA, j + 0, a, azi );
31045				correctUV( uvB, j + 2, b, azi );
31046				correctUV( uvC, j + 4, c, azi );
31047
31048			}
31049
31050		}
31051
31052		function correctUV( uv, stride, vector, azimuth ) {
31053
31054			if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
31055
31056				uvBuffer[ stride ] = uv.x - 1;
31057
31058			}
31059
31060			if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
31061
31062				uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
31063
31064			}
31065
31066		}
31067
31068		// Angle around the Y axis, counter-clockwise when looking from above.
31069
31070		function azimuth( vector ) {
31071
31072			return Math.atan2( vector.z, - vector.x );
31073
31074		}
31075
31076
31077		// Angle above the XZ plane.
31078
31079		function inclination( vector ) {
31080
31081			return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
31082
31083		}
31084
31085	}
31086
31087	copy( source ) {
31088
31089		super.copy( source );
31090
31091		this.parameters = Object.assign( {}, source.parameters );
31092
31093		return this;
31094
31095	}
31096
31097	/**
31098	 * Factory method for creating an instance of this class from the given
31099	 * JSON object.
31100	 *
31101	 * @param {Object} data - A JSON object representing the serialized geometry.
31102	 * @return {PolyhedronGeometry} A new instance.
31103	 */
31104	static fromJSON( data ) {
31105
31106		return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.detail );
31107
31108	}
31109
31110}
31111
31112/**
31113 * A geometry class for representing a dodecahedron.
31114 *
31115 * ```js
31116 * const geometry = new THREE.DodecahedronGeometry();
31117 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
31118 * const dodecahedron = new THREE.Mesh( geometry, material );
31119 * scene.add( dodecahedron );
31120 * ```
31121 *
31122 * @augments PolyhedronGeometry
31123 * @demo scenes/geometry-browser.html#DodecahedronGeometry
31124 */
31125class DodecahedronGeometry extends PolyhedronGeometry {
31126
31127	/**
31128	 * Constructs a new dodecahedron geometry.
31129	 *
31130	 * @param {number} [radius=1] - Radius of the dodecahedron.
31131	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a dodecahedron.
31132	 */
31133	constructor( radius = 1, detail = 0 ) {
31134
31135		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
31136		const r = 1 / t;
31137
31138		const vertices = [
31139
31140			// (±1, ±1, ±1)
31141			-1, -1, -1,	-1, -1, 1,
31142			-1, 1, -1, -1, 1, 1,
31143			1, -1, -1, 1, -1, 1,
31144			1, 1, -1, 1, 1, 1,
31145
31146			// (0, ±1/φ, ±φ)
31147			0, - r, - t, 0, - r, t,
31148			0, r, - t, 0, r, t,
31149
31150			// (±1/φ, ±φ, 0)
31151			- r, - t, 0, - r, t, 0,
31152			r, - t, 0, r, t, 0,
31153
31154			// (±φ, 0, ±1/φ)
31155			- t, 0, - r, t, 0, - r,
31156			- t, 0, r, t, 0, r
31157		];
31158
31159		const indices = [
31160			3, 11, 7, 	3, 7, 15, 	3, 15, 13,
31161			7, 19, 17, 	7, 17, 6, 	7, 6, 15,
31162			17, 4, 8, 	17, 8, 10, 	17, 10, 6,
31163			8, 0, 16, 	8, 16, 2, 	8, 2, 10,
31164			0, 12, 1, 	0, 1, 18, 	0, 18, 16,
31165			6, 10, 2, 	6, 2, 13, 	6, 13, 15,
31166			2, 16, 18, 	2, 18, 3, 	2, 3, 13,
31167			18, 1, 9, 	18, 9, 11, 	18, 11, 3,
31168			4, 14, 12, 	4, 12, 0, 	4, 0, 8,
31169			11, 9, 5, 	11, 5, 19, 	11, 19, 7,
31170			19, 5, 14, 	19, 14, 4, 	19, 4, 17,
31171			1, 12, 14, 	1, 14, 5, 	1, 5, 9
31172		];
31173
31174		super( vertices, indices, radius, detail );
31175
31176		this.type = 'DodecahedronGeometry';
31177
31178		/**
31179		 * Holds the constructor parameters that have been
31180		 * used to generate the geometry. Any modification
31181		 * after instantiation does not change the geometry.
31182		 *
31183		 * @type {Object}
31184		 */
31185		this.parameters = {
31186			radius: radius,
31187			detail: detail
31188		};
31189
31190	}
31191
31192	/**
31193	 * Factory method for creating an instance of this class from the given
31194	 * JSON object.
31195	 *
31196	 * @param {Object} data - A JSON object representing the serialized geometry.
31197	 * @return {DodecahedronGeometry} A new instance.
31198	 */
31199	static fromJSON( data ) {
31200
31201		return new DodecahedronGeometry( data.radius, data.detail );
31202
31203	}
31204
31205}
31206
31207const _v0 = /*@__PURE__*/ new Vector3();
31208const _v1$1 = /*@__PURE__*/ new Vector3();
31209const _normal = /*@__PURE__*/ new Vector3();
31210const _triangle = /*@__PURE__*/ new Triangle();
31211
31212/**
31213 * Can be used as a helper object to view the edges of a geometry.
31214 *
31215 * ```js
31216 * const geometry = new THREE.BoxGeometry();
31217 * const edges = new THREE.EdgesGeometry( geometry );
31218 * const line = new THREE.LineSegments( edges );
31219 * scene.add( line );
31220 * ```
31221 *
31222 * Note: It is not yet possible to serialize/deserialize instances of this class.
31223 *
31224 * @augments BufferGeometry
31225 */
31226class EdgesGeometry extends BufferGeometry {
31227
31228	/**
31229	 * Constructs a new edges geometry.
31230	 *
31231	 * @param {?BufferGeometry} [geometry=null] - The geometry.
31232	 * @param {number} [thresholdAngle=1] - An edge is only rendered if the angle (in degrees)
31233	 * between the face normals of the adjoining faces exceeds this value.
31234	 */
31235	constructor( geometry = null, thresholdAngle = 1 ) {
31236
31237		super();
31238
31239		this.type = 'EdgesGeometry';
31240
31241		/**
31242		 * Holds the constructor parameters that have been
31243		 * used to generate the geometry. Any modification
31244		 * after instantiation does not change the geometry.
31245		 *
31246		 * @type {Object}
31247		 */
31248		this.parameters = {
31249			geometry: geometry,
31250			thresholdAngle: thresholdAngle
31251		};
31252
31253		if ( geometry !== null ) {
31254
31255			const precisionPoints = 4;
31256			const precision = Math.pow( 10, precisionPoints );
31257			const thresholdDot = Math.cos( DEG2RAD * thresholdAngle );
31258
31259			const indexAttr = geometry.getIndex();
31260			const positionAttr = geometry.getAttribute( 'position' );
31261			const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
31262
31263			const indexArr = [ 0, 0, 0 ];
31264			const vertKeys = [ 'a', 'b', 'c' ];
31265			const hashes = new Array( 3 );
31266
31267			const edgeData = {};
31268			const vertices = [];
31269			for ( let i = 0; i < indexCount; i += 3 ) {
31270
31271				if ( indexAttr ) {
31272
31273					indexArr[ 0 ] = indexAttr.getX( i );
31274					indexArr[ 1 ] = indexAttr.getX( i + 1 );
31275					indexArr[ 2 ] = indexAttr.getX( i + 2 );
31276
31277				} else {
31278
31279					indexArr[ 0 ] = i;
31280					indexArr[ 1 ] = i + 1;
31281					indexArr[ 2 ] = i + 2;
31282
31283				}
31284
31285				const { a, b, c } = _triangle;
31286				a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
31287				b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
31288				c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
31289				_triangle.getNormal( _normal );
31290
31291				// create hashes for the edge from the vertices
31292				hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`;
31293				hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`;
31294				hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`;
31295
31296				// skip degenerate triangles
31297				if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
31298
31299					continue;
31300
31301				}
31302
31303				// iterate over every edge
31304				for ( let j = 0; j < 3; j ++ ) {
31305
31306					// get the first and next vertex making up the edge
31307					const jNext = ( j + 1 ) % 3;
31308					const vecHash0 = hashes[ j ];
31309					const vecHash1 = hashes[ jNext ];
31310					const v0 = _triangle[ vertKeys[ j ] ];
31311					const v1 = _triangle[ vertKeys[ jNext ] ];
31312
31313					const hash = `${ vecHash0 }_${ vecHash1 }`;
31314					const reverseHash = `${ vecHash1 }_${ vecHash0 }`;
31315
31316					if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
31317
31318						// if we found a sibling edge add it into the vertex array if
31319						// it meets the angle threshold and delete the edge from the map.
31320						if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
31321
31322							vertices.push( v0.x, v0.y, v0.z );
31323							vertices.push( v1.x, v1.y, v1.z );
31324
31325						}
31326
31327						edgeData[ reverseHash ] = null;
31328
31329					} else if ( ! ( hash in edgeData ) ) {
31330
31331						// if we've already got an edge here then skip adding a new one
31332						edgeData[ hash ] = {
31333
31334							index0: indexArr[ j ],
31335							index1: indexArr[ jNext ],
31336							normal: _normal.clone(),
31337
31338						};
31339
31340					}
31341
31342				}
31343
31344			}
31345
31346			// iterate over all remaining, unmatched edges and add them to the vertex array
31347			for ( const key in edgeData ) {
31348
31349				if ( edgeData[ key ] ) {
31350
31351					const { index0, index1 } = edgeData[ key ];
31352					_v0.fromBufferAttribute( positionAttr, index0 );
31353					_v1$1.fromBufferAttribute( positionAttr, index1 );
31354
31355					vertices.push( _v0.x, _v0.y, _v0.z );
31356					vertices.push( _v1$1.x, _v1$1.y, _v1$1.z );
31357
31358				}
31359
31360			}
31361
31362			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
31363
31364		}
31365
31366	}
31367
31368	copy( source ) {
31369
31370		super.copy( source );
31371
31372		this.parameters = Object.assign( {}, source.parameters );
31373
31374		return this;
31375
31376	}
31377
31378}
31379
31380/**
31381 * An abstract base class for creating an analytic curve object that contains methods
31382 * for interpolation.
31383 *
31384 * @abstract
31385 */
31386class Curve {
31387
31388	/**
31389	 * Constructs a new curve.
31390	 */
31391	constructor() {
31392
31393		/**
31394		 * The type property is used for detecting the object type
31395		 * in context of serialization/deserialization.
31396		 *
31397		 * @type {string}
31398		 * @readonly
31399		 */
31400		this.type = 'Curve';
31401
31402		/**
31403		 * This value determines the amount of divisions when calculating the
31404		 * cumulative segment lengths of a curve via {@link Curve#getLengths}. To ensure
31405		 * precision when using methods like {@link Curve#getSpacedPoints}, it is
31406		 * recommended to increase the value of this property if the curve is very large.
31407		 *
31408		 * @type {number}
31409		 * @default 200
31410		 */
31411		this.arcLengthDivisions = 200;
31412
31413		/**
31414		 * Must be set to `true` if the curve parameters have changed.
31415		 *
31416		 * @type {boolean}
31417		 * @default false
31418		 */
31419		this.needsUpdate = false;
31420
31421		/**
31422		 * An internal cache that holds precomputed curve length values.
31423		 *
31424		 * @private
31425		 * @type {?Array<number>}
31426		 * @default null
31427		 */
31428		this.cacheArcLengths = null;
31429
31430	}
31431
31432	/**
31433	 * This method returns a vector in 2D or 3D space (depending on the curve definition)
31434	 * for the given interpolation factor.
31435	 *
31436	 * @abstract
31437	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
31438	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
31439	 * @return {(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
31440	 */
31441	getPoint( /* t, optionalTarget */ ) {
31442
31443		warn( 'Curve: .getPoint() not implemented.' );
31444
31445	}
31446
31447	/**
31448	 * This method returns a vector in 2D or 3D space (depending on the curve definition)
31449	 * for the given interpolation factor. Unlike {@link Curve#getPoint}, this method honors the length
31450	 * of the curve which equidistant samples.
31451	 *
31452	 * @param {number} u - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
31453	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
31454	 * @return {(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
31455	 */
31456	getPointAt( u, optionalTarget ) {
31457
31458		const t = this.getUtoTmapping( u );
31459		return this.getPoint( t, optionalTarget );
31460
31461	}
31462
31463	/**
31464	 * This method samples the curve via {@link Curve#getPoint} and returns an array of points representing
31465	 * the curve shape.
31466	 *
31467	 * @param {number} [divisions=5] - The number of divisions.
31468	 * @return {Array<(Vector2|Vector3)>} An array holding the sampled curve values. The number of points is `divisions + 1`.
31469	 */
31470	getPoints( divisions = 5 ) {
31471
31472		const points = [];
31473
31474		for ( let d = 0; d <= divisions; d ++ ) {
31475
31476			points.push( this.getPoint( d / divisions ) );
31477
31478		}
31479
31480		return points;
31481
31482	}
31483
31484	// Get sequence of points using getPointAt( u )
31485
31486	/**
31487	 * This method samples the curve via {@link Curve#getPointAt} and returns an array of points representing
31488	 * the curve shape. Unlike {@link Curve#getPoints}, this method returns equi-spaced points across the entire
31489	 * curve.
31490	 *
31491	 * @param {number} [divisions=5] - The number of divisions.
31492	 * @return {Array<(Vector2|Vector3)>} An array holding the sampled curve values. The number of points is `divisions + 1`.
31493	 */
31494	getSpacedPoints( divisions = 5 ) {
31495
31496		const points = [];
31497
31498		for ( let d = 0; d <= divisions; d ++ ) {
31499
31500			points.push( this.getPointAt( d / divisions ) );
31501
31502		}
31503
31504		return points;
31505
31506	}
31507
31508	/**
31509	 * Returns the total arc length of the curve.
31510	 *
31511	 * @return {number} The length of the curve.
31512	 */
31513	getLength() {
31514
31515		const lengths = this.getLengths();
31516		return lengths[ lengths.length - 1 ];
31517
31518	}
31519
31520	/**
31521	 * Returns an array of cumulative segment lengths of the curve.
31522	 *
31523	 * @param {number} [divisions=this.arcLengthDivisions] - The number of divisions.
31524	 * @return {Array<number>} An array holding the cumulative segment lengths.
31525	 */
31526	getLengths( divisions = this.arcLengthDivisions ) {
31527
31528		if ( this.cacheArcLengths &&
31529			( this.cacheArcLengths.length === divisions + 1 ) &&
31530			! this.needsUpdate ) {
31531
31532			return this.cacheArcLengths;
31533
31534		}
31535
31536		this.needsUpdate = false;
31537
31538		const cache = [];
31539		let current, last = this.getPoint( 0 );
31540		let sum = 0;
31541
31542		cache.push( 0 );
31543
31544		for ( let p = 1; p <= divisions; p ++ ) {
31545
31546			current = this.getPoint( p / divisions );
31547			sum += current.distanceTo( last );
31548			cache.push( sum );
31549			last = current;
31550
31551		}
31552
31553		this.cacheArcLengths = cache;
31554
31555		return cache; // { sums: cache, sum: sum }; Sum is in the last element.
31556
31557	}
31558
31559	/**
31560	 * Update the cumulative segment distance cache. The method must be called
31561	 * every time curve parameters are changed. If an updated curve is part of a
31562	 * composed curve like {@link CurvePath}, this method must be called on the
31563	 * composed curve, too.
31564	 */
31565	updateArcLengths() {
31566
31567		this.needsUpdate = true;
31568		this.getLengths();
31569
31570	}
31571
31572	/**
31573	 * Given an interpolation factor in the range `[0,1]`, this method returns an updated
31574	 * interpolation factor in the same range that can be ued to sample equidistant points
31575	 * from a curve.
31576	 *
31577	 * @param {number} u - The interpolation factor.
31578	 * @param {?number} distance - An optional distance on the curve.
31579	 * @return {number} The updated interpolation factor.
31580	 */
31581	getUtoTmapping( u, distance = null ) {
31582
31583		const arcLengths = this.getLengths();
31584
31585		let i = 0;
31586		const il = arcLengths.length;
31587
31588		let targetArcLength; // The targeted u distance value to get
31589
31590		if ( distance ) {
31591
31592			targetArcLength = distance;
31593
31594		} else {
31595
31596			targetArcLength = u * arcLengths[ il - 1 ];
31597
31598		}
31599
31600		// binary search for the index with largest value smaller than target u distance
31601
31602		let low = 0, high = il - 1, comparison;
31603
31604		while ( low <= high ) {
31605
31606			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
31607
31608			comparison = arcLengths[ i ] - targetArcLength;
31609
31610			if ( comparison < 0 ) {
31611
31612				low = i + 1;
31613
31614			} else if ( comparison > 0 ) {
31615
31616				high = i - 1;
31617
31618			} else {
31619
31620				high = i;
31621				break;
31622
31623				// DONE
31624
31625			}
31626
31627		}
31628
31629		i = high;
31630
31631		if ( arcLengths[ i ] === targetArcLength ) {
31632
31633			return i / ( il - 1 );
31634
31635		}
31636
31637		// we could get finer grain at lengths, or use simple interpolation between two points
31638
31639		const lengthBefore = arcLengths[ i ];
31640		const lengthAfter = arcLengths[ i + 1 ];
31641
31642		const segmentLength = lengthAfter - lengthBefore;
31643
31644		// determine where we are between the 'before' and 'after' points
31645
31646		const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
31647
31648		// add that fractional amount to t
31649
31650		const t = ( i + segmentFraction ) / ( il - 1 );
31651
31652		return t;
31653
31654	}
31655
31656	/**
31657	 * Returns a unit vector tangent for the given interpolation factor.
31658	 * If the derived curve does not implement its tangent derivation,
31659	 * two points a small delta apart will be used to find its gradient
31660	 * which seems to give a reasonable approximation.
31661	 *
31662	 * @param {number} t - The interpolation factor.
31663	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
31664	 * @return {(Vector2|Vector3)} The tangent vector.
31665	 */
31666	getTangent( t, optionalTarget ) {
31667
31668		const delta = 0.0001;
31669		let t1 = t - delta;
31670		let t2 = t + delta;
31671
31672		// Capping in case of danger
31673
31674		if ( t1 < 0 ) t1 = 0;
31675		if ( t2 > 1 ) t2 = 1;
31676
31677		const pt1 = this.getPoint( t1 );
31678		const pt2 = this.getPoint( t2 );
31679
31680		const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() );
31681
31682		tangent.copy( pt2 ).sub( pt1 ).normalize();
31683
31684		return tangent;
31685
31686	}
31687
31688	/**
31689	 * Same as {@link Curve#getTangent} but with equidistant samples.
31690	 *
31691	 * @param {number} u - The interpolation factor.
31692	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
31693	 * @return {(Vector2|Vector3)} The tangent vector.
31694	 * @see {@link Curve#getPointAt}
31695	 */
31696	getTangentAt( u, optionalTarget ) {
31697
31698		const t = this.getUtoTmapping( u );
31699		return this.getTangent( t, optionalTarget );
31700
31701	}
31702
31703	/**
31704	 * Generates the Frenet Frames. Requires a curve definition in 3D space. Used
31705	 * in geometries like {@link TubeGeometry} or {@link ExtrudeGeometry}.
31706	 *
31707	 * @param {number} segments - The number of segments.
31708	 * @param {boolean} [closed=false] - Whether the curve is closed or not.
31709	 * @return {{tangents: Array<Vector3>, normals: Array<Vector3>, binormals: Array<Vector3>}} The Frenet Frames.
31710	 */
31711	computeFrenetFrames( segments, closed = false ) {
31712
31713		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
31714
31715		const normal = new Vector3();
31716
31717		const tangents = [];
31718		const normals = [];
31719		const binormals = [];
31720
31721		const vec = new Vector3();
31722		const mat = new Matrix4();
31723
31724		// compute the tangent vectors for each segment on the curve
31725
31726		for ( let i = 0; i <= segments; i ++ ) {
31727
31728			const u = i / segments;
31729
31730			tangents[ i ] = this.getTangentAt( u, new Vector3() );
31731
31732		}
31733
31734		// select an initial normal vector perpendicular to the first tangent vector,
31735		// and in the direction of the minimum tangent xyz component
31736
31737		normals[ 0 ] = new Vector3();
31738		binormals[ 0 ] = new Vector3();
31739		let min = Number.MAX_VALUE;
31740		const tx = Math.abs( tangents[ 0 ].x );
31741		const ty = Math.abs( tangents[ 0 ].y );
31742		const tz = Math.abs( tangents[ 0 ].z );
31743
31744		if ( tx <= min ) {
31745
31746			min = tx;
31747			normal.set( 1, 0, 0 );
31748
31749		}
31750
31751		if ( ty <= min ) {
31752
31753			min = ty;
31754			normal.set( 0, 1, 0 );
31755
31756		}
31757
31758		if ( tz <= min ) {
31759
31760			normal.set( 0, 0, 1 );
31761
31762		}
31763
31764		vec.crossVectors( tangents[ 0 ], normal ).normalize();
31765
31766		normals[ 0 ].crossVectors( tangents[ 0 ], vec );
31767		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
31768
31769
31770		// compute the slowly-varying normal and binormal vectors for each segment on the curve
31771
31772		for ( let i = 1; i <= segments; i ++ ) {
31773
31774			normals[ i ] = normals[ i - 1 ].clone();
31775
31776			binormals[ i ] = binormals[ i - 1 ].clone();
31777
31778			vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
31779
31780			if ( vec.length() > Number.EPSILON ) {
31781
31782				vec.normalize();
31783
31784				const theta = Math.acos( clamp( tangents[ i - 1 ].dot( tangents[ i ] ), -1, 1 ) ); // clamp for floating pt errors
31785
31786				normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
31787
31788			}
31789
31790			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31791
31792		}
31793
31794		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
31795
31796		if ( closed === true ) {
31797
31798			let theta = Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), -1, 1 ) );
31799			theta /= segments;
31800
31801			if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
31802
31803				theta = - theta;
31804
31805			}
31806
31807			for ( let i = 1; i <= segments; i ++ ) {
31808
31809				// twist a little...
31810				normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
31811				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
31812
31813			}
31814
31815		}
31816
31817		return {
31818			tangents: tangents,
31819			normals: normals,
31820			binormals: binormals
31821		};
31822
31823	}
31824
31825	/**
31826	 * Returns a new curve with copied values from this instance.
31827	 *
31828	 * @return {Curve} A clone of this instance.
31829	 */
31830	clone() {
31831
31832		return new this.constructor().copy( this );
31833
31834	}
31835
31836	/**
31837	 * Copies the values of the given curve to this instance.
31838	 *
31839	 * @param {Curve} source - The curve to copy.
31840	 * @return {Curve} A reference to this curve.
31841	 */
31842	copy( source ) {
31843
31844		this.arcLengthDivisions = source.arcLengthDivisions;
31845
31846		return this;
31847
31848	}
31849
31850	/**
31851	 * Serializes the curve into JSON.
31852	 *
31853	 * @return {Object} A JSON object representing the serialized curve.
31854	 * @see {@link ObjectLoader#parse}
31855	 */
31856	toJSON() {
31857
31858		const data = {
31859			metadata: {
31860				version: 4.7,
31861				type: 'Curve',
31862				generator: 'Curve.toJSON'
31863			}
31864		};
31865
31866		data.arcLengthDivisions = this.arcLengthDivisions;
31867		data.type = this.type;
31868
31869		return data;
31870
31871	}
31872
31873	/**
31874	 * Deserializes the curve from the given JSON.
31875	 *
31876	 * @param {Object} json - The JSON holding the serialized curve.
31877	 * @return {Curve} A reference to this curve.
31878	 */
31879	fromJSON( json ) {
31880
31881		this.arcLengthDivisions = json.arcLengthDivisions;
31882
31883		return this;
31884
31885	}
31886
31887}
31888
31889/**
31890 * A curve representing an ellipse.
31891 *
31892 * ```js
31893 * const curve = new THREE.EllipseCurve(
31894 * 	0, 0,
31895 * 	10, 10,
31896 * 	0, 2 * Math.PI,
31897 * 	false,
31898 * 	0
31899 * );
31900 *
31901 * const points = curve.getPoints( 50 );
31902 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
31903 *
31904 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
31905 *
31906 * // Create the final object to add to the scene
31907 * const ellipse = new THREE.Line( geometry, material );
31908 * ```
31909 *
31910 * @augments Curve
31911 */
31912class EllipseCurve extends Curve {
31913
31914	/**
31915	 * Constructs a new ellipse curve.
31916	 *
31917	 * @param {number} [aX=0] - The X center of the ellipse.
31918	 * @param {number} [aY=0] - The Y center of the ellipse.
31919	 * @param {number} [xRadius=1] - The radius of the ellipse in the x direction.
31920	 * @param {number} [yRadius=1] - The radius of the ellipse in the y direction.
31921	 * @param {number} [aStartAngle=0] - The start angle of the curve in radians starting from the positive X axis.
31922	 * @param {number} [aEndAngle=Math.PI*2] - The end angle of the curve in radians starting from the positive X axis.
31923	 * @param {boolean} [aClockwise=false] - Whether the ellipse is drawn clockwise or not.
31924	 * @param {number} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
31925	 */
31926	constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) {
31927
31928		super();
31929
31930		/**
31931		 * This flag can be used for type testing.
31932		 *
31933		 * @type {boolean}
31934		 * @readonly
31935		 * @default true
31936		 */
31937		this.isEllipseCurve = true;
31938
31939		this.type = 'EllipseCurve';
31940
31941		/**
31942		 * The X center of the ellipse.
31943		 *
31944		 * @type {number}
31945		 * @default 0
31946		 */
31947		this.aX = aX;
31948
31949		/**
31950		 * The Y center of the ellipse.
31951		 *
31952		 * @type {number}
31953		 * @default 0
31954		 */
31955		this.aY = aY;
31956
31957		/**
31958		 * The radius of the ellipse in the x direction.
31959		 * Setting the this value equal to the {@link EllipseCurve#yRadius} will result in a circle.
31960		 *
31961		 * @type {number}
31962		 * @default 1
31963		 */
31964		this.xRadius = xRadius;
31965
31966		/**
31967		 * The radius of the ellipse in the y direction.
31968		 * Setting the this value equal to the {@link EllipseCurve#xRadius} will result in a circle.
31969		 *
31970		 * @type {number}
31971		 * @default 1
31972		 */
31973		this.yRadius = yRadius;
31974
31975		/**
31976		 * The start angle of the curve in radians starting from the positive X axis.
31977		 *
31978		 * @type {number}
31979		 * @default 0
31980		 */
31981		this.aStartAngle = aStartAngle;
31982
31983		/**
31984		 * The end angle of the curve in radians starting from the positive X axis.
31985		 *
31986		 * @type {number}
31987		 * @default Math.PI*2
31988		 */
31989		this.aEndAngle = aEndAngle;
31990
31991		/**
31992		 * Whether the ellipse is drawn clockwise or not.
31993		 *
31994		 * @type {boolean}
31995		 * @default false
31996		 */
31997		this.aClockwise = aClockwise;
31998
31999		/**
32000		 * The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
32001		 *
32002		 * @type {number}
32003		 * @default 0
32004		 */
32005		this.aRotation = aRotation;
32006
32007	}
32008
32009	/**
32010	 * Returns a point on the curve.
32011	 *
32012	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32013	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
32014	 * @return {Vector2} The position on the curve.
32015	 */
32016	getPoint( t, optionalTarget = new Vector2() ) {
32017
32018		const point = optionalTarget;
32019
32020		const twoPi = Math.PI * 2;
32021		let deltaAngle = this.aEndAngle - this.aStartAngle;
32022		const samePoints = Math.abs( deltaAngle ) < Number.EPSILON;
32023
32024		// ensures that deltaAngle is 0 .. 2 PI
32025		while ( deltaAngle < 0 ) deltaAngle += twoPi;
32026		while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
32027
32028		if ( deltaAngle < Number.EPSILON ) {
32029
32030			if ( samePoints ) {
32031
32032				deltaAngle = 0;
32033
32034			} else {
32035
32036				deltaAngle = twoPi;
32037
32038			}
32039
32040		}
32041
32042		if ( this.aClockwise === true && ! samePoints ) {
32043
32044			if ( deltaAngle === twoPi ) {
32045
32046				deltaAngle = - twoPi;
32047
32048			} else {
32049
32050				deltaAngle = deltaAngle - twoPi;
32051
32052			}
32053
32054		}
32055
32056		const angle = this.aStartAngle + t * deltaAngle;
32057		let x = this.aX + this.xRadius * Math.cos( angle );
32058		let y = this.aY + this.yRadius * Math.sin( angle );
32059
32060		if ( this.aRotation !== 0 ) {
32061
32062			const cos = Math.cos( this.aRotation );
32063			const sin = Math.sin( this.aRotation );
32064
32065			const tx = x - this.aX;
32066			const ty = y - this.aY;
32067
32068			// Rotate the point about the center of the ellipse.
32069			x = tx * cos - ty * sin + this.aX;
32070			y = tx * sin + ty * cos + this.aY;
32071
32072		}
32073
32074		return point.set( x, y );
32075
32076	}
32077
32078	copy( source ) {
32079
32080		super.copy( source );
32081
32082		this.aX = source.aX;
32083		this.aY = source.aY;
32084
32085		this.xRadius = source.xRadius;
32086		this.yRadius = source.yRadius;
32087
32088		this.aStartAngle = source.aStartAngle;
32089		this.aEndAngle = source.aEndAngle;
32090
32091		this.aClockwise = source.aClockwise;
32092
32093		this.aRotation = source.aRotation;
32094
32095		return this;
32096
32097	}
32098
32099	toJSON() {
32100
32101		const data = super.toJSON();
32102
32103		data.aX = this.aX;
32104		data.aY = this.aY;
32105
32106		data.xRadius = this.xRadius;
32107		data.yRadius = this.yRadius;
32108
32109		data.aStartAngle = this.aStartAngle;
32110		data.aEndAngle = this.aEndAngle;
32111
32112		data.aClockwise = this.aClockwise;
32113
32114		data.aRotation = this.aRotation;
32115
32116		return data;
32117
32118	}
32119
32120	fromJSON( json ) {
32121
32122		super.fromJSON( json );
32123
32124		this.aX = json.aX;
32125		this.aY = json.aY;
32126
32127		this.xRadius = json.xRadius;
32128		this.yRadius = json.yRadius;
32129
32130		this.aStartAngle = json.aStartAngle;
32131		this.aEndAngle = json.aEndAngle;
32132
32133		this.aClockwise = json.aClockwise;
32134
32135		this.aRotation = json.aRotation;
32136
32137		return this;
32138
32139	}
32140
32141}
32142
32143/**
32144 * A curve representing an arc.
32145 *
32146 * @augments EllipseCurve
32147 */
32148class ArcCurve extends EllipseCurve {
32149
32150	/**
32151	 * Constructs a new arc curve.
32152	 *
32153	 * @param {number} [aX=0] - The X center of the ellipse.
32154	 * @param {number} [aY=0] - The Y center of the ellipse.
32155	 * @param {number} [aRadius=1] - The radius of the ellipse in the x direction.
32156	 * @param {number} [aStartAngle=0] - The start angle of the curve in radians starting from the positive X axis.
32157	 * @param {number} [aEndAngle=Math.PI*2] - The end angle of the curve in radians starting from the positive X axis.
32158	 * @param {boolean} [aClockwise=false] - Whether the ellipse is drawn clockwise or not.
32159	 */
32160	constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
32161
32162		super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
32163
32164		/**
32165		 * This flag can be used for type testing.
32166		 *
32167		 * @type {boolean}
32168		 * @readonly
32169		 * @default true
32170		 */
32171		this.isArcCurve = true;
32172
32173		this.type = 'ArcCurve';
32174
32175	}
32176
32177}
32178
32179function CubicPoly() {
32180
32181	/**
32182	 * Centripetal CatmullRom Curve - which is useful for avoiding
32183	* cusps and self-intersections in non-uniform catmull rom curves.
32184	* http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
32185	*
32186	* curve.type accepts centripetal(default), chordal and catmullrom
32187	* curve.tension is used for catmullrom which defaults to 0.5
32188	*/
32189
32190	/*
32191	Based on an optimized c++ solution in
32192	- http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
32193	- http://ideone.com/NoEbVM
32194
32195	This CubicPoly class could be used for reusing some variables and calculations,
32196	but for three.js curve use, it could be possible inlined and flatten into a single function call
32197	which can be placed in CurveUtils.
32198	*/
32199
32200	let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
32201
32202	/*
32203	 * Compute coefficients for a cubic polynomial
32204	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
32205	 * such that
32206	 *   p(0) = x0, p(1) = x1
32207	 *  and
32208	 *   p'(0) = t0, p'(1) = t1.
32209	 */
32210	function init( x0, x1, t0, t1 ) {
32211
32212		c0 = x0;
32213		c1 = t0;
32214		c2 = -3 * x0 + 3 * x1 - 2 * t0 - t1;
32215		c3 = 2 * x0 - 2 * x1 + t0 + t1;
32216
32217	}
32218
32219	return {
32220
32221		initCatmullRom: function ( x0, x1, x2, x3, tension ) {
32222
32223			init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
32224
32225		},
32226
32227		initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
32228
32229			// compute tangents when parameterized in [t1,t2]
32230			let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
32231			let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
32232
32233			// rescale tangents for parametrization in [0,1]
32234			t1 *= dt1;
32235			t2 *= dt1;
32236
32237			init( x1, x2, t1, t2 );
32238
32239		},
32240
32241		calc: function ( t ) {
32242
32243			const t2 = t * t;
32244			const t3 = t2 * t;
32245			return c0 + c1 * t + c2 * t2 + c3 * t3;
32246
32247		}
32248
32249	};
32250
32251}
32252
32253//
32254
32255const tmp = /*@__PURE__*/ new Vector3();
32256const tmp2 = /*@__PURE__*/ new Vector3();
32257const px = /*@__PURE__*/ new CubicPoly();
32258const py = /*@__PURE__*/ new CubicPoly();
32259const pz = /*@__PURE__*/ new CubicPoly();
32260
32261/**
32262 * A curve representing a Catmull-Rom spline.
32263 *
32264 * ```js
32265 * //Create a closed wavey loop
32266 * const curve = new THREE.CatmullRomCurve3( [
32267 * 	new THREE.Vector3( -10, 0, 10 ),
32268 * 	new THREE.Vector3( -5, 5, 5 ),
32269 * 	new THREE.Vector3( 0, 0, 0 ),
32270 * 	new THREE.Vector3( 5, -5, 5 ),
32271 * 	new THREE.Vector3( 10, 0, 10 )
32272 * ] );
32273 *
32274 * const points = curve.getPoints( 50 );
32275 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
32276 *
32277 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
32278 *
32279 * // Create the final object to add to the scene
32280 * const curveObject = new THREE.Line( geometry, material );
32281 * ```
32282 *
32283 * @augments Curve
32284 */
32285class CatmullRomCurve3 extends Curve {
32286
32287	/**
32288	 * Constructs a new Catmull-Rom curve.
32289	 *
32290	 * @param {Array<Vector3>} [points] - An array of 3D points defining the curve.
32291	 * @param {boolean} [closed=false] - Whether the curve is closed or not.
32292	 * @param {('centripetal'|'chordal'|'catmullrom')} [curveType='centripetal'] - The curve type.
32293	 * @param {number} [tension=0.5] - Tension of the curve.
32294	 */
32295	constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) {
32296
32297		super();
32298
32299		/**
32300		 * This flag can be used for type testing.
32301		 *
32302		 * @type {boolean}
32303		 * @readonly
32304		 * @default true
32305		 */
32306		this.isCatmullRomCurve3 = true;
32307
32308		this.type = 'CatmullRomCurve3';
32309
32310		/**
32311		 * An array of 3D points defining the curve.
32312		 *
32313		 * @type {Array<Vector3>}
32314		 */
32315		this.points = points;
32316
32317		/**
32318		 * Whether the curve is closed or not.
32319		 *
32320		 * @type {boolean}
32321		 * @default false
32322		 */
32323		this.closed = closed;
32324
32325		/**
32326		 * The curve type.
32327		 *
32328		 * @type {('centripetal'|'chordal'|'catmullrom')}
32329		 * @default 'centripetal'
32330		 */
32331		this.curveType = curveType;
32332
32333		/**
32334		 * Tension of the curve.
32335		 *
32336		 * @type {number}
32337		 * @default 0.5
32338		 */
32339		this.tension = tension;
32340
32341	}
32342
32343	/**
32344	 * Returns a point on the curve.
32345	 *
32346	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32347	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
32348	 * @return {Vector3} The position on the curve.
32349	 */
32350	getPoint( t, optionalTarget = new Vector3() ) {
32351
32352		const point = optionalTarget;
32353
32354		const points = this.points;
32355		const l = points.length;
32356
32357		const p = ( l - ( this.closed ? 0 : 1 ) ) * t;
32358		let intPoint = Math.floor( p );
32359		let weight = p - intPoint;
32360
32361		if ( this.closed ) {
32362
32363			intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;
32364
32365		} else if ( weight === 0 && intPoint === l - 1 ) {
32366
32367			intPoint = l - 2;
32368			weight = 1;
32369
32370		}
32371
32372		let p0, p3; // 4 points (p1 & p2 defined below)
32373
32374		if ( this.closed || intPoint > 0 ) {
32375
32376			p0 = points[ ( intPoint - 1 ) % l ];
32377
32378		} else {
32379
32380			// extrapolate first point
32381			tmp2.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
32382			p0 = tmp2;
32383
32384		}
32385
32386		const p1 = points[ intPoint % l ];
32387		const p2 = points[ ( intPoint + 1 ) % l ];
32388
32389		if ( this.closed || intPoint + 2 < l ) {
32390
32391			p3 = points[ ( intPoint + 2 ) % l ];
32392
32393		} else {
32394
32395			// extrapolate last point
32396			tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
32397			p3 = tmp;
32398
32399		}
32400
32401		if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {
32402
32403			// init Centripetal / Chordal Catmull-Rom
32404			const pow = this.curveType === 'chordal' ? 0.5 : 0.25;
32405			let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
32406			let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
32407			let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );
32408
32409			// safety check for repeated points
32410			if ( dt1 < 1e-4 ) dt1 = 1.0;
32411			if ( dt0 < 1e-4 ) dt0 = dt1;
32412			if ( dt2 < 1e-4 ) dt2 = dt1;
32413
32414			px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
32415			py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
32416			pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
32417
32418		} else if ( this.curveType === 'catmullrom' ) {
32419
32420			px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );
32421			py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );
32422			pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );
32423
32424		}
32425
32426		point.set(
32427			px.calc( weight ),
32428			py.calc( weight ),
32429			pz.calc( weight )
32430		);
32431
32432		return point;
32433
32434	}
32435
32436	copy( source ) {
32437
32438		super.copy( source );
32439
32440		this.points = [];
32441
32442		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
32443
32444			const point = source.points[ i ];
32445
32446			this.points.push( point.clone() );
32447
32448		}
32449
32450		this.closed = source.closed;
32451		this.curveType = source.curveType;
32452		this.tension = source.tension;
32453
32454		return this;
32455
32456	}
32457
32458	toJSON() {
32459
32460		const data = super.toJSON();
32461
32462		data.points = [];
32463
32464		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
32465
32466			const point = this.points[ i ];
32467			data.points.push( point.toArray() );
32468
32469		}
32470
32471		data.closed = this.closed;
32472		data.curveType = this.curveType;
32473		data.tension = this.tension;
32474
32475		return data;
32476
32477	}
32478
32479	fromJSON( json ) {
32480
32481		super.fromJSON( json );
32482
32483		this.points = [];
32484
32485		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
32486
32487			const point = json.points[ i ];
32488			this.points.push( new Vector3().fromArray( point ) );
32489
32490		}
32491
32492		this.closed = json.closed;
32493		this.curveType = json.curveType;
32494		this.tension = json.tension;
32495
32496		return this;
32497
32498	}
32499
32500}
32501
32502/**
32503 * Interpolations contains spline and Bézier functions internally used by concrete curve classes.
32504 *
32505 * Bezier Curves formulas obtained from: https://en.wikipedia.org/wiki/B%C3%A9zier_curve
32506 *
32507 * @module Interpolations
32508 */
32509
32510/**
32511 * Computes a point on a Catmull-Rom spline.
32512 *
32513 * @param {number} t - The interpolation factor.
32514 * @param {number} p0 - The first control point.
32515 * @param {number} p1 - The second control point.
32516 * @param {number} p2 - The third control point.
32517 * @param {number} p3 - The fourth control point.
32518 * @return {number} The calculated point on a Catmull-Rom spline.
32519 */
32520function CatmullRom( t, p0, p1, p2, p3 ) {
32521
32522	const v0 = ( p2 - p0 ) * 0.5;
32523	const v1 = ( p3 - p1 ) * 0.5;
32524	const t2 = t * t;
32525	const t3 = t * t2;
32526	return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( -3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
32527
32528}
32529
32530//
32531
32532function QuadraticBezierP0( t, p ) {
32533
32534	const k = 1 - t;
32535	return k * k * p;
32536
32537}
32538
32539function QuadraticBezierP1( t, p ) {
32540
32541	return 2 * ( 1 - t ) * t * p;
32542
32543}
32544
32545function QuadraticBezierP2( t, p ) {
32546
32547	return t * t * p;
32548
32549}
32550
32551/**
32552 * Computes a point on a Quadratic Bezier curve.
32553 *
32554 * @param {number} t - The interpolation factor.
32555 * @param {number} p0 - The first control point.
32556 * @param {number} p1 - The second control point.
32557 * @param {number} p2 - The third control point.
32558 * @return {number} The calculated point on a Quadratic Bezier curve.
32559 */
32560function QuadraticBezier( t, p0, p1, p2 ) {
32561
32562	return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +
32563		QuadraticBezierP2( t, p2 );
32564
32565}
32566
32567//
32568
32569function CubicBezierP0( t, p ) {
32570
32571	const k = 1 - t;
32572	return k * k * k * p;
32573
32574}
32575
32576function CubicBezierP1( t, p ) {
32577
32578	const k = 1 - t;
32579	return 3 * k * k * t * p;
32580
32581}
32582
32583function CubicBezierP2( t, p ) {
32584
32585	return 3 * ( 1 - t ) * t * t * p;
32586
32587}
32588
32589function CubicBezierP3( t, p ) {
32590
32591	return t * t * t * p;
32592
32593}
32594
32595/**
32596 * Computes a point on a Cubic Bezier curve.
32597 *
32598 * @param {number} t - The interpolation factor.
32599 * @param {number} p0 - The first control point.
32600 * @param {number} p1 - The second control point.
32601 * @param {number} p2 - The third control point.
32602 * @param {number} p3 - The fourth control point.
32603 * @return {number} The calculated point on a Cubic Bezier curve.
32604 */
32605function CubicBezier( t, p0, p1, p2, p3 ) {
32606
32607	return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +
32608		CubicBezierP3( t, p3 );
32609
32610}
32611
32612/**
32613 * A curve representing a 2D Cubic Bezier curve.
32614 *
32615 * ```js
32616 * const curve = new THREE.CubicBezierCurve(
32617 * 	new THREE.Vector2( - 0, 0 ),
32618 * 	new THREE.Vector2( - 5, 15 ),
32619 * 	new THREE.Vector2( 20, 15 ),
32620 * 	new THREE.Vector2( 10, 0 )
32621 * );
32622 *
32623 * const points = curve.getPoints( 50 );
32624 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
32625 *
32626 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
32627 *
32628 * // Create the final object to add to the scene
32629 * const curveObject = new THREE.Line( geometry, material );
32630 * ```
32631 *
32632 * @augments Curve
32633 */
32634class CubicBezierCurve extends Curve {
32635
32636	/**
32637	 * Constructs a new Cubic Bezier curve.
32638	 *
32639	 * @param {Vector2} [v0] - The start point.
32640	 * @param {Vector2} [v1] - The first control point.
32641	 * @param {Vector2} [v2] - The second control point.
32642	 * @param {Vector2} [v3] - The end point.
32643	 */
32644	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) {
32645
32646		super();
32647
32648		/**
32649		 * This flag can be used for type testing.
32650		 *
32651		 * @type {boolean}
32652		 * @readonly
32653		 * @default true
32654		 */
32655		this.isCubicBezierCurve = true;
32656
32657		this.type = 'CubicBezierCurve';
32658
32659		/**
32660		 * The start point.
32661		 *
32662		 * @type {Vector2}
32663		 */
32664		this.v0 = v0;
32665
32666		/**
32667		 * The first control point.
32668		 *
32669		 * @type {Vector2}
32670		 */
32671		this.v1 = v1;
32672
32673		/**
32674		 * The second control point.
32675		 *
32676		 * @type {Vector2}
32677		 */
32678		this.v2 = v2;
32679
32680		/**
32681		 * The end point.
32682		 *
32683		 * @type {Vector2}
32684		 */
32685		this.v3 = v3;
32686
32687	}
32688
32689	/**
32690	 * Returns a point on the curve.
32691	 *
32692	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32693	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
32694	 * @return {Vector2} The position on the curve.
32695	 */
32696	getPoint( t, optionalTarget = new Vector2() ) {
32697
32698		const point = optionalTarget;
32699
32700		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32701
32702		point.set(
32703			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32704			CubicBezier( t, v0.y, v1.y, v2.y, v3.y )
32705		);
32706
32707		return point;
32708
32709	}
32710
32711	copy( source ) {
32712
32713		super.copy( source );
32714
32715		this.v0.copy( source.v0 );
32716		this.v1.copy( source.v1 );
32717		this.v2.copy( source.v2 );
32718		this.v3.copy( source.v3 );
32719
32720		return this;
32721
32722	}
32723
32724	toJSON() {
32725
32726		const data = super.toJSON();
32727
32728		data.v0 = this.v0.toArray();
32729		data.v1 = this.v1.toArray();
32730		data.v2 = this.v2.toArray();
32731		data.v3 = this.v3.toArray();
32732
32733		return data;
32734
32735	}
32736
32737	fromJSON( json ) {
32738
32739		super.fromJSON( json );
32740
32741		this.v0.fromArray( json.v0 );
32742		this.v1.fromArray( json.v1 );
32743		this.v2.fromArray( json.v2 );
32744		this.v3.fromArray( json.v3 );
32745
32746		return this;
32747
32748	}
32749
32750}
32751
32752/**
32753 * A curve representing a 3D Cubic Bezier curve.
32754 *
32755 * @augments Curve
32756 */
32757class CubicBezierCurve3 extends Curve {
32758
32759	/**
32760	 * Constructs a new Cubic Bezier curve.
32761	 *
32762	 * @param {Vector3} [v0] - The start point.
32763	 * @param {Vector3} [v1] - The first control point.
32764	 * @param {Vector3} [v2] - The second control point.
32765	 * @param {Vector3} [v3] - The end point.
32766	 */
32767	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) {
32768
32769		super();
32770
32771		/**
32772		 * This flag can be used for type testing.
32773		 *
32774		 * @type {boolean}
32775		 * @readonly
32776		 * @default true
32777		 */
32778		this.isCubicBezierCurve3 = true;
32779
32780		this.type = 'CubicBezierCurve3';
32781
32782		/**
32783		 * The start point.
32784		 *
32785		 * @type {Vector3}
32786		 */
32787		this.v0 = v0;
32788
32789		/**
32790		 * The first control point.
32791		 *
32792		 * @type {Vector3}
32793		 */
32794		this.v1 = v1;
32795
32796		/**
32797		 * The second control point.
32798		 *
32799		 * @type {Vector3}
32800		 */
32801		this.v2 = v2;
32802
32803		/**
32804		 * The end point.
32805		 *
32806		 * @type {Vector3}
32807		 */
32808		this.v3 = v3;
32809
32810	}
32811
32812	/**
32813	 * Returns a point on the curve.
32814	 *
32815	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
32816	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
32817	 * @return {Vector3} The position on the curve.
32818	 */
32819	getPoint( t, optionalTarget = new Vector3() ) {
32820
32821		const point = optionalTarget;
32822
32823		const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;
32824
32825		point.set(
32826			CubicBezier( t, v0.x, v1.x, v2.x, v3.x ),
32827			CubicBezier( t, v0.y, v1.y, v2.y, v3.y ),
32828			CubicBezier( t, v0.z, v1.z, v2.z, v3.z )
32829		);
32830
32831		return point;
32832
32833	}
32834
32835	copy( source ) {
32836
32837		super.copy( source );
32838
32839		this.v0.copy( source.v0 );
32840		this.v1.copy( source.v1 );
32841		this.v2.copy( source.v2 );
32842		this.v3.copy( source.v3 );
32843
32844		return this;
32845
32846	}
32847
32848	toJSON() {
32849
32850		const data = super.toJSON();
32851
32852		data.v0 = this.v0.toArray();
32853		data.v1 = this.v1.toArray();
32854		data.v2 = this.v2.toArray();
32855		data.v3 = this.v3.toArray();
32856
32857		return data;
32858
32859	}
32860
32861	fromJSON( json ) {
32862
32863		super.fromJSON( json );
32864
32865		this.v0.fromArray( json.v0 );
32866		this.v1.fromArray( json.v1 );
32867		this.v2.fromArray( json.v2 );
32868		this.v3.fromArray( json.v3 );
32869
32870		return this;
32871
32872	}
32873
32874}
32875
32876/**
32877 * A curve representing a 2D line segment.
32878 *
32879 * @augments Curve
32880 */
32881class LineCurve extends Curve {
32882
32883	/**
32884	 * Constructs a new line curve.
32885	 *
32886	 * @param {Vector2} [v1] - The start point.
32887	 * @param {Vector2} [v2] - The end point.
32888	 */
32889	constructor( v1 = new Vector2(), v2 = new Vector2() ) {
32890
32891		super();
32892
32893		/**
32894		 * This flag can be used for type testing.
32895		 *
32896		 * @type {boolean}
32897		 * @readonly
32898		 * @default true
32899		 */
32900		this.isLineCurve = true;
32901
32902		this.type = 'LineCurve';
32903
32904		/**
32905		 * The start point.
32906		 *
32907		 * @type {Vector2}
32908		 */
32909		this.v1 = v1;
32910
32911		/**
32912		 * The end point.
32913		 *
32914		 * @type {Vector2}
32915		 */
32916		this.v2 = v2;
32917
32918	}
32919
32920	/**
32921	 * Returns a point on the line.
32922	 *
32923	 * @param {number} t - A interpolation factor representing a position on the line. Must be in the range `[0,1]`.
32924	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
32925	 * @return {Vector2} The position on the line.
32926	 */
32927	getPoint( t, optionalTarget = new Vector2() ) {
32928
32929		const point = optionalTarget;
32930
32931		if ( t === 1 ) {
32932
32933			point.copy( this.v2 );
32934
32935		} else {
32936
32937			point.copy( this.v2 ).sub( this.v1 );
32938			point.multiplyScalar( t ).add( this.v1 );
32939
32940		}
32941
32942		return point;
32943
32944	}
32945
32946	// Line curve is linear, so we can overwrite default getPointAt
32947	getPointAt( u, optionalTarget ) {
32948
32949		return this.getPoint( u, optionalTarget );
32950
32951	}
32952
32953	getTangent( t, optionalTarget = new Vector2() ) {
32954
32955		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
32956
32957	}
32958
32959	getTangentAt( u, optionalTarget ) {
32960
32961		return this.getTangent( u, optionalTarget );
32962
32963	}
32964
32965	copy( source ) {
32966
32967		super.copy( source );
32968
32969		this.v1.copy( source.v1 );
32970		this.v2.copy( source.v2 );
32971
32972		return this;
32973
32974	}
32975
32976	toJSON() {
32977
32978		const data = super.toJSON();
32979
32980		data.v1 = this.v1.toArray();
32981		data.v2 = this.v2.toArray();
32982
32983		return data;
32984
32985	}
32986
32987	fromJSON( json ) {
32988
32989		super.fromJSON( json );
32990
32991		this.v1.fromArray( json.v1 );
32992		this.v2.fromArray( json.v2 );
32993
32994		return this;
32995
32996	}
32997
32998}
32999
33000/**
33001 * A curve representing a 3D line segment.
33002 *
33003 * @augments Curve
33004 */
33005class LineCurve3 extends Curve {
33006
33007	/**
33008	 * Constructs a new line curve.
33009	 *
33010	 * @param {Vector3} [v1] - The start point.
33011	 * @param {Vector3} [v2] - The end point.
33012	 */
33013	constructor( v1 = new Vector3(), v2 = new Vector3() ) {
33014
33015		super();
33016
33017		/**
33018		 * This flag can be used for type testing.
33019		 *
33020		 * @type {boolean}
33021		 * @readonly
33022		 * @default true
33023		 */
33024		this.isLineCurve3 = true;
33025
33026		this.type = 'LineCurve3';
33027
33028		/**
33029		 * The start point.
33030		 *
33031		 * @type {Vector3}
33032		 */
33033		this.v1 = v1;
33034
33035		/**
33036		 * The end point.
33037		 *
33038		 * @type {Vector2}
33039		 */
33040		this.v2 = v2;
33041
33042	}
33043
33044	/**
33045	 * Returns a point on the line.
33046	 *
33047	 * @param {number} t - A interpolation factor representing a position on the line. Must be in the range `[0,1]`.
33048	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
33049	 * @return {Vector3} The position on the line.
33050	 */
33051	getPoint( t, optionalTarget = new Vector3() ) {
33052
33053		const point = optionalTarget;
33054
33055		if ( t === 1 ) {
33056
33057			point.copy( this.v2 );
33058
33059		} else {
33060
33061			point.copy( this.v2 ).sub( this.v1 );
33062			point.multiplyScalar( t ).add( this.v1 );
33063
33064		}
33065
33066		return point;
33067
33068	}
33069
33070	// Line curve is linear, so we can overwrite default getPointAt
33071	getPointAt( u, optionalTarget ) {
33072
33073		return this.getPoint( u, optionalTarget );
33074
33075	}
33076
33077	getTangent( t, optionalTarget = new Vector3() ) {
33078
33079		return optionalTarget.subVectors( this.v2, this.v1 ).normalize();
33080
33081	}
33082
33083	getTangentAt( u, optionalTarget ) {
33084
33085		return this.getTangent( u, optionalTarget );
33086
33087	}
33088
33089	copy( source ) {
33090
33091		super.copy( source );
33092
33093		this.v1.copy( source.v1 );
33094		this.v2.copy( source.v2 );
33095
33096		return this;
33097
33098	}
33099
33100	toJSON() {
33101
33102		const data = super.toJSON();
33103
33104		data.v1 = this.v1.toArray();
33105		data.v2 = this.v2.toArray();
33106
33107		return data;
33108
33109	}
33110
33111	fromJSON( json ) {
33112
33113		super.fromJSON( json );
33114
33115		this.v1.fromArray( json.v1 );
33116		this.v2.fromArray( json.v2 );
33117
33118		return this;
33119
33120	}
33121
33122}
33123
33124/**
33125 * A curve representing a 2D Quadratic Bezier curve.
33126 *
33127 * ```js
33128 * const curve = new THREE.QuadraticBezierCurve(
33129 * 	new THREE.Vector2( - 10, 0 ),
33130 * 	new THREE.Vector2( 20, 15 ),
33131 * 	new THREE.Vector2( 10, 0 )
33132 * )
33133 *
33134 * const points = curve.getPoints( 50 );
33135 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
33136 *
33137 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
33138 *
33139 * // Create the final object to add to the scene
33140 * const curveObject = new THREE.Line( geometry, material );
33141 * ```
33142 *
33143 * @augments Curve
33144 */
33145class QuadraticBezierCurve extends Curve {
33146
33147	/**
33148	 * Constructs a new Quadratic Bezier curve.
33149	 *
33150	 * @param {Vector2} [v0] - The start point.
33151	 * @param {Vector2} [v1] - The control point.
33152	 * @param {Vector2} [v2] - The end point.
33153	 */
33154	constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) {
33155
33156		super();
33157
33158		/**
33159		 * This flag can be used for type testing.
33160		 *
33161		 * @type {boolean}
33162		 * @readonly
33163		 * @default true
33164		 */
33165		this.isQuadraticBezierCurve = true;
33166
33167		this.type = 'QuadraticBezierCurve';
33168
33169		/**
33170		 * The start point.
33171		 *
33172		 * @type {Vector2}
33173		 */
33174		this.v0 = v0;
33175
33176		/**
33177		 * The control point.
33178		 *
33179		 * @type {Vector2}
33180		 */
33181		this.v1 = v1;
33182
33183		/**
33184		 * The end point.
33185		 *
33186		 * @type {Vector2}
33187		 */
33188		this.v2 = v2;
33189
33190	}
33191
33192	/**
33193	 * Returns a point on the curve.
33194	 *
33195	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
33196	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
33197	 * @return {Vector2} The position on the curve.
33198	 */
33199	getPoint( t, optionalTarget = new Vector2() ) {
33200
33201		const point = optionalTarget;
33202
33203		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
33204
33205		point.set(
33206			QuadraticBezier( t, v0.x, v1.x, v2.x ),
33207			QuadraticBezier( t, v0.y, v1.y, v2.y )
33208		);
33209
33210		return point;
33211
33212	}
33213
33214	copy( source ) {
33215
33216		super.copy( source );
33217
33218		this.v0.copy( source.v0 );
33219		this.v1.copy( source.v1 );
33220		this.v2.copy( source.v2 );
33221
33222		return this;
33223
33224	}
33225
33226	toJSON() {
33227
33228		const data = super.toJSON();
33229
33230		data.v0 = this.v0.toArray();
33231		data.v1 = this.v1.toArray();
33232		data.v2 = this.v2.toArray();
33233
33234		return data;
33235
33236	}
33237
33238	fromJSON( json ) {
33239
33240		super.fromJSON( json );
33241
33242		this.v0.fromArray( json.v0 );
33243		this.v1.fromArray( json.v1 );
33244		this.v2.fromArray( json.v2 );
33245
33246		return this;
33247
33248	}
33249
33250}
33251
33252/**
33253 * A curve representing a 3D Quadratic Bezier curve.
33254 *
33255 * @augments Curve
33256 */
33257class QuadraticBezierCurve3 extends Curve {
33258
33259	/**
33260	 * Constructs a new Quadratic Bezier curve.
33261	 *
33262	 * @param {Vector3} [v0] - The start point.
33263	 * @param {Vector3} [v1] - The control point.
33264	 * @param {Vector3} [v2] - The end point.
33265	 */
33266	constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) {
33267
33268		super();
33269
33270		/**
33271		 * This flag can be used for type testing.
33272		 *
33273		 * @type {boolean}
33274		 * @readonly
33275		 * @default true
33276		 */
33277		this.isQuadraticBezierCurve3 = true;
33278
33279		this.type = 'QuadraticBezierCurve3';
33280
33281		/**
33282		 * The start point.
33283		 *
33284		 * @type {Vector3}
33285		 */
33286		this.v0 = v0;
33287
33288		/**
33289		 * The control point.
33290		 *
33291		 * @type {Vector3}
33292		 */
33293		this.v1 = v1;
33294
33295		/**
33296		 * The end point.
33297		 *
33298		 * @type {Vector3}
33299		 */
33300		this.v2 = v2;
33301
33302	}
33303
33304	/**
33305	 * Returns a point on the curve.
33306	 *
33307	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
33308	 * @param {Vector3} [optionalTarget] - The optional target vector the result is written to.
33309	 * @return {Vector3} The position on the curve.
33310	 */
33311	getPoint( t, optionalTarget = new Vector3() ) {
33312
33313		const point = optionalTarget;
33314
33315		const v0 = this.v0, v1 = this.v1, v2 = this.v2;
33316
33317		point.set(
33318			QuadraticBezier( t, v0.x, v1.x, v2.x ),
33319			QuadraticBezier( t, v0.y, v1.y, v2.y ),
33320			QuadraticBezier( t, v0.z, v1.z, v2.z )
33321		);
33322
33323		return point;
33324
33325	}
33326
33327	copy( source ) {
33328
33329		super.copy( source );
33330
33331		this.v0.copy( source.v0 );
33332		this.v1.copy( source.v1 );
33333		this.v2.copy( source.v2 );
33334
33335		return this;
33336
33337	}
33338
33339	toJSON() {
33340
33341		const data = super.toJSON();
33342
33343		data.v0 = this.v0.toArray();
33344		data.v1 = this.v1.toArray();
33345		data.v2 = this.v2.toArray();
33346
33347		return data;
33348
33349	}
33350
33351	fromJSON( json ) {
33352
33353		super.fromJSON( json );
33354
33355		this.v0.fromArray( json.v0 );
33356		this.v1.fromArray( json.v1 );
33357		this.v2.fromArray( json.v2 );
33358
33359		return this;
33360
33361	}
33362
33363}
33364
33365/**
33366 * A curve representing a 2D spline curve.
33367 *
33368 * ```js
33369 * // Create a sine-like wave
33370 * const curve = new THREE.SplineCurve( [
33371 * 	new THREE.Vector2( -10, 0 ),
33372 * 	new THREE.Vector2( -5, 5 ),
33373 * 	new THREE.Vector2( 0, 0 ),
33374 * 	new THREE.Vector2( 5, -5 ),
33375 * 	new THREE.Vector2( 10, 0 )
33376 * ] );
33377 *
33378 * const points = curve.getPoints( 50 );
33379 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
33380 *
33381 * const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
33382 *
33383 * // Create the final object to add to the scene
33384 * const splineObject = new THREE.Line( geometry, material );
33385 * ```
33386 *
33387 * @augments Curve
33388 */
33389class SplineCurve extends Curve {
33390
33391	/**
33392	 * Constructs a new 2D spline curve.
33393	 *
33394	 * @param {Array<Vector2>} [points] -  An array of 2D points defining the curve.
33395	 */
33396	constructor( points = [] ) {
33397
33398		super();
33399
33400		/**
33401		 * This flag can be used for type testing.
33402		 *
33403		 * @type {boolean}
33404		 * @readonly
33405		 * @default true
33406		 */
33407		this.isSplineCurve = true;
33408
33409		this.type = 'SplineCurve';
33410
33411		/**
33412		 * An array of 2D points defining the curve.
33413		 *
33414		 * @type {Array<Vector2>}
33415		 */
33416		this.points = points;
33417
33418	}
33419
33420	/**
33421	 * Returns a point on the curve.
33422	 *
33423	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
33424	 * @param {Vector2} [optionalTarget] - The optional target vector the result is written to.
33425	 * @return {Vector2} The position on the curve.
33426	 */
33427	getPoint( t, optionalTarget = new Vector2() ) {
33428
33429		const point = optionalTarget;
33430
33431		const points = this.points;
33432		const p = ( points.length - 1 ) * t;
33433
33434		const intPoint = Math.floor( p );
33435		const weight = p - intPoint;
33436
33437		const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
33438		const p1 = points[ intPoint ];
33439		const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
33440		const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
33441
33442		point.set(
33443			CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
33444			CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
33445		);
33446
33447		return point;
33448
33449	}
33450
33451	copy( source ) {
33452
33453		super.copy( source );
33454
33455		this.points = [];
33456
33457		for ( let i = 0, l = source.points.length; i < l; i ++ ) {
33458
33459			const point = source.points[ i ];
33460
33461			this.points.push( point.clone() );
33462
33463		}
33464
33465		return this;
33466
33467	}
33468
33469	toJSON() {
33470
33471		const data = super.toJSON();
33472
33473		data.points = [];
33474
33475		for ( let i = 0, l = this.points.length; i < l; i ++ ) {
33476
33477			const point = this.points[ i ];
33478			data.points.push( point.toArray() );
33479
33480		}
33481
33482		return data;
33483
33484	}
33485
33486	fromJSON( json ) {
33487
33488		super.fromJSON( json );
33489
33490		this.points = [];
33491
33492		for ( let i = 0, l = json.points.length; i < l; i ++ ) {
33493
33494			const point = json.points[ i ];
33495			this.points.push( new Vector2().fromArray( point ) );
33496
33497		}
33498
33499		return this;
33500
33501	}
33502
33503}
33504
33505var Curves = /*#__PURE__*/Object.freeze({
33506	__proto__: null,
33507	ArcCurve: ArcCurve,
33508	CatmullRomCurve3: CatmullRomCurve3,
33509	CubicBezierCurve: CubicBezierCurve,
33510	CubicBezierCurve3: CubicBezierCurve3,
33511	EllipseCurve: EllipseCurve,
33512	LineCurve: LineCurve,
33513	LineCurve3: LineCurve3,
33514	QuadraticBezierCurve: QuadraticBezierCurve,
33515	QuadraticBezierCurve3: QuadraticBezierCurve3,
33516	SplineCurve: SplineCurve
33517});
33518
33519/**
33520 * A base class extending {@link Curve}. `CurvePath` is simply an
33521 * array of connected curves, but retains the API of a curve.
33522 *
33523 * @augments Curve
33524 */
33525class CurvePath extends Curve {
33526
33527	/**
33528	 * Constructs a new curve path.
33529	 */
33530	constructor() {
33531
33532		super();
33533
33534		this.type = 'CurvePath';
33535
33536		/**
33537		 * An array of curves defining the
33538		 * path.
33539		 *
33540		 * @type {Array<Curve>}
33541		 */
33542		this.curves = [];
33543
33544		/**
33545		 * Whether the path should automatically be closed
33546		 * by a line curve.
33547		 *
33548		 * @type {boolean}
33549		 * @default false
33550		 */
33551		this.autoClose = false;
33552
33553	}
33554
33555	/**
33556	 * Adds a curve to this curve path.
33557	 *
33558	 * @param {Curve} curve - The curve to add.
33559	 */
33560	add( curve ) {
33561
33562		this.curves.push( curve );
33563
33564	}
33565
33566	/**
33567	 * Adds a line curve to close the path.
33568	 *
33569	 * @return {CurvePath} A reference to this curve path.
33570	 */
33571	closePath() {
33572
33573		// Add a line curve if start and end of lines are not connected
33574		const startPoint = this.curves[ 0 ].getPoint( 0 );
33575		const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
33576
33577		if ( ! startPoint.equals( endPoint ) ) {
33578
33579			const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3';
33580			this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) );
33581
33582		}
33583
33584		return this;
33585
33586	}
33587
33588	/**
33589	 * This method returns a vector in 2D or 3D space (depending on the curve definitions)
33590	 * for the given interpolation factor.
33591	 *
33592	 * @param {number} t - A interpolation factor representing a position on the curve. Must be in the range `[0,1]`.
33593	 * @param {(Vector2|Vector3)} [optionalTarget] - The optional target vector the result is written to.
33594	 * @return {?(Vector2|Vector3)} The position on the curve. It can be a 2D or 3D vector depending on the curve definition.
33595	 */
33596	getPoint( t, optionalTarget ) {
33597
33598		// To get accurate point with reference to
33599		// entire path distance at time t,
33600		// following has to be done:
33601
33602		// 1. Length of each sub path have to be known
33603		// 2. Locate and identify type of curve
33604		// 3. Get t for the curve
33605		// 4. Return curve.getPointAt(t')
33606
33607		const d = t * this.getLength();
33608		const curveLengths = this.getCurveLengths();
33609		let i = 0;
33610
33611		// To think about boundaries points.
33612
33613		while ( i < curveLengths.length ) {
33614
33615			if ( curveLengths[ i ] >= d ) {
33616
33617				const diff = curveLengths[ i ] - d;
33618				const curve = this.curves[ i ];
33619
33620				const segmentLength = curve.getLength();
33621				const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
33622
33623				return curve.getPointAt( u, optionalTarget );
33624
33625			}
33626
33627			i ++;
33628
33629		}
33630
33631		return null;
33632
33633		// loop where sum != 0, sum > d , sum+1 <d
33634
33635	}
33636
33637	getLength() {
33638
33639		// We cannot use the default THREE.Curve getPoint() with getLength() because in
33640		// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
33641		// getPoint() depends on getLength
33642
33643		const lens = this.getCurveLengths();
33644		return lens[ lens.length - 1 ];
33645
33646	}
33647
33648	updateArcLengths() {
33649
33650		// cacheLengths must be recalculated.
33651
33652		this.needsUpdate = true;
33653		this.cacheLengths = null;
33654		this.getCurveLengths();
33655
33656	}
33657
33658	/**
33659	 * Returns list of cumulative curve lengths of the defined curves.
33660	 *
33661	 * @return {Array<number>} The curve lengths.
33662	 */
33663	getCurveLengths() {
33664
33665		// Compute lengths and cache them
33666		// We cannot overwrite getLengths() because UtoT mapping uses it.
33667		// We use cache values if curves and cache array are same length
33668
33669		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
33670
33671			return this.cacheLengths;
33672
33673		}
33674
33675		// Get length of sub-curve
33676		// Push sums into cached array
33677
33678		const lengths = [];
33679		let sums = 0;
33680
33681		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33682
33683			sums += this.curves[ i ].getLength();
33684			lengths.push( sums );
33685
33686		}
33687
33688		this.cacheLengths = lengths;
33689
33690		return lengths;
33691
33692	}
33693
33694	getSpacedPoints( divisions = 40 ) {
33695
33696		const points = [];
33697
33698		for ( let i = 0; i <= divisions; i ++ ) {
33699
33700			points.push( this.getPoint( i / divisions ) );
33701
33702		}
33703
33704		if ( this.autoClose ) {
33705
33706			points.push( points[ 0 ] );
33707
33708		}
33709
33710		return points;
33711
33712	}
33713
33714	getPoints( divisions = 12 ) {
33715
33716		const points = [];
33717		let last;
33718
33719		for ( let i = 0, curves = this.curves; i < curves.length; i ++ ) {
33720
33721			const curve = curves[ i ];
33722			const resolution = curve.isEllipseCurve ? divisions * 2
33723				: ( curve.isLineCurve || curve.isLineCurve3 ) ? 1
33724					: curve.isSplineCurve ? divisions * curve.points.length
33725						: divisions;
33726
33727			const pts = curve.getPoints( resolution );
33728
33729			for ( let j = 0; j < pts.length; j ++ ) {
33730
33731				const point = pts[ j ];
33732
33733				if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
33734
33735				points.push( point );
33736				last = point;
33737
33738			}
33739
33740		}
33741
33742		if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
33743
33744			points.push( points[ 0 ] );
33745
33746		}
33747
33748		return points;
33749
33750	}
33751
33752	copy( source ) {
33753
33754		super.copy( source );
33755
33756		this.curves = [];
33757
33758		for ( let i = 0, l = source.curves.length; i < l; i ++ ) {
33759
33760			const curve = source.curves[ i ];
33761
33762			this.curves.push( curve.clone() );
33763
33764		}
33765
33766		this.autoClose = source.autoClose;
33767
33768		return this;
33769
33770	}
33771
33772	toJSON() {
33773
33774		const data = super.toJSON();
33775
33776		data.autoClose = this.autoClose;
33777		data.curves = [];
33778
33779		for ( let i = 0, l = this.curves.length; i < l; i ++ ) {
33780
33781			const curve = this.curves[ i ];
33782			data.curves.push( curve.toJSON() );
33783
33784		}
33785
33786		return data;
33787
33788	}
33789
33790	fromJSON( json ) {
33791
33792		super.fromJSON( json );
33793
33794		this.autoClose = json.autoClose;
33795		this.curves = [];
33796
33797		for ( let i = 0, l = json.curves.length; i < l; i ++ ) {
33798
33799			const curve = json.curves[ i ];
33800			this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );
33801
33802		}
33803
33804		return this;
33805
33806	}
33807
33808}
33809
33810/**
33811 * A 2D path representation. The class provides methods for creating paths
33812 * and contours of 2D shapes similar to the 2D Canvas API.
33813 *
33814 * ```js
33815 * const path = new THREE.Path();
33816 *
33817 * path.lineTo( 0, 0.8 );
33818 * path.quadraticCurveTo( 0, 1, 0.2, 1 );
33819 * path.lineTo( 1, 1 );
33820 *
33821 * const points = path.getPoints();
33822 *
33823 * const geometry = new THREE.BufferGeometry().setFromPoints( points );
33824 * const material = new THREE.LineBasicMaterial( { color: 0xffffff } );
33825 *
33826 * const line = new THREE.Line( geometry, material );
33827 * scene.add( line );
33828 * ```
33829 *
33830 * @augments CurvePath
33831 */
33832class Path extends CurvePath {
33833
33834	/**
33835	 * Constructs a new path.
33836	 *
33837	 * @param {Array<Vector2>} [points] - An array of 2D points defining the path.
33838	 */
33839	constructor( points ) {
33840
33841		super();
33842
33843		this.type = 'Path';
33844
33845		/**
33846		 * The current offset of the path. Any new curve added will start here.
33847		 *
33848		 * @type {Vector2}
33849		 */
33850		this.currentPoint = new Vector2();
33851
33852		if ( points ) {
33853
33854			this.setFromPoints( points );
33855
33856		}
33857
33858	}
33859
33860	/**
33861	 * Creates a path from the given list of points. The points are added
33862	 * to the path as instances of {@link LineCurve}.
33863	 *
33864	 * @param {Array<Vector2>} points - An array of 2D points.
33865	 * @return {Path} A reference to this path.
33866	 */
33867	setFromPoints( points ) {
33868
33869		this.moveTo( points[ 0 ].x, points[ 0 ].y );
33870
33871		for ( let i = 1, l = points.length; i < l; i ++ ) {
33872
33873			this.lineTo( points[ i ].x, points[ i ].y );
33874
33875		}
33876
33877		return this;
33878
33879	}
33880
33881	/**
33882	 * Moves {@link Path#currentPoint} to the given point.
33883	 *
33884	 * @param {number} x - The x coordinate.
33885	 * @param {number} y - The y coordinate.
33886	 * @return {Path} A reference to this path.
33887	 */
33888	moveTo( x, y ) {
33889
33890		this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?
33891
33892		return this;
33893
33894	}
33895
33896	/**
33897	 * Adds an instance of {@link LineCurve} to the path by connecting
33898	 * the current point with the given one.
33899	 *
33900	 * @param {number} x - The x coordinate of the end point.
33901	 * @param {number} y - The y coordinate of the end point.
33902	 * @return {Path} A reference to this path.
33903	 */
33904	lineTo( x, y ) {
33905
33906		const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );
33907		this.curves.push( curve );
33908
33909		this.currentPoint.set( x, y );
33910
33911		return this;
33912
33913	}
33914
33915	/**
33916	 * Adds an instance of {@link QuadraticBezierCurve} to the path by connecting
33917	 * the current point with the given one.
33918	 *
33919	 * @param {number} aCPx - The x coordinate of the control point.
33920	 * @param {number} aCPy - The y coordinate of the control point.
33921	 * @param {number} aX - The x coordinate of the end point.
33922	 * @param {number} aY - The y coordinate of the end point.
33923	 * @return {Path} A reference to this path.
33924	 */
33925	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
33926
33927		const curve = new QuadraticBezierCurve(
33928			this.currentPoint.clone(),
33929			new Vector2( aCPx, aCPy ),
33930			new Vector2( aX, aY )
33931		);
33932
33933		this.curves.push( curve );
33934
33935		this.currentPoint.set( aX, aY );
33936
33937		return this;
33938
33939	}
33940
33941	/**
33942	 * Adds an instance of {@link CubicBezierCurve} to the path by connecting
33943	 * the current point with the given one.
33944	 *
33945	 * @param {number} aCP1x - The x coordinate of the first control point.
33946	 * @param {number} aCP1y - The y coordinate of the first control point.
33947	 * @param {number} aCP2x - The x coordinate of the second control point.
33948	 * @param {number} aCP2y - The y coordinate of the second control point.
33949	 * @param {number} aX - The x coordinate of the end point.
33950	 * @param {number} aY - The y coordinate of the end point.
33951	 * @return {Path} A reference to this path.
33952	 */
33953	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
33954
33955		const curve = new CubicBezierCurve(
33956			this.currentPoint.clone(),
33957			new Vector2( aCP1x, aCP1y ),
33958			new Vector2( aCP2x, aCP2y ),
33959			new Vector2( aX, aY )
33960		);
33961
33962		this.curves.push( curve );
33963
33964		this.currentPoint.set( aX, aY );
33965
33966		return this;
33967
33968	}
33969
33970	/**
33971	 * Adds an instance of {@link SplineCurve} to the path by connecting
33972	 * the current point with the given list of points.
33973	 *
33974	 * @param {Array<Vector2>} pts - An array of points in 2D space.
33975	 * @return {Path} A reference to this path.
33976	 */
33977	splineThru( pts ) {
33978
33979		const npts = [ this.currentPoint.clone() ].concat( pts );
33980
33981		const curve = new SplineCurve( npts );
33982		this.curves.push( curve );
33983
33984		this.currentPoint.copy( pts[ pts.length - 1 ] );
33985
33986		return this;
33987
33988	}
33989
33990	/**
33991	 * Adds an arc as an instance of {@link EllipseCurve} to the path, positioned relative
33992	 * to the current point.
33993	 *
33994	 * @param {number} [aX=0] - The x coordinate of the center of the arc offsetted from the previous curve.
33995	 * @param {number} [aY=0] - The y coordinate of the center of the arc offsetted from the previous curve.
33996	 * @param {number} [aRadius=1] - The radius of the arc.
33997	 * @param {number} [aStartAngle=0] - The start angle in radians.
33998	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
33999	 * @param {boolean} [aClockwise=false] - Whether to sweep the arc clockwise or not.
34000	 * @return {Path} A reference to this path.
34001	 */
34002	arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
34003
34004		const x0 = this.currentPoint.x;
34005		const y0 = this.currentPoint.y;
34006
34007		this.absarc( aX + x0, aY + y0, aRadius,
34008			aStartAngle, aEndAngle, aClockwise );
34009
34010		return this;
34011
34012	}
34013
34014	/**
34015	 * Adds an absolutely positioned arc as an instance of {@link EllipseCurve} to the path.
34016	 *
34017	 * @param {number} [aX=0] - The x coordinate of the center of the arc.
34018	 * @param {number} [aY=0] - The y coordinate of the center of the arc.
34019	 * @param {number} [aRadius=1] - The radius of the arc.
34020	 * @param {number} [aStartAngle=0] - The start angle in radians.
34021	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
34022	 * @param {boolean} [aClockwise=false] - Whether to sweep the arc clockwise or not.
34023	 * @return {Path} A reference to this path.
34024	 */
34025	absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
34026
34027		this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
34028
34029		return this;
34030
34031	}
34032
34033	/**
34034	 * Adds an ellipse as an instance of {@link EllipseCurve} to the path, positioned relative
34035	 * to the current point
34036	 *
34037	 * @param {number} [aX=0] - The x coordinate of the center of the ellipse offsetted from the previous curve.
34038	 * @param {number} [aY=0] - The y coordinate of the center of the ellipse offsetted from the previous curve.
34039	 * @param {number} [xRadius=1] - The radius of the ellipse in the x axis.
34040	 * @param {number} [yRadius=1] - The radius of the ellipse in the y axis.
34041	 * @param {number} [aStartAngle=0] - The start angle in radians.
34042	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
34043	 * @param {boolean} [aClockwise=false] - Whether to sweep the ellipse clockwise or not.
34044	 * @param {number} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
34045	 * @return {Path} A reference to this path.
34046	 */
34047	ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
34048
34049		const x0 = this.currentPoint.x;
34050		const y0 = this.currentPoint.y;
34051
34052		this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
34053
34054		return this;
34055
34056	}
34057
34058	/**
34059	 * Adds an absolutely positioned ellipse as an instance of {@link EllipseCurve} to the path.
34060	 *
34061	 * @param {number} [aX=0] - The x coordinate of the absolute center of the ellipse.
34062	 * @param {number} [aY=0] - The y coordinate of the absolute center of the ellipse.
34063	 * @param {number} [xRadius=1] - The radius of the ellipse in the x axis.
34064	 * @param {number} [yRadius=1] - The radius of the ellipse in the y axis.
34065	 * @param {number} [aStartAngle=0] - The start angle in radians.
34066	 * @param {number} [aEndAngle=Math.PI*2] - The end angle in radians.
34067	 * @param {boolean} [aClockwise=false] - Whether to sweep the ellipse clockwise or not.
34068	 * @param {number} [aRotation=0] - The rotation angle of the ellipse in radians, counterclockwise from the positive X axis.
34069	 * @return {Path} A reference to this path.
34070	 */
34071	absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
34072
34073		const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
34074
34075		if ( this.curves.length > 0 ) {
34076
34077			// if a previous curve is present, attempt to join
34078			const firstPoint = curve.getPoint( 0 );
34079
34080			if ( ! firstPoint.equals( this.currentPoint ) ) {
34081
34082				this.lineTo( firstPoint.x, firstPoint.y );
34083
34084			}
34085
34086		}
34087
34088		this.curves.push( curve );
34089
34090		const lastPoint = curve.getPoint( 1 );
34091		this.currentPoint.copy( lastPoint );
34092
34093		return this;
34094
34095	}
34096
34097	copy( source ) {
34098
34099		super.copy( source );
34100
34101		this.currentPoint.copy( source.currentPoint );
34102
34103		return this;
34104
34105	}
34106
34107	toJSON() {
34108
34109		const data = super.toJSON();
34110
34111		data.currentPoint = this.currentPoint.toArray();
34112
34113		return data;
34114
34115	}
34116
34117	fromJSON( json ) {
34118
34119		super.fromJSON( json );
34120
34121		this.currentPoint.fromArray( json.currentPoint );
34122
34123		return this;
34124
34125	}
34126
34127}
34128
34129/**
34130 * Defines an arbitrary 2d shape plane using paths with optional holes. It
34131 * can be used with {@link ExtrudeGeometry}, {@link ShapeGeometry}, to get
34132 * points, or to get triangulated faces.
34133 *
34134 * ```js
34135 * const heartShape = new THREE.Shape();
34136 *
34137 * heartShape.moveTo( 25, 25 );
34138 * heartShape.bezierCurveTo( 25, 25, 20, 0, 0, 0 );
34139 * heartShape.bezierCurveTo( - 30, 0, - 30, 35, - 30, 35 );
34140 * heartShape.bezierCurveTo( - 30, 55, - 10, 77, 25, 95 );
34141 * heartShape.bezierCurveTo( 60, 77, 80, 55, 80, 35 );
34142 * heartShape.bezierCurveTo( 80, 35, 80, 0, 50, 0 );
34143 * heartShape.bezierCurveTo( 35, 0, 25, 25, 25, 25 );
34144 *
34145 * const extrudeSettings = {
34146 * 	depth: 8,
34147 * 	bevelEnabled: true,
34148 * 	bevelSegments: 2,
34149 * 	steps: 2,
34150 * 	bevelSize: 1,
34151 * 	bevelThickness: 1
34152 * };
34153 *
34154 * const geometry = new THREE.ExtrudeGeometry( heartShape, extrudeSettings );
34155 * const mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial() );
34156 * ```
34157 *
34158 * @augments Path
34159 */
34160class Shape extends Path {
34161
34162	/**
34163	 * Constructs a new shape.
34164	 *
34165	 * @param {Array<Vector2>} [points] - An array of 2D points defining the shape.
34166	 */
34167	constructor( points ) {
34168
34169		super( points );
34170
34171		/**
34172		 * The UUID of the shape.
34173		 *
34174		 * @type {string}
34175		 * @readonly
34176		 */
34177		this.uuid = generateUUID();
34178
34179		this.type = 'Shape';
34180
34181		/**
34182		 * Defines the holes in the shape. Hole definitions must use the
34183		 * opposite winding order (CW/CCW) than the outer shape.
34184		 *
34185		 * @type {Array<Path>}
34186		 * @readonly
34187		 */
34188		this.holes = [];
34189
34190	}
34191
34192	/**
34193	 * Returns an array representing each contour of the holes
34194	 * as a list of 2D points.
34195	 *
34196	 * @param {number} divisions - The fineness of the result.
34197	 * @return {Array<Array<Vector2>>} The holes as a series of 2D points.
34198	 */
34199	getPointsHoles( divisions ) {
34200
34201		const holesPts = [];
34202
34203		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
34204
34205			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
34206
34207		}
34208
34209		return holesPts;
34210
34211	}
34212
34213	// get points of shape and holes (keypoints based on segments parameter)
34214
34215	/**
34216	 * Returns an object that holds contour data for the shape and its holes as
34217	 * arrays of 2D points.
34218	 *
34219	 * @param {number} divisions - The fineness of the result.
34220	 * @return {{shape:Array<Vector2>,holes:Array<Array<Vector2>>}} An object with contour data.
34221	 */
34222	extractPoints( divisions ) {
34223
34224		return {
34225
34226			shape: this.getPoints( divisions ),
34227			holes: this.getPointsHoles( divisions )
34228
34229		};
34230
34231	}
34232
34233	copy( source ) {
34234
34235		super.copy( source );
34236
34237		this.holes = [];
34238
34239		for ( let i = 0, l = source.holes.length; i < l; i ++ ) {
34240
34241			const hole = source.holes[ i ];
34242
34243			this.holes.push( hole.clone() );
34244
34245		}
34246
34247		return this;
34248
34249	}
34250
34251	toJSON() {
34252
34253		const data = super.toJSON();
34254
34255		data.uuid = this.uuid;
34256		data.holes = [];
34257
34258		for ( let i = 0, l = this.holes.length; i < l; i ++ ) {
34259
34260			const hole = this.holes[ i ];
34261			data.holes.push( hole.toJSON() );
34262
34263		}
34264
34265		return data;
34266
34267	}
34268
34269	fromJSON( json ) {
34270
34271		super.fromJSON( json );
34272
34273		this.uuid = json.uuid;
34274		this.holes = [];
34275
34276		for ( let i = 0, l = json.holes.length; i < l; i ++ ) {
34277
34278			const hole = json.holes[ i ];
34279			this.holes.push( new Path().fromJSON( hole ) );
34280
34281		}
34282
34283		return this;
34284
34285	}
34286
34287}
34288
34289/* eslint-disable */
34290// copy of mapbox/earcut version 3.0.2
34291// https://github.com/mapbox/earcut/tree/v3.0.2
34292
34293function earcut(data, holeIndices, dim = 2) {
34294
34295    const hasHoles = holeIndices && holeIndices.length;
34296    const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
34297    let outerNode = linkedList(data, 0, outerLen, dim, true);
34298    const triangles = [];
34299
34300    if (!outerNode || outerNode.next === outerNode.prev) return triangles;
34301
34302    let minX, minY, invSize;
34303
34304    if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
34305
34306    // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
34307    if (data.length > 80 * dim) {
34308        minX = data[0];
34309        minY = data[1];
34310        let maxX = minX;
34311        let maxY = minY;
34312
34313        for (let i = dim; i < outerLen; i += dim) {
34314            const x = data[i];
34315            const y = data[i + 1];
34316            if (x < minX) minX = x;
34317            if (y < minY) minY = y;
34318            if (x > maxX) maxX = x;
34319            if (y > maxY) maxY = y;
34320        }
34321
34322        // minX, minY and invSize are later used to transform coords into integers for z-order calculation
34323        invSize = Math.max(maxX - minX, maxY - minY);
34324        invSize = invSize !== 0 ? 32767 / invSize : 0;
34325    }
34326
34327    earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
34328
34329    return triangles;
34330}
34331
34332// create a circular doubly linked list from polygon points in the specified winding order
34333function linkedList(data, start, end, dim, clockwise) {
34334    let last;
34335
34336    if (clockwise === (signedArea(data, start, end, dim) > 0)) {
34337        for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
34338    } else {
34339        for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);
34340    }
34341
34342    if (last && equals(last, last.next)) {
34343        removeNode(last);
34344        last = last.next;
34345    }
34346
34347    return last;
34348}
34349
34350// eliminate colinear or duplicate points
34351function filterPoints(start, end) {
34352    if (!start) return start;
34353    if (!end) end = start;
34354
34355    let p = start,
34356        again;
34357    do {
34358        again = false;
34359
34360        if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
34361            removeNode(p);
34362            p = end = p.prev;
34363            if (p === p.next) break;
34364            again = true;
34365
34366        } else {
34367            p = p.next;
34368        }
34369    } while (again || p !== end);
34370
34371    return end;
34372}
34373
34374// main ear slicing loop which triangulates a polygon (given as a linked list)
34375function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
34376    if (!ear) return;
34377
34378    // interlink polygon nodes in z-order
34379    if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
34380
34381    let stop = ear;
34382
34383    // iterate through ears, slicing them one by one
34384    while (ear.prev !== ear.next) {
34385        const prev = ear.prev;
34386        const next = ear.next;
34387
34388        if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
34389            triangles.push(prev.i, ear.i, next.i); // cut off the triangle
34390
34391            removeNode(ear);
34392
34393            // skipping the next vertex leads to less sliver triangles
34394            ear = next.next;
34395            stop = next.next;
34396
34397            continue;
34398        }
34399
34400        ear = next;
34401
34402        // if we looped through the whole remaining polygon and can't find any more ears
34403        if (ear === stop) {
34404            // try filtering points and slicing again
34405            if (!pass) {
34406                earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
34407
34408            // if this didn't work, try curing all small self-intersections locally
34409            } else if (pass === 1) {
34410                ear = cureLocalIntersections(filterPoints(ear), triangles);
34411                earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
34412
34413            // as a last resort, try splitting the remaining polygon into two
34414            } else if (pass === 2) {
34415                splitEarcut(ear, triangles, dim, minX, minY, invSize);
34416            }
34417
34418            break;
34419        }
34420    }
34421}
34422
34423// check whether a polygon node forms a valid ear with adjacent nodes
34424function isEar(ear) {
34425    const a = ear.prev,
34426        b = ear,
34427        c = ear.next;
34428
34429    if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
34430
34431    // now make sure we don't have other points inside the potential ear
34432    const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
34433
34434    // triangle bbox
34435    const x0 = Math.min(ax, bx, cx),
34436        y0 = Math.min(ay, by, cy),
34437        x1 = Math.max(ax, bx, cx),
34438        y1 = Math.max(ay, by, cy);
34439
34440    let p = c.next;
34441    while (p !== a) {
34442        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&
34443            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) &&
34444            area(p.prev, p, p.next) >= 0) return false;
34445        p = p.next;
34446    }
34447
34448    return true;
34449}
34450
34451function isEarHashed(ear, minX, minY, invSize) {
34452    const a = ear.prev,
34453        b = ear,
34454        c = ear.next;
34455
34456    if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
34457
34458    const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
34459
34460    // triangle bbox
34461    const x0 = Math.min(ax, bx, cx),
34462        y0 = Math.min(ay, by, cy),
34463        x1 = Math.max(ax, bx, cx),
34464        y1 = Math.max(ay, by, cy);
34465
34466    // z-order range for the current triangle bbox;
34467    const minZ = zOrder(x0, y0, minX, minY, invSize),
34468        maxZ = zOrder(x1, y1, minX, minY, invSize);
34469
34470    let p = ear.prevZ,
34471        n = ear.nextZ;
34472
34473    // look for points inside the triangle in both directions
34474    while (p && p.z >= minZ && n && n.z <= maxZ) {
34475        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
34476            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
34477        p = p.prevZ;
34478
34479        if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
34480            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
34481        n = n.nextZ;
34482    }
34483
34484    // look for remaining points in decreasing z-order
34485    while (p && p.z >= minZ) {
34486        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&
34487            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;
34488        p = p.prevZ;
34489    }
34490
34491    // look for remaining points in increasing z-order
34492    while (n && n.z <= maxZ) {
34493        if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&
34494            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
34495        n = n.nextZ;
34496    }
34497
34498    return true;
34499}
34500
34501// go through all polygon nodes and cure small local self-intersections
34502function cureLocalIntersections(start, triangles) {
34503    let p = start;
34504    do {
34505        const a = p.prev,
34506            b = p.next.next;
34507
34508        if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
34509
34510            triangles.push(a.i, p.i, b.i);
34511
34512            // remove two nodes involved
34513            removeNode(p);
34514            removeNode(p.next);
34515
34516            p = start = b;
34517        }
34518        p = p.next;
34519    } while (p !== start);
34520
34521    return filterPoints(p);
34522}
34523
34524// try splitting polygon into two and triangulate them independently
34525function splitEarcut(start, triangles, dim, minX, minY, invSize) {
34526    // look for a valid diagonal that divides the polygon into two
34527    let a = start;
34528    do {
34529        let b = a.next.next;
34530        while (b !== a.prev) {
34531            if (a.i !== b.i && isValidDiagonal(a, b)) {
34532                // split the polygon in two by the diagonal
34533                let c = splitPolygon(a, b);
34534
34535                // filter colinear points around the cuts
34536                a = filterPoints(a, a.next);
34537                c = filterPoints(c, c.next);
34538
34539                // run earcut on each half
34540                earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
34541                earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
34542                return;
34543            }
34544            b = b.next;
34545        }
34546        a = a.next;
34547    } while (a !== start);
34548}
34549
34550// link every hole into the outer loop, producing a single-ring polygon without holes
34551function eliminateHoles(data, holeIndices, outerNode, dim) {
34552    const queue = [];
34553
34554    for (let i = 0, len = holeIndices.length; i < len; i++) {
34555        const start = holeIndices[i] * dim;
34556        const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
34557        const list = linkedList(data, start, end, dim, false);
34558        if (list === list.next) list.steiner = true;
34559        queue.push(getLeftmost(list));
34560    }
34561
34562    queue.sort(compareXYSlope);
34563
34564    // process holes from left to right
34565    for (let i = 0; i < queue.length; i++) {
34566        outerNode = eliminateHole(queue[i], outerNode);
34567    }
34568
34569    return outerNode;
34570}
34571
34572function compareXYSlope(a, b) {
34573    let result = a.x - b.x;
34574    // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find
34575    // the bridge to the outer shell is always the point that they meet at.
34576    if (result === 0) {
34577        result = a.y - b.y;
34578        if (result === 0) {
34579            const aSlope = (a.next.y - a.y) / (a.next.x - a.x);
34580            const bSlope = (b.next.y - b.y) / (b.next.x - b.x);
34581            result = aSlope - bSlope;
34582        }
34583    }
34584    return result;
34585}
34586
34587// find a bridge between vertices that connects hole with an outer ring and link it
34588function eliminateHole(hole, outerNode) {
34589    const bridge = findHoleBridge(hole, outerNode);
34590    if (!bridge) {
34591        return outerNode;
34592    }
34593
34594    const bridgeReverse = splitPolygon(bridge, hole);
34595
34596    // filter collinear points around the cuts
34597    filterPoints(bridgeReverse, bridgeReverse.next);
34598    return filterPoints(bridge, bridge.next);
34599}
34600
34601// David Eberly's algorithm for finding a bridge between hole and outer polygon
34602function findHoleBridge(hole, outerNode) {
34603    let p = outerNode;
34604    const hx = hole.x;
34605    const hy = hole.y;
34606    let qx = -Infinity;
34607    let m;
34608
34609    // find a segment intersected by a ray from the hole's leftmost point to the left;
34610    // segment's endpoint with lesser x will be potential connection point
34611    // unless they intersect at a vertex, then choose the vertex
34612    if (equals(hole, p)) return p;
34613    do {
34614        if (equals(hole, p.next)) return p.next;
34615        else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {
34616            const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);
34617            if (x <= hx && x > qx) {
34618                qx = x;
34619                m = p.x < p.next.x ? p : p.next;
34620                if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint
34621            }
34622        }
34623        p = p.next;
34624    } while (p !== outerNode);
34625
34626    if (!m) return null;
34627
34628    // look for points inside the triangle of hole point, segment intersection and endpoint;
34629    // if there are no points found, we have a valid connection;
34630    // otherwise choose the point of the minimum angle with the ray as connection point
34631
34632    const stop = m;
34633    const mx = m.x;
34634    const my = m.y;
34635    let tanMin = Infinity;
34636
34637    p = m;
34638
34639    do {
34640        if (hx >= p.x && p.x >= mx && hx !== p.x &&
34641                pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {
34642
34643            const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential
34644
34645            if (locallyInside(p, hole) &&
34646                (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {
34647                m = p;
34648                tanMin = tan;
34649            }
34650        }
34651
34652        p = p.next;
34653    } while (p !== stop);
34654
34655    return m;
34656}
34657
34658// whether sector in vertex m contains sector in vertex p in the same coordinates
34659function sectorContainsSector(m, p) {
34660    return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;
34661}
34662
34663// interlink polygon nodes in z-order
34664function indexCurve(start, minX, minY, invSize) {
34665    let p = start;
34666    do {
34667        if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);
34668        p.prevZ = p.prev;
34669        p.nextZ = p.next;
34670        p = p.next;
34671    } while (p !== start);
34672
34673    p.prevZ.nextZ = null;
34674    p.prevZ = null;
34675
34676    sortLinked(p);
34677}
34678
34679// Simon Tatham's linked list merge sort algorithm
34680// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
34681function sortLinked(list) {
34682    let numMerges;
34683    let inSize = 1;
34684
34685    do {
34686        let p = list;
34687        let e;
34688        list = null;
34689        let tail = null;
34690        numMerges = 0;
34691
34692        while (p) {
34693            numMerges++;
34694            let q = p;
34695            let pSize = 0;
34696            for (let i = 0; i < inSize; i++) {
34697                pSize++;
34698                q = q.nextZ;
34699                if (!q) break;
34700            }
34701            let qSize = inSize;
34702
34703            while (pSize > 0 || (qSize > 0 && q)) {
34704
34705                if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {
34706                    e = p;
34707                    p = p.nextZ;
34708                    pSize--;
34709                } else {
34710                    e = q;
34711                    q = q.nextZ;
34712                    qSize--;
34713                }
34714
34715                if (tail) tail.nextZ = e;
34716                else list = e;
34717
34718                e.prevZ = tail;
34719                tail = e;
34720            }
34721
34722            p = q;
34723        }
34724
34725        tail.nextZ = null;
34726        inSize *= 2;
34727
34728    } while (numMerges > 1);
34729
34730    return list;
34731}
34732
34733// z-order of a point given coords and inverse of the longer side of data bbox
34734function zOrder(x, y, minX, minY, invSize) {
34735    // coords are transformed into non-negative 15-bit integer range
34736    x = (x - minX) * invSize | 0;
34737    y = (y - minY) * invSize | 0;
34738
34739    x = (x | (x << 8)) & 0x00FF00FF;
34740    x = (x | (x << 4)) & 0x0F0F0F0F;
34741    x = (x | (x << 2)) & 0x33333333;
34742    x = (x | (x << 1)) & 0x55555555;
34743
34744    y = (y | (y << 8)) & 0x00FF00FF;
34745    y = (y | (y << 4)) & 0x0F0F0F0F;
34746    y = (y | (y << 2)) & 0x33333333;
34747    y = (y | (y << 1)) & 0x55555555;
34748
34749    return x | (y << 1);
34750}
34751
34752// find the leftmost node of a polygon ring
34753function getLeftmost(start) {
34754    let p = start,
34755        leftmost = start;
34756    do {
34757        if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;
34758        p = p.next;
34759    } while (p !== start);
34760
34761    return leftmost;
34762}
34763
34764// check if a point lies within a convex triangle
34765function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
34766    return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
34767           (ax - px) * (by - py) >= (bx - px) * (ay - py) &&
34768           (bx - px) * (cy - py) >= (cx - px) * (by - py);
34769}
34770
34771// check if a point lies within a convex triangle but false if its equal to the first point of the triangle
34772function pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {
34773    return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);
34774}
34775
34776// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
34777function isValidDiagonal(a, b) {
34778    return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // doesn't intersect other edges
34779           (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
34780            (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
34781            equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case
34782}
34783
34784// signed area of a triangle
34785function area(p, q, r) {
34786    return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
34787}
34788
34789// check if two points are equal
34790function equals(p1, p2) {
34791    return p1.x === p2.x && p1.y === p2.y;
34792}
34793
34794// check if two segments intersect
34795function intersects(p1, q1, p2, q2) {
34796    const o1 = sign(area(p1, q1, p2));
34797    const o2 = sign(area(p1, q1, q2));
34798    const o3 = sign(area(p2, q2, p1));
34799    const o4 = sign(area(p2, q2, q1));
34800
34801    if (o1 !== o2 && o3 !== o4) return true; // general case
34802
34803    if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
34804    if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
34805    if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
34806    if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
34807
34808    return false;
34809}
34810
34811// for collinear points p, q, r, check if point q lies on segment pr
34812function onSegment(p, q, r) {
34813    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);
34814}
34815
34816function sign(num) {
34817    return num > 0 ? 1 : num < 0 ? -1 : 0;
34818}
34819
34820// check if a polygon diagonal intersects any polygon segments
34821function intersectsPolygon(a, b) {
34822    let p = a;
34823    do {
34824        if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&
34825                intersects(p, p.next, a, b)) return true;
34826        p = p.next;
34827    } while (p !== a);
34828
34829    return false;
34830}
34831
34832// check if a polygon diagonal is locally inside the polygon
34833function locallyInside(a, b) {
34834    return area(a.prev, a, a.next) < 0 ?
34835        area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :
34836        area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
34837}
34838
34839// check if the middle point of a polygon diagonal is inside the polygon
34840function middleInside(a, b) {
34841    let p = a;
34842    let inside = false;
34843    const px = (a.x + b.x) / 2;
34844    const py = (a.y + b.y) / 2;
34845    do {
34846        if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&
34847                (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))
34848            inside = !inside;
34849        p = p.next;
34850    } while (p !== a);
34851
34852    return inside;
34853}
34854
34855// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;
34856// if one belongs to the outer ring and another to a hole, it merges it into a single ring
34857function splitPolygon(a, b) {
34858    const a2 = createNode(a.i, a.x, a.y),
34859        b2 = createNode(b.i, b.x, b.y),
34860        an = a.next,
34861        bp = b.prev;
34862
34863    a.next = b;
34864    b.prev = a;
34865
34866    a2.next = an;
34867    an.prev = a2;
34868
34869    b2.next = a2;
34870    a2.prev = b2;
34871
34872    bp.next = b2;
34873    b2.prev = bp;
34874
34875    return b2;
34876}
34877
34878// create a node and optionally link it with previous one (in a circular doubly linked list)
34879function insertNode(i, x, y, last) {
34880    const p = createNode(i, x, y);
34881
34882    if (!last) {
34883        p.prev = p;
34884        p.next = p;
34885
34886    } else {
34887        p.next = last.next;
34888        p.prev = last;
34889        last.next.prev = p;
34890        last.next = p;
34891    }
34892    return p;
34893}
34894
34895function removeNode(p) {
34896    p.next.prev = p.prev;
34897    p.prev.next = p.next;
34898
34899    if (p.prevZ) p.prevZ.nextZ = p.nextZ;
34900    if (p.nextZ) p.nextZ.prevZ = p.prevZ;
34901}
34902
34903function createNode(i, x, y) {
34904    return {
34905        i, // vertex index in coordinates array
34906        x, y, // vertex coordinates
34907        prev: null, // previous and next vertex nodes in a polygon ring
34908        next: null,
34909        z: 0, // z-order curve value
34910        prevZ: null, // previous and next nodes in z-order
34911        nextZ: null,
34912        steiner: false // indicates whether this is a steiner point
34913    };
34914}
34915
34916function signedArea(data, start, end, dim) {
34917    let sum = 0;
34918    for (let i = start, j = end - dim; i < end; i += dim) {
34919        sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
34920        j = i;
34921    }
34922    return sum;
34923}
34924
34925/**
34926 * An implementation of the earcut polygon triangulation algorithm.
34927 * The code is a port of [mapbox/earcut](https://github.com/mapbox/earcut).
34928 *
34929 * @see https://github.com/mapbox/earcut
34930 */
34931class Earcut {
34932
34933	/**
34934	 * Triangulates the given shape definition by returning an array of triangles.
34935	 *
34936	 * @param {Array<number>} data - An array with 2D points.
34937	 * @param {Array<number>} holeIndices - An array with indices defining holes.
34938	 * @param {number} [dim=2] - The number of coordinates per vertex in the input array.
34939	 * @return {Array<number>} An array representing the triangulated faces. Each face is defined by three consecutive numbers
34940	 * representing vertex indices.
34941	 */
34942	static triangulate( data, holeIndices, dim = 2 ) {
34943
34944		return earcut( data, holeIndices, dim );
34945
34946	}
34947
34948}
34949
34950/**
34951 * A class containing utility functions for shapes.
34952 *
34953 * @hideconstructor
34954 */
34955class ShapeUtils {
34956
34957	/**
34958	 * Calculate area of a ( 2D ) contour polygon.
34959	 *
34960	 * @param {Array<Vector2>} contour - An array of 2D points.
34961	 * @return {number} The area.
34962	 */
34963	static area( contour ) {
34964
34965		const n = contour.length;
34966		let a = 0.0;
34967
34968		for ( let p = n - 1, q = 0; q < n; p = q ++ ) {
34969
34970			a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
34971
34972		}
34973
34974		return a * 0.5;
34975
34976	}
34977
34978	/**
34979	 * Returns `true` if the given contour uses a clockwise winding order.
34980	 *
34981	 * @param {Array<Vector2>} pts - An array of 2D points defining a polygon.
34982	 * @return {boolean} Whether the given contour uses a clockwise winding order or not.
34983	 */
34984	static isClockWise( pts ) {
34985
34986		return ShapeUtils.area( pts ) < 0;
34987
34988	}
34989
34990	/**
34991	 * Triangulates the given shape definition.
34992	 *
34993	 * @param {Array<Vector2>} contour - An array of 2D points defining the contour.
34994	 * @param {Array<Array<Vector2>>} holes - An array that holds arrays of 2D points defining the holes.
34995	 * @return {Array<Array<number>>} An array that holds for each face definition an array with three indices.
34996	 */
34997	static triangulateShape( contour, holes ) {
34998
34999		const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]
35000		const holeIndices = []; // array of hole indices
35001		const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]
35002
35003		removeDupEndPts( contour );
35004		addContour( vertices, contour );
35005
35006		//
35007
35008		let holeIndex = contour.length;
35009
35010		holes.forEach( removeDupEndPts );
35011
35012		for ( let i = 0; i < holes.length; i ++ ) {
35013
35014			holeIndices.push( holeIndex );
35015			holeIndex += holes[ i ].length;
35016			addContour( vertices, holes[ i ] );
35017
35018		}
35019
35020		//
35021
35022		const triangles = Earcut.triangulate( vertices, holeIndices );
35023
35024		//
35025
35026		for ( let i = 0; i < triangles.length; i += 3 ) {
35027
35028			faces.push( triangles.slice( i, i + 3 ) );
35029
35030		}
35031
35032		return faces;
35033
35034	}
35035
35036}
35037
35038function removeDupEndPts( points ) {
35039
35040	const l = points.length;
35041
35042	if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {
35043
35044		points.pop();
35045
35046	}
35047
35048}
35049
35050function addContour( vertices, contour ) {
35051
35052	for ( let i = 0; i < contour.length; i ++ ) {
35053
35054		vertices.push( contour[ i ].x );
35055		vertices.push( contour[ i ].y );
35056
35057	}
35058
35059}
35060
35061/**
35062 * Creates extruded geometry from a path shape.
35063 *
35064 * ```js
35065 * const length = 12, width = 8;
35066 *
35067 * const shape = new THREE.Shape();
35068 * shape.moveTo( 0,0 );
35069 * shape.lineTo( 0, width );
35070 * shape.lineTo( length, width );
35071 * shape.lineTo( length, 0 );
35072 * shape.lineTo( 0, 0 );
35073 *
35074 * const geometry = new THREE.ExtrudeGeometry( shape );
35075 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
35076 * const mesh = new THREE.Mesh( geometry, material ) ;
35077 * scene.add( mesh );
35078 * ```
35079 *
35080 * @augments BufferGeometry
35081 * @demo scenes/geometry-browser.html#ExtrudeGeometry
35082 */
35083class ExtrudeGeometry extends BufferGeometry {
35084
35085	/**
35086	 * Constructs a new extrude geometry.
35087	 *
35088	 * @param {Shape|Array<Shape>} [shapes] - A shape or an array of shapes.
35089	 * @param {ExtrudeGeometry~Options} [options] - The extrude settings.
35090	 */
35091	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 = {} ) {
35092
35093		super();
35094
35095		this.type = 'ExtrudeGeometry';
35096
35097		/**
35098		 * Holds the constructor parameters that have been
35099		 * used to generate the geometry. Any modification
35100		 * after instantiation does not change the geometry.
35101		 *
35102		 * @type {Object}
35103		 */
35104		this.parameters = {
35105			shapes: shapes,
35106			options: options
35107		};
35108
35109		shapes = Array.isArray( shapes ) ? shapes : [ shapes ];
35110
35111		const scope = this;
35112
35113		const verticesArray = [];
35114		const uvArray = [];
35115
35116		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
35117
35118			const shape = shapes[ i ];
35119			addShape( shape );
35120
35121		}
35122
35123		// build geometry
35124
35125		this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );
35126		this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );
35127
35128		this.computeVertexNormals();
35129
35130		// functions
35131
35132		function addShape( shape ) {
35133
35134			const placeholder = [];
35135
35136			// options
35137
35138			const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
35139			const steps = options.steps !== undefined ? options.steps : 1;
35140			const depth = options.depth !== undefined ? options.depth : 1;
35141
35142			let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
35143			let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2;
35144			let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1;
35145			let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;
35146			let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
35147
35148			const extrudePath = options.extrudePath;
35149
35150			const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;
35151
35152			//
35153
35154			let extrudePts, extrudeByPath = false;
35155			let splineTube, binormal, normal, position2;
35156
35157			if ( extrudePath ) {
35158
35159				extrudePts = extrudePath.getSpacedPoints( steps );
35160
35161				extrudeByPath = true;
35162				bevelEnabled = false; // bevels not supported for path extrusion
35163
35164				// SETUP TNB variables
35165
35166				const isClosed = extrudePath.isCatmullRomCurve3 ? extrudePath.closed : false;
35167
35168				splineTube = extrudePath.computeFrenetFrames( steps, isClosed );
35169
35170				// log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
35171
35172				binormal = new Vector3();
35173				normal = new Vector3();
35174				position2 = new Vector3();
35175
35176			}
35177
35178			// Safeguards if bevels are not enabled
35179
35180			if ( ! bevelEnabled ) {
35181
35182				bevelSegments = 0;
35183				bevelThickness = 0;
35184				bevelSize = 0;
35185				bevelOffset = 0;
35186
35187			}
35188
35189			// Variables initialization
35190
35191			const shapePoints = shape.extractPoints( curveSegments );
35192
35193			let vertices = shapePoints.shape;
35194			const holes = shapePoints.holes;
35195
35196			const reverse = ! ShapeUtils.isClockWise( vertices );
35197
35198			if ( reverse ) {
35199
35200				vertices = vertices.reverse();
35201
35202				// Maybe we should also check if holes are in the opposite direction, just to be safe ...
35203
35204				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35205
35206					const ahole = holes[ h ];
35207
35208					if ( ShapeUtils.isClockWise( ahole ) ) {
35209
35210						holes[ h ] = ahole.reverse();
35211
35212					}
35213
35214				}
35215
35216			}
35217
35218			/**Merges index-adjacent points that are within a threshold distance of each other. Array is modified in-place. Threshold distance is empirical, and scaled based on the magnitude of point coordinates.
35219			 * @param {Array<Vector2>} points
35220			*/
35221			function mergeOverlappingPoints( points ) {
35222
35223				const THRESHOLD = 1e-10;
35224				const THRESHOLD_SQ = THRESHOLD * THRESHOLD;
35225				let prevPos = points[ 0 ];
35226				for ( let i = 1; i <= points.length; i ++ ) {
35227
35228					const currentIndex = i % points.length;
35229					const currentPos = points[ currentIndex ];
35230					const dx = currentPos.x - prevPos.x;
35231					const dy = currentPos.y - prevPos.y;
35232					const distSq = dx * dx + dy * dy;
35233
35234					const scalingFactorSqrt = Math.max(
35235						Math.abs( currentPos.x ),
35236						Math.abs( currentPos.y ),
35237						Math.abs( prevPos.x ),
35238						Math.abs( prevPos.y )
35239					);
35240					const thresholdSqScaled = THRESHOLD_SQ * scalingFactorSqrt * scalingFactorSqrt;
35241					if ( distSq <= thresholdSqScaled ) {
35242
35243						points.splice( currentIndex, 1 );
35244						i --;
35245						continue;
35246
35247					}
35248
35249					prevPos = currentPos;
35250
35251				}
35252
35253			}
35254
35255			mergeOverlappingPoints( vertices );
35256			holes.forEach( mergeOverlappingPoints );
35257
35258			const numHoles = holes.length;
35259
35260			/* Vertices */
35261
35262			const contour = vertices; // vertices has all points but contour has only points of circumference
35263
35264			for ( let h = 0; h < numHoles; h ++ ) {
35265
35266				const ahole = holes[ h ];
35267
35268				vertices = vertices.concat( ahole );
35269
35270			}
35271
35272
35273			function scalePt2( pt, vec, size ) {
35274
35275				if ( ! vec ) error( 'ExtrudeGeometry: vec does not exist' );
35276
35277				return pt.clone().addScaledVector( vec, size );
35278
35279			}
35280
35281			const vlen = vertices.length;
35282
35283
35284			// Find directions for point movement
35285
35286
35287			function getBevelVec( inPt, inPrev, inNext ) {
35288
35289				// computes for inPt the corresponding point inPt' on a new contour
35290				//   shifted by 1 unit (length of normalized vector) to the left
35291				// if we walk along contour clockwise, this new contour is outside the old one
35292				//
35293				// inPt' is the intersection of the two lines parallel to the two
35294				//  adjacent edges of inPt at a distance of 1 unit on the left side.
35295
35296				let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt
35297
35298				// good reading for geometry algorithms (here: line-line intersection)
35299				// http://geomalgorithms.com/a05-_intersect-1.html
35300
35301				const v_prev_x = inPt.x - inPrev.x,
35302					v_prev_y = inPt.y - inPrev.y;
35303				const v_next_x = inNext.x - inPt.x,
35304					v_next_y = inNext.y - inPt.y;
35305
35306				const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
35307
35308				// check for collinear edges
35309				const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
35310
35311				if ( Math.abs( collinear0 ) > Number.EPSILON ) {
35312
35313					// not collinear
35314
35315					// length of vectors for normalizing
35316
35317					const v_prev_len = Math.sqrt( v_prev_lensq );
35318					const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
35319
35320					// shift adjacent points by unit vectors to the left
35321
35322					const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
35323					const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
35324
35325					const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
35326					const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
35327
35328					// scaling factor for v_prev to intersection point
35329
35330					const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
35331							( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
35332						( v_prev_x * v_next_y - v_prev_y * v_next_x );
35333
35334					// vector from inPt to intersection point
35335
35336					v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
35337					v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
35338
35339					// Don't normalize!, otherwise sharp corners become ugly
35340					//  but prevent crazy spikes
35341					const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
35342					if ( v_trans_lensq <= 2 ) {
35343
35344						return new Vector2( v_trans_x, v_trans_y );
35345
35346					} else {
35347
35348						shrink_by = Math.sqrt( v_trans_lensq / 2 );
35349
35350					}
35351
35352				} else {
35353
35354					// handle special case of collinear edges
35355
35356					let direction_eq = false; // assumes: opposite
35357
35358					if ( v_prev_x > Number.EPSILON ) {
35359
35360						if ( v_next_x > Number.EPSILON ) {
35361
35362							direction_eq = true;
35363
35364						}
35365
35366					} else {
35367
35368						if ( v_prev_x < - Number.EPSILON ) {
35369
35370							if ( v_next_x < - Number.EPSILON ) {
35371
35372								direction_eq = true;
35373
35374							}
35375
35376						} else {
35377
35378							if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {
35379
35380								direction_eq = true;
35381
35382							}
35383
35384						}
35385
35386					}
35387
35388					if ( direction_eq ) {
35389
35390						// log("Warning: lines are a straight sequence");
35391						v_trans_x = - v_prev_y;
35392						v_trans_y = v_prev_x;
35393						shrink_by = Math.sqrt( v_prev_lensq );
35394
35395					} else {
35396
35397						// log("Warning: lines are a straight spike");
35398						v_trans_x = v_prev_x;
35399						v_trans_y = v_prev_y;
35400						shrink_by = Math.sqrt( v_prev_lensq / 2 );
35401
35402					}
35403
35404				}
35405
35406				return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
35407
35408			}
35409
35410
35411			const contourMovements = [];
35412
35413			for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
35414
35415				if ( j === il ) j = 0;
35416				if ( k === il ) k = 0;
35417
35418				//  (j)---(i)---(k)
35419				// log('i,j,k', i, j , k)
35420
35421				contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
35422
35423			}
35424
35425			const holesMovements = [];
35426			let oneHoleMovements, verticesMovements = contourMovements.concat();
35427
35428			for ( let h = 0, hl = numHoles; h < hl; h ++ ) {
35429
35430				const ahole = holes[ h ];
35431
35432				oneHoleMovements = [];
35433
35434				for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
35435
35436					if ( j === il ) j = 0;
35437					if ( k === il ) k = 0;
35438
35439					//  (j)---(i)---(k)
35440					oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
35441
35442				}
35443
35444				holesMovements.push( oneHoleMovements );
35445				verticesMovements = verticesMovements.concat( oneHoleMovements );
35446
35447			}
35448
35449			let faces;
35450
35451			if ( bevelSegments === 0 ) {
35452
35453				faces = ShapeUtils.triangulateShape( contour, holes );
35454
35455			} else {
35456
35457				const contractedContourVertices = [];
35458				const expandedHoleVertices = [];
35459
35460				// Loop bevelSegments, 1 for the front, 1 for the back
35461
35462				for ( let b = 0; b < bevelSegments; b ++ ) {
35463
35464					//for ( b = bevelSegments; b > 0; b -- ) {
35465
35466					const t = b / bevelSegments;
35467					const z = bevelThickness * Math.cos( t * Math.PI / 2 );
35468					const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
35469
35470					// contract shape
35471
35472					for ( let i = 0, il = contour.length; i < il; i ++ ) {
35473
35474						const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
35475
35476						v( vert.x, vert.y, - z );
35477						if ( t === 0 ) contractedContourVertices.push( vert );
35478
35479					}
35480
35481					// expand holes
35482
35483					for ( let h = 0, hl = numHoles; h < hl; h ++ ) {
35484
35485						const ahole = holes[ h ];
35486						oneHoleMovements = holesMovements[ h ];
35487						const oneHoleVertices = [];
35488						for ( let i = 0, il = ahole.length; i < il; i ++ ) {
35489
35490							const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
35491
35492							v( vert.x, vert.y, - z );
35493							if ( t === 0 ) oneHoleVertices.push( vert );
35494
35495						}
35496
35497						if ( t === 0 ) expandedHoleVertices.push( oneHoleVertices );
35498
35499					}
35500
35501				}
35502
35503				faces = ShapeUtils.triangulateShape( contractedContourVertices, expandedHoleVertices );
35504
35505			}
35506
35507			const flen = faces.length;
35508
35509			const bs = bevelSize + bevelOffset;
35510
35511			// Back facing vertices
35512
35513			for ( let i = 0; i < vlen; i ++ ) {
35514
35515				const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
35516
35517				if ( ! extrudeByPath ) {
35518
35519					v( vert.x, vert.y, 0 );
35520
35521				} else {
35522
35523					// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
35524
35525					normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
35526					binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
35527
35528					position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );
35529
35530					v( position2.x, position2.y, position2.z );
35531
35532				}
35533
35534			}
35535
35536			// Add stepped vertices...
35537			// Including front facing vertices
35538
35539			for ( let s = 1; s <= steps; s ++ ) {
35540
35541				for ( let i = 0; i < vlen; i ++ ) {
35542
35543					const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
35544
35545					if ( ! extrudeByPath ) {
35546
35547						v( vert.x, vert.y, depth / steps * s );
35548
35549					} else {
35550
35551						// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
35552
35553						normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );
35554						binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );
35555
35556						position2.copy( extrudePts[ s ] ).add( normal ).add( binormal );
35557
35558						v( position2.x, position2.y, position2.z );
35559
35560					}
35561
35562				}
35563
35564			}
35565
35566
35567			// Add bevel segments planes
35568
35569			//for ( b = 1; b <= bevelSegments; b ++ ) {
35570			for ( let b = bevelSegments - 1; b >= 0; b -- ) {
35571
35572				const t = b / bevelSegments;
35573				const z = bevelThickness * Math.cos( t * Math.PI / 2 );
35574				const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;
35575
35576				// contract shape
35577
35578				for ( let i = 0, il = contour.length; i < il; i ++ ) {
35579
35580					const vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
35581					v( vert.x, vert.y, depth + z );
35582
35583				}
35584
35585				// expand holes
35586
35587				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35588
35589					const ahole = holes[ h ];
35590					oneHoleMovements = holesMovements[ h ];
35591
35592					for ( let i = 0, il = ahole.length; i < il; i ++ ) {
35593
35594						const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
35595
35596						if ( ! extrudeByPath ) {
35597
35598							v( vert.x, vert.y, depth + z );
35599
35600						} else {
35601
35602							v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
35603
35604						}
35605
35606					}
35607
35608				}
35609
35610			}
35611
35612			/* Faces */
35613
35614			// Top and bottom faces
35615
35616			buildLidFaces();
35617
35618			// Sides faces
35619
35620			buildSideFaces();
35621
35622
35623			/////  Internal functions
35624
35625			function buildLidFaces() {
35626
35627				const start = verticesArray.length / 3;
35628
35629				if ( bevelEnabled ) {
35630
35631					let layer = 0; // steps + 1
35632					let offset = vlen * layer;
35633
35634					// Bottom faces
35635
35636					for ( let i = 0; i < flen; i ++ ) {
35637
35638						const face = faces[ i ];
35639						f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
35640
35641					}
35642
35643					layer = steps + bevelSegments * 2;
35644					offset = vlen * layer;
35645
35646					// Top faces
35647
35648					for ( let i = 0; i < flen; i ++ ) {
35649
35650						const face = faces[ i ];
35651						f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
35652
35653					}
35654
35655				} else {
35656
35657					// Bottom faces
35658
35659					for ( let i = 0; i < flen; i ++ ) {
35660
35661						const face = faces[ i ];
35662						f3( face[ 2 ], face[ 1 ], face[ 0 ] );
35663
35664					}
35665
35666					// Top faces
35667
35668					for ( let i = 0; i < flen; i ++ ) {
35669
35670						const face = faces[ i ];
35671						f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
35672
35673					}
35674
35675				}
35676
35677				scope.addGroup( start, verticesArray.length / 3 - start, 0 );
35678
35679			}
35680
35681			// Create faces for the z-sides of the shape
35682
35683			function buildSideFaces() {
35684
35685				const start = verticesArray.length / 3;
35686				let layeroffset = 0;
35687				sidewalls( contour, layeroffset );
35688				layeroffset += contour.length;
35689
35690				for ( let h = 0, hl = holes.length; h < hl; h ++ ) {
35691
35692					const ahole = holes[ h ];
35693					sidewalls( ahole, layeroffset );
35694
35695					//, true
35696					layeroffset += ahole.length;
35697
35698				}
35699
35700
35701				scope.addGroup( start, verticesArray.length / 3 - start, 1 );
35702
35703
35704			}
35705
35706			function sidewalls( contour, layeroffset ) {
35707
35708				let i = contour.length;
35709
35710				while ( -- i >= 0 ) {
35711
35712					const j = i;
35713					let k = i - 1;
35714					if ( k < 0 ) k = contour.length - 1;
35715
35716					//log('b', i,j, i-1, k,vertices.length);
35717
35718					for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) {
35719
35720						const slen1 = vlen * s;
35721						const slen2 = vlen * ( s + 1 );
35722
35723						const a = layeroffset + j + slen1,
35724							b = layeroffset + k + slen1,
35725							c = layeroffset + k + slen2,
35726							d = layeroffset + j + slen2;
35727
35728						f4( a, b, c, d );
35729
35730					}
35731
35732				}
35733
35734			}
35735
35736			function v( x, y, z ) {
35737
35738				placeholder.push( x );
35739				placeholder.push( y );
35740				placeholder.push( z );
35741
35742			}
35743
35744
35745			function f3( a, b, c ) {
35746
35747				addVertex( a );
35748				addVertex( b );
35749				addVertex( c );
35750
35751				const nextIndex = verticesArray.length / 3;
35752				const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
35753
35754				addUV( uvs[ 0 ] );
35755				addUV( uvs[ 1 ] );
35756				addUV( uvs[ 2 ] );
35757
35758			}
35759
35760			function f4( a, b, c, d ) {
35761
35762				addVertex( a );
35763				addVertex( b );
35764				addVertex( d );
35765
35766				addVertex( b );
35767				addVertex( c );
35768				addVertex( d );
35769
35770
35771				const nextIndex = verticesArray.length / 3;
35772				const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
35773
35774				addUV( uvs[ 0 ] );
35775				addUV( uvs[ 1 ] );
35776				addUV( uvs[ 3 ] );
35777
35778				addUV( uvs[ 1 ] );
35779				addUV( uvs[ 2 ] );
35780				addUV( uvs[ 3 ] );
35781
35782			}
35783
35784			function addVertex( index ) {
35785
35786				verticesArray.push( placeholder[ index * 3 + 0 ] );
35787				verticesArray.push( placeholder[ index * 3 + 1 ] );
35788				verticesArray.push( placeholder[ index * 3 + 2 ] );
35789
35790			}
35791
35792
35793			function addUV( vector2 ) {
35794
35795				uvArray.push( vector2.x );
35796				uvArray.push( vector2.y );
35797
35798			}
35799
35800		}
35801
35802	}
35803
35804	copy( source ) {
35805
35806		super.copy( source );
35807
35808		this.parameters = Object.assign( {}, source.parameters );
35809
35810		return this;
35811
35812	}
35813
35814	toJSON() {
35815
35816		const data = super.toJSON();
35817
35818		const shapes = this.parameters.shapes;
35819		const options = this.parameters.options;
35820
35821		return toJSON$1( shapes, options, data );
35822
35823	}
35824
35825	/**
35826	 * Factory method for creating an instance of this class from the given
35827	 * JSON object.
35828	 *
35829	 * @param {Object} data - A JSON object representing the serialized geometry.
35830	 * @param {Array<Shape>} shapes - An array of shapes.
35831	 * @return {ExtrudeGeometry} A new instance.
35832	 */
35833	static fromJSON( data, shapes ) {
35834
35835		const geometryShapes = [];
35836
35837		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
35838
35839			const shape = shapes[ data.shapes[ j ] ];
35840
35841			geometryShapes.push( shape );
35842
35843		}
35844
35845		const extrudePath = data.options.extrudePath;
35846
35847		if ( extrudePath !== undefined ) {
35848
35849			data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );
35850
35851		}
35852
35853		return new ExtrudeGeometry( geometryShapes, data.options );
35854
35855	}
35856
35857}
35858
35859const WorldUVGenerator = {
35860
35861	generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {
35862
35863		const a_x = vertices[ indexA * 3 ];
35864		const a_y = vertices[ indexA * 3 + 1 ];
35865		const b_x = vertices[ indexB * 3 ];
35866		const b_y = vertices[ indexB * 3 + 1 ];
35867		const c_x = vertices[ indexC * 3 ];
35868		const c_y = vertices[ indexC * 3 + 1 ];
35869
35870		return [
35871			new Vector2( a_x, a_y ),
35872			new Vector2( b_x, b_y ),
35873			new Vector2( c_x, c_y )
35874		];
35875
35876	},
35877
35878	generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
35879
35880		const a_x = vertices[ indexA * 3 ];
35881		const a_y = vertices[ indexA * 3 + 1 ];
35882		const a_z = vertices[ indexA * 3 + 2 ];
35883		const b_x = vertices[ indexB * 3 ];
35884		const b_y = vertices[ indexB * 3 + 1 ];
35885		const b_z = vertices[ indexB * 3 + 2 ];
35886		const c_x = vertices[ indexC * 3 ];
35887		const c_y = vertices[ indexC * 3 + 1 ];
35888		const c_z = vertices[ indexC * 3 + 2 ];
35889		const d_x = vertices[ indexD * 3 ];
35890		const d_y = vertices[ indexD * 3 + 1 ];
35891		const d_z = vertices[ indexD * 3 + 2 ];
35892
35893		if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) {
35894
35895			return [
35896				new Vector2( a_x, 1 - a_z ),
35897				new Vector2( b_x, 1 - b_z ),
35898				new Vector2( c_x, 1 - c_z ),
35899				new Vector2( d_x, 1 - d_z )
35900			];
35901
35902		} else {
35903
35904			return [
35905				new Vector2( a_y, 1 - a_z ),
35906				new Vector2( b_y, 1 - b_z ),
35907				new Vector2( c_y, 1 - c_z ),
35908				new Vector2( d_y, 1 - d_z )
35909			];
35910
35911		}
35912
35913	}
35914
35915};
35916
35917function toJSON$1( shapes, options, data ) {
35918
35919	data.shapes = [];
35920
35921	if ( Array.isArray( shapes ) ) {
35922
35923		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
35924
35925			const shape = shapes[ i ];
35926
35927			data.shapes.push( shape.uuid );
35928
35929		}
35930
35931	} else {
35932
35933		data.shapes.push( shapes.uuid );
35934
35935	}
35936
35937	data.options = Object.assign( {}, options );
35938
35939	if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON();
35940
35941	return data;
35942
35943}
35944
35945/**
35946 * A geometry class for representing an icosahedron.
35947 *
35948 * ```js
35949 * const geometry = new THREE.IcosahedronGeometry();
35950 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
35951 * const icosahedron = new THREE.Mesh( geometry, material );
35952 * scene.add( icosahedron );
35953 * ```
35954 *
35955 * @augments PolyhedronGeometry
35956 * @demo scenes/geometry-browser.html#IcosahedronGeometry
35957 */
35958class IcosahedronGeometry extends PolyhedronGeometry {
35959
35960	/**
35961	 * Constructs a new icosahedron geometry.
35962	 *
35963	 * @param {number} [radius=1] - Radius of the icosahedron.
35964	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a icosahedron.
35965	 */
35966	constructor( radius = 1, detail = 0 ) {
35967
35968		const t = ( 1 + Math.sqrt( 5 ) ) / 2;
35969
35970		const vertices = [
35971			-1, t, 0, 	1, t, 0, 	-1, - t, 0, 	1, - t, 0,
35972			0, -1, t, 	0, 1, t,	0, -1, - t, 	0, 1, - t,
35973			t, 0, -1, 	t, 0, 1, 	- t, 0, -1, 	- t, 0, 1
35974		];
35975
35976		const indices = [
35977			0, 11, 5, 	0, 5, 1, 	0, 1, 7, 	0, 7, 10, 	0, 10, 11,
35978			1, 5, 9, 	5, 11, 4,	11, 10, 2,	10, 7, 6,	7, 1, 8,
35979			3, 9, 4, 	3, 4, 2,	3, 2, 6,	3, 6, 8,	3, 8, 9,
35980			4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
35981		];
35982
35983		super( vertices, indices, radius, detail );
35984
35985		this.type = 'IcosahedronGeometry';
35986
35987		/**
35988		 * Holds the constructor parameters that have been
35989		 * used to generate the geometry. Any modification
35990		 * after instantiation does not change the geometry.
35991		 *
35992		 * @type {Object}
35993		 */
35994		this.parameters = {
35995			radius: radius,
35996			detail: detail
35997		};
35998
35999	}
36000
36001	/**
36002	 * Factory method for creating an instance of this class from the given
36003	 * JSON object.
36004	 *
36005	 * @param {Object} data - A JSON object representing the serialized geometry.
36006	 * @return {IcosahedronGeometry} A new instance.
36007	 */
36008	static fromJSON( data ) {
36009
36010		return new IcosahedronGeometry( data.radius, data.detail );
36011
36012	}
36013
36014}
36015
36016/**
36017 * Creates meshes with axial symmetry like vases. The lathe rotates around the Y axis.
36018 *
36019 * ```js
36020 * const points = [];
36021 * for ( let i = 0; i < 10; i ++ ) {
36022 * 	points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
36023 * }
36024 * const geometry = new THREE.LatheGeometry( points );
36025 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36026 * const lathe = new THREE.Mesh( geometry, material );
36027 * scene.add( lathe );
36028 * ```
36029 *
36030 * @augments BufferGeometry
36031 * @demo scenes/geometry-browser.html#LatheGeometry
36032 */
36033class LatheGeometry extends BufferGeometry {
36034
36035	/**
36036	 * Constructs a new lathe geometry.
36037	 *
36038	 * @param {Array<Vector2|Vector3>} [points] - An array of points in 2D space. The x-coordinate of each point
36039	 * must be greater than zero.
36040	 * @param {number} [segments=12] - The number of circumference segments to generate.
36041	 * @param {number} [phiStart=0] - The starting angle in radians.
36042	 * @param {number} [phiLength=Math.PI*2] - The radian (0 to 2PI) range of the lathed section 2PI is a
36043	 * closed lathe, less than 2PI is a portion.
36044	 */
36045	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 ) {
36046
36047		super();
36048
36049		this.type = 'LatheGeometry';
36050
36051		/**
36052		 * Holds the constructor parameters that have been
36053		 * used to generate the geometry. Any modification
36054		 * after instantiation does not change the geometry.
36055		 *
36056		 * @type {Object}
36057		 */
36058		this.parameters = {
36059			points: points,
36060			segments: segments,
36061			phiStart: phiStart,
36062			phiLength: phiLength
36063		};
36064
36065		segments = Math.floor( segments );
36066
36067		// clamp phiLength so it's in range of [ 0, 2PI ]
36068
36069		phiLength = clamp( phiLength, 0, Math.PI * 2 );
36070
36071		// buffers
36072
36073		const indices = [];
36074		const vertices = [];
36075		const uvs = [];
36076		const initNormals = [];
36077		const normals = [];
36078
36079		// helper variables
36080
36081		const inverseSegments = 1.0 / segments;
36082		const vertex = new Vector3();
36083		const uv = new Vector2();
36084		const normal = new Vector3();
36085		const curNormal = new Vector3();
36086		const prevNormal = new Vector3();
36087		let dx = 0;
36088		let dy = 0;
36089
36090		// pre-compute normals for initial "meridian"
36091
36092		for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
36093
36094			switch ( j ) {
36095
36096				case 0:				// special handling for 1st vertex on path
36097
36098					dx = points[ j + 1 ].x - points[ j ].x;
36099					dy = points[ j + 1 ].y - points[ j ].y;
36100
36101					normal.x = dy * 1.0;
36102					normal.y = - dx;
36103					normal.z = dy * 0.0;
36104
36105					prevNormal.copy( normal );
36106
36107					normal.normalize();
36108
36109					initNormals.push( normal.x, normal.y, normal.z );
36110
36111					break;
36112
36113				case ( points.length - 1 ):	// special handling for last Vertex on path
36114
36115					initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z );
36116
36117					break;
36118
36119				default:			// default handling for all vertices in between
36120
36121					dx = points[ j + 1 ].x - points[ j ].x;
36122					dy = points[ j + 1 ].y - points[ j ].y;
36123
36124					normal.x = dy * 1.0;
36125					normal.y = - dx;
36126					normal.z = dy * 0.0;
36127
36128					curNormal.copy( normal );
36129
36130					normal.x += prevNormal.x;
36131					normal.y += prevNormal.y;
36132					normal.z += prevNormal.z;
36133
36134					normal.normalize();
36135
36136					initNormals.push( normal.x, normal.y, normal.z );
36137
36138					prevNormal.copy( curNormal );
36139
36140			}
36141
36142		}
36143
36144		// generate vertices, uvs and normals
36145
36146		for ( let i = 0; i <= segments; i ++ ) {
36147
36148			const phi = phiStart + i * inverseSegments * phiLength;
36149
36150			const sin = Math.sin( phi );
36151			const cos = Math.cos( phi );
36152
36153			for ( let j = 0; j <= ( points.length - 1 ); j ++ ) {
36154
36155				// vertex
36156
36157				vertex.x = points[ j ].x * sin;
36158				vertex.y = points[ j ].y;
36159				vertex.z = points[ j ].x * cos;
36160
36161				vertices.push( vertex.x, vertex.y, vertex.z );
36162
36163				// uv
36164
36165				uv.x = i / segments;
36166				uv.y = j / ( points.length - 1 );
36167
36168				uvs.push( uv.x, uv.y );
36169
36170				// normal
36171
36172				const x = initNormals[ 3 * j + 0 ] * sin;
36173				const y = initNormals[ 3 * j + 1 ];
36174				const z = initNormals[ 3 * j + 0 ] * cos;
36175
36176				normals.push( x, y, z );
36177
36178			}
36179
36180		}
36181
36182		// indices
36183
36184		for ( let i = 0; i < segments; i ++ ) {
36185
36186			for ( let j = 0; j < ( points.length - 1 ); j ++ ) {
36187
36188				const base = j + i * points.length;
36189
36190				const a = base;
36191				const b = base + points.length;
36192				const c = base + points.length + 1;
36193				const d = base + 1;
36194
36195				// faces
36196
36197				indices.push( a, b, d );
36198				indices.push( c, d, b );
36199
36200			}
36201
36202		}
36203
36204		// build geometry
36205
36206		this.setIndex( indices );
36207		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36208		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36209		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36210
36211	}
36212
36213	copy( source ) {
36214
36215		super.copy( source );
36216
36217		this.parameters = Object.assign( {}, source.parameters );
36218
36219		return this;
36220
36221	}
36222
36223	/**
36224	 * Factory method for creating an instance of this class from the given
36225	 * JSON object.
36226	 *
36227	 * @param {Object} data - A JSON object representing the serialized geometry.
36228	 * @return {LatheGeometry} A new instance.
36229	 */
36230	static fromJSON( data ) {
36231
36232		return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength );
36233
36234	}
36235
36236}
36237
36238/**
36239 * A geometry class for representing an octahedron.
36240 *
36241 * ```js
36242 * const geometry = new THREE.OctahedronGeometry();
36243 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36244 * const octahedron = new THREE.Mesh( geometry, material );
36245 * scene.add( octahedron );
36246 * ```
36247 *
36248 * @augments PolyhedronGeometry
36249 * @demo scenes/geometry-browser.html#OctahedronGeometry
36250 */
36251class OctahedronGeometry extends PolyhedronGeometry {
36252
36253	/**
36254	 * Constructs a new octahedron geometry.
36255	 *
36256	 * @param {number} [radius=1] - Radius of the octahedron.
36257	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a octahedron.
36258	 */
36259	constructor( radius = 1, detail = 0 ) {
36260
36261		const vertices = [
36262			1, 0, 0, 	-1, 0, 0,	0, 1, 0,
36263			0, -1, 0, 	0, 0, 1,	0, 0, -1
36264		];
36265
36266		const indices = [
36267			0, 2, 4,	0, 4, 3,	0, 3, 5,
36268			0, 5, 2,	1, 2, 5,	1, 5, 3,
36269			1, 3, 4,	1, 4, 2
36270		];
36271
36272		super( vertices, indices, radius, detail );
36273
36274		this.type = 'OctahedronGeometry';
36275
36276		/**
36277		 * Holds the constructor parameters that have been
36278		 * used to generate the geometry. Any modification
36279		 * after instantiation does not change the geometry.
36280		 *
36281		 * @type {Object}
36282		 */
36283		this.parameters = {
36284			radius: radius,
36285			detail: detail
36286		};
36287
36288	}
36289
36290	/**
36291	 * Factory method for creating an instance of this class from the given
36292	 * JSON object.
36293	 *
36294	 * @param {Object} data - A JSON object representing the serialized geometry.
36295	 * @return {OctahedronGeometry} A new instance.
36296	 */
36297	static fromJSON( data ) {
36298
36299		return new OctahedronGeometry( data.radius, data.detail );
36300
36301	}
36302
36303}
36304
36305/**
36306 * A geometry class for representing a plane.
36307 *
36308 * ```js
36309 * const geometry = new THREE.PlaneGeometry( 1, 1 );
36310 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } );
36311 * const plane = new THREE.Mesh( geometry, material );
36312 * scene.add( plane );
36313 * ```
36314 *
36315 * @augments BufferGeometry
36316 * @demo scenes/geometry-browser.html#PlaneGeometry
36317 */
36318class PlaneGeometry extends BufferGeometry {
36319
36320	/**
36321	 * Constructs a new plane geometry.
36322	 *
36323	 * @param {number} [width=1] - The width along the X axis.
36324	 * @param {number} [height=1] - The height along the Y axis
36325	 * @param {number} [widthSegments=1] - The number of segments along the X axis.
36326	 * @param {number} [heightSegments=1] - The number of segments along the Y axis.
36327	 */
36328	constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
36329
36330		super();
36331
36332		this.type = 'PlaneGeometry';
36333
36334		/**
36335		 * Holds the constructor parameters that have been
36336		 * used to generate the geometry. Any modification
36337		 * after instantiation does not change the geometry.
36338		 *
36339		 * @type {Object}
36340		 */
36341		this.parameters = {
36342			width: width,
36343			height: height,
36344			widthSegments: widthSegments,
36345			heightSegments: heightSegments
36346		};
36347
36348		const width_half = width / 2;
36349		const height_half = height / 2;
36350
36351		const gridX = Math.floor( widthSegments );
36352		const gridY = Math.floor( heightSegments );
36353
36354		const gridX1 = gridX + 1;
36355		const gridY1 = gridY + 1;
36356
36357		const segment_width = width / gridX;
36358		const segment_height = height / gridY;
36359
36360		//
36361
36362		const indices = [];
36363		const vertices = [];
36364		const normals = [];
36365		const uvs = [];
36366
36367		for ( let iy = 0; iy < gridY1; iy ++ ) {
36368
36369			const y = iy * segment_height - height_half;
36370
36371			for ( let ix = 0; ix < gridX1; ix ++ ) {
36372
36373				const x = ix * segment_width - width_half;
36374
36375				vertices.push( x, - y, 0 );
36376
36377				normals.push( 0, 0, 1 );
36378
36379				uvs.push( ix / gridX );
36380				uvs.push( 1 - ( iy / gridY ) );
36381
36382			}
36383
36384		}
36385
36386		for ( let iy = 0; iy < gridY; iy ++ ) {
36387
36388			for ( let ix = 0; ix < gridX; ix ++ ) {
36389
36390				const a = ix + gridX1 * iy;
36391				const b = ix + gridX1 * ( iy + 1 );
36392				const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
36393				const d = ( ix + 1 ) + gridX1 * iy;
36394
36395				indices.push( a, b, d );
36396				indices.push( b, c, d );
36397
36398			}
36399
36400		}
36401
36402		this.setIndex( indices );
36403		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36404		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36405		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36406
36407	}
36408
36409	copy( source ) {
36410
36411		super.copy( source );
36412
36413		this.parameters = Object.assign( {}, source.parameters );
36414
36415		return this;
36416
36417	}
36418
36419	/**
36420	 * Factory method for creating an instance of this class from the given
36421	 * JSON object.
36422	 *
36423	 * @param {Object} data - A JSON object representing the serialized geometry.
36424	 * @return {PlaneGeometry} A new instance.
36425	 */
36426	static fromJSON( data ) {
36427
36428		return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
36429
36430	}
36431
36432}
36433
36434/**
36435 * A class for generating a two-dimensional ring geometry.
36436 *
36437 * ```js
36438 * const geometry = new THREE.RingGeometry( 1, 5, 32 );
36439 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } );
36440 * const mesh = new THREE.Mesh( geometry, material );
36441 * scene.add( mesh );
36442 * ```
36443 *
36444 * @augments BufferGeometry
36445 * @demo scenes/geometry-browser.html#RingGeometry
36446 */
36447class RingGeometry extends BufferGeometry {
36448
36449	/**
36450	 * Constructs a new ring geometry.
36451	 *
36452	 * @param {number} [innerRadius=0.5] - The inner radius of the ring.
36453	 * @param {number} [outerRadius=1] - The outer radius of the ring.
36454	 * @param {number} [thetaSegments=32] - Number of segments. A higher number means the ring will be more round. Minimum is `3`.
36455	 * @param {number} [phiSegments=1] - Number of segments per ring segment. Minimum is `1`.
36456	 * @param {number} [thetaStart=0] - Starting angle in radians.
36457	 * @param {number} [thetaLength=Math.PI*2] - Central angle in radians.
36458	 */
36459	constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) {
36460
36461		super();
36462
36463		this.type = 'RingGeometry';
36464
36465		/**
36466		 * Holds the constructor parameters that have been
36467		 * used to generate the geometry. Any modification
36468		 * after instantiation does not change the geometry.
36469		 *
36470		 * @type {Object}
36471		 */
36472		this.parameters = {
36473			innerRadius: innerRadius,
36474			outerRadius: outerRadius,
36475			thetaSegments: thetaSegments,
36476			phiSegments: phiSegments,
36477			thetaStart: thetaStart,
36478			thetaLength: thetaLength
36479		};
36480
36481		thetaSegments = Math.max( 3, thetaSegments );
36482		phiSegments = Math.max( 1, phiSegments );
36483
36484		// buffers
36485
36486		const indices = [];
36487		const vertices = [];
36488		const normals = [];
36489		const uvs = [];
36490
36491		// some helper variables
36492
36493		let radius = innerRadius;
36494		const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
36495		const vertex = new Vector3();
36496		const uv = new Vector2();
36497
36498		// generate vertices, normals and uvs
36499
36500		for ( let j = 0; j <= phiSegments; j ++ ) {
36501
36502			for ( let i = 0; i <= thetaSegments; i ++ ) {
36503
36504				// values are generate from the inside of the ring to the outside
36505
36506				const segment = thetaStart + i / thetaSegments * thetaLength;
36507
36508				// vertex
36509
36510				vertex.x = radius * Math.cos( segment );
36511				vertex.y = radius * Math.sin( segment );
36512
36513				vertices.push( vertex.x, vertex.y, vertex.z );
36514
36515				// normal
36516
36517				normals.push( 0, 0, 1 );
36518
36519				// uv
36520
36521				uv.x = ( vertex.x / outerRadius + 1 ) / 2;
36522				uv.y = ( vertex.y / outerRadius + 1 ) / 2;
36523
36524				uvs.push( uv.x, uv.y );
36525
36526			}
36527
36528			// increase the radius for next row of vertices
36529
36530			radius += radiusStep;
36531
36532		}
36533
36534		// indices
36535
36536		for ( let j = 0; j < phiSegments; j ++ ) {
36537
36538			const thetaSegmentLevel = j * ( thetaSegments + 1 );
36539
36540			for ( let i = 0; i < thetaSegments; i ++ ) {
36541
36542				const segment = i + thetaSegmentLevel;
36543
36544				const a = segment;
36545				const b = segment + thetaSegments + 1;
36546				const c = segment + thetaSegments + 2;
36547				const d = segment + 1;
36548
36549				// faces
36550
36551				indices.push( a, b, d );
36552				indices.push( b, c, d );
36553
36554			}
36555
36556		}
36557
36558		// build geometry
36559
36560		this.setIndex( indices );
36561		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36562		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36563		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36564
36565	}
36566
36567	copy( source ) {
36568
36569		super.copy( source );
36570
36571		this.parameters = Object.assign( {}, source.parameters );
36572
36573		return this;
36574
36575	}
36576
36577	/**
36578	 * Factory method for creating an instance of this class from the given
36579	 * JSON object.
36580	 *
36581	 * @param {Object} data - A JSON object representing the serialized geometry.
36582	 * @return {RingGeometry} A new instance.
36583	 */
36584	static fromJSON( data ) {
36585
36586		return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength );
36587
36588	}
36589
36590}
36591
36592/**
36593 * Creates an one-sided polygonal geometry from one or more path shapes.
36594 *
36595 * ```js
36596 * const arcShape = new THREE.Shape()
36597 *	.moveTo( 5, 1 )
36598 *	.absarc( 1, 1, 4, 0, Math.PI * 2, false );
36599 *
36600 * const geometry = new THREE.ShapeGeometry( arcShape );
36601 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00, side: THREE.DoubleSide } );
36602 * const mesh = new THREE.Mesh( geometry, material ) ;
36603 * scene.add( mesh );
36604 * ```
36605 *
36606 * @augments BufferGeometry
36607 * @demo scenes/geometry-browser.html#ShapeGeometry
36608 */
36609class ShapeGeometry extends BufferGeometry {
36610
36611	/**
36612	 * Constructs a new shape geometry.
36613	 *
36614	 * @param {Shape|Array<Shape>} [shapes] - A shape or an array of shapes.
36615	 * @param {number} [curveSegments=12] - Number of segments per shape.
36616	 */
36617	constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( -0.5, -0.5 ), new Vector2( 0.5, -0.5 ) ] ), curveSegments = 12 ) {
36618
36619		super();
36620
36621		this.type = 'ShapeGeometry';
36622
36623		/**
36624		 * Holds the constructor parameters that have been
36625		 * used to generate the geometry. Any modification
36626		 * after instantiation does not change the geometry.
36627		 *
36628		 * @type {Object}
36629		 */
36630		this.parameters = {
36631			shapes: shapes,
36632			curveSegments: curveSegments
36633		};
36634
36635		// buffers
36636
36637		const indices = [];
36638		const vertices = [];
36639		const normals = [];
36640		const uvs = [];
36641
36642		// helper variables
36643
36644		let groupStart = 0;
36645		let groupCount = 0;
36646
36647		// allow single and array values for "shapes" parameter
36648
36649		if ( Array.isArray( shapes ) === false ) {
36650
36651			addShape( shapes );
36652
36653		} else {
36654
36655			for ( let i = 0; i < shapes.length; i ++ ) {
36656
36657				addShape( shapes[ i ] );
36658
36659				this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support
36660
36661				groupStart += groupCount;
36662				groupCount = 0;
36663
36664			}
36665
36666		}
36667
36668		// build geometry
36669
36670		this.setIndex( indices );
36671		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36672		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36673		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36674
36675
36676		// helper functions
36677
36678		function addShape( shape ) {
36679
36680			const indexOffset = vertices.length / 3;
36681			const points = shape.extractPoints( curveSegments );
36682
36683			let shapeVertices = points.shape;
36684			const shapeHoles = points.holes;
36685
36686			// check direction of vertices
36687
36688			if ( ShapeUtils.isClockWise( shapeVertices ) === false ) {
36689
36690				shapeVertices = shapeVertices.reverse();
36691
36692			}
36693
36694			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
36695
36696				const shapeHole = shapeHoles[ i ];
36697
36698				if ( ShapeUtils.isClockWise( shapeHole ) === true ) {
36699
36700					shapeHoles[ i ] = shapeHole.reverse();
36701
36702				}
36703
36704			}
36705
36706			const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
36707
36708			// join vertices of inner and outer paths to a single array
36709
36710			for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) {
36711
36712				const shapeHole = shapeHoles[ i ];
36713				shapeVertices = shapeVertices.concat( shapeHole );
36714
36715			}
36716
36717			// vertices, normals, uvs
36718
36719			for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) {
36720
36721				const vertex = shapeVertices[ i ];
36722
36723				vertices.push( vertex.x, vertex.y, 0 );
36724				normals.push( 0, 0, 1 );
36725				uvs.push( vertex.x, vertex.y ); // world uvs
36726
36727			}
36728
36729			// indices
36730
36731			for ( let i = 0, l = faces.length; i < l; i ++ ) {
36732
36733				const face = faces[ i ];
36734
36735				const a = face[ 0 ] + indexOffset;
36736				const b = face[ 1 ] + indexOffset;
36737				const c = face[ 2 ] + indexOffset;
36738
36739				indices.push( a, b, c );
36740				groupCount += 3;
36741
36742			}
36743
36744		}
36745
36746	}
36747
36748	copy( source ) {
36749
36750		super.copy( source );
36751
36752		this.parameters = Object.assign( {}, source.parameters );
36753
36754		return this;
36755
36756	}
36757
36758	toJSON() {
36759
36760		const data = super.toJSON();
36761
36762		const shapes = this.parameters.shapes;
36763
36764		return toJSON( shapes, data );
36765
36766	}
36767
36768	/**
36769	 * Factory method for creating an instance of this class from the given
36770	 * JSON object.
36771	 *
36772	 * @param {Object} data - A JSON object representing the serialized geometry.
36773	 * @param {Array<Shape>} shapes - An array of shapes.
36774	 * @return {ShapeGeometry} A new instance.
36775	 */
36776	static fromJSON( data, shapes ) {
36777
36778		const geometryShapes = [];
36779
36780		for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) {
36781
36782			const shape = shapes[ data.shapes[ j ] ];
36783
36784			geometryShapes.push( shape );
36785
36786		}
36787
36788		return new ShapeGeometry( geometryShapes, data.curveSegments );
36789
36790	}
36791
36792}
36793
36794function toJSON( shapes, data ) {
36795
36796	data.shapes = [];
36797
36798	if ( Array.isArray( shapes ) ) {
36799
36800		for ( let i = 0, l = shapes.length; i < l; i ++ ) {
36801
36802			const shape = shapes[ i ];
36803
36804			data.shapes.push( shape.uuid );
36805
36806		}
36807
36808	} else {
36809
36810		data.shapes.push( shapes.uuid );
36811
36812	}
36813
36814	return data;
36815
36816}
36817
36818/**
36819 * A class for generating a sphere geometry.
36820 *
36821 * ```js
36822 * const geometry = new THREE.SphereGeometry( 15, 32, 16 );
36823 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36824 * const sphere = new THREE.Mesh( geometry, material );
36825 * scene.add( sphere );
36826 * ```
36827 *
36828 * @augments BufferGeometry
36829 * @demo scenes/geometry-browser.html#SphereGeometry
36830 */
36831class SphereGeometry extends BufferGeometry {
36832
36833	/**
36834	 * Constructs a new sphere geometry.
36835	 *
36836	 * @param {number} [radius=1] - The sphere radius.
36837	 * @param {number} [widthSegments=32] - The number of horizontal segments. Minimum value is `3`.
36838	 * @param {number} [heightSegments=16] - The number of vertical segments. Minimum value is `2`.
36839	 * @param {number} [phiStart=0] - The horizontal starting angle in radians.
36840	 * @param {number} [phiLength=Math.PI*2] - The horizontal sweep angle size.
36841	 * @param {number} [thetaStart=0] - The vertical starting angle in radians.
36842	 * @param {number} [thetaLength=Math.PI] - The vertical sweep angle size.
36843	 */
36844	constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) {
36845
36846		super();
36847
36848		this.type = 'SphereGeometry';
36849
36850		/**
36851		 * Holds the constructor parameters that have been
36852		 * used to generate the geometry. Any modification
36853		 * after instantiation does not change the geometry.
36854		 *
36855		 * @type {Object}
36856		 */
36857		this.parameters = {
36858			radius: radius,
36859			widthSegments: widthSegments,
36860			heightSegments: heightSegments,
36861			phiStart: phiStart,
36862			phiLength: phiLength,
36863			thetaStart: thetaStart,
36864			thetaLength: thetaLength
36865		};
36866
36867		widthSegments = Math.max( 3, Math.floor( widthSegments ) );
36868		heightSegments = Math.max( 2, Math.floor( heightSegments ) );
36869
36870		const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );
36871
36872		let index = 0;
36873		const grid = [];
36874
36875		const vertex = new Vector3();
36876		const normal = new Vector3();
36877
36878		// buffers
36879
36880		const indices = [];
36881		const vertices = [];
36882		const normals = [];
36883		const uvs = [];
36884
36885		// generate vertices, normals and uvs
36886
36887		for ( let iy = 0; iy <= heightSegments; iy ++ ) {
36888
36889			const verticesRow = [];
36890
36891			const v = iy / heightSegments;
36892			const theta = thetaStart + v * thetaLength;
36893
36894			const y = radius * Math.cos( theta );
36895			const ringRadius = Math.sqrt( radius * radius - y * y );
36896
36897			// special case for the poles
36898
36899			let uOffset = 0;
36900
36901			if ( iy === 0 && thetaStart === 0 ) {
36902
36903				uOffset = 0.5 / widthSegments;
36904
36905			} else if ( iy === heightSegments && thetaEnd === Math.PI ) {
36906
36907				uOffset = -0.5 / widthSegments;
36908
36909			}
36910
36911			for ( let ix = 0; ix <= widthSegments; ix ++ ) {
36912
36913				const u = ix / widthSegments;
36914				const phi = phiStart + u * phiLength;
36915
36916				// vertex
36917
36918				vertex.x = - ringRadius * Math.cos( phi );
36919				vertex.y = y;
36920				vertex.z = ringRadius * Math.sin( phi );
36921
36922				vertices.push( vertex.x, vertex.y, vertex.z );
36923
36924				// normal
36925
36926				normal.copy( vertex ).normalize();
36927				normals.push( normal.x, normal.y, normal.z );
36928
36929				// uv
36930
36931				uvs.push( u + uOffset, 1 - v );
36932
36933				verticesRow.push( index ++ );
36934
36935			}
36936
36937			grid.push( verticesRow );
36938
36939		}
36940
36941		// indices
36942
36943		for ( let iy = 0; iy < heightSegments; iy ++ ) {
36944
36945			for ( let ix = 0; ix < widthSegments; ix ++ ) {
36946
36947				const a = grid[ iy ][ ix + 1 ];
36948				const b = grid[ iy ][ ix ];
36949				const c = grid[ iy + 1 ][ ix ];
36950				const d = grid[ iy + 1 ][ ix + 1 ];
36951
36952				if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
36953				if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
36954
36955			}
36956
36957		}
36958
36959		// build geometry
36960
36961		this.setIndex( indices );
36962		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
36963		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
36964		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
36965
36966	}
36967
36968	copy( source ) {
36969
36970		super.copy( source );
36971
36972		this.parameters = Object.assign( {}, source.parameters );
36973
36974		return this;
36975
36976	}
36977
36978	/**
36979	 * Factory method for creating an instance of this class from the given
36980	 * JSON object.
36981	 *
36982	 * @param {Object} data - A JSON object representing the serialized geometry.
36983	 * @return {SphereGeometry} A new instance.
36984	 */
36985	static fromJSON( data ) {
36986
36987		return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength );
36988
36989	}
36990
36991}
36992
36993/**
36994 * A geometry class for representing an tetrahedron.
36995 *
36996 * ```js
36997 * const geometry = new THREE.TetrahedronGeometry();
36998 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
36999 * const tetrahedron = new THREE.Mesh( geometry, material );
37000 * scene.add( tetrahedron );
37001 * ```
37002 *
37003 * @augments PolyhedronGeometry
37004 * @demo scenes/geometry-browser.html#TetrahedronGeometry
37005 */
37006class TetrahedronGeometry extends PolyhedronGeometry {
37007
37008	/**
37009	 * Constructs a new tetrahedron geometry.
37010	 *
37011	 * @param {number} [radius=1] - Radius of the tetrahedron.
37012	 * @param {number} [detail=0] - Setting this to a value greater than `0` adds vertices making it no longer a tetrahedron.
37013	 */
37014	constructor( radius = 1, detail = 0 ) {
37015
37016		const vertices = [
37017			1, 1, 1, 	-1, -1, 1, 	-1, 1, -1, 	1, -1, -1
37018		];
37019
37020		const indices = [
37021			2, 1, 0, 	0, 3, 2,	1, 3, 0,	2, 3, 1
37022		];
37023
37024		super( vertices, indices, radius, detail );
37025
37026		this.type = 'TetrahedronGeometry';
37027
37028		/**
37029		 * Holds the constructor parameters that have been
37030		 * used to generate the geometry. Any modification
37031		 * after instantiation does not change the geometry.
37032		 *
37033		 * @type {Object}
37034		 */
37035		this.parameters = {
37036			radius: radius,
37037			detail: detail
37038		};
37039
37040	}
37041
37042	/**
37043	 * Factory method for creating an instance of this class from the given
37044	 * JSON object.
37045	 *
37046	 * @param {Object} data - A JSON object representing the serialized geometry.
37047	 * @return {TetrahedronGeometry} A new instance.
37048	 */
37049	static fromJSON( data ) {
37050
37051		return new TetrahedronGeometry( data.radius, data.detail );
37052
37053	}
37054
37055}
37056
37057/**
37058 * A geometry class for representing an torus.
37059 *
37060 * ```js
37061 * const geometry = new THREE.TorusGeometry( 10, 3, 16, 100 );
37062 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
37063 * const torus = new THREE.Mesh( geometry, material );
37064 * scene.add( torus );
37065 * ```
37066 *
37067 * @augments BufferGeometry
37068 * @demo scenes/geometry-browser.html#TorusGeometry
37069 */
37070class TorusGeometry extends BufferGeometry {
37071
37072	/**
37073	 * Constructs a new torus geometry.
37074	 *
37075	 * @param {number} [radius=1] - Radius of the torus, from the center of the torus to the center of the tube.
37076	 * @param {number} [tube=0.4] - Radius of the tube. Must be smaller than `radius`.
37077	 * @param {number} [radialSegments=12] - The number of radial segments.
37078	 * @param {number} [tubularSegments=48] - The number of tubular segments.
37079	 * @param {number} [arc=Math.PI*2] - Central angle in radians.
37080	 * @param {number} [thetaStart=0] - Start of the tubular sweep in radians.
37081	 * @param {number} [thetaLength=Math.PI*2] - Length of the tubular sweep in radians.
37082	 */
37083	constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI * 2 ) {
37084
37085		super();
37086
37087		this.type = 'TorusGeometry';
37088
37089		/**
37090		 * Holds the constructor parameters that have been
37091		 * used to generate the geometry. Any modification
37092		 * after instantiation does not change the geometry.
37093		 *
37094		 * @type {Object}
37095		 */
37096		this.parameters = {
37097			radius: radius,
37098			tube: tube,
37099			radialSegments: radialSegments,
37100			tubularSegments: tubularSegments,
37101			arc: arc,
37102			thetaStart: thetaStart,
37103			thetaLength: thetaLength,
37104		};
37105
37106		radialSegments = Math.floor( radialSegments );
37107		tubularSegments = Math.floor( tubularSegments );
37108
37109		// buffers
37110
37111		const indices = [];
37112		const vertices = [];
37113		const normals = [];
37114		const uvs = [];
37115
37116		// helper variables
37117
37118		const center = new Vector3();
37119		const vertex = new Vector3();
37120		const normal = new Vector3();
37121
37122		// generate vertices, normals and uvs
37123
37124		for ( let j = 0; j <= radialSegments; j ++ ) {
37125
37126			const v = thetaStart + ( j / radialSegments ) * thetaLength;
37127
37128			for ( let i = 0; i <= tubularSegments; i ++ ) {
37129
37130				const u = i / tubularSegments * arc;
37131
37132				// vertex
37133
37134				vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
37135				vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
37136				vertex.z = tube * Math.sin( v );
37137
37138				vertices.push( vertex.x, vertex.y, vertex.z );
37139
37140				// normal
37141
37142				center.x = radius * Math.cos( u );
37143				center.y = radius * Math.sin( u );
37144				normal.subVectors( vertex, center ).normalize();
37145
37146				normals.push( normal.x, normal.y, normal.z );
37147
37148				// uv
37149
37150				uvs.push( i / tubularSegments );
37151				uvs.push( j / radialSegments );
37152
37153			}
37154
37155		}
37156
37157		// generate indices
37158
37159		for ( let j = 1; j <= radialSegments; j ++ ) {
37160
37161			for ( let i = 1; i <= tubularSegments; i ++ ) {
37162
37163				// indices
37164
37165				const a = ( tubularSegments + 1 ) * j + i - 1;
37166				const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
37167				const c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
37168				const d = ( tubularSegments + 1 ) * j + i;
37169
37170				// faces
37171
37172				indices.push( a, b, d );
37173				indices.push( b, c, d );
37174
37175			}
37176
37177		}
37178
37179		// build geometry
37180
37181		this.setIndex( indices );
37182		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37183		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37184		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37185
37186	}
37187
37188	copy( source ) {
37189
37190		super.copy( source );
37191
37192		this.parameters = Object.assign( {}, source.parameters );
37193
37194		return this;
37195
37196	}
37197
37198	/**
37199	 * Factory method for creating an instance of this class from the given
37200	 * JSON object.
37201	 *
37202	 * @param {Object} data - A JSON object representing the serialized geometry.
37203	 * @return {TorusGeometry} A new instance.
37204	 */
37205	static fromJSON( data ) {
37206
37207		return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc, data.thetaStart, data.thetaLength );
37208
37209	}
37210
37211}
37212
37213/**
37214 * Creates a torus knot, the particular shape of which is defined by a pair
37215 * of coprime integers, p and q. If p and q are not coprime, the result will
37216 * be a torus link.
37217 *
37218 * ```js
37219 * const geometry = new THREE.TorusKnotGeometry( 10, 3, 100, 16 );
37220 * const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
37221 * const torusKnot = new THREE.Mesh( geometry, material );
37222 * scene.add( torusKnot );
37223 * ```
37224 *
37225 * @augments BufferGeometry
37226 * @demo scenes/geometry-browser.html#TorusKnotGeometry
37227 */
37228class TorusKnotGeometry extends BufferGeometry {
37229
37230	/**
37231	 * Constructs a new torus knot geometry.
37232	 *
37233	 * @param {number} [radius=1] - Radius of the torus knot.
37234	 * @param {number} [tube=0.4] - Radius of the tube.
37235	 * @param {number} [tubularSegments=64] - The number of tubular segments.
37236	 * @param {number} [radialSegments=8] - The number of radial segments.
37237	 * @param {number} [p=2] - This value determines, how many times the geometry winds around its axis of rotational symmetry.
37238	 * @param {number} [q=3] - This value determines, how many times the geometry winds around a circle in the interior of the torus.
37239	 */
37240	constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) {
37241
37242		super();
37243
37244		this.type = 'TorusKnotGeometry';
37245
37246		/**
37247		 * Holds the constructor parameters that have been
37248		 * used to generate the geometry. Any modification
37249		 * after instantiation does not change the geometry.
37250		 *
37251		 * @type {Object}
37252		 */
37253		this.parameters = {
37254			radius: radius,
37255			tube: tube,
37256			tubularSegments: tubularSegments,
37257			radialSegments: radialSegments,
37258			p: p,
37259			q: q
37260		};
37261
37262		tubularSegments = Math.floor( tubularSegments );
37263		radialSegments = Math.floor( radialSegments );
37264
37265		// buffers
37266
37267		const indices = [];
37268		const vertices = [];
37269		const normals = [];
37270		const uvs = [];
37271
37272		// helper variables
37273
37274		const vertex = new Vector3();
37275		const normal = new Vector3();
37276
37277		const P1 = new Vector3();
37278		const P2 = new Vector3();
37279
37280		const B = new Vector3();
37281		const T = new Vector3();
37282		const N = new Vector3();
37283
37284		// generate vertices, normals and uvs
37285
37286		for ( let i = 0; i <= tubularSegments; ++ i ) {
37287
37288			// the radian "u" is used to calculate the position on the torus curve of the current tubular segment
37289
37290			const u = i / tubularSegments * p * Math.PI * 2;
37291
37292			// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
37293			// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
37294
37295			calculatePositionOnCurve( u, p, q, radius, P1 );
37296			calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
37297
37298			// calculate orthonormal basis
37299
37300			T.subVectors( P2, P1 );
37301			N.addVectors( P2, P1 );
37302			B.crossVectors( T, N );
37303			N.crossVectors( B, T );
37304
37305			// normalize B, N. T can be ignored, we don't use it
37306
37307			B.normalize();
37308			N.normalize();
37309
37310			for ( let j = 0; j <= radialSegments; ++ j ) {
37311
37312				// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
37313				// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
37314
37315				const v = j / radialSegments * Math.PI * 2;
37316				const cx = - tube * Math.cos( v );
37317				const cy = tube * Math.sin( v );
37318
37319				// now calculate the final vertex position.
37320				// first we orient the extrusion with our basis vectors, then we add it to the current position on the curve
37321
37322				vertex.x = P1.x + ( cx * N.x + cy * B.x );
37323				vertex.y = P1.y + ( cx * N.y + cy * B.y );
37324				vertex.z = P1.z + ( cx * N.z + cy * B.z );
37325
37326				vertices.push( vertex.x, vertex.y, vertex.z );
37327
37328				// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
37329
37330				normal.subVectors( vertex, P1 ).normalize();
37331
37332				normals.push( normal.x, normal.y, normal.z );
37333
37334				// uv
37335
37336				uvs.push( i / tubularSegments );
37337				uvs.push( j / radialSegments );
37338
37339			}
37340
37341		}
37342
37343		// generate indices
37344
37345		for ( let j = 1; j <= tubularSegments; j ++ ) {
37346
37347			for ( let i = 1; i <= radialSegments; i ++ ) {
37348
37349				// indices
37350
37351				const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
37352				const b = ( radialSegments + 1 ) * j + ( i - 1 );
37353				const c = ( radialSegments + 1 ) * j + i;
37354				const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
37355
37356				// faces
37357
37358				indices.push( a, b, d );
37359				indices.push( b, c, d );
37360
37361			}
37362
37363		}
37364
37365		// build geometry
37366
37367		this.setIndex( indices );
37368		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37369		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37370		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37371
37372		// this function calculates the current position on the torus curve
37373
37374		function calculatePositionOnCurve( u, p, q, radius, position ) {
37375
37376			const cu = Math.cos( u );
37377			const su = Math.sin( u );
37378			const quOverP = q / p * u;
37379			const cs = Math.cos( quOverP );
37380
37381			position.x = radius * ( 2 + cs ) * 0.5 * cu;
37382			position.y = radius * ( 2 + cs ) * su * 0.5;
37383			position.z = radius * Math.sin( quOverP ) * 0.5;
37384
37385		}
37386
37387	}
37388
37389	copy( source ) {
37390
37391		super.copy( source );
37392
37393		this.parameters = Object.assign( {}, source.parameters );
37394
37395		return this;
37396
37397	}
37398
37399	/**
37400	 * Factory method for creating an instance of this class from the given
37401	 * JSON object.
37402	 *
37403	 * @param {Object} data - A JSON object representing the serialized geometry.
37404	 * @return {TorusKnotGeometry} A new instance.
37405	 */
37406	static fromJSON( data ) {
37407
37408		return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q );
37409
37410	}
37411
37412}
37413
37414/**
37415 * Creates a tube that extrudes along a 3D curve.
37416 *
37417 * ```js
37418 * class CustomSinCurve extends THREE.Curve {
37419 *
37420 * 	getPoint( t, optionalTarget = new THREE.Vector3() ) {
37421 *
37422 * 		const tx = t * 3 - 1.5;
37423 * 		const ty = Math.sin( 2 * Math.PI * t );
37424 * 		const tz = 0;
37425 *
37426 * 		return optionalTarget.set( tx, ty, tz );
37427 * 	}
37428 *
37429 * }
37430 *
37431 * const path = new CustomSinCurve( 10 );
37432 * const geometry = new THREE.TubeGeometry( path, 20, 2, 8, false );
37433 * const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
37434 * const mesh = new THREE.Mesh( geometry, material );
37435 * scene.add( mesh );
37436 * ```
37437 *
37438 * @augments BufferGeometry
37439 * @demo scenes/geometry-browser.html#TubeGeometry
37440 */
37441class TubeGeometry extends BufferGeometry {
37442
37443	/**
37444	 * Constructs a new tube geometry.
37445	 *
37446	 * @param {Curve} [path=QuadraticBezierCurve3] - A 3D curve defining the path of the tube.
37447	 * @param {number} [tubularSegments=64] - The number of segments that make up the tube.
37448	 * @param {number} [radius=1] -The radius of the tube.
37449	 * @param {number} [radialSegments=8] - The number of segments that make up the cross-section.
37450	 * @param {boolean} [closed=false] - Whether the tube is closed or not.
37451	 */
37452	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 ) {
37453
37454		super();
37455
37456		this.type = 'TubeGeometry';
37457
37458		/**
37459		 * Holds the constructor parameters that have been
37460		 * used to generate the geometry. Any modification
37461		 * after instantiation does not change the geometry.
37462		 *
37463		 * @type {Object}
37464		 */
37465		this.parameters = {
37466			path: path,
37467			tubularSegments: tubularSegments,
37468			radius: radius,
37469			radialSegments: radialSegments,
37470			closed: closed
37471		};
37472
37473		const frames = path.computeFrenetFrames( tubularSegments, closed );
37474
37475		// expose internals
37476
37477		this.tangents = frames.tangents;
37478		this.normals = frames.normals;
37479		this.binormals = frames.binormals;
37480
37481		// helper variables
37482
37483		const vertex = new Vector3();
37484		const normal = new Vector3();
37485		const uv = new Vector2();
37486		let P = new Vector3();
37487
37488		// buffer
37489
37490		const vertices = [];
37491		const normals = [];
37492		const uvs = [];
37493		const indices = [];
37494
37495		// create buffer data
37496
37497		generateBufferData();
37498
37499		// build geometry
37500
37501		this.setIndex( indices );
37502		this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37503		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
37504		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
37505
37506		// functions
37507
37508		function generateBufferData() {
37509
37510			for ( let i = 0; i < tubularSegments; i ++ ) {
37511
37512				generateSegment( i );
37513
37514			}
37515
37516			// if the geometry is not closed, generate the last row of vertices and normals
37517			// at the regular position on the given path
37518			//
37519			// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
37520
37521			generateSegment( ( closed === false ) ? tubularSegments : 0 );
37522
37523			// uvs are generated in a separate function.
37524			// this makes it easy compute correct values for closed geometries
37525
37526			generateUVs();
37527
37528			// finally create faces
37529
37530			generateIndices();
37531
37532		}
37533
37534		function generateSegment( i ) {
37535
37536			// we use getPointAt to sample evenly distributed points from the given path
37537
37538			P = path.getPointAt( i / tubularSegments, P );
37539
37540			// retrieve corresponding normal and binormal
37541
37542			const N = frames.normals[ i ];
37543			const B = frames.binormals[ i ];
37544
37545			// generate normals and vertices for the current segment
37546
37547			for ( let j = 0; j <= radialSegments; j ++ ) {
37548
37549				const v = j / radialSegments * Math.PI * 2;
37550
37551				const sin = Math.sin( v );
37552				const cos = - Math.cos( v );
37553
37554				// normal
37555
37556				normal.x = ( cos * N.x + sin * B.x );
37557				normal.y = ( cos * N.y + sin * B.y );
37558				normal.z = ( cos * N.z + sin * B.z );
37559				normal.normalize();
37560
37561				normals.push( normal.x, normal.y, normal.z );
37562
37563				// vertex
37564
37565				vertex.x = P.x + radius * normal.x;
37566				vertex.y = P.y + radius * normal.y;
37567				vertex.z = P.z + radius * normal.z;
37568
37569				vertices.push( vertex.x, vertex.y, vertex.z );
37570
37571			}
37572
37573		}
37574
37575		function generateIndices() {
37576
37577			for ( let j = 1; j <= tubularSegments; j ++ ) {
37578
37579				for ( let i = 1; i <= radialSegments; i ++ ) {
37580
37581					const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
37582					const b = ( radialSegments + 1 ) * j + ( i - 1 );
37583					const c = ( radialSegments + 1 ) * j + i;
37584					const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
37585
37586					// faces
37587
37588					indices.push( a, b, d );
37589					indices.push( b, c, d );
37590
37591				}
37592
37593			}
37594
37595		}
37596
37597		function generateUVs() {
37598
37599			for ( let i = 0; i <= tubularSegments; i ++ ) {
37600
37601				for ( let j = 0; j <= radialSegments; j ++ ) {
37602
37603					uv.x = i / tubularSegments;
37604					uv.y = j / radialSegments;
37605
37606					uvs.push( uv.x, uv.y );
37607
37608				}
37609
37610			}
37611
37612		}
37613
37614	}
37615
37616	copy( source ) {
37617
37618		super.copy( source );
37619
37620		this.parameters = Object.assign( {}, source.parameters );
37621
37622		return this;
37623
37624	}
37625
37626	toJSON() {
37627
37628		const data = super.toJSON();
37629
37630		data.path = this.parameters.path.toJSON();
37631
37632		return data;
37633
37634	}
37635
37636	/**
37637	 * Factory method for creating an instance of this class from the given
37638	 * JSON object.
37639	 *
37640	 * @param {Object} data - A JSON object representing the serialized geometry.
37641	 * @return {TubeGeometry} A new instance.
37642	 */
37643	static fromJSON( data ) {
37644
37645		// This only works for built-in curves (e.g. CatmullRomCurve3).
37646		// User defined curves or instances of CurvePath will not be deserialized.
37647		return new TubeGeometry(
37648			new Curves[ data.path.type ]().fromJSON( data.path ),
37649			data.tubularSegments,
37650			data.radius,
37651			data.radialSegments,
37652			data.closed
37653		);
37654
37655	}
37656
37657}
37658
37659/**
37660 * Can be used as a helper object to visualize a geometry as a wireframe.
37661 *
37662 * ```js
37663 * const geometry = new THREE.SphereGeometry();
37664 *
37665 * const wireframe = new THREE.WireframeGeometry( geometry );
37666 *
37667 * const line = new THREE.LineSegments( wireframe );
37668 * line.material.depthWrite = false;
37669 * line.material.opacity = 0.25;
37670 * line.material.transparent = true;
37671 *
37672 * scene.add( line );
37673 * ```
37674 *
37675 * Note: It is not yet possible to serialize/deserialize instances of this class.
37676 *
37677 * @augments BufferGeometry
37678 */
37679class WireframeGeometry extends BufferGeometry {
37680
37681	/**
37682	 * Constructs a new wireframe geometry.
37683	 *
37684	 * @param {?BufferGeometry} [geometry=null] - The geometry.
37685	 */
37686	constructor( geometry = null ) {
37687
37688		super();
37689
37690		this.type = 'WireframeGeometry';
37691
37692		/**
37693		 * Holds the constructor parameters that have been
37694		 * used to generate the geometry. Any modification
37695		 * after instantiation does not change the geometry.
37696		 *
37697		 * @type {Object}
37698		 */
37699		this.parameters = {
37700			geometry: geometry
37701		};
37702
37703		if ( geometry !== null ) {
37704
37705			// buffer
37706
37707			const vertices = [];
37708			const edges = new Set();
37709
37710			// helper variables
37711
37712			const start = new Vector3();
37713			const end = new Vector3();
37714
37715			if ( geometry.index !== null ) {
37716
37717				// indexed BufferGeometry
37718
37719				const position = geometry.attributes.position;
37720				const indices = geometry.index;
37721				let groups = geometry.groups;
37722
37723				if ( groups.length === 0 ) {
37724
37725					groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
37726
37727				}
37728
37729				// create a data structure that contains all edges without duplicates
37730
37731				for ( let o = 0, ol = groups.length; o < ol; ++ o ) {
37732
37733					const group = groups[ o ];
37734
37735					const groupStart = group.start;
37736					const groupCount = group.count;
37737
37738					for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) {
37739
37740						for ( let j = 0; j < 3; j ++ ) {
37741
37742							const index1 = indices.getX( i + j );
37743							const index2 = indices.getX( i + ( j + 1 ) % 3 );
37744
37745							start.fromBufferAttribute( position, index1 );
37746							end.fromBufferAttribute( position, index2 );
37747
37748							if ( isUniqueEdge( start, end, edges ) === true ) {
37749
37750								vertices.push( start.x, start.y, start.z );
37751								vertices.push( end.x, end.y, end.z );
37752
37753							}
37754
37755						}
37756
37757					}
37758
37759				}
37760
37761			} else {
37762
37763				// non-indexed BufferGeometry
37764
37765				const position = geometry.attributes.position;
37766
37767				for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) {
37768
37769					for ( let j = 0; j < 3; j ++ ) {
37770
37771						// three edges per triangle, an edge is represented as (index1, index2)
37772						// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)
37773
37774						const index1 = 3 * i + j;
37775						const index2 = 3 * i + ( ( j + 1 ) % 3 );
37776
37777						start.fromBufferAttribute( position, index1 );
37778						end.fromBufferAttribute( position, index2 );
37779
37780						if ( isUniqueEdge( start, end, edges ) === true ) {
37781
37782							vertices.push( start.x, start.y, start.z );
37783							vertices.push( end.x, end.y, end.z );
37784
37785						}
37786
37787					}
37788
37789				}
37790
37791			}
37792
37793			// build geometry
37794
37795			this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
37796
37797		}
37798
37799	}
37800
37801	copy( source ) {
37802
37803		super.copy( source );
37804
37805		this.parameters = Object.assign( {}, source.parameters );
37806
37807		return this;
37808
37809	}
37810
37811}
37812
37813function isUniqueEdge( start, end, edges ) {
37814
37815	const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`;
37816	const hash2 = `${end.x},${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge
37817
37818	if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) {
37819
37820		return false;
37821
37822	} else {
37823
37824		edges.add( hash1 );
37825		edges.add( hash2 );
37826		return true;
37827
37828	}
37829
37830}
37831
37832var Geometries = /*#__PURE__*/Object.freeze({
37833	__proto__: null,
37834	BoxGeometry: BoxGeometry,
37835	CapsuleGeometry: CapsuleGeometry,
37836	CircleGeometry: CircleGeometry,
37837	ConeGeometry: ConeGeometry,
37838	CylinderGeometry: CylinderGeometry,
37839	DodecahedronGeometry: DodecahedronGeometry,
37840	EdgesGeometry: EdgesGeometry,
37841	ExtrudeGeometry: ExtrudeGeometry,
37842	IcosahedronGeometry: IcosahedronGeometry,
37843	LatheGeometry: LatheGeometry,
37844	OctahedronGeometry: OctahedronGeometry,
37845	PlaneGeometry: PlaneGeometry,
37846	PolyhedronGeometry: PolyhedronGeometry,
37847	RingGeometry: RingGeometry,
37848	ShapeGeometry: ShapeGeometry,
37849	SphereGeometry: SphereGeometry,
37850	TetrahedronGeometry: TetrahedronGeometry,
37851	TorusGeometry: TorusGeometry,
37852	TorusKnotGeometry: TorusKnotGeometry,
37853	TubeGeometry: TubeGeometry,
37854	WireframeGeometry: WireframeGeometry
37855});
37856
37857/**
37858 * This material can receive shadows, but otherwise is completely transparent.
37859 *
37860 * ```js
37861 * const geometry = new THREE.PlaneGeometry( 2000, 2000 );
37862 * geometry.rotateX( - Math.PI / 2 );
37863 *
37864 * const material = new THREE.ShadowMaterial();
37865 * material.opacity = 0.2;
37866 *
37867 * const plane = new THREE.Mesh( geometry, material );
37868 * plane.position.y = -200;
37869 * plane.receiveShadow = true;
37870 * scene.add( plane );
37871 * ```
37872 *
37873 * @augments Material
37874 */
37875class ShadowMaterial extends Material {
37876
37877	/**
37878	 * Constructs a new shadow material.
37879	 *
37880	 * @param {Object} [parameters] - An object with one or more properties
37881	 * defining the material's appearance. Any property of the material
37882	 * (including any property from inherited materials) can be passed
37883	 * in here. Color values can be passed any type of value accepted
37884	 * by {@link Color#set}.
37885	 */
37886	constructor( parameters ) {
37887
37888		super();
37889
37890		/**
37891		 * This flag can be used for type testing.
37892		 *
37893		 * @type {boolean}
37894		 * @readonly
37895		 * @default true
37896		 */
37897		this.isShadowMaterial = true;
37898
37899		this.type = 'ShadowMaterial';
37900
37901		/**
37902		 * Color of the material.
37903		 *
37904		 * @type {Color}
37905		 * @default (0,0,0)
37906		 */
37907		this.color = new Color( 0x000000 );
37908
37909		/**
37910		 * Overwritten since shadow materials are transparent
37911		 * by default.
37912		 *
37913		 * @type {boolean}
37914		 * @default true
37915		 */
37916		this.transparent = true;
37917
37918		/**
37919		 * Whether the material is affected by fog or not.
37920		 *
37921		 * @type {boolean}
37922		 * @default true
37923		 */
37924		this.fog = true;
37925
37926		this.setValues( parameters );
37927
37928	}
37929
37930	copy( source ) {
37931
37932		super.copy( source );
37933
37934		this.color.copy( source.color );
37935
37936		this.fog = source.fog;
37937
37938		return this;
37939
37940	}
37941
37942}
37943
37944/**
37945 * Provides utility functions for managing uniforms.
37946 *
37947 * @module UniformsUtils
37948 */
37949
37950/**
37951 * Clones the given uniform definitions by performing a deep-copy. That means
37952 * if the value of a uniform refers to an object like a Vector3 or Texture,
37953 * the cloned uniform will refer to a new object reference.
37954 *
37955 * @param {Object} src - An object representing uniform definitions.
37956 * @return {Object} The cloned uniforms.
37957 */
37958function cloneUniforms( src ) {
37959
37960	const dst = {};
37961
37962	for ( const u in src ) {
37963
37964		dst[ u ] = {};
37965
37966		for ( const p in src[ u ] ) {
37967
37968			const property = src[ u ][ p ];
37969
37970			if ( isThreeObject( property ) ) {
37971
37972				if ( property.isRenderTargetTexture ) {
37973
37974					warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' );
37975					dst[ u ][ p ] = null;
37976
37977				} else {
37978
37979					dst[ u ][ p ] = property.clone();
37980
37981				}
37982
37983			} else if ( Array.isArray( property ) ) {
37984
37985				if ( isThreeObject( property[ 0 ] ) ) {
37986
37987					const clonedProperty = [];
37988
37989					for ( let i = 0, l = property.length; i < l; i ++ ) {
37990
37991						clonedProperty[ i ] = property[ i ].clone();
37992
37993					}
37994
37995					dst[ u ][ p ] = clonedProperty;
37996
37997				} else {
37998
37999					dst[ u ][ p ] = property.slice();
38000
38001				}
38002
38003			} else {
38004
38005				dst[ u ][ p ] = property;
38006
38007			}
38008
38009		}
38010
38011	}
38012
38013	return dst;
38014
38015}
38016
38017/**
38018 * Merges the given uniform definitions into a single object. Since the
38019 * method internally uses cloneUniforms(), it performs a deep-copy when
38020 * producing the merged uniform definitions.
38021 *
38022 * @param {Array} uniforms - An array of objects containing uniform definitions.
38023 * @return {Object} The merged uniforms.
38024 */
38025function mergeUniforms( uniforms ) {
38026
38027	const merged = {};
38028
38029	for ( let u = 0; u < uniforms.length; u ++ ) {
38030
38031		const tmp = cloneUniforms( uniforms[ u ] );
38032
38033		for ( const p in tmp ) {
38034
38035			merged[ p ] = tmp[ p ];
38036
38037		}
38038
38039	}
38040
38041	return merged;
38042
38043}
38044
38045function isThreeObject( property ) {
38046
38047	return ( property && ( property.isColor ||
38048		property.isMatrix3 || property.isMatrix4 ||
38049		property.isVector2 || property.isVector3 || property.isVector4 ||
38050		property.isTexture || property.isQuaternion ) );
38051
38052}
38053
38054function cloneUniformsGroups( src ) {
38055
38056	const dst = [];
38057
38058	for ( let u = 0; u < src.length; u ++ ) {
38059
38060		dst.push( src[ u ].clone() );
38061
38062	}
38063
38064	return dst;
38065
38066}
38067
38068function getUnlitUniformColorSpace( renderer ) {
38069
38070	const currentRenderTarget = renderer.getRenderTarget();
38071
38072	if ( currentRenderTarget === null ) {
38073
38074		// https://github.com/mrdoob/three.js/pull/23937#issuecomment-1111067398
38075		return renderer.outputColorSpace;
38076
38077	}
38078
38079	// https://github.com/mrdoob/three.js/issues/27868
38080	if ( currentRenderTarget.isXRRenderTarget === true ) {
38081
38082		return currentRenderTarget.texture.colorSpace;
38083
38084	}
38085
38086	return ColorManagement.workingColorSpace;
38087
38088}
38089
38090// Legacy
38091
38092const UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };
38093
38094var default_vertex = "void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
38095
38096var default_fragment = "void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
38097
38098/**
38099 * A material rendered with custom shaders. A shader is a small program written in GLSL.
38100 * that runs on the GPU. You may want to use a custom shader if you need to implement an
38101 * effect not included with any of the built-in materials.
38102 *
38103 * There are the following notes to bear in mind when using a `ShaderMaterial`:
38104 *
38105 * - `ShaderMaterial` can only be used with {@link WebGLRenderer}.
38106 * - Built in attributes and uniforms are passed to the shaders along with your code. If
38107 * you don't want that, use {@link RawShaderMaterial} instead.
38108 * - You can use the directive `#pragma unroll_loop_start` and `#pragma unroll_loop_end`
38109 * in order to unroll a `for` loop in GLSL by the shader preprocessor. The directive has
38110 * to be placed right above the loop. The loop formatting has to correspond to a defined standard.
38111 *   - The loop has to be [normalized](https://en.wikipedia.org/wiki/Normalized_loop).
38112 *   - The loop variable has to be *i*.
38113 *   - The value `UNROLLED_LOOP_INDEX` will be replaced with the explicitly
38114 * value of *i* for the given iteration and can be used in preprocessor
38115 * statements.
38116 *
38117 * ```js
38118 * const material = new THREE.ShaderMaterial( {
38119 * 	uniforms: {
38120 * 		time: { value: 1.0 },
38121 * 		resolution: { value: new THREE.Vector2() }
38122 * 	},
38123 * 	vertexShader: document.getElementById( 'vertexShader' ).textContent,
38124 * 	fragmentShader: document.getElementById( 'fragmentShader' ).textContent
38125 * } );
38126 * ```
38127 *
38128 * @augments Material
38129 */
38130class ShaderMaterial extends Material {
38131
38132	/**
38133	 * Constructs a new shader material.
38134	 *
38135	 * @param {Object} [parameters] - An object with one or more properties
38136	 * defining the material's appearance. Any property of the material
38137	 * (including any property from inherited materials) can be passed
38138	 * in here. Color values can be passed any type of value accepted
38139	 * by {@link Color#set}.
38140	 */
38141	constructor( parameters ) {
38142
38143		super();
38144
38145		/**
38146		 * This flag can be used for type testing.
38147		 *
38148		 * @type {boolean}
38149		 * @readonly
38150		 * @default true
38151		 */
38152		this.isShaderMaterial = true;
38153
38154		this.type = 'ShaderMaterial';
38155
38156		/**
38157		 * Defines custom constants using `#define` directives within the GLSL code
38158		 * for both the vertex shader and the fragment shader; each key/value pair
38159		 * yields another directive.
38160		 * ```js
38161		 * defines: {
38162		 * 	FOO: 15,
38163		 * 	BAR: true
38164		 * }
38165		 * ```
38166		 * Yields the lines:
38167		 * ```
38168		 * #define FOO 15
38169		 * #define BAR true
38170		 * ```
38171		 *
38172		 * @type {Object}
38173		 */
38174		this.defines = {};
38175
38176		/**
38177		 * An object of the form:
38178		 * ```js
38179		 * {
38180		 * 	"uniform1": { value: 1.0 },
38181		 * 	"uniform2": { value: 2 }
38182		 * }
38183		 * ```
38184		 * specifying the uniforms to be passed to the shader code; keys are uniform
38185		 * names, values are definitions of the form
38186		 * ```
38187		 * {
38188		 * 	value: 1.0
38189		 * }
38190		 * ```
38191		 * where `value` is the value of the uniform. Names must match the name of
38192		 * the uniform, as defined in the GLSL code. Note that uniforms are refreshed
38193		 * on every frame, so updating the value of the uniform will immediately
38194		 * update the value available to the GLSL code.
38195		 *
38196		 * @type {Object}
38197		 */
38198		this.uniforms = {};
38199
38200		/**
38201		 * An array holding uniforms groups for configuring UBOs.
38202		 *
38203		 * @type {Array<UniformsGroup>}
38204		 */
38205		this.uniformsGroups = [];
38206
38207		/**
38208		 * Vertex shader GLSL code. This is the actual code for the shader.
38209		 *
38210		 * @type {string}
38211		 */
38212		this.vertexShader = default_vertex;
38213
38214		/**
38215		 * Fragment shader GLSL code. This is the actual code for the shader.
38216		 *
38217		 * @type {string}
38218		 */
38219		this.fragmentShader = default_fragment;
38220
38221		/**
38222		 * Controls line thickness or lines.
38223		 *
38224		 * WebGL and WebGPU ignore this setting and always render line primitives with a
38225		 * width of one pixel.
38226		 *
38227		 * @type {number}
38228		 * @default 1
38229		 */
38230		this.linewidth = 1;
38231
38232		/**
38233		 * Renders the geometry as a wireframe.
38234		 *
38235		 * @type {boolean}
38236		 * @default false
38237		 */
38238		this.wireframe = false;
38239
38240		/**
38241		 * Controls the thickness of the wireframe.
38242		 *
38243		 * WebGL and WebGPU ignore this property and always render
38244		 * 1 pixel wide lines.
38245		 *
38246		 * @type {number}
38247		 * @default 1
38248		 */
38249		this.wireframeLinewidth = 1;
38250
38251		/**
38252		 * Defines whether the material color is affected by global fog settings; `true`
38253		 * to pass fog uniforms to the shader.
38254		 *
38255		 * Setting this property to `true` requires the definition of fog uniforms. It is
38256		 * recommended to use `UniformsUtils.merge()` to combine the custom shader uniforms
38257		 * with predefined fog uniforms.
38258		 *
38259		 * ```js
38260		 * const material = new ShaderMaterial( {
38261		 *     uniforms: UniformsUtils.merge( [ UniformsLib[ 'fog' ], shaderUniforms ] );
38262		 *     vertexShader: vertexShader,
38263		 *     fragmentShader: fragmentShader,
38264		 *     fog: true
38265		 * } );
38266		 * ```
38267		 *
38268		 * @type {boolean}
38269		 * @default false
38270		 */
38271		this.fog = false;
38272
38273		/**
38274		 * Defines whether this material uses lighting; `true` to pass uniform data
38275		 * related to lighting to this shader.
38276		 *
38277		 * @type {boolean}
38278		 * @default false
38279		 */
38280		this.lights = false;
38281
38282		/**
38283		 * Defines whether this material supports clipping; `true` to let the renderer
38284		 * pass the clippingPlanes uniform.
38285		 *
38286		 * @type {boolean}
38287		 * @default false
38288		 */
38289		this.clipping = false;
38290
38291		/**
38292		 * Overwritten and set to `true` by default.
38293		 *
38294		 * @type {boolean}
38295		 * @default true
38296		 */
38297		this.forceSinglePass = true;
38298
38299		/**
38300		 * This object allows to enable certain WebGL 2 extensions.
38301		 *
38302		 * - clipCullDistance: set to `true` to use vertex shader clipping
38303		 * - multiDraw: set to `true` to use vertex shader multi_draw / enable gl_DrawID
38304		 *
38305		 * @type {{clipCullDistance:false,multiDraw:false}}
38306		 */
38307		this.extensions = {
38308			clipCullDistance: false, // set to use vertex shader clipping
38309			multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID
38310		};
38311
38312		/**
38313		 * When the rendered geometry doesn't include these attributes but the
38314		 * material does, these default values will be passed to the shaders. This
38315		 * avoids errors when buffer data is missing.
38316		 *
38317		 * - color: [ 1, 1, 1 ]
38318		 * - uv: [ 0, 0 ]
38319		 * - uv1: [ 0, 0 ]
38320		 *
38321		 * @type {Object}
38322		 */
38323		this.defaultAttributeValues = {
38324			'color': [ 1, 1, 1 ],
38325			'uv': [ 0, 0 ],
38326			'uv1': [ 0, 0 ]
38327		};
38328
38329		/**
38330		 * If set, this calls [gl.bindAttribLocation](https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindAttribLocation)
38331		 * to bind a generic vertex index to an attribute variable.
38332		 *
38333		 * @type {string|undefined}
38334		 * @default undefined
38335		 */
38336		this.index0AttributeName = undefined;
38337
38338		/**
38339		 * Can be used to force a uniform update while changing uniforms in
38340		 * {@link Object3D#onBeforeRender}.
38341		 *
38342		 * @type {boolean}
38343		 * @default false
38344		 */
38345		this.uniformsNeedUpdate = false;
38346
38347		/**
38348		 * Defines the GLSL version of custom shader code.
38349		 *
38350		 * @type {?(GLSL1|GLSL3)}
38351		 * @default null
38352		 */
38353		this.glslVersion = null;
38354
38355		if ( parameters !== undefined ) {
38356
38357			this.setValues( parameters );
38358
38359		}
38360
38361	}
38362
38363	copy( source ) {
38364
38365		super.copy( source );
38366
38367		this.fragmentShader = source.fragmentShader;
38368		this.vertexShader = source.vertexShader;
38369
38370		this.uniforms = cloneUniforms( source.uniforms );
38371		this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups );
38372
38373		this.defines = Object.assign( {}, source.defines );
38374
38375		this.wireframe = source.wireframe;
38376		this.wireframeLinewidth = source.wireframeLinewidth;
38377
38378		this.fog = source.fog;
38379		this.lights = source.lights;
38380		this.clipping = source.clipping;
38381
38382		this.extensions = Object.assign( {}, source.extensions );
38383
38384		this.glslVersion = source.glslVersion;
38385
38386		this.defaultAttributeValues = Object.assign( {}, source.defaultAttributeValues );
38387
38388		this.index0AttributeName = source.index0AttributeName;
38389
38390		this.uniformsNeedUpdate = source.uniformsNeedUpdate;
38391
38392		return this;
38393
38394	}
38395
38396	toJSON( meta ) {
38397
38398		const data = super.toJSON( meta );
38399
38400		data.glslVersion = this.glslVersion;
38401		data.uniforms = {};
38402
38403		for ( const name in this.uniforms ) {
38404
38405			const uniform = this.uniforms[ name ];
38406			const value = uniform.value;
38407
38408			if ( value && value.isTexture ) {
38409
38410				data.uniforms[ name ] = {
38411					type: 't',
38412					value: value.toJSON( meta ).uuid
38413				};
38414
38415			} else if ( value && value.isColor ) {
38416
38417				data.uniforms[ name ] = {
38418					type: 'c',
38419					value: value.getHex()
38420				};
38421
38422			} else if ( value && value.isVector2 ) {
38423
38424				data.uniforms[ name ] = {
38425					type: 'v2',
38426					value: value.toArray()
38427				};
38428
38429			} else if ( value && value.isVector3 ) {
38430
38431				data.uniforms[ name ] = {
38432					type: 'v3',
38433					value: value.toArray()
38434				};
38435
38436			} else if ( value && value.isVector4 ) {
38437
38438				data.uniforms[ name ] = {
38439					type: 'v4',
38440					value: value.toArray()
38441				};
38442
38443			} else if ( value && value.isMatrix3 ) {
38444
38445				data.uniforms[ name ] = {
38446					type: 'm3',
38447					value: value.toArray()
38448				};
38449
38450			} else if ( value && value.isMatrix4 ) {
38451
38452				data.uniforms[ name ] = {
38453					type: 'm4',
38454					value: value.toArray()
38455				};
38456
38457			} else {
38458
38459				data.uniforms[ name ] = {
38460					value: value
38461				};
38462
38463				// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far
38464
38465			}
38466
38467		}
38468
38469		if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;
38470
38471		data.vertexShader = this.vertexShader;
38472		data.fragmentShader = this.fragmentShader;
38473
38474		data.lights = this.lights;
38475		data.clipping = this.clipping;
38476
38477		const extensions = {};
38478
38479		for ( const key in this.extensions ) {
38480
38481			if ( this.extensions[ key ] === true ) extensions[ key ] = true;
38482
38483		}
38484
38485		if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
38486
38487		return data;
38488
38489	}
38490
38491	/**
38492	 * Deserializes the material from the given JSON.
38493	 *
38494	 * @param {Object} json - The JSON holding the serialized material.
38495	 * @param {Object<string,Texture>} textures - A dictionary holding textures referenced by the material.
38496	 * @return {ShaderMaterial} A reference to this material.
38497	 */
38498	fromJSON( json, textures ) {
38499
38500		super.fromJSON( json, textures );
38501
38502		if ( json.uniforms !== undefined ) {
38503
38504			for ( const name in json.uniforms ) {
38505
38506				const uniform = json.uniforms[ name ];
38507
38508				this.uniforms[ name ] = {};
38509
38510				switch ( uniform.type ) {
38511
38512					case 't':
38513						this.uniforms[ name ].value = textures[ uniform.value ] || null;
38514						break;
38515
38516					case 'c':
38517						this.uniforms[ name ].value = new Color().setHex( uniform.value );
38518						break;
38519
38520					case 'v2':
38521						this.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
38522						break;
38523
38524					case 'v3':
38525						this.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
38526						break;
38527
38528					case 'v4':
38529						this.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
38530						break;
38531
38532					case 'm3':
38533						this.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
38534						break;
38535
38536					case 'm4':
38537						this.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
38538						break;
38539
38540					default:
38541						this.uniforms[ name ].value = uniform.value;
38542
38543				}
38544
38545			}
38546
38547		}
38548
38549		if ( json.defines !== undefined ) this.defines = json.defines;
38550		if ( json.vertexShader !== undefined ) this.vertexShader = json.vertexShader;
38551		if ( json.fragmentShader !== undefined ) this.fragmentShader = json.fragmentShader;
38552		if ( json.glslVersion !== undefined ) this.glslVersion = json.glslVersion;
38553
38554		if ( json.extensions !== undefined ) {
38555
38556			for ( const key in json.extensions ) {
38557
38558				this.extensions[ key ] = json.extensions[ key ];
38559
38560			}
38561
38562		}
38563
38564		if ( json.lights !== undefined ) this.lights = json.lights;
38565		if ( json.clipping !== undefined ) this.clipping = json.clipping;
38566
38567		return this;
38568
38569	}
38570
38571}
38572
38573/**
38574 * This class works just like {@link ShaderMaterial}, except that definitions
38575 * of built-in uniforms and attributes are not automatically prepended to the
38576 * GLSL shader code.
38577 *
38578 * `RawShaderMaterial` can only be used with {@link WebGLRenderer}.
38579 *
38580 * @augments ShaderMaterial
38581 */
38582class RawShaderMaterial extends ShaderMaterial {
38583
38584	/**
38585	 * Constructs a new raw shader material.
38586	 *
38587	 * @param {Object} [parameters] - An object with one or more properties
38588	 * defining the material's appearance. Any property of the material
38589	 * (including any property from inherited materials) can be passed
38590	 * in here. Color values can be passed any type of value accepted
38591	 * by {@link Color#set}.
38592	 */
38593	constructor( parameters ) {
38594
38595		super( parameters );
38596
38597		/**
38598		 * This flag can be used for type testing.
38599		 *
38600		 * @type {boolean}
38601		 * @readonly
38602		 * @default true
38603		 */
38604		this.isRawShaderMaterial = true;
38605
38606		this.type = 'RawShaderMaterial';
38607
38608	}
38609
38610}
38611
38612/**
38613 * A standard physically based material, using Metallic-Roughness workflow.
38614 *
38615 * Physically based rendering (PBR) has recently become the standard in many
38616 * 3D applications, such as [Unity](https://blogs.unity3d.com/2014/10/29/physically-based-shading-in-unity-5-a-primer/),
38617 * [Unreal](https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/PhysicallyBased/) and
38618 * [3D Studio Max](http://area.autodesk.com/blogs/the-3ds-max-blog/what039s-new-for-rendering-in-3ds-max-2017).
38619 *
38620 * This approach differs from older approaches in that instead of using
38621 * approximations for the way in which light interacts with a surface, a
38622 * physically correct model is used. The idea is that, instead of tweaking
38623 * materials to look good under specific lighting, a material can be created
38624 * that will react 'correctly' under all lighting scenarios.
38625 *
38626 * In practice this gives a more accurate and realistic looking result than
38627 * the {@link MeshLambertMaterial} or {@link MeshPhongMaterial}, at the cost of
38628 * being somewhat more computationally expensive. `MeshStandardMaterial` uses per-fragment
38629 * shading.
38630 *
38631 * Note that for best results you should always specify an environment map when using this material.
38632 *
38633 * For a non-technical introduction to the concept of PBR and how to set up a
38634 * PBR material, check out these articles by the people at [marmoset](https://www.marmoset.co):
38635 *
38636 * - [Basic Theory of Physically Based Rendering](https://www.marmoset.co/posts/basic-theory-of-physically-based-rendering/)
38637 * - [Physically Based Rendering and You Can Too](https://www.marmoset.co/posts/physically-based-rendering-and-you-can-too/)
38638 *
38639 * Technical details of the approach used in three.js (and most other PBR systems) can be found is this
38640 * [paper from Disney](https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf)
38641 * (pdf), by Brent Burley.
38642 *
38643 * @augments Material
38644 * @demo scenes/material-browser.html#MeshStandardMaterial
38645 */
38646class MeshStandardMaterial extends Material {
38647
38648	/**
38649	 * Constructs a new mesh standard material.
38650	 *
38651	 * @param {Object} [parameters] - An object with one or more properties
38652	 * defining the material's appearance. Any property of the material
38653	 * (including any property from inherited materials) can be passed
38654	 * in here. Color values can be passed any type of value accepted
38655	 * by {@link Color#set}.
38656	 */
38657	constructor( parameters ) {
38658
38659		super();
38660
38661		/**
38662		 * This flag can be used for type testing.
38663		 *
38664		 * @type {boolean}
38665		 * @readonly
38666		 * @default true
38667		 */
38668		this.isMeshStandardMaterial = true;
38669
38670		this.type = 'MeshStandardMaterial';
38671
38672		this.defines = { 'STANDARD': '' };
38673
38674		/**
38675		 * Color of the material.
38676		 *
38677		 * @type {Color}
38678		 * @default (1,1,1)
38679		 */
38680		this.color = new Color( 0xffffff ); // diffuse
38681
38682		/**
38683		 * How rough the material appears. `0.0` means a smooth mirror reflection, `1.0`
38684		 * means fully diffuse. If `roughnessMap` is also provided,
38685		 * both values are multiplied.
38686		 *
38687		 * @type {number}
38688		 * @default 1
38689		 */
38690		this.roughness = 1.0;
38691
38692		/**
38693		 * How much the material is like a metal. Non-metallic materials such as wood
38694		 * or stone use `0.0`, metallic use `1.0`, with nothing (usually) in between.
38695		 * A value between `0.0` and `1.0` could be used for a rusty metal look.
38696		 * If `metalnessMap` is also provided, both values are multiplied.
38697		 *
38698		 * @type {number}
38699		 * @default 0
38700		 */
38701		this.metalness = 0.0;
38702
38703		/**
38704		 * The color map. May optionally include an alpha channel, typically combined
38705		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
38706		 * color is modulated by the diffuse `color`.
38707		 *
38708		 * `map` represents color data, and the texture must be assigned a
38709		 * {@link Texture#colorSpace}. Most `map` textures set
38710		 * `texture.colorSpace = SRGBColorSpace`.
38711		 *
38712		 * @type {?Texture}
38713		 * @default null
38714		 */
38715		this.map = null;
38716
38717		/**
38718		 * The light map. Requires a second set of UVs.
38719		 *
38720		 * `lightMap` represents pre-baked illuminance data, and the texture must be assigned
38721		 * a {@link Texture#colorSpace}. Most `lightMap` textures set
38722		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
38723		 * such as `.exr` or `.hdr`.
38724		 *
38725		 * @type {?Texture}
38726		 * @default null
38727		 */
38728		this.lightMap = null;
38729
38730		/**
38731		 * Intensity of the baked light.
38732		 *
38733		 * @type {number}
38734		 * @default 1
38735		 */
38736		this.lightMapIntensity = 1.0;
38737
38738		/**
38739		 * The red channel of this texture is used as the ambient occlusion map.
38740		 * Requires a second set of UVs.
38741		 *
38742		 * `aoMap` represents non-color data. Any texture assigned must have
38743		 * `texture.colorSpace = NoColorSpace` (default).
38744		 *
38745		 * @type {?Texture}
38746		 * @default null
38747		 */
38748		this.aoMap = null;
38749
38750		/**
38751		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
38752		 * disables ambient occlusion. Where intensity is `1` and the AO map's
38753		 * red channel is also `1`, ambient light is fully occluded on a surface.
38754		 *
38755		 * @type {number}
38756		 * @default 1
38757		 */
38758		this.aoMapIntensity = 1.0;
38759
38760		/**
38761		 * Emissive (light) color of the material, essentially a solid color
38762		 * unaffected by other lighting.
38763		 *
38764		 * @type {Color}
38765		 * @default (0,0,0)
38766		 */
38767		this.emissive = new Color( 0x000000 );
38768
38769		/**
38770		 * Intensity of the emissive light. Modulates the emissive color.
38771		 *
38772		 * @type {number}
38773		 * @default 1
38774		 */
38775		this.emissiveIntensity = 1.0;
38776
38777		/**
38778		 * Set emissive (glow) map. The emissive map color is modulated by the
38779		 * emissive color and the emissive intensity. If you have an emissive map,
38780		 * be sure to set the emissive color to something other than black.
38781		 *
38782		 * `emissiveMap` represents color data, and the texture must be assigned a
38783		 * {@link Texture#colorSpace}. Most `emissiveMap` textures set
38784		 * `texture.colorSpace = SRGBColorSpace`.
38785		 *
38786		 * @type {?Texture}
38787		 * @default null
38788		 */
38789		this.emissiveMap = null;
38790
38791		/**
38792		 * The texture to create a bump map. The black and white values map to the
38793		 * perceived depth in relation to the lights. Bump doesn't actually affect
38794		 * the geometry of the object, only the lighting. If a normal map is defined
38795		 * this will be ignored.
38796		 *
38797		 * `bumpMap` represents non-color data. Any texture assigned must have
38798		 * `texture.colorSpace = NoColorSpace` (default).
38799		 *
38800		 * @type {?Texture}
38801		 * @default null
38802		 */
38803		this.bumpMap = null;
38804
38805		/**
38806		 * How much the bump map affects the material. Typical range is `[0,1]`.
38807		 *
38808		 * @type {number}
38809		 * @default 1
38810		 */
38811		this.bumpScale = 1;
38812
38813		/**
38814		 * The texture to create a normal map. The RGB values affect the surface
38815		 * normal for each pixel fragment and change the way the color is lit. Normal
38816		 * maps do not change the actual shape of the surface, only the lighting. In
38817		 * case the material has a normal map authored using the left handed
38818		 * convention, the `y` component of `normalScale` should be negated to compensate
38819		 * for the different handedness.
38820		 *
38821		 * `normalMap` represents non-color data. Any texture assigned must have
38822		 * `texture.colorSpace = NoColorSpace` (default).
38823		 *
38824		 * @type {?Texture}
38825		 * @default null
38826		 */
38827		this.normalMap = null;
38828
38829		/**
38830		 * The type of normal map.
38831		 *
38832		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
38833		 * @default TangentSpaceNormalMap
38834		 */
38835		this.normalMapType = TangentSpaceNormalMap;
38836
38837		/**
38838		 * How much the normal map affects the material. Typical value range is `[0,1]`.
38839		 *
38840		 * @type {Vector2}
38841		 * @default (1,1)
38842		 */
38843		this.normalScale = new Vector2( 1, 1 );
38844
38845		/**
38846		 * The displacement map affects the position of the mesh's vertices. Unlike
38847		 * other maps which only affect the light and shade of the material the
38848		 * displaced vertices can cast shadows, block other objects, and otherwise
38849		 * act as real geometry. The displacement texture is an image where the value
38850		 * of each pixel (white being the highest) is mapped against, and
38851		 * repositions, the vertices of the mesh. For best results, pair a
38852		 * displacement map with a matching normal map, since the renderer can
38853		 * not recompute surface normals from the displaced vertices.
38854		 *
38855		 * `displacementMap` represents non-color data. Any texture assigned must have
38856		 * `texture.colorSpace = NoColorSpace` (default).
38857		 *
38858		 * @type {?Texture}
38859		 * @default null
38860		 */
38861		this.displacementMap = null;
38862
38863		/**
38864		 * How much the displacement map affects the mesh (where black is no
38865		 * displacement, and white is maximum displacement). Without a displacement
38866		 * map set, this value is not applied.
38867		 *
38868		 * @type {number}
38869		 * @default 0
38870		 */
38871		this.displacementScale = 1;
38872
38873		/**
38874		 * The offset of the displacement map's values on the mesh's vertices.
38875		 * The bias is added to the scaled sample of the displacement map.
38876		 * Without a displacement map set, this value is not applied.
38877		 *
38878		 * @type {number}
38879		 * @default 0
38880		 */
38881		this.displacementBias = 0;
38882
38883		/**
38884		 * The green channel of this texture is used to alter the roughness of the
38885		 * material.
38886		 *
38887		 * `roughnessMap` represents non-color data. Any texture assigned must have
38888		 * `texture.colorSpace = NoColorSpace` (default).
38889		 *
38890		 * @type {?Texture}
38891		 * @default null
38892		 */
38893		this.roughnessMap = null;
38894
38895		/**
38896		 * The blue channel of this texture is used to alter the metalness of the
38897		 * material.
38898		 *
38899		 * `metalnessMap` represents non-color data. Any texture assigned must have
38900		 * `texture.colorSpace = NoColorSpace` (default).
38901		 *
38902		 * @type {?Texture}
38903		 * @default null
38904		 */
38905		this.metalnessMap = null;
38906
38907		/**
38908		 * The alpha map is a grayscale texture that controls the opacity across the
38909		 * surface (black: fully transparent; white: fully opaque).
38910		 *
38911		 * Only the color of the texture is used, ignoring the alpha channel if one
38912		 * exists. For RGB and RGBA textures, the renderer will use the green channel
38913		 * when sampling this texture due to the extra bit of precision provided for
38914		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
38915		 * luminance/alpha textures will also still work as expected.
38916		 *
38917		 * `alphaMap` represents non-color data. Any texture assigned must have
38918		 * `texture.colorSpace = NoColorSpace` (default).
38919		 *
38920		 * @type {?Texture}
38921		 * @default null
38922		 */
38923		this.alphaMap = null;
38924
38925		/**
38926		 * The environment map. To ensure a physically correct rendering, environment maps
38927		 * are internally pre-processed with {@link PMREMGenerator}.
38928		 *
38929		 * `envMap` represents luminance data, and the texture must be assigned
38930		 * a {@link Texture#colorSpace}. Most `envMap` textures set
38931		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
38932		 * such as `.exr` or `.hdr`.
38933		 *
38934		 * @type {?Texture}
38935		 * @default null
38936		 */
38937		this.envMap = null;
38938
38939		/**
38940		 * The rotation of the environment map in radians.
38941		 *
38942		 * @type {Euler}
38943		 * @default (0,0,0)
38944		 */
38945		this.envMapRotation = new Euler();
38946
38947		/**
38948		 * Scales the effect of the environment map by multiplying its color.
38949		 *
38950		 * @type {number}
38951		 * @default 1
38952		 */
38953		this.envMapIntensity = 1.0;
38954
38955		/**
38956		 * Renders the geometry as a wireframe.
38957		 *
38958		 * @type {boolean}
38959		 * @default false
38960		 */
38961		this.wireframe = false;
38962
38963		/**
38964		 * Controls the thickness of the wireframe.
38965		 *
38966		 * Can only be used with {@link SVGRenderer}.
38967		 *
38968		 * @type {number}
38969		 * @default 1
38970		 */
38971		this.wireframeLinewidth = 1;
38972
38973		/**
38974		 * Defines appearance of wireframe ends.
38975		 *
38976		 * Can only be used with {@link SVGRenderer}.
38977		 *
38978		 * @type {('round'|'bevel'|'miter')}
38979		 * @default 'round'
38980		 */
38981		this.wireframeLinecap = 'round';
38982
38983		/**
38984		 * Defines appearance of wireframe joints.
38985		 *
38986		 * Can only be used with {@link SVGRenderer}.
38987		 *
38988		 * @type {('round'|'bevel'|'miter')}
38989		 * @default 'round'
38990		 */
38991		this.wireframeLinejoin = 'round';
38992
38993		/**
38994		 * Whether the material is rendered with flat shading or not.
38995		 *
38996		 * @type {boolean}
38997		 * @default false
38998		 */
38999		this.flatShading = false;
39000
39001		/**
39002		 * Whether the material is affected by fog or not.
39003		 *
39004		 * @type {boolean}
39005		 * @default true
39006		 */
39007		this.fog = true;
39008
39009		this.setValues( parameters );
39010
39011	}
39012
39013	copy( source ) {
39014
39015		super.copy( source );
39016
39017		this.defines = { 'STANDARD': '' };
39018
39019		this.color.copy( source.color );
39020		this.roughness = source.roughness;
39021		this.metalness = source.metalness;
39022
39023		this.map = source.map;
39024
39025		this.lightMap = source.lightMap;
39026		this.lightMapIntensity = source.lightMapIntensity;
39027
39028		this.aoMap = source.aoMap;
39029		this.aoMapIntensity = source.aoMapIntensity;
39030
39031		this.emissive.copy( source.emissive );
39032		this.emissiveMap = source.emissiveMap;
39033		this.emissiveIntensity = source.emissiveIntensity;
39034
39035		this.bumpMap = source.bumpMap;
39036		this.bumpScale = source.bumpScale;
39037
39038		this.normalMap = source.normalMap;
39039		this.normalMapType = source.normalMapType;
39040		this.normalScale.copy( source.normalScale );
39041
39042		this.displacementMap = source.displacementMap;
39043		this.displacementScale = source.displacementScale;
39044		this.displacementBias = source.displacementBias;
39045
39046		this.roughnessMap = source.roughnessMap;
39047
39048		this.metalnessMap = source.metalnessMap;
39049
39050		this.alphaMap = source.alphaMap;
39051
39052		this.envMap = source.envMap;
39053		this.envMapRotation.copy( source.envMapRotation );
39054		this.envMapIntensity = source.envMapIntensity;
39055
39056		this.wireframe = source.wireframe;
39057		this.wireframeLinewidth = source.wireframeLinewidth;
39058		this.wireframeLinecap = source.wireframeLinecap;
39059		this.wireframeLinejoin = source.wireframeLinejoin;
39060
39061		this.flatShading = source.flatShading;
39062
39063		this.fog = source.fog;
39064
39065		return this;
39066
39067	}
39068
39069}
39070
39071/**
39072 * An extension of the {@link MeshStandardMaterial}, providing more advanced
39073 * physically-based rendering properties:
39074 *
39075 * - Anisotropy: Ability to represent the anisotropic property of materials
39076 * as observable with brushed metals.
39077 * - Clearcoat: Some materials — like car paints, carbon fiber, and wet surfaces — require
39078 * a clear, reflective layer on top of another layer that may be irregular or rough.
39079 * Clearcoat approximates this effect, without the need for a separate transparent surface.
39080 * - Iridescence: Allows to render the effect where hue varies  depending on the viewing
39081 * angle and illumination angle. This can be seen on soap bubbles, oil films, or on the
39082 * wings of many insects.
39083 * - Physically-based transparency: One limitation of {@link Material#opacity} is that highly
39084 * transparent materials are less reflective. Physically-based transmission provides a more
39085 * realistic option for thin, transparent surfaces like glass.
39086 * - Advanced reflectivity: More flexible reflectivity for non-metallic materials.
39087 * - Retroreflection: Redirects specular light back toward the light source for
39088 * safety materials like road markings and reflective tape.
39089 * - Sheen: Can be used for representing cloth and fabric materials.
39090 *
39091 * As a result of these complex shading features, `MeshPhysicalMaterial` has a
39092 * higher performance cost, per pixel, than other three.js materials. Most
39093 * effects are disabled by default, and add cost as they are enabled. For
39094 * best results, always specify an environment map when using this material.
39095 *
39096 * @augments MeshStandardMaterial
39097 * @demo scenes/material-browser.html#MeshPhysicalMaterial
39098 */
39099class MeshPhysicalMaterial extends MeshStandardMaterial {
39100
39101	/**
39102	 * Constructs a new mesh physical material.
39103	 *
39104	 * @param {Object} [parameters] - An object with one or more properties
39105	 * defining the material's appearance. Any property of the material
39106	 * (including any property from inherited materials) can be passed
39107	 * in here. Color values can be passed any type of value accepted
39108	 * by {@link Color#set}.
39109	 */
39110	constructor( parameters ) {
39111
39112		super();
39113
39114		/**
39115		 * This flag can be used for type testing.
39116		 *
39117		 * @type {boolean}
39118		 * @readonly
39119		 * @default true
39120		 */
39121		this.isMeshPhysicalMaterial = true;
39122
39123		this.defines = {
39124
39125			'STANDARD': '',
39126			'PHYSICAL': ''
39127
39128		};
39129
39130		this.type = 'MeshPhysicalMaterial';
39131
39132		/**
39133		 * The rotation of the anisotropy in tangent, bitangent space, measured in radians
39134		 * counter-clockwise from the tangent. When `anisotropyMap` is present, this
39135		 * property provides additional rotation to the vectors in the texture.
39136		 *
39137		 * @type {number}
39138		 * @default 1
39139		 */
39140		this.anisotropyRotation = 0;
39141
39142		/**
39143		 * Red and green channels represent the anisotropy direction in `[-1, 1]` tangent,
39144		 * bitangent space, to be rotated by `anisotropyRotation`. The blue channel
39145		 * contains strength as `[0, 1]` to be multiplied by `anisotropy`.
39146		 *
39147		 * `anisotropyMap` represents non-color data. Any texture assigned must have
39148		 * `texture.colorSpace = NoColorSpace` (default).
39149		 *
39150		 * @type {?Texture}
39151		 * @default null
39152		 */
39153		this.anisotropyMap = null;
39154
39155		/**
39156		 * The red channel of this texture is multiplied against `clearcoat`,
39157		 * for per-pixel control over a coating's intensity.
39158		 *
39159		 * `clearcoatMap` represents non-color data. Any texture assigned must have
39160		 * `texture.colorSpace = NoColorSpace` (default).
39161		 *
39162		 * @type {?Texture}
39163		 * @default null
39164		 */
39165		this.clearcoatMap = null;
39166
39167		/**
39168		 * Roughness of the clear coat layer, from `0.0` to `1.0`.
39169		 *
39170		 * @type {number}
39171		 * @default 0
39172		 */
39173		this.clearcoatRoughness = 0.0;
39174
39175		/**
39176		 * The green channel of this texture is multiplied against
39177		 * `clearcoatRoughness`, for per-pixel control over a coating's roughness.
39178		 *
39179		 * `clearcoatRoughnessMap` represents non-color data. Any texture assigned must have
39180		 * `texture.colorSpace = NoColorSpace` (default).
39181		 *
39182		 * @type {?Texture}
39183		 * @default null
39184		 */
39185		this.clearcoatRoughnessMap = null;
39186
39187		/**
39188		 * How much `clearcoatNormalMap` affects the clear coat layer, from
39189		 * `(0,0)` to `(1,1)`.
39190		 *
39191		 * @type {Vector2}
39192		 * @default (1,1)
39193		 */
39194		this.clearcoatNormalScale = new Vector2( 1, 1 );
39195
39196		/**
39197		 * Can be used to enable independent normals for the clear coat layer.
39198		 *
39199		 * `clearcoatNormalMap` represents non-color data. Any texture assigned must have
39200		 * `texture.colorSpace = NoColorSpace` (default).
39201		 *
39202		 * @type {?Texture}
39203		 * @default null
39204		 */
39205		this.clearcoatNormalMap = null;
39206
39207		/**
39208		 * Index-of-refraction for non-metallic materials, from `1.0` to `2.333`.
39209		 *
39210		 * @type {number}
39211		 * @default 1.5
39212		 */
39213		this.ior = 1.5;
39214
39215		/**
39216		 * Degree of reflectivity, from `0.0` to `1.0`. Default is `0.5`, which
39217		 * corresponds to an index-of-refraction of `1.5`.
39218		 *
39219		 * This models the reflectivity of non-metallic materials. It has no effect
39220		 * when `metalness` is `1.0`
39221		 *
39222		 * @name MeshPhysicalMaterial#reflectivity
39223		 * @type {number}
39224		 * @default 0.5
39225		 */
39226		Object.defineProperty( this, 'reflectivity', {
39227			get: function () {
39228
39229				return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) );
39230
39231			},
39232			set: function ( reflectivity ) {
39233
39234				this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity );
39235
39236			}
39237		} );
39238
39239		/**
39240		 * The red channel of this texture is multiplied against `iridescence`, for per-pixel
39241		 * control over iridescence.
39242		 *
39243		 * `iridescenceMap` represents non-color data. Any texture assigned must have
39244		 * `texture.colorSpace = NoColorSpace` (default).
39245		 *
39246		 * @type {?Texture}
39247		 * @default null
39248		 */
39249		this.iridescenceMap = null;
39250
39251		/**
39252		 * Strength of the iridescence RGB color shift effect, represented by an index-of-refraction.
39253		 * Between `1.0` to `2.333`.
39254		 *
39255		 * @type {number}
39256		 * @default 1.3
39257		 */
39258		this.iridescenceIOR = 1.3;
39259
39260		/**
39261		 *Array of exactly 2 elements, specifying minimum and maximum thickness of the iridescence layer.
39262		 Thickness of iridescence layer has an equivalent effect of the one `thickness` has on `ior`.
39263		 *
39264		 * @type {Array<number,number>}
39265		 * @default [100,400]
39266		 */
39267		this.iridescenceThicknessRange = [ 100, 400 ];
39268
39269		/**
39270		 * A texture that defines the thickness of the iridescence layer, stored in the green channel.
39271		 * Minimum and maximum values of thickness are defined by `iridescenceThicknessRange` array:
39272		 * - `0.0` in the green channel will result in thickness equal to first element of the array.
39273		 * - `1.0` in the green channel will result in thickness equal to second element of the array.
39274		 * - Values in-between will linearly interpolate between the elements of the array.
39275		 *
39276		 * `iridescenceThicknessMap` represents non-color data. Any texture assigned must have
39277		 * `texture.colorSpace = NoColorSpace` (default).
39278		 *
39279		 * @type {?Texture}
39280		 * @default null
39281		 */
39282		this.iridescenceThicknessMap = null;
39283
39284		/**
39285		 * The sheen tint.
39286		 *
39287		 * @type {Color}
39288		 * @default (0,0,0)
39289		 */
39290		this.sheenColor = new Color( 0x000000 );
39291
39292		/**
39293		 * The RGB channels of this texture are multiplied against  `sheenColor`, for per-pixel control
39294		 * over sheen tint.
39295		 *
39296		 * `sheenColorMap` represents color data, and the texture must be assigned a
39297		 * {@link Texture#colorSpace}. Most `sheenColorMap` textures set
39298		 * `texture.colorSpace = SRGBColorSpace`.
39299		 *
39300		 * @type {?Texture}
39301		 * @default null
39302		 */
39303		this.sheenColorMap = null;
39304
39305		/**
39306		 * Roughness of the sheen layer, from `0.0` to `1.0`.
39307		 *
39308		 * @type {number}
39309		 * @default 1
39310		 */
39311		this.sheenRoughness = 1.0;
39312
39313		/**
39314		 * The alpha channel of this texture is multiplied against `sheenRoughness`, for per-pixel control
39315		 * over sheen roughness.
39316		 *
39317		 * `sheenRoughnessMap` represents non-color data. Any texture assigned must have
39318		 * `texture.colorSpace = NoColorSpace` (default).
39319		 *
39320		 * @type {?Texture}
39321		 * @default null
39322		 */
39323		this.sheenRoughnessMap = null;
39324
39325		/**
39326		 * The red channel of this texture is multiplied against `transmission`, for per-pixel control over
39327		 * optical transparency.
39328		 *
39329		 * `transmissionMap` represents non-color data. Any texture assigned must have
39330		 * `texture.colorSpace = NoColorSpace` (default).
39331		 *
39332		 * @type {?Texture}
39333		 * @default null
39334		 */
39335		this.transmissionMap = null;
39336
39337		/**
39338		 * The thickness of the volume beneath the surface. The value is given in the
39339		 * coordinate space of the mesh. If the value is `0` the material is
39340		 * thin-walled. Otherwise the material is a volume boundary.
39341		 *
39342		 * @type {number}
39343		 * @default 0
39344		 */
39345		this.thickness = 0;
39346
39347		/**
39348		 * A texture that defines the thickness, stored in the green channel. This will
39349		 * be multiplied by `thickness`.
39350		 *
39351		 * `thicknessMap` represents non-color data. Any texture assigned must have
39352		 * `texture.colorSpace = NoColorSpace` (default).
39353		 *
39354		 * @type {?Texture}
39355		 * @default null
39356		 */
39357		this.thicknessMap = null;
39358
39359		/**
39360		 * Density of the medium given as the average distance that light travels in
39361		 * the medium before interacting with a particle. The value is given in world
39362		 * space units, and must be greater than zero.
39363		 *
39364		 * @type {number}
39365		 * @default Infinity
39366		 */
39367		this.attenuationDistance = Infinity;
39368
39369		/**
39370		 * The color that white light turns into due to absorption when reaching the
39371		 * attenuation distance.
39372		 *
39373		 * @type {Color}
39374		 * @default (1,1,1)
39375		 */
39376		this.attenuationColor = new Color( 1, 1, 1 );
39377
39378		/**
39379		 * A float that scales the amount of specular reflection for non-metals only.
39380		 * When set to zero, the model is effectively Lambertian. From `0.0` to `1.0`.
39381		 *
39382		 * @type {number}
39383		 * @default 1
39384		 */
39385		this.specularIntensity = 1.0;
39386
39387		/**
39388		 * The alpha channel of this texture is multiplied against `specularIntensity`,
39389		 * for per-pixel control over specular intensity.
39390		 *
39391		 * `specularIntensityMap` represents non-color data. Any texture assigned must have
39392		 * `texture.colorSpace = NoColorSpace` (default).
39393		 *
39394		 * @type {?Texture}
39395		 * @default null
39396		 */
39397		this.specularIntensityMap = null;
39398
39399		/**
39400		 * Tints the specular reflection at normal incidence for non-metals only.
39401		 *
39402		 * @type {Color}
39403		 * @default (1,1,1)
39404		 */
39405		this.specularColor = new Color( 1, 1, 1 );
39406
39407		/**
39408		 * The RGB channels of this texture are multiplied against `specularColor`,
39409		 * for per-pixel control over specular color.
39410		 *
39411		 * `specularColorMap` represents color data, and the texture must be assigned a
39412		 * {@link Texture#colorSpace}. Most `specularColorMap` textures set
39413		 * `texture.colorSpace = SRGBColorSpace`.
39414		 *
39415		 * @type {?Texture}
39416		 * @default null
39417		 */
39418		this.specularColorMap = null;
39419
39420		this._anisotropy = 0;
39421		this._clearcoat = 0;
39422		this._dispersion = 0;
39423		this._iridescence = 0;
39424		this._retroreflectivity = 0;
39425		this._sheen = 0.0;
39426		this._transmission = 0;
39427
39428		this.setValues( parameters );
39429
39430	}
39431
39432	/**
39433	 * The anisotropy strength, from `0.0` to `1.0`.
39434	 *
39435	 * @type {number}
39436	 * @default 0
39437	 */
39438	get anisotropy() {
39439
39440		return this._anisotropy;
39441
39442	}
39443
39444	set anisotropy( value ) {
39445
39446		if ( this._anisotropy > 0 !== value > 0 ) {
39447
39448			this.version ++;
39449
39450		}
39451
39452		this._anisotropy = value;
39453
39454	}
39455
39456	/**
39457	 * Represents the intensity of the clear coat layer, from `0.0` to `1.0`. Use
39458	 * clear coat related properties to enable multilayer materials that have a
39459	 * thin translucent layer over the base layer.
39460	 *
39461	 * @type {number}
39462	 * @default 0
39463	 */
39464	get clearcoat() {
39465
39466		return this._clearcoat;
39467
39468	}
39469
39470	set clearcoat( value ) {
39471
39472		if ( this._clearcoat > 0 !== value > 0 ) {
39473
39474			this.version ++;
39475
39476		}
39477
39478		this._clearcoat = value;
39479
39480	}
39481	/**
39482	 * The intensity of the iridescence layer, simulating RGB color shift based on the angle between
39483	 * the surface and the viewer, from `0.0` to `1.0`.
39484	 *
39485	 * @type {number}
39486	 * @default 0
39487	 */
39488	get iridescence() {
39489
39490		return this._iridescence;
39491
39492	}
39493
39494	set iridescence( value ) {
39495
39496		if ( this._iridescence > 0 !== value > 0 ) {
39497
39498			this.version ++;
39499
39500		}
39501
39502		this._iridescence = value;
39503
39504	}
39505
39506	/**
39507	 * Defines the strength of the angular separation of colors (chromatic aberration) transmitting
39508	 * through a relatively clear volume. Any value zero or larger is valid, the typical range of
39509	 * realistic values is `[0, 1]`. This property can be only be used with transmissive objects.
39510	 *
39511	 * @type {number}
39512	 * @default 0
39513	 */
39514	get dispersion() {
39515
39516		return this._dispersion;
39517
39518	}
39519
39520	set dispersion( value ) {
39521
39522		if ( this._dispersion > 0 !== value > 0 ) {
39523
39524			this.version ++;
39525
39526		}
39527
39528		this._dispersion = value;
39529
39530	}
39531
39532	/**
39533	 * The strength of retroreflection, from `0.0` to `1.0`. A value of `1.0`
39534	 * evaluates the material's microfacet reflection with the view direction
39535	 * reflected about the surface normal, redirecting the specular lobe back
39536	 * toward the light source.
39537	 *
39538	 * @type {number}
39539	 * @default 0
39540	 */
39541	get retroreflectivity() {
39542
39543		return this._retroreflectivity;
39544
39545	}
39546
39547	set retroreflectivity( value ) {
39548
39549		if ( this._retroreflectivity > 0 !== value > 0 ) {
39550
39551			this.version ++;
39552
39553		}
39554
39555		this._retroreflectivity = value;
39556
39557	}
39558
39559	/**
39560	 * The intensity of the sheen layer, from `0.0` to `1.0`.
39561	 *
39562	 * @type {number}
39563	 * @default 0
39564	 */
39565	get sheen() {
39566
39567		return this._sheen;
39568
39569	}
39570
39571	set sheen( value ) {
39572
39573		if ( this._sheen > 0 !== value > 0 ) {
39574
39575			this.version ++;
39576
39577		}
39578
39579		this._sheen = value;
39580
39581	}
39582
39583	/**
39584	 * Degree of transmission (or optical transparency), from `0.0` to `1.0`.
39585	 *
39586	 * Thin, transparent or semitransparent, plastic or glass materials remain
39587	 * largely reflective even if they are fully transmissive. The transmission
39588	 * property can be used to model these materials.
39589	 *
39590	 * When transmission is non-zero, `opacity` should be  set to `1`.
39591	 *
39592	 * @type {number}
39593	 * @default 0
39594	 */
39595	get transmission() {
39596
39597		return this._transmission;
39598
39599	}
39600
39601	set transmission( value ) {
39602
39603		if ( this._transmission > 0 !== value > 0 ) {
39604
39605			this.version ++;
39606
39607		}
39608
39609		this._transmission = value;
39610
39611	}
39612
39613	copy( source ) {
39614
39615		super.copy( source );
39616
39617		this.defines = {
39618
39619			'STANDARD': '',
39620			'PHYSICAL': ''
39621
39622		};
39623
39624		this.anisotropy = source.anisotropy;
39625		this.anisotropyRotation = source.anisotropyRotation;
39626		this.anisotropyMap = source.anisotropyMap;
39627
39628		this.clearcoat = source.clearcoat;
39629		this.clearcoatMap = source.clearcoatMap;
39630		this.clearcoatRoughness = source.clearcoatRoughness;
39631		this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
39632		this.clearcoatNormalMap = source.clearcoatNormalMap;
39633		this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
39634
39635		this.dispersion = source.dispersion;
39636		this.ior = source.ior;
39637
39638		this.iridescence = source.iridescence;
39639		this.iridescenceMap = source.iridescenceMap;
39640		this.iridescenceIOR = source.iridescenceIOR;
39641		this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ];
39642		this.iridescenceThicknessMap = source.iridescenceThicknessMap;
39643
39644		this.retroreflectivity = source.retroreflectivity;
39645
39646		this.sheen = source.sheen;
39647		this.sheenColor.copy( source.sheenColor );
39648		this.sheenColorMap = source.sheenColorMap;
39649		this.sheenRoughness = source.sheenRoughness;
39650		this.sheenRoughnessMap = source.sheenRoughnessMap;
39651
39652		this.transmission = source.transmission;
39653		this.transmissionMap = source.transmissionMap;
39654
39655		this.thickness = source.thickness;
39656		this.thicknessMap = source.thicknessMap;
39657		this.attenuationDistance = source.attenuationDistance;
39658		this.attenuationColor.copy( source.attenuationColor );
39659
39660		this.specularIntensity = source.specularIntensity;
39661		this.specularIntensityMap = source.specularIntensityMap;
39662		this.specularColor.copy( source.specularColor );
39663		this.specularColorMap = source.specularColorMap;
39664
39665		return this;
39666
39667	}
39668
39669}
39670
39671/**
39672 * A material for shiny surfaces with specular highlights.
39673 *
39674 * The material uses a non-physically based [Blinn-Phong](https://en.wikipedia.org/wiki/Blinn-Phong_shading_model)
39675 * model for calculating reflectance. Unlike the Lambertian model used in the
39676 * {@link MeshLambertMaterial} this can simulate shiny surfaces with specular
39677 * highlights (such as varnished wood). `MeshPhongMaterial` uses per-fragment shading.
39678 *
39679 * Performance will generally be greater when using this material over the
39680 * {@link MeshStandardMaterial} or {@link MeshPhysicalMaterial}, at the cost of
39681 * some graphical accuracy.
39682 *
39683 * @augments Material
39684 * @demo scenes/material-browser.html#MeshPhongMaterial
39685 */
39686class MeshPhongMaterial extends Material {
39687
39688	/**
39689	 * Constructs a new mesh phong material.
39690	 *
39691	 * @param {Object} [parameters] - An object with one or more properties
39692	 * defining the material's appearance. Any property of the material
39693	 * (including any property from inherited materials) can be passed
39694	 * in here. Color values can be passed any type of value accepted
39695	 * by {@link Color#set}.
39696	 */
39697	constructor( parameters ) {
39698
39699		super();
39700
39701		/**
39702		 * This flag can be used for type testing.
39703		 *
39704		 * @type {boolean}
39705		 * @readonly
39706		 * @default true
39707		 */
39708		this.isMeshPhongMaterial = true;
39709
39710		this.type = 'MeshPhongMaterial';
39711
39712		/**
39713		 * Color of the material.
39714		 *
39715		 * @type {Color}
39716		 * @default (1,1,1)
39717		 */
39718		this.color = new Color( 0xffffff ); // diffuse
39719
39720		/**
39721		 * Specular color of the material. The default color is set to `0x111111` (very dark grey)
39722		 *
39723		 * This defines how shiny the material is and the color of its shine.
39724		 *
39725		 * @type {Color}
39726		 */
39727		this.specular = new Color( 0x111111 );
39728
39729		/**
39730		 * How shiny the specular highlight is; a higher value gives a sharper highlight.
39731		 *
39732		 * @type {number}
39733		 * @default 30
39734		 */
39735		this.shininess = 30;
39736
39737		/**
39738		 * The color map. May optionally include an alpha channel, typically combined
39739		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
39740		 * color is modulated by the diffuse `color`.
39741		 *
39742		 * `map` represents color data, and the texture must be assigned a
39743		 * {@link Texture#colorSpace}. Most `map` textures set
39744		 * `texture.colorSpace = SRGBColorSpace`.
39745		 *
39746		 * @type {?Texture}
39747		 * @default null
39748		 */
39749		this.map = null;
39750
39751		/**
39752		 * The light map. Requires a second set of UVs.
39753		 *
39754		 * `lightMap` represents pre-baked illuminance data, and the texture must be assigned
39755		 * a {@link Texture#colorSpace}. Most `lightMap` textures set
39756		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
39757		 * such as `.exr` or `.hdr`.
39758		 *
39759		 * @type {?Texture}
39760		 * @default null
39761		 */
39762		this.lightMap = null;
39763
39764		/**
39765		 * Intensity of the baked light.
39766		 *
39767		 * @type {number}
39768		 * @default 1
39769		 */
39770		this.lightMapIntensity = 1.0;
39771
39772		/**
39773		 * The red channel of this texture is used as the ambient occlusion map.
39774		 * Requires a second set of UVs.
39775		 *
39776		 * `aoMap` represents non-color data. Any texture assigned must have
39777		 * `texture.colorSpace = NoColorSpace` (default).
39778		 *
39779		 * @type {?Texture}
39780		 * @default null
39781		 */
39782		this.aoMap = null;
39783
39784		/**
39785		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
39786		 * disables ambient occlusion. Where intensity is `1` and the AO map's
39787		 * red channel is also `1`, ambient light is fully occluded on a surface.
39788		 *
39789		 * @type {number}
39790		 * @default 1
39791		 */
39792		this.aoMapIntensity = 1.0;
39793
39794		/**
39795		 * Emissive (light) color of the material, essentially a solid color
39796		 * unaffected by other lighting.
39797		 *
39798		 * @type {Color}
39799		 * @default (0,0,0)
39800		 */
39801		this.emissive = new Color( 0x000000 );
39802
39803		/**
39804		 * Intensity of the emissive light. Modulates the emissive color.
39805		 *
39806		 * @type {number}
39807		 * @default 1
39808		 */
39809		this.emissiveIntensity = 1.0;
39810
39811		/**
39812		 * Set emissive (glow) map. The emissive map color is modulated by the
39813		 * emissive color and the emissive intensity. If you have an emissive map,
39814		 * be sure to set the emissive color to something other than black.
39815		 *
39816		 * `emissiveMap` represents color data, and the texture must be assigned a
39817		 * {@link Texture#colorSpace}. Most `emissiveMap` textures set
39818		 * `texture.colorSpace = SRGBColorSpace`.
39819		 *
39820		 * @type {?Texture}
39821		 * @default null
39822		 */
39823		this.emissiveMap = null;
39824
39825		/**
39826		 * The texture to create a bump map. The black and white values map to the
39827		 * perceived depth in relation to the lights. Bump doesn't actually affect
39828		 * the geometry of the object, only the lighting. If a normal map is defined
39829		 * this will be ignored.
39830		 *
39831		 * `bumpMap` represents non-color data. Any texture assigned must have
39832		 * `texture.colorSpace = NoColorSpace` (default).
39833		 *
39834		 * @type {?Texture}
39835		 * @default null
39836		 */
39837		this.bumpMap = null;
39838
39839		/**
39840		 * How much the bump map affects the material. Typical range is `[0,1]`.
39841		 *
39842		 * @type {number}
39843		 * @default 1
39844		 */
39845		this.bumpScale = 1;
39846
39847		/**
39848		 * The texture to create a normal map. The RGB values affect the surface
39849		 * normal for each pixel fragment and change the way the color is lit. Normal
39850		 * maps do not change the actual shape of the surface, only the lighting. In
39851		 * case the material has a normal map authored using the left handed
39852		 * convention, the `y` component of `normalScale` should be negated to compensate
39853		 * for the different handedness.
39854		 *
39855		 * `normalMap` represents non-color data. Any texture assigned must have
39856		 * `texture.colorSpace = NoColorSpace` (default).
39857		 *
39858		 * @type {?Texture}
39859		 * @default null
39860		 */
39861		this.normalMap = null;
39862
39863		/**
39864		 * The type of normal map.
39865		 *
39866		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
39867		 * @default TangentSpaceNormalMap
39868		 */
39869		this.normalMapType = TangentSpaceNormalMap;
39870
39871		/**
39872		 * How much the normal map affects the material. Typical value range is `[0,1]`.
39873		 *
39874		 * @type {Vector2}
39875		 * @default (1,1)
39876		 */
39877		this.normalScale = new Vector2( 1, 1 );
39878
39879		/**
39880		 * The displacement map affects the position of the mesh's vertices. Unlike
39881		 * other maps which only affect the light and shade of the material the
39882		 * displaced vertices can cast shadows, block other objects, and otherwise
39883		 * act as real geometry. The displacement texture is an image where the value
39884		 * of each pixel (white being the highest) is mapped against, and
39885		 * repositions, the vertices of the mesh. For best results, pair a
39886		 * displacement map with a matching normal map, since the renderer can
39887		 * not recompute surface normals from the displaced vertices.
39888		 *
39889		 * `displacementMap` represents non-color data. Any texture assigned must have
39890		 * `texture.colorSpace = NoColorSpace` (default).
39891		 *
39892		 * @type {?Texture}
39893		 * @default null
39894		 */
39895		this.displacementMap = null;
39896
39897		/**
39898		 * How much the displacement map affects the mesh (where black is no
39899		 * displacement, and white is maximum displacement). Without a displacement
39900		 * map set, this value is not applied.
39901		 *
39902		 * @type {number}
39903		 * @default 0
39904		 */
39905		this.displacementScale = 1;
39906
39907		/**
39908		 * The offset of the displacement map's values on the mesh's vertices.
39909		 * The bias is added to the scaled sample of the displacement map.
39910		 * Without a displacement map set, this value is not applied.
39911		 *
39912		 * @type {number}
39913		 * @default 0
39914		 */
39915		this.displacementBias = 0;
39916
39917		/**
39918		 * The specular map value affects both how much the specular surface
39919		 * highlight contributes and how much of the environment map affects the
39920		 * surface.
39921		 *
39922		 * `specularMap` represents color data, and the texture must be assigned a
39923		 * {@link Texture#colorSpace}. Most `specularMap` textures set
39924		 * `texture.colorSpace = SRGBColorSpace`.
39925		 *
39926		 * @type {?Texture}
39927		 * @default null
39928		 */
39929		this.specularMap = null;
39930
39931		/**
39932		 * The alpha map is a grayscale texture that controls the opacity across the
39933		 * surface (black: fully transparent; white: fully opaque).
39934		 *
39935		 * Only the color of the texture is used, ignoring the alpha channel if one
39936		 * exists. For RGB and RGBA textures, the renderer will use the green channel
39937		 * when sampling this texture due to the extra bit of precision provided for
39938		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
39939		 * luminance/alpha textures will also still work as expected.
39940		 *
39941		 * `alphaMap` represents non-color data. Any texture assigned must have
39942		 * `texture.colorSpace = NoColorSpace` (default).
39943		 *
39944		 * @type {?Texture}
39945		 * @default null
39946		 */
39947		this.alphaMap = null;
39948
39949		/**
39950		 * The environment map.
39951		 *
39952		 * `envMap` represents luminance data, and the texture must be assigned
39953		 * a {@link Texture#colorSpace}. Most `envMap` textures set
39954		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
39955		 * such as `.exr` or `.hdr`.
39956		 *
39957		 * @type {?Texture}
39958		 * @default null
39959		 */
39960		this.envMap = null;
39961
39962		/**
39963		 * The rotation of the environment map in radians.
39964		 *
39965		 * @type {Euler}
39966		 * @default (0,0,0)
39967		 */
39968		this.envMapRotation = new Euler();
39969
39970		/**
39971		 * How to combine the result of the surface's color with the environment map, if any.
39972		 *
39973		 * When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
39974		 * blend between the two colors.
39975		 *
39976		 * @type {(MultiplyOperation|MixOperation|AddOperation)}
39977		 * @default MultiplyOperation
39978		 */
39979		this.combine = MultiplyOperation;
39980
39981		/**
39982		 * How much the environment map affects the surface.
39983		 * The valid range is between `0` (no reflections) and `1` (full reflections).
39984		 *
39985		 * @type {number}
39986		 * @default 1
39987		 */
39988		this.reflectivity = 1;
39989
39990		/**
39991		 * Scales the effect of the environment map by multiplying its color.
39992		 *
39993		 * @type {number}
39994		 * @default 1
39995		 */
39996		this.envMapIntensity = 1.0;
39997
39998		/**
39999		 * The index of refraction (IOR) of air (approximately 1) divided by the
40000		 * index of refraction of the material. It is used with environment mapping
40001		 * modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
40002		 * The refraction ratio should not exceed `1`.
40003		 *
40004		 * @type {number}
40005		 * @default 0.98
40006		 */
40007		this.refractionRatio = 0.98;
40008
40009		/**
40010		 * Renders the geometry as a wireframe.
40011		 *
40012		 * @type {boolean}
40013		 * @default false
40014		 */
40015		this.wireframe = false;
40016
40017		/**
40018		 * Controls the thickness of the wireframe.
40019		 *
40020		 * Can only be used with {@link SVGRenderer}.
40021		 *
40022		 * @type {number}
40023		 * @default 1
40024		 */
40025		this.wireframeLinewidth = 1;
40026
40027		/**
40028		 * Defines appearance of wireframe ends.
40029		 *
40030		 * Can only be used with {@link SVGRenderer}.
40031		 *
40032		 * @type {('round'|'bevel'|'miter')}
40033		 * @default 'round'
40034		 */
40035		this.wireframeLinecap = 'round';
40036
40037		/**
40038		 * Defines appearance of wireframe joints.
40039		 *
40040		 * Can only be used with {@link SVGRenderer}.
40041		 *
40042		 * @type {('round'|'bevel'|'miter')}
40043		 * @default 'round'
40044		 */
40045		this.wireframeLinejoin = 'round';
40046
40047		/**
40048		 * Whether the material is rendered with flat shading or not.
40049		 *
40050		 * @type {boolean}
40051		 * @default false
40052		 */
40053		this.flatShading = false;
40054
40055		/**
40056		 * Whether the material is affected by fog or not.
40057		 *
40058		 * @type {boolean}
40059		 * @default true
40060		 */
40061		this.fog = true;
40062
40063		this.setValues( parameters );
40064
40065	}
40066
40067	copy( source ) {
40068
40069		super.copy( source );
40070
40071		this.color.copy( source.color );
40072		this.specular.copy( source.specular );
40073		this.shininess = source.shininess;
40074
40075		this.map = source.map;
40076
40077		this.lightMap = source.lightMap;
40078		this.lightMapIntensity = source.lightMapIntensity;
40079
40080		this.aoMap = source.aoMap;
40081		this.aoMapIntensity = source.aoMapIntensity;
40082
40083		this.emissive.copy( source.emissive );
40084		this.emissiveMap = source.emissiveMap;
40085		this.emissiveIntensity = source.emissiveIntensity;
40086
40087		this.bumpMap = source.bumpMap;
40088		this.bumpScale = source.bumpScale;
40089
40090		this.normalMap = source.normalMap;
40091		this.normalMapType = source.normalMapType;
40092		this.normalScale.copy( source.normalScale );
40093
40094		this.displacementMap = source.displacementMap;
40095		this.displacementScale = source.displacementScale;
40096		this.displacementBias = source.displacementBias;
40097
40098		this.specularMap = source.specularMap;
40099
40100		this.alphaMap = source.alphaMap;
40101
40102		this.envMap = source.envMap;
40103		this.envMapRotation.copy( source.envMapRotation );
40104		this.combine = source.combine;
40105		this.reflectivity = source.reflectivity;
40106		this.envMapIntensity = source.envMapIntensity;
40107		this.refractionRatio = source.refractionRatio;
40108
40109		this.wireframe = source.wireframe;
40110		this.wireframeLinewidth = source.wireframeLinewidth;
40111		this.wireframeLinecap = source.wireframeLinecap;
40112		this.wireframeLinejoin = source.wireframeLinejoin;
40113
40114		this.flatShading = source.flatShading;
40115
40116		this.fog = source.fog;
40117
40118		return this;
40119
40120	}
40121
40122}
40123
40124/**
40125 * A material implementing toon shading.
40126 *
40127 * @augments Material
40128 * @demo scenes/material-browser.html#MeshToonMaterial
40129 */
40130class MeshToonMaterial extends Material {
40131
40132	/**
40133	 * Constructs a new mesh toon material.
40134	 *
40135	 * @param {Object} [parameters] - An object with one or more properties
40136	 * defining the material's appearance. Any property of the material
40137	 * (including any property from inherited materials) can be passed
40138	 * in here. Color values can be passed any type of value accepted
40139	 * by {@link Color#set}.
40140	 */
40141	constructor( parameters ) {
40142
40143		super();
40144
40145		/**
40146		 * This flag can be used for type testing.
40147		 *
40148		 * @type {boolean}
40149		 * @readonly
40150		 * @default true
40151		 */
40152		this.isMeshToonMaterial = true;
40153
40154		this.defines = { 'TOON': '' };
40155
40156		this.type = 'MeshToonMaterial';
40157
40158		/**
40159		 * Color of the material.
40160		 *
40161		 * @type {Color}
40162		 * @default (1,1,1)
40163		 */
40164		this.color = new Color( 0xffffff );
40165
40166		/**
40167		 * The color map. May optionally include an alpha channel, typically combined
40168		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
40169		 * color is modulated by the diffuse `color`.
40170		 *
40171		 * `map` represents color data, and the texture must be assigned a
40172		 * {@link Texture#colorSpace}. Most `map` textures set
40173		 * `texture.colorSpace = SRGBColorSpace`.
40174		 *
40175		 * @type {?Texture}
40176		 * @default null
40177		 */
40178		this.map = null;
40179
40180		/**
40181		 * Gradient map for toon shading. It's required to set
40182		 * {@link Texture#minFilter} and {@link Texture#magFilter} to {@link NearestFilter}
40183		 * when using this type of texture.
40184		 *
40185		 * `gradientMap` represents non-color data. Any texture assigned must have
40186		 * `texture.colorSpace = NoColorSpace` (default).
40187		 *
40188		 * @type {?Texture}
40189		 * @default null
40190		 */
40191		this.gradientMap = null;
40192
40193		/**
40194		 * The light map. Requires a second set of UVs.
40195		 *
40196		 * `lightMap` represents pre-baked illuminance data, and the texture must be assigned
40197		 * a {@link Texture#colorSpace}. Most `lightMap` textures set
40198		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
40199		 * such as `.exr` or `.hdr`.
40200		 *
40201		 * @type {?Texture}
40202		 * @default null
40203		 */
40204		this.lightMap = null;
40205
40206		/**
40207		 * Intensity of the baked light.
40208		 *
40209		 * @type {number}
40210		 * @default 1
40211		 */
40212		this.lightMapIntensity = 1.0;
40213
40214		/**
40215		 * The red channel of this texture is used as the ambient occlusion map.
40216		 * Requires a second set of UVs.
40217		 *
40218		 * `aoMap` represents non-color data. Any texture assigned must have
40219		 * `texture.colorSpace = NoColorSpace` (default).
40220		 *
40221		 * @type {?Texture}
40222		 * @default null
40223		 */
40224		this.aoMap = null;
40225
40226		/**
40227		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
40228		 * disables ambient occlusion. Where intensity is `1` and the AO map's
40229		 * red channel is also `1`, ambient light is fully occluded on a surface.
40230		 *
40231		 * @type {number}
40232		 * @default 1
40233		 */
40234		this.aoMapIntensity = 1.0;
40235
40236		/**
40237		 * Emissive (light) color of the material, essentially a solid color
40238		 * unaffected by other lighting.
40239		 *
40240		 * @type {Color}
40241		 * @default (0,0,0)
40242		 */
40243		this.emissive = new Color( 0x000000 );
40244
40245		/**
40246		 * Intensity of the emissive light. Modulates the emissive color.
40247		 *
40248		 * @type {number}
40249		 * @default 1
40250		 */
40251		this.emissiveIntensity = 1.0;
40252
40253		/**
40254		 * Set emissive (glow) map. The emissive map color is modulated by the
40255		 * emissive color and the emissive intensity. If you have an emissive map,
40256		 * be sure to set the emissive color to something other than black.
40257		 *
40258		 * `emissiveMap` represents color data, and the texture must be assigned a
40259		 * {@link Texture#colorSpace}. Most `emissiveMap` textures set
40260		 * `texture.colorSpace = SRGBColorSpace`.
40261		 *
40262		 * @type {?Texture}
40263		 * @default null
40264		 */
40265		this.emissiveMap = null;
40266
40267		/**
40268		 * The texture to create a bump map. The black and white values map to the
40269		 * perceived depth in relation to the lights. Bump doesn't actually affect
40270		 * the geometry of the object, only the lighting. If a normal map is defined
40271		 * this will be ignored.
40272		 *
40273		 * `bumpMap` represents non-color data. Any texture assigned must have
40274		 * `texture.colorSpace = NoColorSpace` (default).
40275		 *
40276		 * @type {?Texture}
40277		 * @default null
40278		 */
40279		this.bumpMap = null;
40280
40281		/**
40282		 * How much the bump map affects the material. Typical range is `[0,1]`.
40283		 *
40284		 * @type {number}
40285		 * @default 1
40286		 */
40287		this.bumpScale = 1;
40288
40289		/**
40290		 * The texture to create a normal map. The RGB values affect the surface
40291		 * normal for each pixel fragment and change the way the color is lit. Normal
40292		 * maps do not change the actual shape of the surface, only the lighting. In
40293		 * case the material has a normal map authored using the left handed
40294		 * convention, the `y` component of `normalScale` should be negated to compensate
40295		 * for the different handedness.
40296		 *
40297		 * `normalMap` represents non-color data. Any texture assigned must have
40298		 * `texture.colorSpace = NoColorSpace` (default).
40299		 *
40300		 * @type {?Texture}
40301		 * @default null
40302		 */
40303		this.normalMap = null;
40304
40305		/**
40306		 * The type of normal map.
40307		 *
40308		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
40309		 * @default TangentSpaceNormalMap
40310		 */
40311		this.normalMapType = TangentSpaceNormalMap;
40312
40313		/**
40314		 * How much the normal map affects the material. Typical value range is `[0,1]`.
40315		 *
40316		 * @type {Vector2}
40317		 * @default (1,1)
40318		 */
40319		this.normalScale = new Vector2( 1, 1 );
40320
40321		/**
40322		 * The displacement map affects the position of the mesh's vertices. Unlike
40323		 * other maps which only affect the light and shade of the material the
40324		 * displaced vertices can cast shadows, block other objects, and otherwise
40325		 * act as real geometry. The displacement texture is an image where the value
40326		 * of each pixel (white being the highest) is mapped against, and
40327		 * repositions, the vertices of the mesh. For best results, pair a
40328		 * displacement map with a matching normal map, since the renderer can
40329		 * not recompute surface normals from the displaced vertices.
40330		 *
40331		 * `displacementMap` represents non-color data. Any texture assigned must have
40332		 * `texture.colorSpace = NoColorSpace` (default).
40333		 *
40334		 * @type {?Texture}
40335		 * @default null
40336		 */
40337		this.displacementMap = null;
40338
40339		/**
40340		 * How much the displacement map affects the mesh (where black is no
40341		 * displacement, and white is maximum displacement). Without a displacement
40342		 * map set, this value is not applied.
40343		 *
40344		 * @type {number}
40345		 * @default 0
40346		 */
40347		this.displacementScale = 1;
40348
40349		/**
40350		 * The offset of the displacement map's values on the mesh's vertices.
40351		 * The bias is added to the scaled sample of the displacement map.
40352		 * Without a displacement map set, this value is not applied.
40353		 *
40354		 * @type {number}
40355		 * @default 0
40356		 */
40357		this.displacementBias = 0;
40358
40359		/**
40360		 * The alpha map is a grayscale texture that controls the opacity across the
40361		 * surface (black: fully transparent; white: fully opaque).
40362		 *
40363		 * Only the color of the texture is used, ignoring the alpha channel if one
40364		 * exists. For RGB and RGBA textures, the renderer will use the green channel
40365		 * when sampling this texture due to the extra bit of precision provided for
40366		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
40367		 * luminance/alpha textures will also still work as expected.
40368		 *
40369		 * `alphaMap` represents non-color data. Any texture assigned must have
40370		 * `texture.colorSpace = NoColorSpace` (default).
40371		 *
40372		 * @type {?Texture}
40373		 * @default null
40374		 */
40375		this.alphaMap = null;
40376
40377		/**
40378		 * Renders the geometry as a wireframe.
40379		 *
40380		 * @type {boolean}
40381		 * @default false
40382		 */
40383		this.wireframe = false;
40384
40385		/**
40386		 * Controls the thickness of the wireframe.
40387		 *
40388		 * Can only be used with {@link SVGRenderer}.
40389		 *
40390		 * @type {number}
40391		 * @default 1
40392		 */
40393		this.wireframeLinewidth = 1;
40394
40395		/**
40396		 * Defines appearance of wireframe ends.
40397		 *
40398		 * Can only be used with {@link SVGRenderer}.
40399		 *
40400		 * @type {('round'|'bevel'|'miter')}
40401		 * @default 'round'
40402		 */
40403		this.wireframeLinecap = 'round';
40404
40405		/**
40406		 * Defines appearance of wireframe joints.
40407		 *
40408		 * Can only be used with {@link SVGRenderer}.
40409		 *
40410		 * @type {('round'|'bevel'|'miter')}
40411		 * @default 'round'
40412		 */
40413		this.wireframeLinejoin = 'round';
40414
40415		/**
40416		 * Whether the material is affected by fog or not.
40417		 *
40418		 * @type {boolean}
40419		 * @default true
40420		 */
40421		this.fog = true;
40422
40423		this.setValues( parameters );
40424
40425	}
40426
40427	copy( source ) {
40428
40429		super.copy( source );
40430
40431		this.color.copy( source.color );
40432
40433		this.map = source.map;
40434		this.gradientMap = source.gradientMap;
40435
40436		this.lightMap = source.lightMap;
40437		this.lightMapIntensity = source.lightMapIntensity;
40438
40439		this.aoMap = source.aoMap;
40440		this.aoMapIntensity = source.aoMapIntensity;
40441
40442		this.emissive.copy( source.emissive );
40443		this.emissiveMap = source.emissiveMap;
40444		this.emissiveIntensity = source.emissiveIntensity;
40445
40446		this.bumpMap = source.bumpMap;
40447		this.bumpScale = source.bumpScale;
40448
40449		this.normalMap = source.normalMap;
40450		this.normalMapType = source.normalMapType;
40451		this.normalScale.copy( source.normalScale );
40452
40453		this.displacementMap = source.displacementMap;
40454		this.displacementScale = source.displacementScale;
40455		this.displacementBias = source.displacementBias;
40456
40457		this.alphaMap = source.alphaMap;
40458
40459		this.wireframe = source.wireframe;
40460		this.wireframeLinewidth = source.wireframeLinewidth;
40461		this.wireframeLinecap = source.wireframeLinecap;
40462		this.wireframeLinejoin = source.wireframeLinejoin;
40463
40464		this.fog = source.fog;
40465
40466		return this;
40467
40468	}
40469
40470}
40471
40472/**
40473 * A material that maps the normal vectors to RGB colors.
40474 *
40475 * @augments Material
40476 * @demo scenes/material-browser.html#MeshNormalMaterial
40477 */
40478class MeshNormalMaterial extends Material {
40479
40480	/**
40481	 * Constructs a new mesh normal material.
40482	 *
40483	 * @param {Object} [parameters] - An object with one or more properties
40484	 * defining the material's appearance. Any property of the material
40485	 * (including any property from inherited materials) can be passed
40486	 * in here. Color values can be passed any type of value accepted
40487	 * by {@link Color#set}.
40488	 */
40489	constructor( parameters ) {
40490
40491		super();
40492
40493		/**
40494		 * This flag can be used for type testing.
40495		 *
40496		 * @type {boolean}
40497		 * @readonly
40498		 * @default true
40499		 */
40500		this.isMeshNormalMaterial = true;
40501
40502		this.type = 'MeshNormalMaterial';
40503
40504		/**
40505		 * The texture to create a bump map. The black and white values map to the
40506		 * perceived depth in relation to the lights. Bump doesn't actually affect
40507		 * the geometry of the object, only the lighting. If a normal map is defined
40508		 * this will be ignored.
40509		 *
40510		 * `bumpMap` represents non-color data. Any texture assigned must have
40511		 * `texture.colorSpace = NoColorSpace` (default).
40512		 *
40513		 * @type {?Texture}
40514		 * @default null
40515		 */
40516		this.bumpMap = null;
40517
40518		/**
40519		 * How much the bump map affects the material. Typical range is `[0,1]`.
40520		 *
40521		 * @type {number}
40522		 * @default 1
40523		 */
40524		this.bumpScale = 1;
40525
40526		/**
40527		 * The texture to create a normal map. The RGB values affect the surface
40528		 * normal for each pixel fragment and change the way the color is lit. Normal
40529		 * maps do not change the actual shape of the surface, only the lighting. In
40530		 * case the material has a normal map authored using the left handed
40531		 * convention, the `y` component of `normalScale` should be negated to compensate
40532		 * for the different handedness.
40533		 *
40534		 * `normalMap` represents non-color data. Any texture assigned must have
40535		 * `texture.colorSpace = NoColorSpace` (default).
40536		 *
40537		 * @type {?Texture}
40538		 * @default null
40539		 */
40540		this.normalMap = null;
40541
40542		/**
40543		 * The type of normal map.
40544		 *
40545		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
40546		 * @default TangentSpaceNormalMap
40547		 */
40548		this.normalMapType = TangentSpaceNormalMap;
40549
40550		/**
40551		 * How much the normal map affects the material. Typical value range is `[0,1]`.
40552		 *
40553		 * @type {Vector2}
40554		 * @default (1,1)
40555		 */
40556		this.normalScale = new Vector2( 1, 1 );
40557
40558		/**
40559		 * The displacement map affects the position of the mesh's vertices. Unlike
40560		 * other maps which only affect the light and shade of the material the
40561		 * displaced vertices can cast shadows, block other objects, and otherwise
40562		 * act as real geometry. The displacement texture is an image where the value
40563		 * of each pixel (white being the highest) is mapped against, and
40564		 * repositions, the vertices of the mesh. For best results, pair a
40565		 * displacement map with a matching normal map, since the renderer can
40566		 * not recompute surface normals from the displaced vertices.
40567		 *
40568		 * @type {?Texture}
40569		 * @default null
40570		 */
40571		this.displacementMap = null;
40572
40573		/**
40574		 * How much the displacement map affects the mesh (where black is no
40575		 * displacement, and white is maximum displacement). Without a displacement
40576		 * map set, this value is not applied.
40577		 *
40578		 * @type {number}
40579		 * @default 0
40580		 */
40581		this.displacementScale = 1;
40582
40583		/**
40584		 * The offset of the displacement map's values on the mesh's vertices.
40585		 * The bias is added to the scaled sample of the displacement map.
40586		 * Without a displacement map set, this value is not applied.
40587		 *
40588		 * @type {number}
40589		 * @default 0
40590		 */
40591		this.displacementBias = 0;
40592
40593		/**
40594		 * Renders the geometry as a wireframe.
40595		 *
40596		 * @type {boolean}
40597		 * @default false
40598		 */
40599		this.wireframe = false;
40600
40601		/**
40602		 * Controls the thickness of the wireframe.
40603		 *
40604		 * WebGL and WebGPU ignore this property and always render
40605		 * 1 pixel wide lines.
40606		 *
40607		 * @type {number}
40608		 * @default 1
40609		 */
40610		this.wireframeLinewidth = 1;
40611
40612		/**
40613		 * Whether the material is rendered with flat shading or not.
40614		 *
40615		 * @type {boolean}
40616		 * @default false
40617		 */
40618		this.flatShading = false;
40619
40620		this.setValues( parameters );
40621
40622	}
40623
40624	copy( source ) {
40625
40626		super.copy( source );
40627
40628		this.bumpMap = source.bumpMap;
40629		this.bumpScale = source.bumpScale;
40630
40631		this.normalMap = source.normalMap;
40632		this.normalMapType = source.normalMapType;
40633		this.normalScale.copy( source.normalScale );
40634
40635		this.displacementMap = source.displacementMap;
40636		this.displacementScale = source.displacementScale;
40637		this.displacementBias = source.displacementBias;
40638
40639		this.wireframe = source.wireframe;
40640		this.wireframeLinewidth = source.wireframeLinewidth;
40641
40642		this.flatShading = source.flatShading;
40643
40644		return this;
40645
40646	}
40647
40648}
40649
40650/**
40651 * A material for non-shiny surfaces, without specular highlights.
40652 *
40653 * The material uses a non-physically based [Lambertian](https://en.wikipedia.org/wiki/Lambertian_reflectance)
40654 * model for calculating reflectance. This can simulate some surfaces (such
40655 * as untreated wood or stone) well, but cannot simulate shiny surfaces with
40656 * specular highlights (such as varnished wood). `MeshLambertMaterial` uses per-fragment
40657 * shading.
40658 *
40659 * Due to the simplicity of the reflectance and illumination models,
40660 * performance will be greater when using this material over the
40661 * {@link MeshPhongMaterial}, {@link MeshStandardMaterial} or
40662 * {@link MeshPhysicalMaterial}, at the cost of some graphical accuracy.
40663 *
40664 * @augments Material
40665 * @demo scenes/material-browser.html#MeshLambertMaterial
40666 */
40667class MeshLambertMaterial extends Material {
40668
40669	/**
40670	 * Constructs a new mesh lambert material.
40671	 *
40672	 * @param {Object} [parameters] - An object with one or more properties
40673	 * defining the material's appearance. Any property of the material
40674	 * (including any property from inherited materials) can be passed
40675	 * in here. Color values can be passed any type of value accepted
40676	 * by {@link Color#set}.
40677	 */
40678	constructor( parameters ) {
40679
40680		super();
40681
40682		/**
40683		 * This flag can be used for type testing.
40684		 *
40685		 * @type {boolean}
40686		 * @readonly
40687		 * @default true
40688		 */
40689		this.isMeshLambertMaterial = true;
40690
40691		this.type = 'MeshLambertMaterial';
40692
40693		/**
40694		 * Color of the material.
40695		 *
40696		 * @type {Color}
40697		 * @default (1,1,1)
40698		 */
40699		this.color = new Color( 0xffffff ); // diffuse
40700
40701		/**
40702		 * The color map. May optionally include an alpha channel, typically combined
40703		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
40704		 * color is modulated by the diffuse `color`.
40705		 *
40706		 * `map` represents color data, and the texture must be assigned a
40707		 * {@link Texture#colorSpace}. Most `map` textures set
40708		 * `texture.colorSpace = SRGBColorSpace`.
40709		 *
40710		 * @type {?Texture}
40711		 * @default null
40712		 */
40713		this.map = null;
40714
40715		/**
40716		 * The light map. Requires a second set of UVs.
40717		 *
40718		 * `lightMap` represents pre-baked illuminance data, and the texture must be assigned
40719		 * a {@link Texture#colorSpace}. Most `lightMap` textures set
40720		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
40721		 * such as `.exr` or `.hdr`.
40722		 *
40723		 * @type {?Texture}
40724		 * @default null
40725		 */
40726		this.lightMap = null;
40727
40728		/**
40729		 * Intensity of the baked light.
40730		 *
40731		 * @type {number}
40732		 * @default 1
40733		 */
40734		this.lightMapIntensity = 1.0;
40735
40736		/**
40737		 * The red channel of this texture is used as the ambient occlusion map.
40738		 * Requires a second set of UVs.
40739		 *
40740		 * `aoMap` represents non-color data. Any texture assigned must have
40741		 * `texture.colorSpace = NoColorSpace` (default).
40742		 *
40743		 * @type {?Texture}
40744		 * @default null
40745		 */
40746		this.aoMap = null;
40747
40748		/**
40749		 * Intensity of the ambient occlusion effect. Range is `[0,1]`, where `0`
40750		 * disables ambient occlusion. Where intensity is `1` and the AO map's
40751		 * red channel is also `1`, ambient light is fully occluded on a surface.
40752		 *
40753		 * @type {number}
40754		 * @default 1
40755		 */
40756		this.aoMapIntensity = 1.0;
40757
40758		/**
40759		 * Emissive (light) color of the material, essentially a solid color
40760		 * unaffected by other lighting.
40761		 *
40762		 * @type {Color}
40763		 * @default (0,0,0)
40764		 */
40765		this.emissive = new Color( 0x000000 );
40766
40767		/**
40768		 * Intensity of the emissive light. Modulates the emissive color.
40769		 *
40770		 * @type {number}
40771		 * @default 1
40772		 */
40773		this.emissiveIntensity = 1.0;
40774
40775		/**
40776		 * Set emissive (glow) map. The emissive map color is modulated by the
40777		 * emissive color and the emissive intensity. If you have an emissive map,
40778		 * be sure to set the emissive color to something other than black.
40779		 *
40780		 * `emissiveMap` represents color data, and the texture must be assigned a
40781		 * {@link Texture#colorSpace}. Most `emissiveMap` textures set
40782		 * `texture.colorSpace = SRGBColorSpace`.
40783		 *
40784		 * @type {?Texture}
40785		 * @default null
40786		 */
40787		this.emissiveMap = null;
40788
40789		/**
40790		 * The texture to create a bump map. The black and white values map to the
40791		 * perceived depth in relation to the lights. Bump doesn't actually affect
40792		 * the geometry of the object, only the lighting. If a normal map is defined
40793		 * this will be ignored.
40794		 *
40795		 * `bumpMap` represents non-color data. Any texture assigned must have
40796		 * `texture.colorSpace = NoColorSpace` (default).
40797		 *
40798		 * @type {?Texture}
40799		 * @default null
40800		 */
40801		this.bumpMap = null;
40802
40803		/**
40804		 * How much the bump map affects the material. Typical range is `[0,1]`.
40805		 *
40806		 * @type {number}
40807		 * @default 1
40808		 */
40809		this.bumpScale = 1;
40810
40811		/**
40812		 * The texture to create a normal map. The RGB values affect the surface
40813		 * normal for each pixel fragment and change the way the color is lit. Normal
40814		 * maps do not change the actual shape of the surface, only the lighting. In
40815		 * case the material has a normal map authored using the left handed
40816		 * convention, the `y` component of `normalScale` should be negated to compensate
40817		 * for the different handedness.
40818		 *
40819		 * `normalMap` represents non-color data. Any texture assigned must have
40820		 * `texture.colorSpace = NoColorSpace` (default).
40821		 *
40822		 * @type {?Texture}
40823		 * @default null
40824		 */
40825		this.normalMap = null;
40826
40827		/**
40828		 * The type of normal map.
40829		 *
40830		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
40831		 * @default TangentSpaceNormalMap
40832		 */
40833		this.normalMapType = TangentSpaceNormalMap;
40834
40835		/**
40836		 * How much the normal map affects the material. Typical value range is `[0,1]`.
40837		 *
40838		 * @type {Vector2}
40839		 * @default (1,1)
40840		 */
40841		this.normalScale = new Vector2( 1, 1 );
40842
40843		/**
40844		 * The displacement map affects the position of the mesh's vertices. Unlike
40845		 * other maps which only affect the light and shade of the material the
40846		 * displaced vertices can cast shadows, block other objects, and otherwise
40847		 * act as real geometry. The displacement texture is an image where the value
40848		 * of each pixel (white being the highest) is mapped against, and
40849		 * repositions, the vertices of the mesh. For best results, pair a
40850		 * displacement map with a matching normal map, since the renderer can
40851		 * not recompute surface normals from the displaced vertices.
40852		 *
40853		 * `displacementMap` represents non-color data. Any texture assigned must have
40854		 * `texture.colorSpace = NoColorSpace` (default).
40855		 *
40856		 * @type {?Texture}
40857		 * @default null
40858		 */
40859		this.displacementMap = null;
40860
40861		/**
40862		 * How much the displacement map affects the mesh (where black is no
40863		 * displacement, and white is maximum displacement). Without a displacement
40864		 * map set, this value is not applied.
40865		 *
40866		 * @type {number}
40867		 * @default 0
40868		 */
40869		this.displacementScale = 1;
40870
40871		/**
40872		 * The offset of the displacement map's values on the mesh's vertices.
40873		 * The bias is added to the scaled sample of the displacement map.
40874		 * Without a displacement map set, this value is not applied.
40875		 *
40876		 * @type {number}
40877		 * @default 0
40878		 */
40879		this.displacementBias = 0;
40880
40881		/**
40882		 * Specular map used by the material.
40883		 *
40884		 * `specularMap` represents color data, and the texture must be assigned a
40885		 * {@link Texture#colorSpace}. Most `specularMap` textures set
40886		 * `texture.colorSpace = SRGBColorSpace`.
40887		 *
40888		 * @type {?Texture}
40889		 * @default null
40890		 */
40891		this.specularMap = null;
40892
40893		/**
40894		 * The alpha map is a grayscale texture that controls the opacity across the
40895		 * surface (black: fully transparent; white: fully opaque).
40896		 *
40897		 * Only the color of the texture is used, ignoring the alpha channel if one
40898		 * exists. For RGB and RGBA textures, the renderer will use the green channel
40899		 * when sampling this texture due to the extra bit of precision provided for
40900		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
40901		 * luminance/alpha textures will also still work as expected.
40902		 *
40903		 * `alphaMap` represents non-color data. Any texture assigned must have
40904		 * `texture.colorSpace = NoColorSpace` (default).
40905		 *
40906		 * @type {?Texture}
40907		 * @default null
40908		 */
40909		this.alphaMap = null;
40910
40911		/**
40912		 * The environment map.
40913		 *
40914		 * `envMap` represents luminance data, and the texture must be assigned
40915		 * a {@link Texture#colorSpace}. Most `envMap` textures set
40916		 * `texture.colorSpace = LinearSRGBColorSpace` and use float-type formats
40917		 * such as `.exr` or `.hdr`.
40918		 *
40919		 * @type {?Texture}
40920		 * @default null
40921		 */
40922		this.envMap = null;
40923
40924		/**
40925		 * The rotation of the environment map in radians.
40926		 *
40927		 * @type {Euler}
40928		 * @default (0,0,0)
40929		 */
40930		this.envMapRotation = new Euler();
40931
40932		/**
40933		 * How to combine the result of the surface's color with the environment map, if any.
40934		 *
40935		 * When set to `MixOperation`, the {@link MeshBasicMaterial#reflectivity} is used to
40936		 * blend between the two colors.
40937		 *
40938		 * @type {(MultiplyOperation|MixOperation|AddOperation)}
40939		 * @default MultiplyOperation
40940		 */
40941		this.combine = MultiplyOperation;
40942
40943		/**
40944		 * How much the environment map affects the surface.
40945		 * The valid range is between `0` (no reflections) and `1` (full reflections).
40946		 *
40947		 * @type {number}
40948		 * @default 1
40949		 */
40950		this.reflectivity = 1;
40951
40952		/**
40953		 * Scales the effect of the environment map by multiplying its color.
40954		 *
40955		 * @type {number}
40956		 * @default 1
40957		 */
40958		this.envMapIntensity = 1.0;
40959
40960		/**
40961		 * The index of refraction (IOR) of air (approximately 1) divided by the
40962		 * index of refraction of the material. It is used with environment mapping
40963		 * modes {@link CubeRefractionMapping} and {@link EquirectangularRefractionMapping}.
40964		 * The refraction ratio should not exceed `1`.
40965		 *
40966		 * @type {number}
40967		 * @default 0.98
40968		 */
40969		this.refractionRatio = 0.98;
40970
40971		/**
40972		 * Renders the geometry as a wireframe.
40973		 *
40974		 * @type {boolean}
40975		 * @default false
40976		 */
40977		this.wireframe = false;
40978
40979		/**
40980		 * Controls the thickness of the wireframe.
40981		 *
40982		 * Can only be used with {@link SVGRenderer}.
40983		 *
40984		 * @type {number}
40985		 * @default 1
40986		 */
40987		this.wireframeLinewidth = 1;
40988
40989		/**
40990		 * Defines appearance of wireframe ends.
40991		 *
40992		 * Can only be used with {@link SVGRenderer}.
40993		 *
40994		 * @type {('round'|'bevel'|'miter')}
40995		 * @default 'round'
40996		 */
40997		this.wireframeLinecap = 'round';
40998
40999		/**
41000		 * Defines appearance of wireframe joints.
41001		 *
41002		 * Can only be used with {@link SVGRenderer}.
41003		 *
41004		 * @type {('round'|'bevel'|'miter')}
41005		 * @default 'round'
41006		 */
41007		this.wireframeLinejoin = 'round';
41008
41009		/**
41010		 * Whether the material is rendered with flat shading or not.
41011		 *
41012		 * @type {boolean}
41013		 * @default false
41014		 */
41015		this.flatShading = false;
41016
41017		/**
41018		 * Whether the material is affected by fog or not.
41019		 *
41020		 * @type {boolean}
41021		 * @default true
41022		 */
41023		this.fog = true;
41024
41025		this.setValues( parameters );
41026
41027	}
41028
41029	copy( source ) {
41030
41031		super.copy( source );
41032
41033		this.color.copy( source.color );
41034
41035		this.map = source.map;
41036
41037		this.lightMap = source.lightMap;
41038		this.lightMapIntensity = source.lightMapIntensity;
41039
41040		this.aoMap = source.aoMap;
41041		this.aoMapIntensity = source.aoMapIntensity;
41042
41043		this.emissive.copy( source.emissive );
41044		this.emissiveMap = source.emissiveMap;
41045		this.emissiveIntensity = source.emissiveIntensity;
41046
41047		this.bumpMap = source.bumpMap;
41048		this.bumpScale = source.bumpScale;
41049
41050		this.normalMap = source.normalMap;
41051		this.normalMapType = source.normalMapType;
41052		this.normalScale.copy( source.normalScale );
41053
41054		this.displacementMap = source.displacementMap;
41055		this.displacementScale = source.displacementScale;
41056		this.displacementBias = source.displacementBias;
41057
41058		this.specularMap = source.specularMap;
41059
41060		this.alphaMap = source.alphaMap;
41061
41062		this.envMap = source.envMap;
41063		this.envMapRotation.copy( source.envMapRotation );
41064		this.combine = source.combine;
41065		this.reflectivity = source.reflectivity;
41066		this.envMapIntensity = source.envMapIntensity;
41067		this.refractionRatio = source.refractionRatio;
41068
41069		this.wireframe = source.wireframe;
41070		this.wireframeLinewidth = source.wireframeLinewidth;
41071		this.wireframeLinecap = source.wireframeLinecap;
41072		this.wireframeLinejoin = source.wireframeLinejoin;
41073
41074		this.flatShading = source.flatShading;
41075
41076		this.fog = source.fog;
41077
41078		return this;
41079
41080	}
41081
41082}
41083
41084/**
41085 * A material for drawing geometry by depth. Depth is based off of the camera
41086 * near and far plane. White is nearest, black is farthest.
41087 *
41088 * @augments Material
41089 * @demo scenes/material-browser.html#MeshDepthMaterial
41090 */
41091class MeshDepthMaterial extends Material {
41092
41093	/**
41094	 * Constructs a new mesh depth material.
41095	 *
41096	 * @param {Object} [parameters] - An object with one or more properties
41097	 * defining the material's appearance. Any property of the material
41098	 * (including any property from inherited materials) can be passed
41099	 * in here. Color values can be passed any type of value accepted
41100	 * by {@link Color#set}.
41101	 */
41102	constructor( parameters ) {
41103
41104		super();
41105
41106		/**
41107		 * This flag can be used for type testing.
41108		 *
41109		 * @type {boolean}
41110		 * @readonly
41111		 * @default true
41112		 */
41113		this.isMeshDepthMaterial = true;
41114
41115		this.type = 'MeshDepthMaterial';
41116
41117		/**
41118		 * Type for depth packing.
41119		 *
41120		 * @type {(BasicDepthPacking|RGBADepthPacking|RGBDepthPacking|RGDepthPacking)}
41121		 * @default BasicDepthPacking
41122		 */
41123		this.depthPacking = BasicDepthPacking;
41124
41125		/**
41126		 * The color map. May optionally include an alpha channel, typically combined
41127		 * with {@link Material#transparent} or {@link Material#alphaTest}.
41128		 *
41129		 * `map` represents color data, and the texture must be assigned a
41130		 * {@link Texture#colorSpace}. Most `map` textures set
41131		 * `texture.colorSpace = SRGBColorSpace`.
41132		 *
41133		 * @type {?Texture}
41134		 * @default null
41135		 */
41136		this.map = null;
41137
41138		/**
41139		 * The alpha map is a grayscale texture that controls the opacity across the
41140		 * surface (black: fully transparent; white: fully opaque).
41141		 *
41142		 * Only the color of the texture is used, ignoring the alpha channel if one
41143		 * exists. For RGB and RGBA textures, the renderer will use the green channel
41144		 * when sampling this texture due to the extra bit of precision provided for
41145		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
41146		 * luminance/alpha textures will also still work as expected.
41147		 *
41148		 * `alphaMap` represents non-color data. Any texture assigned must have
41149		 * `texture.colorSpace = NoColorSpace` (default).
41150		 *
41151		 * @type {?Texture}
41152		 * @default null
41153		 */
41154		this.alphaMap = null;
41155
41156		/**
41157		 * The displacement map affects the position of the mesh's vertices. Unlike
41158		 * other maps which only affect the light and shade of the material the
41159		 * displaced vertices can cast shadows, block other objects, and otherwise
41160		 * act as real geometry. The displacement texture is an image where the value
41161		 * of each pixel (white being the highest) is mapped against, and
41162		 * repositions, the vertices of the mesh.
41163		 *
41164		 * `displacementMap` represents non-color data. Any texture assigned must have
41165		 * `texture.colorSpace = NoColorSpace` (default).
41166		 *
41167		 * @type {?Texture}
41168		 * @default null
41169		 */
41170		this.displacementMap = null;
41171
41172		/**
41173		 * How much the displacement map affects the mesh (where black is no
41174		 * displacement, and white is maximum displacement). Without a displacement
41175		 * map set, this value is not applied.
41176		 *
41177		 * @type {number}
41178		 * @default 0
41179		 */
41180		this.displacementScale = 1;
41181
41182		/**
41183		 * The offset of the displacement map's values on the mesh's vertices.
41184		 * The bias is added to the scaled sample of the displacement map.
41185		 * Without a displacement map set, this value is not applied.
41186		 *
41187		 * @type {number}
41188		 * @default 0
41189		 */
41190		this.displacementBias = 0;
41191
41192		/**
41193		 * Renders the geometry as a wireframe.
41194		 *
41195		 * @type {boolean}
41196		 * @default false
41197		 */
41198		this.wireframe = false;
41199
41200		/**
41201		 * Controls the thickness of the wireframe.
41202		 *
41203		 * WebGL and WebGPU ignore this property and always render
41204		 * 1 pixel wide lines.
41205		 *
41206		 * @type {number}
41207		 * @default 1
41208		 */
41209		this.wireframeLinewidth = 1;
41210
41211		this.setValues( parameters );
41212
41213	}
41214
41215	copy( source ) {
41216
41217		super.copy( source );
41218
41219		this.depthPacking = source.depthPacking;
41220
41221		this.map = source.map;
41222
41223		this.alphaMap = source.alphaMap;
41224
41225		this.displacementMap = source.displacementMap;
41226		this.displacementScale = source.displacementScale;
41227		this.displacementBias = source.displacementBias;
41228
41229		this.wireframe = source.wireframe;
41230		this.wireframeLinewidth = source.wireframeLinewidth;
41231
41232		return this;
41233
41234	}
41235
41236}
41237
41238/**
41239 * A material used internally for implementing shadow mapping with
41240 * point lights.
41241 *
41242 * Can also be used to customize the shadow casting of an object by assigning
41243 * an instance of `MeshDistanceMaterial` to {@link Object3D#customDistanceMaterial}.
41244 * The following examples demonstrates this approach in order to ensure
41245 * transparent parts of objects do not cast shadows.
41246 *
41247 * @augments Material
41248 */
41249class MeshDistanceMaterial extends Material {
41250
41251	/**
41252	 * Constructs a new mesh distance material.
41253	 *
41254	 * @param {Object} [parameters] - An object with one or more properties
41255	 * defining the material's appearance. Any property of the material
41256	 * (including any property from inherited materials) can be passed
41257	 * in here. Color values can be passed any type of value accepted
41258	 * by {@link Color#set}.
41259	 */
41260	constructor( parameters ) {
41261
41262		super();
41263
41264		/**
41265		 * This flag can be used for type testing.
41266		 *
41267		 * @type {boolean}
41268		 * @readonly
41269		 * @default true
41270		 */
41271		this.isMeshDistanceMaterial = true;
41272
41273		this.type = 'MeshDistanceMaterial';
41274
41275		/**
41276		 * The color map. May optionally include an alpha channel, typically combined
41277		 * with {@link Material#transparent} or {@link Material#alphaTest}.
41278		 *
41279		 * `map` represents color data, and the texture must be assigned a
41280		 * {@link Texture#colorSpace}. Most `map` textures set
41281		 * `texture.colorSpace = SRGBColorSpace`.
41282		 *
41283		 * @type {?Texture}
41284		 * @default null
41285		 */
41286		this.map = null;
41287
41288		/**
41289		 * The alpha map is a grayscale texture that controls the opacity across the
41290		 * surface (black: fully transparent; white: fully opaque).
41291		 *
41292		 * Only the color of the texture is used, ignoring the alpha channel if one
41293		 * exists. For RGB and RGBA textures, the renderer will use the green channel
41294		 * when sampling this texture due to the extra bit of precision provided for
41295		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
41296		 * luminance/alpha textures will also still work as expected.
41297		 *
41298		 * `alphaMap` represents non-color data. Any texture assigned must have
41299		 * `texture.colorSpace = NoColorSpace` (default).
41300		 *
41301		 * @type {?Texture}
41302		 * @default null
41303		 */
41304		this.alphaMap = null;
41305
41306		/**
41307		 * The displacement map affects the position of the mesh's vertices. Unlike
41308		 * other maps which only affect the light and shade of the material the
41309		 * displaced vertices can cast shadows, block other objects, and otherwise
41310		 * act as real geometry. The displacement texture is an image where the value
41311		 * of each pixel (white being the highest) is mapped against, and
41312		 * repositions, the vertices of the mesh.
41313		 *
41314		 * `displacementMap` represents non-color data. Any texture assigned must have
41315		 * `texture.colorSpace = NoColorSpace` (default).
41316		 *
41317		 * @type {?Texture}
41318		 * @default null
41319		 */
41320		this.displacementMap = null;
41321
41322		/**
41323		 * How much the displacement map affects the mesh (where black is no
41324		 * displacement, and white is maximum displacement). Without a displacement
41325		 * map set, this value is not applied.
41326		 *
41327		 * @type {number}
41328		 * @default 0
41329		 */
41330		this.displacementScale = 1;
41331
41332		/**
41333		 * The offset of the displacement map's values on the mesh's vertices.
41334		 * The bias is added to the scaled sample of the displacement map.
41335		 * Without a displacement map set, this value is not applied.
41336		 *
41337		 * @type {number}
41338		 * @default 0
41339		 */
41340		this.displacementBias = 0;
41341
41342		this.setValues( parameters );
41343
41344	}
41345
41346	copy( source ) {
41347
41348		super.copy( source );
41349
41350		this.map = source.map;
41351
41352		this.alphaMap = source.alphaMap;
41353
41354		this.displacementMap = source.displacementMap;
41355		this.displacementScale = source.displacementScale;
41356		this.displacementBias = source.displacementBias;
41357
41358		return this;
41359
41360	}
41361
41362}
41363
41364/**
41365 * This material is defined by a MatCap (or Lit Sphere) texture, which encodes the
41366 * material color and shading.
41367 *
41368 * `MeshMatcapMaterial` does not respond to lights since the matcap image file encodes
41369 * baked lighting. It will cast a shadow onto an object that receives shadows
41370 * (and shadow clipping works), but it will not self-shadow or receive
41371 * shadows.
41372 *
41373 * @augments Material
41374 * @demo scenes/material-browser.html#MeshMatcapMaterial
41375 */
41376class MeshMatcapMaterial extends Material {
41377
41378	/**
41379	 * Constructs a new mesh matcap material.
41380	 *
41381	 * @param {Object} [parameters] - An object with one or more properties
41382	 * defining the material's appearance. Any property of the material
41383	 * (including any property from inherited materials) can be passed
41384	 * in here. Color values can be passed any type of value accepted
41385	 * by {@link Color#set}.
41386	 */
41387	constructor( parameters ) {
41388
41389		super();
41390
41391		/**
41392		 * This flag can be used for type testing.
41393		 *
41394		 * @type {boolean}
41395		 * @readonly
41396		 * @default true
41397		 */
41398		this.isMeshMatcapMaterial = true;
41399
41400		this.defines = { 'MATCAP': '' };
41401
41402		this.type = 'MeshMatcapMaterial';
41403
41404		/**
41405		 * Color of the material.
41406		 *
41407		 * @type {Color}
41408		 * @default (1,1,1)
41409		 */
41410		this.color = new Color( 0xffffff ); // diffuse
41411
41412		/**
41413		 * The matcap map.
41414		 *
41415		 * `matcap` represents luminance data, and the texture must be assigned
41416		 * a {@link Texture#colorSpace}. HDR `matcap` textures (e.g. `.exr`)
41417		 * typically set `texture.colorSpace = LinearSRGBColorSpace`, while LDR
41418		 * `matcap` textures (e.g. `.png`, `.jpg`, `.webp`) typically set
41419		 * `texture.colorSpace = SRGBColorSpace`.
41420		 *
41421		 * @type {?Texture}
41422		 * @default null
41423		 */
41424		this.matcap = null;
41425
41426		/**
41427		 * The color map. May optionally include an alpha channel, typically combined
41428		 * with {@link Material#transparent} or {@link Material#alphaTest}. The texture map
41429		 * color is modulated by the diffuse `color`.
41430		 *
41431		 * `map` represents color data, and the texture must be assigned a
41432		 * {@link Texture#colorSpace}. Most `map` textures set
41433		 * `texture.colorSpace = SRGBColorSpace`.
41434		 *
41435		 * @type {?Texture}
41436		 * @default null
41437		 */
41438		this.map = null;
41439
41440		/**
41441		 * The texture to create a bump map. The black and white values map to the
41442		 * perceived depth in relation to the lights. Bump doesn't actually affect
41443		 * the geometry of the object, only the lighting. If a normal map is defined
41444		 * this will be ignored.
41445		 *
41446		 * `bumpMap` represents non-color data. Any texture assigned must have
41447		 * `texture.colorSpace = NoColorSpace` (default).
41448		 *
41449		 * @type {?Texture}
41450		 * @default null
41451		 */
41452		this.bumpMap = null;
41453
41454		/**
41455		 * How much the bump map affects the material. Typical range is `[0,1]`.
41456		 *
41457		 * @type {number}
41458		 * @default 1
41459		 */
41460		this.bumpScale = 1;
41461
41462		/**
41463		 * The texture to create a normal map. The RGB values affect the surface
41464		 * normal for each pixel fragment and change the way the color is lit. Normal
41465		 * maps do not change the actual shape of the surface, only the lighting. In
41466		 * case the material has a normal map authored using the left handed
41467		 * convention, the `y` component of `normalScale` should be negated to compensate
41468		 * for the different handedness.
41469		 *
41470		 * `normalMap` represents non-color data. Any texture assigned must have
41471		 * `texture.colorSpace = NoColorSpace` (default).
41472		 *
41473		 * @type {?Texture}
41474		 * @default null
41475		 */
41476		this.normalMap = null;
41477
41478		/**
41479		 * The type of normal map.
41480		 *
41481		 * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
41482		 * @default TangentSpaceNormalMap
41483		 */
41484		this.normalMapType = TangentSpaceNormalMap;
41485
41486		/**
41487		 * How much the normal map affects the material. Typical value range is `[0,1]`.
41488		 *
41489		 * @type {Vector2}
41490		 * @default (1,1)
41491		 */
41492		this.normalScale = new Vector2( 1, 1 );
41493
41494		/**
41495		 * The displacement map affects the position of the mesh's vertices. Unlike
41496		 * other maps which only affect the light and shade of the material the
41497		 * displaced vertices can cast shadows, block other objects, and otherwise
41498		 * act as real geometry. The displacement texture is an image where the value
41499		 * of each pixel (white being the highest) is mapped against, and
41500		 * repositions, the vertices of the mesh. For best results, pair a
41501		 * displacement map with a matching normal map, since the renderer can
41502		 * not recompute surface normals from the displaced vertices.
41503		 *
41504		 * `displacementMap` represents non-color data. Any texture assigned must have
41505		 * `texture.colorSpace = NoColorSpace` (default).
41506		 *
41507		 * @type {?Texture}
41508		 * @default null
41509		 */
41510		this.displacementMap = null;
41511
41512		/**
41513		 * How much the displacement map affects the mesh (where black is no
41514		 * displacement, and white is maximum displacement). Without a displacement
41515		 * map set, this value is not applied.
41516		 *
41517		 * @type {number}
41518		 * @default 0
41519		 */
41520		this.displacementScale = 1;
41521
41522		/**
41523		 * The offset of the displacement map's values on the mesh's vertices.
41524		 * The bias is added to the scaled sample of the displacement map.
41525		 * Without a displacement map set, this value is not applied.
41526		 *
41527		 * @type {number}
41528		 * @default 0
41529		 */
41530		this.displacementBias = 0;
41531
41532		/**
41533		 * The alpha map is a grayscale texture that controls the opacity across the
41534		 * surface (black: fully transparent; white: fully opaque).
41535		 *
41536		 * Only the color of the texture is used, ignoring the alpha channel if one
41537		 * exists. For RGB and RGBA textures, the renderer will use the green channel
41538		 * when sampling this texture due to the extra bit of precision provided for
41539		 * green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
41540		 * luminance/alpha textures will also still work as expected.
41541		 *
41542		 * `alphaMap` represents non-color data. Any texture assigned must have
41543		 * `texture.colorSpace = NoColorSpace` (default).
41544		 *
41545		 * @type {?Texture}
41546		 * @default null
41547		 */
41548		this.alphaMap = null;
41549
41550		/**
41551		 * Renders the geometry as a wireframe.
41552		 *
41553		 * @type {boolean}
41554		 * @default false
41555		 */
41556		this.wireframe = false;
41557
41558		/**
41559		 * Controls the thickness of the wireframe.
41560		 *
41561		 * Can only be used with {@link SVGRenderer}.
41562		 *
41563		 * @type {number}
41564		 * @default 1
41565		 */
41566		this.wireframeLinewidth = 1;
41567
41568		/**
41569		 * Whether the material is rendered with flat shading or not.
41570		 *
41571		 * @type {boolean}
41572		 * @default false
41573		 */
41574		this.flatShading = false;
41575
41576		/**
41577		 * Whether the material is affected by fog or not.
41578		 *
41579		 * @type {boolean}
41580		 * @default true
41581		 */
41582		this.fog = true;
41583
41584		this.setValues( parameters );
41585
41586	}
41587
41588
41589	copy( source ) {
41590
41591		super.copy( source );
41592
41593		this.defines = { 'MATCAP': '' };
41594
41595		this.color.copy( source.color );
41596
41597		this.matcap = source.matcap;
41598
41599		this.map = source.map;
41600
41601		this.bumpMap = source.bumpMap;
41602		this.bumpScale = source.bumpScale;
41603
41604		this.normalMap = source.normalMap;
41605		this.normalMapType = source.normalMapType;
41606		this.normalScale.copy( source.normalScale );
41607
41608		this.displacementMap = source.displacementMap;
41609		this.displacementScale = source.displacementScale;
41610		this.displacementBias = source.displacementBias;
41611
41612		this.alphaMap = source.alphaMap;
41613
41614		this.wireframe = source.wireframe;
41615		this.wireframeLinewidth = source.wireframeLinewidth;
41616
41617		this.flatShading = source.flatShading;
41618
41619		this.fog = source.fog;
41620
41621		return this;
41622
41623	}
41624
41625}
41626
41627/**
41628 * A material for rendering line primitives.
41629 *
41630 * Materials define the appearance of renderable 3D objects.
41631 *
41632 * ```js
41633 * const material = new THREE.LineDashedMaterial( {
41634 * 	color: 0xffffff,
41635 * 	scale: 1,
41636 * 	dashSize: 3,
41637 * 	gapSize: 1,
41638 * } );
41639 * ```
41640 *
41641 * @augments LineBasicMaterial
41642 */
41643class LineDashedMaterial extends LineBasicMaterial {
41644
41645	/**
41646	 * Constructs a new line dashed material.
41647	 *
41648	 * @param {Object} [parameters] - An object with one or more properties
41649	 * defining the material's appearance. Any property of the material
41650	 * (including any property from inherited materials) can be passed
41651	 * in here. Color values can be passed any type of value accepted
41652	 * by {@link Color#set}.
41653	 */
41654	constructor( parameters ) {
41655
41656		super();
41657
41658		/**
41659		 * This flag can be used for type testing.
41660		 *
41661		 * @type {boolean}
41662		 * @readonly
41663		 * @default true
41664		 */
41665		this.isLineDashedMaterial = true;
41666		this.type = 'LineDashedMaterial';
41667
41668		/**
41669		 * The scale of the dashed part of a line.
41670		 *
41671		 * @type {number}
41672		 * @default 1
41673		 */
41674		this.scale = 1;
41675
41676		/**
41677		 * The size of the dash. This is both the gap with the stroke.
41678		 *
41679		 * @type {number}
41680		 * @default 3
41681		 */
41682		this.dashSize = 3;
41683
41684		/**
41685		 * The size of the gap.
41686		 *
41687		 * @type {number}
41688		 * @default 1
41689		 */
41690		this.gapSize = 1;
41691
41692		this.setValues( parameters );
41693
41694	}
41695
41696	copy( source ) {
41697
41698		super.copy( source );
41699
41700		this.scale = source.scale;
41701		this.dashSize = source.dashSize;
41702		this.gapSize = source.gapSize;
41703
41704		return this;
41705
41706	}
41707
41708}
41709
41710/**
41711 * Converts an array to a specific type.
41712 *
41713 * @param {TypedArray|Array} array - The array to convert.
41714 * @param {TypedArray.constructor} type - The constructor of a typed array that defines the new type.
41715 * @return {TypedArray} The converted array.
41716 */
41717function convertArray( array, type ) {
41718
41719	if ( ! array || array.constructor === type ) return array;
41720
41721	if ( typeof type.BYTES_PER_ELEMENT === 'number' ) {
41722
41723		return new type( array ); // create typed array
41724
41725	}
41726
41727	return Array.prototype.slice.call( array ); // create Array
41728
41729}
41730
41731/**
41732 * Returns `true` if the given keyframe track settings hold Bezier tangent data.
41733 *
41734 * @param {?Object} settings - The settings of a keyframe track.
41735 * @return {boolean} Whether both tangent arrays are defined or not.
41736 */
41737function hasTangents( settings ) {
41738
41739	return settings !== undefined && settings.inTangents !== undefined && settings.outTangents !== undefined;
41740
41741}
41742
41743/**
41744 * Returns an array by which times and values can be sorted.
41745 *
41746 * @param {Array<number>} times - The keyframe time values.
41747 * @return {Array<number>} The array.
41748 */
41749function getKeyframeOrder( times ) {
41750
41751	function compareTime( i, j ) {
41752
41753		return times[ i ] - times[ j ];
41754
41755	}
41756
41757	const n = times.length;
41758	const result = new Array( n );
41759	for ( let i = 0; i !== n; ++ i ) result[ i ] = i;
41760
41761	result.sort( compareTime );
41762
41763	return result;
41764
41765}
41766
41767/**
41768 * Sorts the given array by the previously computed order via `getKeyframeOrder()`.
41769 *
41770 * @param {Array<number>} values - The values to sort.
41771 * @param {number} stride - The stride.
41772 * @param {Array<number>} order - The sort order.
41773 * @return {Array<number>} The sorted values.
41774 */
41775function sortedArray( values, stride, order ) {
41776
41777	const nValues = values.length;
41778	const result = new values.constructor( nValues );
41779
41780	for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {
41781
41782		const srcOffset = order[ i ] * stride;
41783
41784		for ( let j = 0; j !== stride; ++ j ) {
41785
41786			result[ dstOffset ++ ] = values[ srcOffset + j ];
41787
41788		}
41789
41790	}
41791
41792	return result;
41793
41794}
41795
41796/**
41797 * Used for parsing AOS keyframe formats.
41798 *
41799 * @param {Array<number>} jsonKeys - A list of JSON keyframes.
41800 * @param {Array<number>} times - This array will be filled with keyframe times by this function.
41801 * @param {Array<number>} values - This array will be filled with keyframe values by this function.
41802 * @param {string} valuePropertyName - The name of the property to use.
41803 */
41804function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
41805
41806	let i = 1, key = jsonKeys[ 0 ];
41807
41808	while ( key !== undefined && key[ valuePropertyName ] === undefined ) {
41809
41810		key = jsonKeys[ i ++ ];
41811
41812	}
41813
41814	if ( key === undefined ) return; // no data
41815
41816	let value = key[ valuePropertyName ];
41817	if ( value === undefined ) return; // no data
41818
41819	if ( Array.isArray( value ) ) {
41820
41821		do {
41822
41823			value = key[ valuePropertyName ];
41824
41825			if ( value !== undefined ) {
41826
41827				times.push( key.time );
41828				values.push( ...value ); // push all elements
41829
41830			}
41831
41832			key = jsonKeys[ i ++ ];
41833
41834		} while ( key !== undefined );
41835
41836	} else if ( value.toArray !== undefined ) {
41837
41838		// ...assume THREE.Math-ish
41839
41840		do {
41841
41842			value = key[ valuePropertyName ];
41843
41844			if ( value !== undefined ) {
41845
41846				times.push( key.time );
41847				value.toArray( values, values.length );
41848
41849			}
41850
41851			key = jsonKeys[ i ++ ];
41852
41853		} while ( key !== undefined );
41854
41855	} else {
41856
41857		// otherwise push as-is
41858
41859		do {
41860
41861			value = key[ valuePropertyName ];
41862
41863			if ( value !== undefined ) {
41864
41865				times.push( key.time );
41866				values.push( value );
41867
41868			}
41869
41870			key = jsonKeys[ i ++ ];
41871
41872		} while ( key !== undefined );
41873
41874	}
41875
41876}
41877
41878/**
41879 * Creates a new clip, containing only the segment of the original clip between the given frames.
41880 *
41881 * @param {AnimationClip} sourceClip - The values to sort.
41882 * @param {string} name - The name of the clip.
41883 * @param {number} startFrame - The start frame.
41884 * @param {number} endFrame - The end frame.
41885 * @param {number} [fps=30] - The FPS.
41886 * @return {AnimationClip} The new sub clip.
41887 */
41888function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
41889
41890	const clip = sourceClip.clone();
41891
41892	clip.name = name;
41893
41894	const tracks = [];
41895
41896	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41897
41898		const track = clip.tracks[ i ];
41899		const valueSize = track.getValueSize();
41900
41901		const times = [];
41902		const values = [];
41903
41904		for ( let j = 0; j < track.times.length; ++ j ) {
41905
41906			const frame = track.times[ j ] * fps;
41907
41908			if ( frame < startFrame || frame >= endFrame ) continue;
41909
41910			times.push( track.times[ j ] );
41911
41912			for ( let k = 0; k < valueSize; ++ k ) {
41913
41914				values.push( track.values[ j * valueSize + k ] );
41915
41916			}
41917
41918		}
41919
41920		if ( times.length === 0 ) continue;
41921
41922		track.times = convertArray( times, track.times.constructor );
41923		track.values = convertArray( values, track.values.constructor );
41924
41925		tracks.push( track );
41926
41927	}
41928
41929	clip.tracks = tracks;
41930
41931	// find minimum .times value across all tracks in the trimmed clip
41932
41933	let minStartTime = Infinity;
41934
41935	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41936
41937		if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {
41938
41939			minStartTime = clip.tracks[ i ].times[ 0 ];
41940
41941		}
41942
41943	}
41944
41945	// shift all tracks such that clip begins at t=0
41946
41947	for ( let i = 0; i < clip.tracks.length; ++ i ) {
41948
41949		clip.tracks[ i ].shift( -1 * minStartTime );
41950
41951	}
41952
41953	clip.resetDuration();
41954
41955	return clip;
41956
41957}
41958
41959/**
41960 * Converts the keyframes of the given animation clip to an additive format.
41961 *
41962 * @param {AnimationClip} targetClip - The clip to make additive.
41963 * @param {number} [referenceFrame=0] - The reference frame.
41964 * @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
41965 * @param {number} [fps=30] - The FPS.
41966 * @return {AnimationClip} The updated clip which is now additive.
41967 */
41968function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
41969
41970	if ( fps <= 0 ) fps = 30;
41971
41972	const numTracks = referenceClip.tracks.length;
41973	const referenceTime = referenceFrame / fps;
41974
41975	// Make each track's values relative to the values at the reference frame
41976	for ( let i = 0; i < numTracks; ++ i ) {
41977
41978		const referenceTrack = referenceClip.tracks[ i ];
41979		const referenceTrackType = referenceTrack.ValueTypeName;
41980
41981		// Skip this track if it's non-numeric
41982		if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue;
41983
41984		// Find the track in the target clip whose name and type matches the reference track
41985		const targetTrack = targetClip.tracks.find( function ( track ) {
41986
41987			return track.name === referenceTrack.name
41988				&& track.ValueTypeName === referenceTrackType;
41989
41990		} );
41991
41992		if ( targetTrack === undefined ) continue;
41993
41994		let referenceOffset = 0;
41995		const referenceValueSize = referenceTrack.getValueSize();
41996
41997		if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
41998
41999			referenceOffset = referenceValueSize / 3;
42000
42001		}
42002
42003		let targetOffset = 0;
42004		const targetValueSize = targetTrack.getValueSize();
42005
42006		if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
42007
42008			targetOffset = targetValueSize / 3;
42009
42010		}
42011
42012		const lastIndex = referenceTrack.times.length - 1;
42013		let referenceValue;
42014
42015		// Find the value to subtract out of the track
42016		if ( referenceTime <= referenceTrack.times[ 0 ] ) {
42017
42018			// Reference frame is earlier than the first keyframe, so just use the first keyframe
42019			const startIndex = referenceOffset;
42020			const endIndex = referenceValueSize - referenceOffset;
42021			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
42022
42023		} else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
42024
42025			// Reference frame is after the last keyframe, so just use the last keyframe
42026			const startIndex = lastIndex * referenceValueSize + referenceOffset;
42027			const endIndex = startIndex + referenceValueSize - referenceOffset;
42028			referenceValue = referenceTrack.values.slice( startIndex, endIndex );
42029
42030		} else {
42031
42032			// Interpolate to the reference value
42033			const interpolant = referenceTrack.createInterpolant();
42034			const startIndex = referenceOffset;
42035			const endIndex = referenceValueSize - referenceOffset;
42036			interpolant.evaluate( referenceTime );
42037			referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex );
42038
42039		}
42040
42041		// Conjugate the quaternion
42042		if ( referenceTrackType === 'quaternion' ) {
42043
42044			const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate();
42045			referenceQuat.toArray( referenceValue );
42046
42047		}
42048
42049		// Subtract the reference value from all of the track values
42050
42051		const numTimes = targetTrack.times.length;
42052		for ( let j = 0; j < numTimes; ++ j ) {
42053
42054			const valueStart = j * targetValueSize + targetOffset;
42055
42056			if ( referenceTrackType === 'quaternion' ) {
42057
42058				// Multiply the conjugate for quaternion track types
42059				Quaternion.multiplyQuaternionsFlat(
42060					targetTrack.values,
42061					valueStart,
42062					referenceValue,
42063					0,
42064					targetTrack.values,
42065					valueStart
42066				);
42067
42068			} else {
42069
42070				const valueEnd = targetValueSize - targetOffset * 2;
42071
42072				// Subtract each value for all other numeric track types
42073				for ( let k = 0; k < valueEnd; ++ k ) {
42074
42075					targetTrack.values[ valueStart + k ] -= referenceValue[ k ];
42076
42077				}
42078
42079			}
42080
42081		}
42082
42083	}
42084
42085	targetClip.blendMode = AdditiveAnimationBlendMode;
42086
42087	return targetClip;
42088
42089}
42090
42091/**
42092 * A class with various methods to assist with animations.
42093 *
42094 * @hideconstructor
42095 */
42096class AnimationUtils {
42097
42098	/**
42099	 * Converts an array to a specific type
42100	 *
42101	 * @static
42102	 * @param {TypedArray|Array} array - The array to convert.
42103	 * @param {TypedArray.constructor} type - The constructor of a type array.
42104	 * @return {TypedArray} The converted array
42105	 */
42106	static convertArray( array, type ) {
42107
42108		return convertArray( array, type );
42109
42110	}
42111
42112	/**
42113	 * Returns `true` if the given object is a typed array.
42114	 *
42115	 * @static
42116	 * @param {any} object - The object to check.
42117	 * @return {boolean} Whether the given object is a typed array.
42118	 */
42119	static isTypedArray( object ) {
42120
42121		return isTypedArray( object );
42122
42123	}
42124
42125	/**
42126	 * Returns `true` if the given keyframe track settings hold Bezier tangent data.
42127	 *
42128	 * @static
42129	 * @param {?Object} settings - The settings of a keyframe track.
42130	 * @return {boolean} Whether both tangent arrays are defined or not.
42131	 */
42132	static hasTangents( settings ) {
42133
42134		return hasTangents( settings );
42135
42136	}
42137
42138	/**
42139	 * Returns an array by which times and values can be sorted.
42140	 *
42141	 * @static
42142	 * @param {Array<number>} times - The keyframe time values.
42143	 * @return {Array<number>} The array.
42144	 */
42145	static getKeyframeOrder( times ) {
42146
42147		return getKeyframeOrder( times );
42148
42149	}
42150
42151	/**
42152	 * Sorts the given array by the previously computed order via `getKeyframeOrder()`.
42153	 *
42154	 * @static
42155	 * @param {Array<number>} values - The values to sort.
42156	 * @param {number} stride - The stride.
42157	 * @param {Array<number>} order - The sort order.
42158	 * @return {Array<number>} The sorted values.
42159	 */
42160	static sortedArray( values, stride, order ) {
42161
42162		return sortedArray( values, stride, order );
42163
42164	}
42165
42166	/**
42167	 * Used for parsing AOS keyframe formats.
42168	 *
42169	 * @static
42170	 * @param {Array<number>} jsonKeys - A list of JSON keyframes.
42171	 * @param {Array<number>} times - This array will be filled with keyframe times by this method.
42172	 * @param {Array<number>} values - This array will be filled with keyframe values by this method.
42173	 * @param {string} valuePropertyName - The name of the property to use.
42174	 */
42175	static flattenJSON( jsonKeys, times, values, valuePropertyName ) {
42176
42177		flattenJSON( jsonKeys, times, values, valuePropertyName );
42178
42179	}
42180
42181	/**
42182	 * Creates a new clip, containing only the segment of the original clip between the given frames.
42183	 *
42184	 * @static
42185	 * @param {AnimationClip} sourceClip - The values to sort.
42186	 * @param {string} name - The name of the clip.
42187	 * @param {number} startFrame - The start frame.
42188	 * @param {number} endFrame - The end frame.
42189	 * @param {number} [fps=30] - The FPS.
42190	 * @return {AnimationClip} The new sub clip.
42191	 */
42192	static subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
42193
42194		return subclip( sourceClip, name, startFrame, endFrame, fps );
42195
42196	}
42197
42198	/**
42199	 * Converts the keyframes of the given animation clip to an additive format.
42200	 *
42201	 * @static
42202	 * @param {AnimationClip} targetClip - The clip to make additive.
42203	 * @param {number} [referenceFrame=0] - The reference frame.
42204	 * @param {AnimationClip} [referenceClip=targetClip] - The reference clip.
42205	 * @param {number} [fps=30] - The FPS.
42206	 * @return {AnimationClip} The updated clip which is now additive.
42207	 */
42208	static makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
42209
42210		return makeClipAdditive( targetClip, referenceFrame, referenceClip, fps );
42211
42212	}
42213
42214}
42215
42216/**
42217 * Abstract base class of interpolants over parametric samples.
42218 *
42219 * The parameter domain is one dimensional, typically the time or a path
42220 * along a curve defined by the data.
42221 *
42222 * The sample values can have any dimensionality and derived classes may
42223 * apply special interpretations to the data.
42224 *
42225 * This class provides the interval seek in a Template Method, deferring
42226 * the actual interpolation to derived classes.
42227 *
42228 * Time complexity is O(1) for linear access crossing at most two points
42229 * and O(log N) for random access, where N is the number of positions.
42230 *
42231 * References: {@link http://www.oodesign.com/template-method-pattern.html}
42232 *
42233 * @abstract
42234 */
42235class Interpolant {
42236
42237	/**
42238	 * Constructs a new interpolant.
42239	 *
42240	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
42241	 * @param {TypedArray} sampleValues - The sample values.
42242	 * @param {number} sampleSize - The sample size
42243	 * @param {TypedArray} [resultBuffer] - The result buffer.
42244	 */
42245	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42246
42247		/**
42248		 * The parameter positions.
42249		 *
42250		 * @type {TypedArray}
42251		 */
42252		this.parameterPositions = parameterPositions;
42253
42254		/**
42255		 * A cache index.
42256		 *
42257		 * @private
42258		 * @type {number}
42259		 * @default 0
42260		 */
42261		this._cachedIndex = 0;
42262
42263		/**
42264		 * The result buffer.
42265		 *
42266		 * @type {TypedArray}
42267		 */
42268		this.resultBuffer = resultBuffer !== undefined ? resultBuffer : new sampleValues.constructor( sampleSize );
42269
42270		/**
42271		 * The sample values.
42272		 *
42273		 * @type {TypedArray}
42274		 */
42275		this.sampleValues = sampleValues;
42276
42277		/**
42278		 * The value size.
42279		 *
42280		 * @type {TypedArray}
42281		 */
42282		this.valueSize = sampleSize;
42283
42284		/**
42285		 * The interpolation settings.
42286		 *
42287		 * @type {?Object}
42288		 * @default null
42289		 */
42290		this.settings = null;
42291
42292		/**
42293		 * The default settings object.
42294		 *
42295		 * @type {Object}
42296		 */
42297		this.DefaultSettings_ = {};
42298
42299	}
42300
42301	/**
42302	 * Evaluate the interpolant at position `t`.
42303	 *
42304	 * @param {number} t - The interpolation factor.
42305	 * @return {TypedArray} The result buffer.
42306	 */
42307	evaluate( t ) {
42308
42309		const pp = this.parameterPositions;
42310		let i1 = this._cachedIndex,
42311			t1 = pp[ i1 ],
42312			t0 = pp[ i1 - 1 ];
42313
42314		validate_interval: {
42315
42316			seek: {
42317
42318				let right;
42319
42320				linear_scan: {
42321
42322					//- See http://jsperf.com/comparison-to-undefined/3
42323					//- slower code:
42324					//-
42325					//- 				if ( t >= t1 || t1 === undefined ) {
42326					forward_scan: if ( ! ( t < t1 ) ) {
42327
42328						for ( let giveUpAt = i1 + 2; ; ) {
42329
42330							if ( t1 === undefined ) {
42331
42332								if ( t < t0 ) break forward_scan;
42333
42334								// after end
42335
42336								i1 = pp.length;
42337								this._cachedIndex = i1;
42338								return this.copySampleValue_( i1 - 1 );
42339
42340							}
42341
42342							if ( i1 === giveUpAt ) break; // this loop
42343
42344							t0 = t1;
42345							t1 = pp[ ++ i1 ];
42346
42347							if ( t < t1 ) {
42348
42349								// we have arrived at the sought interval
42350								break seek;
42351
42352							}
42353
42354						}
42355
42356						// prepare binary search on the right side of the index
42357						right = pp.length;
42358						break linear_scan;
42359
42360					}
42361
42362					//- slower code:
42363					//-					if ( t < t0 || t0 === undefined ) {
42364					if ( ! ( t >= t0 ) ) {
42365
42366						// looping?
42367
42368						const t1global = pp[ 1 ];
42369
42370						if ( t < t1global ) {
42371
42372							i1 = 2; // + 1, using the scan for the details
42373							t0 = t1global;
42374
42375						}
42376
42377						// linear reverse scan
42378
42379						for ( let giveUpAt = i1 - 2; ; ) {
42380
42381							if ( t0 === undefined ) {
42382
42383								// before start
42384
42385								this._cachedIndex = 0;
42386								return this.copySampleValue_( 0 );
42387
42388							}
42389
42390							if ( i1 === giveUpAt ) break; // this loop
42391
42392							t1 = t0;
42393							t0 = pp[ -- i1 - 1 ];
42394
42395							if ( t >= t0 ) {
42396
42397								// we have arrived at the sought interval
42398								break seek;
42399
42400							}
42401
42402						}
42403
42404						// prepare binary search on the left side of the index
42405						right = i1;
42406						i1 = 0;
42407						break linear_scan;
42408
42409					}
42410
42411					// the interval is valid
42412
42413					break validate_interval;
42414
42415				} // linear scan
42416
42417				// binary search
42418
42419				while ( i1 < right ) {
42420
42421					const mid = ( i1 + right ) >>> 1;
42422
42423					if ( t < pp[ mid ] ) {
42424
42425						right = mid;
42426
42427					} else {
42428
42429						i1 = mid + 1;
42430
42431					}
42432
42433				}
42434
42435				t1 = pp[ i1 ];
42436				t0 = pp[ i1 - 1 ];
42437
42438				// check boundary cases, again
42439
42440				if ( t0 === undefined ) {
42441
42442					this._cachedIndex = 0;
42443					return this.copySampleValue_( 0 );
42444
42445				}
42446
42447				if ( t1 === undefined ) {
42448
42449					i1 = pp.length;
42450					this._cachedIndex = i1;
42451					return this.copySampleValue_( i1 - 1 );
42452
42453				}
42454
42455			} // seek
42456
42457			this._cachedIndex = i1;
42458
42459			this.intervalChanged_( i1, t0, t1 );
42460
42461		} // validate_interval
42462
42463		return this.interpolate_( i1, t0, t, t1 );
42464
42465	}
42466
42467	/**
42468	 * Returns the interpolation settings.
42469	 *
42470	 * @return {Object} The interpolation settings.
42471	 */
42472	getSettings_() {
42473
42474		return this.settings || this.DefaultSettings_;
42475
42476	}
42477
42478	/**
42479	 * Copies a sample value to the result buffer.
42480	 *
42481	 * @param {number} index - An index into the sample value buffer.
42482	 * @return {TypedArray} The result buffer.
42483	 */
42484	copySampleValue_( index ) {
42485
42486		// copies a sample value to the result buffer
42487
42488		const result = this.resultBuffer,
42489			values = this.sampleValues,
42490			stride = this.valueSize,
42491			offset = index * stride;
42492
42493		for ( let i = 0; i !== stride; ++ i ) {
42494
42495			result[ i ] = values[ offset + i ];
42496
42497		}
42498
42499		return result;
42500
42501	}
42502
42503	/**
42504	 * Copies a sample value to the result buffer.
42505	 *
42506	 * @abstract
42507	 * @param {number} i1 - An index into the sample value buffer.
42508	 * @param {number} t0 - The previous interpolation factor.
42509	 * @param {number} t - The current interpolation factor.
42510	 * @param {number} t1 - The next interpolation factor.
42511	 * @return {TypedArray} The result buffer.
42512	 */
42513	interpolate_( /* i1, t0, t, t1 */ ) {
42514
42515		throw new Error( 'THREE.Interpolant: Call to abstract method.' );
42516		// implementations shall return this.resultBuffer
42517
42518	}
42519
42520	/**
42521	 * Optional method that is executed when the interval has changed.
42522	 *
42523	 * @param {number} i1 - An index into the sample value buffer.
42524	 * @param {number} t0 - The previous interpolation factor.
42525	 * @param {number} t - The current interpolation factor.
42526	 */
42527	intervalChanged_( /* i1, t0, t1 */ ) {
42528
42529		// empty
42530
42531	}
42532
42533}
42534
42535/**
42536 * Fast and simple cubic spline interpolant.
42537 *
42538 * It was derived from a Hermitian construction setting the first derivative
42539 * at each sample position to the linear slope between neighboring positions
42540 * over their parameter interval.
42541 *
42542 * @augments Interpolant
42543 */
42544class CubicInterpolant extends Interpolant {
42545
42546	/**
42547	 * Constructs a new cubic interpolant.
42548	 *
42549	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
42550	 * @param {TypedArray} sampleValues - The sample values.
42551	 * @param {number} sampleSize - The sample size
42552	 * @param {TypedArray} [resultBuffer] - The result buffer.
42553	 */
42554	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42555
42556		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42557
42558		this._weightPrev = -0;
42559		this._offsetPrev = -0;
42560		this._weightNext = -0;
42561		this._offsetNext = -0;
42562
42563		this.DefaultSettings_ = {
42564
42565			endingStart: ZeroCurvatureEnding,
42566			endingEnd: ZeroCurvatureEnding
42567
42568		};
42569
42570	}
42571
42572	intervalChanged_( i1, t0, t1 ) {
42573
42574		const pp = this.parameterPositions;
42575		let iPrev = i1 - 2,
42576			iNext = i1 + 1,
42577
42578			tPrev = pp[ iPrev ],
42579			tNext = pp[ iNext ];
42580
42581		if ( tPrev === undefined ) {
42582
42583			switch ( this.getSettings_().endingStart ) {
42584
42585				case ZeroSlopeEnding:
42586
42587					// f'(t0) = 0
42588					iPrev = i1;
42589					tPrev = 2 * t0 - t1;
42590
42591					break;
42592
42593				case WrapAroundEnding:
42594
42595					// use the other end of the curve
42596					iPrev = pp.length - 2;
42597					tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
42598
42599					break;
42600
42601				default: // ZeroCurvatureEnding
42602
42603					// f''(t0) = 0 a.k.a. Natural Spline
42604					iPrev = i1;
42605					tPrev = t1;
42606
42607			}
42608
42609		}
42610
42611		if ( tNext === undefined ) {
42612
42613			switch ( this.getSettings_().endingEnd ) {
42614
42615				case ZeroSlopeEnding:
42616
42617					// f'(tN) = 0
42618					iNext = i1;
42619					tNext = 2 * t1 - t0;
42620
42621					break;
42622
42623				case WrapAroundEnding:
42624
42625					// use the other end of the curve
42626					iNext = 1;
42627					tNext = t1 + pp[ 1 ] - pp[ 0 ];
42628
42629					break;
42630
42631				default: // ZeroCurvatureEnding
42632
42633					// f''(tN) = 0, a.k.a. Natural Spline
42634					iNext = i1 - 1;
42635					tNext = t0;
42636
42637			}
42638
42639		}
42640
42641		const halfDt = ( t1 - t0 ) * 0.5,
42642			stride = this.valueSize;
42643
42644		this._weightPrev = halfDt / ( t0 - tPrev );
42645		this._weightNext = halfDt / ( tNext - t1 );
42646		this._offsetPrev = iPrev * stride;
42647		this._offsetNext = iNext * stride;
42648
42649	}
42650
42651	interpolate_( i1, t0, t, t1 ) {
42652
42653		const result = this.resultBuffer,
42654			values = this.sampleValues,
42655			stride = this.valueSize,
42656
42657			o1 = i1 * stride,		o0 = o1 - stride,
42658			oP = this._offsetPrev, 	oN = this._offsetNext,
42659			wP = this._weightPrev,	wN = this._weightNext,
42660
42661			p = ( t - t0 ) / ( t1 - t0 ),
42662			pp = p * p,
42663			ppp = pp * p;
42664
42665		// evaluate polynomials
42666
42667		const sP = - wP * ppp + 2 * wP * pp - wP * p;
42668		const s0 = ( 1 + wP ) * ppp + ( -1.5 - 2 * wP ) * pp + ( -0.5 + wP ) * p + 1;
42669		const s1 = ( -1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;
42670		const sN = wN * ppp - wN * pp;
42671
42672		// combine data linearly
42673
42674		for ( let i = 0; i !== stride; ++ i ) {
42675
42676			result[ i ] =
42677					sP * values[ oP + i ] +
42678					s0 * values[ o0 + i ] +
42679					s1 * values[ o1 + i ] +
42680					sN * values[ oN + i ];
42681
42682		}
42683
42684		return result;
42685
42686	}
42687
42688}
42689
42690/**
42691 * A basic linear interpolant.
42692 *
42693 * @augments Interpolant
42694 */
42695class LinearInterpolant extends Interpolant {
42696
42697	/**
42698	 * Constructs a new linear interpolant.
42699	 *
42700	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
42701	 * @param {TypedArray} sampleValues - The sample values.
42702	 * @param {number} sampleSize - The sample size
42703	 * @param {TypedArray} [resultBuffer] - The result buffer.
42704	 */
42705	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42706
42707		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42708
42709	}
42710
42711	interpolate_( i1, t0, t, t1 ) {
42712
42713		const result = this.resultBuffer,
42714			values = this.sampleValues,
42715			stride = this.valueSize,
42716
42717			offset1 = i1 * stride,
42718			offset0 = offset1 - stride,
42719
42720			weight1 = ( t - t0 ) / ( t1 - t0 ),
42721			weight0 = 1 - weight1;
42722
42723		for ( let i = 0; i !== stride; ++ i ) {
42724
42725			result[ i ] =
42726					values[ offset0 + i ] * weight0 +
42727					values[ offset1 + i ] * weight1;
42728
42729		}
42730
42731		return result;
42732
42733	}
42734
42735}
42736
42737/**
42738 * Interpolant that evaluates to the sample value at the position preceding
42739 * the parameter.
42740 *
42741 * @augments Interpolant
42742 */
42743class DiscreteInterpolant extends Interpolant {
42744
42745	/**
42746	 * Constructs a new discrete interpolant.
42747	 *
42748	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
42749	 * @param {TypedArray} sampleValues - The sample values.
42750	 * @param {number} sampleSize - The sample size
42751	 * @param {TypedArray} [resultBuffer] - The result buffer.
42752	 */
42753	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42754
42755		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42756
42757	}
42758
42759	interpolate_( i1 /*, t0, t, t1 */ ) {
42760
42761		return this.copySampleValue_( i1 - 1 );
42762
42763	}
42764
42765}
42766
42767/**
42768 * A Bezier interpolant using cubic Bezier curves with 2D control points.
42769 *
42770 * This interpolant supports the COLLADA/Maya style of Bezier animation where
42771 * each keyframe has explicit in/out tangent control points specified as
42772 * 2D coordinates (time, value).
42773 *
42774 * Tangent data is read from `inTangents` and `outTangents` on the interpolant
42775 * (populated by `KeyframeTrack.InterpolantFactoryMethodBezier`).
42776 *
42777 * For a track with N keyframes and stride S:
42778 * - Each tangent array has N * S * 2 values
42779 * - Layout: [k0_c0_time, k0_c0_value, k0_c1_time, k0_c1_value, ..., k0_cS_time, k0_cS_value,
42780 *            k1_c0_time, k1_c0_value, ...]
42781 *
42782 * @augments Interpolant
42783 */
42784class BezierInterpolant extends Interpolant {
42785
42786	interpolate_( i1, t0, t, t1 ) {
42787
42788		const result = this.resultBuffer;
42789		const values = this.sampleValues;
42790		const stride = this.valueSize;
42791
42792		const offset1 = i1 * stride;
42793		const offset0 = offset1 - stride;
42794
42795		const inTangents = this.inTangents;
42796		const outTangents = this.outTangents;
42797
42798		// If no tangent data, fall back to linear interpolation
42799		if ( ! inTangents || ! outTangents ) {
42800
42801			const weight1 = ( t - t0 ) / ( t1 - t0 );
42802			const weight0 = 1 - weight1;
42803
42804			for ( let i = 0; i !== stride; ++ i ) {
42805
42806				result[ i ] = values[ offset0 + i ] * weight0 + values[ offset1 + i ] * weight1;
42807
42808			}
42809
42810			return result;
42811
42812		}
42813
42814		const tangentStride = stride * 2;
42815		const i0 = i1 - 1;
42816
42817		for ( let i = 0; i !== stride; ++ i ) {
42818
42819			const v0 = values[ offset0 + i ];
42820			const v1 = values[ offset1 + i ];
42821
42822			// outTangent of previous keyframe (C0)
42823			const outTangentOffset = i0 * tangentStride + i * 2;
42824			const c0x = outTangents[ outTangentOffset ];
42825			const c0y = outTangents[ outTangentOffset + 1 ];
42826
42827			// inTangent of current keyframe (C1)
42828			const inTangentOffset = i1 * tangentStride + i * 2;
42829			const c1x = inTangents[ inTangentOffset ];
42830			const c1y = inTangents[ inTangentOffset + 1 ];
42831
42832			// Find the curve parameter s where the Bezier X(s) matches t, then evaluate Y(s)
42833			const s = solveBezierParameter( t, t0, c0x, c1x, t1 );
42834
42835			result[ i ] = cubicBezier( s, v0, c0y, c1y, v1 );
42836
42837		}
42838
42839		return result;
42840
42841	}
42842
42843}
42844
42845function cubicBezier( s, p0, p1, p2, p3 ) {
42846
42847	const k = 1 - s;
42848
42849	return k * k * k * p0 + 3 * k * k * s * p1 + 3 * k * s * s * p2 + s * s * s * p3;
42850
42851}
42852
42853function cubicBezierSlope( s, p0, p1, p2, p3 ) {
42854
42855	const k = 1 - s;
42856
42857	return 3 * k * k * ( p1 - p0 ) + 6 * k * s * ( p2 - p1 ) + 3 * s * s * ( p3 - p2 );
42858
42859}
42860
42861// Solves cubicBezier( s, x0, x1, x2, x3 ) = x for s in [0,1] using Newton-Raphson
42862
42863function solveBezierParameter( x, x0, x1, x2, x3 ) {
42864
42865	let s = ( x - x0 ) / ( x3 - x0 );
42866
42867	for ( let i = 0; i < 8; i ++ ) {
42868
42869		const error = cubicBezier( s, x0, x1, x2, x3 ) - x;
42870		if ( Math.abs( error ) < 1e-10 ) break;
42871
42872		const slope = cubicBezierSlope( s, x0, x1, x2, x3 );
42873		if ( Math.abs( slope ) < 1e-10 ) break;
42874
42875		s = Math.max( 0, Math.min( 1, s - error / slope ) );
42876
42877	}
42878
42879	return s;
42880
42881}
42882
42883/**
42884 * Represents a timed sequence of keyframes, which are composed of lists of
42885 * times and related values, and which are used to animate a specific property
42886 * of an object.
42887 */
42888class KeyframeTrack {
42889
42890	/**
42891	 * Constructs a new keyframe track.
42892	 *
42893	 * @param {string} name - The keyframe track's name.
42894	 * @param {Array<number>} times - A list of keyframe times.
42895	 * @param {Array<number|string|boolean>} values - A list of keyframe values.
42896	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} [interpolation] - The interpolation type.
42897	 */
42898	constructor( name, times, values, interpolation ) {
42899
42900		if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
42901		if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );
42902
42903		/**
42904		 * The track's name can refer to morph targets or bones or
42905		 * possibly other values within an animated object. See {@link PropertyBinding#parseTrackName}
42906		 * for the forms of strings that can be parsed for property binding.
42907		 *
42908		 * @type {string}
42909		 */
42910		this.name = name;
42911
42912		/**
42913		 * The keyframe times.
42914		 *
42915		 * @type {Float32Array}
42916		 */
42917		this.times = convertArray( times, this.TimeBufferType );
42918
42919		/**
42920		 * The keyframe values.
42921		 *
42922		 * @type {Float32Array}
42923		 */
42924		this.values = convertArray( values, this.ValueBufferType );
42925
42926		this.setInterpolation( interpolation || this.DefaultInterpolation );
42927
42928	}
42929
42930	/**
42931	 * Converts the keyframe track to JSON.
42932	 *
42933	 * @static
42934	 * @param {KeyframeTrack} track - The keyframe track to serialize.
42935	 * @return {Object} The serialized keyframe track as JSON.
42936	 */
42937	static toJSON( track ) {
42938
42939		const trackType = track.constructor;
42940
42941		let json;
42942
42943		// derived classes can define a static toJSON method
42944		if ( trackType.toJSON !== this.toJSON ) {
42945
42946			json = trackType.toJSON( track );
42947
42948		} else {
42949
42950			// by default, we assume the data can be serialized as-is
42951			json = {
42952
42953				'name': track.name,
42954				'times': convertArray( track.times, Array ),
42955				'values': convertArray( track.values, Array )
42956
42957			};
42958
42959			const interpolation = track.getInterpolation();
42960
42961			if ( interpolation !== track.DefaultInterpolation ) {
42962
42963				json.interpolation = interpolation;
42964
42965			}
42966
42967			if ( hasTangents( track.settings ) ) {
42968
42969				json.settings = {
42970					inTangents: convertArray( track.settings.inTangents, Array ),
42971					outTangents: convertArray( track.settings.outTangents, Array )
42972				};
42973
42974			}
42975
42976		}
42977
42978		json.type = track.ValueTypeName; // mandatory
42979
42980		return json;
42981
42982	}
42983
42984	/**
42985	 * Factory method for creating a new discrete interpolant.
42986	 *
42987	 * @static
42988	 * @param {TypedArray} [result] - The result buffer.
42989	 * @return {DiscreteInterpolant} The new interpolant.
42990	 */
42991	InterpolantFactoryMethodDiscrete( result ) {
42992
42993		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
42994
42995	}
42996
42997	/**
42998	 * Factory method for creating a new linear interpolant.
42999	 *
43000	 * @static
43001	 * @param {TypedArray} [result] - The result buffer.
43002	 * @return {LinearInterpolant} The new interpolant.
43003	 */
43004	InterpolantFactoryMethodLinear( result ) {
43005
43006		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
43007
43008	}
43009
43010	/**
43011	 * Factory method for creating a new smooth interpolant.
43012	 *
43013	 * @static
43014	 * @param {TypedArray} [result] - The result buffer.
43015	 * @return {CubicInterpolant} The new interpolant.
43016	 */
43017	InterpolantFactoryMethodSmooth( result ) {
43018
43019		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
43020
43021	}
43022
43023	/**
43024	 * Factory method for creating a new Bezier interpolant.
43025	 *
43026	 * The Bezier interpolant requires tangent data to be set via the `settings` property
43027	 * on the track before creating the interpolant. The settings should contain:
43028	 * - `inTangents`: Float32Array with [time, value] pairs per keyframe per component
43029	 * - `outTangents`: Float32Array with [time, value] pairs per keyframe per component
43030	 *
43031	 * @static
43032	 * @param {TypedArray} [result] - The result buffer.
43033	 * @return {BezierInterpolant} The new interpolant.
43034	 */
43035	InterpolantFactoryMethodBezier( result ) {
43036
43037		const interpolant = new BezierInterpolant( this.times, this.values, this.getValueSize(), result );
43038
43039		if ( this.settings ) {
43040
43041			interpolant.inTangents = this.settings.inTangents;
43042			interpolant.outTangents = this.settings.outTangents;
43043
43044		}
43045
43046		return interpolant;
43047
43048	}
43049
43050	/**
43051	 * Defines the interpolation factor method for this keyframe track.
43052	 *
43053	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} interpolation - The interpolation type.
43054	 * @return {KeyframeTrack} A reference to this keyframe track.
43055	 */
43056	setInterpolation( interpolation ) {
43057
43058		let factoryMethod;
43059
43060		switch ( interpolation ) {
43061
43062			case InterpolateDiscrete:
43063
43064				factoryMethod = this.InterpolantFactoryMethodDiscrete;
43065
43066				break;
43067
43068			case InterpolateLinear:
43069
43070				factoryMethod = this.InterpolantFactoryMethodLinear;
43071
43072				break;
43073
43074			case InterpolateSmooth:
43075
43076				factoryMethod = this.InterpolantFactoryMethodSmooth;
43077
43078				break;
43079
43080			case InterpolateBezier:
43081
43082				factoryMethod = this.InterpolantFactoryMethodBezier;
43083
43084				break;
43085
43086		}
43087
43088		if ( factoryMethod === undefined ) {
43089
43090			const message = 'unsupported interpolation for ' +
43091				this.ValueTypeName + ' keyframe track named ' + this.name;
43092
43093			if ( this.createInterpolant === undefined ) {
43094
43095				// fall back to default, unless the default itself is messed up
43096				if ( interpolation !== this.DefaultInterpolation ) {
43097
43098					this.setInterpolation( this.DefaultInterpolation );
43099
43100				} else {
43101
43102					throw new Error( message ); // fatal, in this case
43103
43104				}
43105
43106			}
43107
43108			warn( 'KeyframeTrack:', message );
43109			return this;
43110
43111		}
43112
43113		this.createInterpolant = factoryMethod;
43114
43115		return this;
43116
43117	}
43118
43119	/**
43120	 * Returns the current interpolation type.
43121	 *
43122	 * @return {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} The interpolation type.
43123	 */
43124	getInterpolation() {
43125
43126		switch ( this.createInterpolant ) {
43127
43128			case this.InterpolantFactoryMethodDiscrete:
43129
43130				return InterpolateDiscrete;
43131
43132			case this.InterpolantFactoryMethodLinear:
43133
43134				return InterpolateLinear;
43135
43136			case this.InterpolantFactoryMethodSmooth:
43137
43138				return InterpolateSmooth;
43139
43140			case this.InterpolantFactoryMethodBezier:
43141
43142				return InterpolateBezier;
43143
43144		}
43145
43146	}
43147
43148	/**
43149	 * Returns the value size.
43150	 *
43151	 * @return {number} The value size.
43152	 */
43153	getValueSize() {
43154
43155		return this.values.length / this.times.length;
43156
43157	}
43158
43159	/**
43160	 * Moves all keyframes either forward or backward in time.
43161	 *
43162	 * @param {number} timeOffset - The offset to move the time values.
43163	 * @return {KeyframeTrack} A reference to this keyframe track.
43164	 */
43165	shift( timeOffset ) {
43166
43167		if ( timeOffset !== 0.0 ) {
43168
43169			const times = this.times;
43170
43171			for ( let i = 0, n = times.length; i !== n; ++ i ) {
43172
43173				times[ i ] += timeOffset;
43174
43175			}
43176
43177		}
43178
43179		return this;
43180
43181	}
43182
43183	/**
43184	 * Scale all keyframe times by a factor (useful for frame - seconds conversions).
43185	 *
43186	 * @param {number} timeScale - The time scale.
43187	 * @return {KeyframeTrack} A reference to this keyframe track.
43188	 */
43189	scale( timeScale ) {
43190
43191		if ( timeScale !== 1.0 ) {
43192
43193			const times = this.times;
43194
43195			for ( let i = 0, n = times.length; i !== n; ++ i ) {
43196
43197				times[ i ] *= timeScale;
43198
43199			}
43200
43201			if ( hasTangents( this.settings ) ) {
43202
43203				scaleTangentTimes( this.settings.inTangents, timeScale );
43204				scaleTangentTimes( this.settings.outTangents, timeScale );
43205
43206			}
43207
43208		}
43209
43210		return this;
43211
43212	}
43213
43214	/**
43215	 * Removes keyframes before and after animation without changing any values within the defined time range.
43216	 *
43217	 * Note: The method does not shift around keys to the start of the track time, because for interpolated
43218	 * keys this will change their values
43219	 *
43220	 * @param {number} startTime - The start time.
43221	 * @param {number} endTime - The end time.
43222	 * @return {KeyframeTrack} A reference to this keyframe track.
43223	 */
43224	trim( startTime, endTime ) {
43225
43226		const times = this.times,
43227			nKeys = times.length;
43228
43229		let from = 0,
43230			to = nKeys - 1;
43231
43232		while ( from !== nKeys && times[ from ] < startTime ) {
43233
43234			++ from;
43235
43236		}
43237
43238		while ( to !== -1 && times[ to ] > endTime ) {
43239
43240			-- to;
43241
43242		}
43243
43244		++ to; // inclusive -> exclusive bound
43245
43246		if ( from !== 0 || to !== nKeys ) {
43247
43248			// empty tracks are forbidden, so keep at least one keyframe
43249			if ( from >= to ) {
43250
43251				to = Math.max( to, 1 );
43252				from = to - 1;
43253
43254			}
43255
43256			const stride = this.getValueSize();
43257			this.times = times.slice( from, to );
43258			this.values = this.values.slice( from * stride, to * stride );
43259
43260		}
43261
43262		return this;
43263
43264	}
43265
43266	/**
43267	 * Performs minimal validation on the keyframe track. Returns `true` if the values
43268	 * are valid.
43269	 *
43270	 * @return {boolean} Whether the keyframes are valid or not.
43271	 */
43272	validate() {
43273
43274		let valid = true;
43275
43276		const valueSize = this.getValueSize();
43277		if ( valueSize - Math.floor( valueSize ) !== 0 ) {
43278
43279			error( 'KeyframeTrack: Invalid value size in track.', this );
43280			valid = false;
43281
43282		}
43283
43284		const times = this.times,
43285			values = this.values,
43286
43287			nKeys = times.length;
43288
43289		if ( nKeys === 0 ) {
43290
43291			error( 'KeyframeTrack: Track is empty.', this );
43292			valid = false;
43293
43294		}
43295
43296		let prevTime = null;
43297
43298		for ( let i = 0; i !== nKeys; i ++ ) {
43299
43300			const currTime = times[ i ];
43301
43302			if ( typeof currTime === 'number' && isNaN( currTime ) ) {
43303
43304				error( 'KeyframeTrack: Time is not a valid number.', this, i, currTime );
43305				valid = false;
43306				break;
43307
43308			}
43309
43310			if ( prevTime !== null && prevTime > currTime ) {
43311
43312				error( 'KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
43313				valid = false;
43314				break;
43315
43316			}
43317
43318			prevTime = currTime;
43319
43320		}
43321
43322		if ( values !== undefined ) {
43323
43324			if ( isTypedArray( values ) ) {
43325
43326				for ( let i = 0, n = values.length; i !== n; ++ i ) {
43327
43328					const value = values[ i ];
43329
43330					if ( isNaN( value ) ) {
43331
43332						error( 'KeyframeTrack: Value is not a valid number.', this, i, value );
43333						valid = false;
43334						break;
43335
43336					}
43337
43338				}
43339
43340			}
43341
43342		}
43343
43344		return valid;
43345
43346	}
43347
43348	/**
43349	 * Optimizes this keyframe track by removing equivalent sequential keys (which are
43350	 * common in morph target sequences).
43351	 *
43352	 * @return {KeyframeTrack} A reference to this keyframe track.
43353	 */
43354	optimize() {
43355
43356		// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
43357
43358		// times or values may be shared with other tracks, so overwriting is unsafe
43359		const times = this.times.slice(),
43360			values = this.values.slice(),
43361			stride = this.getValueSize(),
43362
43363			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
43364
43365			lastIndex = times.length - 1;
43366
43367		let writeIndex = 1;
43368
43369		for ( let i = 1; i < lastIndex; ++ i ) {
43370
43371			let keep = false;
43372
43373			const time = times[ i ];
43374			const timeNext = times[ i + 1 ];
43375
43376			// remove adjacent keyframes scheduled at the same time
43377
43378			if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {
43379
43380				if ( ! smoothInterpolation ) {
43381
43382					// remove unnecessary keyframes same as their neighbors
43383
43384					const offset = i * stride,
43385						offsetP = offset - stride,
43386						offsetN = offset + stride;
43387
43388					for ( let j = 0; j !== stride; ++ j ) {
43389
43390						const value = values[ offset + j ];
43391
43392						if ( value !== values[ offsetP + j ] ||
43393							value !== values[ offsetN + j ] ) {
43394
43395							keep = true;
43396							break;
43397
43398						}
43399
43400					}
43401
43402				} else {
43403
43404					keep = true;
43405
43406				}
43407
43408			}
43409
43410			// in-place compaction
43411
43412			if ( keep ) {
43413
43414				if ( i !== writeIndex ) {
43415
43416					times[ writeIndex ] = times[ i ];
43417
43418					const readOffset = i * stride,
43419						writeOffset = writeIndex * stride;
43420
43421					for ( let j = 0; j !== stride; ++ j ) {
43422
43423						values[ writeOffset + j ] = values[ readOffset + j ];
43424
43425					}
43426
43427				}
43428
43429				++ writeIndex;
43430
43431			}
43432
43433		}
43434
43435		// flush last keyframe (compaction looks ahead)
43436
43437		if ( lastIndex > 0 ) {
43438
43439			times[ writeIndex ] = times[ lastIndex ];
43440
43441			for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {
43442
43443				values[ writeOffset + j ] = values[ readOffset + j ];
43444
43445			}
43446
43447			++ writeIndex;
43448
43449		}
43450
43451		if ( writeIndex !== times.length ) {
43452
43453			this.times = times.slice( 0, writeIndex );
43454			this.values = values.slice( 0, writeIndex * stride );
43455
43456		} else {
43457
43458			this.times = times;
43459			this.values = values;
43460
43461		}
43462
43463		return this;
43464
43465	}
43466
43467	/**
43468	 * Returns a new keyframe track with copied values from this instance.
43469	 *
43470	 * @return {KeyframeTrack} A clone of this instance.
43471	 */
43472	clone() {
43473
43474		const times = this.times.slice();
43475		const values = this.values.slice();
43476
43477		const TypedKeyframeTrack = this.constructor;
43478		const track = new TypedKeyframeTrack( this.name, times, values );
43479
43480		// Interpolant argument to constructor is not saved, so copy the factory method directly.
43481		track.createInterpolant = this.createInterpolant;
43482
43483		if ( hasTangents( this.settings ) ) {
43484
43485			track.settings = {
43486				inTangents: this.settings.inTangents.slice(),
43487				outTangents: this.settings.outTangents.slice()
43488			};
43489
43490		}
43491
43492		return track;
43493
43494	}
43495
43496}
43497
43498function scaleTangentTimes( tangents, timeScale ) {
43499
43500	// tangents are [ time, value ] pairs, so only every second entry is a time
43501
43502	for ( let i = 0, n = tangents.length; i !== n; i += 2 ) {
43503
43504		tangents[ i ] *= timeScale;
43505
43506	}
43507
43508}
43509
43510/**
43511 * The value type name.
43512 *
43513 * @type {string}
43514 * @default ''
43515 */
43516KeyframeTrack.prototype.ValueTypeName = '';
43517
43518/**
43519 * The time buffer type of this keyframe track.
43520 *
43521 * @type {TypedArray|Array}
43522 * @default Float32Array.constructor
43523 */
43524KeyframeTrack.prototype.TimeBufferType = Float32Array;
43525
43526/**
43527 * The value buffer type of this keyframe track.
43528 *
43529 * @type {TypedArray|Array}
43530 * @default Float32Array.constructor
43531 */
43532KeyframeTrack.prototype.ValueBufferType = Float32Array;
43533
43534/**
43535 * The default interpolation type of this keyframe track.
43536 *
43537 * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)}
43538 * @default InterpolateLinear
43539 */
43540KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
43541
43542/**
43543 * A track for boolean keyframe values.
43544 *
43545 * @augments KeyframeTrack
43546 */
43547class BooleanKeyframeTrack extends KeyframeTrack {
43548
43549	/**
43550	 * Constructs a new boolean keyframe track.
43551	 *
43552	 * This keyframe track type has no `interpolation` parameter because the
43553	 * interpolation is always discrete.
43554	 *
43555	 * @param {string} name - The keyframe track's name.
43556	 * @param {Array<number>} times - A list of keyframe times.
43557	 * @param {Array<boolean>} values - A list of keyframe values.
43558	 */
43559	constructor( name, times, values ) {
43560
43561		super( name, times, values );
43562
43563	}
43564
43565}
43566
43567/**
43568 * The value type name.
43569 *
43570 * @type {string}
43571 * @default 'bool'
43572 */
43573BooleanKeyframeTrack.prototype.ValueTypeName = 'bool';
43574
43575/**
43576 * The value buffer type of this keyframe track.
43577 *
43578 * @type {TypedArray|Array}
43579 * @default Array.constructor
43580 */
43581BooleanKeyframeTrack.prototype.ValueBufferType = Array;
43582
43583/**
43584 * The default interpolation type of this keyframe track.
43585 *
43586 * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
43587 * @default InterpolateDiscrete
43588 */
43589BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
43590BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
43591BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
43592
43593/**
43594 * A track for color keyframe values.
43595 *
43596 * @augments KeyframeTrack
43597 */
43598class ColorKeyframeTrack extends KeyframeTrack {
43599
43600	/**
43601	 * Constructs a new color keyframe track.
43602	 *
43603	 * @param {string} name - The keyframe track's name.
43604	 * @param {Array<number>} times - A list of keyframe times.
43605	 * @param {Array<number>} values - A list of keyframe values.
43606	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
43607	 */
43608	constructor( name, times, values, interpolation ) {
43609
43610		super( name, times, values, interpolation );
43611
43612	}
43613
43614}
43615
43616/**
43617 * The value type name.
43618 *
43619 * @type {string}
43620 * @default 'color'
43621 */
43622ColorKeyframeTrack.prototype.ValueTypeName = 'color';
43623
43624/**
43625 * A track for numeric keyframe values.
43626 *
43627 * @augments KeyframeTrack
43628 */
43629class NumberKeyframeTrack extends KeyframeTrack {
43630
43631	/**
43632	 * Constructs a new number keyframe track.
43633	 *
43634	 * @param {string} name - The keyframe track's name.
43635	 * @param {Array<number>} times - A list of keyframe times.
43636	 * @param {Array<number>} values - A list of keyframe values.
43637	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
43638	 */
43639	constructor( name, times, values, interpolation ) {
43640
43641		super( name, times, values, interpolation );
43642
43643	}
43644
43645}
43646
43647/**
43648 * The value type name.
43649 *
43650 * @type {string}
43651 * @default 'number'
43652 */
43653NumberKeyframeTrack.prototype.ValueTypeName = 'number';
43654
43655/**
43656 * Spherical linear unit quaternion interpolant.
43657 *
43658 * @augments Interpolant
43659 */
43660class QuaternionLinearInterpolant extends Interpolant {
43661
43662	/**
43663	 * Constructs a new SLERP interpolant.
43664	 *
43665	 * @param {TypedArray} parameterPositions - The parameter positions hold the interpolation factors.
43666	 * @param {TypedArray} sampleValues - The sample values.
43667	 * @param {number} sampleSize - The sample size
43668	 * @param {TypedArray} [resultBuffer] - The result buffer.
43669	 */
43670	constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
43671
43672		super( parameterPositions, sampleValues, sampleSize, resultBuffer );
43673
43674	}
43675
43676	interpolate_( i1, t0, t, t1 ) {
43677
43678		const result = this.resultBuffer,
43679			values = this.sampleValues,
43680			stride = this.valueSize,
43681
43682			alpha = ( t - t0 ) / ( t1 - t0 );
43683
43684		let offset = i1 * stride;
43685
43686		for ( let end = offset + stride; offset !== end; offset += 4 ) {
43687
43688			Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
43689
43690		}
43691
43692		return result;
43693
43694	}
43695
43696}
43697
43698/**
43699 * A track for Quaternion keyframe values.
43700 *
43701 * @augments KeyframeTrack
43702 */
43703class QuaternionKeyframeTrack extends KeyframeTrack {
43704
43705	/**
43706	 * Constructs a new Quaternion keyframe track.
43707	 *
43708	 * @param {string} name - The keyframe track's name.
43709	 * @param {Array<number>} times - A list of keyframe times.
43710	 * @param {Array<number>} values - A list of keyframe values.
43711	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
43712	 */
43713	constructor( name, times, values, interpolation ) {
43714
43715		super( name, times, values, interpolation );
43716
43717	}
43718
43719	/**
43720	 * Overwritten so the method returns Quaternion based interpolant.
43721	 *
43722	 * @static
43723	 * @param {TypedArray} [result] - The result buffer.
43724	 * @return {QuaternionLinearInterpolant} The new interpolant.
43725	 */
43726	InterpolantFactoryMethodLinear( result ) {
43727
43728		return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
43729
43730	}
43731
43732}
43733
43734/**
43735 * The value type name.
43736 *
43737 * @type {string}
43738 * @default 'quaternion'
43739 */
43740QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion';
43741// ValueBufferType is inherited
43742// DefaultInterpolation is inherited;
43743QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
43744
43745/**
43746 * A track for string keyframe values.
43747 *
43748 * @augments KeyframeTrack
43749 */
43750class StringKeyframeTrack extends KeyframeTrack {
43751
43752	/**
43753	 * Constructs a new string keyframe track.
43754	 *
43755	 * This keyframe track type has no `interpolation` parameter because the
43756	 * interpolation is always discrete.
43757	 *
43758	 * @param {string} name - The keyframe track's name.
43759	 * @param {Array<number>} times - A list of keyframe times.
43760	 * @param {Array<string>} values - A list of keyframe values.
43761	 */
43762	constructor( name, times, values ) {
43763
43764		super( name, times, values );
43765
43766	}
43767
43768}
43769
43770/**
43771 * The value type name.
43772 *
43773 * @type {string}
43774 * @default 'string'
43775 */
43776StringKeyframeTrack.prototype.ValueTypeName = 'string';
43777
43778/**
43779 * The value buffer type of this keyframe track.
43780 *
43781 * @type {TypedArray|Array}
43782 * @default Array.constructor
43783 */
43784StringKeyframeTrack.prototype.ValueBufferType = Array;
43785
43786/**
43787 * The default interpolation type of this keyframe track.
43788 *
43789 * @type {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)}
43790 * @default InterpolateDiscrete
43791 */
43792StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
43793StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined;
43794StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined;
43795
43796/**
43797 * A track for vector keyframe values.
43798 *
43799 * @augments KeyframeTrack
43800 */
43801class VectorKeyframeTrack extends KeyframeTrack {
43802
43803	/**
43804	 * Constructs a new vector keyframe track.
43805	 *
43806	 * @param {string} name - The keyframe track's name.
43807	 * @param {Array<number>} times - A list of keyframe times.
43808	 * @param {Array<number>} values - A list of keyframe values.
43809	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth)} [interpolation] - The interpolation type.
43810	 */
43811	constructor( name, times, values, interpolation ) {
43812
43813		super( name, times, values, interpolation );
43814
43815	}
43816
43817}
43818
43819/**
43820 * The value type name.
43821 *
43822 * @type {string}
43823 * @default 'vector'
43824 */
43825VectorKeyframeTrack.prototype.ValueTypeName = 'vector';
43826
43827/**
43828 * A reusable set of keyframe tracks which represent an animation.
43829 */
43830class AnimationClip {
43831
43832	/**
43833	 * Constructs a new animation clip.
43834	 *
43835	 * Note: Instead of instantiating an AnimationClip directly with the constructor, you can
43836	 * use the static interface of this class for creating clips. In most cases though, animation clips
43837	 * will automatically be created by loaders when importing animated 3D assets.
43838	 *
43839	 * @param {string} [name=''] - The clip's name.
43840	 * @param {number} [duration=-1] - The clip's duration in seconds. If a negative value is passed,
43841	 * the duration will be calculated from the passed keyframes.
43842	 * @param {Array<KeyframeTrack>} tracks - An array of keyframe tracks.
43843	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode=NormalAnimationBlendMode] - Defines how the animation
43844	 * is blended/combined when two or more animations are simultaneously played.
43845	 */
43846	constructor( name = '', duration = -1, tracks = [], blendMode = NormalAnimationBlendMode ) {
43847
43848		/**
43849		 * The clip's name.
43850		 *
43851		 * @type {string}
43852		 */
43853		this.name = name;
43854
43855		/**
43856		 *  An array of keyframe tracks.
43857		 *
43858		 * @type {Array<KeyframeTrack>}
43859		 */
43860		this.tracks = tracks;
43861
43862		/**
43863		 * The clip's duration in seconds.
43864		 *
43865		 * @type {number}
43866		 */
43867		this.duration = duration;
43868
43869		/**
43870		 * Defines how the animation is blended/combined when two or more animations
43871		 * are simultaneously played.
43872		 *
43873		 * @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
43874		 */
43875		this.blendMode = blendMode;
43876
43877		/**
43878		 * The UUID of the animation clip.
43879		 *
43880		 * @type {string}
43881		 * @readonly
43882		 */
43883		this.uuid = generateUUID();
43884
43885		/**
43886		 * An object that can be used to store custom data about the animation clip.
43887		 * It should not hold references to functions as these will not be cloned.
43888		 *
43889		 * @type {Object}
43890		 */
43891		this.userData = {};
43892
43893		// this means it should figure out its duration by scanning the tracks
43894		if ( this.duration < 0 ) {
43895
43896			this.resetDuration();
43897
43898		}
43899
43900	}
43901
43902	/**
43903	 * Factory method for creating an animation clip from the given JSON.
43904	 *
43905	 * @static
43906	 * @param {Object} json - The serialized animation clip.
43907	 * @return {AnimationClip} The new animation clip.
43908	 */
43909	static parse( json ) {
43910
43911		const tracks = [],
43912			jsonTracks = json.tracks,
43913			frameTime = 1.0 / ( json.fps || 1.0 );
43914
43915		for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) {
43916
43917			tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );
43918
43919		}
43920
43921		const clip = new this( json.name, json.duration, tracks, json.blendMode );
43922		clip.uuid = json.uuid;
43923
43924		clip.userData = JSON.parse( json.userData || '{}' );
43925
43926		return clip;
43927
43928	}
43929
43930	/**
43931	 * Serializes the given animation clip into JSON.
43932	 *
43933	 * @static
43934	 * @param {AnimationClip} clip - The animation clip to serialize.
43935	 * @return {Object} The JSON object.
43936	 */
43937	static toJSON( clip ) {
43938
43939		const tracks = [],
43940			clipTracks = clip.tracks;
43941
43942		const json = {
43943
43944			'name': clip.name,
43945			'duration': clip.duration,
43946			'tracks': tracks,
43947			'uuid': clip.uuid,
43948			'blendMode': clip.blendMode,
43949			'userData': JSON.stringify( clip.userData ),
43950
43951		};
43952
43953		for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) {
43954
43955			tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );
43956
43957		}
43958
43959		return json;
43960
43961	}
43962
43963	/**
43964	 * Returns a new animation clip from the passed morph targets array of a
43965	 * geometry, taking a name and the number of frames per second.
43966	 *
43967	 * Note: The fps parameter is required, but the animation speed can be
43968	 * overridden via {@link AnimationAction#setDuration}.
43969	 *
43970	 * @static
43971	 * @param {string} name - The name of the animation clip.
43972	 * @param {Array<Object>} morphTargetSequence - A sequence of morph targets.
43973	 * @param {number} fps - The Frames-Per-Second value.
43974	 * @param {boolean} noLoop - Whether the clip should be no loop or not.
43975	 * @return {AnimationClip} The new animation clip.
43976	 */
43977	static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
43978
43979		const numMorphTargets = morphTargetSequence.length;
43980		const tracks = [];
43981
43982		for ( let i = 0; i < numMorphTargets; i ++ ) {
43983
43984			let times = [];
43985			let values = [];
43986
43987			times.push(
43988				( i + numMorphTargets - 1 ) % numMorphTargets,
43989				i,
43990				( i + 1 ) % numMorphTargets );
43991
43992			values.push( 0, 1, 0 );
43993
43994			const order = getKeyframeOrder( times );
43995			times = sortedArray( times, 1, order );
43996			values = sortedArray( values, 1, order );
43997
43998			// if there is a key at the first frame, duplicate it as the
43999			// last frame as well for perfect loop.
44000			if ( ! noLoop && times[ 0 ] === 0 ) {
44001
44002				times.push( numMorphTargets );
44003				values.push( values[ 0 ] );
44004
44005			}
44006
44007			tracks.push(
44008				new NumberKeyframeTrack(
44009					'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',
44010					times, values
44011				).scale( 1.0 / fps ) );
44012
44013		}
44014
44015		return new this( name, -1, tracks );
44016
44017	}
44018
44019	/**
44020	 * Searches for an animation clip by name, taking as its first parameter
44021	 * either an array of clips, or a mesh or geometry that contains an
44022	 * array named "animations" property.
44023	 *
44024	 * @static
44025	 * @param {(Array<AnimationClip>|Object3D)} objectOrClipArray - The array or object to search through.
44026	 * @param {string} name - The name to search for.
44027	 * @return {?AnimationClip} The found animation clip. Returns `null` if no clip has been found.
44028	 */
44029	static findByName( objectOrClipArray, name ) {
44030
44031		let clipArray = objectOrClipArray;
44032
44033		if ( ! Array.isArray( objectOrClipArray ) ) {
44034
44035			const o = objectOrClipArray;
44036			clipArray = o.geometry && o.geometry.animations || o.animations;
44037
44038		}
44039
44040		for ( let i = 0; i < clipArray.length; i ++ ) {
44041
44042			if ( clipArray[ i ].name === name ) {
44043
44044				return clipArray[ i ];
44045
44046			}
44047
44048		}
44049
44050		return null;
44051
44052	}
44053
44054	/**
44055	 * Returns an array of new AnimationClips created from the morph target
44056	 * sequences of a geometry, trying to sort morph target names into
44057	 * animation-group-based patterns like "Walk_001, Walk_002, Run_001, Run_002...".
44058	 *
44059	 * See {@link MD2Loader#parse} as an example for how the method should be used.
44060	 *
44061	 * @static
44062	 * @param {Array<Object>} morphTargets - A sequence of morph targets.
44063	 * @param {number} fps - The Frames-Per-Second value.
44064	 * @param {boolean} noLoop - Whether the clip should be no loop or not.
44065	 * @return {Array<AnimationClip>} An array of new animation clips.
44066	 */
44067	static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
44068
44069		const animationToMorphTargets = {};
44070
44071		// tested with https://regex101.com/ on trick sequences
44072		// such flamingo_flyA_003, flamingo_run1_003, crdeath0059
44073		const pattern = /^([\w-]*?)([\d]+)$/;
44074
44075		// sort morph target names into animation groups based
44076		// patterns like Walk_001, Walk_002, Run_001, Run_002
44077		for ( let i = 0, il = morphTargets.length; i < il; i ++ ) {
44078
44079			const morphTarget = morphTargets[ i ];
44080			const parts = morphTarget.name.match( pattern );
44081
44082			if ( parts && parts.length > 1 ) {
44083
44084				const name = parts[ 1 ];
44085
44086				let animationMorphTargets = animationToMorphTargets[ name ];
44087
44088				if ( ! animationMorphTargets ) {
44089
44090					animationToMorphTargets[ name ] = animationMorphTargets = [];
44091
44092				}
44093
44094				animationMorphTargets.push( morphTarget );
44095
44096			}
44097
44098		}
44099
44100		const clips = [];
44101
44102		for ( const name in animationToMorphTargets ) {
44103
44104			clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
44105
44106		}
44107
44108		return clips;
44109
44110	}
44111
44112	/**
44113	 * Sets the duration of this clip to the duration of its longest keyframe track.
44114	 *
44115	 * @return {AnimationClip} A reference to this animation clip.
44116	 */
44117	resetDuration() {
44118
44119		const tracks = this.tracks;
44120		let duration = 0;
44121
44122		for ( let i = 0, n = tracks.length; i !== n; ++ i ) {
44123
44124			const track = this.tracks[ i ];
44125
44126			duration = Math.max( duration, track.times[ track.times.length - 1 ] );
44127
44128		}
44129
44130		this.duration = duration;
44131
44132		return this;
44133
44134	}
44135
44136	/**
44137	 * Trims all tracks to the clip's duration.
44138	 *
44139	 * @return {AnimationClip} A reference to this animation clip.
44140	 */
44141	trim() {
44142
44143		for ( let i = 0; i < this.tracks.length; i ++ ) {
44144
44145			this.tracks[ i ].trim( 0, this.duration );
44146
44147		}
44148
44149		return this;
44150
44151	}
44152
44153	/**
44154	 * Performs minimal validation on each track in the clip. Returns `true` if all
44155	 * tracks are valid.
44156	 *
44157	 * @return {boolean} Whether the clip's keyframes are valid or not.
44158	 */
44159	validate() {
44160
44161		let valid = true;
44162
44163		for ( let i = 0; i < this.tracks.length; i ++ ) {
44164
44165			valid = valid && this.tracks[ i ].validate();
44166
44167		}
44168
44169		return valid;
44170
44171	}
44172
44173	/**
44174	 * Optimizes each track by removing equivalent sequential keys (which are
44175	 * common in morph target sequences).
44176	 *
44177	 * @return {AnimationClip} A reference to this animation clip.
44178	 */
44179	optimize() {
44180
44181		for ( let i = 0; i < this.tracks.length; i ++ ) {
44182
44183			this.tracks[ i ].optimize();
44184
44185		}
44186
44187		return this;
44188
44189	}
44190
44191	/**
44192	 * Returns a new animation clip with copied values from this instance.
44193	 *
44194	 * @return {AnimationClip} A clone of this instance.
44195	 */
44196	clone() {
44197
44198		const tracks = [];
44199
44200		for ( let i = 0; i < this.tracks.length; i ++ ) {
44201
44202			tracks.push( this.tracks[ i ].clone() );
44203
44204		}
44205
44206		const clip = new this.constructor( this.name, this.duration, tracks, this.blendMode );
44207
44208		clip.userData = JSON.parse( JSON.stringify( this.userData ) );
44209
44210		return clip;
44211
44212	}
44213
44214	/**
44215	 * Serializes this animation clip into JSON.
44216	 *
44217	 * @return {Object} The JSON object.
44218	 */
44219	toJSON() {
44220
44221		return this.constructor.toJSON( this );
44222
44223	}
44224
44225}
44226
44227function getTrackTypeForValueTypeName( typeName ) {
44228
44229	switch ( typeName.toLowerCase() ) {
44230
44231		case 'scalar':
44232		case 'double':
44233		case 'float':
44234		case 'number':
44235		case 'integer':
44236
44237			return NumberKeyframeTrack;
44238
44239		case 'vector':
44240		case 'vector2':
44241		case 'vector3':
44242		case 'vector4':
44243
44244			return VectorKeyframeTrack;
44245
44246		case 'color':
44247
44248			return ColorKeyframeTrack;
44249
44250		case 'quaternion':
44251
44252			return QuaternionKeyframeTrack;
44253
44254		case 'bool':
44255		case 'boolean':
44256
44257			return BooleanKeyframeTrack;
44258
44259		case 'string':
44260
44261			return StringKeyframeTrack;
44262
44263	}
44264
44265	throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
44266
44267}
44268
44269function parseKeyframeTrack( json ) {
44270
44271	if ( json.type === undefined ) {
44272
44273		throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );
44274
44275	}
44276
44277	const trackType = getTrackTypeForValueTypeName( json.type );
44278
44279	if ( json.times === undefined ) {
44280
44281		const times = [], values = [];
44282
44283		flattenJSON( json.keys, times, values, 'value' );
44284
44285		json.times = times;
44286		json.values = values;
44287
44288	}
44289
44290	let track;
44291
44292	// derived classes can define a static parse method
44293	if ( trackType.parse !== undefined ) {
44294
44295		track = trackType.parse( json );
44296
44297	} else {
44298
44299		// by default, we assume a constructor compatible with the base
44300		track = new trackType( json.name, json.times, json.values, json.interpolation );
44301
44302	}
44303
44304	if ( hasTangents( json.settings ) ) {
44305
44306		track.settings = {
44307			inTangents: convertArray( json.settings.inTangents, Float32Array ),
44308			outTangents: convertArray( json.settings.outTangents, Float32Array )
44309		};
44310
44311	}
44312
44313	return track;
44314
44315}
44316
44317/**
44318 * @class
44319 * @classdesc A simple caching system, used internally by {@link FileLoader}.
44320 * To enable caching across all loaders that use {@link FileLoader}, add `THREE.Cache.enabled = true.` once in your app.
44321 * @hideconstructor
44322 */
44323const Cache = {
44324
44325	/**
44326	 * Whether caching is enabled or not.
44327	 *
44328	 * @static
44329	 * @type {boolean}
44330	 * @default false
44331	 */
44332	enabled: false,
44333
44334	/**
44335	 * A dictionary that holds cached files.
44336	 *
44337	 * @static
44338	 * @type {Object<string,Object>}
44339	 */
44340	files: {},
44341
44342	/**
44343	 * Adds a cache entry with a key to reference the file. If this key already
44344	 * holds a file, it is overwritten.
44345	 *
44346	 * @static
44347	 * @param {string} key - The key to reference the cached file.
44348	 * @param {Object} file -  The file to be cached.
44349	 */
44350	add: function ( key, file ) {
44351
44352		if ( this.enabled === false ) return;
44353
44354		if ( isBlobURL( key ) ) return;
44355
44356		// log( 'Cache', 'Adding key:', key );
44357
44358		this.files[ key ] = file;
44359
44360	},
44361
44362	/**
44363	 * Gets the cached value for the given key.
44364	 *
44365	 * @static
44366	 * @param {string} key - The key to reference the cached file.
44367	 * @return {Object|undefined} The cached file. If the key does not exist `undefined` is returned.
44368	 */
44369	get: function ( key ) {
44370
44371		if ( this.enabled === false ) return;
44372
44373		if ( isBlobURL( key ) ) return;
44374
44375		// log( 'Cache', 'Checking key:', key );
44376
44377		return this.files[ key ];
44378
44379	},
44380
44381	/**
44382	 * Removes the cached file associated with the given key.
44383	 *
44384	 * @static
44385	 * @param {string} key - The key to reference the cached file.
44386	 */
44387	remove: function ( key ) {
44388
44389		delete this.files[ key ];
44390
44391	},
44392
44393	/**
44394	 * Remove all values from the cache.
44395	 *
44396	 * @static
44397	 */
44398	clear: function () {
44399
44400		this.files = {};
44401
44402	}
44403
44404};
44405
44406/**
44407 * Returns true if the given cache key contains the blob: scheme.
44408 *
44409 * @private
44410 * @param {string} key - The cache key.
44411 * @return {boolean} Whether the given cache key contains the blob: scheme or not.
44412 */
44413function isBlobURL( key ) {
44414
44415	try {
44416
44417		const urlString = key.slice( key.indexOf( ':' ) + 1 ); // remove type identifier
44418
44419		const url = new URL( urlString );
44420		return url.protocol === 'blob:';
44421
44422	} catch ( e ) {
44423
44424		// If the string is not a valid URL, it throws an error
44425		return false;
44426
44427	}
44428
44429}
44430
44431/**
44432 * Handles and keeps track of loaded and pending data. A default global
44433 * instance of this class is created and used by loaders if not supplied
44434 * manually.
44435 *
44436 * In general that should be sufficient, however there are times when it can
44437 * be useful to have separate loaders - for example if you want to show
44438 * separate loading bars for objects and textures.
44439 *
44440 * ```js
44441 * const manager = new THREE.LoadingManager();
44442 * manager.onLoad = () => console.log( 'Loading complete!' );
44443 *
44444 * const loader1 = new OBJLoader( manager );
44445 * const loader2 = new ColladaLoader( manager );
44446 * ```
44447 */
44448class LoadingManager {
44449
44450	/**
44451	 * Constructs a new loading manager.
44452	 *
44453	 * @param {Function} [onLoad] - Executes when all items have been loaded.
44454	 * @param {Function} [onProgress] - Executes when single items have been loaded.
44455	 * @param {Function} [onError] - Executes when an error occurs.
44456	 */
44457	constructor( onLoad, onProgress, onError ) {
44458
44459		const scope = this;
44460
44461		let isLoading = false;
44462		let itemsLoaded = 0;
44463		let itemsTotal = 0;
44464		let urlModifier = undefined;
44465		const handlers = [];
44466
44467		// Refer to #5689 for the reason why we don't set .onStart
44468		// in the constructor
44469
44470		/**
44471		 * Executes when an item starts loading.
44472		 *
44473		 * @type {Function|undefined}
44474		 * @default undefined
44475		 */
44476		this.onStart = undefined;
44477
44478		/**
44479		 * Executes when all items have been loaded.
44480		 *
44481		 * @type {Function|undefined}
44482		 * @default undefined
44483		 */
44484		this.onLoad = onLoad;
44485
44486		/**
44487		 * Executes when single items have been loaded.
44488		 *
44489		 * @type {Function|undefined}
44490		 * @default undefined
44491		 */
44492		this.onProgress = onProgress;
44493
44494		/**
44495		 * Executes when an error occurs.
44496		 *
44497		 * @type {Function|undefined}
44498		 * @default undefined
44499		 */
44500		this.onError = onError;
44501
44502		/**
44503		 * Used for aborting ongoing requests in loaders using this manager.
44504		 *
44505		 * @private
44506		 * @type {AbortController | null}
44507		 */
44508		this._abortController = null;
44509
44510		/**
44511		 * This should be called by any loader using the manager when the loader
44512		 * starts loading an item.
44513		 *
44514		 * @param {string} url - The URL to load.
44515		 */
44516		this.itemStart = function ( url ) {
44517
44518			itemsTotal ++;
44519
44520			if ( isLoading === false ) {
44521
44522				if ( scope.onStart !== undefined ) {
44523
44524					scope.onStart( url, itemsLoaded, itemsTotal );
44525
44526				}
44527
44528			}
44529
44530			isLoading = true;
44531
44532		};
44533
44534		/**
44535		 * This should be called by any loader using the manager when the loader
44536		 * ended loading an item.
44537		 *
44538		 * @param {string} url - The URL of the loaded item.
44539		 */
44540		this.itemEnd = function ( url ) {
44541
44542			itemsLoaded ++;
44543
44544			if ( scope.onProgress !== undefined ) {
44545
44546				scope.onProgress( url, itemsLoaded, itemsTotal );
44547
44548			}
44549
44550			if ( itemsLoaded === itemsTotal ) {
44551
44552				isLoading = false;
44553
44554				if ( scope.onLoad !== undefined ) {
44555
44556					scope.onLoad();
44557
44558				}
44559
44560			}
44561
44562		};
44563
44564		/**
44565		 * This should be called by any loader using the manager when the loader
44566		 * encounters an error when loading an item.
44567		 *
44568		 * @param {string} url - The URL of the item that produces an error.
44569		 */
44570		this.itemError = function ( url ) {
44571
44572			if ( scope.onError !== undefined ) {
44573
44574				scope.onError( url );
44575
44576			}
44577
44578		};
44579
44580		/**
44581		 * Given a URL, uses the URL modifier callback (if any) and returns a
44582		 * resolved URL. If no URL modifier is set, returns the original URL.
44583		 *
44584		 * @param {string} url - The URL to load.
44585		 * @return {string} The resolved URL.
44586		 */
44587		this.resolveURL = function ( url ) {
44588
44589			// Normalize to NFC so that Unicode URIs (e.g. from glTF)
44590			// are percent-encoded correctly per RFC 3987.
44591
44592			url = url.normalize( 'NFC' );
44593
44594			if ( urlModifier ) {
44595
44596				return urlModifier( url );
44597
44598			}
44599
44600			return url;
44601
44602		};
44603
44604		/**
44605		 * If provided, the callback will be passed each resource URL before a
44606		 * request is sent. The callback may return the original URL, or a new URL to
44607		 * override loading behavior. This behavior can be used to load assets from
44608		 * .ZIP files, drag-and-drop APIs, and Data URIs.
44609		 *
44610		 * ```js
44611		 * const blobs = {'fish.gltf': blob1, 'diffuse.png': blob2, 'normal.png': blob3};
44612		 *
44613		 * const manager = new THREE.LoadingManager();
44614		 *
44615		 * // Initialize loading manager with URL callback.
44616		 * const objectURLs = [];
44617		 * manager.setURLModifier( ( url ) => {
44618		 *
44619		 * 	url = URL.createObjectURL( blobs[ url ] );
44620		 * 	objectURLs.push( url );
44621		 * 	return url;
44622		 *
44623		 * } );
44624		 *
44625		 * // Load as usual, then revoke the blob URLs.
44626		 * const loader = new GLTFLoader( manager );
44627		 * loader.load( 'fish.gltf', (gltf) => {
44628		 *
44629		 * 	scene.add( gltf.scene );
44630		 * 	objectURLs.forEach( ( url ) => URL.revokeObjectURL( url ) );
44631		 *
44632		 * } );
44633		 * ```
44634		 *
44635		 * @param {function(string):string} transform - URL modifier callback. Called with an URL and must return a resolved URL.
44636		 * @return {LoadingManager} A reference to this loading manager.
44637		 */
44638		this.setURLModifier = function ( transform ) {
44639
44640			urlModifier = transform;
44641
44642			return this;
44643
44644		};
44645
44646		/**
44647		 * Registers a loader with the given regular expression. Can be used to
44648		 * define what loader should be used in order to load specific files. A
44649		 * typical use case is to overwrite the default loader for textures.
44650		 *
44651		 * ```js
44652		 * // add handler for TGA textures
44653		 * manager.addHandler( /\.tga$/i, new TGALoader() );
44654		 * ```
44655		 *
44656		 * @param {string} regex - A regular expression.
44657		 * @param {Loader} loader - A loader that should handle matched cases.
44658		 * @return {LoadingManager} A reference to this loading manager.
44659		 */
44660		this.addHandler = function ( regex, loader ) {
44661
44662			handlers.push( regex, loader );
44663
44664			return this;
44665
44666		};
44667
44668		/**
44669		 * Removes the loader for the given regular expression.
44670		 *
44671		 * @param {string} regex - A regular expression.
44672		 * @return {LoadingManager} A reference to this loading manager.
44673		 */
44674		this.removeHandler = function ( regex ) {
44675
44676			const index = handlers.indexOf( regex );
44677
44678			if ( index !== -1 ) {
44679
44680				handlers.splice( index, 2 );
44681
44682			}
44683
44684			return this;
44685
44686		};
44687
44688		/**
44689		 * Can be used to retrieve the registered loader for the given file path.
44690		 *
44691		 * @param {string} file - The file path.
44692		 * @return {?Loader} The registered loader. Returns `null` if no loader was found.
44693		 */
44694		this.getHandler = function ( file ) {
44695
44696			for ( let i = 0, l = handlers.length; i < l; i += 2 ) {
44697
44698				const regex = handlers[ i ];
44699				const loader = handlers[ i + 1 ];
44700
44701				if ( regex.global ) regex.lastIndex = 0; // see #17920
44702
44703				if ( regex.test( file ) ) {
44704
44705					return loader;
44706
44707				}
44708
44709			}
44710
44711			return null;
44712
44713		};
44714
44715		/**
44716		 * Can be used to abort ongoing loading requests in loaders using this manager.
44717		 * The abort only works if the loaders implement {@link Loader#abort} and `AbortSignal.any()`
44718		 * is supported in the browser.
44719		 *
44720		 * @return {LoadingManager} A reference to this loading manager.
44721		 */
44722		this.abort = function () {
44723
44724
44725			this.abortController.abort();
44726			this._abortController = null;
44727
44728			return this;
44729
44730		};
44731
44732	}
44733
44734	// TODO: Revert this back to a single member variable once this issue has been fixed
44735	// https://github.com/cloudflare/workerd/issues/3657
44736
44737	/**
44738	 * Used for aborting ongoing requests in loaders using this manager.
44739	 *
44740	 * @type {AbortController}
44741	 */
44742	get abortController() {
44743
44744		if ( ! this._abortController ) {
44745
44746			this._abortController = new AbortController();
44747
44748		}
44749
44750		return this._abortController;
44751
44752	}
44753
44754}
44755
44756/**
44757 * The global default loading manager.
44758 *
44759 * @constant
44760 * @type {LoadingManager}
44761 */
44762const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager();
44763
44764/**
44765 * Abstract base class for loaders.
44766 *
44767 * @abstract
44768 */
44769class Loader {
44770
44771	/**
44772	 * Constructs a new loader.
44773	 *
44774	 * @param {LoadingManager} [manager] - The loading manager.
44775	 */
44776	constructor( manager ) {
44777
44778		/**
44779		 * The loading manager.
44780		 *
44781		 * @type {LoadingManager}
44782		 * @default DefaultLoadingManager
44783		 */
44784		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
44785
44786		/**
44787		 * The crossOrigin string to implement CORS for loading the url from a
44788		 * different domain that allows CORS.
44789		 *
44790		 * @type {string}
44791		 * @default 'anonymous'
44792		 */
44793		this.crossOrigin = 'anonymous';
44794
44795		/**
44796		 * Whether the XMLHttpRequest uses credentials.
44797		 *
44798		 * @type {boolean}
44799		 * @default false
44800		 */
44801		this.withCredentials = false;
44802
44803		/**
44804		 * The base path from which the asset will be loaded.
44805		 *
44806		 * @type {string}
44807		 */
44808		this.path = '';
44809
44810		/**
44811		 * The base path from which additional resources like textures will be loaded.
44812		 *
44813		 * @type {string}
44814		 */
44815		this.resourcePath = '';
44816
44817		/**
44818		 * The [request header](https://developer.mozilla.org/en-US/docs/Glossary/Request_header)
44819		 * used in HTTP request.
44820		 *
44821		 * @type {Object<string, any>}
44822		 */
44823		this.requestHeader = {};
44824
44825		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
44826
44827			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
44828
44829		}
44830
44831	}
44832
44833	/**
44834	 * This method needs to be implemented by all concrete loaders. It holds the
44835	 * logic for loading assets from the backend.
44836	 *
44837	 * @abstract
44838	 * @param {string} url - The path/URL of the file to be loaded.
44839	 * @param {Function} onLoad - Executed when the loading process has been finished.
44840	 * @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
44841	 * @param {onErrorCallback} [onError] - Executed when errors occur.
44842	 */
44843	load( /* url, onLoad, onProgress, onError */ ) {}
44844
44845	/**
44846	 * A async version of {@link Loader#load}.
44847	 *
44848	 * @param {string} url - The path/URL of the file to be loaded.
44849	 * @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
44850	 * @return {Promise} A Promise that resolves when the asset has been loaded.
44851	 */
44852	loadAsync( url, onProgress ) {
44853
44854		const scope = this;
44855
44856		return new Promise( function ( resolve, reject ) {
44857
44858			scope.load( url, resolve, onProgress, reject );
44859
44860		} );
44861
44862	}
44863
44864	/**
44865	 * This method needs to be implemented by all concrete loaders. It holds the
44866	 * logic for parsing the asset into three.js entities.
44867	 *
44868	 * @abstract
44869	 * @param {any} data - The data to parse.
44870	 */
44871	parse( /* data */ ) {}
44872
44873	/**
44874	 * Sets the `crossOrigin` String to implement CORS for loading the URL
44875	 * from a different domain that allows CORS.
44876	 *
44877	 * @param {string} crossOrigin - The `crossOrigin` value.
44878	 * @return {Loader} A reference to this instance.
44879	 */
44880	setCrossOrigin( crossOrigin ) {
44881
44882		this.crossOrigin = crossOrigin;
44883		return this;
44884
44885	}
44886
44887	/**
44888	 * Whether the XMLHttpRequest uses credentials such as cookies, authorization
44889	 * headers or TLS client certificates, see [XMLHttpRequest.withCredentials](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials).
44890	 *
44891	 * Note: This setting has no effect if you are loading files locally or from the same domain.
44892	 *
44893	 * @param {boolean} value - The `withCredentials` value.
44894	 * @return {Loader} A reference to this instance.
44895	 */
44896	setWithCredentials( value ) {
44897
44898		this.withCredentials = value;
44899		return this;
44900
44901	}
44902
44903	/**
44904	 * Sets the base path for the asset.
44905	 *
44906	 * @param {string} path - The base path.
44907	 * @return {Loader} A reference to this instance.
44908	 */
44909	setPath( path ) {
44910
44911		this.path = path;
44912		return this;
44913
44914	}
44915
44916	/**
44917	 * Sets the base path for dependent resources like textures.
44918	 *
44919	 * @param {string} resourcePath - The resource path.
44920	 * @return {Loader} A reference to this instance.
44921	 */
44922	setResourcePath( resourcePath ) {
44923
44924		this.resourcePath = resourcePath;
44925		return this;
44926
44927	}
44928
44929	/**
44930	 * Sets the given request header.
44931	 *
44932	 * @param {Object} requestHeader - A [request header](https://developer.mozilla.org/en-US/docs/Glossary/Request_header)
44933	 * for configuring the HTTP request.
44934	 * @return {Loader} A reference to this instance.
44935	 */
44936	setRequestHeader( requestHeader ) {
44937
44938		this.requestHeader = requestHeader;
44939		return this;
44940
44941	}
44942
44943	/**
44944	 * This method can be implemented in loaders for aborting ongoing requests.
44945	 *
44946	 * @abstract
44947	 * @return {Loader} A reference to this instance.
44948	 */
44949	abort() {
44950
44951		return this;
44952
44953	}
44954
44955}
44956
44957/**
44958 * Callback for onProgress in loaders.
44959 *
44960 * @callback onProgressCallback
44961 * @param {ProgressEvent} event - An instance of `ProgressEvent` that represents the current loading status.
44962 */
44963
44964/**
44965 * Callback for onError in loaders.
44966 *
44967 * @callback onErrorCallback
44968 * @param {Error} error - The error which occurred during the loading process.
44969 */
44970
44971/**
44972 * The default material name that is used by loaders
44973 * when creating materials for loaded 3D objects.
44974 *
44975 * Note: Not all loaders might honor this setting.
44976 *
44977 * @static
44978 * @type {string}
44979 * @default '__DEFAULT'
44980 */
44981Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT';
44982
44983const loading = {};
44984
44985class HttpError extends Error {
44986
44987	constructor( message, response ) {
44988
44989		super( message );
44990		this.response = response;
44991
44992	}
44993
44994}
44995
44996/**
44997 * A low level class for loading resources with the Fetch API, used internally by
44998 * most loaders. It can also be used directly to load any file type that does
44999 * not have a loader.
45000 *
45001 * This loader supports caching. If you want to use it, add `THREE.Cache.enabled = true;`
45002 * once to your application.
45003 *
45004 * ```js
45005 * const loader = new THREE.FileLoader();
45006 * const data = await loader.loadAsync( 'example.txt' );
45007 * ```
45008 *
45009 * @augments Loader
45010 */
45011class FileLoader extends Loader {
45012
45013	/**
45014	 * Constructs a new file loader.
45015	 *
45016	 * @param {LoadingManager} [manager] - The loading manager.
45017	 */
45018	constructor( manager ) {
45019
45020		super( manager );
45021
45022		/**
45023		 * The expected mime type. Valid values can be found
45024		 * [here](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser/parseFromString#mimetype)
45025		 *
45026		 * @type {string}
45027		 */
45028		this.mimeType = '';
45029
45030		/**
45031		 * The expected response type.
45032		 *
45033		 * @type {('arraybuffer'|'blob'|'document'|'json'|'')}
45034		 * @default ''
45035		 */
45036		this.responseType = '';
45037
45038		/**
45039		 * Used for aborting requests.
45040		 *
45041		 * @private
45042		 * @type {AbortController}
45043		 */
45044		this._abortController = new AbortController();
45045
45046	}
45047
45048	/**
45049	 * Starts loading from the given URL and pass the loaded response to the `onLoad()` callback.
45050	 *
45051	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
45052	 * @param {function(any)} onLoad - Executed when the loading process has been finished.
45053	 * @param {onProgressCallback} [onProgress] - Executed while the loading is in progress.
45054	 * @param {onErrorCallback} [onError] - Executed when errors occur.
45055	 */
45056	load( url, onLoad, onProgress, onError ) {
45057
45058		if ( url === undefined ) url = '';
45059
45060		if ( this.path !== undefined ) url = this.path + url;
45061
45062		url = this.manager.resolveURL( url );
45063
45064		const cached = Cache.get( `file:${url}` );
45065
45066		if ( cached !== undefined ) {
45067
45068			this.manager.itemStart( url );
45069
45070			setTimeout( () => {
45071
45072				if ( onLoad ) onLoad( cached );
45073
45074				this.manager.itemEnd( url );
45075
45076			}, 0 );
45077
45078			return;
45079
45080		}
45081
45082		// Check if request is duplicate
45083
45084		if ( loading[ url ] !== undefined ) {
45085
45086			loading[ url ].push( {
45087
45088				onLoad: onLoad,
45089				onProgress: onProgress,
45090				onError: onError
45091
45092			} );
45093
45094			return;
45095
45096		}
45097
45098		// Initialise array for duplicate requests
45099		loading[ url ] = [];
45100
45101		loading[ url ].push( {
45102			onLoad: onLoad,
45103			onProgress: onProgress,
45104			onError: onError,
45105		} );
45106
45107		// create request
45108		const req = new Request( url, {
45109			headers: new Headers( this.requestHeader ),
45110			credentials: this.withCredentials ? 'include' : 'same-origin',
45111			signal: ( typeof AbortSignal.any === 'function' ) ? AbortSignal.any( [ this._abortController.signal, this.manager.abortController.signal ] ) : this._abortController.signal
45112		} );
45113
45114		// record states ( avoid data race )
45115		const mimeType = this.mimeType;
45116		const responseType = this.responseType;
45117
45118		// start the fetch
45119		fetch( req )
45120			.then( response => {
45121
45122				if ( response.status === 200 || response.status === 0 ) {
45123
45124					// Some browsers return HTTP Status 0 when using non-http protocol
45125					// e.g. 'file://' or 'data://'. Handle as success.
45126
45127					if ( response.status === 0 ) {
45128
45129						warn( 'FileLoader: HTTP Status 0 received.' );
45130
45131					}
45132
45133					// Workaround: Checking if response.body === undefined for Alipay browser #23548
45134
45135					if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) {
45136
45137						return response;
45138
45139					}
45140
45141					const callbacks = loading[ url ];
45142					const reader = response.body.getReader();
45143
45144					// Nginx needs X-File-Size check
45145					// https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content
45146					const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' );
45147					const total = contentLength ? parseInt( contentLength ) : 0;
45148					const lengthComputable = total !== 0;
45149					let loaded = 0;
45150
45151					// periodically read data into the new stream tracking while download progress
45152					const stream = new ReadableStream( {
45153						start( controller ) {
45154
45155							readData();
45156
45157							function readData() {
45158
45159								reader.read().then( ( { done, value } ) => {
45160
45161									if ( done ) {
45162
45163										controller.close();
45164
45165									} else {
45166
45167										loaded += value.byteLength;
45168
45169										const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } );
45170										for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
45171
45172											const callback = callbacks[ i ];
45173											if ( callback.onProgress ) callback.onProgress( event );
45174
45175										}
45176
45177										controller.enqueue( value );
45178										readData();
45179
45180									}
45181
45182								}, ( e ) => {
45183
45184									controller.error( e );
45185
45186								} );
45187
45188							}
45189
45190						}
45191
45192					} );
45193
45194					return new Response( stream );
45195
45196				} else {
45197
45198					throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response );
45199
45200				}
45201
45202			} )
45203			.then( response => {
45204
45205				switch ( responseType ) {
45206
45207					case 'arraybuffer':
45208
45209						return response.arrayBuffer();
45210
45211					case 'blob':
45212
45213						return response.blob();
45214
45215					case 'document':
45216
45217						return response.text()
45218							.then( text => {
45219
45220								const parser = new DOMParser();
45221								return parser.parseFromString( text, mimeType );
45222
45223							} );
45224
45225					case 'json':
45226
45227						return response.json();
45228
45229					default:
45230
45231						if ( mimeType === '' ) {
45232
45233							return response.text();
45234
45235						} else {
45236
45237							// sniff encoding
45238							const re = /charset="?([^;"\s]*)"?/i;
45239							const exec = re.exec( mimeType );
45240							const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined;
45241							const decoder = new TextDecoder( label );
45242							return response.arrayBuffer().then( ab => decoder.decode( ab ) );
45243
45244						}
45245
45246				}
45247
45248			} )
45249			.then( data => {
45250
45251				// Add to cache only on HTTP success, so that we do not cache
45252				// error response bodies as proper responses to requests.
45253				Cache.add( `file:${url}`, data );
45254
45255				const callbacks = loading[ url ];
45256				delete loading[ url ];
45257
45258				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
45259
45260					const callback = callbacks[ i ];
45261					if ( callback.onLoad ) callback.onLoad( data );
45262
45263				}
45264
45265			} )
45266			.catch( err => {
45267
45268				// Abort errors and other errors are handled the same
45269
45270				const callbacks = loading[ url ];
45271
45272				if ( callbacks === undefined ) {
45273
45274					// When onLoad was called and url was deleted in `loading`
45275					this.manager.itemError( url );
45276					throw err;
45277
45278				}
45279
45280				delete loading[ url ];
45281
45282				for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
45283
45284					const callback = callbacks[ i ];
45285					if ( callback.onError ) callback.onError( err );
45286
45287				}
45288
45289				this.manager.itemError( url );
45290
45291			} )
45292			.finally( () => {
45293
45294				this.manager.itemEnd( url );
45295
45296			} );
45297
45298		this.manager.itemStart( url );
45299
45300	}
45301
45302	/**
45303	 * Sets the expected response type.
45304	 *
45305	 * @param {('arraybuffer'|'blob'|'document'|'json'|'')} value - The response type.
45306	 * @return {FileLoader} A reference to this file loader.
45307	 */
45308	setResponseType( value ) {
45309
45310		this.responseType = value;
45311		return this;
45312
45313	}
45314
45315	/**
45316	 * Sets the expected mime type of the loaded file.
45317	 *
45318	 * @param {string} value - The mime type.
45319	 * @return {FileLoader} A reference to this file loader.
45320	 */
45321	setMimeType( value ) {
45322
45323		this.mimeType = value;
45324		return this;
45325
45326	}
45327
45328	/**
45329	 * Aborts ongoing fetch requests.
45330	 *
45331	 * @return {FileLoader} A reference to this instance.
45332	 */
45333	abort() {
45334
45335		this._abortController.abort();
45336		this._abortController = new AbortController();
45337
45338		return this;
45339
45340	}
45341
45342}
45343
45344/**
45345 * Class for loading animation clips in the JSON format. The files are internally
45346 * loaded via {@link FileLoader}.
45347 *
45348 * ```js
45349 * const loader = new THREE.AnimationLoader();
45350 * const animations = await loader.loadAsync( 'animations/animation.js' );
45351 * ```
45352 *
45353 * @augments Loader
45354 */
45355class AnimationLoader extends Loader {
45356
45357	/**
45358	 * Constructs a new animation loader.
45359	 *
45360	 * @param {LoadingManager} [manager] - The loading manager.
45361	 */
45362	constructor( manager ) {
45363
45364		super( manager );
45365
45366	}
45367
45368	/**
45369	 * Starts loading from the given URL and pass the loaded animations as an array
45370	 * holding instances of {@link AnimationClip} to the `onLoad()` callback.
45371	 *
45372	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
45373	 * @param {function(Array<AnimationClip>)} onLoad - Executed when the loading process has been finished.
45374	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
45375	 * @param {onErrorCallback} onError - Executed when errors occur.
45376	 */
45377	load( url, onLoad, onProgress, onError ) {
45378
45379		const scope = this;
45380
45381		const loader = new FileLoader( this.manager );
45382		loader.setPath( this.path );
45383		loader.setRequestHeader( this.requestHeader );
45384		loader.setWithCredentials( this.withCredentials );
45385		loader.load( url, function ( text ) {
45386
45387			try {
45388
45389				onLoad( scope.parse( JSON.parse( text ) ) );
45390
45391			} catch ( e ) {
45392
45393				if ( onError ) {
45394
45395					onError( e );
45396
45397				} else {
45398
45399					error( e );
45400
45401				}
45402
45403				scope.manager.itemError( url );
45404
45405			}
45406
45407		}, onProgress, onError );
45408
45409	}
45410
45411	/**
45412	 * Parses the given JSON object and returns an array of animation clips.
45413	 *
45414	 * @param {Object} json - The serialized animation clips.
45415	 * @return {Array<AnimationClip>} The parsed animation clips.
45416	 */
45417	parse( json ) {
45418
45419		const animations = [];
45420
45421		for ( let i = 0; i < json.length; i ++ ) {
45422
45423			const clip = AnimationClip.parse( json[ i ] );
45424
45425			animations.push( clip );
45426
45427		}
45428
45429		return animations;
45430
45431	}
45432
45433}
45434
45435/**
45436 * Abstract base class for loading compressed texture formats S3TC, ASTC or ETC.
45437 * Textures are internally loaded via {@link FileLoader}.
45438 *
45439 * Derived classes have to implement the `parse()` method which holds the parsing
45440 * for the respective format.
45441 *
45442 * @abstract
45443 * @augments Loader
45444 */
45445class CompressedTextureLoader extends Loader {
45446
45447	/**
45448	 * Constructs a new compressed texture loader.
45449	 *
45450	 * @param {LoadingManager} [manager] - The loading manager.
45451	 */
45452	constructor( manager ) {
45453
45454		super( manager );
45455
45456	}
45457
45458	/**
45459	 * Starts loading from the given URL and passes the loaded compressed texture
45460	 * to the `onLoad()` callback. The method also returns a new texture object which can
45461	 * directly be used for material creation. If you do it this way, the texture
45462	 * may pop up in your scene once the respective loading process is finished.
45463	 *
45464	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
45465	 * @param {function(CompressedTexture)} onLoad - Executed when the loading process has been finished.
45466	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
45467	 * @param {onErrorCallback} onError - Executed when errors occur.
45468	 * @return {CompressedTexture} The compressed texture.
45469	 */
45470	load( url, onLoad, onProgress, onError ) {
45471
45472		const scope = this;
45473
45474		const images = [];
45475
45476		const texture = new CompressedTexture();
45477
45478		const loader = new FileLoader( this.manager );
45479		loader.setPath( this.path );
45480		loader.setResponseType( 'arraybuffer' );
45481		loader.setRequestHeader( this.requestHeader );
45482		loader.setWithCredentials( scope.withCredentials );
45483
45484		let loaded = 0;
45485
45486		function loadTexture( i ) {
45487
45488			loader.load( url[ i ], function ( buffer ) {
45489
45490				const texDatas = scope.parse( buffer, true );
45491
45492				images[ i ] = {
45493					width: texDatas.width,
45494					height: texDatas.height,
45495					format: texDatas.format,
45496					mipmaps: texDatas.mipmaps
45497				};
45498
45499				loaded += 1;
45500
45501				if ( loaded === 6 ) {
45502
45503					if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
45504
45505					texture.image = images;
45506					texture.format = texDatas.format;
45507					texture.needsUpdate = true;
45508
45509					if ( onLoad ) onLoad( texture );
45510
45511				}
45512
45513			}, onProgress, onError );
45514
45515		}
45516
45517		if ( Array.isArray( url ) ) {
45518
45519			for ( let i = 0, il = url.length; i < il; ++ i ) {
45520
45521				loadTexture( i );
45522
45523			}
45524
45525		} else {
45526
45527			// compressed cubemap texture stored in a single DDS file
45528
45529			loader.load( url, function ( buffer ) {
45530
45531				const texDatas = scope.parse( buffer, true );
45532
45533				if ( texDatas.isCubemap ) {
45534
45535					const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
45536
45537					for ( let f = 0; f < faces; f ++ ) {
45538
45539						images[ f ] = { mipmaps: [] };
45540
45541						for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
45542
45543							images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
45544							images[ f ].format = texDatas.format;
45545							images[ f ].width = texDatas.width;
45546							images[ f ].height = texDatas.height;
45547
45548						}
45549
45550					}
45551
45552					texture.image = images;
45553
45554				} else {
45555
45556					texture.image.width = texDatas.width;
45557					texture.image.height = texDatas.height;
45558					texture.mipmaps = texDatas.mipmaps;
45559
45560				}
45561
45562				if ( texDatas.mipmapCount === 1 ) {
45563
45564					texture.minFilter = LinearFilter;
45565
45566				}
45567
45568				texture.format = texDatas.format;
45569				texture.needsUpdate = true;
45570
45571				if ( onLoad ) onLoad( texture );
45572
45573			}, onProgress, onError );
45574
45575		}
45576
45577		return texture;
45578
45579	}
45580
45581}
45582
45583const _loading = new WeakMap();
45584
45585/**
45586 * A loader for loading images. The class loads images with the HTML `Image` API.
45587 *
45588 * ```js
45589 * const loader = new THREE.ImageLoader();
45590 * const image = await loader.loadAsync( 'image.png' );
45591 * ```
45592 * Please note that `ImageLoader` has dropped support for progress
45593 * events in `r84`. For an `ImageLoader` that supports progress events, see
45594 * [this thread](https://github.com/mrdoob/three.js/issues/10439#issuecomment-275785639).
45595 *
45596 * @augments Loader
45597 */
45598class ImageLoader extends Loader {
45599
45600	/**
45601	 * Constructs a new image loader.
45602	 *
45603	 * @param {LoadingManager} [manager] - The loading manager.
45604	 */
45605	constructor( manager ) {
45606
45607		super( manager );
45608
45609	}
45610
45611	/**
45612	 * Starts loading from the given URL and passes the loaded image
45613	 * to the `onLoad()` callback. The method also returns a new `Image` object which can
45614	 * directly be used for texture creation. If you do it this way, the texture
45615	 * may pop up in your scene once the respective loading process is finished.
45616	 *
45617	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
45618	 * @param {function(Image)} onLoad - Executed when the loading process has been finished.
45619	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
45620	 * @param {onErrorCallback} onError - Executed when errors occur.
45621	 * @return {Image} The image.
45622	 */
45623	load( url, onLoad, onProgress, onError ) {
45624
45625		if ( this.path !== undefined ) url = this.path + url;
45626
45627		url = this.manager.resolveURL( url );
45628
45629		const scope = this;
45630
45631		const cached = Cache.get( `image:${url}` );
45632
45633		if ( cached !== undefined ) {
45634
45635			if ( cached.complete === true ) {
45636
45637				scope.manager.itemStart( url );
45638
45639				setTimeout( function () {
45640
45641					if ( onLoad ) onLoad( cached );
45642
45643					scope.manager.itemEnd( url );
45644
45645				}, 0 );
45646
45647			} else {
45648
45649				let arr = _loading.get( cached );
45650
45651				if ( arr === undefined ) {
45652
45653					arr = [];
45654					_loading.set( cached, arr );
45655
45656				}
45657
45658				arr.push( { onLoad, onError } );
45659
45660			}
45661
45662			return cached;
45663
45664		}
45665
45666		const image = createElementNS( 'img' );
45667
45668		function onImageLoad() {
45669
45670			removeEventListeners();
45671
45672			if ( onLoad ) onLoad( this );
45673
45674			//
45675
45676			const callbacks = _loading.get( this ) || [];
45677
45678			for ( let i = 0; i < callbacks.length; i ++ ) {
45679
45680				const callback = callbacks[ i ];
45681				if ( callback.onLoad ) callback.onLoad( this );
45682
45683			}
45684
45685			_loading.delete( this );
45686
45687			scope.manager.itemEnd( url );
45688
45689		}
45690
45691		function onImageError( event ) {
45692
45693			removeEventListeners();
45694
45695			if ( onError ) onError( event );
45696
45697			Cache.remove( `image:${url}` );
45698
45699			//
45700
45701			const callbacks = _loading.get( this ) || [];
45702
45703			for ( let i = 0; i < callbacks.length; i ++ ) {
45704
45705				const callback = callbacks[ i ];
45706				if ( callback.onError ) callback.onError( event );
45707
45708			}
45709
45710			_loading.delete( this );
45711
45712
45713			scope.manager.itemError( url );
45714			scope.manager.itemEnd( url );
45715
45716		}
45717
45718		function removeEventListeners() {
45719
45720			image.removeEventListener( 'load', onImageLoad, false );
45721			image.removeEventListener( 'error', onImageError, false );
45722
45723		}
45724
45725		image.addEventListener( 'load', onImageLoad, false );
45726		image.addEventListener( 'error', onImageError, false );
45727
45728		if ( url.slice( 0, 5 ) !== 'data:' ) {
45729
45730			if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
45731
45732		}
45733
45734		Cache.add( `image:${url}`, image );
45735		scope.manager.itemStart( url );
45736
45737		image.src = url;
45738
45739		return image;
45740
45741	}
45742
45743}
45744
45745/**
45746 * Class for loading cube textures. Images are internally loaded via {@link ImageLoader}.
45747 *
45748 * The loader returns an instance of {@link CubeTexture} and expects the cube map to
45749 * be defined as six separate images representing the sides of a cube. Other cube map definitions
45750 * like vertical and horizontal cross, column and row layouts are not supported.
45751 *
45752 * Note that, by convention, cube maps are specified in a coordinate system
45753 * in which positive-x is to the right when looking up the positive-z axis --
45754 * in other words, using a left-handed coordinate system. Since three.js uses
45755 * a right-handed coordinate system, environment maps used in three.js will
45756 * have pos-x and neg-x swapped.
45757 *
45758 * The loaded cube texture is in sRGB color space. Meaning {@link Texture#colorSpace}
45759 * is set to `SRGBColorSpace` by default.
45760 *
45761 * ```js
45762 * const loader = new THREE.CubeTextureLoader().setPath( 'textures/cubeMaps/' );
45763 * const cubeTexture = await loader.loadAsync( [
45764 * 	'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png'
45765 * ] );
45766 * scene.background = cubeTexture;
45767 * ```
45768 *
45769 * @augments Loader
45770 */
45771class CubeTextureLoader extends Loader {
45772
45773	/**
45774	 * Constructs a new cube texture loader.
45775	 *
45776	 * @param {LoadingManager} [manager] - The loading manager.
45777	 */
45778	constructor( manager ) {
45779
45780		super( manager );
45781
45782	}
45783
45784	/**
45785	 * Starts loading from the given URL and pass the fully loaded cube texture
45786	 * to the `onLoad()` callback. The method also returns a new cube texture object which can
45787	 * directly be used for material creation. If you do it this way, the cube texture
45788	 * may pop up in your scene once the respective loading process is finished.
45789	 *
45790	 * @param {Array<string>} urls - Array of 6 URLs to images, one for each side of the
45791	 * cube texture. The urls should be specified in the following order: pos-x,
45792	 * neg-x, pos-y, neg-y, pos-z, neg-z. An array of data URIs are allowed as well.
45793	 * @param {function(CubeTexture)} onLoad - Executed when the loading process has been finished.
45794	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
45795	 * @param {onErrorCallback} onError - Executed when errors occur.
45796	 * @return {CubeTexture} The cube texture.
45797	 */
45798	load( urls, onLoad, onProgress, onError ) {
45799
45800		const texture = new CubeTexture();
45801		texture.colorSpace = SRGBColorSpace;
45802
45803		const loader = new ImageLoader( this.manager );
45804		loader.setCrossOrigin( this.crossOrigin );
45805		loader.setPath( this.path );
45806
45807		let loaded = 0;
45808
45809		function loadTexture( i ) {
45810
45811			loader.load( urls[ i ], function ( image ) {
45812
45813				texture.images[ i ] = image;
45814
45815				loaded ++;
45816
45817				if ( loaded === 6 ) {
45818
45819					texture.needsUpdate = true;
45820
45821					if ( onLoad ) onLoad( texture );
45822
45823				}
45824
45825			}, undefined, onError );
45826
45827		}
45828
45829		for ( let i = 0; i < urls.length; ++ i ) {
45830
45831			loadTexture( i );
45832
45833		}
45834
45835		return texture;
45836
45837	}
45838
45839}
45840
45841/**
45842 * Abstract base class for loading binary texture formats RGBE, EXR or TGA.
45843 * Textures are internally loaded via {@link FileLoader}.
45844 *
45845 * Derived classes have to implement the `parse()` method which holds the parsing
45846 * for the respective format.
45847 *
45848 * @abstract
45849 * @augments Loader
45850 */
45851class DataTextureLoader extends Loader {
45852
45853	/**
45854	 * Constructs a new data texture loader.
45855	 *
45856	 * @param {LoadingManager} [manager] - The loading manager.
45857	 */
45858	constructor( manager ) {
45859
45860		super( manager );
45861
45862	}
45863
45864	/**
45865	 * Starts loading from the given URL and passes the loaded data texture
45866	 * to the `onLoad()` callback. The method also returns a new texture object which can
45867	 * directly be used for material creation. If you do it this way, the texture
45868	 * may pop up in your scene once the respective loading process is finished.
45869	 *
45870	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
45871	 * @param {function(DataTexture)} onLoad - Executed when the loading process has been finished.
45872	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
45873	 * @param {onErrorCallback} onError - Executed when errors occur.
45874	 * @return {DataTexture} The data texture.
45875	 */
45876	load( url, onLoad, onProgress, onError ) {
45877
45878		const scope = this;
45879
45880		const texture = new DataTexture();
45881
45882		const loader = new FileLoader( this.manager );
45883		loader.setResponseType( 'arraybuffer' );
45884		loader.setRequestHeader( this.requestHeader );
45885		loader.setPath( this.path );
45886		loader.setWithCredentials( scope.withCredentials );
45887		loader.load( url, function ( buffer ) {
45888
45889			let texData;
45890
45891			try {
45892
45893				texData = scope.parse( buffer );
45894
45895			} catch ( e ) {
45896
45897				if ( onError !== undefined ) {
45898
45899					onError( e );
45900
45901				} else {
45902
45903					error( e );
45904
45905				}
45906
45907				return;
45908
45909			}
45910
45911			scope._applyTexData( texture, texData );
45912
45913			if ( onLoad ) onLoad( texture, texData );
45914
45915		}, onProgress, onError );
45916
45917
45918		return texture;
45919
45920	}
45921
45922	/**
45923	 * Parses the given buffer and returns a configured data texture. Use this method
45924	 * for parsing texture data that is already in memory (e.g. drag and drop or data
45925	 * loaded from a server) without going through {@link DataTextureLoader#load}.
45926	 *
45927	 * @param {ArrayBuffer} buffer - The raw texture data.
45928	 * @return {DataTexture} The data texture.
45929	 */
45930	createDataTexture( buffer ) {
45931
45932		const texture = new DataTexture();
45933
45934		this._applyTexData( texture, this.parse( buffer ) );
45935
45936		return texture;
45937
45938	}
45939
45940	/**
45941	 * Applies the given parsed texture data to the given data texture.
45942	 *
45943	 * @private
45944	 * @param {DataTexture} texture - The data texture.
45945	 * @param {DataTextureLoader~TexData} texData - The parsed texture data.
45946	 */
45947	_applyTexData( texture, texData ) {
45948
45949		if ( texData.image !== undefined ) {
45950
45951			texture.image = texData.image;
45952
45953		} else if ( texData.data !== undefined ) {
45954
45955			texture.image.width = texData.width;
45956			texture.image.height = texData.height;
45957			texture.image.data = texData.data;
45958
45959		}
45960
45961		texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
45962		texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
45963
45964		texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
45965		texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
45966
45967		texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
45968
45969		if ( texData.colorSpace !== undefined ) {
45970
45971			texture.colorSpace = texData.colorSpace;
45972
45973		}
45974
45975		if ( texData.flipY !== undefined ) {
45976
45977			texture.flipY = texData.flipY;
45978
45979		}
45980
45981		if ( texData.format !== undefined ) {
45982
45983			texture.format = texData.format;
45984
45985		}
45986
45987		if ( texData.type !== undefined ) {
45988
45989			texture.type = texData.type;
45990
45991		}
45992
45993		if ( texData.mipmaps !== undefined ) {
45994
45995			texture.mipmaps = texData.mipmaps;
45996			texture.minFilter = LinearMipmapLinearFilter; // presumably...
45997
45998		}
45999
46000		if ( texData.mipmapCount === 1 ) {
46001
46002			texture.minFilter = LinearFilter;
46003
46004		}
46005
46006		if ( texData.generateMipmaps !== undefined ) {
46007
46008			texture.generateMipmaps = texData.generateMipmaps;
46009
46010		}
46011
46012		texture.needsUpdate = true;
46013
46014	}
46015
46016}
46017
46018/**
46019 * Class for loading textures. Images are internally
46020 * loaded via {@link ImageLoader}.
46021 *
46022 * ```js
46023 * const loader = new THREE.TextureLoader();
46024 * const texture = await loader.loadAsync( 'textures/land_ocean_ice_cloud_2048.jpg' );
46025 *
46026 * const material = new THREE.MeshBasicMaterial( { map:texture } );
46027 * ```
46028 * Please note that `TextureLoader` has dropped support for progress
46029 * events in `r84`. For a `TextureLoader` that supports progress events, see
46030 * [this thread](https://github.com/mrdoob/three.js/issues/10439#issuecomment-293260145).
46031 *
46032 * @augments Loader
46033 */
46034class TextureLoader extends Loader {
46035
46036	/**
46037	 * Constructs a new texture loader.
46038	 *
46039	 * @param {LoadingManager} [manager] - The loading manager.
46040	 */
46041	constructor( manager ) {
46042
46043		super( manager );
46044
46045	}
46046
46047	/**
46048	 * Starts loading from the given URL and pass the fully loaded texture
46049	 * to the `onLoad()` callback. The method also returns a new texture object which can
46050	 * directly be used for material creation. If you do it this way, the texture
46051	 * may pop up in your scene once the respective loading process is finished.
46052	 *
46053	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
46054	 * @param {function(Texture)} onLoad - Executed when the loading process has been finished.
46055	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
46056	 * @param {onErrorCallback} onError - Executed when errors occur.
46057	 * @return {Texture} The texture.
46058	 */
46059	load( url, onLoad, onProgress, onError ) {
46060
46061		const texture = new Texture();
46062
46063		const loader = new ImageLoader( this.manager );
46064		loader.setCrossOrigin( this.crossOrigin );
46065		loader.setPath( this.path );
46066
46067		loader.load( url, function ( image ) {
46068
46069			texture.image = image;
46070			texture.needsUpdate = true;
46071
46072			if ( onLoad !== undefined ) {
46073
46074				onLoad( texture );
46075
46076			}
46077
46078		}, onProgress, onError );
46079
46080		return texture;
46081
46082	}
46083
46084}
46085
46086/**
46087 * Abstract base class for lights - all other light types inherit the
46088 * properties and methods described here.
46089 *
46090 * @abstract
46091 * @augments Object3D
46092 */
46093class Light extends Object3D {
46094
46095	/**
46096	 * Constructs a new light.
46097	 *
46098	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
46099	 * @param {number} [intensity=1] - The light's strength/intensity.
46100	 */
46101	constructor( color, intensity = 1 ) {
46102
46103		super();
46104
46105		/**
46106		 * This flag can be used for type testing.
46107		 *
46108		 * @type {boolean}
46109		 * @readonly
46110		 * @default true
46111		 */
46112		this.isLight = true;
46113
46114		this.type = 'Light';
46115
46116		/**
46117		 * The light's color.
46118		 *
46119		 * @type {Color}
46120		 */
46121		this.color = new Color( color );
46122
46123		/**
46124		 * The light's intensity.
46125		 *
46126		 * @type {number}
46127		 * @default 1
46128		 */
46129		this.intensity = intensity;
46130
46131	}
46132
46133	copy( source, recursive ) {
46134
46135		super.copy( source, recursive );
46136
46137		this.color.copy( source.color );
46138		this.intensity = source.intensity;
46139
46140		return this;
46141
46142	}
46143
46144	toJSON( meta ) {
46145
46146		const data = super.toJSON( meta );
46147
46148		data.object.color = this.color.getHex();
46149		data.object.intensity = this.intensity;
46150
46151		return data;
46152
46153	}
46154
46155}
46156
46157/**
46158 * A light source positioned directly above the scene, with color fading from
46159 * the sky color to the ground color.
46160 *
46161 * This light cannot be used to cast shadows.
46162 *
46163 * ```js
46164 * const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
46165 * scene.add( light );
46166 * ```
46167 *
46168 * @augments Light
46169 */
46170class HemisphereLight extends Light {
46171
46172	/**
46173	 * Constructs a new hemisphere light.
46174	 *
46175	 * @param {(number|Color|string)} [skyColor=0xffffff] - The light's sky color.
46176	 * @param {(number|Color|string)} [groundColor=0xffffff] - The light's ground color.
46177	 * @param {number} [intensity=1] - The light's strength/intensity.
46178	 */
46179	constructor( skyColor, groundColor, intensity ) {
46180
46181		super( skyColor, intensity );
46182
46183		/**
46184		 * This flag can be used for type testing.
46185		 *
46186		 * @type {boolean}
46187		 * @readonly
46188		 * @default true
46189		 */
46190		this.isHemisphereLight = true;
46191
46192		this.type = 'HemisphereLight';
46193
46194		this.position.copy( Object3D.DEFAULT_UP );
46195		this.updateMatrix();
46196
46197		/**
46198		 * The light's ground color.
46199		 *
46200		 * @type {Color}
46201		 */
46202		this.groundColor = new Color( groundColor );
46203
46204	}
46205
46206	copy( source, recursive ) {
46207
46208		super.copy( source, recursive );
46209
46210		this.groundColor.copy( source.groundColor );
46211
46212		return this;
46213
46214	}
46215
46216	toJSON( meta ) {
46217
46218		const data = super.toJSON( meta );
46219
46220		data.object.groundColor = this.groundColor.getHex();
46221
46222		return data;
46223
46224	}
46225
46226}
46227
46228const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
46229const _lightPositionWorld = /*@__PURE__*/ new Vector3();
46230const _lookTarget = /*@__PURE__*/ new Vector3();
46231
46232/**
46233 * Abstract base class for light shadow classes. These classes
46234 * represent the shadow configuration for different light types.
46235 *
46236 * @abstract
46237 */
46238class LightShadow {
46239
46240	/**
46241	 * Constructs a new light shadow.
46242	 *
46243	 * @param {Camera} camera - The light's view of the world.
46244	 */
46245	constructor( camera ) {
46246
46247		/**
46248		 * The light's view of the world.
46249		 *
46250		 * @type {Camera}
46251		 */
46252		this.camera = camera;
46253
46254		/**
46255		 * The intensity of the shadow. The default is `1`.
46256		 * Valid values are in the range `[0, 1]`.
46257		 *
46258		 * @type {number}
46259		 * @default 1
46260		 */
46261		this.intensity = 1;
46262
46263		/**
46264		 * Shadow map bias, how much to add or subtract from the normalized depth
46265		 * when deciding whether a surface is in shadow.
46266		 *
46267		 * The default is `0`. Very tiny adjustments here (in the order of `0.0001`)
46268		 * may help reduce artifacts in shadows.
46269		 *
46270		 * @type {number}
46271		 * @default 0
46272		 */
46273		this.bias = 0;
46274
46275		/**
46276		 * A node version of `bias`. Only supported with `WebGPURenderer`.
46277		 *
46278		 * If a bias node is defined, `bias` has no effect.
46279		 *
46280		 * @type {?Node<float>}
46281		 * @default null
46282		 */
46283		this.biasNode = null;
46284
46285		/**
46286		 * Defines how much the position used to query the shadow map is offset along
46287		 * the object normal. The default is `0`. Increasing this value can be used to
46288		 * reduce shadow acne especially in large scenes where light shines onto
46289		 * geometry at a shallow angle. The cost is that shadows may appear distorted.
46290		 *
46291		 * @type {number}
46292		 * @default 0
46293		 */
46294		this.normalBias = 0;
46295
46296		/**
46297		 * Setting this to values greater than 1 will blur the edges of the shadow.
46298		 * High values will cause unwanted banding effects in the shadows - a greater
46299		 * map size will allow for a higher value to be used here before these effects
46300		 * become visible.
46301		 *
46302		 * The property has no effect when the shadow map type is `BasicShadowMap`.
46303		 *
46304		 * @type {number}
46305		 * @default 1
46306		 */
46307		this.radius = 1;
46308
46309		/**
46310		 * The amount of samples to use when blurring a VSM shadow map.
46311		 *
46312		 * @type {number}
46313		 * @default 8
46314		 */
46315		this.blurSamples = 8;
46316
46317		/**
46318		 * Defines the width and height of the shadow map. Higher values give better quality
46319		 * shadows at the cost of computation time. Values must be powers of two.
46320		 *
46321		 * @type {Vector2}
46322		 * @default (512,512)
46323		 */
46324		this.mapSize = new Vector2( 512, 512 );
46325
46326		/**
46327		 * The type of shadow texture. The default is `UnsignedByteType`.
46328		 *
46329		 * @type {number}
46330		 * @default UnsignedByteType
46331		 */
46332		this.mapType = UnsignedByteType;
46333
46334		/**
46335		 * The depth map generated using the internal camera; a location beyond a
46336		 * pixel's depth is in shadow. Computed internally during rendering.
46337		 *
46338		 * @type {?RenderTarget}
46339		 * @default null
46340		 */
46341		this.map = null;
46342
46343		/**
46344		 * The distribution map generated using the internal camera; an occlusion is
46345		 * calculated based on the distribution of depths. Computed internally during
46346		 * rendering.
46347		 *
46348		 * @type {?RenderTarget}
46349		 * @default null
46350		 */
46351		this.mapPass = null;
46352
46353		/**
46354		 * Model to shadow camera space, to compute location and depth in shadow map.
46355		 * This is computed internally during rendering.
46356		 *
46357		 * @type {Matrix4}
46358		 */
46359		this.matrix = new Matrix4();
46360
46361		/**
46362		 * Enables automatic updates of the light's shadow. If you do not require dynamic
46363		 * lighting / shadows, you may set this to `false`.
46364		 *
46365		 * @type {boolean}
46366		 * @default true
46367		 */
46368		this.autoUpdate = true;
46369
46370		/**
46371		 * When set to `true`, shadow maps will be updated in the next `render` call.
46372		 * If you have set {@link LightShadow#autoUpdate} to `false`, you will need to
46373		 * set this property to `true` and then make a render call to update the light's shadow.
46374		 *
46375		 * @type {boolean}
46376		 * @default false
46377		 */
46378		this.needsUpdate = false;
46379
46380		this._frustum = new Frustum();
46381		this._frameExtents = new Vector2( 1, 1 );
46382
46383		this._viewportCount = 1;
46384
46385		this._viewports = [
46386
46387			new Vector4( 0, 0, 1, 1 )
46388
46389		];
46390
46391	}
46392
46393	/**
46394	 * Used internally by the renderer to get the number of viewports that need
46395	 * to be rendered for this shadow.
46396	 *
46397	 * @return {number} The viewport count.
46398	 */
46399	getViewportCount() {
46400
46401		return this._viewportCount;
46402
46403	}
46404
46405	/**
46406	 * Used internally by the renderer to get the camera that renders the given viewport.
46407	 *
46408	 * @param {number} [viewportIndex=0] - The viewport index.
46409	 * @return {Camera} The shadow camera.
46410	 */
46411	getCamera( /* viewportIndex */ ) {
46412
46413		return this.camera;
46414
46415	}
46416
46417	/**
46418	 * Gets the shadow cameras frustum. Used internally by the renderer to cull objects.
46419	 *
46420	 * @return {Frustum} The shadow camera frustum.
46421	 */
46422	getFrustum() {
46423
46424		return this._frustum;
46425
46426	}
46427
46428	/**
46429	 * Update the matrices for the camera and shadow, used internally by the renderer.
46430	 *
46431	 * @param {Light} light - The light for which the shadow is being rendered.
46432	 */
46433	updateMatrices( light ) {
46434
46435		const shadowCamera = this.camera;
46436		_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
46437		shadowCamera.position.copy( _lightPositionWorld );
46438
46439		_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
46440		shadowCamera.lookAt( _lookTarget );
46441		shadowCamera.updateMatrixWorld();
46442		this._updateMatrix( shadowCamera, this.matrix, this._frustum );
46443
46444	}
46445
46446	/**
46447	 * Updates a shadow projection matrix and its corresponding frustum.
46448	 *
46449	 * @private
46450	 * @param {Camera} shadowCamera - The shadow camera.
46451	 * @param {Matrix4} shadowMatrix - The target shadow matrix.
46452	 * @param {Frustum} frustum - The target frustum.
46453	 * @param {Vector4} [viewport] - The viewport within the shadow atlas.
46454	 */
46455	_updateMatrix( shadowCamera, shadowMatrix, frustum, viewport ) {
46456
46457		_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
46458		frustum.setFromProjectionMatrix( _projScreenMatrix, shadowCamera.coordinateSystem, shadowCamera.reversedDepth );
46459
46460		const frameExtents = this._frameExtents;
46461		const scaleX = viewport ? viewport.z / frameExtents.x : 1;
46462		const scaleY = viewport ? viewport.w / frameExtents.y : 1;
46463		const offsetX = viewport ? viewport.x / frameExtents.x : 0;
46464		const offsetY = viewport ? viewport.y / frameExtents.y : 0;
46465
46466		if ( shadowCamera.coordinateSystem === WebGPUCoordinateSystem || shadowCamera.reversedDepth ) {
46467
46468			shadowMatrix.set(
46469				0.5 * scaleX, 0.0, 0.0, 0.5 * scaleX + offsetX,
46470				0.0, 0.5 * scaleY, 0.0, 0.5 * scaleY + offsetY,
46471				0.0, 0.0, 1.0, 0.0, // Identity Z (preserving the correct [0, 1] range from the projection matrix)
46472				0.0, 0.0, 0.0, 1.0
46473			);
46474
46475		} else {
46476
46477			shadowMatrix.set(
46478				0.5 * scaleX, 0.0, 0.0, 0.5 * scaleX + offsetX,
46479				0.0, 0.5 * scaleY, 0.0, 0.5 * scaleY + offsetY,
46480				0.0, 0.0, 0.5, 0.5,
46481				0.0, 0.0, 0.0, 1.0
46482			);
46483
46484		}
46485
46486		shadowMatrix.multiply( _projScreenMatrix );
46487
46488	}
46489
46490	/**
46491	 * Returns a viewport definition for the given viewport index.
46492	 *
46493	 * @param {number} viewportIndex - The viewport index.
46494	 * @return {Vector4} The viewport.
46495	 */
46496	getViewport( viewportIndex ) {
46497
46498		return this._viewports[ viewportIndex ];
46499
46500	}
46501
46502	/**
46503	 * Returns the frame extends.
46504	 *
46505	 * @return {Vector2} The frame extends.
46506	 */
46507	getFrameExtents() {
46508
46509		return this._frameExtents;
46510
46511	}
46512
46513	/**
46514	 * Frees the GPU-related resources allocated by this instance. Call this
46515	 * method whenever this instance is no longer used in your app.
46516	 */
46517	dispose() {
46518
46519		if ( this.map ) {
46520
46521			this.map.dispose();
46522
46523		}
46524
46525		if ( this.mapPass ) {
46526
46527			this.mapPass.dispose();
46528
46529		}
46530
46531	}
46532
46533	/**
46534	 * Copies the values of the given light shadow instance to this instance.
46535	 *
46536	 * @param {LightShadow} source - The light shadow to copy.
46537	 * @return {LightShadow} A reference to this light shadow instance.
46538	 */
46539	copy( source ) {
46540
46541		this.camera = source.camera.clone();
46542
46543		this.intensity = source.intensity;
46544
46545		this.bias = source.bias;
46546		this.radius = source.radius;
46547
46548		this.autoUpdate = source.autoUpdate;
46549		this.needsUpdate = source.needsUpdate;
46550		this.normalBias = source.normalBias;
46551		this.blurSamples = source.blurSamples;
46552
46553		this.mapSize.copy( source.mapSize );
46554
46555		this.biasNode = source.biasNode;
46556
46557		return this;
46558
46559	}
46560
46561	/**
46562	 * Returns a new light shadow instance with copied values from this instance.
46563	 *
46564	 * @return {LightShadow} A clone of this instance.
46565	 */
46566	clone() {
46567
46568		return new this.constructor().copy( this );
46569
46570	}
46571
46572	/**
46573	 * Serializes the light shadow into JSON.
46574	 *
46575	 * @return {Object} A JSON object representing the serialized light shadow.
46576	 * @see {@link ObjectLoader#parse}
46577	 */
46578	toJSON() {
46579
46580		const object = {};
46581
46582		object.intensity = this.intensity;
46583		object.bias = this.bias;
46584		object.normalBias = this.normalBias;
46585		object.radius = this.radius;
46586		object.blurSamples = this.blurSamples;
46587		object.mapSize = this.mapSize.toArray();
46588
46589		object.camera = this.camera.toJSON( false ).object;
46590		delete object.camera.matrix;
46591
46592		return object;
46593
46594	}
46595
46596}
46597
46598const _position$2 = /*@__PURE__*/ new Vector3();
46599const _quaternion$2 = /*@__PURE__*/ new Quaternion();
46600const _scale$2 = /*@__PURE__*/ new Vector3();
46601
46602/**
46603 * Abstract base class for cameras. This class should always be inherited
46604 * when you build a new camera.
46605 *
46606 * @abstract
46607 * @augments Object3D
46608 */
46609class Camera extends Object3D {
46610
46611	/**
46612	 * Constructs a new camera.
46613	 */
46614	constructor() {
46615
46616		super();
46617
46618		/**
46619		 * This flag can be used for type testing.
46620		 *
46621		 * @type {boolean}
46622		 * @readonly
46623		 * @default true
46624		 */
46625		this.isCamera = true;
46626
46627		this.type = 'Camera';
46628
46629		/**
46630		 * The inverse of the camera's world matrix.
46631		 *
46632		 * @type {Matrix4}
46633		 */
46634		this.matrixWorldInverse = new Matrix4();
46635
46636		/**
46637		 * The camera's projection matrix.
46638		 *
46639		 * @type {Matrix4}
46640		 */
46641		this.projectionMatrix = new Matrix4();
46642
46643		/**
46644		 * The inverse of the camera's projection matrix.
46645		 *
46646		 * @type {Matrix4}
46647		 */
46648		this.projectionMatrixInverse = new Matrix4();
46649
46650		/**
46651		 * The coordinate system in which the camera is used.
46652		 *
46653		 * @type {(WebGLCoordinateSystem|WebGPUCoordinateSystem)}
46654		 */
46655		this.coordinateSystem = WebGLCoordinateSystem;
46656
46657		this._reversedDepth = false;
46658
46659	}
46660
46661	/**
46662	 * The flag that indicates whether the camera uses a reversed depth buffer.
46663	 *
46664	 * @type {boolean}
46665	 * @default false
46666	 */
46667	get reversedDepth() {
46668
46669		return this._reversedDepth;
46670
46671	}
46672
46673	copy( source, recursive ) {
46674
46675		super.copy( source, recursive );
46676
46677		this.matrixWorldInverse.copy( source.matrixWorldInverse );
46678
46679		this.projectionMatrix.copy( source.projectionMatrix );
46680		this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
46681
46682		this.coordinateSystem = source.coordinateSystem;
46683
46684		return this;
46685
46686	}
46687
46688	/**
46689	 * Returns a vector representing the ("look") direction of the 3D object in world space.
46690	 *
46691	 * This method is overwritten since cameras have a different forward vector compared to other
46692	 * 3D objects. A camera looks down its local, negative z-axis by default.
46693	 *
46694	 * @param {Vector3} target - The target vector the result is stored to.
46695	 * @return {Vector3} The 3D object's direction in world space.
46696	 */
46697	getWorldDirection( target ) {
46698
46699		return super.getWorldDirection( target ).negate();
46700
46701	}
46702
46703	updateMatrixWorld( force ) {
46704
46705		super.updateMatrixWorld( force );
46706
46707		// exclude scale from view matrix to be glTF conform
46708
46709		this.matrixWorld.decompose( _position$2, _quaternion$2, _scale$2 );
46710
46711		if ( _scale$2.x === 1 && _scale$2.y === 1 && _scale$2.z === 1 ) {
46712
46713			this.matrixWorldInverse.copy( this.matrixWorld ).invert();
46714
46715		} else {
46716
46717			this.matrixWorldInverse.compose( _position$2, _quaternion$2, _scale$2.set( 1, 1, 1 ) ).invert();
46718
46719		}
46720
46721	}
46722
46723	updateWorldMatrix( updateParents, updateChildren, force = false ) {
46724
46725		super.updateWorldMatrix( updateParents, updateChildren, force );
46726
46727		// exclude scale from view matrix to be glTF conform
46728
46729		this.matrixWorld.decompose( _position$2, _quaternion$2, _scale$2 );
46730
46731		if ( _scale$2.x === 1 && _scale$2.y === 1 && _scale$2.z === 1 ) {
46732
46733			this.matrixWorldInverse.copy( this.matrixWorld ).invert();
46734
46735		} else {
46736
46737			this.matrixWorldInverse.compose( _position$2, _quaternion$2, _scale$2.set( 1, 1, 1 ) ).invert();
46738
46739		}
46740
46741	}
46742
46743	clone() {
46744
46745		return new this.constructor().copy( this );
46746
46747	}
46748
46749}
46750
46751const _v3$1 = /*@__PURE__*/ new Vector3();
46752const _minTarget = /*@__PURE__*/ new Vector2();
46753const _maxTarget = /*@__PURE__*/ new Vector2();
46754
46755/**
46756 * Camera that uses [perspective projection](https://en.wikipedia.org/wiki/Perspective_(graphical)).
46757 *
46758 * This projection mode is designed to mimic the way the human eye sees. It
46759 * is the most common projection mode used for rendering a 3D scene.
46760 *
46761 * ```js
46762 * const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
46763 * scene.add( camera );
46764 * ```
46765 *
46766 * @augments Camera
46767 */
46768class PerspectiveCamera extends Camera {
46769
46770	/**
46771	 * Constructs a new perspective camera.
46772	 *
46773	 * @param {number} [fov=50] - The vertical field of view.
46774	 * @param {number} [aspect=1] - The aspect ratio.
46775	 * @param {number} [near=0.1] - The camera's near plane.
46776	 * @param {number} [far=2000] - The camera's far plane.
46777	 */
46778	constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
46779
46780		super();
46781
46782		/**
46783		 * This flag can be used for type testing.
46784		 *
46785		 * @type {boolean}
46786		 * @readonly
46787		 * @default true
46788		 */
46789		this.isPerspectiveCamera = true;
46790
46791		this.type = 'PerspectiveCamera';
46792
46793		/**
46794		 * The vertical field of view, from bottom to top of view,
46795		 * in degrees.
46796		 *
46797		 * @type {number}
46798		 * @default 50
46799		 */
46800		this.fov = fov;
46801
46802		/**
46803		 * The zoom factor of the camera.
46804		 *
46805		 * @type {number}
46806		 * @default 1
46807		 */
46808		this.zoom = 1;
46809
46810		/**
46811		 * The camera's near plane. The valid range is greater than `0`
46812		 * and less than the current value of {@link PerspectiveCamera#far}.
46813		 *
46814		 * Note that, unlike for the {@link OrthographicCamera}, `0` is <em>not</em> a
46815		 * valid value for a perspective camera's near plane.
46816		 *
46817		 * @type {number}
46818		 * @default 0.1
46819		 */
46820		this.near = near;
46821
46822		/**
46823		 * The camera's far plane. Must be greater than the
46824		 * current value of {@link PerspectiveCamera#near}.
46825		 *
46826		 * @type {number}
46827		 * @default 2000
46828		 */
46829		this.far = far;
46830
46831		/**
46832		 * Object distance used for stereoscopy and depth-of-field effects. This
46833		 * parameter does not influence the projection matrix unless a
46834		 * {@link StereoCamera} is being used.
46835		 *
46836		 * @type {number}
46837		 * @default 10
46838		 */
46839		this.focus = 10;
46840
46841		/**
46842		 * The aspect ratio, usually the canvas width / canvas height.
46843		 *
46844		 * @type {number}
46845		 * @default 1
46846		 */
46847		this.aspect = aspect;
46848
46849		/**
46850		 * Represents the frustum window specification. This property should not be edited
46851		 * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
46852		 *
46853		 * @type {?Object}
46854		 * @default null
46855		 */
46856		this.view = null;
46857
46858		/**
46859		 * Film size used for the larger axis. Default is `35` (millimeters). This
46860		 * parameter does not influence the projection matrix unless {@link PerspectiveCamera#filmOffset}
46861		 * is set to a nonzero value.
46862		 *
46863		 * @type {number}
46864		 * @default 35
46865		 */
46866		this.filmGauge = 35;
46867
46868		/**
46869		 * Horizontal off-center offset in the same unit as {@link PerspectiveCamera#filmGauge}.
46870		 *
46871		 * @type {number}
46872		 * @default 0
46873		 */
46874		this.filmOffset = 0;
46875
46876		this.updateProjectionMatrix();
46877
46878	}
46879
46880	copy( source, recursive ) {
46881
46882		super.copy( source, recursive );
46883
46884		this.fov = source.fov;
46885		this.zoom = source.zoom;
46886
46887		this.near = source.near;
46888		this.far = source.far;
46889		this.focus = source.focus;
46890
46891		this.aspect = source.aspect;
46892		this.view = source.view === null ? null : Object.assign( {}, source.view );
46893
46894		this.filmGauge = source.filmGauge;
46895		this.filmOffset = source.filmOffset;
46896
46897		return this;
46898
46899	}
46900
46901	/**
46902	 * Sets the FOV by focal length in respect to the current {@link PerspectiveCamera#filmGauge}.
46903	 *
46904	 * The default film gauge is 35, so that the focal length can be specified for
46905	 * a 35mm (full frame) camera.
46906	 *
46907	 * @param {number} focalLength - Values for focal length and film gauge must have the same unit.
46908	 */
46909	setFocalLength( focalLength ) {
46910
46911		/** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */
46912		const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
46913
46914		this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope );
46915		this.updateProjectionMatrix();
46916
46917	}
46918
46919	/**
46920	 * Returns the focal length from the current {@link PerspectiveCamera#fov} and
46921	 * {@link PerspectiveCamera#filmGauge}.
46922	 *
46923	 * @return {number} The computed focal length.
46924	 */
46925	getFocalLength() {
46926
46927		const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov );
46928
46929		return 0.5 * this.getFilmHeight() / vExtentSlope;
46930
46931	}
46932
46933	/**
46934	 * Returns the current vertical field of view angle in degrees considering {@link PerspectiveCamera#zoom}.
46935	 *
46936	 * @return {number} The effective FOV.
46937	 */
46938	getEffectiveFOV() {
46939
46940		return RAD2DEG * 2 * Math.atan(
46941			Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom );
46942
46943	}
46944
46945	/**
46946	 * Returns the width of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
46947	 * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
46948	 *
46949	 * @return {number} The film width.
46950	 */
46951	getFilmWidth() {
46952
46953		// film not completely covered in portrait format (aspect < 1)
46954		return this.filmGauge * Math.min( this.aspect, 1 );
46955
46956	}
46957
46958	/**
46959	 * Returns the height of the image on the film. If {@link PerspectiveCamera#aspect} is greater than or
46960	 * equal to one (landscape format), the result equals {@link PerspectiveCamera#filmGauge}.
46961	 *
46962	 * @return {number} The film width.
46963	 */
46964	getFilmHeight() {
46965
46966		// film not completely covered in landscape format (aspect > 1)
46967		return this.filmGauge / Math.max( this.aspect, 1 );
46968
46969	}
46970
46971	/**
46972	 * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction.
46973	 * Sets `minTarget` and `maxTarget` to the coordinates of the lower-left and upper-right corners of the view rectangle.
46974	 *
46975	 * @param {number} distance - The viewing distance.
46976	 * @param {Vector2} minTarget - The lower-left corner of the view rectangle is written into this vector.
46977	 * @param {Vector2} maxTarget - The upper-right corner of the view rectangle is written into this vector.
46978	 */
46979	getViewBounds( distance, minTarget, maxTarget ) {
46980
46981		_v3$1.set( -1, -1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
46982
46983		minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
46984
46985		_v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse );
46986
46987		maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z );
46988
46989	}
46990
46991	/**
46992	 * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction.
46993	 *
46994	 * @param {number} distance - The viewing distance.
46995	 * @param {Vector2} target - The target vector that is used to store result where x is width and y is height.
46996	 * @returns {Vector2} The view size.
46997	 */
46998	getViewSize( distance, target ) {
46999
47000		this.getViewBounds( distance, _minTarget, _maxTarget );
47001
47002		return target.subVectors( _maxTarget, _minTarget );
47003
47004	}
47005
47006	/**
47007	 * Sets an offset in a larger frustum. This is useful for multi-window or
47008	 * multi-monitor/multi-machine setups.
47009	 *
47010	 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
47011	 * the monitors are in grid like this
47012	 *```
47013	 *   +---+---+---+
47014	 *   | A | B | C |
47015	 *   +---+---+---+
47016	 *   | D | E | F |
47017	 *   +---+---+---+
47018	 *```
47019	 * then for each monitor you would call it like this:
47020	 *```js
47021	 * const w = 1920;
47022	 * const h = 1080;
47023	 * const fullWidth = w * 3;
47024	 * const fullHeight = h * 2;
47025	 *
47026	 * // --A--
47027	 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
47028	 * // --B--
47029	 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
47030	 * // --C--
47031	 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
47032	 * // --D--
47033	 * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
47034	 * // --E--
47035	 * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
47036	 * // --F--
47037	 * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
47038	 * ```
47039	 *
47040	 * Note there is no reason monitors have to be the same size or in a grid.
47041	 *
47042	 * @param {number} fullWidth - The full width of multiview setup.
47043	 * @param {number} fullHeight - The full height of multiview setup.
47044	 * @param {number} x - The horizontal offset of the subcamera.
47045	 * @param {number} y - The vertical offset of the subcamera.
47046	 * @param {number} width - The width of subcamera.
47047	 * @param {number} height - The height of subcamera.
47048	 */
47049	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
47050
47051		this.aspect = fullWidth / fullHeight;
47052
47053		if ( this.view === null ) {
47054
47055			this.view = {
47056				enabled: true,
47057				fullWidth: 1,
47058				fullHeight: 1,
47059				offsetX: 0,
47060				offsetY: 0,
47061				width: 1,
47062				height: 1
47063			};
47064
47065		}
47066
47067		this.view.enabled = true;
47068		this.view.fullWidth = fullWidth;
47069		this.view.fullHeight = fullHeight;
47070		this.view.offsetX = x;
47071		this.view.offsetY = y;
47072		this.view.width = width;
47073		this.view.height = height;
47074
47075		this.updateProjectionMatrix();
47076
47077	}
47078
47079	/**
47080	 * Removes the view offset from the projection matrix.
47081	 */
47082	clearViewOffset() {
47083
47084		if ( this.view !== null ) {
47085
47086			this.view.enabled = false;
47087
47088		}
47089
47090		this.updateProjectionMatrix();
47091
47092	}
47093
47094	/**
47095	 * Updates the camera's projection matrix. Must be called after any change of
47096	 * camera properties.
47097	 */
47098	updateProjectionMatrix() {
47099
47100		const near = this.near;
47101		let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
47102		let height = 2 * top;
47103		let width = this.aspect * height;
47104		let left = -0.5 * width;
47105		const view = this.view;
47106
47107		if ( this.view !== null && this.view.enabled ) {
47108
47109			const fullWidth = view.fullWidth,
47110				fullHeight = view.fullHeight;
47111
47112			left += view.offsetX * width / fullWidth;
47113			top -= view.offsetY * height / fullHeight;
47114			width *= view.width / fullWidth;
47115			height *= view.height / fullHeight;
47116
47117		}
47118
47119		const skew = this.filmOffset;
47120		if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
47121
47122		this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem, this.reversedDepth );
47123
47124		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
47125
47126	}
47127
47128	toJSON( meta ) {
47129
47130		const data = super.toJSON( meta );
47131
47132		data.object.fov = this.fov;
47133		data.object.zoom = this.zoom;
47134
47135		data.object.near = this.near;
47136		data.object.far = this.far;
47137		data.object.focus = this.focus;
47138
47139		data.object.aspect = this.aspect;
47140
47141		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
47142
47143		data.object.filmGauge = this.filmGauge;
47144		data.object.filmOffset = this.filmOffset;
47145
47146		return data;
47147
47148	}
47149
47150}
47151
47152/**
47153 * Represents the shadow configuration of directional lights.
47154 *
47155 * @augments LightShadow
47156 */
47157class SpotLightShadow extends LightShadow {
47158
47159	/**
47160	 * Constructs a new spot light shadow.
47161	 */
47162	constructor() {
47163
47164		super( new PerspectiveCamera( 50, 1, 0.5, 500 ) );
47165
47166		/**
47167		 * This flag can be used for type testing.
47168		 *
47169		 * @type {boolean}
47170		 * @readonly
47171		 * @default true
47172		 */
47173		this.isSpotLightShadow = true;
47174
47175		/**
47176		 * Used to focus the shadow camera. The camera's field of view is set as a
47177		 * percentage of the spotlight's field-of-view. Range is `[0, 1]`.
47178		 *
47179		 * @type {number}
47180		 * @default 1
47181		 */
47182		this.focus = 1;
47183
47184		/**
47185		 * Texture aspect ratio.
47186		 *
47187		 * @type {number}
47188		 * @default 1
47189		 */
47190		this.aspect = 1;
47191
47192	}
47193
47194	updateMatrices( light ) {
47195
47196		const camera = this.camera;
47197
47198		const fov = RAD2DEG * 2 * light.angle * this.focus;
47199		const aspect = ( this.mapSize.width / this.mapSize.height ) * this.aspect;
47200		const far = light.distance || camera.far;
47201
47202		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
47203
47204			camera.fov = fov;
47205			camera.aspect = aspect;
47206			camera.far = far;
47207			camera.updateProjectionMatrix();
47208
47209		}
47210
47211		super.updateMatrices( light );
47212
47213	}
47214
47215	copy( source ) {
47216
47217		super.copy( source );
47218
47219		this.focus = source.focus;
47220		this.aspect = source.aspect;
47221
47222		return this;
47223
47224	}
47225
47226	/**
47227	 * Serializes the light shadow into JSON.
47228	 *
47229	 * @return {Object} A JSON object representing the serialized light shadow.
47230	 * @see {@link ObjectLoader#parse}
47231	 */
47232	toJSON() {
47233
47234		const object = super.toJSON();
47235
47236		object.focus = this.focus;
47237		object.aspect = this.aspect;
47238
47239		return object;
47240
47241	}
47242
47243}
47244
47245/**
47246 * This light gets emitted from a single point in one direction, along a cone
47247 * that increases in size the further from the light it gets.
47248 *
47249 * This light can cast shadows - see the {@link SpotLightShadow} for details.
47250 *
47251 * ```js
47252 * // white spotlight shining from the side, modulated by a texture
47253 * const spotLight = new THREE.SpotLight( 0xffffff );
47254 * spotLight.position.set( 100, 1000, 100 );
47255 * spotLight.map = new THREE.TextureLoader().load( url );
47256 *
47257 * spotLight.castShadow = true;
47258 * spotLight.shadow.mapSize.width = 1024;
47259 * spotLight.shadow.mapSize.height = 1024;
47260 * spotLight.shadow.camera.near = 500;
47261 * spotLight.shadow.camera.far = 4000;
47262 * spotLight.shadow.camera.fov = 30;s
47263 * ```
47264 *
47265 * @augments Light
47266 */
47267class SpotLight extends Light {
47268
47269	/**
47270	 * Constructs a new spot light.
47271	 *
47272	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
47273	 * @param {number} [intensity=1] - The light's strength/intensity measured in candela (cd).
47274	 * @param {number} [distance=0] - Maximum range of the light. `0` means no limit.
47275	 * @param {number} [angle=Math.PI/3] - Maximum angle of light dispersion from its direction whose upper bound is `Math.PI/2`.
47276	 * @param {number} [penumbra=0] - Percent of the spotlight cone that is attenuated due to penumbra. Value range is `[0,1]`.
47277	 * @param {number} [decay=2] - The amount the light dims along the distance of the light.
47278	 */
47279	constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) {
47280
47281		super( color, intensity );
47282
47283		/**
47284		 * This flag can be used for type testing.
47285		 *
47286		 * @type {boolean}
47287		 * @readonly
47288		 * @default true
47289		 */
47290		this.isSpotLight = true;
47291
47292		this.type = 'SpotLight';
47293
47294		this.position.copy( Object3D.DEFAULT_UP );
47295		this.updateMatrix();
47296
47297		/**
47298		 * The spot light points from its position to the
47299		 * target's position.
47300		 *
47301		 * For the target's position to be changed to anything other
47302		 * than the default, it must be added to the scene.
47303		 *
47304		 * It is also possible to set the target to be another 3D object
47305		 * in the scene. The light will now track the target object.
47306		 *
47307		 * @type {Object3D}
47308		 */
47309		this.target = new Object3D();
47310
47311		/**
47312		 * Maximum range of the light. `0` means no limit.
47313		 *
47314		 * @type {number}
47315		 * @default 0
47316		 */
47317		this.distance = distance;
47318
47319		/**
47320		 * Maximum angle of light dispersion from its direction whose upper bound is `Math.PI/2`.
47321		 *
47322		 * @type {number}
47323		 * @default Math.PI/3
47324		 */
47325		this.angle = angle;
47326
47327		/**
47328		 * Percent of the spotlight cone that is attenuated due to penumbra.
47329		 * Value range is `[0,1]`.
47330		 *
47331		 * @type {number}
47332		 * @default 0
47333		 */
47334		this.penumbra = penumbra;
47335
47336		/**
47337		 * The amount the light dims along the distance of the light. In context of
47338		 * physically-correct rendering the default value should not be changed.
47339		 *
47340		 * @type {number}
47341		 * @default 2
47342		 */
47343		this.decay = decay;
47344
47345		/**
47346		 * A texture used to modulate the color of the light. The spot light
47347		 * color is mixed with the RGB value of this texture, with a ratio
47348		 * corresponding to its alpha value. The cookie-like masking effect is
47349		 * reproduced using pixel values (0, 0, 0, 1-cookie_value).
47350		 *
47351		 * *Warning*: This property is disabled if {@link Object3D#castShadow} is set to `false`.
47352		 *
47353		 * @type {?Texture}
47354		 * @default null
47355		 */
47356		this.map = null;
47357
47358		/**
47359		 * This property holds the light's shadow configuration.
47360		 *
47361		 * @type {SpotLightShadow}
47362		 */
47363		this.shadow = new SpotLightShadow();
47364
47365	}
47366
47367	/**
47368	 * The light's power. Power is the luminous power of the light measured in lumens (lm).
47369	 *  Changing the power will also change the light's intensity.
47370	 *
47371	 * @type {number}
47372	 */
47373	get power() {
47374
47375		// compute the light's luminous power (in lumens) from its intensity (in candela)
47376		// by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
47377		return this.intensity * Math.PI;
47378
47379	}
47380
47381	set power( power ) {
47382
47383		// set the light's intensity (in candela) from the desired luminous power (in lumens)
47384		this.intensity = power / Math.PI;
47385
47386	}
47387
47388	dispose() {
47389
47390		super.dispose();
47391
47392		this.shadow.dispose();
47393
47394	}
47395
47396	copy( source, recursive ) {
47397
47398		super.copy( source, recursive );
47399
47400		this.distance = source.distance;
47401		this.angle = source.angle;
47402		this.penumbra = source.penumbra;
47403		this.decay = source.decay;
47404
47405		this.target = source.target.clone();
47406		this.map = source.map;
47407		this.shadow = source.shadow.clone();
47408
47409		return this;
47410
47411	}
47412
47413	toJSON( meta ) {
47414
47415		const data = super.toJSON( meta );
47416
47417		data.object.distance = this.distance;
47418		data.object.angle = this.angle;
47419		data.object.decay = this.decay;
47420		data.object.penumbra = this.penumbra;
47421
47422		data.object.target = this.target.uuid;
47423
47424		if ( this.map && this.map.isTexture ) data.object.map = this.map.toJSON( meta ).uuid;
47425
47426		data.object.shadow = this.shadow.toJSON();
47427
47428		return data;
47429
47430	}
47431
47432}
47433
47434/**
47435 * Represents the shadow configuration of point lights.
47436 *
47437 * @augments LightShadow
47438 */
47439class PointLightShadow extends LightShadow {
47440
47441	/**
47442	 * Constructs a new point light shadow.
47443	 */
47444	constructor() {
47445
47446		super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
47447
47448		/**
47449		 * This flag can be used for type testing.
47450		 *
47451		 * @type {boolean}
47452		 * @readonly
47453		 * @default true
47454		 */
47455		this.isPointLightShadow = true;
47456
47457	}
47458
47459}
47460
47461/**
47462 * A light that gets emitted from a single point in all directions. A common
47463 * use case for this is to replicate the light emitted from a bare
47464 * lightbulb.
47465 *
47466 * This light can cast shadows - see the {@link PointLightShadow} for details.
47467 *
47468 * ```js
47469 * const light = new THREE.PointLight( 0xff0000, 1, 100 );
47470 * light.position.set( 50, 50, 50 );
47471 * scene.add( light );
47472 * ```
47473 *
47474 * @augments Light
47475 */
47476class PointLight extends Light {
47477
47478	/**
47479	 * Constructs a new point light.
47480	 *
47481	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
47482	 * @param {number} [intensity=1] - The light's strength/intensity measured in candela (cd).
47483	 * @param {number} [distance=0] - Maximum range of the light. `0` means no limit.
47484	 * @param {number} [decay=2] - The amount the light dims along the distance of the light.
47485	 */
47486	constructor( color, intensity, distance = 0, decay = 2 ) {
47487
47488		super( color, intensity );
47489
47490		/**
47491		 * This flag can be used for type testing.
47492		 *
47493		 * @type {boolean}
47494		 * @readonly
47495		 * @default true
47496		 */
47497		this.isPointLight = true;
47498
47499		this.type = 'PointLight';
47500
47501		/**
47502		 * When distance is zero, light will attenuate according to inverse-square
47503		 * law to infinite distance. When distance is non-zero, light will attenuate
47504		 * according to inverse-square law until near the distance cutoff, where it
47505		 * will then attenuate quickly and smoothly to 0. Inherently, cutoffs are not
47506		 * physically correct.
47507		 *
47508		 * @type {number}
47509		 * @default 0
47510		 */
47511		this.distance = distance;
47512
47513		/**
47514		 * The amount the light dims along the distance of the light. In context of
47515		 * physically-correct rendering the default value should not be changed.
47516		 *
47517		 * @type {number}
47518		 * @default 2
47519		 */
47520		this.decay = decay;
47521
47522		/**
47523		 * This property holds the light's shadow configuration.
47524		 *
47525		 * @type {PointLightShadow}
47526		 */
47527		this.shadow = new PointLightShadow();
47528
47529	}
47530
47531	/**
47532	 * The light's power. Power is the luminous power of the light measured in lumens (lm).
47533	 * Changing the power will also change the light's intensity.
47534	 *
47535	 * @type {number}
47536	 */
47537	get power() {
47538
47539		// compute the light's luminous power (in lumens) from its intensity (in candela)
47540		// for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
47541		return this.intensity * 4 * Math.PI;
47542
47543	}
47544
47545	set power( power ) {
47546
47547		// set the light's intensity (in candela) from the desired luminous power (in lumens)
47548		this.intensity = power / ( 4 * Math.PI );
47549
47550	}
47551
47552	dispose() {
47553
47554		super.dispose();
47555
47556		this.shadow.dispose();
47557
47558	}
47559
47560	copy( source, recursive ) {
47561
47562		super.copy( source, recursive );
47563
47564		this.distance = source.distance;
47565		this.decay = source.decay;
47566
47567		this.shadow = source.shadow.clone();
47568
47569		return this;
47570
47571	}
47572
47573	toJSON( meta ) {
47574
47575		const data = super.toJSON( meta );
47576
47577		data.object.distance = this.distance;
47578		data.object.decay = this.decay;
47579
47580		data.object.shadow = this.shadow.toJSON();
47581
47582		return data;
47583
47584	}
47585
47586}
47587
47588/**
47589 * Camera that uses [orthographic projection](https://en.wikipedia.org/wiki/Orthographic_projection).
47590 *
47591 * In this projection mode, an object's size in the rendered image stays
47592 * constant regardless of its distance from the camera. This can be useful
47593 * for rendering 2D scenes and UI elements, amongst other things.
47594 *
47595 * ```js
47596 * const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
47597 * scene.add( camera );
47598 * ```
47599 *
47600 * @augments Camera
47601 */
47602class OrthographicCamera extends Camera {
47603
47604	/**
47605	 * Constructs a new orthographic camera.
47606	 *
47607	 * @param {number} [left=-1] - The left plane of the camera's frustum.
47608	 * @param {number} [right=1] - The right plane of the camera's frustum.
47609	 * @param {number} [top=1] - The top plane of the camera's frustum.
47610	 * @param {number} [bottom=-1] - The bottom plane of the camera's frustum.
47611	 * @param {number} [near=0.1] - The camera's near plane.
47612	 * @param {number} [far=2000] - The camera's far plane.
47613	 */
47614	constructor( left = -1, right = 1, top = 1, bottom = -1, near = 0.1, far = 2000 ) {
47615
47616		super();
47617
47618		/**
47619		 * This flag can be used for type testing.
47620		 *
47621		 * @type {boolean}
47622		 * @readonly
47623		 * @default true
47624		 */
47625		this.isOrthographicCamera = true;
47626
47627		this.type = 'OrthographicCamera';
47628
47629		/**
47630		 * The zoom factor of the camera.
47631		 *
47632		 * @type {number}
47633		 * @default 1
47634		 */
47635		this.zoom = 1;
47636
47637		/**
47638		 * Represents the frustum window specification. This property should not be edited
47639		 * directly but via {@link PerspectiveCamera#setViewOffset} and {@link PerspectiveCamera#clearViewOffset}.
47640		 *
47641		 * @type {?Object}
47642		 * @default null
47643		 */
47644		this.view = null;
47645
47646		/**
47647		 * The left plane of the camera's frustum.
47648		 *
47649		 * @type {number}
47650		 * @default -1
47651		 */
47652		this.left = left;
47653
47654		/**
47655		 * The right plane of the camera's frustum.
47656		 *
47657		 * @type {number}
47658		 * @default 1
47659		 */
47660		this.right = right;
47661
47662		/**
47663		 * The top plane of the camera's frustum.
47664		 *
47665		 * @type {number}
47666		 * @default 1
47667		 */
47668		this.top = top;
47669
47670		/**
47671		 * The bottom plane of the camera's frustum.
47672		 *
47673		 * @type {number}
47674		 * @default -1
47675		 */
47676		this.bottom = bottom;
47677
47678		/**
47679		 * The camera's near plane. The valid range is greater than `0`
47680		 * and less than the current value of {@link OrthographicCamera#far}.
47681		 *
47682		 * Note that, unlike for the {@link PerspectiveCamera}, `0` is a
47683		 * valid value for an orthographic camera's near plane.
47684		 *
47685		 * @type {number}
47686		 * @default 0.1
47687		 */
47688		this.near = near;
47689
47690		/**
47691		 * The camera's far plane. Must be greater than the
47692		 * current value of {@link OrthographicCamera#near}.
47693		 *
47694		 * @type {number}
47695		 * @default 2000
47696		 */
47697		this.far = far;
47698
47699		this.updateProjectionMatrix();
47700
47701	}
47702
47703	copy( source, recursive ) {
47704
47705		super.copy( source, recursive );
47706
47707		this.left = source.left;
47708		this.right = source.right;
47709		this.top = source.top;
47710		this.bottom = source.bottom;
47711		this.near = source.near;
47712		this.far = source.far;
47713
47714		this.zoom = source.zoom;
47715		this.view = source.view === null ? null : Object.assign( {}, source.view );
47716
47717		return this;
47718
47719	}
47720
47721	/**
47722	 * Sets an offset in a larger frustum. This is useful for multi-window or
47723	 * multi-monitor/multi-machine setups.
47724	 *
47725	 * @param {number} fullWidth - The full width of multiview setup.
47726	 * @param {number} fullHeight - The full height of multiview setup.
47727	 * @param {number} x - The horizontal offset of the subcamera.
47728	 * @param {number} y - The vertical offset of the subcamera.
47729	 * @param {number} width - The width of subcamera.
47730	 * @param {number} height - The height of subcamera.
47731	 * @see {@link PerspectiveCamera#setViewOffset}
47732	 */
47733	setViewOffset( fullWidth, fullHeight, x, y, width, height ) {
47734
47735		if ( this.view === null ) {
47736
47737			this.view = {
47738				enabled: true,
47739				fullWidth: 1,
47740				fullHeight: 1,
47741				offsetX: 0,
47742				offsetY: 0,
47743				width: 1,
47744				height: 1
47745			};
47746
47747		}
47748
47749		this.view.enabled = true;
47750		this.view.fullWidth = fullWidth;
47751		this.view.fullHeight = fullHeight;
47752		this.view.offsetX = x;
47753		this.view.offsetY = y;
47754		this.view.width = width;
47755		this.view.height = height;
47756
47757		this.updateProjectionMatrix();
47758
47759	}
47760
47761	/**
47762	 * Removes the view offset from the projection matrix.
47763	 */
47764	clearViewOffset() {
47765
47766		if ( this.view !== null ) {
47767
47768			this.view.enabled = false;
47769
47770		}
47771
47772		this.updateProjectionMatrix();
47773
47774	}
47775
47776	/**
47777	 * Updates the camera's projection matrix. Must be called after any change of
47778	 * camera properties.
47779	 */
47780	updateProjectionMatrix() {
47781
47782		const dx = ( this.right - this.left ) / ( 2 * this.zoom );
47783		const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
47784		const cx = ( this.right + this.left ) / 2;
47785		const cy = ( this.top + this.bottom ) / 2;
47786
47787		let left = cx - dx;
47788		let right = cx + dx;
47789		let top = cy + dy;
47790		let bottom = cy - dy;
47791
47792		if ( this.view !== null && this.view.enabled ) {
47793
47794			const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
47795			const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
47796
47797			left += scaleW * this.view.offsetX;
47798			right = left + scaleW * this.view.width;
47799			top -= scaleH * this.view.offsetY;
47800			bottom = top - scaleH * this.view.height;
47801
47802		}
47803
47804		this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem, this.reversedDepth );
47805
47806		this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
47807
47808	}
47809
47810	toJSON( meta ) {
47811
47812		const data = super.toJSON( meta );
47813
47814		data.object.zoom = this.zoom;
47815		data.object.left = this.left;
47816		data.object.right = this.right;
47817		data.object.top = this.top;
47818		data.object.bottom = this.bottom;
47819		data.object.near = this.near;
47820		data.object.far = this.far;
47821
47822		if ( this.view !== null ) data.object.view = Object.assign( {}, this.view );
47823
47824		return data;
47825
47826	}
47827
47828}
47829
47830/**
47831 * Represents the shadow configuration of directional lights.
47832 *
47833 * @augments LightShadow
47834 */
47835class DirectionalLightShadow extends LightShadow {
47836
47837	/**
47838	 * Constructs a new directional light shadow.
47839	 */
47840	constructor() {
47841
47842		super( new OrthographicCamera( -5, 5, 5, -5, 0.5, 500 ) );
47843
47844		/**
47845		 * This flag can be used for type testing.
47846		 *
47847		 * @type {boolean}
47848		 * @readonly
47849		 * @default true
47850		 */
47851		this.isDirectionalLightShadow = true;
47852
47853	}
47854
47855}
47856
47857/**
47858 * A light that gets emitted in a specific direction. This light will behave
47859 * as though it is infinitely far away and the rays produced from it are all
47860 * parallel. The common use case for this is to simulate daylight; the sun is
47861 * far enough away that its position can be considered to be infinite, and
47862 * all light rays coming from it are parallel.
47863 *
47864 * A common point of confusion for directional lights is that setting the
47865 * rotation has no effect. This is because three.js's DirectionalLight is the
47866 * equivalent to what is often called a 'Target Direct Light' in other
47867 * applications.
47868 *
47869 * This means that its direction is calculated as pointing from the light's
47870 * {@link Object3D#position} to the {@link DirectionalLight#target} position
47871 * (as opposed to a 'Free Direct Light' that just has a rotation
47872 * component).
47873 *
47874 * This light can cast shadows - see the {@link DirectionalLightShadow} for details.
47875 *
47876 * ```js
47877 * // White directional light at half intensity shining from the top.
47878 * const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
47879 * scene.add( directionalLight );
47880 * ```
47881 *
47882 * @augments Light
47883 */
47884class DirectionalLight extends Light {
47885
47886	/**
47887	 * Constructs a new directional light.
47888	 *
47889	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
47890	 * @param {number} [intensity=1] - The light's strength/intensity.
47891	 */
47892	constructor( color, intensity ) {
47893
47894		super( color, intensity );
47895
47896		/**
47897		 * This flag can be used for type testing.
47898		 *
47899		 * @type {boolean}
47900		 * @readonly
47901		 * @default true
47902		 */
47903		this.isDirectionalLight = true;
47904
47905		this.type = 'DirectionalLight';
47906
47907		this.position.copy( Object3D.DEFAULT_UP );
47908		this.updateMatrix();
47909
47910		/**
47911		 * The directional light points from its position to the
47912		 * target's position.
47913		 *
47914		 * For the target's position to be changed to anything other
47915		 * than the default, it must be added to the scene.
47916		 *
47917		 * It is also possible to set the target to be another 3D object
47918		 * in the scene. The light will now track the target object.
47919		 *
47920		 * @type {Object3D}
47921		 */
47922		this.target = new Object3D();
47923
47924		/**
47925		 * This property holds the light's shadow configuration.
47926		 *
47927		 * @type {DirectionalLightShadow}
47928		 */
47929		this.shadow = new DirectionalLightShadow();
47930
47931	}
47932
47933	dispose() {
47934
47935		super.dispose();
47936
47937		this.shadow.dispose();
47938
47939	}
47940
47941	copy( source ) {
47942
47943		super.copy( source );
47944
47945		this.target = source.target.clone();
47946		this.shadow = source.shadow.clone();
47947
47948		return this;
47949
47950	}
47951
47952	toJSON( meta ) {
47953
47954		const data = super.toJSON( meta );
47955
47956		data.object.shadow = this.shadow.toJSON();
47957		data.object.target = this.target.uuid;
47958
47959		return data;
47960
47961	}
47962
47963}
47964
47965/**
47966 * This light globally illuminates all objects in the scene equally.
47967 *
47968 * It cannot be used to cast shadows as it does not have a direction.
47969 *
47970 * ```js
47971 * const light = new THREE.AmbientLight( 0x404040 ); // soft white light
47972 * scene.add( light );
47973 * ```
47974 *
47975 * @augments Light
47976 */
47977class AmbientLight extends Light {
47978
47979	/**
47980	 * Constructs a new ambient light.
47981	 *
47982	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
47983	 * @param {number} [intensity=1] - The light's strength/intensity.
47984	 */
47985	constructor( color, intensity ) {
47986
47987		super( color, intensity );
47988
47989		/**
47990		 * This flag can be used for type testing.
47991		 *
47992		 * @type {boolean}
47993		 * @readonly
47994		 * @default true
47995		 */
47996		this.isAmbientLight = true;
47997
47998		this.type = 'AmbientLight';
47999
48000	}
48001
48002}
48003
48004/**
48005 * This class emits light uniformly across the face a rectangular plane.
48006 * This light type can be used to simulate light sources such as bright
48007 * windows or strip lighting.
48008 *
48009 * Important Notes:
48010 *
48011 * - There is no shadow support.
48012 * - Only PBR materials are supported.
48013 * - You have to include `RectAreaLightUniformsLib` (`WebGLRenderer`) or `RectAreaLightTexturesLib` (`WebGPURenderer`)
48014 * into your app and init the uniforms/textures.
48015 *
48016 * ```js
48017 * RectAreaLightUniformsLib.init(); // only relevant for WebGLRenderer
48018 * THREE.RectAreaLightNode.setLTC( RectAreaLightTexturesLib.init() ); //  only relevant for WebGPURenderer
48019 *
48020 * const intensity = 1; const width = 10; const height = 10;
48021 * const rectLight = new THREE.RectAreaLight( 0xffffff, intensity, width, height );
48022 * rectLight.position.set( 5, 5, 0 );
48023 * rectLight.lookAt( 0, 0, 0 );
48024 * scene.add( rectLight )
48025 * ```
48026 *
48027 * @augments Light
48028 */
48029class RectAreaLight extends Light {
48030
48031	/**
48032	 * Constructs a new area light.
48033	 *
48034	 * @param {(number|Color|string)} [color=0xffffff] - The light's color.
48035	 * @param {number} [intensity=1] - The light's strength/intensity.
48036	 * @param {number} [width=10] - The width of the light.
48037	 * @param {number} [height=10] - The height of the light.
48038	 */
48039	constructor( color, intensity, width = 10, height = 10 ) {
48040
48041		super( color, intensity );
48042
48043		/**
48044		 * This flag can be used for type testing.
48045		 *
48046		 * @type {boolean}
48047		 * @readonly
48048		 * @default true
48049		 */
48050		this.isRectAreaLight = true;
48051
48052		this.type = 'RectAreaLight';
48053
48054		/**
48055		 * The width of the light.
48056		 *
48057		 * @type {number}
48058		 * @default 10
48059		 */
48060		this.width = width;
48061
48062		/**
48063		 * The height of the light.
48064		 *
48065		 * @type {number}
48066		 * @default 10
48067		 */
48068		this.height = height;
48069
48070	}
48071
48072	/**
48073	 * The light's power. Power is the luminous power of the light measured in lumens (lm).
48074	 * Changing the power will also change the light's intensity.
48075	 *
48076	 * @type {number}
48077	 */
48078	get power() {
48079
48080		// compute the light's luminous power (in lumens) from its intensity (in nits)
48081		return this.intensity * this.width * this.height * Math.PI;
48082
48083	}
48084
48085	set power( power ) {
48086
48087		// set the light's intensity (in nits) from the desired luminous power (in lumens)
48088		this.intensity = power / ( this.width * this.height * Math.PI );
48089
48090	}
48091
48092	copy( source ) {
48093
48094		super.copy( source );
48095
48096		this.width = source.width;
48097		this.height = source.height;
48098
48099		return this;
48100
48101	}
48102
48103	toJSON( meta ) {
48104
48105		const data = super.toJSON( meta );
48106
48107		data.object.width = this.width;
48108		data.object.height = this.height;
48109
48110		return data;
48111
48112	}
48113
48114}
48115
48116/**
48117 * Represents a third-order spherical harmonics (SH). Light probes use this class
48118 * to encode lighting information.
48119 *
48120 * - Primary reference: {@link https://graphics.stanford.edu/papers/envmap/envmap.pdf}
48121 * - Secondary reference: {@link https://www.ppsloan.org/publications/StupidSH36.pdf}
48122 */
48123class SphericalHarmonics3 {
48124
48125	/**
48126	 * Constructs a new spherical harmonics.
48127	 */
48128	constructor() {
48129
48130		/**
48131		 * This flag can be used for type testing.
48132		 *
48133		 * @type {boolean}
48134		 * @readonly
48135		 * @default true
48136		 */
48137		this.isSphericalHarmonics3 = true;
48138
48139		/**
48140		 * An array holding the (9) SH coefficients.
48141		 *
48142		 * @type {Array<Vector3>}
48143		 */
48144		this.coefficients = [];
48145
48146		for ( let i = 0; i < 9; i ++ ) {
48147
48148			this.coefficients.push( new Vector3() );
48149
48150		}
48151
48152	}
48153
48154	/**
48155	 * Sets the given SH coefficients to this instance by copying
48156	 * the values.
48157	 *
48158	 * @param {Array<Vector3>} coefficients - The SH coefficients.
48159	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
48160	 */
48161	set( coefficients ) {
48162
48163		for ( let i = 0; i < 9; i ++ ) {
48164
48165			this.coefficients[ i ].copy( coefficients[ i ] );
48166
48167		}
48168
48169		return this;
48170
48171	}
48172
48173	/**
48174	 * Sets all SH coefficients to `0`.
48175	 *
48176	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
48177	 */
48178	zero() {
48179
48180		for ( let i = 0; i < 9; i ++ ) {
48181
48182			this.coefficients[ i ].set( 0, 0, 0 );
48183
48184		}
48185
48186		return this;
48187
48188	}
48189
48190	/**
48191	 * Returns the radiance in the direction of the given normal.
48192	 *
48193	 * @param {Vector3} normal - The normal vector (assumed to be unit length)
48194	 * @param {Vector3} target - The target vector that is used to store the method's result.
48195	 * @return {Vector3} The radiance.
48196	 */
48197	getAt( normal, target ) {
48198
48199		// normal is assumed to be unit length
48200
48201		const x = normal.x, y = normal.y, z = normal.z;
48202
48203		const coeff = this.coefficients;
48204
48205		// band 0
48206		target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
48207
48208		// band 1
48209		target.addScaledVector( coeff[ 1 ], 0.488603 * y );
48210		target.addScaledVector( coeff[ 2 ], 0.488603 * z );
48211		target.addScaledVector( coeff[ 3 ], 0.488603 * x );
48212
48213		// band 2
48214		target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
48215		target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
48216		target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
48217		target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
48218		target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
48219
48220		return target;
48221
48222	}
48223
48224	/**
48225	 * Returns the irradiance (radiance convolved with cosine lobe) in the
48226	 * direction of the given normal.
48227	 *
48228	 * @param {Vector3} normal - The normal vector (assumed to be unit length)
48229	 * @param {Vector3} target - The target vector that is used to store the method's result.
48230	 * @return {Vector3} The irradiance.
48231	 */
48232	getIrradianceAt( normal, target ) {
48233
48234		// normal is assumed to be unit length
48235
48236		const x = normal.x, y = normal.y, z = normal.z;
48237
48238		const coeff = this.coefficients;
48239
48240		// band 0
48241		target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
48242
48243		// band 1
48244		target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
48245		target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
48246		target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
48247
48248		// band 2
48249		target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
48250		target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
48251		target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
48252		target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
48253		target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
48254
48255		return target;
48256
48257	}
48258
48259	/**
48260	 * Adds the given SH to this instance.
48261	 *
48262	 * @param {SphericalHarmonics3} sh - The SH to add.
48263	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
48264	 */
48265	add( sh ) {
48266
48267		for ( let i = 0; i < 9; i ++ ) {
48268
48269			this.coefficients[ i ].add( sh.coefficients[ i ] );
48270
48271		}
48272
48273		return this;
48274
48275	}
48276
48277	/**
48278	 * A convenience method for performing {@link SphericalHarmonics3#add} and
48279	 * {@link SphericalHarmonics3#scale} at once.
48280	 *
48281	 * @param {SphericalHarmonics3} sh - The SH to add.
48282	 * @param {number} s - The scale factor.
48283	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
48284	 */
48285	addScaledSH( sh, s ) {
48286
48287		for ( let i = 0; i < 9; i ++ ) {
48288
48289			this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
48290
48291		}
48292
48293		return this;
48294
48295	}
48296
48297	/**
48298	 * Scales this SH by the given scale factor.
48299	 *
48300	 * @param {number} s - The scale factor.
48301	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
48302	 */
48303	scale( s ) {
48304
48305		for ( let i = 0; i < 9; i ++ ) {
48306
48307			this.coefficients[ i ].multiplyScalar( s );
48308
48309		}
48310
48311		return this;
48312
48313	}
48314
48315	/**
48316	 * Linear interpolates between the given SH and this instance by the given
48317	 * alpha factor.
48318	 *
48319	 * @param {SphericalHarmonics3} sh - The SH to interpolate with.
48320	 * @param {number} alpha - The alpha factor.
48321	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
48322	 */
48323	lerp( sh, alpha ) {
48324
48325		for ( let i = 0; i < 9; i ++ ) {
48326
48327			this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
48328
48329		}
48330
48331		return this;
48332
48333	}
48334
48335	/**
48336	 * Returns `true` if this spherical harmonics is equal with the given one.
48337	 *
48338	 * @param {SphericalHarmonics3} sh - The spherical harmonics to test for equality.
48339	 * @return {boolean} Whether this spherical harmonics is equal with the given one.
48340	 */
48341	equals( sh ) {
48342
48343		for ( let i = 0; i < 9; i ++ ) {
48344
48345			if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
48346
48347				return false;
48348
48349			}
48350
48351		}
48352
48353		return true;
48354
48355	}
48356
48357	/**
48358	 * Copies the values of the given spherical harmonics to this instance.
48359	 *
48360	 * @param {SphericalHarmonics3} sh - The spherical harmonics to copy.
48361	 * @return {SphericalHarmonics3} A reference to this spherical harmonics.
48362	 */
48363	copy( sh ) {
48364
48365		return this.set( sh.coefficients );
48366
48367	}
48368
48369	/**
48370	 * Returns a new spherical harmonics with copied values from this instance.
48371	 *
48372	 * @return {SphericalHarmonics3} A clone of this instance.
48373	 */
48374	clone() {
48375
48376		return new this.constructor().copy( this );
48377
48378	}
48379
48380	/**
48381	 * Sets the SH coefficients of this instance from the given array.
48382	 *
48383	 * @param {Array<number>} array - An array holding the SH coefficients.
48384	 * @param {number} [offset=0] - The array offset where to start copying.
48385	 * @return {SphericalHarmonics3} A clone of this instance.
48386	 */
48387	fromArray( array, offset = 0 ) {
48388
48389		const coefficients = this.coefficients;
48390
48391		for ( let i = 0; i < 9; i ++ ) {
48392
48393			coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
48394
48395		}
48396
48397		return this;
48398
48399	}
48400
48401	/**
48402	 * Returns an array with the SH coefficients, or copies them into the provided
48403	 * array. The coefficients are represented as numbers.
48404	 *
48405	 * @param {Array<number>} [array=[]] - The target array.
48406	 * @param {number} [offset=0] - The array offset where to start copying.
48407	 * @return {Array<number>} An array with flat SH coefficients.
48408	 */
48409	toArray( array = [], offset = 0 ) {
48410
48411		const coefficients = this.coefficients;
48412
48413		for ( let i = 0; i < 9; i ++ ) {
48414
48415			coefficients[ i ].toArray( array, offset + ( i * 3 ) );
48416
48417		}
48418
48419		return array;
48420
48421	}
48422
48423	/**
48424	 * Computes the SH basis for the given normal vector.
48425	 *
48426	 * @param {Vector3} normal - The normal.
48427	 * @param {Array<number>} shBasis - The target array holding the SH basis.
48428	 */
48429	static getBasisAt( normal, shBasis ) {
48430
48431		// normal is assumed to be unit length
48432
48433		const x = normal.x, y = normal.y, z = normal.z;
48434
48435		// band 0
48436		shBasis[ 0 ] = 0.282095;
48437
48438		// band 1
48439		shBasis[ 1 ] = 0.488603 * y;
48440		shBasis[ 2 ] = 0.488603 * z;
48441		shBasis[ 3 ] = 0.488603 * x;
48442
48443		// band 2
48444		shBasis[ 4 ] = 1.092548 * x * y;
48445		shBasis[ 5 ] = 1.092548 * y * z;
48446		shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
48447		shBasis[ 7 ] = 1.092548 * x * z;
48448		shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
48449
48450	}
48451
48452}
48453
48454/**
48455 * Light probes are an alternative way of adding light to a 3D scene. Unlike
48456 * classical light sources (e.g. directional, point or spot lights), light
48457 * probes do not emit light. Instead they store information about light
48458 * passing through 3D space. During rendering, the light that hits a 3D
48459 * object is approximated by using the data from the light probe.
48460 *
48461 * Light probes are usually created from (radiance) environment maps. The
48462 * class {@link LightProbeGenerator} can be used to create light probes from
48463 * cube textures or render targets. However, light estimation data could also
48464 * be provided in other forms e.g. by WebXR. This enables the rendering of
48465 * augmented reality content that reacts to real world lighting.
48466 *
48467 * The current probe implementation in three.js supports so-called diffuse
48468 * light probes. This type of light probe is functionally equivalent to an
48469 * irradiance environment map.
48470 *
48471 * @augments Light
48472 */
48473class LightProbe extends Light {
48474
48475	/**
48476	 * Constructs a new light probe.
48477	 *
48478	 * @param {SphericalHarmonics3} sh - The spherical harmonics which represents encoded lighting information.
48479	 * @param {number} [intensity=1] - The light's strength/intensity.
48480	 */
48481	constructor( sh = new SphericalHarmonics3(), intensity = 1 ) {
48482
48483		super( undefined, intensity );
48484
48485		/**
48486		 * This flag can be used for type testing.
48487		 *
48488		 * @type {boolean}
48489		 * @readonly
48490		 * @default true
48491		 */
48492		this.isLightProbe = true;
48493
48494		/**
48495		 * A light probe uses spherical harmonics to encode lighting information.
48496		 *
48497		 * @type {SphericalHarmonics3}
48498		 */
48499		this.sh = sh;
48500
48501	}
48502
48503	copy( source ) {
48504
48505		super.copy( source );
48506
48507		this.sh.copy( source.sh );
48508
48509		return this;
48510
48511	}
48512
48513	toJSON( meta ) {
48514
48515		const data = super.toJSON( meta );
48516
48517		data.object.sh = this.sh.toArray();
48518
48519		return data;
48520
48521	}
48522
48523}
48524
48525const _customMaterials = {};
48526
48527/**
48528 * Class for loading materials. The files are internally
48529 * loaded via {@link FileLoader}.
48530 *
48531 * ```js
48532 * const loader = new THREE.MaterialLoader();
48533 * const material = await loader.loadAsync( 'material.json' );
48534 * ```
48535 * This loader does not support node materials. Use {@link NodeMaterialLoader} instead.
48536 *
48537 * @augments Loader
48538 */
48539class MaterialLoader extends Loader {
48540
48541	/**
48542	 * Constructs a new material loader.
48543	 *
48544	 * @param {LoadingManager} [manager] - The loading manager.
48545	 */
48546	constructor( manager ) {
48547
48548		super( manager );
48549
48550		/**
48551		 * A dictionary holding textures used by the material.
48552		 *
48553		 * @type {Object<string,Texture>}
48554		 */
48555		this.textures = {};
48556
48557	}
48558
48559	/**
48560	 * Starts loading from the given URL and pass the loaded material to the `onLoad()` callback.
48561	 *
48562	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
48563	 * @param {function(Material)} onLoad - Executed when the loading process has been finished.
48564	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
48565	 * @param {onErrorCallback} onError - Executed when errors occur.
48566	 */
48567	load( url, onLoad, onProgress, onError ) {
48568
48569		const scope = this;
48570
48571		const loader = new FileLoader( scope.manager );
48572		loader.setPath( scope.path );
48573		loader.setRequestHeader( scope.requestHeader );
48574		loader.setWithCredentials( scope.withCredentials );
48575		loader.load( url, function ( text ) {
48576
48577			try {
48578
48579				onLoad( scope.parse( JSON.parse( text ) ) );
48580
48581			} catch ( e ) {
48582
48583				if ( onError ) {
48584
48585					onError( e );
48586
48587				} else {
48588
48589					error( e );
48590
48591				}
48592
48593				scope.manager.itemError( url );
48594
48595			}
48596
48597		}, onProgress, onError );
48598
48599	}
48600
48601	/**
48602	 * Parses the given JSON object and returns a material.
48603	 *
48604	 * @param {Object} json - The serialized material.
48605	 * @return {Material} The parsed material.
48606	 */
48607	parse( json ) {
48608
48609		const material = this.createMaterialFromType( json.type );
48610
48611		material.fromJSON( json, this.textures );
48612
48613		return material;
48614
48615	}
48616
48617	/**
48618	 * Textures are not embedded in the material JSON so they have
48619	 * to be injected before the loading process starts.
48620	 *
48621	 * @param {Object} value - A dictionary holding textures for material properties.
48622	 * @return {MaterialLoader} A reference to this material loader.
48623	 */
48624	setTextures( value ) {
48625
48626		this.textures = value;
48627		return this;
48628
48629	}
48630
48631	/**
48632	 * Creates a material for the given type.
48633	 *
48634	 * @param {string} type - The material type.
48635	 * @return {Material} The new material.
48636	 */
48637	createMaterialFromType( type ) {
48638
48639		return MaterialLoader.createMaterialFromType( type );
48640
48641	}
48642
48643	/**
48644	 * Creates a material for the given type.
48645	 *
48646	 * @static
48647	 * @param {string} type - The material type.
48648	 * @return {Material} The new material.
48649	 */
48650	static createMaterialFromType( type ) {
48651
48652		const materialLib = {
48653			ShadowMaterial,
48654			SpriteMaterial,
48655			RawShaderMaterial,
48656			ShaderMaterial,
48657			PointsMaterial,
48658			MeshPhysicalMaterial,
48659			MeshStandardMaterial,
48660			MeshPhongMaterial,
48661			MeshToonMaterial,
48662			MeshNormalMaterial,
48663			MeshLambertMaterial,
48664			MeshDepthMaterial,
48665			MeshDistanceMaterial,
48666			MeshBasicMaterial,
48667			MeshMatcapMaterial,
48668			LineDashedMaterial,
48669			LineBasicMaterial,
48670			Material,
48671			... _customMaterials
48672		};
48673
48674		const MaterialType = materialLib[ type ];
48675
48676		let materialInstance;
48677
48678		if ( MaterialType === undefined ) {
48679
48680			warnOnce( `MaterialLoader: Unknown material type "${ type }". Use .registerMaterial() before starting the deserialization process.` );
48681			materialInstance = new Material();
48682
48683		} else {
48684
48685			materialInstance = new MaterialType();
48686
48687		}
48688
48689		return materialInstance;
48690
48691	}
48692
48693	/**
48694	 * Registers the given material at the internal
48695	 * material library.
48696	 *
48697	 * @static
48698	 * @param {string} type - The material type.
48699	 * @param {Material.constructor} materialClass - The material class.
48700	 */
48701	static registerMaterial( type, materialClass ) {
48702
48703		_customMaterials[ type ] = materialClass;
48704
48705	}
48706
48707}
48708
48709/**
48710 * A class with loader utility functions.
48711 */
48712class LoaderUtils {
48713
48714	/**
48715	 * Extracts the base URL from the given URL.
48716	 *
48717	 * @param {string} url -The URL to extract the base URL from.
48718	 * @return {string} The extracted base URL.
48719	 */
48720	static extractUrlBase( url ) {
48721
48722		const index = url.lastIndexOf( '/' );
48723
48724		if ( index === -1 ) return './';
48725
48726		return url.slice( 0, index + 1 );
48727
48728	}
48729
48730	/**
48731	 * Resolves relative URLs against the given path. Absolute paths, data urls,
48732	 * and blob URLs will be returned as is. Invalid URLs will return an empty
48733	 * string.
48734	 *
48735	 * @param {string} url -The URL to resolve.
48736	 * @param {string} path - The base path for relative URLs to be resolved against.
48737	 * @return {string} The resolved URL.
48738	 */
48739	static resolveURL( url, path ) {
48740
48741		// Invalid URL
48742		if ( typeof url !== 'string' || url === '' ) return '';
48743
48744		// Host Relative URL
48745		if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
48746
48747			path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
48748
48749		}
48750
48751		// Absolute URL http://,https://,//
48752		if ( /^(https?:)?\/\//i.test( url ) ) return url;
48753
48754		// Data URI
48755		if ( /^data:.*,.*$/i.test( url ) ) return url;
48756
48757		// Blob URL
48758		if ( /^blob:.*$/i.test( url ) ) return url;
48759
48760		// Relative URL
48761		return path + url;
48762
48763	}
48764
48765}
48766
48767/**
48768 * An instanced version of a geometry.
48769 */
48770class InstancedBufferGeometry extends BufferGeometry {
48771
48772	/**
48773	 * Constructs a new instanced buffer geometry.
48774	 */
48775	constructor() {
48776
48777		super();
48778
48779		/**
48780		 * This flag can be used for type testing.
48781		 *
48782		 * @type {boolean}
48783		 * @readonly
48784		 * @default true
48785		 */
48786		this.isInstancedBufferGeometry = true;
48787
48788		this.type = 'InstancedBufferGeometry';
48789
48790		/**
48791		 * The instance count.
48792		 *
48793		 * @type {number}
48794		 * @default Infinity
48795		 */
48796		this.instanceCount = Infinity;
48797
48798	}
48799
48800	copy( source ) {
48801
48802		super.copy( source );
48803
48804		this.instanceCount = source.instanceCount;
48805
48806		return this;
48807
48808	}
48809
48810	toJSON() {
48811
48812		const data = super.toJSON();
48813
48814		data.instanceCount = this.instanceCount;
48815
48816		data.isInstancedBufferGeometry = true;
48817
48818		return data;
48819
48820	}
48821
48822}
48823
48824/**
48825 * Class for loading geometries. The files are internally
48826 * loaded via {@link FileLoader}.
48827 *
48828 * ```js
48829 * const loader = new THREE.BufferGeometryLoader();
48830 * const geometry = await loader.loadAsync( 'models/json/pressure.json' );
48831 *
48832 * const material = new THREE.MeshBasicMaterial( { color: 0xF5F5F5 } );
48833 * const object = new THREE.Mesh( geometry, material );
48834 * scene.add( object );
48835 * ```
48836 *
48837 * @augments Loader
48838 */
48839class BufferGeometryLoader extends Loader {
48840
48841	/**
48842	 * Constructs a new geometry loader.
48843	 *
48844	 * @param {LoadingManager} [manager] - The loading manager.
48845	 */
48846	constructor( manager ) {
48847
48848		super( manager );
48849
48850	}
48851
48852	/**
48853	 * Starts loading from the given URL and pass the loaded geometry to the `onLoad()` callback.
48854	 *
48855	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
48856	 * @param {function(BufferGeometry)} onLoad - Executed when the loading process has been finished.
48857	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
48858	 * @param {onErrorCallback} onError - Executed when errors occur.
48859	 */
48860	load( url, onLoad, onProgress, onError ) {
48861
48862		const scope = this;
48863
48864		const loader = new FileLoader( scope.manager );
48865		loader.setPath( scope.path );
48866		loader.setRequestHeader( scope.requestHeader );
48867		loader.setWithCredentials( scope.withCredentials );
48868		loader.load( url, function ( text ) {
48869
48870			try {
48871
48872				onLoad( scope.parse( JSON.parse( text ) ) );
48873
48874			} catch ( e ) {
48875
48876				if ( onError ) {
48877
48878					onError( e );
48879
48880				} else {
48881
48882					error( e );
48883
48884				}
48885
48886				scope.manager.itemError( url );
48887
48888			}
48889
48890		}, onProgress, onError );
48891
48892	}
48893
48894	/**
48895	 * Parses the given JSON object and returns a geometry.
48896	 *
48897	 * @param {Object} json - The serialized geometry.
48898	 * @return {BufferGeometry} The parsed geometry.
48899	 */
48900	parse( json ) {
48901
48902		const interleavedBufferMap = {};
48903		const arrayBufferMap = {};
48904
48905		function getInterleavedBuffer( json, uuid ) {
48906
48907			if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
48908
48909			const interleavedBuffers = json.interleavedBuffers;
48910			const interleavedBuffer = interleavedBuffers[ uuid ];
48911
48912			const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
48913
48914			const array = getTypedArray( interleavedBuffer.type, buffer );
48915			const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
48916			ib.uuid = interleavedBuffer.uuid;
48917
48918			if ( interleavedBuffer.usage !== undefined ) ib.setUsage( interleavedBuffer.usage );
48919
48920			interleavedBufferMap[ uuid ] = ib;
48921
48922			return ib;
48923
48924		}
48925
48926		function getArrayBuffer( json, uuid ) {
48927
48928			if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
48929
48930			const arrayBuffers = json.arrayBuffers;
48931			const arrayBuffer = arrayBuffers[ uuid ];
48932
48933			const ab = new Uint32Array( arrayBuffer ).buffer;
48934
48935			arrayBufferMap[ uuid ] = ab;
48936
48937			return ab;
48938
48939		}
48940
48941		const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
48942
48943		const index = json.data.index;
48944
48945		if ( index !== undefined ) {
48946
48947			const typedArray = getTypedArray( index.type, index.array );
48948			geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
48949
48950		}
48951
48952		const attributes = json.data.attributes;
48953
48954		for ( const key in attributes ) {
48955
48956			const attribute = attributes[ key ];
48957			let bufferAttribute;
48958
48959			if ( attribute.isInterleavedBufferAttribute ) {
48960
48961				const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
48962				bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
48963
48964			} else {
48965
48966				const typedArray = getTypedArray( attribute.type, attribute.array );
48967				const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
48968				bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
48969
48970			}
48971
48972			if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
48973			if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
48974			if ( attribute.gpuType !== undefined ) bufferAttribute.gpuType = attribute.gpuType;
48975
48976			geometry.setAttribute( key, bufferAttribute );
48977
48978		}
48979
48980		const morphAttributes = json.data.morphAttributes;
48981
48982		if ( morphAttributes ) {
48983
48984			for ( const key in morphAttributes ) {
48985
48986				const attributeArray = morphAttributes[ key ];
48987
48988				const array = [];
48989
48990				for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
48991
48992					const attribute = attributeArray[ i ];
48993					let bufferAttribute;
48994
48995					if ( attribute.isInterleavedBufferAttribute ) {
48996
48997						const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
48998						bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
48999
49000					} else {
49001
49002						const typedArray = getTypedArray( attribute.type, attribute.array );
49003						bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
49004
49005					}
49006
49007					if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
49008					if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
49009					if ( attribute.gpuType !== undefined ) bufferAttribute.gpuType = attribute.gpuType;
49010					array.push( bufferAttribute );
49011
49012				}
49013
49014				geometry.morphAttributes[ key ] = array;
49015
49016			}
49017
49018		}
49019
49020		const morphTargetsRelative = json.data.morphTargetsRelative;
49021
49022		if ( morphTargetsRelative ) {
49023
49024			geometry.morphTargetsRelative = true;
49025
49026		}
49027
49028		const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
49029
49030		if ( groups !== undefined ) {
49031
49032			for ( let i = 0, n = groups.length; i !== n; ++ i ) {
49033
49034				const group = groups[ i ];
49035
49036				geometry.addGroup( group.start, group.count, group.materialIndex );
49037
49038			}
49039
49040		}
49041
49042		const boundingSphere = json.data.boundingSphere;
49043
49044		if ( boundingSphere !== undefined ) {
49045
49046			geometry.boundingSphere = new Sphere().fromJSON( boundingSphere );
49047
49048		}
49049
49050		if ( json.name ) geometry.name = json.name;
49051		if ( json.userData ) geometry.userData = json.userData;
49052
49053		return geometry;
49054
49055	}
49056
49057}
49058
49059const _customGeometries = {};
49060
49061/**
49062 * A loader for loading a JSON resource in the [JSON Object/Scene format](https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4).
49063 * The files are internally loaded via {@link FileLoader}.
49064 *
49065 * ```js
49066 * const loader = new THREE.ObjectLoader();
49067 * const obj = await loader.loadAsync( 'models/json/example.json' );
49068 * scene.add( obj );
49069 *
49070 * // Alternatively, to parse a previously loaded JSON structure
49071 * const object = await loader.parseAsync( a_json_object );
49072 * scene.add( object );
49073 * ```
49074 *
49075 * @augments Loader
49076 */
49077class ObjectLoader extends Loader {
49078
49079	/**
49080	 * Constructs a new object loader.
49081	 *
49082	 * @param {LoadingManager} [manager] - The loading manager.
49083	 */
49084	constructor( manager ) {
49085
49086		super( manager );
49087
49088	}
49089
49090	/**
49091	 * Starts loading from the given URL and pass the loaded 3D object to the `onLoad()` callback.
49092	 *
49093	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
49094	 * @param {function(Object3D)} onLoad - Executed when the loading process has been finished.
49095	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
49096	 * @param {onErrorCallback} onError - Executed when errors occur.
49097	 */
49098	load( url, onLoad, onProgress, onError ) {
49099
49100		const scope = this;
49101
49102		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
49103		this.resourcePath = this.resourcePath || path;
49104
49105		const loader = new FileLoader( this.manager );
49106		loader.setPath( this.path );
49107		loader.setRequestHeader( this.requestHeader );
49108		loader.setWithCredentials( this.withCredentials );
49109		loader.load( url, function ( text ) {
49110
49111			let json = null;
49112
49113			try {
49114
49115				json = JSON.parse( text );
49116
49117			} catch ( e ) {
49118
49119				if ( onError !== undefined ) onError( e );
49120
49121				error( 'ObjectLoader: Can\'t parse ' + url + '.', e.message );
49122
49123				return;
49124
49125			}
49126
49127			const metadata = json.metadata;
49128
49129			if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
49130
49131				if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) );
49132
49133				error( 'ObjectLoader: Can\'t load ' + url );
49134				return;
49135
49136			}
49137
49138			scope.parse( json, onLoad );
49139
49140		}, onProgress, onError );
49141
49142	}
49143
49144	/**
49145	 * Async version of {@link ObjectLoader#load}.
49146	 *
49147	 * @async
49148	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
49149	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
49150	 * @return {Promise<Object3D>} A Promise that resolves with the loaded 3D object.
49151	 */
49152	async loadAsync( url, onProgress ) {
49153
49154		const scope = this;
49155
49156		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
49157		this.resourcePath = this.resourcePath || path;
49158
49159		const loader = new FileLoader( this.manager );
49160		loader.setPath( this.path );
49161		loader.setRequestHeader( this.requestHeader );
49162		loader.setWithCredentials( this.withCredentials );
49163
49164		const text = await loader.loadAsync( url, onProgress );
49165
49166		let json;
49167
49168		try {
49169
49170			json = JSON.parse( text );
49171
49172		} catch ( e ) {
49173
49174			throw new Error( 'THREE.ObjectLoader: Can\'t parse ' + url + '. ' + e.message );
49175
49176		}
49177
49178		const metadata = json.metadata;
49179
49180		if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
49181
49182			throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url );
49183
49184		}
49185
49186		return await scope.parseAsync( json );
49187
49188	}
49189
49190	/**
49191	 * Parses the given JSON. This is used internally by {@link ObjectLoader#load}
49192	 * but can also be used directly to parse a previously loaded JSON structure.
49193	 *
49194	 * @param {Object} json - The serialized 3D object.
49195	 * @param {onLoad} onLoad - Executed when all resources (e.g. textures) have been fully loaded.
49196	 * @return {Object3D} The parsed 3D object.
49197	 */
49198	parse( json, onLoad ) {
49199
49200		const animations = this.parseAnimations( json.animations );
49201		const shapes = this.parseShapes( json.shapes );
49202		const geometries = this.parseGeometries( json.geometries, shapes );
49203
49204		const images = this.parseImages( json.images, function () {
49205
49206			if ( onLoad !== undefined ) onLoad( object );
49207
49208		} );
49209
49210		const textures = this.parseTextures( json.textures, images );
49211		const materials = this.parseMaterials( json.materials, textures );
49212
49213		const object = this.parseObject( json.object, geometries, materials, textures, animations );
49214		const skeletons = this.parseSkeletons( json.skeletons, object );
49215
49216		this.bindSkeletons( object, skeletons );
49217		this.bindLightTargets( object );
49218
49219		//
49220
49221		if ( onLoad !== undefined ) {
49222
49223			let hasImages = false;
49224
49225			for ( const uuid in images ) {
49226
49227				if ( images[ uuid ].data instanceof HTMLImageElement ) {
49228
49229					hasImages = true;
49230					break;
49231
49232				}
49233
49234			}
49235
49236			if ( hasImages === false ) onLoad( object );
49237
49238		}
49239
49240		return object;
49241
49242	}
49243
49244	/**
49245	 * Async version of {@link ObjectLoader#parse}.
49246	 *
49247	 * @param {Object} json - The serialized 3D object.
49248	 * @return {Promise<Object3D>} A Promise that resolves with the parsed 3D object.
49249	 */
49250	async parseAsync( json ) {
49251
49252		const animations = this.parseAnimations( json.animations );
49253		const shapes = this.parseShapes( json.shapes );
49254		const geometries = this.parseGeometries( json.geometries, shapes );
49255
49256		const images = await this.parseImagesAsync( json.images );
49257
49258		const textures = this.parseTextures( json.textures, images );
49259		const materials = this.parseMaterials( json.materials, textures );
49260
49261		const object = this.parseObject( json.object, geometries, materials, textures, animations );
49262		const skeletons = this.parseSkeletons( json.skeletons, object );
49263
49264		this.bindSkeletons( object, skeletons );
49265		this.bindLightTargets( object );
49266
49267		return object;
49268
49269	}
49270
49271	/**
49272	 * Registers the given geometry at the internal
49273	 * geometry library.
49274	 *
49275	 * @static
49276	 * @param {string} type - The geometry type.
49277	 * @param {BufferGeometry.constructor} geometryClass - The geometry class.
49278	 */
49279	static registerGeometry( type, geometryClass ) {
49280
49281		_customGeometries[ type ] = geometryClass;
49282
49283	}
49284
49285	// internals
49286
49287	parseShapes( json ) {
49288
49289		const shapes = {};
49290
49291		if ( json !== undefined ) {
49292
49293			for ( let i = 0, l = json.length; i < l; i ++ ) {
49294
49295				const shape = new Shape().fromJSON( json[ i ] );
49296
49297				shapes[ shape.uuid ] = shape;
49298
49299			}
49300
49301		}
49302
49303		return shapes;
49304
49305	}
49306
49307	parseSkeletons( json, object ) {
49308
49309		const skeletons = {};
49310		const bones = {};
49311
49312		// generate bone lookup table
49313
49314		object.traverse( function ( child ) {
49315
49316			if ( child.isBone ) bones[ child.uuid ] = child;
49317
49318		} );
49319
49320		// create skeletons
49321
49322		if ( json !== undefined ) {
49323
49324			for ( let i = 0, l = json.length; i < l; i ++ ) {
49325
49326				const skeleton = new Skeleton().fromJSON( json[ i ], bones );
49327
49328				skeletons[ skeleton.uuid ] = skeleton;
49329
49330			}
49331
49332		}
49333
49334		return skeletons;
49335
49336	}
49337
49338	parseGeometries( json, shapes ) {
49339
49340		const geometries = {};
49341
49342		if ( json !== undefined ) {
49343
49344			const bufferGeometryLoader = new BufferGeometryLoader();
49345
49346			for ( let i = 0, l = json.length; i < l; i ++ ) {
49347
49348				let geometry;
49349				const data = json[ i ];
49350
49351				switch ( data.type ) {
49352
49353					case 'BufferGeometry':
49354					case 'InstancedBufferGeometry':
49355
49356						geometry = bufferGeometryLoader.parse( data );
49357						break;
49358
49359					default:
49360
49361						if ( data.type in Geometries ) {
49362
49363							geometry = Geometries[ data.type ].fromJSON( data, shapes );
49364
49365						} else if ( data.type in _customGeometries ) {
49366
49367							geometry = _customGeometries[ data.type ].fromJSON( data, shapes );
49368
49369						} else {
49370
49371							warn( `ObjectLoader: Unknown geometry type "${ data.type }". Use .registerGeometry() before starting the deserialization process.` );
49372
49373						}
49374
49375				}
49376
49377				geometry.uuid = data.uuid;
49378
49379				if ( data.name !== undefined ) geometry.name = data.name;
49380				if ( data.userData !== undefined ) geometry.userData = data.userData;
49381
49382				geometries[ data.uuid ] = geometry;
49383
49384			}
49385
49386		}
49387
49388		return geometries;
49389
49390	}
49391
49392	parseMaterials( json, textures ) {
49393
49394		const cache = {}; // MultiMaterial
49395		const materials = {};
49396
49397		if ( json !== undefined ) {
49398
49399			const loader = new MaterialLoader();
49400			loader.setTextures( textures );
49401
49402			for ( let i = 0, l = json.length; i < l; i ++ ) {
49403
49404				const data = json[ i ];
49405
49406				if ( cache[ data.uuid ] === undefined ) {
49407
49408					cache[ data.uuid ] = loader.parse( data );
49409
49410				}
49411
49412				materials[ data.uuid ] = cache[ data.uuid ];
49413
49414			}
49415
49416		}
49417
49418		return materials;
49419
49420	}
49421
49422	parseAnimations( json ) {
49423
49424		const animations = {};
49425
49426		if ( json !== undefined ) {
49427
49428			for ( let i = 0; i < json.length; i ++ ) {
49429
49430				const data = json[ i ];
49431
49432				const clip = AnimationClip.parse( data );
49433
49434				animations[ clip.uuid ] = clip;
49435
49436			}
49437
49438		}
49439
49440		return animations;
49441
49442	}
49443
49444	parseImages( json, onLoad ) {
49445
49446		const scope = this;
49447		const images = {};
49448
49449		let loader;
49450
49451		function loadImage( url ) {
49452
49453			url = scope.manager.resolveURL( url );
49454
49455			scope.manager.itemStart( url );
49456
49457			return loader.load( url, function () {
49458
49459				scope.manager.itemEnd( url );
49460
49461			}, undefined, function () {
49462
49463				scope.manager.itemError( url );
49464				scope.manager.itemEnd( url );
49465
49466			} );
49467
49468		}
49469
49470		function deserializeImage( image ) {
49471
49472			if ( typeof image === 'string' ) {
49473
49474				const url = image;
49475
49476				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
49477
49478				return loadImage( path );
49479
49480			} else {
49481
49482				if ( image.data ) {
49483
49484					return {
49485						data: getTypedArray( image.type, image.data ),
49486						width: image.width,
49487						height: image.height
49488					};
49489
49490				} else {
49491
49492					return null;
49493
49494				}
49495
49496			}
49497
49498		}
49499
49500		if ( json !== undefined && json.length > 0 ) {
49501
49502			const manager = new LoadingManager( onLoad );
49503
49504			loader = new ImageLoader( manager );
49505			loader.setCrossOrigin( this.crossOrigin );
49506
49507			for ( let i = 0, il = json.length; i < il; i ++ ) {
49508
49509				const image = json[ i ];
49510				const url = image.url;
49511
49512				if ( Array.isArray( url ) ) {
49513
49514					// load array of images e.g CubeTexture
49515
49516					const imageArray = [];
49517
49518					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
49519
49520						const currentUrl = url[ j ];
49521
49522						const deserializedImage = deserializeImage( currentUrl );
49523
49524						if ( deserializedImage !== null ) {
49525
49526							if ( deserializedImage instanceof HTMLImageElement ) {
49527
49528								imageArray.push( deserializedImage );
49529
49530							} else {
49531
49532								// special case: handle array of data textures for cube textures
49533
49534								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
49535
49536							}
49537
49538						}
49539
49540					}
49541
49542					images[ image.uuid ] = new TextureSource( imageArray );
49543
49544				} else {
49545
49546					// load single image
49547
49548					const deserializedImage = deserializeImage( image.url );
49549					images[ image.uuid ] = new TextureSource( deserializedImage );
49550
49551
49552				}
49553
49554			}
49555
49556		}
49557
49558		return images;
49559
49560	}
49561
49562	async parseImagesAsync( json ) {
49563
49564		const scope = this;
49565		const images = {};
49566
49567		let loader;
49568
49569		async function deserializeImage( image ) {
49570
49571			if ( typeof image === 'string' ) {
49572
49573				const url = image;
49574
49575				const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
49576
49577				return await loader.loadAsync( path );
49578
49579			} else {
49580
49581				if ( image.data ) {
49582
49583					return {
49584						data: getTypedArray( image.type, image.data ),
49585						width: image.width,
49586						height: image.height
49587					};
49588
49589				} else {
49590
49591					return null;
49592
49593				}
49594
49595			}
49596
49597		}
49598
49599		if ( json !== undefined && json.length > 0 ) {
49600
49601			loader = new ImageLoader( this.manager );
49602			loader.setCrossOrigin( this.crossOrigin );
49603
49604			for ( let i = 0, il = json.length; i < il; i ++ ) {
49605
49606				const image = json[ i ];
49607				const url = image.url;
49608
49609				if ( Array.isArray( url ) ) {
49610
49611					// load array of images e.g CubeTexture
49612
49613					const imageArray = [];
49614
49615					for ( let j = 0, jl = url.length; j < jl; j ++ ) {
49616
49617						const currentUrl = url[ j ];
49618
49619						const deserializedImage = await deserializeImage( currentUrl );
49620
49621						if ( deserializedImage !== null ) {
49622
49623							if ( deserializedImage instanceof HTMLImageElement ) {
49624
49625								imageArray.push( deserializedImage );
49626
49627							} else {
49628
49629								// special case: handle array of data textures for cube textures
49630
49631								imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
49632
49633							}
49634
49635						}
49636
49637					}
49638
49639					images[ image.uuid ] = new TextureSource( imageArray );
49640
49641				} else {
49642
49643					// load single image
49644
49645					const deserializedImage = await deserializeImage( image.url );
49646					images[ image.uuid ] = new TextureSource( deserializedImage );
49647
49648				}
49649
49650			}
49651
49652		}
49653
49654		return images;
49655
49656	}
49657
49658	parseTextures( json, images ) {
49659
49660		function parseConstant( value, type ) {
49661
49662			if ( typeof value === 'number' ) return value;
49663
49664			warn( 'ObjectLoader.parseTexture: Constant should be in numeric form.', value );
49665
49666			return type[ value ];
49667
49668		}
49669
49670		const textures = {};
49671
49672		if ( json !== undefined ) {
49673
49674			for ( let i = 0, l = json.length; i < l; i ++ ) {
49675
49676				const data = json[ i ];
49677
49678				if ( data.image === undefined ) {
49679
49680					warn( 'ObjectLoader: No "image" specified for', data.uuid );
49681
49682				}
49683
49684				if ( images[ data.image ] === undefined ) {
49685
49686					warn( 'ObjectLoader: Undefined image', data.image );
49687
49688				}
49689
49690				const source = images[ data.image ];
49691				const image = source.data;
49692
49693				let texture;
49694
49695				if ( Array.isArray( image ) ) {
49696
49697					texture = new CubeTexture();
49698
49699					if ( image.length === 6 ) texture.needsUpdate = true;
49700
49701				} else {
49702
49703					if ( image && image.data ) {
49704
49705						texture = new DataTexture();
49706
49707					} else {
49708
49709						texture = new Texture();
49710
49711					}
49712
49713					if ( image ) texture.needsUpdate = true; // textures can have undefined image data
49714
49715				}
49716
49717				texture.source = source;
49718
49719				texture.uuid = data.uuid;
49720
49721				if ( data.name !== undefined ) texture.name = data.name;
49722
49723				if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
49724				if ( data.channel !== undefined ) texture.channel = data.channel;
49725
49726				if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
49727				if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
49728				if ( data.center !== undefined ) texture.center.fromArray( data.center );
49729				if ( data.rotation !== undefined ) texture.rotation = data.rotation;
49730
49731				if ( data.wrap !== undefined ) {
49732
49733					texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
49734					texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
49735
49736				}
49737
49738				if ( data.format !== undefined ) texture.format = data.format;
49739				if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat;
49740				if ( data.type !== undefined ) texture.type = data.type;
49741				if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace;
49742
49743				if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
49744				if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
49745				if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
49746
49747				if ( data.flipY !== undefined ) texture.flipY = data.flipY;
49748
49749				if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps;
49750				if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
49751				if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
49752				if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction;
49753				if ( data.normalized !== undefined ) texture.normalized = data.normalized;
49754
49755				if ( data.userData !== undefined ) texture.userData = data.userData;
49756
49757				textures[ data.uuid ] = texture;
49758
49759			}
49760
49761		}
49762
49763		return textures;
49764
49765	}
49766
49767	parseObject( data, geometries, materials, textures, animations ) {
49768
49769		let object;
49770
49771		function getGeometry( name ) {
49772
49773			if ( geometries[ name ] === undefined ) {
49774
49775				warn( 'ObjectLoader: Undefined geometry', name );
49776
49777			}
49778
49779			return geometries[ name ];
49780
49781		}
49782
49783		function getMaterial( name ) {
49784
49785			if ( name === undefined ) return undefined;
49786
49787			if ( Array.isArray( name ) ) {
49788
49789				const array = [];
49790
49791				for ( let i = 0, l = name.length; i < l; i ++ ) {
49792
49793					const uuid = name[ i ];
49794
49795					if ( materials[ uuid ] === undefined ) {
49796
49797						warn( 'ObjectLoader: Undefined material', uuid );
49798
49799					}
49800
49801					array.push( materials[ uuid ] );
49802
49803				}
49804
49805				return array;
49806
49807			}
49808
49809			if ( materials[ name ] === undefined ) {
49810
49811				warn( 'ObjectLoader: Undefined material', name );
49812
49813			}
49814
49815			return materials[ name ];
49816
49817		}
49818
49819		function getTexture( uuid ) {
49820
49821			if ( textures[ uuid ] === undefined ) {
49822
49823				warn( 'ObjectLoader: Undefined texture', uuid );
49824
49825			}
49826
49827			return textures[ uuid ];
49828
49829		}
49830
49831		let geometry, material;
49832
49833		switch ( data.type ) {
49834
49835			case 'Scene':
49836
49837				object = new Scene();
49838
49839				if ( data.background !== undefined ) {
49840
49841					if ( Number.isInteger( data.background ) ) {
49842
49843						object.background = new Color( data.background );
49844
49845					} else {
49846
49847						object.background = getTexture( data.background );
49848
49849					}
49850
49851				}
49852
49853				if ( data.environment !== undefined ) {
49854
49855					object.environment = getTexture( data.environment );
49856
49857				}
49858
49859				if ( data.fog !== undefined ) {
49860
49861					if ( data.fog.type === 'Fog' ) {
49862
49863						object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
49864
49865					} else if ( data.fog.type === 'FogExp2' ) {
49866
49867						object.fog = new FogExp2( data.fog.color, data.fog.density );
49868
49869					}
49870
49871					if ( data.fog.name !== '' ) {
49872
49873						object.fog.name = data.fog.name;
49874
49875					}
49876
49877				}
49878
49879				if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness;
49880				if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity;
49881				if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation );
49882
49883				if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity;
49884				if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation );
49885
49886				break;
49887
49888			case 'PerspectiveCamera':
49889
49890				object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
49891
49892				if ( data.focus !== undefined ) object.focus = data.focus;
49893				if ( data.zoom !== undefined ) object.zoom = data.zoom;
49894				if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
49895				if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
49896				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
49897
49898				break;
49899
49900			case 'OrthographicCamera':
49901
49902				object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
49903
49904				if ( data.zoom !== undefined ) object.zoom = data.zoom;
49905				if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
49906
49907				break;
49908
49909			case 'AmbientLight':
49910
49911				object = new AmbientLight( data.color, data.intensity );
49912
49913				break;
49914
49915			case 'DirectionalLight':
49916
49917				object = new DirectionalLight( data.color, data.intensity );
49918				object.target = data.target || '';
49919
49920				break;
49921
49922			case 'PointLight':
49923
49924				object = new PointLight( data.color, data.intensity, data.distance, data.decay );
49925
49926				break;
49927
49928			case 'RectAreaLight':
49929
49930				object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
49931
49932				break;
49933
49934			case 'SpotLight':
49935
49936				object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
49937				object.target = data.target || '';
49938
49939				break;
49940
49941			case 'HemisphereLight':
49942
49943				object = new HemisphereLight( data.color, data.groundColor, data.intensity );
49944
49945				break;
49946
49947			case 'LightProbe':
49948
49949				const sh = new SphericalHarmonics3().fromArray( data.sh );
49950				object = new LightProbe( sh, data.intensity );
49951
49952				break;
49953
49954			case 'SkinnedMesh':
49955
49956				geometry = getGeometry( data.geometry );
49957			 	material = getMaterial( data.material );
49958
49959				object = new SkinnedMesh( geometry, material );
49960
49961				if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
49962				if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
49963				if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
49964
49965				break;
49966
49967			case 'Mesh':
49968
49969				geometry = getGeometry( data.geometry );
49970				material = getMaterial( data.material );
49971
49972				object = new Mesh( geometry, material );
49973
49974				break;
49975
49976			case 'InstancedMesh':
49977
49978				geometry = getGeometry( data.geometry );
49979				material = getMaterial( data.material );
49980				const count = data.count;
49981				const instanceMatrix = data.instanceMatrix;
49982				const instanceColor = data.instanceColor;
49983
49984				object = new InstancedMesh( geometry, material, count );
49985				object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
49986				if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
49987
49988				break;
49989
49990			case 'BatchedMesh':
49991
49992				geometry = getGeometry( data.geometry );
49993				material = getMaterial( data.material );
49994
49995				object = new BatchedMesh( data.maxInstanceCount, data.maxVertexCount, data.maxIndexCount, material );
49996				object.geometry = geometry;
49997				object.perObjectFrustumCulled = data.perObjectFrustumCulled;
49998				object.sortObjects = data.sortObjects;
49999
50000				object._drawRanges = data.drawRanges;
50001				object._reservedRanges = data.reservedRanges;
50002
50003				object._geometryInfo = data.geometryInfo.map( info => {
50004
50005					let box = null;
50006					let sphere = null;
50007					if ( info.boundingBox !== undefined ) {
50008
50009						box = new Box3().fromJSON( info.boundingBox );
50010
50011					}
50012
50013					if ( info.boundingSphere !== undefined ) {
50014
50015						sphere = new Sphere().fromJSON( info.boundingSphere );
50016
50017					}
50018
50019					return {
50020						...info,
50021						boundingBox: box,
50022						boundingSphere: sphere
50023					};
50024
50025				} );
50026				object._instanceInfo = data.instanceInfo;
50027
50028				object._availableInstanceIds = data._availableInstanceIds;
50029				object._availableGeometryIds = data._availableGeometryIds;
50030
50031				object._nextIndexStart = data.nextIndexStart;
50032				object._nextVertexStart = data.nextVertexStart;
50033				object._geometryCount = data.geometryCount;
50034
50035				object._maxInstanceCount = data.maxInstanceCount;
50036				object._maxVertexCount = data.maxVertexCount;
50037				object._maxIndexCount = data.maxIndexCount;
50038
50039				object._geometryInitialized = data.geometryInitialized;
50040
50041				object._matricesTexture = getTexture( data.matricesTexture.uuid );
50042
50043				object._indirectTexture = getTexture( data.indirectTexture.uuid );
50044
50045				if ( data.colorsTexture !== undefined ) {
50046
50047					object._colorsTexture = getTexture( data.colorsTexture.uuid );
50048
50049				}
50050
50051				if ( data.boundingSphere !== undefined ) {
50052
50053					object.boundingSphere = new Sphere().fromJSON( data.boundingSphere );
50054
50055				}
50056
50057				if ( data.boundingBox !== undefined ) {
50058
50059					object.boundingBox = new Box3().fromJSON( data.boundingBox );
50060
50061				}
50062
50063				break;
50064
50065			case 'LOD':
50066
50067				object = new LOD();
50068
50069				break;
50070
50071			case 'Line':
50072
50073				object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
50074
50075				break;
50076
50077			case 'LineLoop':
50078
50079				object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
50080
50081				break;
50082
50083			case 'LineSegments':
50084
50085				object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
50086
50087				break;
50088
50089			case 'PointCloud':
50090			case 'Points':
50091
50092				object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
50093
50094				break;
50095
50096			case 'Sprite':
50097
50098				object = new Sprite( getMaterial( data.material ) );
50099
50100				break;
50101
50102			case 'Group':
50103
50104				object = new Group();
50105
50106				break;
50107
50108			case 'Bone':
50109
50110				object = new Bone();
50111
50112				break;
50113
50114			default:
50115
50116				object = new Object3D();
50117
50118		}
50119
50120		object.uuid = data.uuid;
50121
50122		if ( data.name !== undefined ) object.name = data.name;
50123
50124		if ( data.matrix !== undefined ) {
50125
50126			object.matrix.fromArray( data.matrix );
50127
50128			if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
50129			if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
50130
50131		} else {
50132
50133			if ( data.position !== undefined ) object.position.fromArray( data.position );
50134			if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
50135			if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
50136			if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
50137
50138		}
50139
50140		if ( data.up !== undefined ) object.up.fromArray( data.up );
50141
50142		if ( data.pivot !== undefined ) object.pivot = new Vector3().fromArray( data.pivot );
50143
50144		if ( data.morphTargetDictionary !== undefined ) object.morphTargetDictionary = Object.assign( {}, data.morphTargetDictionary );
50145		if ( data.morphTargetInfluences !== undefined ) object.morphTargetInfluences = data.morphTargetInfluences.slice();
50146
50147		if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
50148		if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
50149
50150		if ( data.shadow ) {
50151
50152			if ( data.shadow.intensity !== undefined ) object.shadow.intensity = data.shadow.intensity;
50153			if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
50154			if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
50155			if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
50156			if ( data.shadow.blurSamples !== undefined ) object.shadow.blurSamples = data.shadow.blurSamples;
50157			if ( data.shadow.focus !== undefined ) object.shadow.focus = data.shadow.focus;
50158			if ( data.shadow.aspect !== undefined ) object.shadow.aspect = data.shadow.aspect;
50159			if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
50160			if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
50161
50162		}
50163
50164		if ( data.visible !== undefined ) object.visible = data.visible;
50165		if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
50166		if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
50167		if ( data.static !== undefined ) object.static = data.static;
50168		if ( data.userData !== undefined ) object.userData = data.userData;
50169		if ( data.layers !== undefined ) object.layers.mask = data.layers;
50170
50171		if ( data.children !== undefined ) {
50172
50173			const children = data.children;
50174
50175			for ( let i = 0; i < children.length; i ++ ) {
50176
50177				object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) );
50178
50179			}
50180
50181		}
50182
50183		if ( data.animations !== undefined ) {
50184
50185			const objectAnimations = data.animations;
50186
50187			for ( let i = 0; i < objectAnimations.length; i ++ ) {
50188
50189				const uuid = objectAnimations[ i ];
50190
50191				object.animations.push( animations[ uuid ] );
50192
50193			}
50194
50195		}
50196
50197		if ( data.type === 'LOD' ) {
50198
50199			if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
50200
50201			const levels = data.levels;
50202
50203			for ( let l = 0; l < levels.length; l ++ ) {
50204
50205				const level = levels[ l ];
50206				const child = object.getObjectByProperty( 'uuid', level.object );
50207
50208				if ( child !== undefined ) {
50209
50210					object.addLevel( child, level.distance, level.hysteresis );
50211
50212				}
50213
50214			}
50215
50216		}
50217
50218		return object;
50219
50220	}
50221
50222	bindSkeletons( object, skeletons ) {
50223
50224		if ( Object.keys( skeletons ).length === 0 ) return;
50225
50226		object.traverse( function ( child ) {
50227
50228			if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
50229
50230				const skeleton = skeletons[ child.skeleton ];
50231
50232				if ( skeleton === undefined ) {
50233
50234					warn( 'ObjectLoader: No skeleton found with UUID:', child.skeleton );
50235
50236				} else {
50237
50238					child.bind( skeleton, child.bindMatrix );
50239
50240				}
50241
50242			}
50243
50244		} );
50245
50246	}
50247
50248	bindLightTargets( object ) {
50249
50250		object.traverse( function ( child ) {
50251
50252			if ( child.isDirectionalLight || child.isSpotLight ) {
50253
50254				const uuid = child.target;
50255
50256				const target = object.getObjectByProperty( 'uuid', uuid );
50257
50258				if ( target !== undefined ) {
50259
50260					child.target = target;
50261
50262				} else {
50263
50264					child.target = new Object3D();
50265
50266				}
50267
50268			}
50269
50270		} );
50271
50272	}
50273
50274}
50275
50276const TEXTURE_MAPPING = {
50277	UVMapping: UVMapping,
50278	CubeReflectionMapping: CubeReflectionMapping,
50279	CubeRefractionMapping: CubeRefractionMapping,
50280	EquirectangularReflectionMapping: EquirectangularReflectionMapping,
50281	EquirectangularRefractionMapping: EquirectangularRefractionMapping,
50282	CubeUVReflectionMapping: CubeUVReflectionMapping
50283};
50284
50285const TEXTURE_WRAPPING = {
50286	RepeatWrapping: RepeatWrapping,
50287	ClampToEdgeWrapping: ClampToEdgeWrapping,
50288	MirroredRepeatWrapping: MirroredRepeatWrapping
50289};
50290
50291const TEXTURE_FILTER = {
50292	NearestFilter: NearestFilter,
50293	NearestMipmapNearestFilter: NearestMipmapNearestFilter,
50294	NearestMipmapLinearFilter: NearestMipmapLinearFilter,
50295	LinearFilter: LinearFilter,
50296	LinearMipmapNearestFilter: LinearMipmapNearestFilter,
50297	LinearMipmapLinearFilter: LinearMipmapLinearFilter
50298};
50299
50300const _errorMap = new WeakMap();
50301
50302/**
50303 * A loader for loading images as an [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap).
50304 * An `ImageBitmap` provides an asynchronous and resource efficient pathway to prepare
50305 * textures for rendering.
50306 *
50307 * Note that {@link Texture#flipY} and {@link Texture#premultiplyAlpha} are ignored with image bitmaps.
50308 * These options need to be configured via {@link ImageBitmapLoader#setOptions} prior to loading,
50309 * unlike regular images which can be configured on the Texture to set these options on GPU upload instead.
50310 *
50311 * To match the default behaviour of {@link Texture}, the following options are needed:
50312 *
50313 * ```js
50314 * { imageOrientation: 'flipY', premultiplyAlpha: 'none' }
50315 * ```
50316 *
50317 * Also note that unlike {@link FileLoader}, this loader will only avoid multiple concurrent requests to the same URL if {@link Cache} is enabled.
50318 *
50319 * ```js
50320 * const loader = new THREE.ImageBitmapLoader();
50321 * loader.setOptions( { imageOrientation: 'flipY' } ); // set options if needed
50322 * const imageBitmap = await loader.loadAsync( 'image.png' );
50323 *
50324 * const texture = new THREE.Texture( imageBitmap );
50325 * texture.needsUpdate = true;
50326 * ```
50327 *
50328 * @augments Loader
50329 */
50330class ImageBitmapLoader extends Loader {
50331
50332	/**
50333	 * Constructs a new image bitmap loader.
50334	 *
50335	 * @param {LoadingManager} [manager] - The loading manager.
50336	 */
50337	constructor( manager ) {
50338
50339		super( manager );
50340
50341		/**
50342		 * This flag can be used for type testing.
50343		 *
50344		 * @type {boolean}
50345		 * @readonly
50346		 * @default true
50347		 */
50348		this.isImageBitmapLoader = true;
50349
50350		if ( typeof createImageBitmap === 'undefined' ) {
50351
50352			warn( 'ImageBitmapLoader: createImageBitmap() not supported.' );
50353
50354		}
50355
50356		if ( typeof fetch === 'undefined' ) {
50357
50358			warn( 'ImageBitmapLoader: fetch() not supported.' );
50359
50360		}
50361
50362		/**
50363		 * Represents the loader options.
50364		 *
50365		 * @type {Object}
50366		 * @default {premultiplyAlpha:'none'}
50367		 */
50368		this.options = { premultiplyAlpha: 'none' };
50369
50370		/**
50371		 * Used for aborting requests.
50372		 *
50373		 * @private
50374		 * @type {AbortController}
50375		 */
50376		this._abortController = new AbortController();
50377
50378	}
50379
50380	/**
50381	 * Sets the given loader options. The structure of the object must match the `options` parameter of
50382	 * [createImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/Window/createImageBitmap).
50383	 *
50384	 * Note: When caching is enabled, the cache key is based on the URL only. Loading the same URL with
50385	 * different options will return the cached result of the first request.
50386	 *
50387	 * @param {Object} options - The loader options to set.
50388	 * @return {ImageBitmapLoader} A reference to this image bitmap loader.
50389	 */
50390	setOptions( options ) {
50391
50392		this.options = options;
50393
50394		return this;
50395
50396	}
50397
50398	/**
50399	 * Starts loading from the given URL and pass the loaded image bitmap to the `onLoad()` callback.
50400	 *
50401	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
50402	 * @param {function(ImageBitmap)} onLoad - Executed when the loading process has been finished.
50403	 * @param {onProgressCallback} onProgress - Unsupported in this loader.
50404	 * @param {onErrorCallback} onError - Executed when errors occur.
50405	 */
50406	load( url, onLoad, onProgress, onError ) {
50407
50408		if ( url === undefined ) url = '';
50409
50410		if ( this.path !== undefined ) url = this.path + url;
50411
50412		url = this.manager.resolveURL( url );
50413
50414		const scope = this;
50415
50416		const cached = Cache.get( `image-bitmap:${url}` );
50417
50418		if ( cached !== undefined ) {
50419
50420			scope.manager.itemStart( url );
50421
50422			// If cached is a promise, wait for it to resolve
50423			if ( cached.then ) {
50424
50425				cached.then( imageBitmap => {
50426
50427					// check if there is an error for the cached promise
50428
50429					if ( _errorMap.has( cached ) === true ) {
50430
50431						if ( onError ) onError( _errorMap.get( cached ) );
50432
50433						scope.manager.itemError( url );
50434						scope.manager.itemEnd( url );
50435
50436					} else {
50437
50438						if ( onLoad ) onLoad( imageBitmap );
50439
50440						scope.manager.itemEnd( url );
50441
50442					}
50443
50444				} );
50445
50446				return;
50447
50448			}
50449
50450			// If cached is not a promise (i.e., it's already an imageBitmap)
50451			setTimeout( function () {
50452
50453				if ( onLoad ) onLoad( cached );
50454
50455				scope.manager.itemEnd( url );
50456
50457			}, 0 );
50458
50459			return;
50460
50461		}
50462
50463		const fetchOptions = {};
50464		fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
50465		fetchOptions.headers = this.requestHeader;
50466		fetchOptions.signal = ( typeof AbortSignal.any === 'function' ) ? AbortSignal.any( [ this._abortController.signal, this.manager.abortController.signal ] ) : this._abortController.signal;
50467
50468		const promise = fetch( url, fetchOptions ).then( function ( res ) {
50469
50470			return res.blob();
50471
50472		} ).then( function ( blob ) {
50473
50474			return createImageBitmap( blob, Object.assign( {}, scope.options, { colorSpaceConversion: 'none' } ) );
50475
50476		} ).then( function ( imageBitmap ) {
50477
50478			Cache.add( `image-bitmap:${url}`, imageBitmap );
50479
50480			if ( onLoad ) onLoad( imageBitmap );
50481
50482			scope.manager.itemEnd( url );
50483
50484			return imageBitmap; // see #34150
50485
50486		} ).catch( function ( e ) {
50487
50488			if ( onError ) onError( e );
50489
50490			_errorMap.set( promise, e );
50491
50492			Cache.remove( `image-bitmap:${url}` );
50493
50494			scope.manager.itemError( url );
50495			scope.manager.itemEnd( url );
50496
50497		} );
50498
50499		Cache.add( `image-bitmap:${url}`, promise );
50500		scope.manager.itemStart( url );
50501
50502	}
50503
50504	/**
50505	 * Aborts ongoing fetch requests.
50506	 *
50507	 * @return {ImageBitmapLoader} A reference to this instance.
50508	 */
50509	abort() {
50510
50511		this._abortController.abort();
50512		this._abortController = new AbortController();
50513
50514		return this;
50515
50516	}
50517
50518}
50519
50520let _context;
50521
50522/**
50523 * Manages the global audio context in the engine.
50524 *
50525 * @hideconstructor
50526 */
50527class AudioContext {
50528
50529	/**
50530	 * Returns the global native audio context.
50531	 *
50532	 * @return {Window.AudioContext} The native audio context.
50533	 */
50534	static getContext() {
50535
50536		if ( _context === undefined ) {
50537
50538			_context = new ( window.AudioContext || window.webkitAudioContext )();
50539
50540		}
50541
50542		return _context;
50543
50544	}
50545
50546	/**
50547	 * Allows to set the global native audio context from outside.
50548	 *
50549	 * @param {Window.AudioContext} value - The native context to set.
50550	 */
50551	static setContext( value ) {
50552
50553		_context = value;
50554
50555	}
50556
50557}
50558
50559/**
50560 * Class for loading audio buffers. Audios are internally
50561 * loaded via {@link FileLoader}.
50562 *
50563 * ```js
50564 * const audioListener = new THREE.AudioListener();
50565 * const ambientSound = new THREE.Audio( audioListener );
50566 *
50567 * const loader = new THREE.AudioLoader();
50568 * const audioBuffer = await loader.loadAsync( 'audio/ambient_ocean.ogg' );
50569 *
50570 * ambientSound.setBuffer( audioBuffer );
50571 * ambientSound.play();
50572 * ```
50573 *
50574 * @augments Loader
50575 */
50576class AudioLoader extends Loader {
50577
50578	/**
50579	 * Constructs a new audio loader.
50580	 *
50581	 * @param {LoadingManager} [manager] - The loading manager.
50582	 */
50583	constructor( manager ) {
50584
50585		super( manager );
50586
50587	}
50588
50589	/**
50590	 * Starts loading from the given URL and passes the loaded audio buffer
50591	 * to the `onLoad()` callback.
50592	 *
50593	 * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
50594	 * @param {function(AudioBuffer)} onLoad - Executed when the loading process has been finished.
50595	 * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
50596	 * @param {onErrorCallback} onError - Executed when errors occur.
50597	 */
50598	load( url, onLoad, onProgress, onError ) {
50599
50600		const scope = this;
50601
50602		const loader = new FileLoader( this.manager );
50603		loader.setResponseType( 'arraybuffer' );
50604		loader.setPath( this.path );
50605		loader.setRequestHeader( this.requestHeader );
50606		loader.setWithCredentials( this.withCredentials );
50607		loader.load( url, function ( buffer ) {
50608
50609			try {
50610
50611				// Create a copy of the buffer. The `decodeAudioData` method
50612				// detaches the buffer when complete, preventing reuse.
50613				const bufferCopy = buffer.slice( 0 );
50614
50615				const context = AudioContext.getContext();
50616
50617				const decodeUrl = url + '#decode';
50618				scope.manager.itemStart( decodeUrl ); // prevent loading manager from completing too early, see #33378
50619
50620				context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
50621
50622					onLoad( audioBuffer );
50623					scope.manager.itemEnd( decodeUrl );
50624
50625				} ).catch( function ( e ) {
50626
50627					handleError( e );
50628					scope.manager.itemEnd( decodeUrl );
50629
50630				} );
50631
50632			} catch ( e ) {
50633
50634				handleError( e );
50635
50636			}
50637
50638		}, onProgress, onError );
50639
50640		function handleError( e ) {
50641
50642			if ( onError ) {
50643
50644				onError( e );
50645
50646			} else {
50647
50648				error( e );
50649
50650			}
50651
50652			scope.manager.itemError( url );
50653
50654		}
50655
50656	}
50657
50658}
50659
50660const _eyeRight = /*@__PURE__*/ new Matrix4();
50661const _eyeLeft = /*@__PURE__*/ new Matrix4();
50662const _projectionMatrix = /*@__PURE__*/ new Matrix4();
50663
50664/**
50665 * A special type of camera that uses two perspective cameras with
50666 * stereoscopic projection. Can be used for rendering stereo effects
50667 * like [3D Anaglyph](https://en.wikipedia.org/wiki/Anaglyph_3D) or
50668 * [Parallax Barrier](https://en.wikipedia.org/wiki/parallax_barrier).
50669 */
50670class StereoCamera {
50671
50672	/**
50673	 * Constructs a new stereo camera.
50674	 */
50675	constructor() {
50676
50677		/**
50678		 * The type property is used for detecting the object type
50679		 * in context of serialization/deserialization.
50680		 *
50681		 * @type {string}
50682		 * @readonly
50683		 */
50684		this.type = 'StereoCamera';
50685
50686		/**
50687		 * The aspect.
50688		 *
50689		 * @type {number}
50690		 * @default 1
50691		 */
50692		this.aspect = 1;
50693
50694		/**
50695		 * The eye separation which represents the distance
50696		 * between the left and right camera.
50697		 *
50698		 * @type {number}
50699		 * @default 0.064
50700		 */
50701		this.eyeSep = 0.064;
50702
50703		/**
50704		 * The camera representing the left eye. This is added to layer `1` so objects to be
50705		 * rendered by the left camera must also be added to this layer.
50706		 *
50707		 * @type {PerspectiveCamera}
50708		 */
50709		this.cameraL = new PerspectiveCamera();
50710		this.cameraL.layers.enable( 1 );
50711		this.cameraL.matrixAutoUpdate = false;
50712
50713		/**
50714		 * The camera representing the right eye. This is added to layer `2` so objects to be
50715		 * rendered by the right camera must also be added to this layer.
50716		 *
50717		 * @type {PerspectiveCamera}
50718		 */
50719		this.cameraR = new PerspectiveCamera();
50720		this.cameraR.layers.enable( 2 );
50721		this.cameraR.matrixAutoUpdate = false;
50722
50723		this._cache = {
50724			focus: null,
50725			fov: null,
50726			aspect: null,
50727			near: null,
50728			far: null,
50729			zoom: null,
50730			eyeSep: null
50731		};
50732
50733	}
50734
50735	/**
50736	 * Updates the stereo camera based on the given perspective camera.
50737	 *
50738	 * @param {PerspectiveCamera} camera - The perspective camera.
50739	 */
50740	update( camera ) {
50741
50742		const cache = this._cache;
50743
50744		const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
50745			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
50746			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
50747
50748		if ( needsUpdate ) {
50749
50750			cache.focus = camera.focus;
50751			cache.fov = camera.fov;
50752			cache.aspect = camera.aspect * this.aspect;
50753			cache.near = camera.near;
50754			cache.far = camera.far;
50755			cache.zoom = camera.zoom;
50756			cache.eyeSep = this.eyeSep;
50757
50758			// Off-axis stereoscopic effect based on
50759			// http://paulbourke.net/stereographics/stereorender/
50760
50761			_projectionMatrix.copy( camera.projectionMatrix );
50762			const eyeSepHalf = cache.eyeSep / 2;
50763			const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
50764			const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
50765			let xmin, xmax;
50766
50767			// translate xOffset
50768
50769			_eyeLeft.elements[ 12 ] = - eyeSepHalf;
50770			_eyeRight.elements[ 12 ] = eyeSepHalf;
50771
50772			// for left eye
50773
50774			xmin = - ymax * cache.aspect + eyeSepOnProjection;
50775			xmax = ymax * cache.aspect + eyeSepOnProjection;
50776
50777			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
50778			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
50779
50780			this.cameraL.projectionMatrix.copy( _projectionMatrix );
50781
50782			// for right eye
50783
50784			xmin = - ymax * cache.aspect - eyeSepOnProjection;
50785			xmax = ymax * cache.aspect - eyeSepOnProjection;
50786
50787			_projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
50788			_projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
50789
50790			this.cameraR.projectionMatrix.copy( _projectionMatrix );
50791
50792		}
50793
50794		this.cameraL.matrix.copy( camera.matrixWorld ).multiply( _eyeLeft );
50795		this.cameraL.matrixWorldNeedsUpdate = true;
50796
50797		this.cameraR.matrix.copy( camera.matrixWorld ).multiply( _eyeRight );
50798		this.cameraR.matrixWorldNeedsUpdate = true;
50799
50800	}
50801
50802}
50803
50804const fov = -90; // negative fov is not an error
50805const aspect = 1;
50806
50807/**
50808 * A special type of camera that is positioned in 3D space to render its surroundings into a
50809 * cube render target. The render target can then be used as an environment map for rendering
50810 * realtime reflections in your scene.
50811 *
50812 * ```js
50813 * // Create cube render target
50814 * const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, { generateMipmaps: true, minFilter: THREE.LinearMipmapLinearFilter } );
50815 *
50816 * // Create cube camera
50817 * const cubeCamera = new THREE.CubeCamera( 1, 100000, cubeRenderTarget );
50818 * scene.add( cubeCamera );
50819 *
50820 * // Create car
50821 * const chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeRenderTarget.texture } );
50822 * const car = new THREE.Mesh( carGeometry, chromeMaterial );
50823 * scene.add( car );
50824 *
50825 * // Update the render target cube
50826 * car.visible = false;
50827 * cubeCamera.position.copy( car.position );
50828 * cubeCamera.update( renderer, scene );
50829 *
50830 * // Render the scene
50831 * car.visible = true;
50832 * renderer.render( scene, camera );
50833 * ```
50834 *
50835 * @augments Object3D
50836 */
50837class CubeCamera extends Object3D {
50838
50839	/**
50840	 * Constructs a new cube camera.
50841	 *
50842	 * @param {number} near - The camera's near plane.
50843	 * @param {number} far - The camera's far plane.
50844	 * @param {WebGLCubeRenderTarget} renderTarget - The cube render target.
50845	 */
50846	constructor( near, far, renderTarget ) {
50847
50848		super();
50849
50850		this.type = 'CubeCamera';
50851
50852		/**
50853		 * A reference to the cube render target.
50854		 *
50855		 * @type {WebGLCubeRenderTarget}
50856		 */
50857		this.renderTarget = renderTarget;
50858
50859		/**
50860		 * The current active coordinate system.
50861		 *
50862		 * @type {?(WebGLCoordinateSystem|WebGPUCoordinateSystem)}
50863		 * @default null
50864		 */
50865		this.coordinateSystem = null;
50866
50867		/**
50868		 * The current active mipmap level
50869		 *
50870		 * @type {number}
50871		 * @default 0
50872		 */
50873		this.activeMipmapLevel = 0;
50874
50875		const cameraPX = new PerspectiveCamera( fov, aspect, near, far );
50876		cameraPX.layers = this.layers;
50877		this.add( cameraPX );
50878
50879		const cameraNX = new PerspectiveCamera( fov, aspect, near, far );
50880		cameraNX.layers = this.layers;
50881		this.add( cameraNX );
50882
50883		const cameraPY = new PerspectiveCamera( fov, aspect, near, far );
50884		cameraPY.layers = this.layers;
50885		this.add( cameraPY );
50886
50887		const cameraNY = new PerspectiveCamera( fov, aspect, near, far );
50888		cameraNY.layers = this.layers;
50889		this.add( cameraNY );
50890
50891		const cameraPZ = new PerspectiveCamera( fov, aspect, near, far );
50892		cameraPZ.layers = this.layers;
50893		this.add( cameraPZ );
50894
50895		const cameraNZ = new PerspectiveCamera( fov, aspect, near, far );
50896		cameraNZ.layers = this.layers;
50897		this.add( cameraNZ );
50898
50899	}
50900
50901	/**
50902	 * Must be called when the coordinate system of the cube camera is changed.
50903	 */
50904	updateCoordinateSystem() {
50905
50906		const coordinateSystem = this.coordinateSystem;
50907
50908		const cameras = this.children.concat();
50909
50910		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
50911
50912		for ( const camera of cameras ) this.remove( camera );
50913
50914		if ( coordinateSystem === WebGLCoordinateSystem ) {
50915
50916			cameraPX.up.set( 0, 1, 0 );
50917			cameraPX.lookAt( 1, 0, 0 );
50918
50919			cameraNX.up.set( 0, 1, 0 );
50920			cameraNX.lookAt( -1, 0, 0 );
50921
50922			cameraPY.up.set( 0, 0, -1 );
50923			cameraPY.lookAt( 0, 1, 0 );
50924
50925			cameraNY.up.set( 0, 0, 1 );
50926			cameraNY.lookAt( 0, -1, 0 );
50927
50928			cameraPZ.up.set( 0, 1, 0 );
50929			cameraPZ.lookAt( 0, 0, 1 );
50930
50931			cameraNZ.up.set( 0, 1, 0 );
50932			cameraNZ.lookAt( 0, 0, -1 );
50933
50934		} else if ( coordinateSystem === WebGPUCoordinateSystem ) {
50935
50936			cameraPX.up.set( 0, -1, 0 );
50937			cameraPX.lookAt( -1, 0, 0 );
50938
50939			cameraNX.up.set( 0, -1, 0 );
50940			cameraNX.lookAt( 1, 0, 0 );
50941
50942			cameraPY.up.set( 0, 0, 1 );
50943			cameraPY.lookAt( 0, 1, 0 );
50944
50945			cameraNY.up.set( 0, 0, -1 );
50946			cameraNY.lookAt( 0, -1, 0 );
50947
50948			cameraPZ.up.set( 0, -1, 0 );
50949			cameraPZ.lookAt( 0, 0, 1 );
50950
50951			cameraNZ.up.set( 0, -1, 0 );
50952			cameraNZ.lookAt( 0, 0, -1 );
50953
50954		} else {
50955
50956			throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
50957
50958		}
50959
50960		for ( const camera of cameras ) {
50961
50962			this.add( camera );
50963
50964			camera.updateMatrixWorld();
50965
50966		}
50967
50968	}
50969
50970	/**
50971	 * Calling this method will render the given scene with the given renderer
50972	 * into the cube render target of the camera.
50973	 *
50974	 * @param {(Renderer|WebGLRenderer)} renderer - The renderer.
50975	 * @param {Scene} scene - The scene to render.
50976	 */
50977	update( renderer, scene ) {
50978
50979		if ( this.parent === null ) this.updateMatrixWorld();
50980
50981		const { renderTarget, activeMipmapLevel } = this;
50982
50983		if ( this.coordinateSystem !== renderer.coordinateSystem ) {
50984
50985			this.coordinateSystem = renderer.coordinateSystem;
50986
50987			this.updateCoordinateSystem();
50988
50989		}
50990
50991		const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
50992
50993		const currentRenderTarget = renderer.getRenderTarget();
50994		const currentActiveCubeFace = renderer.getActiveCubeFace();
50995		const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
50996
50997		const currentXrEnabled = renderer.xr.enabled;
50998
50999		renderer.xr.enabled = false;
51000
51001		const generateMipmaps = renderTarget.texture.generateMipmaps;
51002
51003		renderTarget.texture.generateMipmaps = false;
51004
51005		// https://github.com/mrdoob/three.js/issues/31413#issuecomment-3095966812
51006
51007		let reversedDepthBuffer = false;
51008
51009		if ( renderer.isWebGLRenderer === true ) {
51010
51011			reversedDepthBuffer = renderer.state.buffers.depth.getReversed();
51012
51013		} else {
51014
51015			reversedDepthBuffer = renderer.reversedDepthBuffer;
51016
51017		}
51018
51019		renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
51020		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
51021		renderer.render( scene, cameraPX );
51022
51023		renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
51024		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
51025		renderer.render( scene, cameraNX );
51026
51027		renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
51028		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
51029		renderer.render( scene, cameraPY );
51030
51031		renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
51032		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
51033		renderer.render( scene, cameraNY );
51034
51035		renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
51036		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
51037		renderer.render( scene, cameraPZ );
51038
51039		// mipmaps are generated during the last call of render()
51040		// at this point, all sides of the cube render target are defined
51041
51042		renderTarget.texture.generateMipmaps = generateMipmaps;
51043
51044		renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
51045		if ( reversedDepthBuffer && renderer.autoClear === false ) renderer.clearDepth();
51046		renderer.render( scene, cameraNZ );
51047
51048		renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
51049
51050		renderer.xr.enabled = currentXrEnabled;
51051
51052		renderTarget.texture.needsPMREMUpdate = true;
51053
51054	}
51055
51056}
51057
51058/**
51059 * This type of camera can be used in order to efficiently render a scene with a
51060 * predefined set of cameras. This is an important performance aspect for
51061 * rendering VR scenes.
51062 *
51063 * An instance of `ArrayCamera` always has an array of sub cameras. It's mandatory
51064 * to define for each sub camera the `viewport` property which determines the
51065 * part of the viewport that is rendered with this camera.
51066 *
51067 * @augments PerspectiveCamera
51068 */
51069class ArrayCamera extends PerspectiveCamera {
51070
51071	/**
51072	 * Constructs a new array camera.
51073	 *
51074	 * @param {Array<PerspectiveCamera>} [array=[]] - An array of perspective sub cameras.
51075	 */
51076	constructor( array = [] ) {
51077
51078		super();
51079
51080		/**
51081		 * This flag can be used for type testing.
51082		 *
51083		 * @type {boolean}
51084		 * @readonly
51085		 * @default true
51086		 */
51087		this.isArrayCamera = true;
51088
51089		/**
51090		 * Whether this camera is used with multiview rendering or not.
51091		 *
51092		 * @type {boolean}
51093		 * @readonly
51094		 * @default false
51095		 */
51096		this.isMultiViewCamera = false;
51097
51098		/**
51099		 * An array of perspective sub cameras.
51100		 *
51101		 * @type {Array<PerspectiveCamera>}
51102		 */
51103		this.cameras = array;
51104
51105	}
51106
51107}
51108
51109/**
51110 * This class is an alternative to {@link Clock} with a different API design and behavior.
51111 * The goal is to avoid the conceptual flaws that became apparent in `Clock` over time.
51112 *
51113 * - `Timer` has an `update()` method that updates its internal state. That makes it possible to
51114 * call `getDelta()` and `getElapsed()` multiple times per simulation step without getting different values.
51115 * - The class can make use of the Page Visibility API to avoid large time delta values when the app
51116 * is inactive (e.g. tab switched or browser hidden).
51117 *
51118 * ```js
51119 * const timer = new Timer();
51120 * timer.connect( document ); // use Page Visibility API
51121 * ```
51122 */
51123class Timer {
51124
51125	/**
51126	 * Constructs a new timer.
51127	 */
51128	constructor() {
51129
51130		this._previousTime = 0;
51131		this._currentTime = 0;
51132		this._startTime = performance.now();
51133
51134		this._delta = 0;
51135		this._elapsed = 0;
51136
51137		this._timescale = 1;
51138
51139		this._document = null;
51140		this._pageVisibilityHandler = null;
51141
51142	}
51143
51144	/**
51145	 * Connect the timer to the given document.Calling this method is not mandatory to
51146	 * use the timer but enables the usage of the Page Visibility API to avoid large time
51147	 * delta values.
51148	 *
51149	 * @param {Document} document - The document.
51150	 */
51151	connect( document ) {
51152
51153		this._document = document;
51154
51155		// use Page Visibility API to avoid large time delta values
51156
51157		if ( document.hidden !== undefined ) {
51158
51159			this._pageVisibilityHandler = handleVisibilityChange.bind( this );
51160
51161			document.addEventListener( 'visibilitychange', this._pageVisibilityHandler, false );
51162
51163		}
51164
51165	}
51166
51167	/**
51168	 * Disconnects the timer from the DOM and also disables the usage of the Page Visibility API.
51169	 */
51170	disconnect() {
51171
51172		if ( this._pageVisibilityHandler !== null ) {
51173
51174			this._document.removeEventListener( 'visibilitychange', this._pageVisibilityHandler );
51175			this._pageVisibilityHandler = null;
51176
51177		}
51178
51179		this._document = null;
51180
51181	}
51182
51183	/**
51184	 * Returns the time delta in seconds.
51185	 *
51186	 * @return {number} The time delta in second.
51187	 */
51188	getDelta() {
51189
51190		return this._delta / 1000;
51191
51192	}
51193
51194	/**
51195	 * Returns the elapsed time in seconds.
51196	 *
51197	 * @return {number} The elapsed time in second.
51198	 */
51199	getElapsed() {
51200
51201		return this._elapsed / 1000;
51202
51203	}
51204
51205	/**
51206	 * Returns the timescale.
51207	 *
51208	 * @return {number} The timescale.
51209	 */
51210	getTimescale() {
51211
51212		return this._timescale;
51213
51214	}
51215
51216	/**
51217	 * Sets the given timescale which scale the time delta computation
51218	 * in `update()`.
51219	 *
51220	 * @param {number} timescale - The timescale to set.
51221	 * @return {Timer} A reference to this timer.
51222	 */
51223	setTimescale( timescale ) {
51224
51225		this._timescale = timescale;
51226
51227		return this;
51228
51229	}
51230
51231	/**
51232	 * Resets the time computation for the current simulation step.
51233	 *
51234	 * @return {Timer} A reference to this timer.
51235	 */
51236	reset() {
51237
51238		this._currentTime = performance.now() - this._startTime;
51239
51240		return this;
51241
51242	}
51243
51244	/**
51245	 * Can be used to free all internal resources. Usually called when
51246	 * the timer instance isn't required anymore.
51247	 */
51248	dispose() {
51249
51250		this.disconnect();
51251
51252	}
51253
51254	/**
51255	 * Updates the internal state of the timer. This method should be called
51256	 * once per simulation step and before you perform queries against the timer
51257	 * (e.g. via `getDelta()`).
51258	 *
51259	 * @param {number} timestamp - The current time in milliseconds. Can be obtained
51260	 * from the `requestAnimationFrame` callback argument. If not provided, the current
51261	 * time will be determined with `performance.now`.
51262	 * @return {Timer} A reference to this timer.
51263	 */
51264	update( timestamp ) {
51265
51266		if ( this._pageVisibilityHandler !== null && this._document.hidden === true ) {
51267
51268			this._delta = 0;
51269
51270		} else {
51271
51272			this._previousTime = this._currentTime;
51273			this._currentTime = ( timestamp !== undefined ? timestamp : performance.now() ) - this._startTime;
51274
51275			this._delta = ( this._currentTime - this._previousTime ) * this._timescale;
51276			this._elapsed += this._delta; // _elapsed is the accumulation of all previous deltas
51277
51278		}
51279
51280		return this;
51281
51282	}
51283
51284}
51285
51286function handleVisibilityChange() {
51287
51288	if ( this._document.hidden === false ) this.reset();
51289
51290}
51291
51292const _position$1 = /*@__PURE__*/ new Vector3();
51293const _quaternion$1 = /*@__PURE__*/ new Quaternion();
51294const _scale$1 = /*@__PURE__*/ new Vector3();
51295
51296const _forward = /*@__PURE__*/ new Vector3();
51297const _up = /*@__PURE__*/ new Vector3();
51298
51299/**
51300 * The class represents a virtual listener of the all positional and non-positional audio effects
51301 * in the scene. A three.js application usually creates a single listener. It is a mandatory
51302 * constructor parameter for audios entities like {@link Audio} and {@link PositionalAudio}.
51303 *
51304 * In most cases, the listener object is a child of the camera. So the 3D transformation of the
51305 * camera represents the 3D transformation of the listener.
51306 *
51307 * @augments Object3D
51308 */
51309class AudioListener extends Object3D {
51310
51311	/**
51312	 * Constructs a new audio listener.
51313	 */
51314	constructor() {
51315
51316		super();
51317
51318		this.type = 'AudioListener';
51319
51320		/**
51321		 * The native audio context.
51322		 *
51323		 * @type {AudioContext}
51324		 * @readonly
51325		 */
51326		this.context = AudioContext.getContext();
51327
51328		/**
51329		 * The gain node used for volume control.
51330		 *
51331		 * @type {GainNode}
51332		 * @readonly
51333		 */
51334		this.gain = this.context.createGain();
51335		this.gain.connect( this.context.destination );
51336
51337		/**
51338		 * An optional filter.
51339		 *
51340		 * Defined via {@link AudioListener#setFilter}.
51341		 *
51342		 * @type {?AudioNode}
51343		 * @default null
51344		 * @readonly
51345		 */
51346		this.filter = null;
51347
51348		/**
51349		 * Time delta values required for `linearRampToValueAtTime()` usage.
51350		 *
51351		 * @type {number}
51352		 * @default 0
51353		 * @readonly
51354		 */
51355		this.timeDelta = 0;
51356
51357		// private
51358
51359		this._timer = new Timer();
51360
51361	}
51362
51363	/**
51364	 * Returns the listener's input node.
51365	 *
51366	 * This method is used by other audio nodes to connect to this listener.
51367	 *
51368	 * @return {GainNode} The input node.
51369	 */
51370	getInput() {
51371
51372		return this.gain;
51373
51374	}
51375
51376	/**
51377	 * Removes the current filter from this listener.
51378	 *
51379	 * @return {AudioListener} A reference to this listener.
51380	 */
51381	removeFilter() {
51382
51383		if ( this.filter !== null ) {
51384
51385			this.gain.disconnect( this.filter );
51386			this.filter.disconnect( this.context.destination );
51387			this.gain.connect( this.context.destination );
51388			this.filter = null;
51389
51390		}
51391
51392		return this;
51393
51394	}
51395
51396	/**
51397	 * Returns the current set filter.
51398	 *
51399	 * @return {?AudioNode} The filter.
51400	 */
51401	getFilter() {
51402
51403		return this.filter;
51404
51405	}
51406
51407	/**
51408	 * Sets the given filter to this listener.
51409	 *
51410	 * @param {AudioNode} value - The filter to set.
51411	 * @return {AudioListener} A reference to this listener.
51412	 */
51413	setFilter( value ) {
51414
51415		if ( this.filter !== null ) {
51416
51417			this.gain.disconnect( this.filter );
51418			this.filter.disconnect( this.context.destination );
51419
51420		} else {
51421
51422			this.gain.disconnect( this.context.destination );
51423
51424		}
51425
51426		this.filter = value;
51427		this.gain.connect( this.filter );
51428		this.filter.connect( this.context.destination );
51429
51430		return this;
51431
51432	}
51433
51434	/**
51435	 * Returns the applications master volume.
51436	 *
51437	 * @return {number} The master volume.
51438	 */
51439	getMasterVolume() {
51440
51441		return this.gain.gain.value;
51442
51443	}
51444
51445	/**
51446	 * Sets the applications master volume. This volume setting affects
51447	 * all audio nodes in the scene.
51448	 *
51449	 * @param {number} value - The master volume to set.
51450	 * @return {AudioListener} A reference to this listener.
51451	 */
51452	setMasterVolume( value ) {
51453
51454		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
51455
51456		return this;
51457
51458	}
51459
51460	updateMatrixWorld( force ) {
51461
51462		super.updateMatrixWorld( force );
51463
51464		this._timer.update();
51465
51466		const listener = this.context.listener;
51467
51468		this.timeDelta = this._timer.getDelta();
51469
51470		this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 );
51471
51472		// the initial forward and up directions must be orthogonal
51473		_forward.set( 0, 0, -1 ).applyQuaternion( _quaternion$1 );
51474		_up.set( 0, 1, 0 ).applyQuaternion( _quaternion$1 );
51475
51476		if ( listener.positionX ) {
51477
51478			// code path for Chrome (see #14393)
51479
51480			const endTime = this.context.currentTime + this.timeDelta;
51481
51482			listener.positionX.linearRampToValueAtTime( _position$1.x, endTime );
51483			listener.positionY.linearRampToValueAtTime( _position$1.y, endTime );
51484			listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime );
51485			listener.forwardX.linearRampToValueAtTime( _forward.x, endTime );
51486			listener.forwardY.linearRampToValueAtTime( _forward.y, endTime );
51487			listener.forwardZ.linearRampToValueAtTime( _forward.z, endTime );
51488			listener.upX.linearRampToValueAtTime( _up.x, endTime );
51489			listener.upY.linearRampToValueAtTime( _up.y, endTime );
51490			listener.upZ.linearRampToValueAtTime( _up.z, endTime );
51491
51492		} else {
51493
51494			listener.setPosition( _position$1.x, _position$1.y, _position$1.z );
51495			listener.setOrientation( _forward.x, _forward.y, _forward.z, _up.x, _up.y, _up.z );
51496
51497		}
51498
51499	}
51500
51501}
51502
51503/**
51504 * Represents a non-positional ( global ) audio object.
51505 *
51506 * This and related audio modules make use of the [Web Audio API](https://www.w3.org/TR/webaudio-1.1/).
51507 *
51508 * ```js
51509 * // create an AudioListener and add it to the camera
51510 * const listener = new THREE.AudioListener();
51511 * camera.add( listener );
51512 *
51513 * // create a global audio source
51514 * const sound = new THREE.Audio( listener );
51515 *
51516 * // load a sound and set it as the Audio object's buffer
51517 * const audioLoader = new THREE.AudioLoader();
51518 * audioLoader.load( 'sounds/ambient.ogg', function( buffer ) {
51519 * 	sound.setBuffer( buffer );
51520 * 	sound.setLoop( true );
51521 * 	sound.setVolume( 0.5 );
51522 * 	sound.play();
51523 * });
51524 * ```
51525 *
51526 * @augments Object3D
51527 */
51528class Audio extends Object3D {
51529
51530	/**
51531	 * Constructs a new audio.
51532	 *
51533	 * @param {AudioListener} listener - The global audio listener.
51534	 */
51535	constructor( listener ) {
51536
51537		super();
51538
51539		this.type = 'Audio';
51540
51541		/**
51542		 * The global audio listener.
51543		 *
51544		 * @type {AudioListener}
51545		 * @readonly
51546		 */
51547		this.listener = listener;
51548
51549		/**
51550		 * The audio context.
51551		 *
51552		 * @type {AudioContext}
51553		 * @readonly
51554		 */
51555		this.context = listener.context;
51556
51557		/**
51558		 * The gain node used for volume control.
51559		 *
51560		 * @type {GainNode}
51561		 * @readonly
51562		 */
51563		this.gain = this.context.createGain();
51564		this.gain.connect( listener.getInput() );
51565
51566		/**
51567		 * Whether to start playback automatically or not.
51568		 *
51569		 * @type {boolean}
51570		 * @default false
51571		 */
51572		this.autoplay = false;
51573
51574		/**
51575		 * A reference to an audio buffer.
51576		 *
51577		 * Defined via {@link Audio#setBuffer}.
51578		 *
51579		 * @type {?AudioBuffer}
51580		 * @default null
51581		 * @readonly
51582		 */
51583		this.buffer = null;
51584
51585		/**
51586		 * Modify pitch, measured in cents. +/- 100 is a semitone.
51587		 * +/- 1200 is an octave.
51588		 *
51589		 * Defined via {@link Audio#setDetune}.
51590		 *
51591		 * @type {number}
51592		 * @default 0
51593		 * @readonly
51594		 */
51595		this.detune = 0;
51596
51597		/**
51598		 * Whether the audio should loop or not.
51599		 *
51600		 * Defined via {@link Audio#setLoop}.
51601		 *
51602		 * @type {boolean}
51603		 * @default false
51604		 * @readonly
51605		 */
51606		this.loop = false;
51607
51608		/**
51609		 * Defines where in the audio buffer the replay should
51610		 * start, in seconds.
51611		 *
51612		 * @type {number}
51613		 * @default 0
51614		 */
51615		this.loopStart = 0;
51616
51617		/**
51618		 * Defines where in the audio buffer the replay should
51619		 * stop, in seconds.
51620		 *
51621		 * @type {number}
51622		 * @default 0
51623		 */
51624		this.loopEnd = 0;
51625
51626		/**
51627		 * An offset to the time within the audio buffer the playback
51628		 * should begin, in seconds.
51629		 *
51630		 * @type {number}
51631		 * @default 0
51632		 */
51633		this.offset = 0;
51634
51635		/**
51636		 * Overrides the default duration of the audio.
51637		 *
51638		 * @type {undefined|number}
51639		 * @default undefined
51640		 */
51641		this.duration = undefined;
51642
51643		/**
51644		 * The playback speed.
51645		 *
51646		 * Defined via {@link Audio#setPlaybackRate}.
51647		 *
51648		 * @type {number}
51649		 * @readonly
51650		 * @default 1
51651		 */
51652		this.playbackRate = 1;
51653
51654		/**
51655		 * Indicates whether the audio is playing or not.
51656		 *
51657		 * This flag will be automatically set when using {@link Audio#play},
51658		 * {@link Audio#pause}, {@link Audio#stop}.
51659		 *
51660		 * @type {boolean}
51661		 * @readonly
51662		 * @default false
51663		 */
51664		this.isPlaying = false;
51665
51666		/**
51667		 * Indicates whether the audio playback can be controlled
51668		 * with method like {@link Audio#play} or {@link Audio#pause}.
51669		 *
51670		 * This flag will be automatically set when audio sources are
51671		 * defined.
51672		 *
51673		 * @type {boolean}
51674		 * @readonly
51675		 * @default true
51676		 */
51677		this.hasPlaybackControl = true;
51678
51679		/**
51680		 * Holds a reference to the current audio source.
51681		 *
51682		 * The property is automatically by one of the `set*()` methods.
51683		 *
51684		 * @type {?AudioNode}
51685		 * @readonly
51686		 * @default null
51687		 */
51688		this.source = null;
51689
51690		/**
51691		 * Defines the source type.
51692		 *
51693		 * The property is automatically set by one of the `set*()` methods.
51694		 *
51695		 * @type {('empty'|'audioNode'|'mediaNode'|'mediaStreamNode'|'buffer')}
51696		 * @readonly
51697		 * @default 'empty'
51698		 */
51699		this.sourceType = 'empty';
51700
51701		this._startedAt = 0;
51702		this._progress = 0;
51703		this._connected = false;
51704
51705		/**
51706		 * Can be used to apply a variety of low-order filters to create
51707		 * more complex sound effects e.g. via `BiquadFilterNode`.
51708		 *
51709		 * The property is automatically set by {@link Audio#setFilters}.
51710		 *
51711		 * @type {Array<AudioNode>}
51712		 * @readonly
51713		 */
51714		this.filters = [];
51715
51716	}
51717
51718	/**
51719	 * Returns the output audio node.
51720	 *
51721	 * @return {GainNode} The output node.
51722	 */
51723	getOutput() {
51724
51725		return this.gain;
51726
51727	}
51728
51729	/**
51730	 * Sets the given audio node as the source of this instance.
51731	 *
51732	 * {@link Audio#sourceType} is set to `audioNode` and {@link Audio#hasPlaybackControl} to `false`.
51733	 *
51734	 * @param {AudioNode} audioNode - The audio node like an instance of `OscillatorNode`.
51735	 * @return {Audio} A reference to this instance.
51736	 */
51737	setNodeSource( audioNode ) {
51738
51739		this.hasPlaybackControl = false;
51740		this.sourceType = 'audioNode';
51741		this.source = audioNode;
51742		this.connect();
51743
51744		return this;
51745
51746	}
51747
51748	/**
51749	 * Sets the given media element as the source of this instance.
51750	 *
51751	 * {@link Audio#sourceType} is set to `mediaNode` and {@link Audio#hasPlaybackControl} to `false`.
51752	 *
51753	 * @param {HTMLMediaElement} mediaElement - The media element.
51754	 * @return {Audio} A reference to this instance.
51755	 */
51756	setMediaElementSource( mediaElement ) {
51757
51758		this.hasPlaybackControl = false;
51759		this.sourceType = 'mediaNode';
51760		this.source = this.context.createMediaElementSource( mediaElement );
51761		this.connect();
51762
51763		return this;
51764
51765	}
51766
51767	/**
51768	 * Sets the given media stream as the source of this instance.
51769	 *
51770	 * {@link Audio#sourceType} is set to `mediaStreamNode` and {@link Audio#hasPlaybackControl} to `false`.
51771	 *
51772	 * @param {MediaStream} mediaStream - The media stream.
51773	 * @return {Audio} A reference to this instance.
51774	 */
51775	setMediaStreamSource( mediaStream ) {
51776
51777		this.hasPlaybackControl = false;
51778		this.sourceType = 'mediaStreamNode';
51779		this.source = this.context.createMediaStreamSource( mediaStream );
51780		this.connect();
51781
51782		return this;
51783
51784	}
51785
51786	/**
51787	 * Sets the given audio buffer as the source of this instance.
51788	 *
51789	 * {@link Audio#sourceType} is set to `buffer` and {@link Audio#hasPlaybackControl} to `true`.
51790	 *
51791	 * @param {AudioBuffer} audioBuffer - The audio buffer.
51792	 * @return {Audio} A reference to this instance.
51793	 */
51794	setBuffer( audioBuffer ) {
51795
51796		this.buffer = audioBuffer;
51797		this.sourceType = 'buffer';
51798
51799		if ( this.autoplay ) this.play();
51800
51801		return this;
51802
51803	}
51804
51805	/**
51806	 * Starts the playback of the audio.
51807	 *
51808	 * Can only be used with compatible audio sources that allow playback control.
51809	 *
51810	 * @param {number} [delay=0] - The delay, in seconds, at which the audio should start playing.
51811	 * @return {Audio|undefined} A reference to this instance.
51812	 */
51813	play( delay = 0 ) {
51814
51815		if ( this.isPlaying === true ) {
51816
51817			warn( 'Audio: Audio is already playing.' );
51818			return;
51819
51820		}
51821
51822		if ( this.hasPlaybackControl === false ) {
51823
51824			warn( 'Audio: this Audio has no playback control.' );
51825			return;
51826
51827		}
51828
51829		this._startedAt = this.context.currentTime + delay;
51830
51831		const source = this.context.createBufferSource();
51832		source.buffer = this.buffer;
51833		source.loop = this.loop;
51834		source.loopStart = this.loopStart;
51835		source.loopEnd = this.loopEnd;
51836		source.onended = this.onEnded.bind( this );
51837		source.start( this._startedAt, this._progress + this.offset, this.duration );
51838
51839		this.isPlaying = true;
51840
51841		this.source = source;
51842
51843		this.setDetune( this.detune );
51844		this.setPlaybackRate( this.playbackRate );
51845
51846		return this.connect();
51847
51848	}
51849
51850	/**
51851	 * Pauses the playback of the audio.
51852	 *
51853	 * Can only be used with compatible audio sources that allow playback control.
51854	 *
51855	 * @return {Audio|undefined} A reference to this instance.
51856	 */
51857	pause() {
51858
51859		if ( this.hasPlaybackControl === false ) {
51860
51861			warn( 'Audio: this Audio has no playback control.' );
51862			return;
51863
51864		}
51865
51866		if ( this.isPlaying === true ) {
51867
51868			// update current progress
51869
51870			this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
51871
51872			if ( this.loop === true ) {
51873
51874				// ensure _progress does not exceed duration with looped audios
51875
51876				this._progress = this._progress % ( this.duration || this.buffer.duration );
51877
51878			}
51879
51880			this.source.stop();
51881			this.source.onended = null;
51882
51883			this.isPlaying = false;
51884
51885		}
51886
51887		return this;
51888
51889	}
51890
51891	/**
51892	 * Stops the playback of the audio.
51893	 *
51894	 * Can only be used with compatible audio sources that allow playback control.
51895	 *
51896	 * @param {number} [delay=0] - The delay, in seconds, at which the audio should stop playing.
51897	 * @return {Audio|undefined} A reference to this instance.
51898	 */
51899	stop( delay = 0 ) {
51900
51901		if ( this.hasPlaybackControl === false ) {
51902
51903			warn( 'Audio: this Audio has no playback control.' );
51904			return;
51905
51906		}
51907
51908		this._progress = 0;
51909
51910		if ( this.source !== null ) {
51911
51912			this.source.stop( this.context.currentTime + delay );
51913			this.source.onended = null;
51914
51915		}
51916
51917		this.isPlaying = false;
51918
51919		return this;
51920
51921	}
51922
51923	/**
51924	 * Connects to the audio source. This is used internally on
51925	 * initialisation and when setting / removing filters.
51926	 *
51927	 * @return {Audio} A reference to this instance.
51928	 */
51929	connect() {
51930
51931		if ( this.filters.length > 0 ) {
51932
51933			this.source.connect( this.filters[ 0 ] );
51934
51935			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
51936
51937				this.filters[ i - 1 ].connect( this.filters[ i ] );
51938
51939			}
51940
51941			this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
51942
51943		} else {
51944
51945			this.source.connect( this.getOutput() );
51946
51947		}
51948
51949		this._connected = true;
51950
51951		return this;
51952
51953	}
51954
51955	/**
51956	 * Disconnects to the audio source. This is used internally on
51957	 * initialisation and when setting / removing filters.
51958	 *
51959	 * @return {Audio|undefined} A reference to this instance.
51960	 */
51961	disconnect() {
51962
51963		if ( this._connected === false ) {
51964
51965			return;
51966
51967		}
51968
51969		if ( this.filters.length > 0 ) {
51970
51971			this.source.disconnect( this.filters[ 0 ] );
51972
51973			for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
51974
51975				this.filters[ i - 1 ].disconnect( this.filters[ i ] );
51976
51977			}
51978
51979			this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
51980
51981		} else {
51982
51983			this.source.disconnect( this.getOutput() );
51984
51985		}
51986
51987		this._connected = false;
51988
51989		return this;
51990
51991	}
51992
51993	/**
51994	 * Returns the current set filters.
51995	 *
51996	 * @return {Array<AudioNode>} The list of filters.
51997	 */
51998	getFilters() {
51999
52000		return this.filters;
52001
52002	}
52003
52004	/**
52005	 * Sets an array of filters and connects them with the audio source.
52006	 *
52007	 * @param {Array<AudioNode>} [value] - A list of filters.
52008	 * @return {Audio} A reference to this instance.
52009	 */
52010	setFilters( value ) {
52011
52012		if ( ! value ) value = [];
52013
52014		if ( this._connected === true ) {
52015
52016			this.disconnect();
52017			this.filters = value.slice();
52018			this.connect();
52019
52020		} else {
52021
52022			this.filters = value.slice();
52023
52024		}
52025
52026		return this;
52027
52028	}
52029
52030	/**
52031	 * Defines the detuning of oscillation in cents.
52032	 *
52033	 * @param {number} value - The detuning of oscillation in cents.
52034	 * @return {Audio} A reference to this instance.
52035	 */
52036	setDetune( value ) {
52037
52038		this.detune = value;
52039
52040		if ( this.isPlaying === true && this.source.detune !== undefined ) {
52041
52042			this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
52043
52044		}
52045
52046		return this;
52047
52048	}
52049
52050	/**
52051	 * Returns the detuning of oscillation in cents.
52052	 *
52053	 * @return {number} The detuning of oscillation in cents.
52054	 */
52055	getDetune() {
52056
52057		return this.detune;
52058
52059	}
52060
52061	/**
52062	 * Returns the first filter in the list of filters.
52063	 *
52064	 * @return {AudioNode|undefined} The first filter in the list of filters.
52065	 */
52066	getFilter() {
52067
52068		return this.getFilters()[ 0 ];
52069
52070	}
52071
52072	/**
52073	 * Applies a single filter node to the audio.
52074	 *
52075	 * @param {AudioNode} [filter] - The filter to set.
52076	 * @return {Audio} A reference to this instance.
52077	 */
52078	setFilter( filter ) {
52079
52080		return this.setFilters( filter ? [ filter ] : [] );
52081
52082	}
52083
52084	/**
52085	 * Sets the playback rate.
52086	 *
52087	 * Can only be used with compatible audio sources that allow playback control.
52088	 *
52089	 * @param {number} [value] - The playback rate to set.
52090	 * @return {Audio|undefined} A reference to this instance.
52091	 */
52092	setPlaybackRate( value ) {
52093
52094		if ( this.hasPlaybackControl === false ) {
52095
52096			warn( 'Audio: this Audio has no playback control.' );
52097			return;
52098
52099		}
52100
52101		this.playbackRate = value;
52102
52103		if ( this.isPlaying === true ) {
52104
52105			this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
52106
52107		}
52108
52109		return this;
52110
52111	}
52112
52113	/**
52114	 * Returns the current playback rate.
52115
52116	 * @return {number} The playback rate.
52117	 */
52118	getPlaybackRate() {
52119
52120		return this.playbackRate;
52121
52122	}
52123
52124	/**
52125	 * Automatically called when playback finished.
52126	 */
52127	onEnded() {
52128
52129		this.isPlaying = false;
52130		this._progress = 0;
52131
52132	}
52133
52134	/**
52135	 * Returns the loop flag.
52136	 *
52137	 * Can only be used with compatible audio sources that allow playback control.
52138	 *
52139	 * @return {boolean} Whether the audio should loop or not.
52140	 */
52141	getLoop() {
52142
52143		if ( this.hasPlaybackControl === false ) {
52144
52145			warn( 'Audio: this Audio has no playback control.' );
52146			return false;
52147
52148		}
52149
52150		return this.loop;
52151
52152	}
52153
52154	/**
52155	 * Sets the loop flag.
52156	 *
52157	 * Can only be used with compatible audio sources that allow playback control.
52158	 *
52159	 * @param {boolean} value - Whether the audio should loop or not.
52160	 * @return {Audio|undefined} A reference to this instance.
52161	 */
52162	setLoop( value ) {
52163
52164		if ( this.hasPlaybackControl === false ) {
52165
52166			warn( 'Audio: this Audio has no playback control.' );
52167			return;
52168
52169		}
52170
52171		this.loop = value;
52172
52173		if ( this.isPlaying === true ) {
52174
52175			this.source.loop = this.loop;
52176
52177		}
52178
52179		return this;
52180
52181	}
52182
52183	/**
52184	 * Sets the loop start value which defines where in the audio buffer the replay should
52185	 * start, in seconds.
52186	 *
52187	 * @param {number} value - The loop start value.
52188	 * @return {Audio} A reference to this instance.
52189	 */
52190	setLoopStart( value ) {
52191
52192		this.loopStart = value;
52193
52194		return this;
52195
52196	}
52197
52198	/**
52199	 * Sets the loop end value which defines where in the audio buffer the replay should
52200	 * stop, in seconds.
52201	 *
52202	 * @param {number} value - The loop end value.
52203	 * @return {Audio} A reference to this instance.
52204	 */
52205	setLoopEnd( value ) {
52206
52207		this.loopEnd = value;
52208
52209		return this;
52210
52211	}
52212
52213	/**
52214	 * Returns the volume.
52215	 *
52216	 * @return {number} The volume.
52217	 */
52218	getVolume() {
52219
52220		return this.gain.gain.value;
52221
52222	}
52223
52224	/**
52225	 * Sets the volume.
52226	 *
52227	 * @param {number} value - The volume to set.
52228	 * @return {Audio} A reference to this instance.
52229	 */
52230	setVolume( value ) {
52231
52232		this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
52233
52234		return this;
52235
52236	}
52237
52238	copy( source, recursive ) {
52239
52240		super.copy( source, recursive );
52241
52242		if ( source.sourceType !== 'buffer' ) {
52243
52244			warn( 'Audio: Audio source type cannot be copied.' );
52245
52246			return this;
52247
52248		}
52249
52250		this.autoplay = source.autoplay;
52251
52252		this.buffer = source.buffer;
52253		this.detune = source.detune;
52254		this.loop = source.loop;
52255		this.loopStart = source.loopStart;
52256		this.loopEnd = source.loopEnd;
52257		this.offset = source.offset;
52258		this.duration = source.duration;
52259		this.playbackRate = source.playbackRate;
52260		this.hasPlaybackControl = source.hasPlaybackControl;
52261		this.sourceType = source.sourceType;
52262
52263		this.filters = source.filters.slice();
52264
52265		return this;
52266
52267	}
52268
52269	clone( recursive ) {
52270
52271		return new this.constructor( this.listener ).copy( this, recursive );
52272
52273	}
52274
52275}
52276
52277const _position = /*@__PURE__*/ new Vector3();
52278const _quaternion = /*@__PURE__*/ new Quaternion();
52279const _scale = /*@__PURE__*/ new Vector3();
52280const _orientation = /*@__PURE__*/ new Vector3();
52281
52282/**
52283 * Represents a positional audio object.
52284 *
52285 * ```js
52286 * // create an AudioListener and add it to the camera
52287 * const listener = new THREE.AudioListener();
52288 * camera.add( listener );
52289 *
52290 * // create the PositionalAudio object (passing in the listener)
52291 * const sound = new THREE.PositionalAudio( listener );
52292 *
52293 * // load a sound and set it as the PositionalAudio object's buffer
52294 * const audioLoader = new THREE.AudioLoader();
52295 * audioLoader.load( 'sounds/song.ogg', function( buffer ) {
52296 * 	sound.setBuffer( buffer );
52297 * 	sound.setRefDistance( 20 );
52298 * 	sound.play();
52299 * });
52300 *
52301 * // create an object for the sound to play from
52302 * const sphere = new THREE.SphereGeometry( 20, 32, 16 );
52303 * const material = new THREE.MeshPhongMaterial( { color: 0xff2200 } );
52304 * const mesh = new THREE.Mesh( sphere, material );
52305 * scene.add( mesh );
52306 *
52307 * // finally add the sound to the mesh
52308 * mesh.add( sound );
52309 *
52310 * @augments Audio
52311 */
52312class PositionalAudio extends Audio {
52313
52314	/**
52315	 * Constructs a positional audio.
52316	 *
52317	 * @param {AudioListener} listener - The global audio listener.
52318	 */
52319	constructor( listener ) {
52320
52321		super( listener );
52322
52323		/**
52324		 * The panner node represents the location, direction, and behavior of an audio
52325		 * source in 3D space.
52326		 *
52327		 * @type {PannerNode}
52328		 * @readonly
52329		 */
52330		this.panner = this.context.createPanner();
52331		this.panner.panningModel = 'HRTF';
52332		this.panner.connect( this.gain );
52333
52334	}
52335
52336	connect() {
52337
52338		super.connect();
52339
52340		this.panner.connect( this.gain );
52341
52342		return this;
52343
52344	}
52345
52346	disconnect() {
52347
52348		super.disconnect();
52349
52350		this.panner.disconnect( this.gain );
52351
52352		return this;
52353
52354	}
52355
52356	getOutput() {
52357
52358		return this.panner;
52359
52360	}
52361
52362	/**
52363	 * Returns the current reference distance.
52364	 *
52365	 * @return {number} The reference distance.
52366	 */
52367	getRefDistance() {
52368
52369		return this.panner.refDistance;
52370
52371	}
52372
52373	/**
52374	 * Defines the reference distance for reducing volume as the audio source moves
52375	 * further from the listener – i.e. the distance at which the volume reduction
52376	 * starts taking effect.
52377	 *
52378	 * @param {number} value - The reference distance to set.
52379	 * @return {PositionalAudio} A reference to this instance.
52380	 */
52381	setRefDistance( value ) {
52382
52383		this.panner.refDistance = value;
52384
52385		return this;
52386
52387	}
52388
52389	/**
52390	 * Returns the current rolloff factor.
52391	 *
52392	 * @return {number} The rolloff factor.
52393	 */
52394	getRolloffFactor() {
52395
52396		return this.panner.rolloffFactor;
52397
52398	}
52399
52400	/**
52401	 * Defines how quickly the volume is reduced as the source moves away from the listener.
52402	 *
52403	 * @param {number} value - The rolloff factor.
52404	 * @return {PositionalAudio} A reference to this instance.
52405	 */
52406	setRolloffFactor( value ) {
52407
52408		this.panner.rolloffFactor = value;
52409
52410		return this;
52411
52412	}
52413
52414	/**
52415	 * Returns the current distance model.
52416	 *
52417	 * @return {('linear'|'inverse'|'exponential')} The distance model.
52418	 */
52419	getDistanceModel() {
52420
52421		return this.panner.distanceModel;
52422
52423	}
52424
52425	/**
52426	 * Defines which algorithm to use to reduce the volume of the audio source
52427	 * as it moves away from the listener.
52428	 *
52429	 * Read [the spec](https://www.w3.org/TR/webaudio-1.1/#enumdef-distancemodeltype)
52430	 * for more details.
52431	 *
52432	 * @param {('linear'|'inverse'|'exponential')} value - The distance model to set.
52433	 * @return {PositionalAudio} A reference to this instance.
52434	 */
52435	setDistanceModel( value ) {
52436
52437		this.panner.distanceModel = value;
52438
52439		return this;
52440
52441	}
52442
52443	/**
52444	 * Returns the current max distance.
52445	 *
52446	 * @return {number} The max distance.
52447	 */
52448	getMaxDistance() {
52449
52450		return this.panner.maxDistance;
52451
52452	}
52453
52454	/**
52455	 * Defines the maximum distance between the audio source and the listener,
52456	 * after which the volume is not reduced any further.
52457	 *
52458	 * This value is used only by the `linear` distance model.
52459	 *
52460	 * @param {number} value - The max distance.
52461	 * @return {PositionalAudio} A reference to this instance.
52462	 */
52463	setMaxDistance( value ) {
52464
52465		this.panner.maxDistance = value;
52466
52467		return this;
52468
52469	}
52470
52471	/**
52472	 * Sets the directional cone in which the audio can be listened.
52473	 *
52474	 * @param {number} coneInnerAngle - An angle, in degrees, of a cone inside of which there will be no volume reduction.
52475	 * @param {number} coneOuterAngle - An angle, in degrees, of a cone outside of which the volume will be reduced by a constant value, defined by the `coneOuterGain` parameter.
52476	 * @param {number} coneOuterGain - The amount of volume reduction outside the cone defined by the `coneOuterAngle`. When set to `0`, no sound can be heard.
52477	 * @return {PositionalAudio} A reference to this instance.
52478	 */
52479	setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
52480
52481		this.panner.coneInnerAngle = coneInnerAngle;
52482		this.panner.coneOuterAngle = coneOuterAngle;
52483		this.panner.coneOuterGain = coneOuterGain;
52484
52485		return this;
52486
52487	}
52488
52489	updateMatrixWorld( force ) {
52490
52491		super.updateMatrixWorld( force );
52492
52493		if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
52494
52495		this.matrixWorld.decompose( _position, _quaternion, _scale );
52496
52497		_orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
52498
52499		const panner = this.panner;
52500
52501		if ( panner.positionX ) {
52502
52503			// code path for Chrome and Firefox (see #14393)
52504
52505			const endTime = this.context.currentTime + this.listener.timeDelta;
52506
52507			panner.positionX.linearRampToValueAtTime( _position.x, endTime );
52508			panner.positionY.linearRampToValueAtTime( _position.y, endTime );
52509			panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
52510			panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
52511			panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
52512			panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
52513
52514		} else {
52515
52516			panner.setPosition( _position.x, _position.y, _position.z );
52517			panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
52518
52519		}
52520
52521	}
52522
52523}
52524
52525/**
52526 * This class can be used to analyse audio data.
52527 *
52528 * ```js
52529 * // create an AudioListener and add it to the camera
52530 * const listener = new THREE.AudioListener();
52531 * camera.add( listener );
52532 *
52533 * // create an Audio source
52534 * const sound = new THREE.Audio( listener );
52535 *
52536 * // load a sound and set it as the Audio object's buffer
52537 * const audioLoader = new THREE.AudioLoader();
52538 * audioLoader.load( 'sounds/ambient.ogg', function( buffer ) {
52539 * 	sound.setBuffer( buffer );
52540 * 	sound.setLoop(true);
52541 * 	sound.setVolume(0.5);
52542 * 	sound.play();
52543 * });
52544 *
52545 * // create an AudioAnalyser, passing in the sound and desired fftSize
52546 * const analyser = new THREE.AudioAnalyser( sound, 32 );
52547 *
52548 * // get the average frequency of the sound
52549 * const data = analyser.getAverageFrequency();
52550 * ```
52551 */
52552class AudioAnalyser {
52553
52554	/**
52555	 * Constructs a new audio analyzer.
52556	 *
52557	 * @param {Audio} audio - The audio to analyze.
52558	 * @param {number} [fftSize=2048] - The window size in samples that is used when performing a Fast Fourier Transform (FFT) to get frequency domain data.
52559	 */
52560	constructor( audio, fftSize = 2048 ) {
52561
52562		/**
52563		 * The global audio listener.
52564		 *
52565		 * @type {AnalyserNode}
52566		 */
52567		this.analyser = audio.context.createAnalyser();
52568		this.analyser.fftSize = fftSize;
52569
52570		/**
52571		 * Holds the analyzed data.
52572		 *
52573		 * @type {Uint8Array}
52574		 */
52575		this.data = new Uint8Array( this.analyser.frequencyBinCount );
52576
52577		audio.getOutput().connect( this.analyser );
52578
52579	}
52580
52581	/**
52582	 * Returns an array with frequency data of the audio.
52583	 *
52584	 * Each item in the array represents the decibel value for a specific frequency.
52585	 * The frequencies are spread linearly from 0 to 1/2 of the sample rate.
52586	 * For example, for 48000 sample rate, the last item of the array will represent
52587	 * the decibel value for 24000 Hz.
52588	 *
52589	 * @return {Uint8Array} The frequency data.
52590	 */
52591	getFrequencyData() {
52592
52593		this.analyser.getByteFrequencyData( this.data );
52594
52595		return this.data;
52596
52597	}
52598
52599	/**
52600	 * Returns the average of the frequencies returned by {@link AudioAnalyser#getFrequencyData}.
52601	 *
52602	 * @return {number} The average frequency.
52603	 */
52604	getAverageFrequency() {
52605
52606		let value = 0;
52607		const data = this.getFrequencyData();
52608
52609		for ( let i = 0; i < data.length; i ++ ) {
52610
52611			value += data[ i ];
52612
52613		}
52614
52615		return value / data.length;
52616
52617	}
52618
52619}
52620
52621/**
52622 * Buffered scene graph property that allows weighted accumulation; used internally.
52623 */
52624class PropertyMixer {
52625
52626	/**
52627	 * Constructs a new property mixer.
52628	 *
52629	 * @param {PropertyBinding} binding - The property binding.
52630	 * @param {string} typeName - The keyframe track type name.
52631	 * @param {number} valueSize - The keyframe track value size.
52632	 */
52633	constructor( binding, typeName, valueSize ) {
52634
52635		/**
52636		 * The property binding.
52637		 *
52638		 * @type {PropertyBinding}
52639		 */
52640		this.binding = binding;
52641
52642		/**
52643		 * The keyframe track value size.
52644		 *
52645		 * @type {number}
52646		 */
52647		this.valueSize = valueSize;
52648
52649		let mixFunction,
52650			mixFunctionAdditive,
52651			setIdentity;
52652
52653		// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
52654		//
52655		// interpolators can use .buffer as their .result
52656		// the data then goes to 'incoming'
52657		//
52658		// 'accu0' and 'accu1' are used frame-interleaved for
52659		// the cumulative result and are compared to detect
52660		// changes
52661		//
52662		// 'orig' stores the original state of the property
52663		//
52664		// 'add' is used for additive cumulative results
52665		//
52666		// 'work' is optional and is only present for quaternion types. It is used
52667		// to store intermediate quaternion multiplication results
52668
52669		switch ( typeName ) {
52670
52671			case 'quaternion':
52672				mixFunction = this._slerp;
52673				mixFunctionAdditive = this._slerpAdditive;
52674				setIdentity = this._setAdditiveIdentityQuaternion;
52675
52676				this.buffer = new Float64Array( valueSize * 6 );
52677				this._workIndex = 5;
52678				break;
52679
52680			case 'string':
52681			case 'bool':
52682				mixFunction = this._select;
52683
52684				// Use the regular mix function and for additive on these types,
52685				// additive is not relevant for non-numeric types
52686				mixFunctionAdditive = this._select;
52687
52688				setIdentity = this._setAdditiveIdentityOther;
52689
52690				this.buffer = new Array( valueSize * 5 );
52691				break;
52692
52693			default:
52694				mixFunction = this._lerp;
52695				mixFunctionAdditive = this._lerpAdditive;
52696				setIdentity = this._setAdditiveIdentityNumeric;
52697
52698				this.buffer = new Float64Array( valueSize * 5 );
52699
52700		}
52701
52702		this._mixBufferRegion = mixFunction;
52703		this._mixBufferRegionAdditive = mixFunctionAdditive;
52704		this._setIdentity = setIdentity;
52705		this._origIndex = 3;
52706		this._addIndex = 4;
52707
52708		/**
52709		 * Accumulated weight of the property binding.
52710		 *
52711		 * @type {number}
52712		 * @default 0
52713		 */
52714		this.cumulativeWeight = 0;
52715
52716		/**
52717		 * Accumulated additive weight of the property binding.
52718		 *
52719		 * @type {number}
52720		 * @default 0
52721		 */
52722		this.cumulativeWeightAdditive = 0;
52723
52724		/**
52725		 * Number of active keyframe tracks currently using this property binding.
52726		 *
52727		 * @type {number}
52728		 * @default 0
52729		 */
52730		this.useCount = 0;
52731
52732		/**
52733		 * Number of keyframe tracks referencing this property binding.
52734		 *
52735		 * @type {number}
52736		 * @default 0
52737		 */
52738		this.referenceCount = 0;
52739
52740	}
52741
52742	/**
52743	 * Accumulates data in the `incoming` region into `accu<i>`.
52744	 *
52745	 * @param {number} accuIndex - The accumulation index.
52746	 * @param {number} weight - The weight.
52747	 */
52748	accumulate( accuIndex, weight ) {
52749
52750		// note: happily accumulating nothing when weight = 0, the caller knows
52751		// the weight and shouldn't have made the call in the first place
52752
52753		const buffer = this.buffer,
52754			stride = this.valueSize,
52755			offset = accuIndex * stride + stride;
52756
52757		let currentWeight = this.cumulativeWeight;
52758
52759		if ( currentWeight === 0 ) {
52760
52761			// accuN := incoming * weight
52762
52763			for ( let i = 0; i !== stride; ++ i ) {
52764
52765				buffer[ offset + i ] = buffer[ i ];
52766
52767			}
52768
52769			currentWeight = weight;
52770
52771		} else {
52772
52773			// accuN := accuN + incoming * weight
52774
52775			currentWeight += weight;
52776			const mix = weight / currentWeight;
52777			this._mixBufferRegion( buffer, offset, 0, mix, stride );
52778
52779		}
52780
52781		this.cumulativeWeight = currentWeight;
52782
52783	}
52784
52785	/**
52786	 * Accumulates data in the `incoming` region into `add`.
52787	 *
52788	 * @param {number} weight - The weight.
52789	 */
52790	accumulateAdditive( weight ) {
52791
52792		const buffer = this.buffer,
52793			stride = this.valueSize,
52794			offset = stride * this._addIndex;
52795
52796		if ( this.cumulativeWeightAdditive === 0 ) {
52797
52798			// add = identity
52799
52800			this._setIdentity();
52801
52802		}
52803
52804		// add := add + incoming * weight
52805
52806		this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
52807		this.cumulativeWeightAdditive += weight;
52808
52809	}
52810
52811	/**
52812	 * Applies the state of `accu<i>` to the binding when accus differ.
52813	 *
52814	 * @param {number} accuIndex - The accumulation index.
52815	 */
52816	apply( accuIndex ) {
52817
52818		const stride = this.valueSize,
52819			buffer = this.buffer,
52820			offset = accuIndex * stride + stride,
52821
52822			weight = this.cumulativeWeight,
52823			weightAdditive = this.cumulativeWeightAdditive,
52824
52825			binding = this.binding;
52826
52827		this.cumulativeWeight = 0;
52828		this.cumulativeWeightAdditive = 0;
52829
52830		if ( weight < 1 ) {
52831
52832			// accuN := accuN + original * ( 1 - cumulativeWeight )
52833
52834			const originalValueOffset = stride * this._origIndex;
52835
52836			this._mixBufferRegion(
52837				buffer, offset, originalValueOffset, 1 - weight, stride );
52838
52839		}
52840
52841		if ( weightAdditive > 0 ) {
52842
52843			// accuN := accuN + additive accuN
52844
52845			this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
52846
52847		}
52848
52849		for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
52850
52851			if ( buffer[ i ] !== buffer[ i + stride ] ) {
52852
52853				// value has changed -> update scene graph
52854
52855				binding.setValue( buffer, offset );
52856				break;
52857
52858			}
52859
52860		}
52861
52862	}
52863
52864
52865	/**
52866	 * Remembers the state of the bound property and copy it to both accus.
52867	 */
52868	saveOriginalState() {
52869
52870		const binding = this.binding;
52871
52872		const buffer = this.buffer,
52873			stride = this.valueSize,
52874
52875			originalValueOffset = stride * this._origIndex;
52876
52877		binding.getValue( buffer, originalValueOffset );
52878
52879		// accu[0..1] := orig -- initially detect changes against the original
52880		for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
52881
52882			buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
52883
52884		}
52885
52886		// Add to identity for additive
52887		this._setIdentity();
52888
52889		this.cumulativeWeight = 0;
52890		this.cumulativeWeightAdditive = 0;
52891
52892	}
52893
52894	/**
52895	 * Applies the state previously taken via {@link PropertyMixer#saveOriginalState} to the binding.
52896	 */
52897	restoreOriginalState() {
52898
52899		const originalValueOffset = this.valueSize * 3;
52900		this.binding.setValue( this.buffer, originalValueOffset );
52901
52902	}
52903
52904	// internals
52905
52906	_setAdditiveIdentityNumeric() {
52907
52908		const startIndex = this._addIndex * this.valueSize;
52909		const endIndex = startIndex + this.valueSize;
52910
52911		for ( let i = startIndex; i < endIndex; i ++ ) {
52912
52913			this.buffer[ i ] = 0;
52914
52915		}
52916
52917	}
52918
52919	_setAdditiveIdentityQuaternion() {
52920
52921		this._setAdditiveIdentityNumeric();
52922		this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
52923
52924	}
52925
52926	_setAdditiveIdentityOther() {
52927
52928		const startIndex = this._origIndex * this.valueSize;
52929		const targetIndex = this._addIndex * this.valueSize;
52930
52931		for ( let i = 0; i < this.valueSize; i ++ ) {
52932
52933			this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
52934
52935		}
52936
52937	}
52938
52939
52940	// mix functions
52941
52942	_select( buffer, dstOffset, srcOffset, t, stride ) {
52943
52944		if ( t >= 0.5 ) {
52945
52946			for ( let i = 0; i !== stride; ++ i ) {
52947
52948				buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
52949
52950			}
52951
52952		}
52953
52954	}
52955
52956	_slerp( buffer, dstOffset, srcOffset, t ) {
52957
52958		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
52959
52960	}
52961
52962	_slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
52963
52964		const workOffset = this._workIndex * stride;
52965
52966		// Store result in intermediate buffer offset
52967		Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
52968
52969		// Slerp to the intermediate result
52970		Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
52971
52972	}
52973
52974	_lerp( buffer, dstOffset, srcOffset, t, stride ) {
52975
52976		const s = 1 - t;
52977
52978		for ( let i = 0; i !== stride; ++ i ) {
52979
52980			const j = dstOffset + i;
52981
52982			buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
52983
52984		}
52985
52986	}
52987
52988	_lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
52989
52990		for ( let i = 0; i !== stride; ++ i ) {
52991
52992			const j = dstOffset + i;
52993
52994			buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
52995
52996		}
52997
52998	}
52999
53000}
53001
53002// Characters [].:/ are reserved for track binding syntax.
53003const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
53004const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
53005
53006// Attempts to allow node names from any language. ES5's `\w` regexp matches
53007// only latin characters, and the unicode \p{L} is not yet supported. So
53008// instead, we exclude reserved characters and match everything else.
53009const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
53010const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
53011
53012// Parent directories, delimited by '/' or ':'. Currently unused, but must
53013// be matched to parse the rest of the track name.
53014const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
53015
53016// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
53017const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
53018
53019// Object on target node, and accessor. May not contain reserved
53020// characters. Accessor may contain any character except closing bracket.
53021const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
53022
53023// Property and accessor. May not contain reserved characters. Accessor may
53024// contain any non-bracket characters.
53025const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
53026
53027const _trackRe = new RegExp( ''
53028	+ '^'
53029	+ _directoryRe
53030	+ _nodeRe
53031	+ _objectRe
53032	+ _propertyRe
53033	+ '$'
53034);
53035
53036const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ];
53037
53038class Composite {
53039
53040	constructor( targetGroup, path, optionalParsedPath ) {
53041
53042		const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
53043
53044		this._targetGroup = targetGroup;
53045		this._bindings = targetGroup.subscribe_( path, parsedPath );
53046
53047	}
53048
53049	getValue( array, offset ) {
53050
53051		this.bind(); // bind all binding
53052
53053		const firstValidIndex = this._targetGroup.nCachedObjects_,
53054			binding = this._bindings[ firstValidIndex ];
53055
53056		// and only call .getValue on the first
53057		if ( binding !== undefined ) binding.getValue( array, offset );
53058
53059	}
53060
53061	setValue( array, offset ) {
53062
53063		const bindings = this._bindings;
53064
53065		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
53066
53067			bindings[ i ].setValue( array, offset );
53068
53069		}
53070
53071	}
53072
53073	bind() {
53074
53075		const bindings = this._bindings;
53076
53077		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
53078
53079			bindings[ i ].bind();
53080
53081		}
53082
53083	}
53084
53085	unbind() {
53086
53087		const bindings = this._bindings;
53088
53089		for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
53090
53091			bindings[ i ].unbind();
53092
53093		}
53094
53095	}
53096
53097}
53098
53099// Note: This class uses a State pattern on a per-method basis:
53100// 'bind' sets 'this.getValue' / 'setValue' and shadows the
53101// prototype version of these methods with one that represents
53102// the bound state. When the property is not found, the methods
53103// become no-ops.
53104
53105
53106/**
53107 * This holds a reference to a real property in the scene graph; used internally.
53108 */
53109class PropertyBinding {
53110
53111	/**
53112	 * Constructs a new property binding.
53113	 *
53114	 * @param {Object} rootNode - The root node.
53115	 * @param {string} path - The path.
53116	 * @param {?Object} [parsedPath] - The parsed path.
53117	 */
53118	constructor( rootNode, path, parsedPath ) {
53119
53120		/**
53121		 * The object path to the animated property.
53122		 *
53123		 * @type {string}
53124		 */
53125		this.path = path;
53126
53127		/**
53128		 * An object holding information about the path.
53129		 *
53130		 * @type {Object}
53131		 */
53132		this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
53133
53134		/**
53135		 * The object owns the animated property.
53136		 *
53137		 * @type {?Object}
53138		 */
53139		this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
53140
53141		/**
53142		 * The root node.
53143		 *
53144		 * @type {Object3D|Skeleton}
53145		 */
53146		this.rootNode = rootNode;
53147
53148		// initial state of these methods that calls 'bind'
53149		this.getValue = this._getValue_unbound;
53150		this.setValue = this._setValue_unbound;
53151
53152	}
53153
53154
53155	/**
53156	 * Factory method for creating a property binding from the given parameters.
53157	 *
53158	 * @static
53159	 * @param {Object} root - The root node.
53160	 * @param {string} path - The path.
53161	 * @param {?Object} [parsedPath] - The parsed path.
53162	 * @return {PropertyBinding|Composite} The created property binding or composite.
53163	 */
53164	static create( root, path, parsedPath ) {
53165
53166		if ( ! ( root && root.isAnimationObjectGroup ) ) {
53167
53168			return new PropertyBinding( root, path, parsedPath );
53169
53170		} else {
53171
53172			return new PropertyBinding.Composite( root, path, parsedPath );
53173
53174		}
53175
53176	}
53177
53178	/**
53179	 * Replaces spaces with underscores and removes unsupported characters from
53180	 * node names, to ensure compatibility with parseTrackName().
53181	 *
53182	 * @param {string} name - Node name to be sanitized.
53183	 * @return {string} The sanitized node name.
53184	 */
53185	static sanitizeNodeName( name ) {
53186
53187		return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
53188
53189	}
53190
53191	/**
53192	 * Parses the given track name (an object path to an animated property) and
53193	 * returns an object with information about the path. Matches strings in the following forms:
53194	 *
53195	 * - nodeName.property
53196	 * - nodeName.property[accessor]
53197	 * - nodeName.material.property[accessor]
53198	 * - uuid.property[accessor]
53199	 * - uuid.objectName[objectIndex].propertyName[propertyIndex]
53200	 * - parentName/nodeName.property
53201	 * - parentName/parentName/nodeName.property[index]
53202	 * - .bone[Armature.DEF_cog].position
53203	 * - scene:helium_balloon_model:helium_balloon_model.position
53204	 *
53205	 * @static
53206	 * @param {string} trackName - The track name to parse.
53207	 * @return {Object} The parsed track name as an object.
53208	 */
53209	static parseTrackName( trackName ) {
53210
53211		const matches = _trackRe.exec( trackName );
53212
53213		if ( matches === null ) {
53214
53215			throw new Error( 'THREE.PropertyBinding: Cannot parse trackName: ' + trackName );
53216
53217		}
53218
53219		const results = {
53220			// directoryName: matches[ 1 ], // (tschw) currently unused
53221			nodeName: matches[ 2 ],
53222			objectName: matches[ 3 ],
53223			objectIndex: matches[ 4 ],
53224			propertyName: matches[ 5 ], // required
53225			propertyIndex: matches[ 6 ]
53226		};
53227
53228		const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
53229
53230		if ( lastDot !== undefined && lastDot !== -1 ) {
53231
53232			const objectName = results.nodeName.substring( lastDot + 1 );
53233
53234			// Object names must be checked against an allowlist. Otherwise, there
53235			// is no way to parse 'foo.bar.baz': 'baz' must be a property, but
53236			// 'bar' could be the objectName, or part of a nodeName (which can
53237			// include '.' characters).
53238			if ( _supportedObjectNames.indexOf( objectName ) !== -1 ) {
53239
53240				results.nodeName = results.nodeName.substring( 0, lastDot );
53241				results.objectName = objectName;
53242
53243			}
53244
53245		}
53246
53247		if ( results.propertyName === null || results.propertyName.length === 0 ) {
53248
53249			throw new Error( 'THREE.PropertyBinding: can not parse propertyName from trackName: ' + trackName );
53250
53251		}
53252
53253		return results;
53254
53255	}
53256
53257	/**
53258	 * Searches for a node in the hierarchy of the given root object by the given
53259	 * node name.
53260	 *
53261	 * @static
53262	 * @param {Object} root - The root object.
53263	 * @param {string|number} nodeName - The name of the node.
53264	 * @return {?Object} The found node. Returns `null` if no object was found.
53265	 */
53266	static findNode( root, nodeName ) {
53267
53268		if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === -1 || nodeName === root.name || nodeName === root.uuid ) {
53269
53270			return root;
53271
53272		}
53273
53274		// search into skeleton bones.
53275		if ( root.skeleton ) {
53276
53277			const bone = root.skeleton.getBoneByName( nodeName );
53278
53279			if ( bone !== undefined ) {
53280
53281				return bone;
53282
53283			}
53284
53285		}
53286
53287		// search into node subtree.
53288		if ( root.children ) {
53289
53290			const searchNodeSubtree = function ( children ) {
53291
53292				for ( let i = 0; i < children.length; i ++ ) {
53293
53294					const childNode = children[ i ];
53295
53296					if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
53297
53298						return childNode;
53299
53300					}
53301
53302					const result = searchNodeSubtree( childNode.children );
53303
53304					if ( result ) return result;
53305
53306				}
53307
53308				return null;
53309
53310			};
53311
53312			const subTreeNode = searchNodeSubtree( root.children );
53313
53314			if ( subTreeNode ) {
53315
53316				return subTreeNode;
53317
53318			}
53319
53320		}
53321
53322		return null;
53323
53324	}
53325
53326	// these are used to "bind" a nonexistent property
53327	_getValue_unavailable() {}
53328	_setValue_unavailable() {}
53329
53330	// Getters
53331
53332	_getValue_direct( buffer, offset ) {
53333
53334		buffer[ offset ] = this.targetObject[ this.propertyName ];
53335
53336	}
53337
53338	_getValue_array( buffer, offset ) {
53339
53340		const source = this.resolvedProperty;
53341
53342		for ( let i = 0, n = source.length; i !== n; ++ i ) {
53343
53344			buffer[ offset ++ ] = source[ i ];
53345
53346		}
53347
53348	}
53349
53350	_getValue_arrayElement( buffer, offset ) {
53351
53352		buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
53353
53354	}
53355
53356	_getValue_toArray( buffer, offset ) {
53357
53358		this.resolvedProperty.toArray( buffer, offset );
53359
53360	}
53361
53362	// Direct
53363
53364	_setValue_direct( buffer, offset ) {
53365
53366		this.targetObject[ this.propertyName ] = buffer[ offset ];
53367
53368	}
53369
53370	_setValue_direct_setNeedsUpdate( buffer, offset ) {
53371
53372		this.targetObject[ this.propertyName ] = buffer[ offset ];
53373		this.targetObject.needsUpdate = true;
53374
53375	}
53376
53377	_setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
53378
53379		this.targetObject[ this.propertyName ] = buffer[ offset ];
53380		this.targetObject.matrixWorldNeedsUpdate = true;
53381
53382	}
53383
53384	// EntireArray
53385
53386	_setValue_array( buffer, offset ) {
53387
53388		const dest = this.resolvedProperty;
53389
53390		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
53391
53392			dest[ i ] = buffer[ offset ++ ];
53393
53394		}
53395
53396	}
53397
53398	_setValue_array_setNeedsUpdate( buffer, offset ) {
53399
53400		const dest = this.resolvedProperty;
53401
53402		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
53403
53404			dest[ i ] = buffer[ offset ++ ];
53405
53406		}
53407
53408		this.targetObject.needsUpdate = true;
53409
53410	}
53411
53412	_setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
53413
53414		const dest = this.resolvedProperty;
53415
53416		for ( let i = 0, n = dest.length; i !== n; ++ i ) {
53417
53418			dest[ i ] = buffer[ offset ++ ];
53419
53420		}
53421
53422		this.targetObject.matrixWorldNeedsUpdate = true;
53423
53424	}
53425
53426	// ArrayElement
53427
53428	_setValue_arrayElement( buffer, offset ) {
53429
53430		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
53431
53432	}
53433
53434	_setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
53435
53436		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
53437		this.targetObject.needsUpdate = true;
53438
53439	}
53440
53441	_setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
53442
53443		this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
53444		this.targetObject.matrixWorldNeedsUpdate = true;
53445
53446	}
53447
53448	// HasToFromArray
53449
53450	_setValue_fromArray( buffer, offset ) {
53451
53452		this.resolvedProperty.fromArray( buffer, offset );
53453
53454	}
53455
53456	_setValue_fromArray_setNeedsUpdate( buffer, offset ) {
53457
53458		this.resolvedProperty.fromArray( buffer, offset );
53459		this.targetObject.needsUpdate = true;
53460
53461	}
53462
53463	_setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
53464
53465		this.resolvedProperty.fromArray( buffer, offset );
53466		this.targetObject.matrixWorldNeedsUpdate = true;
53467
53468	}
53469
53470	_getValue_unbound( targetArray, offset ) {
53471
53472		this.bind();
53473		this.getValue( targetArray, offset );
53474
53475	}
53476
53477	_setValue_unbound( sourceArray, offset ) {
53478
53479		this.bind();
53480		this.setValue( sourceArray, offset );
53481
53482	}
53483
53484	/**
53485	 * Creates a getter / setter pair for the property tracked by this binding.
53486	 */
53487	bind() {
53488
53489		let targetObject = this.node;
53490		const parsedPath = this.parsedPath;
53491
53492		const objectName = parsedPath.objectName;
53493		const propertyName = parsedPath.propertyName;
53494		let propertyIndex = parsedPath.propertyIndex;
53495
53496		if ( ! targetObject ) {
53497
53498			targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName );
53499
53500			this.node = targetObject;
53501
53502		}
53503
53504		// set fail state so we can just 'return' on error
53505		this.getValue = this._getValue_unavailable;
53506		this.setValue = this._setValue_unavailable;
53507
53508		// ensure there is a value node
53509		if ( ! targetObject ) {
53510
53511			warn( 'PropertyBinding: No target node found for track: ' + this.path + '.' );
53512			return;
53513
53514		}
53515
53516		if ( objectName ) {
53517
53518			let objectIndex = parsedPath.objectIndex;
53519
53520			// special cases were we need to reach deeper into the hierarchy to get the face materials....
53521			switch ( objectName ) {
53522
53523				case 'materials':
53524
53525					if ( ! targetObject.material ) {
53526
53527						error( 'PropertyBinding: Can not bind to material as node does not have a material.', this );
53528						return;
53529
53530					}
53531
53532					if ( ! targetObject.material.materials ) {
53533
53534						error( 'PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
53535						return;
53536
53537					}
53538
53539					targetObject = targetObject.material.materials;
53540
53541					break;
53542
53543				case 'bones':
53544
53545					if ( ! targetObject.skeleton ) {
53546
53547						error( 'PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
53548						return;
53549
53550					}
53551
53552					// potential future optimization: skip this if propertyIndex is already an integer
53553					// and convert the integer string to a true integer.
53554
53555					targetObject = targetObject.skeleton.bones;
53556
53557					// support resolving morphTarget names into indices.
53558					for ( let i = 0; i < targetObject.length; i ++ ) {
53559
53560						if ( targetObject[ i ].name === objectIndex ) {
53561
53562							objectIndex = i;
53563							break;
53564
53565						}
53566
53567					}
53568
53569					break;
53570
53571				case 'map':
53572
53573					if ( 'map' in targetObject ) {
53574
53575						targetObject = targetObject.map;
53576						break;
53577
53578					}
53579
53580					if ( ! targetObject.material ) {
53581
53582						error( 'PropertyBinding: Can not bind to material as node does not have a material.', this );
53583						return;
53584
53585					}
53586
53587					if ( ! targetObject.material.map ) {
53588
53589						error( 'PropertyBinding: Can not bind to material.map as node.material does not have a map.', this );
53590						return;
53591
53592					}
53593
53594					targetObject = targetObject.material.map;
53595					break;
53596
53597				default:
53598
53599					if ( targetObject[ objectName ] === undefined ) {
53600
53601						error( 'PropertyBinding: Can not bind to objectName of node undefined.', this );
53602						return;
53603
53604					}
53605
53606					targetObject = targetObject[ objectName ];
53607
53608			}
53609
53610
53611			if ( objectIndex !== undefined ) {
53612
53613				if ( targetObject[ objectIndex ] === undefined ) {
53614
53615					error( 'PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
53616					return;
53617
53618				}
53619
53620				targetObject = targetObject[ objectIndex ];
53621
53622			}
53623
53624		}
53625
53626		// resolve property
53627		const nodeProperty = targetObject[ propertyName ];
53628
53629		if ( nodeProperty === undefined ) {
53630
53631			const nodeName = parsedPath.nodeName;
53632
53633			error( 'PropertyBinding: Trying to update property for track: ' + nodeName +
53634				'.' + propertyName + ' but it wasn\'t found.', targetObject );
53635			return;
53636
53637		}
53638
53639		// determine versioning scheme
53640		let versioning = this.Versioning.None;
53641
53642		this.targetObject = targetObject;
53643
53644		if ( targetObject.isMaterial === true ) {
53645
53646			versioning = this.Versioning.NeedsUpdate;
53647
53648		} else if ( targetObject.isObject3D === true ) {
53649
53650			versioning = this.Versioning.MatrixWorldNeedsUpdate;
53651
53652		}
53653
53654		// determine how the property gets bound
53655		let bindingType = this.BindingType.Direct;
53656
53657		if ( propertyIndex !== undefined ) {
53658
53659			// access a sub element of the property array (only primitives are supported right now)
53660
53661			if ( propertyName === 'morphTargetInfluences' ) {
53662
53663				// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
53664
53665				// support resolving morphTarget names into indices.
53666				if ( ! targetObject.geometry ) {
53667
53668					error( 'PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
53669					return;
53670
53671				}
53672
53673				if ( ! targetObject.geometry.morphAttributes ) {
53674
53675					error( 'PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
53676					return;
53677
53678				}
53679
53680				if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
53681
53682					propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
53683
53684				}
53685
53686			}
53687
53688			bindingType = this.BindingType.ArrayElement;
53689
53690			this.resolvedProperty = nodeProperty;
53691			this.propertyIndex = propertyIndex;
53692
53693		} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
53694
53695			// must use copy for Object3D.Euler/Quaternion
53696
53697			bindingType = this.BindingType.HasFromToArray;
53698
53699			this.resolvedProperty = nodeProperty;
53700
53701		} else if ( Array.isArray( nodeProperty ) ) {
53702
53703			bindingType = this.BindingType.EntireArray;
53704
53705			this.resolvedProperty = nodeProperty;
53706
53707		} else {
53708
53709			this.propertyName = propertyName;
53710
53711		}
53712
53713		// select getter / setter
53714		this.getValue = this.GetterByBindingType[ bindingType ];
53715		this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
53716
53717	}
53718
53719	/**
53720	 * Unbinds the property.
53721	 */
53722	unbind() {
53723
53724		this.node = null;
53725
53726		// back to the prototype version of getValue / setValue
53727		// note: avoiding to mutate the shape of 'this' via 'delete'
53728		this.getValue = this._getValue_unbound;
53729		this.setValue = this._setValue_unbound;
53730
53731	}
53732
53733}
53734
53735PropertyBinding.Composite = Composite;
53736
53737PropertyBinding.prototype.BindingType = {
53738	Direct: 0,
53739	EntireArray: 1,
53740	ArrayElement: 2,
53741	HasFromToArray: 3
53742};
53743
53744PropertyBinding.prototype.Versioning = {
53745	None: 0,
53746	NeedsUpdate: 1,
53747	MatrixWorldNeedsUpdate: 2
53748};
53749
53750PropertyBinding.prototype.GetterByBindingType = [
53751
53752	PropertyBinding.prototype._getValue_direct,
53753	PropertyBinding.prototype._getValue_array,
53754	PropertyBinding.prototype._getValue_arrayElement,
53755	PropertyBinding.prototype._getValue_toArray,
53756
53757];
53758
53759PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
53760
53761	[
53762		// Direct
53763		PropertyBinding.prototype._setValue_direct,
53764		PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
53765		PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
53766
53767	], [
53768
53769		// EntireArray
53770
53771		PropertyBinding.prototype._setValue_array,
53772		PropertyBinding.prototype._setValue_array_setNeedsUpdate,
53773		PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
53774
53775	], [
53776
53777		// ArrayElement
53778		PropertyBinding.prototype._setValue_arrayElement,
53779		PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
53780		PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
53781
53782	], [
53783
53784		// HasToFromArray
53785		PropertyBinding.prototype._setValue_fromArray,
53786		PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
53787		PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
53788
53789	]
53790
53791];
53792
53793/**
53794 * A group of objects that receives a shared animation state.
53795 *
53796 * Usage:
53797 *
53798 * - Add objects you would otherwise pass as 'root' to the
53799 * constructor or the .clipAction method of AnimationMixer.
53800 * - Instead pass this object as 'root'.
53801 * - You can also add and remove objects later when the mixer is running.
53802 *
53803 * Note:
53804 *
53805 * - Objects of this class appear as one object to the mixer,
53806 * so cache control of the individual objects must be done on the group.
53807 *
53808 * Limitation:
53809 *
53810 * - The animated properties must be compatible among the all objects in the group.
53811 * - A single property can either be controlled through a target group or directly, but not both.
53812 */
53813class AnimationObjectGroup {
53814
53815	/**
53816	 * Constructs a new animation group.
53817	 *
53818	 * @param {...Object3D} arguments - An arbitrary number of 3D objects that share the same animation state.
53819	 */
53820	constructor() {
53821
53822		/**
53823		 * This flag can be used for type testing.
53824		 *
53825		 * @type {boolean}
53826		 * @readonly
53827		 * @default true
53828		 */
53829		this.isAnimationObjectGroup = true;
53830
53831		/**
53832		 * The UUID of the 3D object.
53833		 *
53834		 * @type {string}
53835		 * @readonly
53836		 */
53837		this.uuid = generateUUID();
53838
53839		// cached objects followed by the active ones
53840		this._objects = Array.prototype.slice.call( arguments );
53841
53842		this.nCachedObjects_ = 0; // threshold
53843		// note: read by PropertyBinding.Composite
53844
53845		const indices = {};
53846		this._indicesByUUID = indices; // for bookkeeping
53847
53848		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
53849
53850			indices[ arguments[ i ].uuid ] = i;
53851
53852		}
53853
53854		this._paths = []; // inside: string
53855		this._parsedPaths = []; // inside: { we don't care, here }
53856		this._bindings = []; // inside: Array< PropertyBinding >
53857		this._bindingsIndicesByPath = {}; // inside: indices in these arrays
53858
53859		const scope = this;
53860
53861		this.stats = {
53862
53863			objects: {
53864				get total() {
53865
53866					return scope._objects.length;
53867
53868				},
53869				get inUse() {
53870
53871					return this.total - scope.nCachedObjects_;
53872
53873				}
53874			},
53875			get bindingsPerObject() {
53876
53877				return scope._bindings.length;
53878
53879			}
53880
53881		};
53882
53883	}
53884
53885	/**
53886	 * Adds an arbitrary number of objects to this animation group.
53887	 *
53888	 * @param {...Object3D} arguments - The 3D objects to add.
53889	 */
53890	add() {
53891
53892		const objects = this._objects,
53893			indicesByUUID = this._indicesByUUID,
53894			paths = this._paths,
53895			parsedPaths = this._parsedPaths,
53896			bindings = this._bindings,
53897			nBindings = bindings.length;
53898
53899		let knownObject = undefined,
53900			nObjects = objects.length,
53901			nCachedObjects = this.nCachedObjects_;
53902
53903		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
53904
53905			const object = arguments[ i ],
53906				uuid = object.uuid;
53907			let index = indicesByUUID[ uuid ];
53908
53909			if ( index === undefined ) {
53910
53911				// unknown object -> add it to the ACTIVE region
53912
53913				index = nObjects ++;
53914				indicesByUUID[ uuid ] = index;
53915				objects.push( object );
53916
53917				// accounting is done, now do the same for all bindings
53918
53919				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
53920
53921					bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
53922
53923				}
53924
53925			} else if ( index < nCachedObjects ) {
53926
53927				knownObject = objects[ index ];
53928
53929				// move existing object to the ACTIVE region
53930
53931				const firstActiveIndex = -- nCachedObjects,
53932					lastCachedObject = objects[ firstActiveIndex ];
53933
53934				indicesByUUID[ lastCachedObject.uuid ] = index;
53935				objects[ index ] = lastCachedObject;
53936
53937				indicesByUUID[ uuid ] = firstActiveIndex;
53938				objects[ firstActiveIndex ] = object;
53939
53940				// accounting is done, now do the same for all bindings
53941
53942				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
53943
53944					const bindingsForPath = bindings[ j ],
53945						lastCached = bindingsForPath[ firstActiveIndex ];
53946
53947					let binding = bindingsForPath[ index ];
53948
53949					bindingsForPath[ index ] = lastCached;
53950
53951					if ( binding === undefined ) {
53952
53953						// since we do not bother to create new bindings
53954						// for objects that are cached, the binding may
53955						// or may not exist
53956
53957						binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
53958
53959					}
53960
53961					bindingsForPath[ firstActiveIndex ] = binding;
53962
53963				}
53964
53965			} else if ( objects[ index ] !== knownObject ) {
53966
53967				error( 'AnimationObjectGroup: Different objects with the same UUID ' +
53968					'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
53969
53970			} // else the object is already where we want it to be
53971
53972		} // for arguments
53973
53974		this.nCachedObjects_ = nCachedObjects;
53975
53976	}
53977
53978	/**
53979	 * Removes an arbitrary number of objects to this animation group
53980	 *
53981	 * @param {...Object3D} arguments - The 3D objects to remove.
53982	 */
53983	remove() {
53984
53985		const objects = this._objects,
53986			indicesByUUID = this._indicesByUUID,
53987			bindings = this._bindings,
53988			nBindings = bindings.length;
53989
53990		let nCachedObjects = this.nCachedObjects_;
53991
53992		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
53993
53994			const object = arguments[ i ],
53995				uuid = object.uuid,
53996				index = indicesByUUID[ uuid ];
53997
53998			if ( index !== undefined && index >= nCachedObjects ) {
53999
54000				// move existing object into the CACHED region
54001
54002				const lastCachedIndex = nCachedObjects ++,
54003					firstActiveObject = objects[ lastCachedIndex ];
54004
54005				indicesByUUID[ firstActiveObject.uuid ] = index;
54006				objects[ index ] = firstActiveObject;
54007
54008				indicesByUUID[ uuid ] = lastCachedIndex;
54009				objects[ lastCachedIndex ] = object;
54010
54011				// accounting is done, now do the same for all bindings
54012
54013				for ( let j = 0, m = nBindings; j !== m; ++ j ) {
54014
54015					const bindingsForPath = bindings[ j ],
54016						firstActive = bindingsForPath[ lastCachedIndex ],
54017						binding = bindingsForPath[ index ];
54018
54019					bindingsForPath[ index ] = firstActive;
54020					bindingsForPath[ lastCachedIndex ] = binding;
54021
54022				}
54023
54024			}
54025
54026		} // for arguments
54027
54028		this.nCachedObjects_ = nCachedObjects;
54029
54030	}
54031
54032	/**
54033	 * Deallocates all memory resources for the passed 3D objects of this animation group.
54034	 *
54035	 * @param {...Object3D} arguments - The 3D objects to uncache.
54036	 */
54037	uncache() {
54038
54039		const objects = this._objects,
54040			indicesByUUID = this._indicesByUUID,
54041			bindings = this._bindings,
54042			nBindings = bindings.length;
54043
54044		let nCachedObjects = this.nCachedObjects_,
54045			nObjects = objects.length;
54046
54047		for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
54048
54049			const object = arguments[ i ],
54050				uuid = object.uuid,
54051				index = indicesByUUID[ uuid ];
54052
54053			if ( index !== undefined ) {
54054
54055				delete indicesByUUID[ uuid ];
54056
54057				if ( index < nCachedObjects ) {
54058
54059					// object is cached, shrink the CACHED region
54060
54061					const firstActiveIndex = -- nCachedObjects,
54062						lastCachedObject = objects[ firstActiveIndex ],
54063						lastIndex = -- nObjects,
54064						lastObject = objects[ lastIndex ];
54065
54066					if ( index !== firstActiveIndex ) {
54067
54068						// last cached object takes this object's place
54069
54070						indicesByUUID[ lastCachedObject.uuid ] = index;
54071
54072					}
54073
54074					objects[ index ] = lastCachedObject;
54075
54076					if ( firstActiveIndex !== lastIndex ) {
54077
54078						// last object goes to the activated slot and pop
54079
54080						indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
54081
54082					}
54083
54084					objects[ firstActiveIndex ] = lastObject;
54085					objects.pop();
54086
54087					// accounting is done, now do the same for all bindings
54088
54089					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
54090
54091						const bindingsForPath = bindings[ j ],
54092							lastCached = bindingsForPath[ firstActiveIndex ],
54093							last = bindingsForPath[ lastIndex ];
54094
54095						bindingsForPath[ index ] = lastCached;
54096						bindingsForPath[ firstActiveIndex ] = last;
54097						bindingsForPath.pop();
54098
54099					}
54100
54101				} else {
54102
54103					// object is active, just swap with the last and pop
54104
54105					const lastIndex = -- nObjects,
54106						lastObject = objects[ lastIndex ];
54107
54108					if ( index !== lastIndex ) {
54109
54110						indicesByUUID[ lastObject.uuid ] = index;
54111
54112					}
54113
54114					objects[ index ] = lastObject;
54115					objects.pop();
54116
54117					// accounting is done, now do the same for all bindings
54118
54119					for ( let j = 0, m = nBindings; j !== m; ++ j ) {
54120
54121						const bindingsForPath = bindings[ j ];
54122
54123						bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
54124						bindingsForPath.pop();
54125
54126					}
54127
54128				} // cached or active
54129
54130			} // if object is known
54131
54132		} // for arguments
54133
54134		this.nCachedObjects_ = nCachedObjects;
54135
54136	}
54137
54138	// Internal interface used by befriended PropertyBinding.Composite:
54139
54140	subscribe_( path, parsedPath ) {
54141
54142		// returns an array of bindings for the given path that is changed
54143		// according to the contained objects in the group
54144
54145		const indicesByPath = this._bindingsIndicesByPath;
54146		let index = indicesByPath[ path ];
54147		const bindings = this._bindings;
54148
54149		if ( index !== undefined ) return bindings[ index ];
54150
54151		const paths = this._paths,
54152			parsedPaths = this._parsedPaths,
54153			objects = this._objects,
54154			nObjects = objects.length,
54155			nCachedObjects = this.nCachedObjects_,
54156			bindingsForPath = new Array( nObjects );
54157
54158		index = bindings.length;
54159
54160		indicesByPath[ path ] = index;
54161
54162		paths.push( path );
54163		parsedPaths.push( parsedPath );
54164		bindings.push( bindingsForPath );
54165
54166		for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
54167
54168			const object = objects[ i ];
54169			bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
54170
54171		}
54172
54173		return bindingsForPath;
54174
54175	}
54176
54177	unsubscribe_( path ) {
54178
54179		// tells the group to forget about a property path and no longer
54180		// update the array previously obtained with 'subscribe_'
54181
54182		const indicesByPath = this._bindingsIndicesByPath,
54183			index = indicesByPath[ path ];
54184
54185		if ( index !== undefined ) {
54186
54187			const paths = this._paths,
54188				parsedPaths = this._parsedPaths,
54189				bindings = this._bindings,
54190				lastBindingsIndex = bindings.length - 1,
54191				lastBindings = bindings[ lastBindingsIndex ],
54192				lastBindingsPath = paths[ lastBindingsIndex ];
54193
54194			indicesByPath[ lastBindingsPath ] = index;
54195
54196			bindings[ index ] = lastBindings;
54197			bindings.pop();
54198
54199			parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
54200			parsedPaths.pop();
54201
54202			paths[ index ] = paths[ lastBindingsIndex ];
54203			paths.pop();
54204
54205		}
54206
54207	}
54208
54209}
54210
54211/**
54212 * An instance of `AnimationAction` schedules the playback of an animation which is
54213 * stored in {@link AnimationClip}.
54214 */
54215class AnimationAction {
54216
54217	/**
54218	 * Constructs a new animation action.
54219	 *
54220	 * @param {AnimationMixer} mixer - The mixer that is controlled by this action.
54221	 * @param {AnimationClip} clip - The animation clip that holds the actual keyframes.
54222	 * @param {?Object3D} [localRoot=null] - The root object on which this action is performed.
54223	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
54224	 */
54225	constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
54226
54227		this._mixer = mixer;
54228		this._clip = clip;
54229		this._localRoot = localRoot;
54230
54231		/**
54232		 * Defines how the animation is blended/combined when two or more animations
54233		 * are simultaneously played.
54234		 *
54235		 * @type {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)}
54236		 */
54237		this.blendMode = blendMode;
54238
54239		const tracks = clip.tracks,
54240			nTracks = tracks.length,
54241			interpolants = new Array( nTracks );
54242
54243		const interpolantSettings = {
54244			endingStart: ZeroCurvatureEnding,
54245			endingEnd: ZeroCurvatureEnding
54246		};
54247
54248		for ( let i = 0; i !== nTracks; ++ i ) {
54249
54250			const interpolant = tracks[ i ].createInterpolant( null );
54251			interpolants[ i ] = interpolant;
54252			interpolant.settings = interpolantSettings;
54253
54254		}
54255
54256		this._interpolantSettings = interpolantSettings;
54257
54258		this._interpolants = interpolants; // bound by the mixer
54259
54260		// inside: PropertyMixer (managed by the mixer)
54261		this._propertyBindings = new Array( nTracks );
54262
54263		this._cacheIndex = null; // for the memory manager
54264		this._byClipCacheIndex = null; // for the memory manager
54265
54266		this._timeScaleInterpolant = null;
54267		this._restoreTimeScale = null;
54268		this._weightInterpolant = null;
54269
54270		/**
54271		 * The loop mode, set via {@link AnimationAction#setLoop}.
54272		 *
54273		 * @type {(LoopRepeat|LoopOnce|LoopPingPong)}
54274		 * @default LoopRepeat
54275		 */
54276		this.loop = LoopRepeat;
54277		this._loopCount = -1;
54278
54279		// global mixer time when the action is to be started
54280		// it's set back to 'null' upon start of the action
54281		this._startTime = null;
54282
54283		/**
54284		 * The local time of this action (in seconds, starting with `0`).
54285		 *
54286		 * The value gets clamped or wrapped to `[0,clip.duration]` (according to the
54287		 * loop state).
54288		 *
54289		 * @type {number}
54290		 * @default Infinity
54291		 */
54292		this.time = 0;
54293
54294		/**
54295		 * Scaling factor for the {@link AnimationAction#time}. A value of `0` causes the
54296		 * animation to pause. Negative values cause the animation to play backwards.
54297		 *
54298		 * @type {number}
54299		 * @default 1
54300		 */
54301		this.timeScale = 1;
54302		this._effectiveTimeScale = 1;
54303
54304		/**
54305		 * The degree of influence of this action (in the interval `[0, 1]`). Values
54306		 * between `0` (no impact) and `1` (full impact) can be used to blend between
54307		 * several actions.
54308		 *
54309		 * @type {number}
54310		 * @default 1
54311		 */
54312		this.weight = 1;
54313		this._effectiveWeight = 1;
54314
54315		/**
54316		 * The number of repetitions of the performed clip over the course of this action.
54317		 * Can be set via {@link AnimationAction#setLoop}.
54318		 *
54319		 * Setting this number has no effect if {@link AnimationAction#loop} is set to
54320		 * `THREE:LoopOnce`.
54321		 *
54322		 * @type {number}
54323		 * @default Infinity
54324		 */
54325		this.repetitions = Infinity;
54326
54327		/**
54328		 * If set to `true`, the playback of the action is paused.
54329		 *
54330		 * @type {boolean}
54331		 * @default false
54332		 */
54333		this.paused = false;
54334
54335		/**
54336		 * If set to `false`, the action is disabled so it has no impact.
54337		 *
54338		 * When the action is re-enabled, the animation continues from its current
54339		 * time (setting `enabled` to `false` doesn't reset the action).
54340		 *
54341		 * @type {boolean}
54342		 * @default true
54343		 */
54344		this.enabled = true;
54345
54346		/**
54347		 * If set to true the animation will automatically be paused on its last frame.
54348		 *
54349		 * If set to false, {@link AnimationAction#enabled} will automatically be switched
54350		 * to `false` when the last loop of the action has finished, so that this action has
54351		 * no further impact.
54352		 *
54353		 * Note: This member has no impact if the action is interrupted (it
54354		 * has only an effect if its last loop has really finished).
54355		 *
54356		 * @type {boolean}
54357		 * @default false
54358		 */
54359		this.clampWhenFinished = false;
54360
54361		/**
54362		 * Enables smooth interpolation without separate clips for start, loop and end.
54363		 *
54364		 * @type {boolean}
54365		 * @default true
54366		 */
54367		this.zeroSlopeAtStart = true;
54368
54369		/**
54370		 * Enables smooth interpolation without separate clips for start, loop and end.
54371		 *
54372		 * @type {boolean}
54373		 * @default true
54374		 */
54375		this.zeroSlopeAtEnd = true;
54376
54377	}
54378
54379	/**
54380	 * Starts the playback of the animation.
54381	 *
54382	 * @return {AnimationAction} A reference to this animation action.
54383	 */
54384	play() {
54385
54386		this._mixer._activateAction( this );
54387
54388		return this;
54389
54390	}
54391
54392	/**
54393	 * Stops the playback of the animation.
54394	 *
54395	 * @return {AnimationAction} A reference to this animation action.
54396	 */
54397	stop() {
54398
54399		this._mixer._deactivateAction( this );
54400
54401		return this.reset();
54402
54403	}
54404
54405	/**
54406	 * Resets the playback of the animation.
54407	 *
54408	 * @return {AnimationAction} A reference to this animation action.
54409	 */
54410	reset() {
54411
54412		this.paused = false;
54413		this.enabled = true;
54414
54415		this.time = 0; // restart clip
54416		this._loopCount = -1;// forget previous loops
54417		this._startTime = null;// forget scheduling
54418
54419		return this.stopFading().stopWarping();
54420
54421	}
54422
54423	/**
54424	 * Returns `true` if the animation is running.
54425	 *
54426	 * @return {boolean} Whether the animation is running or not.
54427	 */
54428	isRunning() {
54429
54430		return this.enabled && ! this.paused && this.timeScale !== 0 &&
54431			this._startTime === null && this._mixer._isActiveAction( this );
54432
54433	}
54434
54435	/**
54436	 * Returns `true` when {@link AnimationAction#play} has been called.
54437	 *
54438	 * @return {boolean} Whether the animation is scheduled or not.
54439	 */
54440	isScheduled() {
54441
54442		return this._mixer._isActiveAction( this );
54443
54444	}
54445
54446	/**
54447	 * Defines the time when the animation should start.
54448	 *
54449	 * @param {number} time - The start time in seconds.
54450	 * @return {AnimationAction} A reference to this animation action.
54451	 */
54452	startAt( time ) {
54453
54454		this._startTime = time;
54455
54456		return this;
54457
54458	}
54459
54460	/**
54461	 * Configures the loop settings for this action.
54462	 *
54463	 * @param {(LoopRepeat|LoopOnce|LoopPingPong)} mode - The loop mode.
54464	 * @param {number} repetitions - The number of repetitions.
54465	 * @return {AnimationAction} A reference to this animation action.
54466	 */
54467	setLoop( mode, repetitions ) {
54468
54469		this.loop = mode;
54470		this.repetitions = repetitions;
54471
54472		return this;
54473
54474	}
54475
54476	/**
54477	 * Sets the effective weight of this action.
54478	 *
54479	 * An action has no effect and thus an effective weight of zero when the
54480	 * action is disabled.
54481	 *
54482	 * @param {number} weight - The weight to set.
54483	 * @return {AnimationAction} A reference to this animation action.
54484	 */
54485	setEffectiveWeight( weight ) {
54486
54487		this.weight = weight;
54488
54489		// note: same logic as when updated at runtime
54490		this._effectiveWeight = this.enabled ? weight : 0;
54491
54492		return this.stopFading();
54493
54494	}
54495
54496	/**
54497	 * Returns the effective weight of this action.
54498	 *
54499	 * @return {number} The effective weight.
54500	 */
54501	getEffectiveWeight() {
54502
54503		return this._effectiveWeight;
54504
54505	}
54506
54507	/**
54508	 * Fades the animation in by increasing its weight gradually from `0` to `1`,
54509	 * within the passed time interval.
54510	 *
54511	 * @param {number} duration - The duration of the fade.
54512	 * @return {AnimationAction} A reference to this animation action.
54513	 */
54514	fadeIn( duration ) {
54515
54516		return this._scheduleFading( duration, 0, 1 );
54517
54518	}
54519
54520	/**
54521	 * Fades the animation out by decreasing its weight gradually from `1` to `0`,
54522	 * within the passed time interval.
54523	 *
54524	 * @param {number} duration - The duration of the fade.
54525	 * @return {AnimationAction} A reference to this animation action.
54526	 */
54527	fadeOut( duration ) {
54528
54529		return this._scheduleFading( duration, 1, 0 );
54530
54531	}
54532
54533	/**
54534	 * Causes this action to fade in and the given action to fade out,
54535	 * within the passed time interval.
54536	 *
54537	 * @param {AnimationAction} fadeOutAction - The animation action to fade out.
54538	 * @param {number} duration - The duration of the fade.
54539	 * @param {boolean} [warp=false] - Whether warping should be used or not.
54540	 * @return {AnimationAction} A reference to this animation action.
54541	 */
54542	crossFadeFrom( fadeOutAction, duration, warp = false ) {
54543
54544		fadeOutAction.fadeOut( duration );
54545		this.fadeIn( duration );
54546
54547		if ( warp === true ) {
54548
54549			const fadeInDuration = this._clip.duration,
54550				fadeOutDuration = fadeOutAction._clip.duration,
54551
54552				startEndRatio = fadeOutDuration / fadeInDuration,
54553				endStartRatio = fadeInDuration / fadeOutDuration;
54554
54555
54556			fadeOutAction._restoreTimeScale = fadeOutAction.timeScale;
54557			this._restoreTimeScale = this.timeScale;
54558
54559			fadeOutAction.warp( 1.0, startEndRatio, duration );
54560			this.warp( endStartRatio, 1.0, duration );
54561
54562		}
54563
54564		return this;
54565
54566	}
54567
54568	/**
54569	 * Causes this action to fade out and the given action to fade in,
54570	 * within the passed time interval.
54571	 *
54572	 * @param {AnimationAction} fadeInAction - The animation action to fade in.
54573	 * @param {number} duration - The duration of the fade.
54574	 * @param {boolean} [warp=false] - Whether warping should be used or not.
54575	 * @return {AnimationAction} A reference to this animation action.
54576	 */
54577	crossFadeTo( fadeInAction, duration, warp = false ) {
54578
54579		return fadeInAction.crossFadeFrom( this, duration, warp );
54580
54581	}
54582
54583	/**
54584	 * Stops any fading which is applied to this action.
54585	 *
54586	 * @return {AnimationAction} A reference to this animation action.
54587	 */
54588	stopFading() {
54589
54590		const weightInterpolant = this._weightInterpolant;
54591
54592		if ( weightInterpolant !== null ) {
54593
54594			this._weightInterpolant = null;
54595			this._mixer._takeBackControlInterpolant( weightInterpolant );
54596
54597		}
54598
54599		return this;
54600
54601	}
54602
54603	/**
54604	 * Sets the effective time scale of this action.
54605	 *
54606	 * An action has no effect and thus an effective time scale of zero when the
54607	 * action is paused.
54608	 *
54609	 * @param {number} timeScale - The time scale to set.
54610	 * @return {AnimationAction} A reference to this animation action.
54611	 */
54612	setEffectiveTimeScale( timeScale ) {
54613
54614		this.timeScale = timeScale;
54615		this._effectiveTimeScale = this.paused ? 0 : timeScale;
54616
54617		return this.stopWarping();
54618
54619	}
54620
54621	/**
54622	 * Returns the effective time scale of this action.
54623	 *
54624	 * @return {number} The effective time scale.
54625	 */
54626	getEffectiveTimeScale() {
54627
54628		return this._effectiveTimeScale;
54629
54630	}
54631
54632	/**
54633	 * Sets the duration for a single loop of this action.
54634	 *
54635	 * @param {number} duration - The duration to set.
54636	 * @return {AnimationAction} A reference to this animation action.
54637	 */
54638	setDuration( duration ) {
54639
54640		this.timeScale = this._clip.duration / duration;
54641
54642		return this.stopWarping();
54643
54644	}
54645
54646	/**
54647	 * Synchronizes this action with the passed other action.
54648	 *
54649	 * @param {AnimationAction} action - The action to sync with.
54650	 * @return {AnimationAction} A reference to this animation action.
54651	 */
54652	syncWith( action ) {
54653
54654		this.time = action.time;
54655		this.timeScale = action.timeScale;
54656
54657		return this.stopWarping();
54658
54659	}
54660
54661	/**
54662	 * Decelerates this animation's speed to `0` within the passed time interval.
54663	 *
54664	 * @param {number} duration - The duration.
54665	 * @return {AnimationAction} A reference to this animation action.
54666	 */
54667	halt( duration ) {
54668
54669		return this.warp( this._effectiveTimeScale, 0, duration );
54670
54671	}
54672
54673	/**
54674	 * Changes the playback speed, within the passed time interval, by modifying
54675	 * {@link AnimationAction#timeScale} gradually from `startTimeScale` to
54676	 * `endTimeScale`.
54677	 *
54678	 * @param {number} startTimeScale - The start time scale.
54679	 * @param {number} endTimeScale - The end time scale.
54680	 * @param {number} duration - The duration.
54681	 * @return {AnimationAction} A reference to this animation action.
54682	 */
54683	warp( startTimeScale, endTimeScale, duration ) {
54684
54685		const mixer = this._mixer,
54686			now = mixer.time,
54687			timeScale = this.timeScale;
54688
54689		let interpolant = this._timeScaleInterpolant;
54690
54691		if ( interpolant === null ) {
54692
54693			interpolant = mixer._lendControlInterpolant();
54694			this._timeScaleInterpolant = interpolant;
54695
54696		}
54697
54698		const times = interpolant.parameterPositions,
54699			values = interpolant.sampleValues;
54700
54701		times[ 0 ] = now;
54702		times[ 1 ] = now + duration;
54703
54704		values[ 0 ] = startTimeScale / timeScale;
54705		values[ 1 ] = endTimeScale / timeScale;
54706
54707		return this;
54708
54709	}
54710
54711	/**
54712	 * Stops any scheduled warping which is applied to this action.
54713	 *
54714	 * @return {AnimationAction} A reference to this animation action.
54715	 */
54716	stopWarping() {
54717
54718		const timeScaleInterpolant = this._timeScaleInterpolant;
54719
54720		if ( timeScaleInterpolant !== null ) {
54721
54722			this._timeScaleInterpolant = null;
54723			this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
54724
54725		}
54726
54727		this._restoreTimeScale = null;
54728
54729		return this;
54730
54731	}
54732
54733	/**
54734	 * Returns the animation mixer of this animation action.
54735	 *
54736	 * @return {AnimationMixer} The animation mixer.
54737	 */
54738	getMixer() {
54739
54740		return this._mixer;
54741
54742	}
54743
54744	/**
54745	 * Returns the animation clip of this animation action.
54746	 *
54747	 * @return {AnimationClip} The animation clip.
54748	 */
54749	getClip() {
54750
54751		return this._clip;
54752
54753	}
54754
54755	/**
54756	 * Returns the root object of this animation action.
54757	 *
54758	 * @return {Object3D} The root object.
54759	 */
54760	getRoot() {
54761
54762		return this._localRoot || this._mixer._root;
54763
54764	}
54765
54766	// Internal
54767
54768	_update( time, deltaTime, timeDirection, accuIndex ) {
54769
54770		// called by the mixer
54771
54772		if ( ! this.enabled ) {
54773
54774			// call ._updateWeight() to update ._effectiveWeight
54775
54776			this._updateWeight( time );
54777			return;
54778
54779		}
54780
54781		const startTime = this._startTime;
54782
54783		if ( startTime !== null ) {
54784
54785			// check for scheduled start of action
54786
54787			const timeRunning = ( time - startTime ) * timeDirection;
54788			if ( timeRunning < 0 || timeDirection === 0 ) {
54789
54790				deltaTime = 0;
54791
54792			} else {
54793
54794
54795				this._startTime = null; // unschedule
54796				deltaTime = timeDirection * timeRunning;
54797
54798			}
54799
54800		}
54801
54802		// apply time scale and advance time
54803
54804		deltaTime *= this._updateTimeScale( time );
54805		const clipTime = this._updateTime( deltaTime );
54806
54807		// note: _updateTime may disable the action resulting in
54808		// an effective weight of 0
54809
54810		const weight = this._updateWeight( time );
54811
54812		if ( weight > 0 ) {
54813
54814			const interpolants = this._interpolants;
54815			const propertyMixers = this._propertyBindings;
54816
54817			switch ( this.blendMode ) {
54818
54819				case AdditiveAnimationBlendMode:
54820
54821					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
54822
54823						interpolants[ j ].evaluate( clipTime );
54824						propertyMixers[ j ].accumulateAdditive( weight );
54825
54826					}
54827
54828					break;
54829
54830				case NormalAnimationBlendMode:
54831				default:
54832
54833					for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
54834
54835						interpolants[ j ].evaluate( clipTime );
54836						propertyMixers[ j ].accumulate( accuIndex, weight );
54837
54838					}
54839
54840			}
54841
54842		}
54843
54844	}
54845
54846	_updateWeight( time ) {
54847
54848		let weight = 0;
54849
54850		if ( this.enabled ) {
54851
54852			weight = this.weight;
54853			const interpolant = this._weightInterpolant;
54854
54855			if ( interpolant !== null ) {
54856
54857				const interpolantValue = interpolant.evaluate( time )[ 0 ];
54858
54859				weight *= interpolantValue;
54860
54861				if ( time > interpolant.parameterPositions[ 1 ] ) {
54862
54863					this.stopFading();
54864
54865					if ( interpolantValue === 0 ) {
54866
54867						// faded out, disable
54868						this.enabled = false;
54869
54870					}
54871
54872				}
54873
54874			}
54875
54876		}
54877
54878		this._effectiveWeight = weight;
54879		return weight;
54880
54881	}
54882
54883	_updateTimeScale( time ) {
54884
54885		let timeScale = 0;
54886
54887		if ( ! this.paused ) {
54888
54889			timeScale = this.timeScale;
54890
54891			const interpolant = this._timeScaleInterpolant;
54892
54893			if ( interpolant !== null ) {
54894
54895				const interpolantValue = interpolant.evaluate( time )[ 0 ];
54896
54897				timeScale *= interpolantValue;
54898
54899				if ( time > interpolant.parameterPositions[ 1 ] ) {
54900
54901					if ( timeScale === 0 ) {
54902
54903						// motion has halted, pause
54904						this.paused = true;
54905
54906					} else {
54907
54908						if ( this._restoreTimeScale !== null ) {
54909
54910							timeScale = this._restoreTimeScale;
54911
54912						}
54913
54914						// warp done - apply final time scale
54915						this.timeScale = timeScale;
54916
54917					}
54918
54919					this.stopWarping();
54920
54921				}
54922
54923			}
54924
54925		}
54926
54927		this._effectiveTimeScale = timeScale;
54928		return timeScale;
54929
54930	}
54931
54932	_updateTime( deltaTime ) {
54933
54934		const duration = this._clip.duration;
54935		const loop = this.loop;
54936
54937		let time = this.time + deltaTime;
54938		let loopCount = this._loopCount;
54939
54940		const pingPong = ( loop === LoopPingPong );
54941
54942		if ( deltaTime === 0 ) {
54943
54944			if ( loopCount === -1 ) return time;
54945
54946			return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
54947
54948		}
54949
54950		if ( loop === LoopOnce ) {
54951
54952			if ( loopCount === -1 ) {
54953
54954				// just started
54955
54956				this._loopCount = 0;
54957				this._setEndings( true, true, false );
54958
54959			}
54960
54961			handle_stop: {
54962
54963				if ( time >= duration ) {
54964
54965					time = duration;
54966
54967				} else if ( time < 0 ) {
54968
54969					time = 0;
54970
54971				} else {
54972
54973					this.time = time;
54974
54975					break handle_stop;
54976
54977				}
54978
54979				if ( this.clampWhenFinished ) this.paused = true;
54980				else this.enabled = false;
54981
54982				this.time = time;
54983
54984				this._mixer.dispatchEvent( {
54985					type: 'finished', action: this,
54986					direction: deltaTime < 0 ? -1 : 1
54987				} );
54988
54989			}
54990
54991		} else { // repetitive Repeat or PingPong
54992
54993			if ( loopCount === -1 ) {
54994
54995				// just started
54996
54997				if ( deltaTime >= 0 ) {
54998
54999					loopCount = 0;
55000
55001					this._setEndings( true, this.repetitions === 0, pingPong );
55002
55003				} else {
55004
55005					// when looping in reverse direction, the initial
55006					// transition through zero counts as a repetition,
55007					// so leave loopCount at -1
55008
55009					this._setEndings( this.repetitions === 0, true, pingPong );
55010
55011				}
55012
55013			}
55014
55015			if ( time >= duration || time < 0 ) {
55016
55017				// wrap around
55018
55019				const loopDelta = Math.floor( time / duration ); // signed
55020				time -= duration * loopDelta;
55021
55022				loopCount += Math.abs( loopDelta );
55023
55024				const pending = this.repetitions - loopCount;
55025
55026				if ( pending <= 0 ) {
55027
55028					// have to stop (switch state, clamp time, fire event)
55029
55030					if ( this.clampWhenFinished ) this.paused = true;
55031					else this.enabled = false;
55032
55033					time = deltaTime > 0 ? duration : 0;
55034
55035					this.time = time;
55036
55037					this._mixer.dispatchEvent( {
55038						type: 'finished', action: this,
55039						direction: deltaTime > 0 ? 1 : -1
55040					} );
55041
55042				} else {
55043
55044					// keep running
55045
55046					if ( pending === 1 ) {
55047
55048						// entering the last round
55049
55050						const atStart = deltaTime < 0;
55051						this._setEndings( atStart, ! atStart, pingPong );
55052
55053					} else {
55054
55055						this._setEndings( false, false, pingPong );
55056
55057					}
55058
55059					this._loopCount = loopCount;
55060
55061					this.time = time;
55062
55063					this._mixer.dispatchEvent( {
55064						type: 'loop', action: this, loopDelta: loopDelta
55065					} );
55066
55067				}
55068
55069			} else {
55070
55071				this._loopCount = loopCount;
55072				this.time = time;
55073
55074			}
55075
55076			if ( pingPong && ( loopCount & 1 ) === 1 ) {
55077
55078				// invert time for the "pong round"
55079
55080				return duration - time;
55081
55082			}
55083
55084		}
55085
55086		return time;
55087
55088	}
55089
55090	_setEndings( atStart, atEnd, pingPong ) {
55091
55092		const settings = this._interpolantSettings;
55093
55094		if ( pingPong ) {
55095
55096			settings.endingStart = ZeroSlopeEnding;
55097			settings.endingEnd = ZeroSlopeEnding;
55098
55099		} else {
55100
55101			// assuming for LoopOnce atStart == atEnd == true
55102
55103			if ( atStart ) {
55104
55105				settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
55106
55107			} else {
55108
55109				settings.endingStart = WrapAroundEnding;
55110
55111			}
55112
55113			if ( atEnd ) {
55114
55115				settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
55116
55117			} else {
55118
55119				settings.endingEnd = WrapAroundEnding;
55120
55121			}
55122
55123		}
55124
55125	}
55126
55127	_scheduleFading( duration, weightNow, weightThen ) {
55128
55129		const mixer = this._mixer, now = mixer.time;
55130		let interpolant = this._weightInterpolant;
55131
55132		if ( interpolant === null ) {
55133
55134			interpolant = mixer._lendControlInterpolant();
55135			this._weightInterpolant = interpolant;
55136
55137		}
55138
55139		const times = interpolant.parameterPositions,
55140			values = interpolant.sampleValues;
55141
55142		times[ 0 ] = now;
55143		values[ 0 ] = weightNow;
55144		times[ 1 ] = now + duration;
55145		values[ 1 ] = weightThen;
55146
55147		return this;
55148
55149	}
55150
55151}
55152
55153const _controlInterpolantsResultBuffer = new Float32Array( 1 );
55154
55155/**
55156 * `AnimationMixer` is a player for animations on a particular object in
55157 * the scene. When multiple objects in the scene are animated independently,
55158 * one `AnimationMixer` may be used for each object.
55159 */
55160class AnimationMixer extends EventDispatcher {
55161
55162	/**
55163	 * Constructs a new animation mixer.
55164	 *
55165	 * @param {Object3D} root - The object whose animations shall be played by this mixer.
55166	 */
55167	constructor( root ) {
55168
55169		super();
55170
55171		this._root = root;
55172		this._initMemoryManager();
55173		this._accuIndex = 0;
55174
55175		/**
55176		 * The global mixer time (in seconds; starting with `0` on the mixer's creation).
55177		 *
55178		 * @type {number}
55179		 * @default 0
55180		 */
55181		this.time = 0;
55182
55183		/**
55184		 * A scaling factor for the global time.
55185		 *
55186		 * Note: Setting this member to `0` and later back to `1` is a
55187		 * possibility to pause/unpause all actions that are controlled by this
55188		 * mixer.
55189		 *
55190		 * @type {number}
55191		 * @default 1
55192		 */
55193		this.timeScale = 1.0;
55194
55195		if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
55196
55197			__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) );
55198
55199		}
55200
55201	}
55202
55203	_bindAction( action, prototypeAction ) {
55204
55205		const root = action._localRoot || this._root,
55206			tracks = action._clip.tracks,
55207			nTracks = tracks.length,
55208			bindings = action._propertyBindings,
55209			interpolants = action._interpolants,
55210			rootUuid = root.uuid,
55211			bindingsByRoot = this._bindingsByRootAndName;
55212
55213		let bindingsByName = bindingsByRoot[ rootUuid ];
55214
55215		if ( bindingsByName === undefined ) {
55216
55217			bindingsByName = {};
55218			bindingsByRoot[ rootUuid ] = bindingsByName;
55219
55220		}
55221
55222		for ( let i = 0; i !== nTracks; ++ i ) {
55223
55224			const track = tracks[ i ],
55225				trackName = track.name;
55226
55227			let binding = bindingsByName[ trackName ];
55228
55229			if ( binding !== undefined ) {
55230
55231				++ binding.referenceCount;
55232				bindings[ i ] = binding;
55233
55234			} else {
55235
55236				binding = bindings[ i ];
55237
55238				if ( binding !== undefined ) {
55239
55240					// existing binding, make sure the cache knows
55241
55242					if ( binding._cacheIndex === null ) {
55243
55244						++ binding.referenceCount;
55245						this._addInactiveBinding( binding, rootUuid, trackName );
55246
55247					}
55248
55249					continue;
55250
55251				}
55252
55253				const path = prototypeAction && prototypeAction.
55254					_propertyBindings[ i ].binding.parsedPath;
55255
55256				binding = new PropertyMixer(
55257					PropertyBinding.create( root, trackName, path ),
55258					track.ValueTypeName, track.getValueSize() );
55259
55260				++ binding.referenceCount;
55261				this._addInactiveBinding( binding, rootUuid, trackName );
55262
55263				bindings[ i ] = binding;
55264
55265			}
55266
55267			interpolants[ i ].resultBuffer = binding.buffer;
55268
55269		}
55270
55271	}
55272
55273	_activateAction( action ) {
55274
55275		if ( ! this._isActiveAction( action ) ) {
55276
55277			if ( action._cacheIndex === null ) {
55278
55279				// this action has been forgotten by the cache, but the user
55280				// appears to be still using it -> rebind
55281
55282				const rootUuid = ( action._localRoot || this._root ).uuid,
55283					clipUuid = action._clip.uuid,
55284					actionsForClip = this._actionsByClip[ clipUuid ];
55285
55286				this._bindAction( action,
55287					actionsForClip && actionsForClip.knownActions[ 0 ] );
55288
55289				this._addInactiveAction( action, clipUuid, rootUuid );
55290
55291			}
55292
55293			const bindings = action._propertyBindings;
55294
55295			// increment reference counts / sort out state
55296			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
55297
55298				const binding = bindings[ i ];
55299
55300				if ( binding.useCount ++ === 0 ) {
55301
55302					this._lendBinding( binding );
55303					binding.saveOriginalState();
55304
55305				}
55306
55307			}
55308
55309			this._lendAction( action );
55310
55311		}
55312
55313	}
55314
55315	_deactivateAction( action ) {
55316
55317		if ( this._isActiveAction( action ) ) {
55318
55319			const bindings = action._propertyBindings;
55320
55321			// decrement reference counts / sort out state
55322			for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
55323
55324				const binding = bindings[ i ];
55325
55326				if ( -- binding.useCount === 0 ) {
55327
55328					binding.restoreOriginalState();
55329					this._takeBackBinding( binding );
55330
55331				}
55332
55333			}
55334
55335			this._takeBackAction( action );
55336
55337		}
55338
55339	}
55340
55341	// Memory manager
55342
55343	_initMemoryManager() {
55344
55345		this._actions = []; // 'nActiveActions' followed by inactive ones
55346		this._nActiveActions = 0;
55347
55348		this._actionsByClip = {};
55349		// inside:
55350		// {
55351		// 	knownActions: Array< AnimationAction > - used as prototypes
55352		// 	actionByRoot: AnimationAction - lookup
55353		// }
55354
55355
55356		this._bindings = []; // 'nActiveBindings' followed by inactive ones
55357		this._nActiveBindings = 0;
55358
55359		this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
55360
55361
55362		this._controlInterpolants = []; // same game as above
55363		this._nActiveControlInterpolants = 0;
55364
55365		const scope = this;
55366
55367		this.stats = {
55368
55369			actions: {
55370				get total() {
55371
55372					return scope._actions.length;
55373
55374				},
55375				get inUse() {
55376
55377					return scope._nActiveActions;
55378
55379				}
55380			},
55381			bindings: {
55382				get total() {
55383
55384					return scope._bindings.length;
55385
55386				},
55387				get inUse() {
55388
55389					return scope._nActiveBindings;
55390
55391				}
55392			},
55393			controlInterpolants: {
55394				get total() {
55395
55396					return scope._controlInterpolants.length;
55397
55398				},
55399				get inUse() {
55400
55401					return scope._nActiveControlInterpolants;
55402
55403				}
55404			}
55405
55406		};
55407
55408	}
55409
55410	// Memory management for AnimationAction objects
55411
55412	_isActiveAction( action ) {
55413
55414		const index = action._cacheIndex;
55415		return index !== null && index < this._nActiveActions;
55416
55417	}
55418
55419	_addInactiveAction( action, clipUuid, rootUuid ) {
55420
55421		const actions = this._actions,
55422			actionsByClip = this._actionsByClip;
55423
55424		let actionsForClip = actionsByClip[ clipUuid ];
55425
55426		if ( actionsForClip === undefined ) {
55427
55428			actionsForClip = {
55429
55430				knownActions: [ action ],
55431				actionByRoot: {}
55432
55433			};
55434
55435			action._byClipCacheIndex = 0;
55436
55437			actionsByClip[ clipUuid ] = actionsForClip;
55438
55439		} else {
55440
55441			const knownActions = actionsForClip.knownActions;
55442
55443			action._byClipCacheIndex = knownActions.length;
55444			knownActions.push( action );
55445
55446		}
55447
55448		action._cacheIndex = actions.length;
55449		actions.push( action );
55450
55451		actionsForClip.actionByRoot[ rootUuid ] = action;
55452
55453	}
55454
55455	_removeInactiveAction( action ) {
55456
55457		const actions = this._actions,
55458			lastInactiveAction = actions[ actions.length - 1 ],
55459			cacheIndex = action._cacheIndex;
55460
55461		lastInactiveAction._cacheIndex = cacheIndex;
55462		actions[ cacheIndex ] = lastInactiveAction;
55463		actions.pop();
55464
55465		action._cacheIndex = null;
55466
55467
55468		const clipUuid = action._clip.uuid,
55469			actionsByClip = this._actionsByClip,
55470			actionsForClip = actionsByClip[ clipUuid ],
55471			knownActionsForClip = actionsForClip.knownActions,
55472
55473			lastKnownAction =
55474				knownActionsForClip[ knownActionsForClip.length - 1 ],
55475
55476			byClipCacheIndex = action._byClipCacheIndex;
55477
55478		lastKnownAction._byClipCacheIndex = byClipCacheIndex;
55479		knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
55480		knownActionsForClip.pop();
55481
55482		action._byClipCacheIndex = null;
55483
55484
55485		const actionByRoot = actionsForClip.actionByRoot,
55486			rootUuid = ( action._localRoot || this._root ).uuid;
55487
55488		delete actionByRoot[ rootUuid ];
55489
55490		if ( knownActionsForClip.length === 0 ) {
55491
55492			delete actionsByClip[ clipUuid ];
55493
55494		}
55495
55496		this._removeInactiveBindingsForAction( action );
55497
55498	}
55499
55500	_removeInactiveBindingsForAction( action ) {
55501
55502		const bindings = action._propertyBindings;
55503
55504		for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
55505
55506			const binding = bindings[ i ];
55507
55508			if ( -- binding.referenceCount === 0 ) {
55509
55510				this._removeInactiveBinding( binding );
55511
55512			}
55513
55514		}
55515
55516	}
55517
55518	_lendAction( action ) {
55519
55520		// [ active actions |  inactive actions  ]
55521		// [  active actions >| inactive actions ]
55522		//                 s        a
55523		//                  <-swap->
55524		//                 a        s
55525
55526		const actions = this._actions,
55527			prevIndex = action._cacheIndex,
55528
55529			lastActiveIndex = this._nActiveActions ++,
55530
55531			firstInactiveAction = actions[ lastActiveIndex ];
55532
55533		action._cacheIndex = lastActiveIndex;
55534		actions[ lastActiveIndex ] = action;
55535
55536		firstInactiveAction._cacheIndex = prevIndex;
55537		actions[ prevIndex ] = firstInactiveAction;
55538
55539	}
55540
55541	_takeBackAction( action ) {
55542
55543		// [  active actions  | inactive actions ]
55544		// [ active actions |< inactive actions  ]
55545		//        a        s
55546		//         <-swap->
55547		//        s        a
55548
55549		const actions = this._actions,
55550			prevIndex = action._cacheIndex,
55551
55552			firstInactiveIndex = -- this._nActiveActions,
55553
55554			lastActiveAction = actions[ firstInactiveIndex ];
55555
55556		action._cacheIndex = firstInactiveIndex;
55557		actions[ firstInactiveIndex ] = action;
55558
55559		lastActiveAction._cacheIndex = prevIndex;
55560		actions[ prevIndex ] = lastActiveAction;
55561
55562	}
55563
55564	// Memory management for PropertyMixer objects
55565
55566	_addInactiveBinding( binding, rootUuid, trackName ) {
55567
55568		const bindingsByRoot = this._bindingsByRootAndName,
55569			bindings = this._bindings;
55570
55571		let bindingByName = bindingsByRoot[ rootUuid ];
55572
55573		if ( bindingByName === undefined ) {
55574
55575			bindingByName = {};
55576			bindingsByRoot[ rootUuid ] = bindingByName;
55577
55578		}
55579
55580		bindingByName[ trackName ] = binding;
55581
55582		binding._cacheIndex = bindings.length;
55583		bindings.push( binding );
55584
55585	}
55586
55587	_removeInactiveBinding( binding ) {
55588
55589		const bindings = this._bindings,
55590			propBinding = binding.binding,
55591			rootUuid = propBinding.rootNode.uuid,
55592			trackName = propBinding.path,
55593			bindingsByRoot = this._bindingsByRootAndName,
55594			bindingByName = bindingsByRoot[ rootUuid ],
55595
55596			lastInactiveBinding = bindings[ bindings.length - 1 ],
55597			cacheIndex = binding._cacheIndex;
55598
55599		lastInactiveBinding._cacheIndex = cacheIndex;
55600		bindings[ cacheIndex ] = lastInactiveBinding;
55601		bindings.pop();
55602
55603		delete bindingByName[ trackName ];
55604
55605		if ( Object.keys( bindingByName ).length === 0 ) {
55606
55607			delete bindingsByRoot[ rootUuid ];
55608
55609		}
55610
55611	}
55612
55613	_lendBinding( binding ) {
55614
55615		const bindings = this._bindings,
55616			prevIndex = binding._cacheIndex,
55617
55618			lastActiveIndex = this._nActiveBindings ++,
55619
55620			firstInactiveBinding = bindings[ lastActiveIndex ];
55621
55622		binding._cacheIndex = lastActiveIndex;
55623		bindings[ lastActiveIndex ] = binding;
55624
55625		firstInactiveBinding._cacheIndex = prevIndex;
55626		bindings[ prevIndex ] = firstInactiveBinding;
55627
55628	}
55629
55630	_takeBackBinding( binding ) {
55631
55632		const bindings = this._bindings,
55633			prevIndex = binding._cacheIndex,
55634
55635			firstInactiveIndex = -- this._nActiveBindings,
55636
55637			lastActiveBinding = bindings[ firstInactiveIndex ];
55638
55639		binding._cacheIndex = firstInactiveIndex;
55640		bindings[ firstInactiveIndex ] = binding;
55641
55642		lastActiveBinding._cacheIndex = prevIndex;
55643		bindings[ prevIndex ] = lastActiveBinding;
55644
55645	}
55646
55647
55648	// Memory management of Interpolants for weight and time scale
55649
55650	_lendControlInterpolant() {
55651
55652		const interpolants = this._controlInterpolants,
55653			lastActiveIndex = this._nActiveControlInterpolants ++;
55654
55655		let interpolant = interpolants[ lastActiveIndex ];
55656
55657		if ( interpolant === undefined ) {
55658
55659			interpolant = new LinearInterpolant(
55660				new Float32Array( 2 ), new Float32Array( 2 ),
55661				1, _controlInterpolantsResultBuffer );
55662
55663			interpolant.__cacheIndex = lastActiveIndex;
55664			interpolants[ lastActiveIndex ] = interpolant;
55665
55666		}
55667
55668		return interpolant;
55669
55670	}
55671
55672	_takeBackControlInterpolant( interpolant ) {
55673
55674		const interpolants = this._controlInterpolants,
55675			prevIndex = interpolant.__cacheIndex,
55676
55677			firstInactiveIndex = -- this._nActiveControlInterpolants,
55678
55679			lastActiveInterpolant = interpolants[ firstInactiveIndex ];
55680
55681		interpolant.__cacheIndex = firstInactiveIndex;
55682		interpolants[ firstInactiveIndex ] = interpolant;
55683
55684		lastActiveInterpolant.__cacheIndex = prevIndex;
55685		interpolants[ prevIndex ] = lastActiveInterpolant;
55686
55687	}
55688
55689	/**
55690	 * Returns an instance of {@link AnimationAction} for the passed clip.
55691	 *
55692	 * If an action fitting the clip and root parameters doesn't yet exist, it
55693	 * will be created by this method. Calling this method several times with the
55694	 * same clip and root parameters always returns the same action.
55695	 *
55696	 * @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
55697	 * @param {Object3D} [optionalRoot] - An alternative root object.
55698	 * @param {(NormalAnimationBlendMode|AdditiveAnimationBlendMode)} [blendMode] - The blend mode.
55699	 * @return {?AnimationAction} The animation action.
55700	 */
55701	clipAction( clip, optionalRoot, blendMode ) {
55702
55703		const root = optionalRoot || this._root,
55704			rootUuid = root.uuid;
55705
55706		let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
55707
55708		const clipUuid = clipObject !== null ? clipObject.uuid : clip;
55709
55710		const actionsForClip = this._actionsByClip[ clipUuid ];
55711		let prototypeAction = null;
55712
55713		if ( blendMode === undefined ) {
55714
55715			if ( clipObject !== null ) {
55716
55717				blendMode = clipObject.blendMode;
55718
55719			} else {
55720
55721				blendMode = NormalAnimationBlendMode;
55722
55723			}
55724
55725		}
55726
55727		if ( actionsForClip !== undefined ) {
55728
55729			const existingAction = actionsForClip.actionByRoot[ rootUuid ];
55730
55731			if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
55732
55733				return existingAction;
55734
55735			}
55736
55737			// we know the clip, so we don't have to parse all
55738			// the bindings again but can just copy
55739			prototypeAction = actionsForClip.knownActions[ 0 ];
55740
55741			// also, take the clip from the prototype action
55742			if ( clipObject === null )
55743				clipObject = prototypeAction._clip;
55744
55745		}
55746
55747		// clip must be known when specified via string
55748		if ( clipObject === null ) return null;
55749
55750		// allocate all resources required to run it
55751		const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
55752
55753		this._bindAction( newAction, prototypeAction );
55754
55755		// and make the action known to the memory manager
55756		this._addInactiveAction( newAction, clipUuid, rootUuid );
55757
55758		return newAction;
55759
55760	}
55761
55762	/**
55763	 * Returns an existing animation action for the passed clip.
55764	 *
55765	 * @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
55766	 * @param {Object3D} [optionalRoot] - An alternative root object.
55767	 * @return {?AnimationAction} The animation action. Returns `null` if no action was found.
55768	 */
55769	existingAction( clip, optionalRoot ) {
55770
55771		const root = optionalRoot || this._root,
55772			rootUuid = root.uuid,
55773
55774			clipObject = typeof clip === 'string' ?
55775				AnimationClip.findByName( root, clip ) : clip,
55776
55777			clipUuid = clipObject ? clipObject.uuid : clip,
55778
55779			actionsForClip = this._actionsByClip[ clipUuid ];
55780
55781		if ( actionsForClip !== undefined ) {
55782
55783			return actionsForClip.actionByRoot[ rootUuid ] || null;
55784
55785		}
55786
55787		return null;
55788
55789	}
55790
55791	/**
55792	 * Deactivates all previously scheduled actions on this mixer.
55793	 *
55794	 * @return {AnimationMixer} A reference to this animation mixer.
55795	 */
55796	stopAllAction() {
55797
55798		const actions = this._actions,
55799			nActions = this._nActiveActions;
55800
55801		for ( let i = nActions - 1; i >= 0; -- i ) {
55802
55803			actions[ i ].stop();
55804
55805		}
55806
55807		return this;
55808
55809	}
55810
55811	/**
55812	 * Advances the global mixer time and updates the animation.
55813	 *
55814	 * This is usually done in the render loop by passing the delta
55815	 * time from {@link Clock} or {@link Timer}.
55816	 *
55817	 * @param {number} deltaTime - The delta time in seconds.
55818	 * @return {AnimationMixer} A reference to this animation mixer.
55819	 */
55820	update( deltaTime ) {
55821
55822		deltaTime *= this.timeScale;
55823
55824		const actions = this._actions,
55825			nActions = this._nActiveActions,
55826
55827			time = this.time += deltaTime,
55828			timeDirection = Math.sign( deltaTime ),
55829
55830			accuIndex = this._accuIndex ^= 1;
55831
55832		// run active actions
55833
55834		for ( let i = 0; i !== nActions; ++ i ) {
55835
55836			const action = actions[ i ];
55837
55838			action._update( time, deltaTime, timeDirection, accuIndex );
55839
55840		}
55841
55842		// update scene graph
55843
55844		const bindings = this._bindings,
55845			nBindings = this._nActiveBindings;
55846
55847		for ( let i = 0; i !== nBindings; ++ i ) {
55848
55849			bindings[ i ].apply( accuIndex );
55850
55851		}
55852
55853		return this;
55854
55855	}
55856
55857	/**
55858	 * Sets the global mixer to a specific time and updates the animation accordingly.
55859	 *
55860	 * This is useful when you need to jump to an exact time in an animation. The
55861	 * input parameter will be scaled by {@link AnimationMixer#timeScale}
55862	 *
55863	 * @param {number} time - The time to set in seconds.
55864	 * @return {AnimationMixer} A reference to this animation mixer.
55865	 */
55866	setTime( time ) {
55867
55868		this.time = 0; // Zero out time attribute for AnimationMixer object;
55869		for ( let i = 0; i < this._actions.length; i ++ ) {
55870
55871			this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
55872
55873		}
55874
55875		return this.update( time ); // Update used to set exact time. Returns "this" AnimationMixer object.
55876
55877	}
55878
55879	/**
55880	 * Returns this mixer's root object.
55881	 *
55882	 * @return {Object3D} The mixer's root object.
55883	 */
55884	getRoot() {
55885
55886		return this._root;
55887
55888	}
55889
55890	/**
55891	 * Deallocates all memory resources for a clip. Before using this method make
55892	 * sure to call {@link AnimationAction#stop} for all related actions.
55893	 *
55894	 * @param {AnimationClip} clip - The clip to uncache.
55895	 */
55896	uncacheClip( clip ) {
55897
55898		const actions = this._actions,
55899			clipUuid = clip.uuid,
55900			actionsByClip = this._actionsByClip,
55901			actionsForClip = actionsByClip[ clipUuid ];
55902
55903		if ( actionsForClip !== undefined ) {
55904
55905			// note: just calling _removeInactiveAction would mess up the
55906			// iteration state and also require updating the state we can
55907			// just throw away
55908
55909			const actionsToRemove = actionsForClip.knownActions;
55910
55911			for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
55912
55913				const action = actionsToRemove[ i ];
55914
55915				this._deactivateAction( action );
55916
55917				const cacheIndex = action._cacheIndex,
55918					lastInactiveAction = actions[ actions.length - 1 ];
55919
55920				action._cacheIndex = null;
55921				action._byClipCacheIndex = null;
55922
55923				lastInactiveAction._cacheIndex = cacheIndex;
55924				actions[ cacheIndex ] = lastInactiveAction;
55925				actions.pop();
55926
55927				this._removeInactiveBindingsForAction( action );
55928
55929			}
55930
55931			delete actionsByClip[ clipUuid ];
55932
55933		}
55934
55935	}
55936
55937	/**
55938	 * Deallocates all memory resources for a root object. Before using this
55939	 * method make sure to call {@link AnimationAction#stop} for all related
55940	 * actions or alternatively {@link AnimationMixer#stopAllAction} when the
55941	 * mixer operates on a single root.
55942	 *
55943	 * @param {Object3D} root - The root object to uncache.
55944	 */
55945	uncacheRoot( root ) {
55946
55947		const rootUuid = root.uuid,
55948			actionsByClip = this._actionsByClip;
55949
55950		for ( const clipUuid in actionsByClip ) {
55951
55952			const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
55953				action = actionByRoot[ rootUuid ];
55954
55955			if ( action !== undefined ) {
55956
55957				this._deactivateAction( action );
55958				this._removeInactiveAction( action );
55959
55960			}
55961
55962		}
55963
55964		const bindingsByRoot = this._bindingsByRootAndName,
55965			bindingByName = bindingsByRoot[ rootUuid ];
55966
55967		if ( bindingByName !== undefined ) {
55968
55969			for ( const trackName in bindingByName ) {
55970
55971				const binding = bindingByName[ trackName ];
55972				binding.restoreOriginalState();
55973				this._removeInactiveBinding( binding );
55974
55975			}
55976
55977		}
55978
55979	}
55980
55981	/**
55982	 * Deallocates all memory resources for an action. The action is identified by the
55983	 * given clip and an optional root object. Before using this method make
55984	 * sure to call {@link AnimationAction#stop} to deactivate the action.
55985	 *
55986	 * @param {AnimationClip|string} clip - An animation clip or alternatively the name of the animation clip.
55987	 * @param {Object3D} [optionalRoot] - An alternative root object.
55988	 */
55989	uncacheAction( clip, optionalRoot ) {
55990
55991		const action = this.existingAction( clip, optionalRoot );
55992
55993		if ( action !== null ) {
55994
55995			this._deactivateAction( action );
55996			this._removeInactiveAction( action );
55997
55998		}
55999
56000	}
56001
56002}
56003
56004/**
56005 * Represents a 3D render target.
56006 *
56007 * @augments RenderTarget
56008 */
56009class RenderTarget3D extends RenderTarget {
56010
56011	/**
56012	 * Constructs a new 3D render target.
56013	 *
56014	 * @param {number} [width=1] - The width of the render target.
56015	 * @param {number} [height=1] - The height of the render target.
56016	 * @param {number} [depth=1] - The height of the render target.
56017	 * @param {RenderTarget~Options} [options] - The configuration object.
56018	 */
56019	constructor( width = 1, height = 1, depth = 1, options = {} ) {
56020
56021		super( width, height, options );
56022
56023		/**
56024		 * This flag can be used for type testing.
56025		 *
56026		 * @type {boolean}
56027		 * @readonly
56028		 * @default true
56029		 */
56030		this.isRenderTarget3D = true;
56031
56032		this.depth = depth;
56033
56034		// overwrite attachments with 3D textures
56035
56036		for ( let i = 0; i < this.textures.length; i ++ ) {
56037
56038			const texture = new Data3DTexture( null, width, height, depth );
56039			texture.isRenderTargetTexture = true;
56040			texture.renderTarget = this;
56041
56042			this.textures[ i ] = texture;
56043
56044		}
56045
56046		this._setTextureOptions( options );
56047
56048	}
56049
56050}
56051
56052/**
56053 * Represents a uniform which is a global shader variable. They are passed to shader programs.
56054 *
56055 * When declaring a uniform of a {@link ShaderMaterial}, it is declared by value or by object.
56056 * ```js
56057 * uniforms: {
56058 * 	time: { value: 1.0 },
56059 * 	resolution: new Uniform( new Vector2() )
56060 * };
56061 * ```
56062 * Since this class can only be used in context of {@link ShaderMaterial}, it is only supported
56063 * in {@link WebGLRenderer}.
56064 */
56065class Uniform {
56066
56067	/**
56068	 * Constructs a new uniform.
56069	 *
56070	 * @param {any} value - The uniform value.
56071	 */
56072	constructor( value ) {
56073
56074		/**
56075		 * The uniform value.
56076		 *
56077		 * @type {any}
56078		 */
56079		this.value = value;
56080
56081	}
56082
56083	/**
56084	 * Returns a new uniform with copied values from this instance.
56085	 * If the value has a `clone()` method, the value is cloned as well.
56086	 *
56087	 * @return {Uniform} A clone of this instance.
56088	 */
56089	clone() {
56090
56091		return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
56092
56093	}
56094
56095}
56096
56097let _id = 0;
56098
56099/**
56100 * A class for managing multiple uniforms in a single group. The renderer will process
56101 * such a definition as a single UBO.
56102 *
56103 * Since this class can only be used in context of {@link ShaderMaterial}, it is only supported
56104 * in {@link WebGLRenderer}.
56105 *
56106 * @augments EventDispatcher
56107 */
56108class UniformsGroup extends EventDispatcher {
56109
56110	/**
56111	 * Constructs a new uniforms group.
56112	 */
56113	constructor() {
56114
56115		super();
56116
56117		/**
56118		 * This flag can be used for type testing.
56119		 *
56120		 * @type {boolean}
56121		 * @readonly
56122		 * @default true
56123		 */
56124		this.isUniformsGroup = true;
56125
56126		/**
56127		 * The ID of the 3D object.
56128		 *
56129		 * @name UniformsGroup#id
56130		 * @type {number}
56131		 * @readonly
56132		 */
56133		Object.defineProperty( this, 'id', { value: _id ++ } );
56134
56135		/**
56136		 * The name of the uniforms group.
56137		 *
56138		 * @type {string}
56139		 */
56140		this.name = '';
56141
56142		/**
56143		 * The buffer usage.
56144		 *
56145		 * @type {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)}
56146		 * @default StaticDrawUsage
56147		 */
56148		this.usage = StaticDrawUsage;
56149
56150		/**
56151		 * An array holding the uniforms.
56152		 *
56153		 * @type {Array<Uniform>}
56154		 */
56155		this.uniforms = [];
56156
56157	}
56158
56159	/**
56160	 * Adds the given uniform to this uniforms group.
56161	 *
56162	 * @param {Uniform} uniform - The uniform to add.
56163	 * @return {UniformsGroup} A reference to this uniforms group.
56164	 */
56165	add( uniform ) {
56166
56167		this.uniforms.push( uniform );
56168
56169		return this;
56170
56171	}
56172
56173	/**
56174	 * Removes the given uniform from this uniforms group.
56175	 *
56176	 * @param {Uniform} uniform - The uniform to remove.
56177	 * @return {UniformsGroup} A reference to this uniforms group.
56178	 */
56179	remove( uniform ) {
56180
56181		const index = this.uniforms.indexOf( uniform );
56182
56183		if ( index !== -1 ) this.uniforms.splice( index, 1 );
56184
56185		return this;
56186
56187	}
56188
56189	/**
56190	 * Sets the name of this uniforms group.
56191	 *
56192	 * @param {string} name - The name to set.
56193	 * @return {UniformsGroup} A reference to this uniforms group.
56194	 */
56195	setName( name ) {
56196
56197		this.name = name;
56198
56199		return this;
56200
56201	}
56202
56203	/**
56204	 * Sets the usage of this uniforms group.
56205	 *
56206	 * @param {(StaticDrawUsage|DynamicDrawUsage|StreamDrawUsage|StaticReadUsage|DynamicReadUsage|StreamReadUsage|StaticCopyUsage|DynamicCopyUsage|StreamCopyUsage)} value - The usage to set.
56207	 * @return {UniformsGroup} A reference to this uniforms group.
56208	 */
56209	setUsage( value ) {
56210
56211		this.usage = value;
56212
56213		return this;
56214
56215	}
56216
56217	/**
56218	 * Frees the GPU-related resources allocated by this instance. Call this
56219	 * method whenever this instance is no longer used in your app.
56220	 *
56221	 * @fires Texture#dispose
56222	 */
56223	dispose() {
56224
56225		this.dispatchEvent( { type: 'dispose' } );
56226
56227	}
56228
56229	/**
56230	 * Copies the values of the given uniforms group to this instance.
56231	 *
56232	 * @param {UniformsGroup} source - The uniforms group to copy.
56233	 * @return {UniformsGroup} A reference to this uniforms group.
56234	 */
56235	copy( source ) {
56236
56237		this.name = source.name;
56238		this.usage = source.usage;
56239
56240		const uniformsSource = source.uniforms;
56241
56242		this.uniforms.length = 0;
56243
56244		for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) {
56245
56246			const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ];
56247
56248			for ( let j = 0; j < uniforms.length; j ++ ) {
56249
56250				this.uniforms.push( uniforms[ j ].clone() );
56251
56252			}
56253
56254		}
56255
56256		return this;
56257
56258	}
56259
56260	/**
56261	 * Returns a new uniforms group with copied values from this instance.
56262	 *
56263	 * @return {UniformsGroup} A clone of this instance.
56264	 */
56265	clone() {
56266
56267		return new this.constructor().copy( this );
56268
56269	}
56270
56271}
56272
56273/**
56274 * An instanced version of an interleaved buffer.
56275 *
56276 * @augments InterleavedBuffer
56277 */
56278class InstancedInterleavedBuffer extends InterleavedBuffer {
56279
56280	/**
56281	 * Constructs a new instanced interleaved buffer.
56282	 *
56283	 * @param {TypedArray} array - A typed array with a shared buffer storing attribute data.
56284	 * @param {number} stride - The number of typed-array elements per vertex.
56285	 * @param {number} [meshPerAttribute=1] - Defines how often a value of this interleaved buffer should be repeated.
56286	 */
56287	constructor( array, stride, meshPerAttribute = 1 ) {
56288
56289		super( array, stride );
56290
56291		/**
56292		 * This flag can be used for type testing.
56293		 *
56294		 * @type {boolean}
56295		 * @readonly
56296		 * @default true
56297		 */
56298		this.isInstancedInterleavedBuffer = true;
56299
56300		/**
56301		 * Defines how often a value of this buffer attribute should be repeated,
56302		 * see {@link InstancedBufferAttribute#meshPerAttribute}.
56303		 *
56304		 * @type {number}
56305		 * @default 1
56306		 */
56307		this.meshPerAttribute = meshPerAttribute;
56308
56309	}
56310
56311	copy( source ) {
56312
56313		super.copy( source );
56314
56315		this.meshPerAttribute = source.meshPerAttribute;
56316
56317		return this;
56318
56319	}
56320
56321	clone( data ) {
56322
56323		const ib = super.clone( data );
56324
56325		ib.meshPerAttribute = this.meshPerAttribute;
56326
56327		return ib;
56328
56329	}
56330
56331	toJSON( data ) {
56332
56333		const json = super.toJSON( data );
56334
56335		json.isInstancedInterleavedBuffer = true;
56336		json.meshPerAttribute = this.meshPerAttribute;
56337
56338		return json;
56339
56340	}
56341
56342}
56343
56344/**
56345 * An alternative version of a buffer attribute with more control over the VBO.
56346 *
56347 * The renderer does not construct a VBO for this kind of attribute. Instead, it uses
56348 * whatever VBO is passed in constructor and can later be altered via the `buffer` property.
56349 *
56350 * The most common use case for this class is when some kind of GPGPU calculation interferes
56351 * or even produces the VBOs in question.
56352 *
56353 * Notice that this class can only be used with {@link WebGLRenderer}.
56354 */
56355class GLBufferAttribute {
56356
56357	/**
56358	 * Constructs a new GL buffer attribute.
56359	 *
56360	 * @param {WebGLBuffer} buffer - The native WebGL buffer.
56361	 * @param {number} type - The native data type (e.g. `gl.FLOAT`).
56362	 * @param {number} itemSize - The item size.
56363	 * @param {number} elementSize - The corresponding size (in bytes) for the given `type` parameter.
56364	 * @param {number} count - The expected number of vertices in VBO.
56365	 * @param {boolean} [normalized=false] - Whether the data are normalized or not.
56366	 */
56367	constructor( buffer, type, itemSize, elementSize, count, normalized = false ) {
56368
56369		/**
56370		 * This flag can be used for type testing.
56371		 *
56372		 * @type {boolean}
56373		 * @readonly
56374		 * @default true
56375		 */
56376		this.isGLBufferAttribute = true;
56377
56378		/**
56379		 * The name of the buffer attribute.
56380		 *
56381		 * @type {string}
56382		 */
56383		this.name = '';
56384
56385		/**
56386		 * The native WebGL buffer.
56387		 *
56388		 * @type {WebGLBuffer}
56389		 */
56390		this.buffer = buffer;
56391
56392		/**
56393		 * The native data type.
56394		 *
56395		 * @type {number}
56396		 */
56397		this.type = type;
56398
56399		/**
56400		 * The item size, see {@link BufferAttribute#itemSize}.
56401		 *
56402		 * @type {number}
56403		 */
56404		this.itemSize = itemSize;
56405
56406		/**
56407		 * The corresponding size (in bytes) for the given `type` parameter.
56408		 *
56409		 * @type {number}
56410		 */
56411		this.elementSize = elementSize;
56412
56413		/**
56414		 * The expected number of vertices in VBO.
56415		 *
56416		 * @type {number}
56417		 */
56418		this.count = count;
56419
56420		/**
56421		 * Applies to integer data only. Indicates how the underlying data in the buffer maps to
56422		 * the values in the GLSL code. For instance, if `buffer` contains data of `gl.UNSIGNED_SHORT`,
56423		 * and `normalized` is `true`, the values `0 - +65535` in the buffer data will be mapped to
56424		 * `0.0f - +1.0f` in the GLSL attribute. If `normalized` is `false`, the values will be converted
56425		 * to floats unmodified, i.e. `65535` becomes `65535.0f`.
56426		 *
56427		 * @type {boolean}
56428		 */
56429		this.normalized = normalized;
56430
56431		/**
56432		 * A version number, incremented every time the `needsUpdate` is set to `true`.
56433		 *
56434		 * @type {number}
56435		 */
56436		this.version = 0;
56437
56438	}
56439
56440	/**
56441	 * Flag to indicate that this attribute has changed and should be re-sent to
56442	 * the GPU. Set this to `true` when you modify the value of the array.
56443	 *
56444	 * @type {number}
56445	 * @default false
56446	 * @param {boolean} value
56447	 */
56448	set needsUpdate( value ) {
56449
56450		if ( value === true ) this.version ++;
56451
56452	}
56453
56454	/**
56455	 * Sets the given native WebGL buffer.
56456	 *
56457	 * @param {WebGLBuffer} buffer - The buffer to set.
56458	 * @return {BufferAttribute} A reference to this instance.
56459	 */
56460	setBuffer( buffer ) {
56461
56462		this.buffer = buffer;
56463
56464		return this;
56465
56466	}
56467
56468	/**
56469	 * Sets the given native data type and element size.
56470	 *
56471	 * @param {number} type - The native data type (e.g. `gl.FLOAT`).
56472	 * @param {number} elementSize - The corresponding size (in bytes) for the given `type` parameter.
56473	 * @return {BufferAttribute} A reference to this instance.
56474	 */
56475	setType( type, elementSize ) {
56476
56477		this.type = type;
56478		this.elementSize = elementSize;
56479
56480		return this;
56481
56482	}
56483
56484	/**
56485	 * Sets the item size.
56486	 *
56487	 * @param {number} itemSize - The item size.
56488	 * @return {BufferAttribute} A reference to this instance.
56489	 */
56490	setItemSize( itemSize ) {
56491
56492		this.itemSize = itemSize;
56493
56494		return this;
56495
56496	}
56497
56498	/**
56499	 * Sets the count (the expected number of vertices in VBO).
56500	 *
56501	 * @param {number} count - The count.
56502	 * @return {BufferAttribute} A reference to this instance.
56503	 */
56504	setCount( count ) {
56505
56506		this.count = count;
56507
56508		return this;
56509
56510	}
56511
56512}
56513
56514const _matrix = /*@__PURE__*/ new Matrix4();
56515
56516/**
56517 * This class is designed to assist with raycasting. Raycasting is used for
56518 * mouse picking (working out what objects in the 3d space the mouse is over)
56519 * amongst other things.
56520 */
56521class Raycaster {
56522
56523	/**
56524	 * Constructs a new raycaster.
56525	 *
56526	 * @param {Vector3} origin - The origin vector where the ray casts from.
56527	 * @param {Vector3} direction - The (normalized) direction vector that gives direction to the ray.
56528	 * @param {number} [near=0] - All results returned are further away than near. Near can't be negative.
56529	 * @param {number} [far=Infinity] - All results returned are closer than far. Far can't be lower than near.
56530	 */
56531	constructor( origin, direction, near = 0, far = Infinity ) {
56532
56533		/**
56534		 * The ray used for raycasting.
56535		 *
56536		 * @type {Ray}
56537		 */
56538		this.ray = new Ray( origin, direction );
56539
56540		/**
56541		 * All results returned are further away than near. Near can't be negative.
56542		 *
56543		 * @type {number}
56544		 * @default 0
56545		 */
56546		this.near = near;
56547
56548		/**
56549		 * All results returned are closer than far. Far can't be lower than near.
56550		 *
56551		 * @type {number}
56552		 * @default Infinity
56553		 */
56554		this.far = far;
56555
56556		/**
56557		 * The camera to use when raycasting against view-dependent objects such as
56558		 * billboarded objects like sprites. This field can be set manually or
56559		 * is set when calling `setFromCamera()`.
56560		 *
56561		 * @type {?Camera}
56562		 * @default null
56563		 */
56564		this.camera = null;
56565
56566		/**
56567		 * Allows to selectively ignore 3D objects when performing intersection tests.
56568		 * The following code example ensures that only 3D objects on layer `1` will be
56569		 * honored by raycaster.
56570		 * ```js
56571		 * raycaster.layers.set( 1 );
56572		 * object.layers.enable( 1 );
56573		 * ```
56574		 *
56575		 * @type {Layers}
56576		 */
56577		this.layers = new Layers();
56578
56579
56580		/**
56581		 * A parameter object that configures the raycasting. It has the structure:
56582		 *
56583		 * ```
56584		 * {
56585		 * 	Mesh: {},
56586		 * 	Line: { threshold: 1 },
56587		 * 	LOD: {},
56588		 * 	Points: { threshold: 1 },
56589		 * 	Sprite: {}
56590		 * }
56591		 * ```
56592		 * Where `threshold` is the precision of the raycaster when intersecting objects, in world units.
56593		 *
56594		 * @type {Object}
56595		 */
56596		this.params = {
56597			Mesh: {},
56598			Line: { threshold: 1 },
56599			LOD: {},
56600			Points: { threshold: 1 },
56601			Sprite: {}
56602		};
56603
56604	}
56605
56606	/**
56607	 * Updates the ray with a new origin and direction by copying the values from the arguments.
56608	 *
56609	 * @param {Vector3} origin - The origin vector where the ray casts from.
56610	 * @param {Vector3} direction - The (normalized) direction vector that gives direction to the ray.
56611	 */
56612	set( origin, direction ) {
56613
56614		// direction is assumed to be normalized (for accurate distance calculations)
56615
56616		this.ray.set( origin, direction );
56617
56618	}
56619
56620	/**
56621	 * Uses the given coordinates and camera to compute a new origin and direction for the internal ray.
56622	 *
56623	 * @param {Vector2} coords - 2D coordinates of the mouse, in normalized device coordinates (NDC).
56624	 * X and Y components should be between `-1` and `1`.
56625	 * @param {Camera} camera - The camera from which the ray should originate.
56626	 */
56627	setFromCamera( coords, camera ) {
56628
56629		if ( camera.isPerspectiveCamera ) {
56630
56631			this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
56632			this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
56633			this.camera = camera;
56634
56635		} else if ( camera.isOrthographicCamera ) {
56636
56637			this.ray.origin.set( coords.x, coords.y, camera.projectionMatrix.elements[ 14 ] ).unproject( camera ); // set origin in plane of camera
56638			this.ray.direction.set( 0, 0, -1 ).transformDirection( camera.matrixWorld );
56639			this.camera = camera;
56640
56641		} else {
56642
56643			error( 'Raycaster: Unsupported camera type: ' + camera.type );
56644
56645		}
56646
56647	}
56648
56649	/**
56650	 * Uses the given WebXR controller to compute a new origin and direction for the internal ray.
56651	 *
56652	 * @param {WebXRController} controller - The controller to copy the position and direction from.
56653	 * @return {Raycaster} A reference to this raycaster.
56654	 */
56655	setFromXRController( controller ) {
56656
56657		_matrix.identity().extractRotation( controller.matrixWorld );
56658
56659		this.ray.origin.setFromMatrixPosition( controller.matrixWorld );
56660		this.ray.direction.set( 0, 0, -1 ).applyMatrix4( _matrix );
56661
56662		return this;
56663
56664	}
56665
56666	/**
56667	 * The intersection point of a raycaster intersection test.
56668	 * @typedef {Object} Raycaster~Intersection
56669	 * @property {number} distance - The distance from the ray's origin to the intersection point.
56670	 * @property {number} distanceToRay -  Some 3D objects e.g. {@link Points} provide the distance of the
56671	 * intersection to the nearest point on the ray. For other objects it will be `undefined`.
56672	 * @property {Vector3} point - The intersection point, in world coordinates.
56673	 * @property {Object} face - The face that has been intersected.
56674	 * @property {number} faceIndex - The face index.
56675	 * @property {Object3D} object - The 3D object that has been intersected.
56676	 * @property {Vector2} uv - U,V coordinates at point of intersection.
56677	 * @property {Vector2} uv1 - Second set of U,V coordinates at point of intersection.
56678	 * @property {Vector3} normal - Interpolated normal vector at point of intersection.
56679	 * @property {number} instanceId - The index number of the instance where the ray
56680	 * intersects the {@link InstancedMesh}.
56681	 */
56682
56683	/**
56684	 * Checks all intersection between the ray and the object with or without the
56685	 * descendants. Intersections are returned sorted by distance, closest first.
56686	 *
56687	 * `Raycaster` delegates to the `raycast()` method of the passed 3D object, when
56688	 * evaluating whether the ray intersects the object or not. This allows meshes to respond
56689	 * differently to ray casting than lines or points.
56690	 *
56691	 * Note that for meshes, faces must be pointed towards the origin of the ray in order
56692	 * to be detected; intersections of the ray passing through the back of a face will not
56693	 * be detected. To raycast against both faces of an object, you'll want to set  {@link Material#side}
56694	 * to `THREE.DoubleSide`.
56695	 *
56696	 * Note that a ray hitting a triangle mesh exactly along an edge shared by two faces may be
56697	 * reported by both faces, resulting in two coincident intersections (identical point and
56698	 * distance) in the returned array.
56699	 *
56700	 * @param {Object3D} object - The 3D object to check for intersection with the ray.
56701	 * @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
56702	 * Otherwise it only checks intersection with the object.
56703	 * @param {Array<Raycaster~Intersection>} [intersects=[]] The target array that holds the result of the method.
56704	 * @return {Array<Raycaster~Intersection>} An array holding the intersection points.
56705	 */
56706	intersectObject( object, recursive = true, intersects = [] ) {
56707
56708		intersect( object, this, intersects, recursive );
56709
56710		intersects.sort( ascSort );
56711
56712		return intersects;
56713
56714	}
56715
56716	/**
56717	 * Checks all intersection between the ray and the objects with or without
56718	 * the descendants. Intersections are returned sorted by distance, closest first.
56719	 *
56720	 * @param {Array<Object3D>} objects - The 3D objects to check for intersection with the ray.
56721	 * @param {boolean} [recursive=true] - If set to `true`, it also checks all descendants.
56722	 * Otherwise it only checks intersection with the object.
56723	 * @param {Array<Raycaster~Intersection>} [intersects=[]] The target array that holds the result of the method.
56724	 * @return {Array<Raycaster~Intersection>} An array holding the intersection points.
56725	 */
56726	intersectObjects( objects, recursive = true, intersects = [] ) {
56727
56728		for ( let i = 0, l = objects.length; i < l; i ++ ) {
56729
56730			intersect( objects[ i ], this, intersects, recursive );
56731
56732		}
56733
56734		intersects.sort( ascSort );
56735
56736		return intersects;
56737
56738	}
56739
56740}
56741
56742function ascSort( a, b ) {
56743
56744	return a.distance - b.distance;
56745
56746}
56747
56748function intersect( object, raycaster, intersects, recursive ) {
56749
56750	let propagate = true;
56751
56752	if ( object.layers.test( raycaster.layers ) ) {
56753
56754		const result = object.raycast( raycaster, intersects );
56755
56756		if ( result === false ) propagate = false;
56757
56758	}
56759
56760	if ( propagate === true && recursive === true ) {
56761
56762		const children = object.children;
56763
56764		for ( let i = 0, l = children.length; i < l; i ++ ) {
56765
56766			intersect( children[ i ], raycaster, intersects, true );
56767
56768		}
56769
56770	}
56771
56772}
56773
56774/**
56775 * Class for keeping track of time.
56776 *
56777 * @deprecated since r183.
56778 */
56779class Clock {
56780
56781	/**
56782	 * Constructs a new clock.
56783	 *
56784	 * @deprecated since 183.
56785	 * @param {boolean} [autoStart=true] - Whether to automatically start the clock when
56786	 * `getDelta()` is called for the first time.
56787	 */
56788	constructor( autoStart = true ) {
56789
56790		/**
56791		 * If set to `true`, the clock starts automatically when `getDelta()` is called
56792		 * for the first time.
56793		 *
56794		 * @type {boolean}
56795		 * @default true
56796		 */
56797		this.autoStart = autoStart;
56798
56799		/**
56800		 * Holds the time at which the clock's `start()` method was last called.
56801		 *
56802		 * @type {number}
56803		 * @default 0
56804		 */
56805		this.startTime = 0;
56806
56807		/**
56808		 * Holds the time at which the clock's `start()`, `getElapsedTime()` or
56809		 * `getDelta()` methods were last called.
56810		 *
56811		 * @type {number}
56812		 * @default 0
56813		 */
56814		this.oldTime = 0;
56815
56816		/**
56817		 * Keeps track of the total time that the clock has been running.
56818		 *
56819		 * @type {number}
56820		 * @default 0
56821		 */
56822		this.elapsedTime = 0;
56823
56824		/**
56825		 * Whether the clock is running or not.
56826		 *
56827		 * @type {boolean}
56828		 * @default true
56829		 */
56830		this.running = false;
56831
56832		warn( 'Clock: This module has been deprecated. Please use THREE.Timer instead.' ); // @deprecated, r183
56833
56834	}
56835
56836	/**
56837	 * Starts the clock. When `autoStart` is set to `true`, the method is automatically
56838	 * called by the class.
56839	 */
56840	start() {
56841
56842		this.startTime = performance.now();
56843
56844		this.oldTime = this.startTime;
56845		this.elapsedTime = 0;
56846		this.running = true;
56847
56848	}
56849
56850	/**
56851	 * Stops the clock.
56852	 */
56853	stop() {
56854
56855		this.getElapsedTime();
56856		this.running = false;
56857		this.autoStart = false;
56858
56859	}
56860
56861	/**
56862	 * Returns the elapsed time in seconds.
56863	 *
56864	 * @return {number} The elapsed time.
56865	 */
56866	getElapsedTime() {
56867
56868		this.getDelta();
56869		return this.elapsedTime;
56870
56871	}
56872
56873	/**
56874	 * Returns the delta time in seconds.
56875	 *
56876	 * @return {number} The delta time.
56877	 */
56878	getDelta() {
56879
56880		let diff = 0;
56881
56882		if ( this.autoStart && ! this.running ) {
56883
56884			this.start();
56885			return 0;
56886
56887		}
56888
56889		if ( this.running ) {
56890
56891			const newTime = performance.now();
56892
56893			diff = ( newTime - this.oldTime ) / 1000;
56894			this.oldTime = newTime;
56895
56896			this.elapsedTime += diff;
56897
56898		}
56899
56900		return diff;
56901
56902	}
56903
56904}
56905
56906/**
56907 * This class can be used to represent points in 3D space as
56908 * [Spherical coordinates](https://en.wikipedia.org/wiki/Spherical_coordinate_system).
56909 */
56910class Spherical {
56911
56912	/**
56913	 * Constructs a new spherical.
56914	 *
56915	 * @param {number} [radius=1] - The radius, or the Euclidean distance (straight-line distance) from the point to the origin.
56916	 * @param {number} [phi=0] - The polar angle in radians from the y (up) axis.
56917	 * @param {number} [theta=0] - The equator/azimuthal angle in radians around the y (up) axis.
56918	 */
56919	constructor( radius = 1, phi = 0, theta = 0 ) {
56920
56921		/**
56922		 * The radius, or the Euclidean distance (straight-line distance) from the point to the origin.
56923		 *
56924		 * @type {number}
56925		 * @default 1
56926		 */
56927		this.radius = radius;
56928
56929		/**
56930		 * The polar angle in radians from the y (up) axis.
56931		 *
56932		 * @type {number}
56933		 * @default 0
56934		 */
56935		this.phi = phi;
56936
56937		/**
56938		 * The equator/azimuthal angle in radians around the y (up) axis.
56939		 *
56940		 * @type {number}
56941		 * @default 0
56942		 */
56943		this.theta = theta;
56944
56945	}
56946
56947	/**
56948	 * Sets the spherical components by copying the given values.
56949	 *
56950	 * @param {number} radius - The radius.
56951	 * @param {number} phi - The polar angle.
56952	 * @param {number} theta - The azimuthal angle.
56953	 * @return {Spherical} A reference to this spherical.
56954	 */
56955	set( radius, phi, theta ) {
56956
56957		this.radius = radius;
56958		this.phi = phi;
56959		this.theta = theta;
56960
56961		return this;
56962
56963	}
56964
56965	/**
56966	 * Copies the values of the given spherical to this instance.
56967	 *
56968	 * @param {Spherical} other - The spherical to copy.
56969	 * @return {Spherical} A reference to this spherical.
56970	 */
56971	copy( other ) {
56972
56973		this.radius = other.radius;
56974		this.phi = other.phi;
56975		this.theta = other.theta;
56976
56977		return this;
56978
56979	}
56980
56981	/**
56982	 * Restricts the polar angle [page:.phi phi] to be between `0.000001` and pi -
56983	 * `0.000001`.
56984	 *
56985	 * @return {Spherical} A reference to this spherical.
56986	 */
56987	makeSafe() {
56988
56989		const EPS = 0.000001;
56990		this.phi = clamp( this.phi, EPS, Math.PI - EPS );
56991
56992		return this;
56993
56994	}
56995
56996	/**
56997	 * Sets the spherical components from the given vector which is assumed to hold
56998	 * Cartesian coordinates.
56999	 *
57000	 * @param {Vector3} v - The vector to set.
57001	 * @return {Spherical} A reference to this spherical.
57002	 */
57003	setFromVector3( v ) {
57004
57005		return this.setFromCartesianCoords( v.x, v.y, v.z );
57006
57007	}
57008
57009	/**
57010	 * Sets the spherical components from the given Cartesian coordinates.
57011	 *
57012	 * @param {number} x - The x value.
57013	 * @param {number} y - The y value.
57014	 * @param {number} z - The z value.
57015	 * @return {Spherical} A reference to this spherical.
57016	 */
57017	setFromCartesianCoords( x, y, z ) {
57018
57019		this.radius = Math.sqrt( x * x + y * y + z * z );
57020
57021		if ( this.radius === 0 ) {
57022
57023			this.theta = 0;
57024			this.phi = 0;
57025
57026		} else {
57027
57028			this.theta = Math.atan2( x, z );
57029			this.phi = Math.acos( clamp( y / this.radius, -1, 1 ) );
57030
57031		}
57032
57033		return this;
57034
57035	}
57036
57037	/**
57038	 * Returns a new spherical with copied values from this instance.
57039	 *
57040	 * @return {Spherical} A clone of this instance.
57041	 */
57042	clone() {
57043
57044		return new this.constructor().copy( this );
57045
57046	}
57047
57048}
57049
57050/**
57051 * This class can be used to represent points in 3D space as
57052 * [Cylindrical coordinates](https://en.wikipedia.org/wiki/Cylindrical_coordinate_system).
57053 */
57054class Cylindrical {
57055
57056	/**
57057	 * Constructs a new cylindrical.
57058	 *
57059	 * @param {number} [radius=1] - The distance from the origin to a point in the x-z plane.
57060	 * @param {number} [theta=0] - A counterclockwise angle in the x-z plane measured in radians from the positive z-axis.
57061	 * @param {number} [y=0] - The height above the x-z plane.
57062	 */
57063	constructor( radius = 1, theta = 0, y = 0 ) {
57064
57065		/**
57066		 * The distance from the origin to a point in the x-z plane.
57067		 *
57068		 * @type {number}
57069		 * @default 1
57070		 */
57071		this.radius = radius;
57072
57073		/**
57074		 * A counterclockwise angle in the x-z plane measured in radians from the positive z-axis.
57075		 *
57076		 * @type {number}
57077		 * @default 0
57078		 */
57079		this.theta = theta;
57080
57081		/**
57082		 * The height above the x-z plane.
57083		 *
57084		 * @type {number}
57085		 * @default 0
57086		 */
57087		this.y = y;
57088
57089	}
57090
57091	/**
57092	 * Sets the cylindrical components by copying the given values.
57093	 *
57094	 * @param {number} radius - The radius.
57095	 * @param {number} theta - The theta angle.
57096	 * @param {number} y - The height value.
57097	 * @return {Cylindrical} A reference to this cylindrical.
57098	 */
57099	set( radius, theta, y ) {
57100
57101		this.radius = radius;
57102		this.theta = theta;
57103		this.y = y;
57104
57105		return this;
57106
57107	}
57108
57109	/**
57110	 * Copies the values of the given cylindrical to this instance.
57111	 *
57112	 * @param {Cylindrical} other - The cylindrical to copy.
57113	 * @return {Cylindrical} A reference to this cylindrical.
57114	 */
57115	copy( other ) {
57116
57117		this.radius = other.radius;
57118		this.theta = other.theta;
57119		this.y = other.y;
57120
57121		return this;
57122
57123	}
57124
57125	/**
57126	 * Sets the cylindrical components from the given vector which is assumed to hold
57127	 * Cartesian coordinates.
57128	 *
57129	 * @param {Vector3} v - The vector to set.
57130	 * @return {Cylindrical} A reference to this cylindrical.
57131	 */
57132	setFromVector3( v ) {
57133
57134		return this.setFromCartesianCoords( v.x, v.y, v.z );
57135
57136	}
57137
57138	/**
57139	 * Sets the cylindrical components from the given Cartesian coordinates.
57140	 *
57141	 * @param {number} x - The x value.
57142	 * @param {number} y - The x value.
57143	 * @param {number} z - The x value.
57144	 * @return {Cylindrical} A reference to this cylindrical.
57145	 */
57146	setFromCartesianCoords( x, y, z ) {
57147
57148		this.radius = Math.sqrt( x * x + z * z );
57149		this.theta = Math.atan2( x, z );
57150		this.y = y;
57151
57152		return this;
57153
57154	}
57155
57156	/**
57157	 * Returns a new cylindrical with copied values from this instance.
57158	 *
57159	 * @return {Cylindrical} A clone of this instance.
57160	 */
57161	clone() {
57162
57163		return new this.constructor().copy( this );
57164
57165	}
57166
57167}
57168
57169/**
57170 * Represents a 2x2 matrix.
57171 *
57172 * A Note on Row-Major and Column-Major Ordering:
57173 *
57174 * The constructor and {@link Matrix2#set} method take arguments in
57175 * [row-major](https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order)
57176 * order, while internally they are stored in the {@link Matrix2#elements} array in column-major order.
57177 * This means that calling:
57178 * ```js
57179 * const m = new THREE.Matrix2();
57180 * m.set( 11, 12,
57181 *        21, 22 );
57182 * ```
57183 * will result in the elements array containing:
57184 * ```js
57185 * m.elements = [ 11, 21,
57186 *                12, 22 ];
57187 * ```
57188 * and internally all calculations are performed using column-major ordering.
57189 * However, as the actual ordering makes no difference mathematically and
57190 * most people are used to thinking about matrices in row-major order, the
57191 * three.js documentation shows matrices in row-major order. Just bear in
57192 * mind that if you are reading the source code, you'll have to take the
57193 * transpose of any matrices outlined here to make sense of the calculations.
57194 */
57195class Matrix2 {
57196
57197	static {
57198
57199		/**
57200		 * This flag can be used for type testing.
57201		 *
57202		 * @type {boolean}
57203		 * @readonly
57204		 * @default true
57205		 */
57206		Matrix2.prototype.isMatrix2 = true;
57207
57208	}
57209
57210	/**
57211	 * Constructs a new 2x2 matrix. The arguments are supposed to be
57212	 * in row-major order. If no arguments are provided, the constructor
57213	 * initializes the matrix as an identity matrix.
57214	 *
57215	 * @param {number} [n11] - 1-1 matrix element.
57216	 * @param {number} [n12] - 1-2 matrix element.
57217	 * @param {number} [n21] - 2-1 matrix element.
57218	 * @param {number} [n22] - 2-2 matrix element.
57219	 */
57220	constructor( n11, n12, n21, n22 ) {
57221
57222		/**
57223		 * A column-major list of matrix values.
57224		 *
57225		 * @type {Array<number>}
57226		 */
57227		this.elements = [
57228			1, 0,
57229			0, 1,
57230		];
57231
57232		if ( n11 !== undefined ) {
57233
57234			this.set( n11, n12, n21, n22 );
57235
57236		}
57237
57238	}
57239
57240	/**
57241	 * Sets this matrix to the 2x2 identity matrix.
57242	 *
57243	 * @return {Matrix2} A reference to this matrix.
57244	 */
57245	identity() {
57246
57247		this.set(
57248			1, 0,
57249			0, 1,
57250		);
57251
57252		return this;
57253
57254	}
57255
57256	/**
57257	 * Sets the elements of the matrix from the given array.
57258	 *
57259	 * @param {Array<number>} array - The matrix elements in column-major order.
57260	 * @param {number} [offset=0] - Index of the first element in the array.
57261	 * @return {Matrix2} A reference to this matrix.
57262	 */
57263	fromArray( array, offset = 0 ) {
57264
57265		for ( let i = 0; i < 4; i ++ ) {
57266
57267			this.elements[ i ] = array[ i + offset ];
57268
57269		}
57270
57271		return this;
57272
57273	}
57274
57275	/**
57276	 * Sets the elements of the matrix.The arguments are supposed to be
57277	 * in row-major order.
57278	 *
57279	 * @param {number} n11 - 1-1 matrix element.
57280	 * @param {number} n12 - 1-2 matrix element.
57281	 * @param {number} n21 - 2-1 matrix element.
57282	 * @param {number} n22 - 2-2 matrix element.
57283	 * @return {Matrix2} A reference to this matrix.
57284	 */
57285	set( n11, n12, n21, n22 ) {
57286
57287		const te = this.elements;
57288
57289		te[ 0 ] = n11; te[ 2 ] = n12;
57290		te[ 1 ] = n21; te[ 3 ] = n22;
57291
57292		return this;
57293
57294	}
57295
57296}
57297
57298const _vector$4 = /*@__PURE__*/ new Vector2();
57299
57300/**
57301 * Represents an axis-aligned bounding box (AABB) in 2D space.
57302 */
57303class Box2 {
57304
57305	/**
57306	 * Constructs a new bounding box.
57307	 *
57308	 * @param {Vector2} [min=(Infinity,Infinity)] - A vector representing the lower boundary of the box.
57309	 * @param {Vector2} [max=(-Infinity,-Infinity)] - A vector representing the upper boundary of the box.
57310	 */
57311	constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) {
57312
57313		/**
57314		 * This flag can be used for type testing.
57315		 *
57316		 * @type {boolean}
57317		 * @readonly
57318		 * @default true
57319		 */
57320		this.isBox2 = true;
57321
57322		/**
57323		 * The lower boundary of the box.
57324		 *
57325		 * @type {Vector2}
57326		 */
57327		this.min = min;
57328
57329		/**
57330		 * The upper boundary of the box.
57331		 *
57332		 * @type {Vector2}
57333		 */
57334		this.max = max;
57335
57336	}
57337
57338	/**
57339	 * Sets the lower and upper boundaries of this box.
57340	 * Please note that this method only copies the values from the given objects.
57341	 *
57342	 * @param {Vector2} min - The lower boundary of the box.
57343	 * @param {Vector2} max - The upper boundary of the box.
57344	 * @return {Box2} A reference to this bounding box.
57345	 */
57346	set( min, max ) {
57347
57348		this.min.copy( min );
57349		this.max.copy( max );
57350
57351		return this;
57352
57353	}
57354
57355	/**
57356	 * Sets the upper and lower bounds of this box so it encloses the position data
57357	 * in the given array.
57358	 *
57359	 * @param {Array<Vector2>} points - An array holding 2D position data as instances of {@link Vector2}.
57360	 * @return {Box2} A reference to this bounding box.
57361	 */
57362	setFromPoints( points ) {
57363
57364		this.makeEmpty();
57365
57366		for ( let i = 0, il = points.length; i < il; i ++ ) {
57367
57368			this.expandByPoint( points[ i ] );
57369
57370		}
57371
57372		return this;
57373
57374	}
57375
57376	/**
57377	 * Centers this box on the given center vector and sets this box's width, height and
57378	 * depth to the given size values.
57379	 *
57380	 * @param {Vector2} center - The center of the box.
57381	 * @param {Vector2} size - The x and y dimensions of the box.
57382	 * @return {Box2} A reference to this bounding box.
57383	 */
57384	setFromCenterAndSize( center, size ) {
57385
57386		const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 );
57387		this.min.copy( center ).sub( halfSize );
57388		this.max.copy( center ).add( halfSize );
57389
57390		return this;
57391
57392	}
57393
57394	/**
57395	 * Returns a new box with copied values from this instance.
57396	 *
57397	 * @return {Box2} A clone of this instance.
57398	 */
57399	clone() {
57400
57401		return new this.constructor().copy( this );
57402
57403	}
57404
57405	/**
57406	 * Copies the values of the given box to this instance.
57407	 *
57408	 * @param {Box2} box - The box to copy.
57409	 * @return {Box2} A reference to this bounding box.
57410	 */
57411	copy( box ) {
57412
57413		this.min.copy( box.min );
57414		this.max.copy( box.max );
57415
57416		return this;
57417
57418	}
57419
57420	/**
57421	 * Makes this box empty which means in encloses a zero space in 2D.
57422	 *
57423	 * @return {Box2} A reference to this bounding box.
57424	 */
57425	makeEmpty() {
57426
57427		this.min.x = this.min.y = + Infinity;
57428		this.max.x = this.max.y = - Infinity;
57429
57430		return this;
57431
57432	}
57433
57434	/**
57435	 * Returns true if this box includes zero points within its bounds.
57436	 * Note that a box with equal lower and upper bounds still includes one
57437	 * point, the one both bounds share.
57438	 *
57439	 * @return {boolean} Whether this box is empty or not.
57440	 */
57441	isEmpty() {
57442
57443		// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
57444
57445		return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
57446
57447	}
57448
57449	/**
57450	 * Returns the center point of this box.
57451	 *
57452	 * @param {Vector2} target - The target vector that is used to store the method's result.
57453	 * @return {Vector2} The center point.
57454	 */
57455	getCenter( target ) {
57456
57457		return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
57458
57459	}
57460
57461	/**
57462	 * Returns the dimensions of this box.
57463	 *
57464	 * @param {Vector2} target - The target vector that is used to store the method's result.
57465	 * @return {Vector2} The size.
57466	 */
57467	getSize( target ) {
57468
57469		return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
57470
57471	}
57472
57473	/**
57474	 * Expands the boundaries of this box to include the given point.
57475	 *
57476	 * @param {Vector2} point - The point that should be included by the bounding box.
57477	 * @return {Box2} A reference to this bounding box.
57478	 */
57479	expandByPoint( point ) {
57480
57481		this.min.min( point );
57482		this.max.max( point );
57483
57484		return this;
57485
57486	}
57487
57488	/**
57489	 * Expands this box equilaterally by the given vector. The width of this
57490	 * box will be expanded by the x component of the vector in both
57491	 * directions. The height of this box will be expanded by the y component of
57492	 * the vector in both directions.
57493	 *
57494	 * @param {Vector2} vector - The vector that should expand the bounding box.
57495	 * @return {Box2} A reference to this bounding box.
57496	 */
57497	expandByVector( vector ) {
57498
57499		this.min.sub( vector );
57500		this.max.add( vector );
57501
57502		return this;
57503
57504	}
57505
57506	/**
57507	 * Expands each dimension of the box by the given scalar. If negative, the
57508	 * dimensions of the box will be contracted.
57509	 *
57510	 * @param {number} scalar - The scalar value that should expand the bounding box.
57511	 * @return {Box2} A reference to this bounding box.
57512	 */
57513	expandByScalar( scalar ) {
57514
57515		this.min.addScalar( - scalar );
57516		this.max.addScalar( scalar );
57517
57518		return this;
57519
57520	}
57521
57522	/**
57523	 * Returns `true` if the given point lies within or on the boundaries of this box.
57524	 *
57525	 * @param {Vector2} point - The point to test.
57526	 * @return {boolean} Whether the bounding box contains the given point or not.
57527	 */
57528	containsPoint( point ) {
57529
57530		return point.x >= this.min.x && point.x <= this.max.x &&
57531			point.y >= this.min.y && point.y <= this.max.y;
57532
57533	}
57534
57535	/**
57536	 * Returns `true` if this bounding box includes the entirety of the given bounding box.
57537	 * If this box and the given one are identical, this function also returns `true`.
57538	 *
57539	 * @param {Box2} box - The bounding box to test.
57540	 * @return {boolean} Whether the bounding box contains the given bounding box or not.
57541	 */
57542	containsBox( box ) {
57543
57544		return this.min.x <= box.min.x && box.max.x <= this.max.x &&
57545			this.min.y <= box.min.y && box.max.y <= this.max.y;
57546
57547	}
57548
57549	/**
57550	 * Returns a point as a proportion of this box's width and height.
57551	 *
57552	 * @param {Vector2} point - A point in 2D space.
57553	 * @param {Vector2} target - The target vector that is used to store the method's result.
57554	 * @return {Vector2} A point as a proportion of this box's width and height.
57555	 */
57556	getParameter( point, target ) {
57557
57558		// This can potentially have a divide by zero if the box
57559		// has a size dimension of 0.
57560
57561		return target.set(
57562			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
57563			( point.y - this.min.y ) / ( this.max.y - this.min.y )
57564		);
57565
57566	}
57567
57568	/**
57569	 * Returns `true` if the given bounding box intersects with this bounding box.
57570	 *
57571	 * @param {Box2} box - The bounding box to test.
57572	 * @return {boolean} Whether the given bounding box intersects with this bounding box.
57573	 */
57574	intersectsBox( box ) {
57575
57576		// using 4 splitting planes to rule out intersections
57577
57578		return box.max.x >= this.min.x && box.min.x <= this.max.x &&
57579			box.max.y >= this.min.y && box.min.y <= this.max.y;
57580
57581	}
57582
57583	/**
57584	 * Clamps the given point within the bounds of this box.
57585	 *
57586	 * @param {Vector2} point - The point to clamp.
57587	 * @param {Vector2} target - The target vector that is used to store the method's result.
57588	 * @return {Vector2} The clamped point.
57589	 */
57590	clampPoint( point, target ) {
57591
57592		return target.copy( point ).clamp( this.min, this.max );
57593
57594	}
57595
57596	/**
57597	 * Returns the euclidean distance from any edge of this box to the specified point. If
57598	 * the given point lies inside of this box, the distance will be `0`.
57599	 *
57600	 * @param {Vector2} point - The point to compute the distance to.
57601	 * @return {number} The euclidean distance.
57602	 */
57603	distanceToPoint( point ) {
57604
57605		return this.clampPoint( point, _vector$4 ).distanceTo( point );
57606
57607	}
57608
57609	/**
57610	 * Computes the intersection of this bounding box and the given one, setting the upper
57611	 * bound of this box to the lesser of the two boxes' upper bounds and the
57612	 * lower bound of this box to the greater of the two boxes' lower bounds. If
57613	 * there's no overlap, makes this box empty.
57614	 *
57615	 * @param {Box2} box - The bounding box to intersect with.
57616	 * @return {Box2} A reference to this bounding box.
57617	 */
57618	intersect( box ) {
57619
57620		this.min.max( box.min );
57621		this.max.min( box.max );
57622
57623		if ( this.isEmpty() ) this.makeEmpty();
57624
57625		return this;
57626
57627	}
57628
57629	/**
57630	 * Computes the union of this box and another and the given one, setting the upper
57631	 * bound of this box to the greater of the two boxes' upper bounds and the
57632	 * lower bound of this box to the lesser of the two boxes' lower bounds.
57633	 *
57634	 * @param {Box2} box - The bounding box that will be unioned with this instance.
57635	 * @return {Box2} A reference to this bounding box.
57636	 */
57637	union( box ) {
57638
57639		this.min.min( box.min );
57640		this.max.max( box.max );
57641
57642		return this;
57643
57644	}
57645
57646	/**
57647	 * Adds the given offset to both the upper and lower bounds of this bounding box,
57648	 * effectively moving it in 2D space.
57649	 *
57650	 * @param {Vector2} offset - The offset that should be used to translate the bounding box.
57651	 * @return {Box2} A reference to this bounding box.
57652	 */
57653	translate( offset ) {
57654
57655		this.min.add( offset );
57656		this.max.add( offset );
57657
57658		return this;
57659
57660	}
57661
57662	/**
57663	 * Returns `true` if this bounding box is equal with the given one.
57664	 *
57665	 * @param {Box2} box - The box to test for equality.
57666	 * @return {boolean} Whether this bounding box is equal with the given one.
57667	 */
57668	equals( box ) {
57669
57670		return box.min.equals( this.min ) && box.max.equals( this.max );
57671
57672	}
57673
57674}
57675
57676const _startP = /*@__PURE__*/ new Vector3();
57677const _startEnd = /*@__PURE__*/ new Vector3();
57678
57679const _d1 = /*@__PURE__*/ new Vector3();
57680const _d2 = /*@__PURE__*/ new Vector3();
57681const _r = /*@__PURE__*/ new Vector3();
57682const _c1 = /*@__PURE__*/ new Vector3();
57683const _c2 = /*@__PURE__*/ new Vector3();
57684
57685/**
57686 * An analytical line segment in 3D space represented by a start and end point.
57687 */
57688class Line3 {
57689
57690	/**
57691	 * Constructs a new line segment.
57692	 *
57693	 * @param {Vector3} [start=(0,0,0)] - Start of the line segment.
57694	 * @param {Vector3} [end=(0,0,0)] - End of the line segment.
57695	 */
57696	constructor( start = new Vector3(), end = new Vector3() ) {
57697
57698		/**
57699		 * Start of the line segment.
57700		 *
57701		 * @type {Vector3}
57702		 */
57703		this.start = start;
57704
57705		/**
57706		 * End of the line segment.
57707		 *
57708		 * @type {Vector3}
57709		 */
57710		this.end = end;
57711
57712	}
57713
57714	/**
57715	 * Sets the start and end values by copying the given vectors.
57716	 *
57717	 * @param {Vector3} start - The start point.
57718	 * @param {Vector3} end - The end point.
57719	 * @return {Line3} A reference to this line segment.
57720	 */
57721	set( start, end ) {
57722
57723		this.start.copy( start );
57724		this.end.copy( end );
57725
57726		return this;
57727
57728	}
57729
57730	/**
57731	 * Copies the values of the given line segment to this instance.
57732	 *
57733	 * @param {Line3} line - The line segment to copy.
57734	 * @return {Line3} A reference to this line segment.
57735	 */
57736	copy( line ) {
57737
57738		this.start.copy( line.start );
57739		this.end.copy( line.end );
57740
57741		return this;
57742
57743	}
57744
57745	/**
57746	 * Returns the center of the line segment.
57747	 *
57748	 * @param {Vector3} target - The target vector that is used to store the method's result.
57749	 * @return {Vector3} The center point.
57750	 */
57751	getCenter( target ) {
57752
57753		return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
57754
57755	}
57756
57757	/**
57758	 * Returns the delta vector of the line segment's start and end point.
57759	 *
57760	 * @param {Vector3} target - The target vector that is used to store the method's result.
57761	 * @return {Vector3} The delta vector.
57762	 */
57763	delta( target ) {
57764
57765		return target.subVectors( this.end, this.start );
57766
57767	}
57768
57769	/**
57770	 * Returns the squared Euclidean distance between the line' start and end point.
57771	 *
57772	 * @return {number} The squared Euclidean distance.
57773	 */
57774	distanceSq() {
57775
57776		return this.start.distanceToSquared( this.end );
57777
57778	}
57779
57780	/**
57781	 * Returns the Euclidean distance between the line' start and end point.
57782	 *
57783	 * @return {number} The Euclidean distance.
57784	 */
57785	distance() {
57786
57787		return this.start.distanceTo( this.end );
57788
57789	}
57790
57791	/**
57792	 * Returns a vector at a certain position along the line segment.
57793	 *
57794	 * @param {number} t - A value between `[0,1]` to represent a position along the line segment.
57795	 * @param {Vector3} target - The target vector that is used to store the method's result.
57796	 * @return {Vector3} The delta vector.
57797	 */
57798	at( t, target ) {
57799
57800		return this.delta( target ).multiplyScalar( t ).add( this.start );
57801
57802	}
57803
57804	/**
57805	 * Returns a point parameter based on the closest point as projected on the line segment.
57806	 *
57807	 * @param {Vector3} point - The point for which to return a point parameter.
57808	 * @param {boolean} clampToLine - Whether to clamp the result to the range `[0,1]` or not.
57809	 * @return {number} The point parameter.
57810	 */
57811	closestPointToPointParameter( point, clampToLine ) {
57812
57813		_startP.subVectors( point, this.start );
57814		_startEnd.subVectors( this.end, this.start );
57815
57816		const startEnd2 = _startEnd.dot( _startEnd );
57817
57818		if ( startEnd2 === 0 ) return 0;
57819
57820		const startEnd_startP = _startEnd.dot( _startP );
57821
57822		let t = startEnd_startP / startEnd2;
57823
57824		if ( clampToLine ) {
57825
57826			t = clamp( t, 0, 1 );
57827
57828		}
57829
57830		return t;
57831
57832	}
57833
57834	/**
57835	 * Returns the closest point on the line for a given point.
57836	 *
57837	 * @param {Vector3} point - The point to compute the closest point on the line for.
57838	 * @param {boolean} clampToLine - Whether to clamp the result to the range `[0,1]` or not.
57839	 * @param {Vector3} target - The target vector that is used to store the method's result.
57840	 * @return {Vector3} The closest point on the line.
57841	 */
57842	closestPointToPoint( point, clampToLine, target ) {
57843
57844		const t = this.closestPointToPointParameter( point, clampToLine );
57845
57846		return this.delta( target ).multiplyScalar( t ).add( this.start );
57847
57848	}
57849
57850	/**
57851	 * Returns the closest squared distance between this line segment and the given one.
57852	 *
57853	 * @param {Line3} line - The line segment to compute the closest squared distance to.
57854	 * @param {Vector3} [c1] - The closest point on this line segment.
57855	 * @param {Vector3} [c2] - The closest point on the given line segment.
57856	 * @return {number} The squared distance between this line segment and the given one.
57857	 */
57858	distanceSqToLine3( line, c1 = _c1, c2 = _c2 ) {
57859
57860		// from Real-Time Collision Detection by Christer Ericson, chapter 5.1.9
57861
57862		// Computes closest points C1 and C2 of S1(s)=P1+s*(Q1-P1) and
57863		// S2(t)=P2+t*(Q2-P2), returning s and t. Function result is squared
57864		// distance between between S1(s) and S2(t)
57865
57866		const EPSILON = 1e-8 * 1e-8; // must be squared since we compare squared length
57867		let s, t;
57868
57869		const p1 = this.start;
57870		const p2 = line.start;
57871		const q1 = this.end;
57872		const q2 = line.end;
57873
57874		_d1.subVectors( q1, p1 ); // Direction vector of segment S1
57875		_d2.subVectors( q2, p2 ); // Direction vector of segment S2
57876		_r.subVectors( p1, p2 );
57877
57878		const a = _d1.dot( _d1 ); // Squared length of segment S1, always nonnegative
57879		const e = _d2.dot( _d2 ); // Squared length of segment S2, always nonnegative
57880		const f = _d2.dot( _r );
57881
57882		// Check if either or both segments degenerate into points
57883
57884		if ( a <= EPSILON && e <= EPSILON ) {
57885
57886			// Both segments degenerate into points
57887
57888			c1.copy( p1 );
57889			c2.copy( p2 );
57890
57891			c1.sub( c2 );
57892
57893			return c1.dot( c1 );
57894
57895		}
57896
57897		if ( a <= EPSILON ) {
57898
57899			// First segment degenerates into a point
57900
57901			s = 0;
57902			t = f / e; // s = 0 => t = (b*s + f) / e = f / e
57903			t = clamp( t, 0, 1 );
57904
57905
57906		} else {
57907
57908			const c = _d1.dot( _r );
57909
57910			if ( e <= EPSILON ) {
57911
57912				// Second segment degenerates into a point
57913
57914				t = 0;
57915				s = clamp( - c / a, 0, 1 ); // t = 0 => s = (b*t - c) / a = -c / a
57916
57917			} else {
57918
57919				// The general nondegenerate case starts here
57920
57921				const b = _d1.dot( _d2 );
57922				const denom = a * e - b * b; // Always nonnegative
57923
57924				// If segments not parallel, compute closest point on L1 to L2 and
57925				// clamp to segment S1. Else pick arbitrary s (here 0)
57926
57927				if ( denom !== 0 ) {
57928
57929					s = clamp( ( b * f - c * e ) / denom, 0, 1 );
57930
57931				} else {
57932
57933					s = 0;
57934
57935				}
57936
57937				// Compute point on L2 closest to S1(s) using
57938				// t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
57939
57940				t = ( b * s + f ) / e;
57941
57942				// If t in [0,1] done. Else clamp t, recompute s for the new value
57943				// of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
57944				// and clamp s to [0, 1]
57945
57946				if ( t < 0 ) {
57947
57948					t = 0.;
57949					s = clamp( - c / a, 0, 1 );
57950
57951				} else if ( t > 1 ) {
57952
57953					t = 1;
57954					s = clamp( ( b - c ) / a, 0, 1 );
57955
57956				}
57957
57958			}
57959
57960		}
57961
57962		c1.copy( p1 ).addScaledVector( _d1, s );
57963		c2.copy( p2 ).addScaledVector( _d2, t );
57964
57965		return c1.distanceToSquared( c2 );
57966
57967	}
57968
57969	/**
57970	 * Applies a 4x4 transformation matrix to this line segment.
57971	 *
57972	 * @param {Matrix4} matrix - The transformation matrix.
57973	 * @return {Line3} A reference to this line segment.
57974	 */
57975	applyMatrix4( matrix ) {
57976
57977		this.start.applyMatrix4( matrix );
57978		this.end.applyMatrix4( matrix );
57979
57980		return this;
57981
57982	}
57983
57984	/**
57985	 * Returns `true` if this line segment is equal with the given one.
57986	 *
57987	 * @param {Line3} line - The line segment to test for equality.
57988	 * @return {boolean} Whether this line segment is equal with the given one.
57989	 */
57990	equals( line ) {
57991
57992		return line.start.equals( this.start ) && line.end.equals( this.end );
57993
57994	}
57995
57996	/**
57997	 * Returns a new line segment with copied values from this instance.
57998	 *
57999	 * @return {Line3} A clone of this instance.
58000	 */
58001	clone() {
58002
58003		return new this.constructor().copy( this );
58004
58005	}
58006
58007}
58008
58009const _vector$3 = /*@__PURE__*/ new Vector3();
58010
58011/**
58012 * This displays a cone shaped helper object for a {@link SpotLight}.
58013 *
58014 * When the spot light or its target are transformed or light properties are
58015 * changed, it's necessary to call the `update()` method of the respective helper.
58016 *
58017 * ```js
58018 * const spotLight = new THREE.SpotLight( 0xffffff );
58019 * spotLight.position.set( 10, 10, 10 );
58020 * scene.add( spotLight );
58021 *
58022 * const spotLightHelper = new THREE.SpotLightHelper( spotLight );
58023 * scene.add( spotLightHelper );
58024 * ```
58025 *
58026 * @augments Object3D
58027 */
58028class SpotLightHelper extends Object3D {
58029
58030	/**
58031	 * Constructs a new spot light helper.
58032	 *
58033	 * @param {HemisphereLight} light - The light to be visualized.
58034	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
58035	 * the color of the light.
58036	 */
58037	constructor( light, color ) {
58038
58039		super();
58040
58041		/**
58042		 * The light being visualized.
58043		 *
58044		 * @type {SpotLight}
58045		 */
58046		this.light = light;
58047
58048		this.matrixAutoUpdate = false;
58049
58050		/**
58051		 * The color parameter passed in the constructor.
58052		 * If not set, the helper will take the color of the light.
58053		 *
58054		 * @type {number|Color|string}
58055		 */
58056		this.color = color;
58057
58058		this.type = 'SpotLightHelper';
58059
58060		const geometry = new BufferGeometry();
58061
58062		const positions = [
58063			0, 0, 0, 	0, 0, 1,
58064			0, 0, 0, 	1, 0, 1,
58065			0, 0, 0,	-1, 0, 1,
58066			0, 0, 0, 	0, 1, 1,
58067			0, 0, 0, 	0, -1, 1
58068		];
58069
58070		for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
58071
58072			const p1 = ( i / l ) * Math.PI * 2;
58073			const p2 = ( j / l ) * Math.PI * 2;
58074
58075			positions.push(
58076				Math.cos( p1 ), Math.sin( p1 ), 1,
58077				Math.cos( p2 ), Math.sin( p2 ), 1
58078			);
58079
58080		}
58081
58082		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
58083
58084		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
58085
58086		this.cone = new LineSegments( geometry, material );
58087		this.add( this.cone );
58088
58089		this.update();
58090
58091	}
58092
58093	/**
58094	 * Frees the GPU-related resources allocated by this instance. Call this
58095	 * method whenever this instance is no longer used in your app.
58096	 */
58097	dispose() {
58098
58099		super.dispose();
58100
58101		this.cone.geometry.dispose();
58102		this.cone.material.dispose();
58103
58104	}
58105
58106	/**
58107	 * Updates the helper to match the position and direction of the
58108	 * light being visualized.
58109	 */
58110	update() {
58111
58112		this.light.updateWorldMatrix( true, false );
58113		this.light.target.updateWorldMatrix( true, false );
58114
58115		// update the local matrix based on the parent and light target transforms
58116		if ( this.parent ) {
58117
58118			this.parent.updateWorldMatrix( true );
58119
58120			this.matrix
58121				.copy( this.parent.matrixWorld )
58122				.invert()
58123				.multiply( this.light.matrixWorld );
58124
58125		} else {
58126
58127			this.matrix.copy( this.light.matrixWorld );
58128
58129		}
58130
58131		this.matrixWorldNeedsUpdate = true;
58132
58133		const coneLength = this.light.distance ? this.light.distance : 1000;
58134		const coneWidth = coneLength * Math.tan( this.light.angle );
58135
58136		this.cone.scale.set( coneWidth, coneWidth, coneLength );
58137
58138		_vector$3.setFromMatrixPosition( this.light.target.matrixWorld );
58139
58140		this.cone.lookAt( _vector$3 );
58141
58142		if ( this.color !== undefined ) {
58143
58144			this.cone.material.color.set( this.color );
58145
58146		} else {
58147
58148			this.cone.material.color.copy( this.light.color );
58149
58150		}
58151
58152	}
58153
58154}
58155
58156const _vector$2 = /*@__PURE__*/ new Vector3();
58157const _boneMatrix = /*@__PURE__*/ new Matrix4();
58158const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
58159
58160/**
58161 * A helper object to assist with visualizing a {@link Skeleton}.
58162 *
58163 * ```js
58164 * const helper = new THREE.SkeletonHelper( skinnedMesh );
58165 * scene.add( helper );
58166 * ```
58167 *
58168 * @augments LineSegments
58169 */
58170class SkeletonHelper extends LineSegments {
58171
58172	/**
58173	 * Constructs a new skeleton helper.
58174	 *
58175	 * @param {Object3D} object -  Usually an instance of {@link SkinnedMesh}. However, any 3D object
58176	 * can be used if it represents a hierarchy of bones (see {@link Bone}).
58177	 */
58178	constructor( object ) {
58179
58180		const bones = getBoneList( object );
58181
58182		const geometry = new BufferGeometry();
58183
58184		const vertices = [];
58185		const colors = [];
58186
58187		for ( let i = 0; i < bones.length; i ++ ) {
58188
58189			const bone = bones[ i ];
58190
58191			if ( bone.parent && bone.parent.isBone ) {
58192
58193				vertices.push( 0, 0, 0 );
58194				vertices.push( 0, 0, 0 );
58195				colors.push( 0, 0, 0 );
58196				colors.push( 0, 0, 0 );
58197
58198			}
58199
58200		}
58201
58202		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
58203		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
58204
58205		const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
58206
58207		super( geometry, material );
58208
58209		/**
58210		 * This flag can be used for type testing.
58211		 *
58212		 * @type {boolean}
58213		 * @readonly
58214		 * @default true
58215		 */
58216		this.isSkeletonHelper = true;
58217
58218		this.type = 'SkeletonHelper';
58219
58220		/**
58221		 * The object being visualized.
58222		 *
58223		 * @type {Object3D}
58224		 */
58225		this.root = object;
58226
58227		/**
58228		 * The list of bones that the helper visualizes.
58229		 *
58230		 * @type {Array<Bone>}
58231		 */
58232		this.bones = bones;
58233
58234		this.matrix = object.matrixWorld;
58235		this.matrixAutoUpdate = false;
58236
58237		// colors
58238
58239		const color1 = new Color( 0x0000ff );
58240		const color2 = new Color( 0x00ff00 );
58241
58242		this.setColors( color1, color2 );
58243
58244	}
58245
58246	updateMatrixWorld( force ) {
58247
58248		const bones = this.bones;
58249
58250		const geometry = this.geometry;
58251		const position = geometry.getAttribute( 'position' );
58252
58253		_matrixWorldInv.copy( this.root.matrixWorld ).invert();
58254
58255		for ( let i = 0, j = 0; i < bones.length; i ++ ) {
58256
58257			const bone = bones[ i ];
58258
58259			if ( bone.parent && bone.parent.isBone ) {
58260
58261				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
58262				_vector$2.setFromMatrixPosition( _boneMatrix );
58263				position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z );
58264
58265				_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
58266				_vector$2.setFromMatrixPosition( _boneMatrix );
58267				position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z );
58268
58269				j += 2;
58270
58271			}
58272
58273		}
58274
58275		geometry.getAttribute( 'position' ).needsUpdate = true;
58276
58277		super.updateMatrixWorld( force );
58278
58279	}
58280
58281	/**
58282	 * Defines the colors of the helper.
58283	 *
58284	 * @param {Color} color1 - The first line color for each bone.
58285	 * @param {Color} color2 - The second line color for each bone.
58286	 * @return {SkeletonHelper} A reference to this helper.
58287	 */
58288	setColors( color1, color2 ) {
58289
58290		const geometry = this.geometry;
58291		const colorAttribute = geometry.getAttribute( 'color' );
58292
58293		for ( let i = 0; i < colorAttribute.count; i += 2 ) {
58294
58295			colorAttribute.setXYZ( i, color1.r, color1.g, color1.b );
58296			colorAttribute.setXYZ( i + 1, color2.r, color2.g, color2.b );
58297
58298		}
58299
58300		colorAttribute.needsUpdate = true;
58301
58302		return this;
58303
58304	}
58305
58306	/**
58307	 * Frees the GPU-related resources allocated by this instance. Call this
58308	 * method whenever this instance is no longer used in your app.
58309	 */
58310	dispose() {
58311
58312		super.dispose();
58313
58314		this.geometry.dispose();
58315		this.material.dispose();
58316
58317	}
58318
58319}
58320
58321
58322function getBoneList( object ) {
58323
58324	const boneList = [];
58325
58326	if ( object.isBone === true ) {
58327
58328		boneList.push( object );
58329
58330	}
58331
58332	for ( let i = 0; i < object.children.length; i ++ ) {
58333
58334		boneList.push( ...getBoneList( object.children[ i ] ) );
58335
58336	}
58337
58338	return boneList;
58339
58340}
58341
58342/**
58343 * This displays a helper object consisting of a spherical mesh for
58344 * visualizing an instance of {@link PointLight}.
58345 *
58346 * ```js
58347 * const pointLight = new THREE.PointLight( 0xff0000, 1, 100 );
58348 * pointLight.position.set( 10, 10, 10 );
58349 * scene.add( pointLight );
58350 *
58351 * const sphereSize = 1;
58352 * const pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
58353 * scene.add( pointLightHelper );
58354 * ```
58355 *
58356 * @augments Mesh
58357 */
58358class PointLightHelper extends Mesh {
58359
58360	/**
58361	 * Constructs a new point light helper.
58362	 *
58363	 * @param {PointLight} light - The light to be visualized.
58364	 * @param {number} [sphereSize=1] - The size of the sphere helper.
58365	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
58366	 * the color of the light.
58367	 */
58368	constructor( light, sphereSize, color ) {
58369
58370		const geometry = new SphereGeometry( sphereSize, 4, 2 );
58371		const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
58372
58373		super( geometry, material );
58374
58375		/**
58376		 * The light being visualized.
58377		 *
58378		 * @type {PointLight}
58379		 */
58380		this.light = light;
58381
58382		/**
58383		 * The color parameter passed in the constructor.
58384		 * If not set, the helper will take the color of the light.
58385		 *
58386		 * @type {number|Color|string}
58387		 */
58388		this.color = color;
58389
58390		this.type = 'PointLightHelper';
58391
58392		this.matrix = this.light.matrixWorld;
58393		this.matrixAutoUpdate = false;
58394
58395		this.update();
58396
58397	}
58398
58399	/**
58400	 * Frees the GPU-related resources allocated by this instance. Call this
58401	 * method whenever this instance is no longer used in your app.
58402	 */
58403	dispose() {
58404
58405		super.dispose();
58406
58407		this.geometry.dispose();
58408		this.material.dispose();
58409
58410	}
58411
58412	/**
58413	 * Updates the helper to match the position of the
58414	 * light being visualized.
58415	 */
58416	update() {
58417
58418		this.matrixWorldNeedsUpdate = true;
58419
58420		this.light.updateWorldMatrix( true, false );
58421
58422		if ( this.color !== undefined ) {
58423
58424			this.material.color.set( this.color );
58425
58426		} else {
58427
58428			this.material.color.copy( this.light.color );
58429
58430		}
58431
58432		/*
58433		const d = this.light.distance;
58434
58435		if ( d === 0.0 ) {
58436
58437			this.lightDistance.visible = false;
58438
58439		} else {
58440
58441			this.lightDistance.visible = true;
58442			this.lightDistance.scale.set( d, d, d );
58443
58444		}
58445		*/
58446
58447	}
58448
58449}
58450
58451const _vector$1 = /*@__PURE__*/ new Vector3();
58452const _color1 = /*@__PURE__*/ new Color();
58453const _color2 = /*@__PURE__*/ new Color();
58454
58455/**
58456 * Creates a visual aid consisting of a spherical mesh for a
58457 * given {@link HemisphereLight}.
58458 *
58459 * When the hemisphere light is transformed or its light properties are changed,
58460 * it's necessary to call the `update()` method of the respective helper.
58461 *
58462 * ```js
58463 * const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
58464 * const helper = new THREE.HemisphereLightHelper( light, 5 );
58465 * scene.add( helper );
58466 * ```
58467 *
58468 * @augments Object3D
58469 */
58470class HemisphereLightHelper extends Object3D {
58471
58472	/**
58473	 * Constructs a new hemisphere light helper.
58474	 *
58475	 * @param {HemisphereLight} light - The light to be visualized.
58476	 * @param {number} [size=1] - The size of the mesh used to visualize the light.
58477	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
58478	 * the color of the light.
58479	 */
58480	constructor( light, size, color ) {
58481
58482		super();
58483
58484		/**
58485		 * The light being visualized.
58486		 *
58487		 * @type {HemisphereLight}
58488		 */
58489		this.light = light;
58490
58491		this.matrix = light.matrixWorld;
58492		this.matrixAutoUpdate = false;
58493
58494		/**
58495		 * The color parameter passed in the constructor.
58496		 * If not set, the helper will take the color of the light.
58497		 *
58498		 * @type {number|Color|string}
58499		 */
58500		this.color = color;
58501
58502		this.type = 'HemisphereLightHelper';
58503
58504		const geometry = new OctahedronGeometry( size );
58505		geometry.rotateY( Math.PI * 0.5 );
58506
58507		this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
58508		if ( this.color === undefined ) this.material.vertexColors = true;
58509
58510		const position = geometry.getAttribute( 'position' );
58511		const colors = new Float32Array( position.count * 3 );
58512
58513		geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
58514
58515		this.add( new Mesh( geometry, this.material ) );
58516
58517		this.update();
58518
58519	}
58520
58521	/**
58522	 * Frees the GPU-related resources allocated by this instance. Call this
58523	 * method whenever this instance is no longer used in your app.
58524	 */
58525	dispose() {
58526
58527		super.dispose();
58528
58529		this.children[ 0 ].geometry.dispose();
58530		this.children[ 0 ].material.dispose();
58531
58532	}
58533
58534	/**
58535	 * Updates the helper to match the position and direction of the
58536	 * light being visualized.
58537	 */
58538	update() {
58539
58540		const mesh = this.children[ 0 ];
58541
58542		if ( this.color !== undefined ) {
58543
58544			this.material.color.set( this.color );
58545
58546		} else {
58547
58548			const colors = mesh.geometry.getAttribute( 'color' );
58549
58550			_color1.copy( this.light.color );
58551			_color2.copy( this.light.groundColor );
58552
58553			for ( let i = 0, l = colors.count; i < l; i ++ ) {
58554
58555				const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
58556
58557				colors.setXYZ( i, color.r, color.g, color.b );
58558
58559			}
58560
58561			colors.needsUpdate = true;
58562
58563		}
58564
58565		this.matrixWorldNeedsUpdate = true;
58566
58567		this.light.updateWorldMatrix( true, false );
58568
58569		mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() );
58570
58571	}
58572
58573}
58574
58575/**
58576 * The helper is an object to define grids. Grids are two-dimensional
58577 * arrays of lines.
58578 *
58579 * ```js
58580 * const size = 10;
58581 * const divisions = 10;
58582 *
58583 * const gridHelper = new THREE.GridHelper( size, divisions );
58584 * scene.add( gridHelper );
58585 * ```
58586 *
58587 * @augments LineSegments
58588 */
58589class GridHelper extends LineSegments {
58590
58591	/**
58592	 * Constructs a new grid helper.
58593	 *
58594	 * @param {number} [size=10] - The size of the grid.
58595	 * @param {number} [divisions=10] - The number of divisions across the grid.
58596	 * @param {number|Color|string} [color1=0x444444] - The color of the center line.
58597	 * @param {number|Color|string} [color2=0x888888] - The color of the lines of the grid.
58598	 */
58599	constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
58600
58601		color1 = new Color( color1 );
58602		color2 = new Color( color2 );
58603
58604		const center = divisions / 2;
58605		const step = size / divisions;
58606		const halfSize = size / 2;
58607
58608		const vertices = [], colors = [];
58609
58610		for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
58611
58612			vertices.push( - halfSize, 0, k, halfSize, 0, k );
58613			vertices.push( k, 0, - halfSize, k, 0, halfSize );
58614
58615			const color = i === center ? color1 : color2;
58616
58617			color.toArray( colors, j ); j += 3;
58618			color.toArray( colors, j ); j += 3;
58619			color.toArray( colors, j ); j += 3;
58620			color.toArray( colors, j ); j += 3;
58621
58622		}
58623
58624		const geometry = new BufferGeometry();
58625		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
58626		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
58627
58628		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
58629
58630		super( geometry, material );
58631
58632		this.type = 'GridHelper';
58633
58634	}
58635
58636	/**
58637	 * Frees the GPU-related resources allocated by this instance. Call this
58638	 * method whenever this instance is no longer used in your app.
58639	 */
58640	dispose() {
58641
58642		super.dispose();
58643
58644		this.geometry.dispose();
58645		this.material.dispose();
58646
58647	}
58648
58649}
58650
58651/**
58652 * This helper is an object to define polar grids. Grids are
58653 * two-dimensional arrays of lines.
58654 *
58655 * ```js
58656 * const radius = 10;
58657 * const sectors = 16;
58658 * const rings = 8;
58659 * const divisions = 64;
58660 *
58661 * const helper = new THREE.PolarGridHelper( radius, sectors, rings, divisions );
58662 * scene.add( helper );
58663 * ```
58664 *
58665 * @augments LineSegments
58666 */
58667class PolarGridHelper extends LineSegments {
58668
58669	/**
58670	 * Constructs a new polar grid helper.
58671	 *
58672	 * @param {number} [radius=10] - The radius of the polar grid. This can be any positive number.
58673	 * @param {number} [sectors=16] - The number of sectors the grid will be divided into. This can be any positive integer.
58674	 * @param {number} [rings=16] - The number of rings. This can be any positive integer.
58675	 * @param {number} [divisions=64] - The number of line segments used for each circle. This can be any positive integer.
58676	 * @param {number|Color|string} [color1=0x444444] - The first color used for grid elements.
58677	 * @param {number|Color|string} [color2=0x888888] -  The second color used for grid elements.
58678	 */
58679	constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
58680
58681		color1 = new Color( color1 );
58682		color2 = new Color( color2 );
58683
58684		const vertices = [];
58685		const colors = [];
58686
58687		// create the sectors
58688
58689		if ( sectors > 1 ) {
58690
58691			for ( let i = 0; i < sectors; i ++ ) {
58692
58693				const v = ( i / sectors ) * ( Math.PI * 2 );
58694
58695				const x = Math.sin( v ) * radius;
58696				const z = Math.cos( v ) * radius;
58697
58698				vertices.push( 0, 0, 0 );
58699				vertices.push( x, 0, z );
58700
58701				const color = ( i & 1 ) ? color1 : color2;
58702
58703				colors.push( color.r, color.g, color.b );
58704				colors.push( color.r, color.g, color.b );
58705
58706			}
58707
58708		}
58709
58710		// create the rings
58711
58712		for ( let i = 0; i < rings; i ++ ) {
58713
58714			const color = ( i & 1 ) ? color1 : color2;
58715
58716			const r = radius - ( radius / rings * i );
58717
58718			for ( let j = 0; j < divisions; j ++ ) {
58719
58720				// first vertex
58721
58722				let v = ( j / divisions ) * ( Math.PI * 2 );
58723
58724				let x = Math.sin( v ) * r;
58725				let z = Math.cos( v ) * r;
58726
58727				vertices.push( x, 0, z );
58728				colors.push( color.r, color.g, color.b );
58729
58730				// second vertex
58731
58732				v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
58733
58734				x = Math.sin( v ) * r;
58735				z = Math.cos( v ) * r;
58736
58737				vertices.push( x, 0, z );
58738				colors.push( color.r, color.g, color.b );
58739
58740			}
58741
58742		}
58743
58744		const geometry = new BufferGeometry();
58745		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
58746		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
58747
58748		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
58749
58750		super( geometry, material );
58751
58752		this.type = 'PolarGridHelper';
58753
58754	}
58755
58756	/**
58757	 * Frees the GPU-related resources allocated by this instance. Call this
58758	 * method whenever this instance is no longer used in your app.
58759	 */
58760	dispose() {
58761
58762		super.dispose();
58763
58764		this.geometry.dispose();
58765		this.material.dispose();
58766
58767	}
58768
58769}
58770
58771const _v1 = /*@__PURE__*/ new Vector3();
58772const _v2 = /*@__PURE__*/ new Vector3();
58773const _v3 = /*@__PURE__*/ new Vector3();
58774
58775/**
58776 * Helper object to assist with visualizing a {@link DirectionalLight}'s
58777 * effect on the scene. This consists of a plane and a line representing the
58778 * light's position and direction.
58779 *
58780 * When the directional light or its target are transformed or light properties
58781 * are changed, it's necessary to call the `update()` method of the respective helper.
58782 *
58783 * ```js
58784 * const light = new THREE.DirectionalLight( 0xFFFFFF );
58785 * scene.add( light );
58786 *
58787 * const helper = new THREE.DirectionalLightHelper( light, 5 );
58788 * scene.add( helper );
58789 * ```
58790 *
58791 * @augments Object3D
58792 */
58793class DirectionalLightHelper extends Object3D {
58794
58795	/**
58796	 * Constructs a new directional light helper.
58797	 *
58798	 * @param {DirectionalLight} light - The light to be visualized.
58799	 * @param {number} [size=1] - The dimensions of the plane.
58800	 * @param {number|Color|string} [color] - The helper's color. If not set, the helper will take
58801	 * the color of the light.
58802	 */
58803	constructor( light, size, color ) {
58804
58805		super();
58806
58807		/**
58808		 * The light being visualized.
58809		 *
58810		 * @type {DirectionalLight}
58811		 */
58812		this.light = light;
58813
58814		this.matrix = light.matrixWorld;
58815		this.matrixAutoUpdate = false;
58816
58817		/**
58818		 * The color parameter passed in the constructor.
58819		 * If not set, the helper will take the color of the light.
58820		 *
58821		 * @type {number|Color|string}
58822		 */
58823		this.color = color;
58824
58825		this.type = 'DirectionalLightHelper';
58826
58827		if ( size === undefined ) size = 1;
58828
58829		let geometry = new BufferGeometry();
58830		geometry.setAttribute( 'position', new Float32BufferAttribute( [
58831			- size, size, 0,
58832			size, size, 0,
58833			size, - size, 0,
58834			- size, - size, 0,
58835			- size, size, 0
58836		], 3 ) );
58837
58838		const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
58839
58840		/**
58841		 * Contains the line showing the location of the directional light.
58842		 *
58843		 * @type {Line}
58844		 */
58845		this.lightPlane = new Line( geometry, material );
58846		this.add( this.lightPlane );
58847
58848		geometry = new BufferGeometry();
58849		geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
58850
58851		/**
58852		 * Represents the target line of the directional light.
58853		 *
58854		 * @type {Line}
58855		 */
58856		this.targetLine = new Line( geometry, material );
58857		this.add( this.targetLine );
58858
58859		this.update();
58860
58861	}
58862
58863	/**
58864	 * Frees the GPU-related resources allocated by this instance. Call this
58865	 * method whenever this instance is no longer used in your app.
58866	 */
58867	dispose() {
58868
58869		super.dispose();
58870
58871		this.lightPlane.geometry.dispose();
58872		this.lightPlane.material.dispose();
58873		this.targetLine.geometry.dispose();
58874		this.targetLine.material.dispose();
58875
58876	}
58877
58878	/**
58879	 * Updates the helper to match the position and direction of the
58880	 * light being visualized.
58881	 */
58882	update() {
58883
58884		this.matrixWorldNeedsUpdate = true;
58885
58886		this.light.updateWorldMatrix( true, false );
58887		this.light.target.updateWorldMatrix( true, false );
58888
58889		_v1.setFromMatrixPosition( this.light.matrixWorld );
58890		_v2.setFromMatrixPosition( this.light.target.matrixWorld );
58891		_v3.subVectors( _v2, _v1 );
58892
58893		this.lightPlane.lookAt( _v2 );
58894
58895		if ( this.color !== undefined ) {
58896
58897			this.lightPlane.material.color.set( this.color );
58898			this.targetLine.material.color.set( this.color );
58899
58900		} else {
58901
58902			this.lightPlane.material.color.copy( this.light.color );
58903			this.targetLine.material.color.copy( this.light.color );
58904
58905		}
58906
58907		this.targetLine.lookAt( _v2 );
58908		this.targetLine.scale.z = _v3.length();
58909
58910	}
58911
58912}
58913
58914const _vector = /*@__PURE__*/ new Vector3();
58915const _camera = /*@__PURE__*/ new Camera();
58916
58917/**
58918 * This helps with visualizing what a camera contains in its frustum. It
58919 * visualizes the frustum of a camera using a line segments.
58920 *
58921 * Based on frustum visualization in [lightgl.js shadowmap example](https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html).
58922 *
58923 * `CameraHelper` must be a child of the scene.
58924 *
58925 * When the camera is transformed or its projection matrix is changed, it's necessary
58926 * to call the `update()` method of the respective helper.
58927 *
58928 * ```js
58929 * const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
58930 * const helper = new THREE.CameraHelper( camera );
58931 * scene.add( helper );
58932 * ```
58933 *
58934 * @augments LineSegments
58935 */
58936class CameraHelper extends LineSegments {
58937
58938	/**
58939	 * Constructs a new arrow helper.
58940	 *
58941	 * @param {Camera} camera - The camera to visualize.
58942	 */
58943	constructor( camera ) {
58944
58945		const geometry = new BufferGeometry();
58946		const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
58947
58948		const vertices = [];
58949		const colors = [];
58950
58951		const pointMap = {};
58952
58953		// near
58954
58955		addLine( 'n1', 'n2' );
58956		addLine( 'n2', 'n4' );
58957		addLine( 'n4', 'n3' );
58958		addLine( 'n3', 'n1' );
58959
58960		// far
58961
58962		addLine( 'f1', 'f2' );
58963		addLine( 'f2', 'f4' );
58964		addLine( 'f4', 'f3' );
58965		addLine( 'f3', 'f1' );
58966
58967		// sides
58968
58969		addLine( 'n1', 'f1' );
58970		addLine( 'n2', 'f2' );
58971		addLine( 'n3', 'f3' );
58972		addLine( 'n4', 'f4' );
58973
58974		// cone
58975
58976		addLine( 'p', 'n1' );
58977		addLine( 'p', 'n2' );
58978		addLine( 'p', 'n3' );
58979		addLine( 'p', 'n4' );
58980
58981		// up
58982
58983		addLine( 'u1', 'u2' );
58984		addLine( 'u2', 'u3' );
58985		addLine( 'u3', 'u1' );
58986
58987		// target
58988
58989		addLine( 'c', 't' );
58990		addLine( 'p', 'c' );
58991
58992		// cross
58993
58994		addLine( 'cn1', 'cn2' );
58995		addLine( 'cn3', 'cn4' );
58996
58997		addLine( 'cf1', 'cf2' );
58998		addLine( 'cf3', 'cf4' );
58999
59000		function addLine( a, b ) {
59001
59002			addPoint( a );
59003			addPoint( b );
59004
59005		}
59006
59007		function addPoint( id ) {
59008
59009			vertices.push( 0, 0, 0 );
59010			colors.push( 0, 0, 0 );
59011
59012			if ( pointMap[ id ] === undefined ) {
59013
59014				pointMap[ id ] = [];
59015
59016			}
59017
59018			pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
59019
59020		}
59021
59022		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
59023		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
59024
59025		super( geometry, material );
59026
59027		this.type = 'CameraHelper';
59028
59029		/**
59030		 * The camera being visualized.
59031		 *
59032		 * @type {Camera}
59033		 */
59034		this.camera = camera;
59035		if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
59036
59037		this.matrix = camera.matrixWorld;
59038		this.matrixAutoUpdate = false;
59039
59040		/**
59041		 * This contains the points used to visualize the camera.
59042		 *
59043		 * @type {Object<string,Array<number>>}
59044		 */
59045		this.pointMap = pointMap;
59046
59047		this.update();
59048
59049		// colors
59050
59051		const colorFrustum = new Color( 0xffaa00 );
59052		const colorCone = new Color( 0xff0000 );
59053		const colorUp = new Color( 0x00aaff );
59054		const colorTarget = new Color( 0xffffff );
59055		const colorCross = new Color( 0x333333 );
59056
59057		this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross );
59058
59059	}
59060
59061	/**
59062	 * Defines the colors of the helper.
59063	 *
59064	 * @param {Color} frustum - The frustum line color.
59065	 * @param {Color} cone - The cone line color.
59066	 * @param {Color} up - The up line color.
59067	 * @param {Color} target - The target line color.
59068	 * @param {Color} cross - The cross line color.
59069	 * @return {CameraHelper} A reference to this helper.
59070	 */
59071	setColors( frustum, cone, up, target, cross ) {
59072
59073		const geometry = this.geometry;
59074
59075		const colorAttribute = geometry.getAttribute( 'color' );
59076
59077		// near
59078
59079		colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2
59080		colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4
59081		colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3
59082		colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1
59083
59084		// far
59085
59086		colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2
59087		colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4
59088		colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3
59089		colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1
59090
59091		// sides
59092
59093		colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1
59094		colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2
59095		colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3
59096		colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4
59097
59098		// cone
59099
59100		colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1
59101		colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2
59102		colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3
59103		colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4
59104
59105		// up
59106
59107		colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2
59108		colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3
59109		colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1
59110
59111		// target
59112
59113		colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t
59114		colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c
59115
59116		// cross
59117
59118		colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2
59119		colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4
59120
59121		colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2
59122		colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4
59123
59124		colorAttribute.needsUpdate = true;
59125
59126		return this;
59127
59128	}
59129
59130	/**
59131	 * Updates the helper based on the projection matrix of the camera.
59132	 */
59133	update() {
59134
59135		const geometry = this.geometry;
59136		const pointMap = this.pointMap;
59137
59138		const w = 1, h = 1;
59139
59140		let nearZ, farZ;
59141
59142		// we need just camera projection matrix inverse
59143		// world matrix must be identity
59144
59145		_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
59146
59147		// Adjust z values based on coordinate system
59148
59149		if ( this.camera.reversedDepth === true ) {
59150
59151			nearZ = 1;
59152			farZ = 0;
59153
59154		} else {
59155
59156			if ( this.camera.coordinateSystem === WebGLCoordinateSystem ) {
59157
59158				nearZ = -1;
59159				farZ = 1;
59160
59161			} else if ( this.camera.coordinateSystem === WebGPUCoordinateSystem ) {
59162
59163				nearZ = 0;
59164				farZ = 1;
59165
59166			} else {
59167
59168				throw new Error( 'THREE.CameraHelper.update(): Invalid coordinate system: ' + this.camera.coordinateSystem );
59169
59170			}
59171
59172		}
59173
59174
59175		// center / target
59176		setPoint( 'c', pointMap, geometry, _camera, 0, 0, nearZ );
59177		setPoint( 't', pointMap, geometry, _camera, 0, 0, farZ );
59178
59179		// near
59180
59181		setPoint( 'n1', pointMap, geometry, _camera, - w, - h, nearZ );
59182		setPoint( 'n2', pointMap, geometry, _camera, w, - h, nearZ );
59183		setPoint( 'n3', pointMap, geometry, _camera, - w, h, nearZ );
59184		setPoint( 'n4', pointMap, geometry, _camera, w, h, nearZ );
59185
59186		// far
59187
59188		setPoint( 'f1', pointMap, geometry, _camera, - w, - h, farZ );
59189		setPoint( 'f2', pointMap, geometry, _camera, w, - h, farZ );
59190		setPoint( 'f3', pointMap, geometry, _camera, - w, h, farZ );
59191		setPoint( 'f4', pointMap, geometry, _camera, w, h, farZ );
59192
59193		// up
59194
59195		setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, nearZ );
59196		setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, nearZ );
59197		setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, nearZ );
59198
59199		// cross
59200
59201		setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, farZ );
59202		setPoint( 'cf2', pointMap, geometry, _camera, w, 0, farZ );
59203		setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, farZ );
59204		setPoint( 'cf4', pointMap, geometry, _camera, 0, h, farZ );
59205
59206		setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, nearZ );
59207		setPoint( 'cn2', pointMap, geometry, _camera, w, 0, nearZ );
59208		setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, nearZ );
59209		setPoint( 'cn4', pointMap, geometry, _camera, 0, h, nearZ );
59210
59211		geometry.getAttribute( 'position' ).needsUpdate = true;
59212
59213	}
59214
59215	/**
59216	 * Frees the GPU-related resources allocated by this instance. Call this
59217	 * method whenever this instance is no longer used in your app.
59218	 */
59219	dispose() {
59220
59221		super.dispose();
59222
59223		this.geometry.dispose();
59224		this.material.dispose();
59225
59226	}
59227
59228}
59229
59230
59231function setPoint( point, pointMap, geometry, camera, x, y, z ) {
59232
59233	_vector.set( x, y, z ).unproject( camera );
59234
59235	const points = pointMap[ point ];
59236
59237	if ( points !== undefined ) {
59238
59239		const position = geometry.getAttribute( 'position' );
59240
59241		for ( let i = 0, l = points.length; i < l; i ++ ) {
59242
59243			position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z );
59244
59245		}
59246
59247	}
59248
59249}
59250
59251const _box = /*@__PURE__*/ new Box3();
59252
59253/**
59254 * Helper object to graphically show the world-axis-aligned bounding box
59255 * around an object. The actual bounding box is handled with {@link Box3},
59256 * this is just a visual helper for debugging. It can be automatically
59257 * resized with {@link BoxHelper#update} when the object it's created from
59258 * is transformed. Note that the object must have a geometry for this to work,
59259 * so it won't work with sprites.
59260 *
59261 * ```js
59262 * const sphere = new THREE.SphereGeometry();
59263 * const object = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( 0xff0000 ) );
59264 * const box = new THREE.BoxHelper( object, 0xffff00 );
59265 * scene.add( box );
59266 * ```
59267 *
59268 * @augments LineSegments
59269 */
59270class BoxHelper extends LineSegments {
59271
59272	/**
59273	 * Constructs a new box helper.
59274	 *
59275	 * @param {Object3D} [object] - The 3D object to show the world-axis-aligned bounding box.
59276	 * @param {number|Color|string} [color=0xffff00] - The box's color.
59277	 */
59278	constructor( object, color = 0xffff00 ) {
59279
59280		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 ] );
59281		const positions = new Float32Array( 8 * 3 );
59282
59283		const geometry = new BufferGeometry();
59284		geometry.setIndex( new BufferAttribute( indices, 1 ) );
59285		geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
59286
59287		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
59288
59289		/**
59290		 * The 3D object being visualized.
59291		 *
59292		 * @type {Object3D}
59293		 */
59294		this.object = object;
59295		this.type = 'BoxHelper';
59296
59297		this.matrixAutoUpdate = false;
59298
59299		this.update();
59300
59301	}
59302
59303	/**
59304	 * Updates the helper's geometry to match the dimensions of the object,
59305	 * including any children.
59306	 */
59307	update() {
59308
59309		if ( this.object !== undefined ) {
59310
59311			_box.setFromObject( this.object );
59312
59313		}
59314
59315		if ( _box.isEmpty() ) return;
59316
59317		const min = _box.min;
59318		const max = _box.max;
59319
59320		/*
59321			5____4
59322		1/___0/|
59323		| 6__|_7
59324		2/___3/
59325
59326		0: max.x, max.y, max.z
59327		1: min.x, max.y, max.z
59328		2: min.x, min.y, max.z
59329		3: max.x, min.y, max.z
59330		4: max.x, max.y, min.z
59331		5: min.x, max.y, min.z
59332		6: min.x, min.y, min.z
59333		7: max.x, min.y, min.z
59334		*/
59335
59336		const position = this.geometry.attributes.position;
59337		const array = position.array;
59338
59339		array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
59340		array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
59341		array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
59342		array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
59343		array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
59344		array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
59345		array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
59346		array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
59347
59348		position.needsUpdate = true;
59349
59350		this.geometry.computeBoundingSphere();
59351
59352	}
59353
59354	/**
59355	 * Updates the wireframe box for the passed object.
59356	 *
59357	 * @param {Object3D} object - The 3D object to create the helper for.
59358	 * @return {BoxHelper} A reference to this instance.
59359	 */
59360	setFromObject( object ) {
59361
59362		this.object = object;
59363		this.update();
59364
59365		return this;
59366
59367	}
59368
59369	copy( source, recursive ) {
59370
59371		super.copy( source, recursive );
59372
59373		this.object = source.object;
59374
59375		return this;
59376
59377	}
59378
59379	/**
59380	 * Frees the GPU-related resources allocated by this instance. Call this
59381	 * method whenever this instance is no longer used in your app.
59382	 */
59383	dispose() {
59384
59385		super.dispose();
59386
59387		this.geometry.dispose();
59388		this.material.dispose();
59389
59390	}
59391
59392}
59393
59394/**
59395 * A helper object to visualize an instance of {@link Box3}.
59396 *
59397 * ```js
59398 * const box = new THREE.Box3();
59399 * box.setFromCenterAndSize( new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 2, 1, 3 ) );
59400 *
59401 * const helper = new THREE.Box3Helper( box, 0xffff00 );
59402 * scene.add( helper )
59403 * ```
59404 *
59405 * @augments LineSegments
59406 */
59407class Box3Helper extends LineSegments {
59408
59409	/**
59410	 * Constructs a new box3 helper.
59411	 *
59412	 * @param {Box3} box - The box to visualize.
59413	 * @param {number|Color|string} [color=0xffff00] - The box's color.
59414	 */
59415	constructor( box, color = 0xffff00 ) {
59416
59417		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 ] );
59418
59419		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 ];
59420
59421		const geometry = new BufferGeometry();
59422
59423		geometry.setIndex( new BufferAttribute( indices, 1 ) );
59424
59425		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
59426
59427		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
59428
59429		/**
59430		 * The box being visualized.
59431		 *
59432		 * @type {Box3}
59433		 */
59434		this.box = box;
59435
59436		this.type = 'Box3Helper';
59437
59438		this.geometry.computeBoundingSphere();
59439
59440	}
59441
59442	updateMatrixWorld( force ) {
59443
59444		const box = this.box;
59445
59446		if ( box.isEmpty() ) return;
59447
59448		box.getCenter( this.position );
59449
59450		box.getSize( this.scale );
59451
59452		this.scale.multiplyScalar( 0.5 );
59453
59454		super.updateMatrixWorld( force );
59455
59456	}
59457
59458	/**
59459	 * Frees the GPU-related resources allocated by this instance. Call this
59460	 * method whenever this instance is no longer used in your app.
59461	 */
59462	dispose() {
59463
59464		super.dispose();
59465
59466		this.geometry.dispose();
59467		this.material.dispose();
59468
59469	}
59470
59471}
59472
59473/**
59474 * A helper object to visualize an instance of {@link Plane}.
59475 *
59476 * ```js
59477 * const plane = new THREE.Plane( new THREE.Vector3( 1, 1, 0.2 ), 3 );
59478 * const helper = new THREE.PlaneHelper( plane, 1, 0xffff00 );
59479 * scene.add( helper );
59480 * ```
59481 *
59482 * @augments Line
59483 */
59484class PlaneHelper extends Line {
59485
59486	/**
59487	 * Constructs a new plane helper.
59488	 *
59489	 * @param {Plane} plane - The plane to be visualized.
59490	 * @param {number} [size=1] - The side length of plane helper.
59491	 * @param {number|Color|string} [hex=0xffff00] - The helper's color.
59492	 */
59493	constructor( plane, size = 1, hex = 0xffff00 ) {
59494
59495		const color = hex;
59496
59497		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 ];
59498
59499		const geometry = new BufferGeometry();
59500		geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
59501		geometry.computeBoundingSphere();
59502
59503		super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
59504
59505		this.type = 'PlaneHelper';
59506
59507		/**
59508		 * The plane being visualized.
59509		 *
59510		 * @type {Plane}
59511		 */
59512		this.plane = plane;
59513
59514		/**
59515		 * The side length of plane helper.
59516		 *
59517		 * @type {number}
59518		 * @default 1
59519		 */
59520		this.size = size;
59521
59522		const positions2 = [ 1, 1, 0, -1, 1, 0, -1, -1, 0, 1, 1, 0, -1, -1, 0, 1, -1, 0 ];
59523
59524		const geometry2 = new BufferGeometry();
59525		geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
59526		geometry2.computeBoundingSphere();
59527
59528		this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
59529
59530	}
59531
59532	updateMatrixWorld( force ) {
59533
59534		this.position.set( 0, 0, 0 );
59535
59536		this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 );
59537
59538		this.lookAt( this.plane.normal );
59539
59540		this.translateZ( - this.plane.constant );
59541
59542		super.updateMatrixWorld( force );
59543
59544	}
59545
59546	/**
59547	 * Updates the helper to match the position and direction of the
59548	 * light being visualized.
59549	 */
59550	dispose() {
59551
59552		super.dispose();
59553
59554		this.geometry.dispose();
59555		this.material.dispose();
59556		this.children[ 0 ].geometry.dispose();
59557		this.children[ 0 ].material.dispose();
59558
59559	}
59560
59561}
59562
59563const _axis = /*@__PURE__*/ new Vector3();
59564let _lineGeometry, _coneGeometry;
59565
59566/**
59567 * An 3D arrow object for visualizing directions.
59568 *
59569 * ```js
59570 * const dir = new THREE.Vector3( 1, 2, 0 );
59571 *
59572 * //normalize the direction vector (convert to vector of length 1)
59573 * dir.normalize();
59574 *
59575 * const origin = new THREE.Vector3( 0, 0, 0 );
59576 * const length = 1;
59577 * const hex = 0xffff00;
59578 *
59579 * const arrowHelper = new THREE.ArrowHelper( dir, origin, length, hex );
59580 * scene.add( arrowHelper );
59581 * ```
59582 *
59583 * @augments Object3D
59584 */
59585class ArrowHelper extends Object3D {
59586
59587	/**
59588	 * Constructs a new arrow helper.
59589	 *
59590	 * @param {Vector3} [dir=(0, 0, 1)] - The (normalized) direction vector.
59591	 * @param {Vector3} [origin=(0, 0, 0)] - Point at which the arrow starts.
59592	 * @param {number} [length=1] - Length of the arrow in world units.
59593	 * @param {(number|Color|string)} [color=0xffff00] - Color of the arrow.
59594	 * @param {number} [headLength=length*0.2] - The length of the head of the arrow.
59595	 * @param {number} [headWidth=headLength*0.2] - The width of the head of the arrow.
59596	 */
59597	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 ) {
59598
59599		super();
59600
59601		this.type = 'ArrowHelper';
59602
59603		if ( _lineGeometry === undefined ) {
59604
59605			_lineGeometry = new BufferGeometry();
59606			_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
59607
59608			_coneGeometry = new ConeGeometry( 0.5, 1, 5, 1 );
59609			_coneGeometry.translate( 0, -0.5, 0 );
59610
59611		}
59612
59613		this.position.copy( origin );
59614
59615		/**
59616		 * The line part of the arrow helper.
59617		 *
59618		 * @type {Line}
59619		 */
59620		this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
59621		this.line.matrixAutoUpdate = false;
59622		this.add( this.line );
59623
59624		/**
59625		 * The cone part of the arrow helper.
59626		 *
59627		 * @type {Mesh}
59628		 */
59629		this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
59630		this.cone.matrixAutoUpdate = false;
59631		this.add( this.cone );
59632
59633		this.setDirection( dir );
59634		this.setLength( length, headLength, headWidth );
59635
59636	}
59637
59638	/**
59639	 * Sets the direction of the helper.
59640	 *
59641	 * @param {Vector3} dir - The normalized direction vector.
59642	 */
59643	setDirection( dir ) {
59644
59645		// dir is assumed to be normalized
59646
59647		if ( dir.y > 0.99999 ) {
59648
59649			this.quaternion.set( 0, 0, 0, 1 );
59650
59651		} else if ( dir.y < -0.99999 ) {
59652
59653			this.quaternion.set( 1, 0, 0, 0 );
59654
59655		} else {
59656
59657			_axis.set( dir.z, 0, - dir.x ).normalize();
59658
59659			const radians = Math.acos( dir.y );
59660
59661			this.quaternion.setFromAxisAngle( _axis, radians );
59662
59663		}
59664
59665	}
59666
59667	/**
59668	 * Sets the length of the helper.
59669	 *
59670	 * @param {number} length - Length of the arrow in world units.
59671	 * @param {number} [headLength=length*0.2] - The length of the head of the arrow.
59672	 * @param {number} [headWidth=headLength*0.2] - The width of the head of the arrow.
59673	 */
59674	setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
59675
59676		this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
59677		this.line.updateMatrix();
59678
59679		this.cone.scale.set( headWidth, headLength, headWidth );
59680		this.cone.position.y = length;
59681		this.cone.updateMatrix();
59682
59683	}
59684
59685	/**
59686	 * Sets the color of the helper.
59687	 *
59688	 * @param {number|Color|string} color - The color to set.
59689	 */
59690	setColor( color ) {
59691
59692		this.line.material.color.set( color );
59693		this.cone.material.color.set( color );
59694
59695	}
59696
59697	copy( source ) {
59698
59699		super.copy( source, false );
59700
59701		this.line.copy( source.line );
59702		this.cone.copy( source.cone );
59703
59704		return this;
59705
59706	}
59707
59708	/**
59709	 * Frees the GPU-related resources allocated by this instance. Call this
59710	 * method whenever this instance is no longer used in your app.
59711	 */
59712	dispose() {
59713
59714		super.dispose();
59715
59716		this.line.geometry.dispose();
59717		this.line.material.dispose();
59718		this.cone.geometry.dispose();
59719		this.cone.material.dispose();
59720
59721	}
59722
59723}
59724
59725/**
59726 * An axis object to visualize the 3 axes in a simple way.
59727 * The X axis is red. The Y axis is green. The Z axis is blue.
59728 *
59729 * ```js
59730 * const axesHelper = new THREE.AxesHelper( 5 );
59731 * scene.add( axesHelper );
59732 * ```
59733 *
59734 * @augments LineSegments
59735 */
59736class AxesHelper extends LineSegments {
59737
59738	/**
59739	 * Constructs a new axes helper.
59740	 *
59741	 * @param {number} [size=1] - Size of the lines representing the axes.
59742	 */
59743	constructor( size = 1 ) {
59744
59745		const vertices = [
59746			0, 0, 0,	size, 0, 0,
59747			0, 0, 0,	0, size, 0,
59748			0, 0, 0,	0, 0, size
59749		];
59750
59751		const colors = [
59752			1, 0, 0,	1, 0.6, 0,
59753			0, 1, 0,	0.6, 1, 0,
59754			0, 0, 1,	0, 0.6, 1
59755		];
59756
59757		const geometry = new BufferGeometry();
59758		geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
59759		geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
59760
59761		const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
59762
59763		super( geometry, material );
59764
59765		this.type = 'AxesHelper';
59766
59767	}
59768
59769	/**
59770	 * Defines the colors of the axes helper.
59771	 *
59772	 * @param {number|Color|string} xAxisColor - The color for the x axis.
59773	 * @param {number|Color|string} yAxisColor - The color for the y axis.
59774	 * @param {number|Color|string} zAxisColor - The color for the z axis.
59775	 * @return {AxesHelper} A reference to this axes helper.
59776	 */
59777	setColors( xAxisColor, yAxisColor, zAxisColor ) {
59778
59779		const color = new Color();
59780		const array = this.geometry.attributes.color.array;
59781
59782		color.set( xAxisColor );
59783		color.toArray( array, 0 );
59784		color.toArray( array, 3 );
59785
59786		color.set( yAxisColor );
59787		color.toArray( array, 6 );
59788		color.toArray( array, 9 );
59789
59790		color.set( zAxisColor );
59791		color.toArray( array, 12 );
59792		color.toArray( array, 15 );
59793
59794		this.geometry.attributes.color.needsUpdate = true;
59795
59796		return this;
59797
59798	}
59799
59800	/**
59801	 * Frees the GPU-related resources allocated by this instance. Call this
59802	 * method whenever this instance is no longer used in your app.
59803	 */
59804	dispose() {
59805
59806		super.dispose();
59807
59808		this.geometry.dispose();
59809		this.material.dispose();
59810
59811	}
59812
59813}
59814
59815/**
59816 * This class is used to convert a series of paths to an array of
59817 * shapes. It is specifically used in context of fonts and SVG.
59818 */
59819class ShapePath {
59820
59821	/**
59822	 * Constructs a new shape path.
59823	 */
59824	constructor() {
59825
59826		this.type = 'ShapePath';
59827
59828		/**
59829		 * The color of the shape.
59830		 *
59831		 * @type {Color}
59832		 */
59833		this.color = new Color();
59834
59835		/**
59836		 * The paths that have been generated for this shape.
59837		 *
59838		 * @type {Array<Path>}
59839		 * @default null
59840		 */
59841		this.subPaths = [];
59842
59843		/**
59844		 * The current path that is being generated.
59845		 *
59846		 * @type {?Path}
59847		 * @default null
59848		 */
59849		this.currentPath = null;
59850
59851		/**
59852		 * An object that can be used to store custom data about the shape path.
59853		 * Mainly used by SVGLoader to store style information.
59854		 *
59855		 * @type {Object}
59856		 */
59857		this.userData = {};
59858
59859	}
59860
59861	/**
59862	 * Creates a new path and moves it current point to the given one.
59863	 *
59864	 * @param {number} x - The x coordinate.
59865	 * @param {number} y - The y coordinate.
59866	 * @return {ShapePath} A reference to this shape path.
59867	 */
59868	moveTo( x, y ) {
59869
59870		this.currentPath = new Path();
59871		this.subPaths.push( this.currentPath );
59872		this.currentPath.moveTo( x, y );
59873
59874		return this;
59875
59876	}
59877
59878	/**
59879	 * Adds an instance of {@link LineCurve} to the path by connecting
59880	 * the current point with the given one.
59881	 *
59882	 * @param {number} x - The x coordinate of the end point.
59883	 * @param {number} y - The y coordinate of the end point.
59884	 * @return {ShapePath} A reference to this shape path.
59885	 */
59886	lineTo( x, y ) {
59887
59888		this.currentPath.lineTo( x, y );
59889
59890		return this;
59891
59892	}
59893
59894	/**
59895	 * Adds an instance of {@link QuadraticBezierCurve} to the path by connecting
59896	 * the current point with the given one.
59897	 *
59898	 * @param {number} aCPx - The x coordinate of the control point.
59899	 * @param {number} aCPy - The y coordinate of the control point.
59900	 * @param {number} aX - The x coordinate of the end point.
59901	 * @param {number} aY - The y coordinate of the end point.
59902	 * @return {ShapePath} A reference to this shape path.
59903	 */
59904	quadraticCurveTo( aCPx, aCPy, aX, aY ) {
59905
59906		this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
59907
59908		return this;
59909
59910	}
59911
59912	/**
59913	 * Adds an instance of {@link CubicBezierCurve} to the path by connecting
59914	 * the current point with the given one.
59915	 *
59916	 * @param {number} aCP1x - The x coordinate of the first control point.
59917	 * @param {number} aCP1y - The y coordinate of the first control point.
59918	 * @param {number} aCP2x - The x coordinate of the second control point.
59919	 * @param {number} aCP2y - The y coordinate of the second control point.
59920	 * @param {number} aX - The x coordinate of the end point.
59921	 * @param {number} aY - The y coordinate of the end point.
59922	 * @return {ShapePath} A reference to this shape path.
59923	 */
59924	bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
59925
59926		this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
59927
59928		return this;
59929
59930	}
59931
59932	/**
59933	 * Adds an instance of {@link SplineCurve} to the path by connecting
59934	 * the current point with the given list of points.
59935	 *
59936	 * @param {Array<Vector2>} pts - An array of points in 2D space.
59937	 * @return {ShapePath} A reference to this shape path.
59938	 */
59939	splineThru( pts ) {
59940
59941		this.currentPath.splineThru( pts );
59942
59943		return this;
59944
59945	}
59946
59947	/**
59948	 * Converts the paths into an array of shapes.
59949	 *
59950	 * @return {Array<Shape>} An array of shapes.
59951	 */
59952	toShapes() {
59953
59954		// Point-in-polygon test using the even-odd ray-casting rule. Valid for
59955		// simple (non self-intersecting) polygons.
59956		function pointInPolygon( p, polygon ) {
59957
59958			let inside = false;
59959			const n = polygon.length;
59960
59961			for ( let i = 0, j = n - 1; i < n; j = i ++ ) {
59962
59963				const a = polygon[ i ];
59964				const b = polygon[ j ];
59965
59966				if ( ( a.y > p.y ) !== ( b.y > p.y ) &&
59967							p.x < ( b.x - a.x ) * ( p.y - a.y ) / ( b.y - a.y ) + a.x ) {
59968
59969					inside = ! inside;
59970
59971				}
59972
59973			}
59974
59975			return inside;
59976
59977		}
59978
59979		// Returns a point guaranteed to be strictly inside the given simple
59980		// polygon. First tries the bounding-box center; if that falls outside
59981		// the polygon, casts a horizontal ray at the center's y and picks the
59982		// midpoint between the first two sorted intercepts.
59983		//
59984		// Port of paper.js' Path#getInteriorPoint()
59985		// https://github.com/paperjs/paper.js/blob/develop/src/path/PathItem.Boolean.js
59986		function getInteriorPoint( polygon, boundingBox ) {
59987
59988			const point = boundingBox.getCenter( new Vector2() );
59989
59990			if ( pointInPolygon( point, polygon ) ) return point;
59991
59992			const y = point.y;
59993			const intercepts = [];
59994			const n = polygon.length;
59995
59996			for ( let i = 0; i < n; i ++ ) {
59997
59998				const a = polygon[ i ];
59999				const b = polygon[ ( i + 1 ) % n ];
60000
60001				// Half-open crossing rule — counts each vertex exactly once and
60002				// skips horizontal edges.
60003				if ( ( a.y > y ) !== ( b.y > y ) ) {
60004
60005					const x = a.x + ( y - a.y ) * ( b.x - a.x ) / ( b.y - a.y );
60006					intercepts.push( x );
60007
60008				}
60009
60010			}
60011
60012			if ( intercepts.length > 1 ) {
60013
60014				intercepts.sort( ( a, b ) => a - b );
60015				point.x = ( intercepts[ 0 ] + intercepts[ 1 ] ) / 2;
60016
60017			}
60018
60019			return point;
60020
60021		}
60022
60023		// Resolve fill-rule. Defaults to 'nonzero'.
60024		let fillRule = ( this.userData.style && this.userData.style.fillRule ) || 'nonzero';
60025
60026		if ( fillRule !== 'nonzero' && fillRule !== 'evenodd' ) {
60027
60028			warn( 'Fill-rule "' + fillRule + '" is not supported, falling back to "nonzero".' );
60029			fillRule = 'nonzero';
60030
60031		}
60032
60033		// Predicate that decides whether a winding number falls inside the fill
60034		// region, per the SVG fill-rule spec. Works for negative windings too,
60035		// because JavaScript's bitwise AND preserves odd/even under two's
60036		// complement.
60037		const isInside = fillRule === 'nonzero'
60038			? ( w => w !== 0 )
60039			: ( w => ( w & 1 ) !== 0 );
60040
60041		// Build an entry per usable subpath. Self-winding follows the standard
60042		// convention used by ShapeUtils: counter-clockwise (signed area > 0)
60043		// contributes +1 to the winding number at an interior point,
60044		// clockwise contributes -1.
60045		const entries = [];
60046
60047		for ( const subPath of this.subPaths ) {
60048
60049			const points = subPath.getPoints();
60050			if ( points.length < 3 ) continue;
60051
60052			const area = ShapeUtils.area( points );
60053			if ( area === 0 ) continue;
60054
60055			const boundingBox = new Box2();
60056			for ( let i = 0; i < points.length; i ++ ) boundingBox.expandByPoint( points[ i ] );
60057
60058			entries.push( {
60059				subPath: subPath,
60060				points: points,
60061				boundingBox: boundingBox,
60062				interiorPoint: getInteriorPoint( points, boundingBox ),
60063				absArea: Math.abs( area ),
60064				winding: area < 0 ? -1 : 1,
60065				container: null,
60066				exclude: false,
60067				role: null
60068			} );
60069
60070		}
60071
60072		// Sort by area descending. This guarantees that any subpath that could
60073		// contain `entries[i]` is located at a smaller index and has already
60074		// been processed when it's entries[i]'s turn. Port of paper.js'
60075		// reorientPaths() algorithm.
60076		entries.sort( ( a, b ) => b.absArea - a.absArea );
60077
60078		// Walk already-processed entries from closest-in-size to largest,
60079		// stopping at the innermost container. Accumulate the container's
60080		// cumulative winding into this entry's winding so that the final value
60081		// equals the winding number at this entry's interior point.
60082		//
60083		// A subpath only contributes to the fill boundary when crossing it
60084		// actually flips the "insideness" per the fill rule; otherwise it's a
60085		// redundant overlap and gets excluded to avoid double-counting.
60086		for ( let i = 0; i < entries.length; i ++ ) {
60087
60088			const entry = entries[ i ];
60089			let containerWinding = 0;
60090
60091			for ( let j = i - 1; j >= 0; j -- ) {
60092
60093				const candidate = entries[ j ];
60094
60095				if ( ! candidate.boundingBox.containsBox( entry.boundingBox ) ) continue;
60096				if ( ! pointInPolygon( entry.interiorPoint, candidate.points ) ) continue;
60097
60098				entry.container = candidate.exclude ? candidate.container : candidate;
60099				containerWinding = candidate.winding;
60100				entry.winding += containerWinding;
60101				break;
60102
60103			}
60104
60105			if ( isInside( entry.winding ) === isInside( containerWinding ) ) {
60106
60107				entry.exclude = true;
60108
60109			}
60110
60111		}
60112
60113		// Classify retained entries. An entry is an outer shape if it has no
60114		// container or if its container is itself a hole (a solid nested inside
60115		// a hole becomes a new top-level shape); otherwise it's a hole in its
60116		// container. Entries were already sorted outermost-first, so each
60117		// container's role is known by the time we look at it.
60118		for ( const entry of entries ) {
60119
60120			if ( entry.exclude ) continue;
60121			entry.role = ( entry.container === null || entry.container.role === 'hole' ) ? 'outer' : 'hole';
60122
60123		}
60124
60125		// Build Shapes for outers first, then attach holes to their container's
60126		// Shape.
60127		const shapes = [];
60128		const shapeByEntry = new Map();
60129
60130		for ( const entry of entries ) {
60131
60132			if ( entry.exclude || entry.role !== 'outer' ) continue;
60133
60134			const shape = new Shape();
60135			shape.curves = entry.subPath.curves;
60136			shapes.push( shape );
60137			shapeByEntry.set( entry, shape );
60138
60139		}
60140
60141		for ( const entry of entries ) {
60142
60143			if ( entry.exclude || entry.role !== 'hole' ) continue;
60144
60145			const shape = shapeByEntry.get( entry.container );
60146			if ( ! shape ) continue;
60147
60148			const hole = new Path();
60149			hole.curves = entry.subPath.curves;
60150			shape.holes.push( hole );
60151
60152		}
60153
60154		return shapes;
60155
60156
60157	}
60158
60159}
60160
60161/**
60162 * Abstract base class for controls.
60163 *
60164 * @abstract
60165 * @augments EventDispatcher
60166 */
60167class Controls extends EventDispatcher {
60168
60169	/**
60170	 * Constructs a new controls instance.
60171	 *
60172	 * @param {Object3D} object - The object that is managed by the controls.
60173	 * @param {?HTMLElement} domElement - The HTML element used for event listeners.
60174	 */
60175	constructor( object, domElement = null ) {
60176
60177		super();
60178
60179		/**
60180		 * The object that is managed by the controls.
60181		 *
60182		 * @type {Object3D}
60183		 */
60184		this.object = object;
60185
60186		/**
60187		 * The HTML element used for event listeners.
60188		 *
60189		 * @type {?HTMLElement}
60190		 * @default null
60191		 */
60192		this.domElement = domElement;
60193
60194		/**
60195		 * Whether the controls responds to user input or not.
60196		 *
60197		 * @type {boolean}
60198		 * @default true
60199		 */
60200		this.enabled = true;
60201
60202		/**
60203		 * The internal state of the controls.
60204		 *
60205		 * @type {number}
60206		 * @default -1
60207		 */
60208		this.state = -1;
60209
60210		/**
60211		 * This object defines the keyboard input of the controls.
60212		 *
60213		 * @type {Object}
60214		 */
60215		this.keys = {};
60216
60217		/**
60218		 * This object defines what type of actions are assigned to the available mouse buttons.
60219		 * It depends on the control implementation what kind of mouse buttons and actions are supported.
60220		 *
60221		 * @type {{LEFT: ?number, MIDDLE: ?number, RIGHT: ?number}}
60222		 */
60223		this.mouseButtons = { LEFT: null, MIDDLE: null, RIGHT: null };
60224
60225		/**
60226		 * This object defines what type of actions are assigned to what kind of touch interaction.
60227		 * It depends on the control implementation what kind of touch interaction and actions are supported.
60228		 *
60229		 * @type {{ONE: ?number, TWO: ?number}}
60230		 */
60231		this.touches = { ONE: null, TWO: null };
60232
60233	}
60234
60235	/**
60236	 * Connects the controls to the DOM. This method has so called "side effects" since
60237	 * it adds the module's event listeners to the DOM.
60238	 *
60239	 * @param {HTMLElement} element - The DOM element to connect to.
60240	 */
60241	connect( element ) {
60242
60243		if ( this.domElement !== null ) this.disconnect();
60244
60245		this.domElement = element;
60246
60247	}
60248
60249	/**
60250	 * Disconnects the controls from the DOM.
60251	 */
60252	disconnect() {}
60253
60254	/**
60255	 * Call this method if you no longer want use to the controls. It frees all internal
60256	 * resources and removes all event listeners.
60257	 */
60258	dispose() {}
60259
60260	/**
60261	 * Controls should implement this method if they have to update their internal state
60262	 * per simulation step.
60263	 *
60264	 * @param {number} [delta] - The time delta in seconds.
60265	 */
60266	update( /* delta */ ) {}
60267
60268}
60269
60270/**
60271 * Scales the texture as large as possible within its surface without cropping
60272 * or stretching the texture. The method preserves the original aspect ratio of
60273 * the texture. Akin to CSS `object-fit: contain`
60274 *
60275 * @param {Texture} texture - The texture.
60276 * @param {number} aspect - The texture's aspect ratio.
60277 * @return {Texture} The updated texture.
60278 */
60279function contain( texture, aspect ) {
60280
60281	const imageAspect = ( texture.image && texture.image.width ) ? texture.image.width / texture.image.height : 1;
60282
60283	if ( imageAspect > aspect ) {
60284
60285		texture.repeat.x = 1;
60286		texture.repeat.y = imageAspect / aspect;
60287
60288		texture.offset.x = 0;
60289		texture.offset.y = ( 1 - texture.repeat.y ) / 2;
60290
60291	} else {
60292
60293		texture.repeat.x = aspect / imageAspect;
60294		texture.repeat.y = 1;
60295
60296		texture.offset.x = ( 1 - texture.repeat.x ) / 2;
60297		texture.offset.y = 0;
60298
60299	}
60300
60301	return texture;
60302
60303}
60304
60305/**
60306 * Scales the texture to the smallest possible size to fill the surface, leaving
60307 * no empty space. The method preserves the original aspect ratio of the texture.
60308 * Akin to CSS `object-fit: cover`.
60309 *
60310 * @param {Texture} texture - The texture.
60311 * @param {number} aspect - The texture's aspect ratio.
60312 * @return {Texture} The updated texture.
60313 */
60314function cover( texture, aspect ) {
60315
60316	const imageAspect = ( texture.image && texture.image.width ) ? texture.image.width / texture.image.height : 1;
60317
60318	if ( imageAspect > aspect ) {
60319
60320		texture.repeat.x = aspect / imageAspect;
60321		texture.repeat.y = 1;
60322
60323		texture.offset.x = ( 1 - texture.repeat.x ) / 2;
60324		texture.offset.y = 0;
60325
60326	} else {
60327
60328		texture.repeat.x = 1;
60329		texture.repeat.y = imageAspect / aspect;
60330
60331		texture.offset.x = 0;
60332		texture.offset.y = ( 1 - texture.repeat.y ) / 2;
60333
60334	}
60335
60336	return texture;
60337
60338}
60339
60340/**
60341 * Configures the texture to the default transformation. Akin to CSS `object-fit: fill`.
60342 *
60343 * @param {Texture} texture - The texture.
60344 * @return {Texture} The updated texture.
60345 */
60346function fill( texture ) {
60347
60348	texture.repeat.x = 1;
60349	texture.repeat.y = 1;
60350
60351	texture.offset.x = 0;
60352	texture.offset.y = 0;
60353
60354	return texture;
60355
60356}
60357
60358/**
60359 * Determines how many bytes must be used to represent the texture.
60360 *
60361 * @param {number} width - The width of the texture.
60362 * @param {number} height - The height of the texture.
60363 * @param {number} format - The texture's format.
60364 * @param {number} type - The texture's type.
60365 * @return {number} The byte length.
60366 */
60367function getByteLength( width, height, format, type ) {
60368
60369	const typeByteLength = getTextureTypeByteLength( type );
60370
60371	switch ( format ) {
60372
60373		// https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml
60374		case AlphaFormat:
60375			return width * height;
60376		case RedFormat:
60377			return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength;
60378		case RedIntegerFormat:
60379			return ( ( width * height ) / typeByteLength.components ) * typeByteLength.byteLength;
60380		case RGFormat:
60381			return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength;
60382		case RGIntegerFormat:
60383			return ( ( width * height * 2 ) / typeByteLength.components ) * typeByteLength.byteLength;
60384		case RGBFormat:
60385			return ( ( width * height * 3 ) / typeByteLength.components ) * typeByteLength.byteLength;
60386		case RGBAFormat:
60387			return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength;
60388		case RGBAIntegerFormat:
60389			return ( ( width * height * 4 ) / typeByteLength.components ) * typeByteLength.byteLength;
60390
60391		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_s3tc_srgb/
60392		case RGB_S3TC_DXT1_Format:
60393		case RGBA_S3TC_DXT1_Format:
60394			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8;
60395		case RGBA_S3TC_DXT3_Format:
60396		case RGBA_S3TC_DXT5_Format:
60397			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
60398
60399		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_pvrtc/
60400		case RGB_PVRTC_2BPPV1_Format:
60401		case RGBA_PVRTC_2BPPV1_Format:
60402			return ( Math.max( width, 16 ) * Math.max( height, 8 ) ) / 4;
60403		case RGB_PVRTC_4BPPV1_Format:
60404		case RGBA_PVRTC_4BPPV1_Format:
60405			return ( Math.max( width, 8 ) * Math.max( height, 8 ) ) / 2;
60406
60407		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_etc/
60408		case RGB_ETC1_Format:
60409		case RGB_ETC2_Format:
60410		case R11_EAC_Format:
60411		case SIGNED_R11_EAC_Format:
60412			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 8;
60413		case RGBA_ETC2_EAC_Format:
60414		case RG11_EAC_Format:
60415		case SIGNED_RG11_EAC_Format:
60416			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
60417
60418		// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/
60419		case RGBA_ASTC_4x4_Format:
60420			return Math.floor( ( width + 3 ) / 4 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
60421		case RGBA_ASTC_5x4_Format:
60422			return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 3 ) / 4 ) * 16;
60423		case RGBA_ASTC_5x5_Format:
60424			return Math.floor( ( width + 4 ) / 5 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
60425		case RGBA_ASTC_6x5_Format:
60426			return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
60427		case RGBA_ASTC_6x6_Format:
60428			return Math.floor( ( width + 5 ) / 6 ) * Math.floor( ( height + 5 ) / 6 ) * 16;
60429		case RGBA_ASTC_8x5_Format:
60430			return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
60431		case RGBA_ASTC_8x6_Format:
60432			return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 5 ) / 6 ) * 16;
60433		case RGBA_ASTC_8x8_Format:
60434			return Math.floor( ( width + 7 ) / 8 ) * Math.floor( ( height + 7 ) / 8 ) * 16;
60435		case RGBA_ASTC_10x5_Format:
60436			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 4 ) / 5 ) * 16;
60437		case RGBA_ASTC_10x6_Format:
60438			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 5 ) / 6 ) * 16;
60439		case RGBA_ASTC_10x8_Format:
60440			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 7 ) / 8 ) * 16;
60441		case RGBA_ASTC_10x10_Format:
60442			return Math.floor( ( width + 9 ) / 10 ) * Math.floor( ( height + 9 ) / 10 ) * 16;
60443		case RGBA_ASTC_12x10_Format:
60444			return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 9 ) / 10 ) * 16;
60445		case RGBA_ASTC_12x12_Format:
60446			return Math.floor( ( width + 11 ) / 12 ) * Math.floor( ( height + 11 ) / 12 ) * 16;
60447
60448		// https://registry.khronos.org/webgl/extensions/EXT_texture_compression_bptc/
60449		case RGBA_BPTC_Format:
60450		case RGB_BPTC_SIGNED_Format:
60451		case RGB_BPTC_UNSIGNED_Format:
60452			return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16;
60453
60454		// https://registry.khronos.org/webgl/extensions/EXT_texture_compression_rgtc/
60455		case RED_RGTC1_Format:
60456		case SIGNED_RED_RGTC1_Format:
60457			return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 8;
60458		case RED_GREEN_RGTC2_Format:
60459		case SIGNED_RED_GREEN_RGTC2_Format:
60460			return Math.ceil( width / 4 ) * Math.ceil( height / 4 ) * 16;
60461
60462	}
60463
60464	throw new Error(
60465		`Unable to determine texture byte length for ${format} format.`,
60466	);
60467
60468}
60469
60470function getTextureTypeByteLength( type ) {
60471
60472	switch ( type ) {
60473
60474		case UnsignedByteType:
60475		case ByteType:
60476			return { byteLength: 1, components: 1 };
60477		case UnsignedShortType:
60478		case ShortType:
60479		case HalfFloatType:
60480			return { byteLength: 2, components: 1 };
60481		case UnsignedShort4444Type:
60482		case UnsignedShort5551Type:
60483			return { byteLength: 2, components: 4 };
60484		case UnsignedIntType:
60485		case IntType:
60486		case FloatType:
60487			return { byteLength: 4, components: 1 };
60488		case UnsignedInt5999Type:
60489		case UnsignedInt101111Type:
60490			return { byteLength: 4, components: 3 };
60491
60492	}
60493
60494	throw new Error( `THREE.TextureUtils: Unknown texture type ${type}.` );
60495
60496}
60497
60498/**
60499 * A class containing utility functions for textures.
60500 *
60501 * @hideconstructor
60502 */
60503class TextureUtils {
60504
60505	/**
60506	 * Scales the texture as large as possible within its surface without cropping
60507	 * or stretching the texture. The method preserves the original aspect ratio of
60508	 * the texture. Akin to CSS `object-fit: contain`
60509	 *
60510	 * @param {Texture} texture - The texture.
60511	 * @param {number} aspect - The texture's aspect ratio.
60512	 * @return {Texture} The updated texture.
60513	 */
60514	static contain( texture, aspect ) {
60515
60516		return contain( texture, aspect );
60517
60518	}
60519
60520	/**
60521	 * Scales the texture to the smallest possible size to fill the surface, leaving
60522	 * no empty space. The method preserves the original aspect ratio of the texture.
60523	 * Akin to CSS `object-fit: cover`.
60524	 *
60525	 * @param {Texture} texture - The texture.
60526	 * @param {number} aspect - The texture's aspect ratio.
60527	 * @return {Texture} The updated texture.
60528	 */
60529	static cover( texture, aspect ) {
60530
60531		return cover( texture, aspect );
60532
60533	}
60534
60535	/**
60536	 * Configures the texture to the default transformation. Akin to CSS `object-fit: fill`.
60537	 *
60538	 * @param {Texture} texture - The texture.
60539	 * @return {Texture} The updated texture.
60540	 */
60541	static fill( texture ) {
60542
60543		return fill( texture );
60544
60545	}
60546
60547	/**
60548	 * Determines how many bytes must be used to represent the texture.
60549	 *
60550	 * @param {number} width - The width of the texture.
60551	 * @param {number} height - The height of the texture.
60552	 * @param {number} format - The texture's format.
60553	 * @param {number} type - The texture's type.
60554	 * @return {number} The byte length.
60555	 */
60556	static getByteLength( width, height, format, type ) {
60557
60558		return getByteLength( width, height, format, type );
60559
60560	}
60561
60562}
60563
60564if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
60565
60566	__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
60567		revision: REVISION,
60568	} } ) );
60569
60570}
60571
60572if ( typeof window !== 'undefined' ) {
60573
60574	if ( window.__THREE__ ) {
60575
60576		warn( 'WARNING: Multiple instances of Three.js being imported.' );
60577
60578	} else {
60579
60580		window.__THREE__ = REVISION;
60581
60582	}
60583
60584}
60585
60586export { 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, BezierInterpolant, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, BufferAttribute, BufferGeometry, BufferGeometryLoader, ByteType, Cache, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, Color, ColorKeyframeTrack, ColorManagement, Compatibility, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ConeGeometry, ConstantAlphaFactor, ConstantColorFactor, Controls, CubeCamera, CubeDepthTexture, 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, DodecahedronGeometry, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EdgesGeometry, EllipseCurve, EqualCompare, EqualDepth, EqualStencilFunc, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExternalTexture, ExtrudeGeometry, FileLoader, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fog, FogExp2, FramebufferTexture, FrontSide, Frustum, FrustumArray, GLBufferAttribute, GLSL1, GLSL3, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HTMLTexture, HalfFloatType, HemisphereLight, HemisphereLightHelper, IcosahedronGeometry, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateBezier, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InterpolationSamplingMode, InterpolationSamplingType, InvertStencilOp, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightShadow, Line, Line3, LineBasicMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineLoop, LineSegments, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, LoopOnce, LoopPingPong, LoopRepeat, MOUSE, Material, MaterialBlending, MaterialLoader, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, Mesh, MeshBasicMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshMatcapMaterial, MeshNormalMaterial, MeshPhongMaterial, MeshPhysicalMaterial, MeshStandardMaterial, MeshToonMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoNormalPacking, NoToneMapping, NormalAnimationBlendMode, NormalBlending, NormalGAPacking, NormalRGPacking, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, PCFShadowMap, PCFSoftShadowMap, Path, PerspectiveCamera, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, Points, PointsMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PropertyBinding, PropertyMixer, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, R11_EAC_Format, RAD2DEG, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RG11_EAC_Format, 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, RGBDepthPacking, RGBFormat, RGBIntegerFormat, 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, RGDepthPacking, RGFormat, RGIntegerFormat, RawShaderMaterial, Ray, Raycaster, RectAreaLight, RedFormat, RedIntegerFormat, ReinhardToneMapping, RenderObjectRefreshType, RenderTarget, RenderTarget3D, RepeatWrapping, ReplaceStencilOp, ReverseSubtractEquation, ReversedDepthFuncs, RingGeometry, SIGNED_R11_EAC_Format, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SIGNED_RG11_EAC_Format, SRGBColorSpace, SRGBTransfer, Scene, 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, TextureSource, TextureUtils, Timer, TimestampQuery, TorusGeometry, TorusKnotGeometry, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform, UniformsGroup, UniformsUtils, UnsignedByteType, UnsignedInt101111Type, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, VSMShadowMap, Vector2, Vector3, Vector4, VectorKeyframeTrack, VideoFrameTexture, VideoTexture, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLRenderTarget, WebGPUCoordinateSystem, WebXRController, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, cloneUniforms, createCanvasElement, createElementNS, error, getByteLength, getConsoleFunction, getUnlitUniformColorSpace, isTypedArray, log, mergeUniforms, probeAsync, setConsoleFunction, warn, warnOnce, yieldToMain };

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.